Commit 2651f9bce3a5f3a4e43e955ebcbaa34cdf15ad6e

Authored by YunaiV
1 parent ad1d1978

完成角色的授权的功能

ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
... ... @@ -112,18 +112,6 @@ public class SysMenuServiceImpl implements ISysMenuService {
112 112 }
113 113  
114 114 /**
115   - * 构建前端所需要下拉树结构
116   - *
117   - * @param menus 菜单列表
118   - * @return 下拉树结构列表
119   - */
120   - @Override
121   - public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus) {
122   - List<SysMenu> menuTrees = buildMenuTree(menus);
123   - return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
124   - }
125   -
126   - /**
127 115 * 查询菜单使用数量
128 116 *
129 117 * @param menuId 菜单ID
... ...
ruoyi-ui/src/api/system/menu.js
1   -import request from '@/utils/request'
2   -
3   -// 查询菜单列表
4   -export function listMenu(query) {
5   - return request({
6   - url: '/system/menu/list',
7   - method: 'get',
8   - params: query
9   - })
10   -}
11   -
12   -// 查询菜单详细
13   -export function getMenu(id) {
14   - return request({
15   - url: '/system/menu/get?id=' + id,
16   - method: 'get'
17   - })
18   -}
19   -
20   -// 查询菜单下拉树结构
21   -export function treeselect() {
22   - return request({
23   - url: '/system/menu/treeselect',
24   - method: 'get'
25   - })
26   -}
27   -
28   -// 根据角色ID查询菜单下拉树结构
29   -export function roleMenuTreeselect(roleId) {
30   - return request({
31   - url: '/system/menu/roleMenuTreeselect/' + roleId,
32   - method: 'get'
33   - })
34   -}
35   -
36   -// 新增菜单
37   -export function addMenu(data) {
38   - return request({
39   - url: '/system/menu/create',
40   - method: 'post',
41   - data: data
42   - })
43   -}
44   -
45   -// 修改菜单
46   -export function updateMenu(data) {
47   - return request({
48   - url: '/system/menu/update',
49   - method: 'post',
50   - data: data
51   - })
52   -}
53   -
54   -// 删除菜单
55   -export function delMenu(id) {
56   - return request({
57   - url: '/system/menu/delete?id=' + id,
58   - method: 'post'
59   - })
60   -}
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询菜单列表
  4 +export function listMenu(query) {
  5 + return request({
  6 + url: '/system/menu/list',
  7 + method: 'get',
  8 + params: query
  9 + })
  10 +}
  11 +
  12 +// 查询菜单(精简)列表
  13 +export function listSimpleMenus() {
  14 + return request({
  15 + url: '/system/menu/list-all-simple',
  16 + method: 'get'
  17 + })
  18 +}
  19 +
  20 +// 查询菜单详细
  21 +export function getMenu(id) {
  22 + return request({
  23 + url: '/system/menu/get?id=' + id,
  24 + method: 'get'
  25 + })
  26 +}
  27 +
  28 +// 新增菜单
  29 +export function addMenu(data) {
  30 + return request({
  31 + url: '/system/menu/create',
  32 + method: 'post',
  33 + data: data
  34 + })
  35 +}
  36 +
  37 +// 修改菜单
  38 +export function updateMenu(data) {
  39 + return request({
  40 + url: '/system/menu/update',
  41 + method: 'post',
  42 + data: data
  43 + })
  44 +}
  45 +
  46 +// 删除菜单
  47 +export function delMenu(id) {
  48 + return request({
  49 + url: '/system/menu/delete?id=' + id,
  50 + method: 'post'
  51 + })
  52 +}
... ...
ruoyi-ui/src/api/system/permission.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询角色拥有的菜单数组
  4 +export function listRoleMenus(roleId) {
  5 + return request({
  6 + url: '/system/permission/list-role-resources?roleId=' + roleId,
  7 + method: 'get'
  8 + })
  9 +}
  10 +
  11 +// 赋予角色菜单
  12 +export function assignRoleMenu(data) {
  13 + return request({
  14 + url: '/system/permission/assign-role-menu',
  15 + method: 'post',
  16 + data: data
  17 + })
  18 +}
... ...
ruoyi-ui/src/utils/ruoyi.js
... ... @@ -148,5 +148,5 @@ export function handleTree(data, id, parentId, children, rootId) {
148 148 //返回第一层
149 149 return father[parentId] === rootId;
150 150 });
151   - return treeData != '' ? treeData : data;
  151 + return treeData !== '' ? treeData : data;
152 152 }
... ...
ruoyi-ui/src/views/system/role/index.vue
... ... @@ -182,9 +182,9 @@
182 182 </el-select>
183 183 </el-form-item>
184 184 <el-form-item label="数据权限" v-show="form.dataScope == 2">
  185 + <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
185 186 <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
186 187 <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
187   - <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
188 188 <el-tree
189 189 class="tree-border"
190 190 :data="deptOptions"
... ... @@ -192,7 +192,7 @@
192 192 default-expand-all
193 193 ref="dept"
194 194 node-key="id"
195   - :check-strictly="!form.deptCheckStrictly"
  195 + :check-strictly="form.deptCheckStrictly"
196 196 empty-text="加载中,请稍后"
197 197 :props="defaultProps"
198 198 ></el-tree>
... ... @@ -214,16 +214,16 @@
214 214 <el-input v-model="form.code" :disabled="true" />
215 215 </el-form-item>
216 216 <el-form-item label="菜单权限">
  217 + <el-checkbox v-model="!form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动(选中父节点,自动选择子节点)</el-checkbox>
217 218 <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
218 219 <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
219   - <el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
220 220 <el-tree
221 221 class="tree-border"
222 222 :data="menuOptions"
223 223 show-checkbox
224 224 ref="menu"
225 225 node-key="id"
226   - :check-strictly="!form.menuCheckStrictly"
  226 + :check-strictly="form.menuCheckStrictly"
227 227 empty-text="加载中,请稍后"
228 228 :props="defaultProps"
229 229 ></el-tree>
... ... @@ -239,7 +239,8 @@
239 239  
240 240 <script>
241 241 import { listRole, getRole, delRole, addRole, updateRole, exportRole, dataScope, changeRoleStatus } from "@/api/system/role";
242   -import { treeselect as menuTreeselect, roleMenuTreeselect } from "@/api/system/menu";
  242 +import { listSimpleMenus } from "@/api/system/menu";
  243 +import { listRoleMenus, assignRoleMenu } from "@/api/system/permission";
243 244 import { treeselect as deptTreeselect, roleDeptTreeselect } from "@/api/system/dept";
244 245 import {SysCommonStatusEnum, SysMenuTypeEnum} from "@/utils/constants";
245 246 import {DICT_TYPE, getDictDataLabel, getDictDatas} from "@/utils/dict";
... ... @@ -311,8 +312,8 @@ export default {
311 312 // 表单参数
312 313 form: {},
313 314 defaultProps: {
314   - children: "children",
315   - label: "label"
  315 + label: "name",
  316 + children: "children"
316 317 },
317 318 // 表单校验
318 319 rules: {
... ... @@ -349,12 +350,6 @@ export default {
349 350 }
350 351 );
351 352 },
352   - /** 查询菜单树结构 */
353   - getMenuTreeselect() {
354   - menuTreeselect().then(response => {
355   - this.menuOptions = response.data;
356   - });
357   - },
358 353 /** 查询部门树结构 */
359 354 getDeptTreeselect() {
360 355 deptTreeselect().then(response => {
... ... @@ -379,13 +374,6 @@ export default {
379 374 checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
380 375 return checkedKeys;
381 376 },
382   - /** 根据角色ID查询菜单树结构 */
383   - getRoleMenuTreeselect(id) {
384   - return roleMenuTreeselect(id).then(response => {
385   - this.menuOptions = response.menus;
386   - return response;
387   - });
388   - },
389 377 /** 根据角色ID查询部门树结构 */
390 378 getRoleDeptTreeselect(id) {
391 379 return roleDeptTreeselect(id).then(response => {
... ... @@ -432,23 +420,22 @@ export default {
432 420 },
433 421 // 表单重置
434 422 reset() {
435   - if (this.$refs.menu != undefined) {
  423 + if (this.$refs.menu !== undefined) {
436 424 this.$refs.menu.setCheckedKeys([]);
437 425 }
438   - this.menuExpand = false,
439   - this.menuNodeAll = false,
440   - this.deptExpand = true,
441   - this.deptNodeAll = false,
  426 + this.menuExpand = false;
  427 + this.menuNodeAll = false;
  428 + this.deptExpand = true;
  429 + this.deptNodeAll = false;
442 430 this.form = {
443 431 id: undefined,
444 432 name: undefined,
445 433 code: undefined,
446 434 sort: 0,
447   - status: "0",
448   - ids: [],
449 435 deptIds: [],
450   - menuCheckStrictly: true,
451   - deptCheckStrictly: true,
  436 + menuIds: [],
  437 + menuCheckStrictly: false, // 非严格,菜单弹窗的父子级联动
  438 + deptCheckStrictly: false,
452 439 remark: undefined
453 440 };
454 441 this.resetForm("form");
... ... @@ -466,12 +453,12 @@ export default {
466 453 },
467 454 // 树权限(展开/折叠)
468 455 handleCheckedTreeExpand(value, type) {
469   - if (type == 'menu') {
  456 + if (type === 'menu') {
470 457 let treeList = this.menuOptions;
471 458 for (let i = 0; i < treeList.length; i++) {
472 459 this.$refs.menu.store.nodesMap[treeList[i].id].expanded = value;
473 460 }
474   - } else if (type == 'dept') {
  461 + } else if (type === 'dept') {
475 462 let treeList = this.deptOptions;
476 463 for (let i = 0; i < treeList.length; i++) {
477 464 this.$refs.dept.store.nodesMap[treeList[i].id].expanded = value;
... ... @@ -480,18 +467,18 @@ export default {
480 467 },
481 468 // 树权限(全选/全不选)
482 469 handleCheckedTreeNodeAll(value, type) {
483   - if (type == 'menu') {
  470 + if (type === 'menu') {
484 471 this.$refs.menu.setCheckedNodes(value ? this.menuOptions: []);
485   - } else if (type == 'dept') {
  472 + } else if (type === 'dept') {
486 473 this.$refs.dept.setCheckedNodes(value ? this.deptOptions: []);
487 474 }
488 475 },
489 476 // 树权限(父子联动)
490 477 handleCheckedTreeConnect(value, type) {
491   - if (type == 'menu') {
492   - this.form.menuCheckStrictly = value ? true: false;
493   - } else if (type == 'dept') {
494   - this.form.deptCheckStrictly = value ? true: false;
  478 + if (type === 'menu') {
  479 + this.form.menuCheckStrictly = value;
  480 + } else if (type === 'dept') {
  481 + this.form.deptCheckStrictly = value;
495 482 }
496 483 },
497 484 /** 新增按钮操作 */
... ... @@ -514,27 +501,27 @@ export default {
514 501 handleMenu(row) {
515 502 this.reset();
516 503 const id = row.id
517   - // TODO 优化
518   - this.getMenuTreeselect();
519   - const roleMenu = this.getRoleMenuTreeselect(id);
520   - this.$nextTick(() => {
521   - roleMenu.then(res => {
522   - this.$refs.menu.setCheckedKeys(res.checkedKeys);
523   - });
524   - });
  504 + // 处理了 form 的角色 name 和 code 的展示
  505 + this.form.id = id;
  506 + this.form.name = row.name;
  507 + this.form.code = row.code;
  508 + // 打开弹窗
525 509 this.openMenu = true;
526   -
527   - // const roleDeptTreeselect = this.getRoleDeptTreeselect(row.id);
528   - // getRole(row.id).then(response => {
529   - // this.form = response.data;
530   - // this.openDataScope = true;
531   - // this.$nextTick(() => {
532   - // roleDeptTreeselect.then(res => {
533   - // this.$refs.dept.setCheckedKeys(res.checkedKeys);
534   - // });
535   - // });
536   - // this.title = "分配数据权限";
537   - // });
  510 + // 获得菜单列表
  511 + listSimpleMenus().then(response => {
  512 + // 处理 menuOptions 参数
  513 + this.menuOptions = [];
  514 + this.menuOptions.push(...this.handleTree(response.data, "id"));
  515 + });
  516 + // 获得角色拥有的菜单集合
  517 + listRoleMenus(id).then(response => {
  518 + // 设置为严格,避免设置父节点自动选中子节点,解决半选中问题
  519 + // this.form.menuCheckStrictly = true
  520 + // 设置选中
  521 + this.$refs.menu.setCheckedKeys(response.data, false);
  522 + // 设置为非严格,继续使用半选中
  523 + // this.form.menuCheckStrictly = false
  524 + })
538 525 },
539 526 /** 分配数据权限操作 */
540 527 handleDataScope(row) {
... ... @@ -556,16 +543,12 @@ export default {
556 543 this.$refs["form"].validate(valid => {
557 544 if (valid) {
558 545 if (this.form.id !== undefined) {
559   - // TODO 芋艿:需要迁移
560   - // this.form.ids = this.getMenuAllCheckedKeys();
561 546 updateRole(this.form).then(response => {
562 547 this.msgSuccess("修改成功");
563 548 this.open = false;
564 549 this.getList();
565 550 });
566 551 } else {
567   - // TODO 芋艿:需要迁移
568   - // this.form.ids = this.getMenuAllCheckedKeys();
569 552 addRole(this.form).then(response => {
570 553 this.msgSuccess("新增成功");
571 554 this.open = false;
... ... @@ -577,7 +560,7 @@ export default {
577 560 },
578 561 /** 提交按钮(数据权限) */
579 562 submitDataScope: function() {
580   - if (this.form.id != undefined) {
  563 + if (this.form.id !== undefined) {
581 564 this.form.deptIds = this.getDeptAllCheckedKeys();
582 565 dataScope(this.form).then(response => {
583 566 this.msgSuccess("修改成功");
... ... @@ -589,11 +572,13 @@ export default {
589 572 /** 提交按钮(菜单权限) */
590 573 submitMenu: function() {
591 574 // TODO 需要改动下
592   - if (this.form.id != undefined) {
593   - this.form.deptIds = this.getDeptAllCheckedKeys();
594   - dataScope(this.form).then(response => {
  575 + if (this.form.id !== undefined) {
  576 + assignRoleMenu({
  577 + roleId: this.form.id,
  578 + menuIds: this.getMenuAllCheckedKeys()
  579 + }).then(response => {
595 580 this.msgSuccess("修改成功");
596   - this.openDataScope = false;
  581 + this.openMenu = false;
597 582 this.getList();
598 583 });
599 584 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysMenuController.java
1 1 package cn.iocoder.dashboard.modules.system.controller.permission;
2 2  
  3 +import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
3 4 import cn.iocoder.dashboard.common.pojo.CommonResult;
4   -import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO;
5   -import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuListReqVO;
6   -import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuRespVO;
7   -import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO;
  5 +import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.*;
8 6 import cn.iocoder.dashboard.modules.system.convert.permission.SysMenuConvert;
9 7 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
10 8 import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService;
... ... @@ -15,6 +13,7 @@ import org.springframework.validation.annotation.Validated;
15 13 import org.springframework.web.bind.annotation.*;
16 14  
17 15 import javax.annotation.Resource;
  16 +import java.util.Comparator;
18 17 import java.util.List;
19 18  
20 19 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
... ... @@ -30,8 +29,22 @@ public class SysMenuController {
30 29 @ApiOperation("获取菜单列表")
31 30 // @PreAuthorize("@ss.hasPermi('system:menu:list')")
32 31 @GetMapping("/list")
33   - public CommonResult<List<SysMenuRespVO>> list(SysMenuListReqVO reqVO) {
34   - return success(menuService.listMenus(reqVO));
  32 + public CommonResult<List<SysMenuRespVO>> listMenus(SysMenuListReqVO reqVO) {
  33 + List<SysMenuDO> list = menuService.listMenus(reqVO);
  34 + list.sort(Comparator.comparing(SysMenuDO::getSort));
  35 + return success(SysMenuConvert.INSTANCE.convertList(list));
  36 + }
  37 +
  38 + @ApiOperation(value = "获取菜单精简信息列表", notes = "只包含被开启的菜单,主要用于前端的下拉选项")
  39 + @GetMapping("/list-all-simple")
  40 + public CommonResult<List<SysMenuSimpleRespVO>> listSimpleMenus() {
  41 + // 获得菜单列表,只要开启状态的
  42 + SysMenuListReqVO reqVO = new SysMenuListReqVO();
  43 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  44 + List<SysMenuDO> list = menuService.listMenus(reqVO);
  45 + // 排序后,返回个诶前端
  46 + list.sort(Comparator.comparing(SysMenuDO::getSort));
  47 + return success(SysMenuConvert.INSTANCE.convertList02(list));
35 48 }
36 49  
37 50 @ApiOperation("获取菜单信息")
... ... @@ -43,17 +56,6 @@ public class SysMenuController {
43 56 }
44 57  
45 58 // /**
46   -// * 获取菜单下拉树列表
47   -// */
48   -// @GetMapping("/treeselect")
49   -// public AjaxResult treeselect(SysMenu menu) {
50   -// LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
51   -// Long userId = loginUser.getUser().getUserId();
52   -// List<SysMenu> menus = menuService.selectMenuList(menu, userId);
53   -// return AjaxResult.success(menuService.buildMenuTreeSelect(menus));
54   -// }
55   -//
56   -// /**
57 59 // * 加载对应角色菜单列表树
58 60 // */
59 61 // @GetMapping(value = "/roleMenuTreeselect/{roleId}")
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysPermissionController.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.permission;
  2 +
  3 +import cn.iocoder.dashboard.common.pojo.CommonResult;
  4 +import cn.iocoder.dashboard.modules.system.controller.permission.vo.permission.SysPermissionAssignRoleMenuReqVO;
  5 +import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
  6 +import io.swagger.annotations.Api;
  7 +import io.swagger.annotations.ApiImplicitParam;
  8 +import io.swagger.annotations.ApiOperation;
  9 +import org.springframework.validation.annotation.Validated;
  10 +import org.springframework.web.bind.annotation.*;
  11 +
  12 +import javax.annotation.Resource;
  13 +import java.util.Set;
  14 +
  15 +import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
  16 +
  17 +/**
  18 + * 权限 Controller,提供赋予用户、角色的权限的 API 接口
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +@Api(tags = "权限 API")
  23 +@RestController
  24 +@RequestMapping("/system/permission")
  25 +public class SysPermissionController {
  26 +
  27 + @Resource
  28 + private SysPermissionService permissionService;
  29 +
  30 + @ApiOperation("获得角色拥有的菜单编号")
  31 + @GetMapping("/list-role-resources")
  32 + @ApiImplicitParam(name = "roleId", value = "角色编号", required = true)
  33 +// @RequiresPermissions("system:permission:assign-role-menu")
  34 + public CommonResult<Set<Long>> listRoleMenus(Long roleId) {
  35 + return success(permissionService.listRoleMenuIds(roleId));
  36 + }
  37 +
  38 + @PostMapping("/assign-role-menu")
  39 + @ApiOperation("赋予角色菜单")
  40 +// @RequiresPermissions("system:permission:assign-role-resource")
  41 + public CommonResult<Boolean> assignRoleMenu(@Validated @RequestBody SysPermissionAssignRoleMenuReqVO reqVO) {
  42 + permissionService.assignRoleMenu(reqVO.getRoleId(), reqVO.getMenuIds());
  43 + return success(true);
  44 + }
  45 +
  46 +// @GetMapping("/list-admin-roles")
  47 +// @ApiOperation("获得管理员拥有的角色编号列表")
  48 +//// @RequiresPermissions("system:permission:assign-admin-role")
  49 +// @ApiImplicitParam(name = "adminId", value = "管理员编号", required = true)
  50 +// public CommonResult<Set<Integer>> listAdminRoles(Integer adminId) {
  51 +// return success(permissionManager.listAdminRoles(adminId));
  52 +// }
  53 +
  54 +// @PostMapping("/assign-admin-role")
  55 +// @ApiOperation("赋予用户角色")
  56 +//// @RequiresPermissions("system:permission:assign-admin-role")
  57 +// public CommonResult<Boolean> assignAdminRole(PermissionAssignAdminRoleDTO assignAdminRoleDTO) {
  58 +// permissionManager.assignAdminRole(assignAdminRoleDTO);
  59 +// return success(true);
  60 +// }
  61 +
  62 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/menu/SysMenuSimpleRespVO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.permission.vo.menu;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.AllArgsConstructor;
  6 +import lombok.Data;
  7 +import lombok.NoArgsConstructor;
  8 +
  9 +@ApiModel("菜单精简信息 Response VO")
  10 +@Data
  11 +@NoArgsConstructor
  12 +@AllArgsConstructor
  13 +public class SysMenuSimpleRespVO {
  14 +
  15 + @ApiModelProperty(value = "菜单编号", required = true, example = "1024")
  16 + private Integer id;
  17 +
  18 + @ApiModelProperty(value = "菜单名称", required = true, example = "芋道")
  19 + private String name;
  20 +
  21 + @ApiModelProperty(value = "父菜单 ID", required = true, example = "1024")
  22 + private Long parentId;
  23 +
  24 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/permission/SysPermissionAssignRoleMenuReqVO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.permission.vo.permission;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +import java.util.Collections;
  9 +import java.util.Set;
  10 +
  11 +@ApiModel("赋予角色菜单 Request VO")
  12 +@Data
  13 +public class SysPermissionAssignRoleMenuReqVO {
  14 +
  15 + @ApiModelProperty(value = "角色名", required = true, example = "1")
  16 + @NotNull(message = "角色编号不能为空")
  17 + private Long roleId;
  18 +
  19 + @ApiModelProperty(value = "菜单编号列表", example = "1,3,5")
  20 + private Set<Long> menuIds = Collections.emptySet(); // 兜底
  21 +
  22 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/convert/permission/SysMenuConvert.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.dashboard.modules.system.convert.permission;
2 2  
3 3 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO;
4 4 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuRespVO;
  5 +import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuSimpleRespVO;
5 6 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO;
6 7 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
7 8 import org.mapstruct.Mapper;
... ... @@ -22,4 +23,6 @@ public interface SysMenuConvert {
22 23  
23 24 SysMenuRespVO convert(SysMenuDO bean);
24 25  
  26 + List<SysMenuSimpleRespVO> convertList02(List<SysMenuDO> list);
  27 +
25 28 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/permission/SysRoleMenuMapper.java
1 1 package cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission;
2 2  
3 3 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleMenuDO;
  4 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4 5 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 6 import org.apache.ibatis.annotations.Mapper;
6 7  
  8 +import java.util.Collection;
  9 +import java.util.List;
  10 +import java.util.stream.Collectors;
  11 +
7 12 @Mapper
8 13 public interface SysRoleMenuMapper extends BaseMapper<SysRoleMenuDO> {
  14 +
  15 + default List<SysRoleMenuDO> selectListByRoleId(Long roleId) {
  16 + return selectList(new QueryWrapper<SysRoleMenuDO>().eq("role_id", roleId));
  17 + }
  18 +
  19 + default void insertList(Long roleId, Collection<Long> menuIds) {
  20 + List<SysRoleMenuDO> list = menuIds.stream().map(menuId -> {
  21 + SysRoleMenuDO entity = new SysRoleMenuDO();
  22 + entity.setRoleId(roleId);
  23 + entity.setMenuId(menuId);
  24 + return entity;
  25 + }).collect(Collectors.toList());
  26 + // TODO 芋艿,mybatis plus 增加批量插入的功能
  27 + list.forEach(this::insert);
  28 + }
  29 +
  30 + default void deleteListByRoleIdAndMenuIds(Long roleId, Collection<Long> menuIds) {
  31 + delete(new QueryWrapper<SysRoleMenuDO>().eq("role_id", roleId)
  32 + .in("menu_id", menuIds));
  33 + }
  34 +
9 35 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuService.java
... ... @@ -2,7 +2,6 @@ package cn.iocoder.dashboard.modules.system.service.permission;
2 2  
3 3 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO;
4 4 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuListReqVO;
5   -import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuRespVO;
6 5 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO;
7 6 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
8 7  
... ... @@ -22,12 +21,19 @@ public interface SysMenuService {
22 21 void init();
23 22  
24 23 /**
  24 + * 获得所有菜单列表
  25 + *
  26 + * @return 菜单列表
  27 + */
  28 + List<SysMenuDO> listMenus();
  29 +
  30 + /**
25 31 * 筛选菜单列表
26 32 *
27 33 * @param reqVO 筛选条件请求 VO
28 34 * @return 菜单列表
29 35 */
30   - List<SysMenuRespVO> listMenus(SysMenuListReqVO reqVO);
  36 + List<SysMenuDO> listMenus(SysMenuListReqVO reqVO);
31 37  
32 38 /**
33 39 * 获得所有菜单,从缓存中
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java
... ... @@ -44,6 +44,22 @@ public interface SysPermissionService {
44 44 Set<Long> listUserRoleIds(Long userId, @Nullable Collection<Integer> roleStatuses);
45 45  
46 46 /**
  47 + * 获得角色拥有的菜单编号集合
  48 + *
  49 + * @param roleId 角色编号
  50 + * @return 菜单编号集合
  51 + */
  52 + Set<Long> listRoleMenuIds(Long roleId);
  53 +
  54 + /**
  55 + * 赋予赋予角色菜单
  56 + *
  57 + * @param roleId 角色编号
  58 + * @param menuIds 菜单编号集合
  59 + */
  60 + void assignRoleMenu(Long roleId, Set<Long> menuIds);
  61 +
  62 + /**
47 63 * 处理角色删除时,删除关联授权角色
48 64 *
49 65 * @param roleId 角色编号
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java
... ... @@ -3,7 +3,6 @@ package cn.iocoder.dashboard.modules.system.service.permission.impl;
3 3 import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
4 4 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO;
5 5 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuListReqVO;
6   -import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuRespVO;
7 6 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO;
8 7 import cn.iocoder.dashboard.modules.system.convert.permission.SysMenuConvert;
9 8 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysMenuMapper;
... ... @@ -78,10 +77,13 @@ public class SysMenuServiceImpl implements SysMenuService {
78 77 }
79 78  
80 79 @Override
81   - public List<SysMenuRespVO> listMenus(SysMenuListReqVO reqVO) {
82   - List<SysMenuDO> list = menuMapper.selectList(reqVO);
83   - // TODO 排序
84   - return SysMenuConvert.INSTANCE.convertList(list);
  80 + public List<SysMenuDO> listMenus() {
  81 + return menuMapper.selectList();
  82 + }
  83 +
  84 + @Override
  85 + public List<SysMenuDO> listMenus(SysMenuListReqVO reqVO) {
  86 + return menuMapper.selectList(reqVO);
85 87 }
86 88  
87 89 @Override
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java
1 1 package cn.iocoder.dashboard.modules.system.service.permission.impl;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.hutool.core.collection.CollectionUtil;
4 5 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysRoleMenuMapper;
5 6 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysUserRoleMapper;
... ... @@ -16,6 +17,7 @@ import com.google.common.collect.ImmutableMultimap;
16 17 import com.google.common.collect.Multimap;
17 18 import lombok.extern.slf4j.Slf4j;
18 19 import org.springframework.stereotype.Service;
  20 +import org.springframework.transaction.annotation.Transactional;
19 21  
20 22 import javax.annotation.PostConstruct;
21 23 import javax.annotation.Resource;
... ... @@ -111,6 +113,36 @@ public class SysPermissionServiceImpl implements SysPermissionService {
111 113 }
112 114  
113 115 @Override
  116 + public Set<Long> listRoleMenuIds(Long roleId) {
  117 + // 如果是管理员的情况下,获取全部菜单编号
  118 + SysRoleDO role = roleService.getRole(roleId);
  119 + if (roleService.hasAnyAdmin(Collections.singletonList(role))) {
  120 + return CollectionUtils.convertSet(menuService.listMenus(), SysMenuDO::getId);
  121 + }
  122 + // 如果是非管理员的情况下,获得拥有的菜单编号
  123 + return CollectionUtils.convertSet(roleMenuMapper.selectListByRoleId(roleId),
  124 + SysRoleMenuDO::getMenuId);
  125 + }
  126 +
  127 + @Override
  128 + @Transactional
  129 + public void assignRoleMenu(Long roleId, Set<Long> menuIds) {
  130 + // 获得角色拥有菜单编号
  131 + Set<Long> dbMenuIds = CollectionUtils.convertSet(roleMenuMapper.selectListByRoleId(roleId),
  132 + SysRoleMenuDO::getMenuId);
  133 + // 计算新增和删除的菜单编号
  134 + Collection<Long> createMenuIds = CollUtil.subtract(menuIds, dbMenuIds);
  135 + Collection<Long> deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIds);
  136 + // 执行新增和删除。对于已经授权的菜单,不用做任何处理
  137 + if (!CollectionUtil.isEmpty(createMenuIds)) {
  138 + roleMenuMapper.insertList(roleId, createMenuIds);
  139 + }
  140 + if (!CollectionUtil.isEmpty(deleteMenuIds)) {
  141 + roleMenuMapper.deleteListByRoleIdAndMenuIds(roleId, deleteMenuIds);
  142 + }
  143 + }
  144 +
  145 + @Override
114 146 public void processRoleDeleted(Long roleId) {
115 147 // TODO 实现我
116 148 // // 标记删除 RoleResource
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java
... ... @@ -18,6 +18,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
18 18 import com.google.common.collect.ImmutableMap;
19 19 import lombok.extern.slf4j.Slf4j;
20 20 import org.springframework.stereotype.Service;
  21 +import org.springframework.transaction.annotation.Transactional;
21 22 import org.springframework.util.StringUtils;
22 23  
23 24 import javax.annotation.PostConstruct;
... ... @@ -115,6 +116,7 @@ public class SysRoleServiceImpl implements SysRoleService {
115 116 }
116 117  
117 118 @Override
  119 + @Transactional
118 120 public void deleteRole(Long id) {
119 121 // 校验是否可以更新
120 122 this.checkUpdateRole(id);
... ... @@ -129,7 +131,6 @@ public class SysRoleServiceImpl implements SysRoleService {
129 131 return roleMapper.selectById(id);
130 132 }
131 133  
132   -
133 134 @Override
134 135 public PageResult<SysRoleDO> pageRole(SysRolePageReqVO reqVO) {
135 136 IPage<SysRoleDO> roleDOPage = roleMapper.selectPage(reqVO);
... ...