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,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 * @param menuId 菜单ID 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,5 +148,5 @@ export function handleTree(data, id, parentId, children, rootId) {
148 //返回第一层 148 //返回第一层
149 return father[parentId] === rootId; 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,9 +182,9 @@
182 </el-select> 182 </el-select>
183 </el-form-item> 183 </el-form-item>
184 <el-form-item label="数据权限" v-show="form.dataScope == 2"> 184 <el-form-item label="数据权限" v-show="form.dataScope == 2">
  185 + <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
185 <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox> 186 <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
186 <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox> 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 <el-tree 188 <el-tree
189 class="tree-border" 189 class="tree-border"
190 :data="deptOptions" 190 :data="deptOptions"
@@ -192,7 +192,7 @@ @@ -192,7 +192,7 @@
192 default-expand-all 192 default-expand-all
193 ref="dept" 193 ref="dept"
194 node-key="id" 194 node-key="id"
195 - :check-strictly="!form.deptCheckStrictly" 195 + :check-strictly="form.deptCheckStrictly"
196 empty-text="加载中,请稍后" 196 empty-text="加载中,请稍后"
197 :props="defaultProps" 197 :props="defaultProps"
198 ></el-tree> 198 ></el-tree>
@@ -214,16 +214,16 @@ @@ -214,16 +214,16 @@
214 <el-input v-model="form.code" :disabled="true" /> 214 <el-input v-model="form.code" :disabled="true" />
215 </el-form-item> 215 </el-form-item>
216 <el-form-item label="菜单权限"> 216 <el-form-item label="菜单权限">
  217 + <el-checkbox v-model="!form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动(选中父节点,自动选择子节点)</el-checkbox>
217 <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox> 218 <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
218 <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox> 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 <el-tree 220 <el-tree
221 class="tree-border" 221 class="tree-border"
222 :data="menuOptions" 222 :data="menuOptions"
223 show-checkbox 223 show-checkbox
224 ref="menu" 224 ref="menu"
225 node-key="id" 225 node-key="id"
226 - :check-strictly="!form.menuCheckStrictly" 226 + :check-strictly="form.menuCheckStrictly"
227 empty-text="加载中,请稍后" 227 empty-text="加载中,请稍后"
228 :props="defaultProps" 228 :props="defaultProps"
229 ></el-tree> 229 ></el-tree>
@@ -239,7 +239,8 @@ @@ -239,7 +239,8 @@
239 239
240 <script> 240 <script>
241 import { listRole, getRole, delRole, addRole, updateRole, exportRole, dataScope, changeRoleStatus } from "@/api/system/role"; 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 import { treeselect as deptTreeselect, roleDeptTreeselect } from "@/api/system/dept"; 244 import { treeselect as deptTreeselect, roleDeptTreeselect } from "@/api/system/dept";
244 import {SysCommonStatusEnum, SysMenuTypeEnum} from "@/utils/constants"; 245 import {SysCommonStatusEnum, SysMenuTypeEnum} from "@/utils/constants";
245 import {DICT_TYPE, getDictDataLabel, getDictDatas} from "@/utils/dict"; 246 import {DICT_TYPE, getDictDataLabel, getDictDatas} from "@/utils/dict";
@@ -311,8 +312,8 @@ export default { @@ -311,8 +312,8 @@ export default {
311 // 表单参数 312 // 表单参数
312 form: {}, 313 form: {},
313 defaultProps: { 314 defaultProps: {
314 - children: "children",  
315 - label: "label" 315 + label: "name",
  316 + children: "children"
316 }, 317 },
317 // 表单校验 318 // 表单校验
318 rules: { 319 rules: {
@@ -349,12 +350,6 @@ export default { @@ -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 getDeptTreeselect() { 354 getDeptTreeselect() {
360 deptTreeselect().then(response => { 355 deptTreeselect().then(response => {
@@ -379,13 +374,6 @@ export default { @@ -379,13 +374,6 @@ export default {
379 checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys); 374 checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
380 return checkedKeys; 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 /** 根据角色ID查询部门树结构 */ 377 /** 根据角色ID查询部门树结构 */
390 getRoleDeptTreeselect(id) { 378 getRoleDeptTreeselect(id) {
391 return roleDeptTreeselect(id).then(response => { 379 return roleDeptTreeselect(id).then(response => {
@@ -432,23 +420,22 @@ export default { @@ -432,23 +420,22 @@ export default {
432 }, 420 },
433 // 表单重置 421 // 表单重置
434 reset() { 422 reset() {
435 - if (this.$refs.menu != undefined) { 423 + if (this.$refs.menu !== undefined) {
436 this.$refs.menu.setCheckedKeys([]); 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 this.form = { 430 this.form = {
443 id: undefined, 431 id: undefined,
444 name: undefined, 432 name: undefined,
445 code: undefined, 433 code: undefined,
446 sort: 0, 434 sort: 0,
447 - status: "0",  
448 - ids: [],  
449 deptIds: [], 435 deptIds: [],
450 - menuCheckStrictly: true,  
451 - deptCheckStrictly: true, 436 + menuIds: [],
  437 + menuCheckStrictly: false, // 非严格,菜单弹窗的父子级联动
  438 + deptCheckStrictly: false,
452 remark: undefined 439 remark: undefined
453 }; 440 };
454 this.resetForm("form"); 441 this.resetForm("form");
@@ -466,12 +453,12 @@ export default { @@ -466,12 +453,12 @@ export default {
466 }, 453 },
467 // 树权限(展开/折叠) 454 // 树权限(展开/折叠)
468 handleCheckedTreeExpand(value, type) { 455 handleCheckedTreeExpand(value, type) {
469 - if (type == 'menu') { 456 + if (type === 'menu') {
470 let treeList = this.menuOptions; 457 let treeList = this.menuOptions;
471 for (let i = 0; i < treeList.length; i++) { 458 for (let i = 0; i < treeList.length; i++) {
472 this.$refs.menu.store.nodesMap[treeList[i].id].expanded = value; 459 this.$refs.menu.store.nodesMap[treeList[i].id].expanded = value;
473 } 460 }
474 - } else if (type == 'dept') { 461 + } else if (type === 'dept') {
475 let treeList = this.deptOptions; 462 let treeList = this.deptOptions;
476 for (let i = 0; i < treeList.length; i++) { 463 for (let i = 0; i < treeList.length; i++) {
477 this.$refs.dept.store.nodesMap[treeList[i].id].expanded = value; 464 this.$refs.dept.store.nodesMap[treeList[i].id].expanded = value;
@@ -480,18 +467,18 @@ export default { @@ -480,18 +467,18 @@ export default {
480 }, 467 },
481 // 树权限(全选/全不选) 468 // 树权限(全选/全不选)
482 handleCheckedTreeNodeAll(value, type) { 469 handleCheckedTreeNodeAll(value, type) {
483 - if (type == 'menu') { 470 + if (type === 'menu') {
484 this.$refs.menu.setCheckedNodes(value ? this.menuOptions: []); 471 this.$refs.menu.setCheckedNodes(value ? this.menuOptions: []);
485 - } else if (type == 'dept') { 472 + } else if (type === 'dept') {
486 this.$refs.dept.setCheckedNodes(value ? this.deptOptions: []); 473 this.$refs.dept.setCheckedNodes(value ? this.deptOptions: []);
487 } 474 }
488 }, 475 },
489 // 树权限(父子联动) 476 // 树权限(父子联动)
490 handleCheckedTreeConnect(value, type) { 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,27 +501,27 @@ export default {
514 handleMenu(row) { 501 handleMenu(row) {
515 this.reset(); 502 this.reset();
516 const id = row.id 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 this.openMenu = true; 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 handleDataScope(row) { 527 handleDataScope(row) {
@@ -556,16 +543,12 @@ export default { @@ -556,16 +543,12 @@ export default {
556 this.$refs["form"].validate(valid => { 543 this.$refs["form"].validate(valid => {
557 if (valid) { 544 if (valid) {
558 if (this.form.id !== undefined) { 545 if (this.form.id !== undefined) {
559 - // TODO 芋艿:需要迁移  
560 - // this.form.ids = this.getMenuAllCheckedKeys();  
561 updateRole(this.form).then(response => { 546 updateRole(this.form).then(response => {
562 this.msgSuccess("修改成功"); 547 this.msgSuccess("修改成功");
563 this.open = false; 548 this.open = false;
564 this.getList(); 549 this.getList();
565 }); 550 });
566 } else { 551 } else {
567 - // TODO 芋艿:需要迁移  
568 - // this.form.ids = this.getMenuAllCheckedKeys();  
569 addRole(this.form).then(response => { 552 addRole(this.form).then(response => {
570 this.msgSuccess("新增成功"); 553 this.msgSuccess("新增成功");
571 this.open = false; 554 this.open = false;
@@ -577,7 +560,7 @@ export default { @@ -577,7 +560,7 @@ export default {
577 }, 560 },
578 /** 提交按钮(数据权限) */ 561 /** 提交按钮(数据权限) */
579 submitDataScope: function() { 562 submitDataScope: function() {
580 - if (this.form.id != undefined) { 563 + if (this.form.id !== undefined) {
581 this.form.deptIds = this.getDeptAllCheckedKeys(); 564 this.form.deptIds = this.getDeptAllCheckedKeys();
582 dataScope(this.form).then(response => { 565 dataScope(this.form).then(response => {
583 this.msgSuccess("修改成功"); 566 this.msgSuccess("修改成功");
@@ -589,11 +572,13 @@ export default { @@ -589,11 +572,13 @@ export default {
589 /** 提交按钮(菜单权限) */ 572 /** 提交按钮(菜单权限) */
590 submitMenu: function() { 573 submitMenu: function() {
591 // TODO 需要改动下 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 this.msgSuccess("修改成功"); 580 this.msgSuccess("修改成功");
596 - this.openDataScope = false; 581 + this.openMenu = false;
597 this.getList(); 582 this.getList();
598 }); 583 });
599 } 584 }
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/SysMenuController.java
1 package cn.iocoder.dashboard.modules.system.controller.permission; 1 package cn.iocoder.dashboard.modules.system.controller.permission;
2 2
  3 +import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
3 import cn.iocoder.dashboard.common.pojo.CommonResult; 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 import cn.iocoder.dashboard.modules.system.convert.permission.SysMenuConvert; 6 import cn.iocoder.dashboard.modules.system.convert.permission.SysMenuConvert;
9 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO; 7 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
10 import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService; 8 import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService;
@@ -15,6 +13,7 @@ import org.springframework.validation.annotation.Validated; @@ -15,6 +13,7 @@ import org.springframework.validation.annotation.Validated;
15 import org.springframework.web.bind.annotation.*; 13 import org.springframework.web.bind.annotation.*;
16 14
17 import javax.annotation.Resource; 15 import javax.annotation.Resource;
  16 +import java.util.Comparator;
18 import java.util.List; 17 import java.util.List;
19 18
20 import static cn.iocoder.dashboard.common.pojo.CommonResult.success; 19 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
@@ -30,8 +29,22 @@ public class SysMenuController { @@ -30,8 +29,22 @@ public class SysMenuController {
30 @ApiOperation("获取菜单列表") 29 @ApiOperation("获取菜单列表")
31 // @PreAuthorize("@ss.hasPermi('system:menu:list')") 30 // @PreAuthorize("@ss.hasPermi('system:menu:list')")
32 @GetMapping("/list") 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 @ApiOperation("获取菜单信息") 50 @ApiOperation("获取菜单信息")
@@ -43,17 +56,6 @@ public class SysMenuController { @@ -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 // @GetMapping(value = "/roleMenuTreeselect/{roleId}") 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,6 +2,7 @@ package cn.iocoder.dashboard.modules.system.convert.permission;
2 2
3 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO; 3 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO;
4 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuRespVO; 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 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO; 6 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO;
6 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO; 7 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
7 import org.mapstruct.Mapper; 8 import org.mapstruct.Mapper;
@@ -22,4 +23,6 @@ public interface SysMenuConvert { @@ -22,4 +23,6 @@ public interface SysMenuConvert {
22 23
23 SysMenuRespVO convert(SysMenuDO bean); 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 package cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission; 1 package cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission;
2 2
3 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleMenuDO; 3 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleMenuDO;
  4 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4 import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 import org.apache.ibatis.annotations.Mapper; 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 @Mapper 12 @Mapper
8 public interface SysRoleMenuMapper extends BaseMapper<SysRoleMenuDO> { 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,7 +2,6 @@ package cn.iocoder.dashboard.modules.system.service.permission;
2 2
3 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO; 3 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO;
4 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuListReqVO; 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 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO; 5 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO;
7 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO; 6 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
8 7
@@ -22,12 +21,19 @@ public interface SysMenuService { @@ -22,12 +21,19 @@ public interface SysMenuService {
22 void init(); 21 void init();
23 22
24 /** 23 /**
  24 + * 获得所有菜单列表
  25 + *
  26 + * @return 菜单列表
  27 + */
  28 + List<SysMenuDO> listMenus();
  29 +
  30 + /**
25 * 筛选菜单列表 31 * 筛选菜单列表
26 * 32 *
27 * @param reqVO 筛选条件请求 VO 33 * @param reqVO 筛选条件请求 VO
28 * @return 菜单列表 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,6 +44,22 @@ public interface SysPermissionService {
44 Set<Long> listUserRoleIds(Long userId, @Nullable Collection<Integer> roleStatuses); 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 * @param roleId 角色编号 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,7 +3,6 @@ package cn.iocoder.dashboard.modules.system.service.permission.impl;
3 import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; 3 import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
4 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO; 4 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuCreateReqVO;
5 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuListReqVO; 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; 6 import cn.iocoder.dashboard.modules.system.controller.permission.vo.menu.SysMenuUpdateReqVO;
8 import cn.iocoder.dashboard.modules.system.convert.permission.SysMenuConvert; 7 import cn.iocoder.dashboard.modules.system.convert.permission.SysMenuConvert;
9 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysMenuMapper; 8 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysMenuMapper;
@@ -78,10 +77,13 @@ public class SysMenuServiceImpl implements SysMenuService { @@ -78,10 +77,13 @@ public class SysMenuServiceImpl implements SysMenuService {
78 } 77 }
79 78
80 @Override 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 @Override 89 @Override
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java
1 package cn.iocoder.dashboard.modules.system.service.permission.impl; 1 package cn.iocoder.dashboard.modules.system.service.permission.impl;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.hutool.core.collection.CollectionUtil; 4 import cn.hutool.core.collection.CollectionUtil;
4 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysRoleMenuMapper; 5 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysRoleMenuMapper;
5 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysUserRoleMapper; 6 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysUserRoleMapper;
@@ -16,6 +17,7 @@ import com.google.common.collect.ImmutableMultimap; @@ -16,6 +17,7 @@ import com.google.common.collect.ImmutableMultimap;
16 import com.google.common.collect.Multimap; 17 import com.google.common.collect.Multimap;
17 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
18 import org.springframework.stereotype.Service; 19 import org.springframework.stereotype.Service;
  20 +import org.springframework.transaction.annotation.Transactional;
19 21
20 import javax.annotation.PostConstruct; 22 import javax.annotation.PostConstruct;
21 import javax.annotation.Resource; 23 import javax.annotation.Resource;
@@ -111,6 +113,36 @@ public class SysPermissionServiceImpl implements SysPermissionService { @@ -111,6 +113,36 @@ public class SysPermissionServiceImpl implements SysPermissionService {
111 } 113 }
112 114
113 @Override 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 public void processRoleDeleted(Long roleId) { 146 public void processRoleDeleted(Long roleId) {
115 // TODO 实现我 147 // TODO 实现我
116 // // 标记删除 RoleResource 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,6 +18,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
18 import com.google.common.collect.ImmutableMap; 18 import com.google.common.collect.ImmutableMap;
19 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
20 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
  21 +import org.springframework.transaction.annotation.Transactional;
21 import org.springframework.util.StringUtils; 22 import org.springframework.util.StringUtils;
22 23
23 import javax.annotation.PostConstruct; 24 import javax.annotation.PostConstruct;
@@ -115,6 +116,7 @@ public class SysRoleServiceImpl implements SysRoleService { @@ -115,6 +116,7 @@ public class SysRoleServiceImpl implements SysRoleService {
115 } 116 }
116 117
117 @Override 118 @Override
  119 + @Transactional
118 public void deleteRole(Long id) { 120 public void deleteRole(Long id) {
119 // 校验是否可以更新 121 // 校验是否可以更新
120 this.checkUpdateRole(id); 122 this.checkUpdateRole(id);
@@ -129,7 +131,6 @@ public class SysRoleServiceImpl implements SysRoleService { @@ -129,7 +131,6 @@ public class SysRoleServiceImpl implements SysRoleService {
129 return roleMapper.selectById(id); 131 return roleMapper.selectById(id);
130 } 132 }
131 133
132 -  
133 @Override 134 @Override
134 public PageResult<SysRoleDO> pageRole(SysRolePageReqVO reqVO) { 135 public PageResult<SysRoleDO> pageRole(SysRolePageReqVO reqVO) {
135 IPage<SysRoleDO> roleDOPage = roleMapper.selectPage(reqVO); 136 IPage<SysRoleDO> roleDOPage = roleMapper.selectPage(reqVO);