Sfoglia il codice sorgente

优化多角色数据权限匹配规则

RuoYi 3 anni fa
parent
commit
c95cb70af3
23 ha cambiato i file con 296 aggiunte e 47 eliminazioni
  1. 1 24
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
  2. 17 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
  3. 31 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
  4. 1 1
      ruoyi-admin/src/main/resources/templates/system/dept/add.html
  5. 1 1
      ruoyi-admin/src/main/resources/templates/system/dept/tree.html
  6. 1 1
      ruoyi-admin/src/main/resources/templates/system/role/dataScope.html
  7. 1 2
      ruoyi-admin/src/main/resources/templates/system/user/add.html
  8. 51 0
      ruoyi-admin/src/main/resources/templates/system/user/deptTree.html
  9. 1 2
      ruoyi-admin/src/main/resources/templates/system/user/edit.html
  10. 1 1
      ruoyi-admin/src/main/resources/templates/system/user/user.html
  11. 5 0
      ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
  12. 27 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/context/PermissionContextHolder.java
  13. 1 1
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java
  14. 14 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java
  15. 26 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
  16. 11 2
      ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
  17. 30 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/PermissionsAspect.java
  18. 27 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysLoginService.java
  19. 8 0
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
  20. 8 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
  21. 5 12
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
  22. 21 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
  23. 7 0
      ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml

+ 1 - 24
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java

@@ -17,7 +17,6 @@ import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.Ztree;
 import com.ruoyi.common.core.domain.entity.SysDept;
-import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.service.ISysDeptService;
@@ -166,7 +165,7 @@ public class SysDeptController extends BaseController
      */
     @GetMapping(value = { "/selectDeptTree/{deptId}", "/selectDeptTree/{deptId}/{excludeId}" })
     public String selectDeptTree(@PathVariable("deptId") Long deptId,
-            @PathVariable(value = "excludeId", required = false) String excludeId, ModelMap mmap)
+            @PathVariable(value = "excludeId", required = false) Long excludeId, ModelMap mmap)
     {
         mmap.put("dept", deptService.selectDeptById(deptId));
         mmap.put("excludeId", excludeId);
@@ -174,17 +173,6 @@ public class SysDeptController extends BaseController
     }
 
     /**
-     * 加载部门列表树
-     */
-    @GetMapping("/treeData")
-    @ResponseBody
-    public List<Ztree> treeData()
-    {
-        List<Ztree> ztrees = deptService.selectDeptTree(new SysDept());
-        return ztrees;
-    }
-
-    /**
      * 加载部门列表树(排除下级)
      */
     @GetMapping("/treeData/{excludeId}")
@@ -196,15 +184,4 @@ public class SysDeptController extends BaseController
         List<Ztree> ztrees = deptService.selectDeptTreeExcludeChild(dept);
         return ztrees;
     }
-
-    /**
-     * 加载角色部门(数据权限)列表树
-     */
-    @GetMapping("/roleDeptTreeData")
-    @ResponseBody
-    public List<Ztree> deptTreeData(SysRole role)
-    {
-        List<Ztree> ztrees = deptService.roleDeptTreeData(role);
-        return ztrees;
-    }
 }

+ 17 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java

@@ -15,6 +15,7 @@ import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.Ztree;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.page.TableDataInfo;
@@ -22,6 +23,7 @@ import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.shiro.util.AuthorizationUtils;
 import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.service.ISysDeptService;
 import com.ruoyi.system.service.ISysRoleService;
 import com.ruoyi.system.service.ISysUserService;
 
@@ -42,6 +44,9 @@ public class SysRoleController extends BaseController
     @Autowired
     private ISysUserService userService;
 
+    @Autowired
+    private ISysDeptService deptService;
+
     @RequiresPermissions("system:role:view")
     @GetMapping()
     public String role()
@@ -303,4 +308,16 @@ public class SysRoleController extends BaseController
         roleService.checkRoleDataScope(roleId);
         return toAjax(roleService.insertAuthUsers(roleId, userIds));
     }
+
+    /**
+     * 加载角色部门(数据权限)列表树
+     */
+    @RequiresPermissions("system:role:edit")
+    @GetMapping("/deptTreeData")
+    @ResponseBody
+    public List<Ztree> deptTreeData(SysRole role)
+    {
+        List<Ztree> ztrees = deptService.roleDeptTreeData(role);
+        return ztrees;
+    }
 }

+ 31 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java

@@ -18,6 +18,8 @@ import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.Ztree;
+import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.page.TableDataInfo;
@@ -28,6 +30,7 @@ import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.shiro.service.SysPasswordService;
 import com.ruoyi.framework.shiro.util.AuthorizationUtils;
+import com.ruoyi.system.service.ISysDeptService;
 import com.ruoyi.system.service.ISysPostService;
 import com.ruoyi.system.service.ISysRoleService;
 import com.ruoyi.system.service.ISysUserService;
@@ -48,6 +51,9 @@ public class SysUserController extends BaseController
 
     @Autowired
     private ISysRoleService roleService;
+    
+    @Autowired
+    private ISysDeptService deptService;
 
     @Autowired
     private ISysPostService postService;
@@ -299,4 +305,29 @@ public class SysUserController extends BaseController
         userService.checkUserDataScope(user.getUserId());
         return toAjax(userService.changeStatus(user));
     }
+
+    /**
+     * 加载部门列表树
+     */
+    @RequiresPermissions("system:user:list")
+    @GetMapping("/deptTreeData")
+    @ResponseBody
+    public List<Ztree> deptTreeData()
+    {
+        List<Ztree> ztrees = deptService.selectDeptTree(new SysDept());
+        return ztrees;
+    }
+
+    /**
+     * 选择部门树
+     * 
+     * @param deptId 部门ID
+     */
+    @RequiresPermissions("system:user:list")
+    @GetMapping("/selectDeptTree/{deptId}")
+    public String selectDeptTree(@PathVariable("deptId") Long deptId, ModelMap mmap)
+    {
+        mmap.put("dept", deptService.selectDeptById(deptId));
+        return prefix + "/deptTree";
+    }
 }

+ 1 - 1
ruoyi-admin/src/main/resources/templates/system/dept/add.html

@@ -116,7 +116,7 @@
 			var options = {
 				title: '部门选择',
 				width: "380",
-				url: prefix + "/selectDeptTree/" + treeId,
+				url: prefix + "/selectDeptTree/" + treeId + "/0",
 				callBack: doSubmit
 			};
 			$.modal.openOptions(options);

+ 1 - 1
ruoyi-admin/src/main/resources/templates/system/dept/tree.html

@@ -32,7 +32,7 @@
 	    var deptId = [[${deptId}]];
 	    var excludeId = [[${excludeId}]];
 		$(function() {
-			var url = $.common.isEmpty(excludeId) ? prefix + "/treeData": prefix + "/treeData/" + excludeId;
+			var url = prefix + "/treeData/" + excludeId;
 			var options = {
 		        url: url,
 		        expandLevel: 2,

+ 1 - 1
ruoyi-admin/src/main/resources/templates/system/role/dataScope.html

@@ -52,7 +52,7 @@
 	<script type="text/javascript">
 	
 	    $(function() {
-			var url = ctx + "system/dept/roleDeptTreeData?roleId=" + $("#roleId").val();
+			var url = ctx + "system/role/deptTreeData?roleId=" + $("#roleId").val();
 			var options = {
 				id: "deptTrees",
 		        url: url,

+ 1 - 2
ruoyi-admin/src/main/resources/templates/system/user/add.html

@@ -239,7 +239,7 @@
         function selectDeptTree() {
         	var treeId = $("#treeId").val();
         	var deptId = $.common.isEmpty(treeId) ? "100" : $("#treeId").val();
-        	var url = ctx + "system/dept/selectDeptTree/" + deptId;
+        	var url = ctx + "system/user/selectDeptTree/" + deptId;
 			var options = {
 				title: '选择部门',
 				width: "380",
@@ -250,7 +250,6 @@
 		}
 		
 		function doSubmit(index, layero){
-			var tree = layero.find("iframe")[0].contentWindow.$._tree;
 			var body = $.modal.getChildFrame(index);
    			$("#treeId").val(body.find('#treeId').val());
    			$("#treeName").val(body.find('#treeName').val());

+ 51 - 0
ruoyi-admin/src/main/resources/templates/system/user/deptTree.html

@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('部门树选择')" />
+	<th:block th:include="include :: ztree-css" />
+</head>
+<style>
+	body{height:auto;font-family: "Microsoft YaHei";}
+	button{font-family: "SimSun","Helvetica Neue",Helvetica,Arial;}
+</style>
+<body class="hold-transition box box-main">
+	<input id="treeId"   name="treeId"    type="hidden" th:value="${dept.deptId}"/>
+	<input id="treeName" name="treeName"  type="hidden" th:value="${dept.deptName}"/>
+	<div class="wrapper"><div class="treeShowHideButton" onclick="$.tree.toggleSearch();">
+		<label id="btnShow" title="显示搜索" style="display:none;">︾</label>
+		<label id="btnHide" title="隐藏搜索">︽</label>
+	</div>
+	<div class="treeSearchInput" id="search">
+		<label for="keyword">关键字:</label><input type="text" class="empty" id="keyword" maxlength="50">
+		<button class="btn" id="btn" onclick="$.tree.searchNode()"> 搜索 </button>
+	</div>
+	<div class="treeExpandCollapse">
+		<a href="#" onclick="$.tree.expand()">展开</a> /
+		<a href="#" onclick="$.tree.collapse()">折叠</a>
+	</div>
+	<div id="tree" class="ztree treeselect"></div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: ztree-js" />
+	<script th:inline="javascript">
+	    var prefix = ctx + "system/user"
+	    var deptId = [[${deptId}]];
+		$(function() {
+			var url = prefix + "/deptTreeData";
+			var options = {
+		        url: url,
+		        expandLevel: 2,
+		        onClick : zOnClick
+		    };
+			$.tree.init(options);
+		});
+		
+		function zOnClick(event, treeId, treeNode) {
+		    var treeId = treeNode.id;
+		    var treeName = treeNode.name;
+		    $("#treeId").val(treeId);
+		    $("#treeName").val(treeName);
+		}
+	</script>
+</body>
+</html>

+ 1 - 2
ruoyi-admin/src/main/resources/templates/system/user/edit.html

@@ -203,7 +203,7 @@
         /* 用户管理-修改-选择部门树 */
         function selectDeptTree() {
         	var deptId = $.common.isEmpty($("#treeId").val()) ? "100" : $("#treeId").val();
-            var url = ctx + "system/dept/selectDeptTree/" + deptId;
+            var url = ctx + "system/user/selectDeptTree/" + deptId;
 		    var options = {
 				title: '选择部门',
 				width: "380",
@@ -214,7 +214,6 @@
 		}
 		
 		function doSubmit(index, layero){
-			var tree = layero.find("iframe")[0].contentWindow.$._tree;
 			var body = $.modal.getChildFrame(index);
    			$("#treeId").val(body.find('#treeId').val());
    			$("#treeName").val(body.find('#treeName').val());

+ 1 - 1
ruoyi-admin/src/main/resources/templates/system/user/user.html

@@ -191,7 +191,7 @@
 		
 		function queryDeptTree()
 		{
-			var url = ctx + "system/dept/treeData";
+			var url = ctx + "system/user/deptTreeData";
 			var options = {
 		        url: url,
 		        expandLevel: 2,

+ 5 - 0
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java

@@ -25,4 +25,9 @@ public @interface DataScope
      * 用户表的别名
      */
     public String userAlias() default "";
+
+    /**
+     * 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@RequiresPermissions获取,多个权限用逗号分隔开来
+     */
+    public String permission() default "";
 }

+ 27 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/context/PermissionContextHolder.java

@@ -0,0 +1,27 @@
+package com.ruoyi.common.core.context;
+
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import com.ruoyi.common.core.text.Convert;
+
+/**
+ * 权限信息
+ * 
+ * @author ruoyi
+ */
+public class PermissionContextHolder
+{
+    private static final String PERMISSION_CONTEXT_ATTRIBUTES = "PERMISSION_CONTEXT";
+
+    public static void setContext(String permission)
+    {
+        RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission,
+                RequestAttributes.SCOPE_REQUEST);
+    }
+
+    public static String getContext()
+    {
+        return Convert.toStr(RequestContextHolder.currentRequestAttributes().getAttribute(PERMISSION_CONTEXT_ATTRIBUTES,
+                RequestAttributes.SCOPE_REQUEST));
+    }
+}

+ 1 - 1
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java

@@ -131,7 +131,7 @@ public class SysDictData extends BaseEntity
 
     public boolean getDefault()
     {
-        return UserConstants.YES.equals(this.isDefault) ? true : false;
+        return UserConstants.YES.equals(this.isDefault);
     }
 
     public String getIsDefault()

+ 14 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java

@@ -1,5 +1,6 @@
 package com.ruoyi.common.core.domain.entity;
 
+import java.util.Set;
 import javax.validation.constraints.*;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
@@ -52,6 +53,9 @@ public class SysRole extends BaseEntity
     /** 部门组(数据权限) */
     private Long[] deptIds;
 
+    /** 角色菜单权限 */
+    private Set<String> permissions;
+
     public SysRole()
     {
 
@@ -177,6 +181,16 @@ public class SysRole extends BaseEntity
         this.deptIds = deptIds;
     }
 
+    public Set<String> getPermissions()
+    {
+        return permissions;
+    }
+
+    public void setPermissions(Set<String> permissions)
+    {
+        this.permissions = permissions;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

+ 26 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java

@@ -325,6 +325,32 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
     }
 
     /**
+     * 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
+     *
+     * @param set 给定的集合
+     * @param array 给定的数组
+     * @return boolean 结果
+     */
+    public static boolean containsAny(Collection<String> collection, String... array)
+    {
+        if (isEmpty(collection) || isEmpty(array))
+        {
+            return false;
+        }
+        else
+        {
+            for (String str : array)
+            {
+                if (collection.contains(str))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
      * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
      *
      * @param cs 指定字符串

+ 11 - 2
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java

@@ -7,9 +7,11 @@ import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.springframework.stereotype.Component;
 import com.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.core.context.PermissionContextHolder;
 import com.ruoyi.common.core.domain.BaseEntity;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.text.Convert;
 import com.ruoyi.common.utils.ShiroUtils;
 import com.ruoyi.common.utils.StringUtils;
 
@@ -68,8 +70,9 @@ public class DataScopeAspect
             // 如果是超级管理员,则不过滤数据
             if (!currentUser.isAdmin())
             {
+                String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
                 dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
-                        controllerDataScope.userAlias());
+                        controllerDataScope.userAlias(), permission);
             }
         }
     }
@@ -81,8 +84,9 @@ public class DataScopeAspect
      * @param user 用户
      * @param deptAlias 部门别名
      * @param userAlias 用户别名
+     * @param permission 权限字符
      */
-    public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
+    public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
     {
         StringBuilder sqlString = new StringBuilder();
         List<String> conditions = new ArrayList<String>();
@@ -94,6 +98,11 @@ public class DataScopeAspect
             {
                 continue;
             }
+            if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
+                    && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
+            {
+                continue;
+            }
             if (DATA_SCOPE_ALL.equals(dataScope))
             {
                 sqlString = new StringBuilder();

+ 30 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/PermissionsAspect.java

@@ -0,0 +1,30 @@
+package com.ruoyi.framework.aspectj;
+
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.core.context.PermissionContextHolder;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 自定义权限拦截器,将权限字符串放到当前请求中以便用于多个角色匹配符合要求的权限
+ * 
+ * @author ruoyi
+ */
+@Aspect
+@Component
+public class PermissionsAspect
+{
+    @Before("@annotation(controllerRequiresPermissions)")
+    public void doBefore(JoinPoint point, RequiresPermissions controllerRequiresPermissions) throws Throwable
+    {
+        handleRequiresPermissions(point, controllerRequiresPermissions);
+    }
+
+    protected void handleRequiresPermissions(final JoinPoint joinPoint, RequiresPermissions requiresPermissions)
+    {
+        PermissionContextHolder.setContext(StringUtils.join(requiresPermissions.value(), ","));
+    }
+}

+ 27 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/shiro/service/SysLoginService.java

@@ -1,10 +1,13 @@
 package com.ruoyi.framework.shiro.service;
 
+import java.util.List;
+import java.util.Set;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.constant.ShiroConstants;
 import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.enums.UserStatus;
 import com.ruoyi.common.exception.user.CaptchaException;
@@ -19,6 +22,7 @@ import com.ruoyi.common.utils.ShiroUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.manager.AsyncManager;
 import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.system.service.ISysMenuService;
 import com.ruoyi.system.service.ISysUserService;
 
 /**
@@ -35,6 +39,9 @@ public class SysLoginService
     @Autowired
     private ISysUserService userService;
 
+    @Autowired
+    private ISysMenuService menuService;
+
     /**
      * 登录
      */
@@ -104,6 +111,7 @@ public class SysLoginService
         passwordService.validate(user, password);
 
         AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
+        setRolePermission(user);
         recordLoginInfo(user.getUserId());
         return user;
     }
@@ -129,6 +137,25 @@ public class SysLoginService
     */
 
     /**
+     * 设置角色权限
+     *
+     * @param user 用户信息
+     */
+    public void setRolePermission(SysUser user)
+    {
+        List<SysRole> roles = user.getRoles();
+        if (!roles.isEmpty() && roles.size() > 1)
+        {
+            // 多角色设置permissions属性,以便数据权限匹配权限
+            for (SysRole role : roles)
+            {
+                Set<String> rolePerms = menuService.selectPermsByRoleId(role.getRoleId());
+                role.setPermissions(rolePerms);
+            }
+        }
+    }
+
+    /**
      * 记录登录信息
      *
      * @param userId 用户ID

+ 8 - 0
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java

@@ -50,6 +50,14 @@ public interface SysMenuMapper
     public List<String> selectPermsByUserId(Long userId);
 
     /**
+     * 根据角色ID查询权限
+     * 
+     * @param roleId 角色ID
+     * @return 权限列表
+     */
+    public List<String> selectPermsByRoleId(Long roleId);
+
+    /**
      * 根据角色ID查询菜单
      * 
      * @param roleId 角色ID

+ 8 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java

@@ -49,6 +49,14 @@ public interface ISysMenuService
     public Set<String> selectPermsByUserId(Long userId);
 
     /**
+     * 根据角色ID查询权限
+     * 
+     * @param roleId 角色ID
+     * @return 权限列表
+     */
+    public Set<String> selectPermsByRoleId(Long roleId);
+
+    /**
      * 根据角色ID查询菜单
      * 
      * @param role 角色对象

+ 5 - 12
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java

@@ -1,7 +1,6 @@
 package com.ruoyi.system.service.impl;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -71,18 +70,12 @@ public class SysDeptServiceImpl implements ISysDeptService
     public List<Ztree> selectDeptTreeExcludeChild(SysDept dept)
     {
         Long excludeId = dept.getExcludeId();
-        List<SysDept> deptList = deptMapper.selectDeptList(dept);
-        Iterator<SysDept> it = deptList.iterator();
-        while (it.hasNext())
+        List<SysDept> depts = deptMapper.selectDeptList(dept);
+        if (excludeId.intValue() > 0)
         {
-            SysDept d = (SysDept) it.next();
-            if (d.getDeptId().intValue() == excludeId
-                    || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), excludeId + ""))
-            {
-                it.remove();
-            }
+            depts.removeIf(d -> d.getDeptId().intValue() == excludeId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), excludeId + ""));
         }
-        List<Ztree> ztrees = initZtree(deptList);
+        List<Ztree> ztrees = initZtree(depts);
         return ztrees;
     }
 
@@ -97,7 +90,7 @@ public class SysDeptServiceImpl implements ISysDeptService
     {
         Long roleId = role.getRoleId();
         List<Ztree> ztrees = new ArrayList<Ztree>();
-        List<SysDept> deptList = selectDeptList(new SysDept());
+        List<SysDept> deptList = SpringUtils.getAopProxy(this).selectDeptList(new SysDept());
         if (StringUtils.isNotNull(roleId))
         {
             List<String> roleDeptList = deptMapper.selectRoleDeptTree(roleId);

+ 21 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java

@@ -122,6 +122,27 @@ public class SysMenuServiceImpl implements ISysMenuService
     }
 
     /**
+     * 根据角色ID查询权限
+     * 
+     * @param roleId 角色ID
+     * @return 权限列表
+     */
+    @Override
+    public Set<String> selectPermsByRoleId(Long roleId)
+    {
+        List<String> perms = menuMapper.selectPermsByRoleId(roleId);
+        Set<String> permsSet = new HashSet<>();
+        for (String perm : perms)
+        {
+            if (StringUtils.isNotEmpty(perm))
+            {
+                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+            }
+        }
+        return permsSet;
+    }
+
+    /**
      * 根据角色ID查询菜单
      * 
      * @param role 角色对象

+ 7 - 0
ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml

@@ -70,6 +70,13 @@
 		where m.visible = '0' and r.status = '0' and ur.user_id = #{userId}
 	</select>
 
+	<select id="selectPermsByRoleId" parameterType="Long" resultType="String">
+		select distinct m.perms
+		from sys_menu m
+			 left join sys_role_menu rm on m.menu_id = rm.menu_id
+		where m.visible = '0' and rm.role_id = #{roleId}
+	</select>
+
 	<select id="selectMenuTree" parameterType="Long" resultType="String">
 		select concat(m.menu_id, ifnull(m.perms,'')) as perms
 		from sys_menu m