实战10 角色管理

news2024/11/20 11:35:23

目录

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 {
    @Resource
    private UserMapper userMapper;

    /**
     * 根据用户查询角色列表
     *
     * @param page
     * @param roleQueryVo
     * @return
     */
    @Override
    public 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
     */
    @Override
    public boolean hasRoleCount(Long id) {
        return baseMapper.getRoleCountByRoleId(id) > 0 ;
    }

    /***
     * 删除角色
     * @param id :
     * @return boolean
     */
    @Override
    public boolean deleteRoleById(Long id) {
        // 删除角色权限关系
        baseMapper.deleteRolePermissionByRoleId(id);
        // 删除角色
        return baseMapper.deleteById(id) > 0 ;
    }

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

    /**
     * 根据用户ID查询该用户拥有的角色ID
     *
     * @param userId
     * @return
     */
    @Override
    public 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 {
    @Resource
    private IRoleService roleService;

    @Resource
    private 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-pagination
    background
    @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: '', //角色ID
      assignTreeData: [], //树节点数据
      //树节点属性
      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 = pageNo
      this.searchModel.pageSize = pageSize
      let res = await getRoles(this.searchModel)
      if (res.success){
        //console.log(res)
        this.roleList = res.data.records
        this.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 login
  login({ commit }, userInfo) {
    const { username, password } = userInfo
    return new Promise((resolve, reject) => {
      login({ username: username.trim(), password: password }).then(response => {
        const { token, expireTime } = response
        commit('SET_TOKEN', token)
        setToken(token)
        // 设置token过期时间
        setTokenTime(expireTime)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // get user info
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {
        const { data } = response

        if (!data) {
          reject('Verification failed, please Login again.')
        }

        // 从后端反馈的data数据中解构出用户相关信息
        const { roles, name, avatar, introduction, id } = data

        // roles must be a non-empty array
        if (!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 logout
  logout({ 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/2485
        dispatch('tagsView/delAllViews', null, { root: true })

        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  // remove token
  resetToken({ commit }) {
    return new Promise(resolve => {
      commit('SET_TOKEN', '')
      commit('SET_ROLES', [])
      removeToken()
      resolve()
    })
  },

  // dynamically modify permissions
  async 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 roles
    const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })
    // dynamically add accessible routes
    router.addRoutes(accessRoutes)

    // reset visited views and cached views
    dispatch('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
         */
        @Override
        public 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,   // 角色id
        userId: 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
     */
    @Override
    public 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() {
      //获取选中的节点key
      let ids = this.$refs.assignTree.getCheckedKeys()
      //获取选中节点的父节点id
      let 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)
      }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1337743.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实验八 基于FPGA的分频器的设计

基本任务一&#xff1a;设计一个分频器&#xff0c;输入信号50MHZ,输出信号频率分别为1KHZ&#xff0c;500HZ&#xff0c;1HZ。 m100&#xff1a; 扩展任务二&#xff1a;控制蜂鸣器发出滴滴滴的声音

补题与总结:leetcode第 377 场周赛

文章目录 写在最前面的复盘2977. 转换字符串的最小成本 II&#xff08;Flody 爆搜优化->dp&#xff09; 写在最前面的复盘 感谢leetcode&#xff0c;丰富了我为数不多的卡常经验 2是简单思维题&#xff0c;但卡常 4是爆搜优化&#xff0c;也卡常&#xff0c;补题时给卡麻了…

【HBase】——简介

1 HBase 定义 Apache HBase™ 是以 hdfs 为数据存储的&#xff0c;一种分布式、可扩展的 NoSQL 数据库。 2 HBase 数据模型 • HBase 的设计理念依据 Google 的 BigTable 论文&#xff0c;论文中对于数据模型的首句介绍。 Bigtable 是一个稀疏的、分布式的、持久的多维排序 m…

.Net7.0 或更高版本 System.Drawing.Common 上传图片跨平台方案

项目升级.Net7.0以后&#xff0c;System.Drawing.Common开关已经被删除&#xff0c;且System.Drawing.Common仅在 Windows 上支持 &#xff0c;于是想办法将原来上传图片验证文件名和获取图片扩展名方法替换一下&#xff0c;便开始搜索相关解决方案。 .Net6.0文档&#xff1a;…

Python 高级(四):线程池 ThreadPoolExecutor

大家好&#xff0c;我是水滴~~ 当涉及到需要同时处理多个任务的情况时&#xff0c;使用线程池是一种高效的方法。Python提供了concurrent.futures模块&#xff0c;其中的ThreadPoolExecutor类使得使用线程池变得非常方便。本文将详细介绍Python线程池的概念、使用方法和示例代…

使用 AnyGo 修改 iPhone 手机定位

在当今数字化时代&#xff0c;我们的手机已经成为我们日常生活中不可或缺的一部分。然而&#xff0c;有时我们可能会遇到一些情况&#xff0c;需要修改手机的定位信息。这个需求可能来自于各种不同的原因&#xff0c;包括但不限于保护个人隐私、测试应用程序的地理位置相关功能…

数据仓库【5】:项目实战

数据仓库【5】&#xff1a;项目实战 1、项目概述1.1、项目背景1.2、复购率计算 2、数据描述3、架构设计3.1、数据仓库架构图 4、环境搭建4.1、环境说明4.2、集群规划4.3、搭建流程 5、项目开发5.1、业务数据生成5.2、ETL数据导入5.3、ODS层创建&数据接入5.4、DWD层创建&…

【面试】Java中的多种设计模式(十种主要设计模式)

Java中的多种设计模式&#xff08;十种主要设计模式&#xff09; 文章概述 设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。它是软件工程中常见问题的解决方案的一种描述或模板。设计模式可以提供一种通用的、可重用的解决方案&#xff0c;帮助开发…

leetcode 75. 颜色分类(medium)(优质解法)

链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 代码&#xff1a; class Solution {public void sortColors(int[] nums) {int left-1,rightnums.length,i0;while(i<right){if(nums[i]0){left;swap(nums,left,i);i;}else if(nums…

【学习笔记】Java函数式编程03 Stream流-终结操作

书接上回 3.3.3 终结操作 3.3.3.1 forEach 对集合的每一个元素进行处理 接触很多了不赘述 3.3.3.2 count 用来获取当前流中的元素的个数 比如&#xff0c;打印出所有作家的作品的总数 System.out.println(authors.stream().flatMap(author -> author.getBooks().stre…

第九部分 图论

目录 例 相关概念 握手定理 例1 图的度数列 例 无向图的连通性 无向图的连通度 例2 例3 有向图D如图所示&#xff0c;求 A, A2, A3, A4&#xff0c;并回答诸问题&#xff1a; 中间有几章这里没有写&#xff0c;感兴趣可以自己去学&#xff0c;组合数学跟高中差不多&#xff0c…

2024,华为重塑笔记本的“创新周期”

作者 | 曾响铃 文 | 响铃说 谈及电脑PC&#xff0c;相信不少消费者都会下意识地给行业贴一个标签&#xff1a;夕阳行业。毕竟当下已经是移动互联网时代&#xff0c;传统PC的使用场景不断萎缩&#xff0c;市场研究机构Gartner报告显示&#xff0c;截至2023年第三季度&#xff…

LLM应用于MPC

现有的基于学习的自动驾驶系统&#xff08;AD&#xff09;在理解高级信息和提供可解释性方面存在挑战。为了解决这些问题&#xff0c;这项工作采用LLM作为复杂AD场景的决策组件。作者设计了认知途径&#xff08;cognitive pathway&#xff09;来实现LLM的综合推理&#xff0c;并…

python作业题百度网盘,python作业答案怎么查

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python作业题百度网盘&#xff0c;python作业答案怎么查&#xff0c;今天让我们一起来看看吧&#xff01; 1 以下代码的输出结果为&#xff1a; alist [1, 2, 3, 4] print(alist.reverse()) print(alist) A.[4, 3, 2, …

Python爬虫中的代理IP设置与实战策略

在Python爬虫中&#xff0c;使用代理IP设置是一种常见的策略&#xff0c;主要用于以下几个目的&#xff1a; 1. 避免被目标网站封禁&#xff1a;频繁的请求可能会引起目标网站的注意&#xff0c;导致你的IP被封锁。通过使用代理IP&#xff0c;你可以模拟来自不同地点和设备的请…

【WPF】使用Behavior以及ValidationRule实现表单校验

文章目录 使用ValidationRule实现检测用户输入EmptyValidationRule 非空校验TextBox设置非空校验TextBox设置非空校验并显示校验提示 结语 使用ValidationRule实现检测用户输入 EmptyValidationRule是TextBox内容是否为空校验&#xff0c;TextBox的Binding属性设置ValidationRu…

AR智慧校园三维主电子沙盘系统研究及应用

一 、概述 易图讯科技(www.3dgis.top)自主研发的智慧校园三维主电子沙盘系统&#xff0c;采用B/S架构模式&#xff0c;采用自主可控高性能WebGIS可视化引擎&#xff0c;支持多用户客户端通过网络请求访问服务器地图和专题数据&#xff0c;提供地理信息数据、专题数据的并发访问…

爬虫工作量由小到大的思维转变---<第二十八章 Scrapy中间件说明书>

爬虫工作量由小到大的思维转变---&#xff1c;第二十六章 Scrapy通一通中间件的问题&#xff1e;-CSDN博客 前言: (书接上面链接)自定义中间件玩不明白? 好吧,写个翻译的文档点笔记,让中间件更通俗一点!!! 正文: 全局图: 爬虫中间件--->翻译笔记: from scrapy import s…

ES慢查询分析——性能提升6 倍

问题 生产环境频繁报警。查询跨度91天的数据&#xff0c;请求耗时已经来到了30s。报警的阈值为5s。 背景 查询关键词简单&#xff0c;为‘北京’ 单次仅检索两个字段 查询时间跨度为91天&#xff0c;覆盖数据为450亿数据 问题分析 使用profle分析&#xff0c;复现监控报警的…

Go在Win10上接收UDP组播数据

第一步、绑定本机某张网卡的IP和端口&#xff0c;本代码选择IP为0.0.0.0&#xff0c;端口为8000&#xff1b;第二步、加入组播&#xff0c;组播地址为“224.0.0.1”&#xff1b;第三步、循环接收UDP组播数据&#xff1b; 代码 package mainimport ("fmt""golang…