当前位置: 首页 > news >正文

实战10 角色管理

目录

1、角色后端接口

2、角色列表查询

2.1 效果图

2.2页面原型代码

2.3 角色api代码 role.js

2.4 查询角色列表代码

4、 新增和编辑角色

5、删除角色

6、分配权限

6.1 分配权限思路

6.2 分配权限回显接口

6.3 分配权限回显前端实现

6.4分配权限后端接口

6.4.1 RolePermissionDTO​

6.4.2 RoleMapper

6.4.3 RoleMapper.xml

6.4.4 RoleService

6.4.5 RoleServiceImp

 6.4.6 RoleController

6.5分配权限回显前端实现


1、角色后端接口

package com.cizhu.vo.query;import com.cizhu.entity.Permission;
import lombok.Data;@Data
public class RoleQueryVo extends Permission {private Long pageNo = 1L;//当前页码private Long pageSize = 10L;//每页显示数量private Long userId;//用户ID
}
package com.cizhu.mapper;import com.cizhu.entity.Role;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Select;import java.util.List;/*** <p>*  Mapper 接口* </p>** @author cizhu* @since 2023-12-14*/
public interface RoleMapper extends BaseMapper<Role> {@Select("select count(1) from sys_user_role where role_id = #{roleId}")int getRoleCountByRoleId(Long roleId);@Delete("delete from sys_role_permission where role_id = #{roleId}")void deleteRolePermissionByRoleId(Long roleId);/*** 保存角色权限关系* @param roleId* @param permissionIds* @return*/int saveRolePermission(Long roleId, List<Long> permissionIds);/*** 根据用户ID查询该用户拥有的角色ID* @param userId* @return*/@Select("select role_id from `sys_user_role` where user_id = #{userId}")List<Long> findRoleIdByUserId(Long userId);}
package com.cizhu.service;import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cizhu.entity.Role;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cizhu.vo.query.RoleQueryVo;import java.util.List;/*** <p>*  服务类* </p>** @author cizhu* @since 2023-12-14*/
public interface IRoleService extends IService<Role> {/*** 根据用户查询角色列表* @param page* @param roleQueryVo* @return*/IPage<Role> findRoleListByUserId(IPage<Role> page, RoleQueryVo roleQueryVo);/**** 检查该角色是否已被使用* @param id:* @return boolean*/boolean hasRoleCount(Long id);/**** 删除角色* @param id:* @return boolean*/boolean deleteRoleById(Long id);/*** 保存角色权限关系* @param roleId* @param permissionIds* @return*/boolean saveRolePermission(Long roleId, List<Long> permissionIds);/*** 根据用户ID查询该用户拥有的角色ID* @param userId* @return*/List<Long> findRoleIdByUserId(Long userId);
}
package com.cizhu.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cizhu.entity.Role;
import com.cizhu.entity.User;
import com.cizhu.mapper.RoleMapper;
import com.cizhu.mapper.UserMapper;
import com.cizhu.service.IPermissionService;
import com.cizhu.service.IRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cizhu.utils.Result;
import com.cizhu.vo.query.RoleQueryVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.util.List;/*** <p>*  服务实现类* </p>** @author cizhu* @since 2023-12-14*/
@Service
@Transactional
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {@Resourceprivate UserMapper userMapper;/*** 根据用户查询角色列表** @param page* @param roleQueryVo* @return*/@Overridepublic IPage<Role> findRoleListByUserId(IPage<Role> page, RoleQueryVo roleQueryVo) {//创建条件构造器QueryWrapper<Role> queryWrapper = new QueryWrapper<Role>();//角色名称queryWrapper.like(!ObjectUtils.isEmpty(roleQueryVo.getRoleName()),"role_name",roleQueryVo.getRoleName());//排序queryWrapper.orderByAsc("id");//根据用户ID查询用户信息User user = userMapper.selectById(roleQueryVo.getUserId());//如果用户不为空、且不是管理员,则只能查询自己创建的角色if(user!=null && !ObjectUtils.isEmpty(user.getIsAdmin()) && user.getIsAdmin() !=1){queryWrapper.eq("create_user",roleQueryVo.getUserId());}return baseMapper.selectPage(page,queryWrapper);}/**** 检查该角色是否已被使用* @param id :* @return boolean*/@Overridepublic boolean hasRoleCount(Long id) {return baseMapper.getRoleCountByRoleId(id) > 0 ;}/**** 删除角色* @param id :* @return boolean*/@Overridepublic boolean deleteRoleById(Long id) {// 删除角色权限关系baseMapper.deleteRolePermissionByRoleId(id);// 删除角色return baseMapper.deleteById(id) > 0 ;}/*** 保存角色权限关系** @param roleId* @param permissionIds* @return*/@Overridepublic boolean saveRolePermission(Long roleId, List<Long> permissionIds) {//删除该角色对应的权限信息baseMapper.deleteRolePermissionByRoleId(roleId);//保存角色权限return baseMapper.saveRolePermission(roleId,permissionIds)>0;}/*** 根据用户ID查询该用户拥有的角色ID** @param userId* @return*/@Overridepublic List<Long> findRoleIdByUserId(Long userId) {return baseMapper.findRoleIdByUserId(userId);}
}
package com.cizhu.controller;import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cizhu.dto.RolePermissionDTO;
import com.cizhu.entity.Role;
import com.cizhu.service.IPermissionService;
import com.cizhu.service.IRoleService;
import com.cizhu.utils.Result;
import com.cizhu.vo.query.RolePermissionVo;
import com.cizhu.vo.query.RoleQueryVo;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;/*** <p>*  前端控制器* </p>** @author cizhu* @since 2023-12-14*/
@RestController
@RequestMapping("/api/role")
public class RoleController {@Resourceprivate IRoleService roleService;@Resourceprivate IPermissionService permissionService;/*** 分页查询角色列表* @param roleQueryVo* @return*/@GetMapping("/list")public Result list(RoleQueryVo roleQueryVo){//创建分页对象IPage<Role> page = new Page<Role>(roleQueryVo.getPageNo(),roleQueryVo.getPageSize());//调用分页查询方法roleService.findRoleListByUserId(page,roleQueryVo);//返回数据return Result.ok(page);}/*** 添加角色* @param role* @return*/@PostMapping("/add")public Result add(@RequestBody Role role){if(roleService.save(role)){return Result.ok().message("角色添加成功");}return Result.error().message("角色添加失败");}/*** 修改角色* @param role* @return*/@PutMapping("/update")public Result update(@RequestBody Role role){if(roleService.updateById(role)){return Result.ok().message("角色修改成功");}return Result.error().message("角色修改失败");}/*** 删除角色* @param id* @return*/@DeleteMapping("/delete/{id}")public Result delete(@PathVariable Long id){if(roleService.deleteRoleById(id)){return Result.ok().message("角色删除成功");}return Result.error().message("角色删除失败");}/*** 检查该角色是否已被使用* @param id* @return*/@GetMapping("/check/{id}")public Result check(@PathVariable Long id){//检查该角色是否已被使用if(roleService.hasRoleCount(id)){return Result.exist().message("该角色已分配给其他用户使用,无法删除");}return Result.ok();}/*** 分配权限-查询权限树数据* @param userId* @param roleId* @return*/@GetMapping("/getAssignPermissionTree")public Result getAssignPermissionTree(Long userId, Long roleId) {//调用查询权限树数据的方法RolePermissionVo permissionTree = permissionService.findPermissionTree(userId, roleId);//返回数据return Result.ok(permissionTree);}/*** 分配权限-保存权限数据** @param rolePermissionDTO* @return*/@PostMapping("/saveRoleAssign")public Result saveRoleAssign(@RequestBody RolePermissionDTO rolePermissionDTO) {if (roleService.saveRolePermission(rolePermissionDTO.getRoleId(),rolePermissionDTO.getList())) {return Result.ok().message("权限分配成功");} else {return Result.error().message("权限分配失败");}}}

2、角色列表查询

2.1 效果图

2.2页面原型代码

<template><el-main><!-- 查询条件 --><el-form :model="searchModel" ref="searchForm" label-width="80px" :inline="true" size="small"><el-form-item><el-input v-model="searchModel.roleName" placeholder="请输入角色名称"/></el-form-item><el-form-item><el-button type="primary" icon="el-icon-search" @click="search(pageNo,pageSize)">查询</el-button><el-button icon="el-icon-refresh-right" @click="resetValue()">重置</el-button><el-button type="success" icon="el-icon-plus" @click="openAddWindow()">新增</el-button></el-form-item></el-form><!-- 数据表格 --><el-table :data="roleList" :height="tableHeight" border stripe style="width: 100%; margin-bottom: 10px"><el-table-column prop="roleCode" label="角色编码" width="160" align="center"></el-table-column><el-table-column prop="roleName" label="角色名称"></el-table-column><el-table-column prop="remark" label="角色备注"></el-table-column><el-table-column label="操作" align="center" width="290"><template slot-scope="scope"><el-button icon="el-icon-edit" type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button><el-button icon="el-icon-delete" type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button><el-button icon="el-icon-setting" type="primary" size="small" @click="assignRole(scope.row)">分配权限</el-button></template></el-table-column></el-table><!-- 分页工具栏 --><el-paginationbackground@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="pageNo":page-sizes="[10, 20, 30, 40, 50]":page-size="10"layout="total, sizes, prev, pager, next, jumper":total="total"></el-pagination><!-- 添加和修改角色窗口 --><system-dialog:title="roleDialog.title":visible="roleDialog.visible":width="roleDialog.width":height="roleDialog.height"@onClose="onClose"@onConfirm="onConfirm"><div slot="content"><el-form :model="role" ref="roleForm" :rules="rules" label-width="80px" :inline="false" size="small"><el-form-item label="角色编码" prop="roleCode"><el-input v-model="role.roleCode"></el-input></el-form-item><el-form-item label="角色名称" prop="roleName"><el-input v-model="role.roleName"></el-input></el-form-item><el-form-item label="角色描述"><el-input type="textarea" v-model="role.remark" :rows="5"></el-input></el-form-item></el-form></div></system-dialog><!-- 分配权限树窗口 --><system-dialog:title="assignDialog.title":visible="assignDialog.visible":width="assignDialog.width":height="assignDialog.height"@onClose="onAssignClose"@onConfirm="onAssignConfirm"><div slot="content"><el-tree ref="assignTree" :data="assignTreeData" node-key="id":props="defaultProps" empty-text="暂无数据" :show-checkbox="true":highlight-current="true" default-expand-all></el-tree></div></system-dialog></el-main>
</template>

2.3 角色api代码 role.js

import http from '@/utils/request'export function getRoutes() {// return request({//   url: '/vue-element-admin/routes',//   method: 'get'// })
}/**
* 查询角色列表
* @returns
*/
export async function getRoles(params) {return await http.get("/api/role/list", params)
}/*** 新增角色* @param {*} data * @returns */
export async function addRole(data) {return await http.post("/api/role/add", data)
}/*** 修改角色* @param {*} data * @returns */
export async function updateRole(data) {return await http.put("/api/role/update", data)
}/**
* 查询角色是否已被使用
* @returns
*/
export async function checkRole(params) {return await http.getRestApi("/api/role/check", params)
}/*** 删除角色* @param {*} id */
export async function deleteRole(params) {return await http.delete("/api/role/delete", params)
}/*** 查询分配权限树列表
* @returns*/
export async function getAssignTree(params) {return await http.get("/api/role/getAssignPermissionTree", params)
}/**
* 分配权限
* @returns
*/
export async function assignSave(params) {return await http.post("/api/role/saveRoleAssign", params)
}

2.4 查询角色列表代码

<script>
//导入role.js脚本
import {getRoles, addRole, updateRole, deleteRole, checkRole, getAssignTree, assignSave} from '@/api/role';
// 导入对话框组件
import SystemDialog from '@/components/system/SystemDialog.vue'
//导入末级节点脚本
import leafUtils from '@/utils/leaf'export default {name: 'roleList',//注册组件components:{ SystemDialog },data() {return {//查询条件searchModel: {roleName: '',pageNo:1,pageSize:10,userId:this.$store.getters.userId //用户ID},roleList: [], //数据列表tableHeight: 0, //表格高度pageNo: 1, //当前页码pageSize: 10, //每页显示数量total: 0, //总数量rules: {roleCode: [{ required: true, trigger: 'blur', message: '请输入角色编码' }],roleName: [{ required: true, trigger: 'blur', message: '请输入角色名称' }]},//添加和修改角色窗口属性roleDialog: {title: '',visible: false,height: 230,width: 500},//角色对象role: {id:"",roleCode:"",roleName:"",remark:"",createUser:this.$store.getters.userId},//分配权限窗口属性assignDialog: {title: '',visible: false,height: 450,width: 300},roleId: '', //角色IDassignTreeData: [], //树节点数据//树节点属性defaultProps: {children: 'children',label: 'label'}}},created() {//调用查询角色列表的方法this.search();},mounted() {this.$nextTick(() => {this.tableHeight = window.innerHeight - 220})},methods: {/*** 查询*/async search(pageNo=1,pageSize=10) {this.searchModel.pageNo = pageNothis.searchModel.pageSize = pageSizelet res = await getRoles(this.searchModel)if (res.success){//console.log(res)this.roleList = res.data.recordsthis.total = res.data.total}},/*** 每页显示数量发生变化*/handleSizeChange(size){this.pageSize = size// 查询数据this.search(this.pageNo, size)},/*** 显示第几页*/handleCurrentChange(page){this.pageNo = page// 查询数据this.search(page, this.pageSize)},/*** 重置查询条件*/resetValue(){//重置查询条件this.searchModel.roleName = ""this.search()},

获取当前用户ID store/user.js

import { login, logout, getInfo } from '@/api/user'
import { getToken, setToken, removeToken, setTokenTime } from '@/utils/auth'
import router, { resetRouter } from '@/router'const state = {token: getToken(),  // 获取token信息name: '',avatar: '',introduction: '',roles: []
}const mutations = {SET_TOKEN: (state, token) => {state.token = token},SET_INTRODUCTION: (state, introduction) => {state.introduction = introduction},SET_NAME: (state, name) => {state.name = name},SET_AVATAR: (state, avatar) => {state.avatar = avatar},SET_ROLES: (state, roles) => {state.roles = roles},SET_USERUID: (state, userId) => {state.userId = userId},
}const actions = {// user loginlogin({ commit }, userInfo) {const { username, password } = userInforeturn new Promise((resolve, reject) => {login({ username: username.trim(), password: password }).then(response => {const { token, expireTime } = responsecommit('SET_TOKEN', token)setToken(token)// 设置token过期时间setTokenTime(expireTime)resolve()}).catch(error => {reject(error)})})},// get user infogetInfo({ commit, state }) {return new Promise((resolve, reject) => {getInfo(state.token).then(response => {const { data } = responseif (!data) {reject('Verification failed, please Login again.')}// 从后端反馈的data数据中解构出用户相关信息const { roles, name, avatar, introduction, id } = data// roles must be a non-empty arrayif (!roles || roles.length <= 0) {reject('getInfo: roles must be a non-null array!')}commit('SET_ROLES', roles)commit('SET_NAME', name)commit('SET_AVATAR', avatar)commit('SET_INTRODUCTION', introduction)commit('SET_USERUID', id)//将权限字段保存到sessionStorage中sessionStorage.setItem("codeList",JSON.stringify(roles));resolve(data)}).catch(error => {reject(error)})})},// user logoutlogout({ commit, state, dispatch }) {return new Promise((resolve, reject) => {logout(state.token).then(() => {commit('SET_TOKEN', '')commit('SET_ROLES', [])removeToken()resetRouter()// reset visited views and cached views// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485dispatch('tagsView/delAllViews', null, { root: true })resolve()}).catch(error => {reject(error)})})},// remove tokenresetToken({ commit }) {return new Promise(resolve => {commit('SET_TOKEN', '')commit('SET_ROLES', [])removeToken()resolve()})},// dynamically modify permissionsasync changeRoles({ commit, dispatch }, role) {const token = role + '-token'commit('SET_TOKEN', token)setToken(token)const { roles } = await dispatch('getInfo')resetRouter()// generate accessible routes map based on rolesconst accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })// dynamically add accessible routesrouter.addRoutes(accessRoutes)// reset visited views and cached viewsdispatch('tagsView/delAllViews', null, { root: true })}
}export default {namespaced: true,state,mutations,actions
}

4、 新增和编辑角色

   /*** 打开添加窗口*/openAddWindow() {//清空表单数据this.$resetForm("roleForm",this.role);this.roleDialog.title = '新增角色'//设置窗口标题this.roleDialog.visible = true//显示窗口},/*** 窗口取消事件*/onClose() {this.roleDialog.visible = false},/*** 窗口确认事件*/onConfirm() {//表单验证this.$refs.roleForm.validate(async (valid)=>{// 验证通过if (valid) {let res = null// 判断是新增还是修改操作(role.id是否为空)if (this.role.id === ""){// 发送新增角色请求res = await addRole(this.role)}else{// 发送修改角色请求res = await updateRole(this.role)}if (res.success){// 提示成功this.$message.success(res.message)// 刷新数据//this.search(this.pageNo, this.pageSize)window.location.reload();//关闭窗口this.roleDialog.visible = false;}else{this.$message.error(res.message)}}});},/*** 编辑角色*/handleEdit(row){//数据回显this.$objCopy(row, this.role); //将当前编辑的数据复制到role对象中//设置窗口标题this.roleDialog.title = "编辑角色";//显示编辑角色窗口this.roleDialog.visible = true;}

 5、删除角色

 /*** 删除角色*/async handleDelete(row){//查询角色是否已被使用let result = await checkRole({ id: row.id })//判断是否可以删除if (!result.success) {//提示不能删除this.$message.warning(result.message);} else {//确认是否删除let confirm = await this.$myconfirm("确定要删除该数据吗?")if (confirm) {//发送删除请求let res = await deleteRole({ id: row.id })//判断是否成功if (res.success) {//成功提示this.$message.success(res.message)//刷新this.search(this.pageNo, this.pageSize)} else {//失败提示this.$message.error(res.message)}}}},

6、分配权限

6.1 分配权限思路

6.2 分配权限回显接口

 PermissionService

    /*** 查询分配权限树列表* @param userId* @param roleId* @return*/RolePermissionVo findPermissionTree(Long userId, Long roleId);

PermissionServiceImp

   /*** 查询分配权限树列表** @param userId* @param roleId* @return*/@Overridepublic RolePermissionVo findPermissionTree(Long userId, Long roleId) {// 1.查询当前用户信息User user = userService.getById(userId);List<Permission> list = null;//2.判断当前用户角色,如果是管理员,则查询所有权限;如果不是管理员,则只查询自己所拥有的的权限if (!ObjectUtils.isEmpty(user) && user.getIsAdmin() == 1){//查询所有权限list = baseMapper.selectList(null);}else{//根据用户ID查询list = baseMapper.findPermissionListByUserId(userId);}//3.组装成树数据List<Permission> permissionList = MenuTree.makeMenuTree(list, 0L);//4.查询要分配角色的原有权限List<Permission> rolePermissions = baseMapper.findPermissionListByRoleId(roleId);//5.找出该角色存在的数据List<Long> listIds = new ArrayList<Long>();Optional.ofNullable(list).orElse(new ArrayList<>()).stream().filter(item -> item != null).forEach(item -> {Optional.ofNullable(rolePermissions).orElse(new ArrayList<>()).stream().filter(Objects::nonNull).forEach(obj -> {// 判断两者的权限id是否一致if(item.getId().equals(obj.getId())){listIds.add(obj.getId());return;}});});//创建RolePermissionVo vo = new RolePermissionVo();vo.setPermissionList(permissionList);vo.setCheckList(listIds.toArray());return vo;}

 RoleController

 6.3 分配权限回显前端实现

/*** 分配权限*/async assignRole(row){this.roleId = row.id// 构建查询参数let params = {roleId: row.id,   // 角色iduserId: this.$store.getters.userId  // 用户id}// 发送查询分配权限菜单请求let res = await getAssignTree(params)if (res.success){//获取当前登录用户所拥有的所有菜单权限let {permissionList} = res.data//获取当前被分配角色的已经拥有的菜单权限let { checkList } = res.data//判断当前菜单是否是最后一级let { setLeaf } = leafUtils()//设置权限菜单列表let newPermissionList = setLeaf(permissionList)//设置树节点菜单数据this.assignTreeData = newPermissionList//将回调延迟到下次DOM更新循环之后执行,在修改数据之后立即使用它,然后等待DOM更新。this.$nextTick(() => {//获取树菜单的节点数据let nodes = this.$refs.assignTree.children//设置子节点this.setChild(nodes, checkList)})}//显示窗口this.assignDialog.visible = true//设置窗口标题this.assignDialog.title = `给【${row.roleName}】分配权限`},/*** 设置子节点*/setChild(childNodes, checkList) {//判断是否存在子节点if (childNodes && childNodes.length > 0){//循环所有权限for (let i=0; i< childNodes.length; i++) {//根据data或key获取树组件中的node节点let node = this.$refs.assignTree.getNode(childNodes[i])//判断使用已经拥有对应的角色权限数据if (checkList && checkList.length > 0) {//循环遍历已有的权限集合for (let j = 0; j < checkList.length; j++) {//找到已经存在的菜单权限节点if (checkList[j] == childNodes[i].id) {//如果节点是展开状态,则将树节点选中if (childNodes[i].open) {this.$refs.assignTree.setChecked(node, true)break}}}}//如果存在子节点,则递归选中if (childNodes[i].children) {this.setChild(childNodes[i].children, checkList)}}}},/*** 分配权限窗口取消事件*/onAssignClose() {this.assignDialog.visible = false},

6.4分配权限后端接口

6.4.1 RolePermissionDTO

6.4.2 RoleMapper

6.4.3 RoleMapper.xml

6.4.4 RoleService

    /*** 保存角色权限关系* @param roleId* @param permissionIds* @return*/boolean saveRolePermission(Long roleId, List<Long> permissionIds);

6.4.5 RoleServiceImp

    /*** 保存角色权限关系** @param roleId* @param permissionIds* @return*/@Overridepublic boolean saveRolePermission(Long roleId, List<Long> permissionIds) {//删除该角色对应的权限信息baseMapper.deleteRolePermissionByRoleId(roleId);//保存角色权限return baseMapper.saveRolePermission(roleId,permissionIds)>0;}

 6.4.6 RoleController

/*** 分配权限-保存权限数据** @param rolePermissionDTO* @return*/@PostMapping("/saveRoleAssign")public Result saveRoleAssign(@RequestBody RolePermissionDTO rolePermissionDTO) {if (roleService.saveRolePermission(rolePermissionDTO.getRoleId(),rolePermissionDTO.getList())) {return Result.ok().message("权限分配成功");} else {return Result.error().message("权限分配失败");}}

6.5分配权限回显前端实现

    /*** 分配权限窗口确认事件*/async onAssignConfirm() {//获取选中的节点keylet ids = this.$refs.assignTree.getCheckedKeys()//获取选中节点的父节点idlet pids = this.$refs.assignTree.getHalfCheckedKeys()//组装选中的节点ID数据let listId = ids.concat(pids)//组装参数let params = {roleId: this.roleId,list: listId}//发送请求let res = await assignSave(params)//判断是否成功if (res.success) {//关闭窗口this.assignDialog.visible = false//提示成功this.$message.success(res.message)} else {//提示失败this.$message.error(res.data)}}

相关文章:

实战10 角色管理

目录 1、角色后端接口 2、角色列表查询 2.1 效果图 2.2页面原型代码 2.3 角色api代码 role.js 2.4 查询角色列表代码 4、 新增和编辑角色 5、删除角色 6、分配权限 6.1 分配权限思路 6.2 分配权限回显接口 6.3 分配权限回显前端实现 6.4分配权限后端接口 6.4.1 R…...

Lua的底层原理与C#交互原理浅析【更新中】

目录 lua底层原理浅析 table底层原理浅析 Lua表的C语言定义 原理和实现 userdata lua和C#的交互机制&#xff08;更新中&#xff09; 基本介绍 Lua 与 C/C 的数据交互 Lua 调用 C/C 函数 C/C 调用 Lua 函数 基元类型传递 对象类型传递 Lua 调用 C# 总结 网上有很…...

鸿蒙项目二—— 注册和登录

此部分和上篇文章是连续剧 &#xff0c;如果需要&#xff0c;请查看 一、注册 import http from ohos.net.http; Entry Component struct Reg {// 定义数据&#xff1a;State username: string "";State userpass: string "";State userpass2: string …...

Dijkstra(迪杰斯特拉)算法总结

知识概览 Dijkstra算法适用于解决所有边权都是正数的最短路问题。Dijkstra算法分为朴素的Dijkstra算法和堆优化版的Dijkstra算法。朴素的Dijkstra算法时间复杂度为&#xff0c;适用于稠密图。堆优化版的Dijkstra算法时间复杂度为&#xff0c;适用于稀疏图。稠密图的边数m和是一…...

设计模式?!

如何解决复杂性 链接&#xff1a;不同的设计模式实例代码&#xff08;更新中&#xff09; 分解 人们面对复杂性有一个常见的做法&#xff1a;即分而治之&#xff0c;将大问题分解为多个小问题&#xff0c;将复杂问题分解为多个简单问题。 抽象 更高层次来讲&#xff0c;人们处…...

Pytorch项目,肺癌检测项目之三

成功获取到数据之后&#xff0c;我们需要将数据放到Pytorch里面去处理&#xff0c;我们需要将其转换成Dataset数据集&#xff0c;方便去使用相同的API。要转换成Dataset数据集需要实现两个方法&#xff0c;方法一&#xff1a; 方法二&#xff1a; 运行比较慢的话&#xff0c…...

深圳鼎信|输电线路防山火视频监控预警装置:森林火灾来袭,安全不留白!

受线路走廊制约和环保要求影响&#xff0c;输电线路大多建立在高山上&#xff0c;不仅可以减少地面障碍物和人类活动的干扰&#xff0c;还能提高线路的抗灾能力和可靠性。但同时也会面临其它的难题&#xff0c;例如森林火灾预防。今天&#xff0c;深圳鼎信智慧将从不同角度分析…...

【Bash/Shell】知识总结

文章目录 1. 总体认识1.1. Shell概述1.2. 第一个Shell脚本1.3. 注释 2. 变量2.1. 定义变量2.2. 使用变量2.3. 只读变量2.4. 删除变量2.5. 变量类型2.5.1. 字符串变量2.5.2. 整数变量2.5.3. 数组变量2.5.4. 环境变量2.5.5. 特殊变量 3. 输出3.1. echo命令3.2. printf命令 4. 运算…...

单例模式(C++实现)

RAII运用 只能在栈上创建对象 只能在堆上创建的对象 单例模式 设计模式 懒汉模式 解决线程安全 优化 饿汉模式 饿汉和懒汉的区别 线程安全与STL与其他锁...

ElasticSearch 聚合统计

聚合统计 度量聚合&#xff1a;求字段的平均值&#xff0c;最小值&#xff0c;最大值&#xff0c;总和等 桶聚合&#xff1a;将文档分成不同的桶&#xff0c;桶的划分可以根据字段的值&#xff0c;范围&#xff0c;日期间隔 管道聚合&#xff1a;在桶聚合的结果上执行进一步计…...

SpringIOC之MethodBasedEvaluationContext

博主介绍:✌全网粉丝5W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌ 博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+…...

【网络安全 | 网络协议】结合Wireshark讲解TCP三次握手

前言 TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、可靠的传输层协议。在建立 TCP 连接时&#xff0c;需要进行三次握手&#xff0c;防止因为网络延迟、拥塞等原因导致的数据丢失或错误传输&#xff0c;确保双方都能够正常通信。 TCP三次握手在Wireshark数据包中…...

钦丰科技(安徽)股份有限公司携卫生级阀门管件盛装亮相2024发酵展

钦丰科技(安徽)股份有限公司携卫生级阀门管件盛装亮相2024济南生物发酵展&#xff01; 展位号&#xff1a;2号馆A65展位 2024第12届国际生物发酵产品与技术装备展览会&#xff08;济南&#xff09;于3月5-7日在山东国际会展中心盛大召开&#xff0c;展会同期将举办30余场高质…...

Python模拟动态星空

前言 今天&#xff0c;我们来用Python做个星空。 一、模拟星空 1,.首先导入所需要的库&#xff1a; from turtle import * from random import random, randint 2.初始画面&#xff1a; screen Screen() width, height 800, 600 screen.setup(width, height) screen.tit…...

最新技术整理3款开源免费直播推流工具,实现实时视频推流、视频拉流,目标端可以是服务器、云平台、移动设备等(附源码)

最新技术整理3款开源免费直播推流工具&#xff0c;实现实时视频推流、视频拉流&#xff0c;目标端可以是服务器、云平台、移动设备等&#xff08;附源码&#xff09;。 什么是推流&#xff1f; 视频推流是指将实时的视频数据从一个源端发送到一个或多个目标端的过程。推流的源…...

shell ——数组

数组中可以存放多个值&#xff0c;Bash Shell只能支持以为数字&#xff0c;初始化时不需要定义数组大小。 数组中元素下标从0开始。 数组的定义 shell数组用括号来表示&#xff0c;元素用空格分割开。 array_name(value1 value2 value3 ...) 给一个简单数组例子 cat firs…...

GO语言基础笔记(五):包的介绍

在Go语言中&#xff0c;包&#xff08;package&#xff09;是代码组织和重用的基本单位。Go的标准库中包含了许多实用的包&#xff0c;它们提供了从基础数据处理到复杂网络编程等各种功能。下面是一些常用的Go标准库包及其作用的介绍&#xff1a; 目录 1. fmt 2. net/http …...

【Unity6.0+AI】Sentis加载模型识别手写数字案例实现

按照国际惯例,看效果: 素材准备: 自己在PS中绘制黑底白字手写字体,导出jpg,尺寸28*28! 素材设置 基本步骤 准备工作:从 ONNX Model Zoo 下载手写识别 ONNX 模型文件 【下载模型】MNIST 手写数字识别模型 mnist-12.onnx,并将其拖入项目窗口的 Assets 文件夹。 【下载模…...

VScode跑通Remix.js官方的contact程序开发过程

目录 1 引言 2 安装并跑起来 3 设置根路由 4 用links来添加风格资源 ​5 联系人路由的UI 6 添加联系人的UI组件 7 嵌套路由和出口 8 类型推理 9 Loader里的URL参数 10 验证参数并抛出响应 书接上回&#xff0c;我们已经跑通了remix的quick start项目&#xff0c;接下…...

讲座思考 | 周志华教授:新型机器学习神经元模型的探索

12月22日&#xff0c;有幸听了南京大学周志华教授题为“新型机器学习神经元模型的探索”的讲座。现场热闹非凡&#xff0c;大家像追星一样拿着“西瓜书”找周教授签名。周教授讲得依旧循循善诱&#xff0c;由浅入深&#xff0c;听得我很入迷&#xff0c;故作此记。 周教授首先就…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...

恶补电源:1.电桥

一、元器件的选择 搜索并选择电桥&#xff0c;再multisim中选择FWB&#xff0c;就有各种型号的电桥: 电桥是用来干嘛的呢&#xff1f; 它是一个由四个二极管搭成的“桥梁”形状的电路&#xff0c;用来把交流电&#xff08;AC&#xff09;变成直流电&#xff08;DC&#xff09;。…...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...

CSS 工具对比:UnoCSS vs Tailwind CSS,谁是你的菜?

在现代前端开发中&#xff0c;Utility-First (功能优先) CSS 框架已经成为主流。其中&#xff0c;Tailwind CSS 无疑是市场的领导者和标杆。然而&#xff0c;一个名为 UnoCSS 的新星正以其惊人的性能和极致的灵活性迅速崛起。 这篇文章将深入探讨这两款工具的核心理念、技术差…...

高保真组件库:开关

一:制作关状态 拖入一个矩形作为关闭的底色:44 x 22,填充灰色CCCCCC,圆角23,边框宽度0,文本为”关“,右对齐,边距2,2,6,2,文本颜色白色FFFFFF。 拖拽一个椭圆,尺寸18 x 18,边框为0。3. 全选转为动态面板状态1命名为”关“。 二:制作开状态 复制关状态并命名为”开…...