ソースを参照

更新 Role 相关页面和接口

reghao 1 年間 前
コミット
09876ac3ee
20 ファイル変更228 行追加291 行削除
  1. 10 2
      web/src/main/java/cn/reghao/devops/web/account/controller/RoleController.java
  2. 2 2
      web/src/main/java/cn/reghao/devops/web/account/controller/UserController.java
  3. 6 6
      web/src/main/java/cn/reghao/devops/web/account/controller/page/MenuPageController.java
  4. 9 11
      web/src/main/java/cn/reghao/devops/web/account/controller/page/RolePageController.java
  5. 10 10
      web/src/main/java/cn/reghao/devops/web/account/controller/page/UserPageController.java
  6. 0 30
      web/src/main/java/cn/reghao/devops/web/account/db/query/RoleQuery.java
  7. 0 107
      web/src/main/java/cn/reghao/devops/web/account/db/query/RoleQueryImpl.java
  8. 0 9
      web/src/main/java/cn/reghao/devops/web/account/db/query/UserQuery.java
  9. 1 39
      web/src/main/java/cn/reghao/devops/web/account/db/query/UserQueryImpl.java
  10. 0 34
      web/src/main/java/cn/reghao/devops/web/account/model/dto/RoleDTO.java
  11. 20 0
      web/src/main/java/cn/reghao/devops/web/account/model/dto/RoleDto.java
  12. 3 3
      web/src/main/java/cn/reghao/devops/web/account/model/po/Role.java
  13. 2 2
      web/src/main/java/cn/reghao/devops/web/account/model/vo/RoleVO.java
  14. 4 5
      web/src/main/java/cn/reghao/devops/web/account/service/HomeService.java
  15. 27 1
      web/src/main/java/cn/reghao/devops/web/account/service/RoleService.java
  16. 114 8
      web/src/main/java/cn/reghao/devops/web/account/service/impl/RoleServiceImpl.java
  17. 4 4
      web/src/main/resources/templates/rbac/role/add.html
  18. 2 2
      web/src/main/resources/templates/rbac/role/detail.html
  19. 12 14
      web/src/main/resources/templates/rbac/role/index.html
  20. 2 2
      web/src/main/resources/templates/rbac/role/users.html

+ 10 - 2
web/src/main/java/cn/reghao/devops/web/account/controller/RoleController.java

@@ -1,6 +1,7 @@
 package cn.reghao.devops.web.account.controller;
 package cn.reghao.devops.web.account.controller;
 
 
 import cn.reghao.devops.web.account.db.query.MenuQuery;
 import cn.reghao.devops.web.account.db.query.MenuQuery;
+import cn.reghao.devops.web.account.model.dto.RoleDto;
 import cn.reghao.devops.web.account.model.po.Menu;
 import cn.reghao.devops.web.account.model.po.Menu;
 import cn.reghao.devops.web.account.model.po.Role;
 import cn.reghao.devops.web.account.model.po.Role;
 import cn.reghao.devops.web.account.service.RoleService;
 import cn.reghao.devops.web.account.service.RoleService;
@@ -34,8 +35,8 @@ public class RoleController {
 
 
     @ApiOperation("添加或修改角色")
     @ApiOperation("添加或修改角色")
     @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
     @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
-    public String addOrModifyRole(@Validated Role role) {
-        roleService.addOrModify(role);
+    public String addOrModifyRole(@Validated RoleDto roleDto) {
+        roleService.addOrUpdate(roleDto);
         return WebResult.success();
         return WebResult.success();
     }
     }
 
 
@@ -46,6 +47,13 @@ public class RoleController {
         return WebResult.success();
         return WebResult.success();
     }
     }
 
 
+    /**
+     * spring data jpa 会自动根据 id 参数查询 Role 实例
+     *
+     * @param
+     * @return
+     * @date 2024-07-30 16:08:42
+     */
     @ApiOperation("获取角色可访问的资源")
     @ApiOperation("获取角色可访问的资源")
     @GetMapping(value = "/menus/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
     @GetMapping(value = "/menus/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
     public String getRoleMenus(@PathVariable("id") Role role) {
     public String getRoleMenus(@PathVariable("id") Role role) {

+ 2 - 2
web/src/main/java/cn/reghao/devops/web/account/controller/AccountProfileController.java → web/src/main/java/cn/reghao/devops/web/account/controller/UserController.java

@@ -25,10 +25,10 @@ import java.util.List;
 @Api(tags = "用户接口")
 @Api(tags = "用户接口")
 @RequestMapping("/api/rbac/user")
 @RequestMapping("/api/rbac/user")
 @RestController
 @RestController
-public class AccountProfileController {
+public class UserController {
     private final AccountService accountService;
     private final AccountService accountService;
 
 
-    public AccountProfileController(AccountService accountService) {
+    public UserController(AccountService accountService) {
         this.accountService = accountService;
         this.accountService = accountService;
     }
     }
 
 

+ 6 - 6
web/src/main/java/cn/reghao/devops/web/account/controller/page/MenuPageController.java

@@ -1,10 +1,10 @@
 package cn.reghao.devops.web.account.controller.page;
 package cn.reghao.devops.web.account.controller.page;
 
 
 import cn.reghao.devops.web.account.db.query.MenuQuery;
 import cn.reghao.devops.web.account.db.query.MenuQuery;
-import cn.reghao.devops.web.account.db.query.RoleQuery;
 import cn.reghao.devops.web.account.model.dto.MenuDTO;
 import cn.reghao.devops.web.account.model.dto.MenuDTO;
 import cn.reghao.devops.web.account.model.po.Role;
 import cn.reghao.devops.web.account.model.po.Role;
 import cn.reghao.devops.web.account.model.po.Menu;
 import cn.reghao.devops.web.account.model.po.Menu;
+import cn.reghao.devops.web.account.service.RoleService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.stereotype.Controller;
 import org.springframework.stereotype.Controller;
@@ -21,11 +21,11 @@ import java.util.*;
 @RequestMapping("/rbac/menu")
 @RequestMapping("/rbac/menu")
 @Controller
 @Controller
 public class MenuPageController {
 public class MenuPageController {
-    private final RoleQuery roleQuery;
+    private final RoleService roleService;
     private final MenuQuery menuQuery;
     private final MenuQuery menuQuery;
 
 
-    public MenuPageController(RoleQuery roleQuery, MenuQuery menuQuery) {
-        this.roleQuery = roleQuery;
+    public MenuPageController(RoleService roleService, MenuQuery menuQuery) {
+        this.roleService = roleService;
         this.menuQuery = menuQuery;
         this.menuQuery = menuQuery;
     }
     }
 
 
@@ -49,7 +49,7 @@ public class MenuPageController {
             pMenu = menuQuery.findById(pid);
             pMenu = menuQuery.findById(pid);
         }
         }
 
 
-        Set<Role> allRoles = new HashSet<>(roleQuery.findAll());
+        Set<Role> allRoles = new HashSet<>(roleService.getAllRoles());
         Set<Role> menuRoles = Collections.emptySet();
         Set<Role> menuRoles = Collections.emptySet();
 
 
         model.addAttribute("allRoles", allRoles);
         model.addAttribute("allRoles", allRoles);
@@ -69,7 +69,7 @@ public class MenuPageController {
             pMenu = menuQuery.findById(pid);
             pMenu = menuQuery.findById(pid);
         }
         }
 
 
-        Set<Role> allRoles = new HashSet<>(roleQuery.findAll());
+        Set<Role> allRoles = new HashSet<>(roleService.getAllRoles());
         //Set<Role> menuRoles = menu.getRoles();
         //Set<Role> menuRoles = menu.getRoles();
         Set<Role> menuRoles = Collections.emptySet();
         Set<Role> menuRoles = Collections.emptySet();
 
 

+ 9 - 11
web/src/main/java/cn/reghao/devops/web/account/controller/page/RolePageController.java

@@ -1,13 +1,12 @@
 package cn.reghao.devops.web.account.controller.page;
 package cn.reghao.devops.web.account.controller.page;
 
 
-import cn.reghao.devops.web.account.db.query.RoleQuery;
 import cn.reghao.devops.web.account.model.po.User;
 import cn.reghao.devops.web.account.model.po.User;
 import cn.reghao.devops.web.account.model.vo.RoleVO;
 import cn.reghao.devops.web.account.model.vo.RoleVO;
+import cn.reghao.devops.web.account.service.RoleService;
 import cn.reghao.devops.web.util.db.PageSort;
 import cn.reghao.devops.web.util.db.PageSort;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageImpl;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.stereotype.Controller;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.ui.Model;
@@ -23,10 +22,10 @@ import java.util.List;
 @RequestMapping("/rbac/role")
 @RequestMapping("/rbac/role")
 @Controller
 @Controller
 public class RolePageController {
 public class RolePageController {
-    private RoleQuery roleQuery;
+    private final RoleService roleService;
 
 
-    public RolePageController(RoleQuery roleQuery) {
-        this.roleQuery = roleQuery;
+    public RolePageController(RoleService roleService) {
+        this.roleService = roleService;
     }
     }
 
 
     @ApiOperation("角色列表页面")
     @ApiOperation("角色列表页面")
@@ -34,11 +33,10 @@ public class RolePageController {
     public String rolePage(@RequestParam(value = "name", required = false) String name, Model model) {
     public String rolePage(@RequestParam(value = "name", required = false) String name, Model model) {
         Page<RoleVO> page;
         Page<RoleVO> page;
         if (name != null) {
         if (name != null) {
-            List<RoleVO> list = roleQuery.getByMatchName(name);
-            page = new PageImpl<>(list);
+            page = roleService.getByPage(null, name);
         } else {
         } else {
             PageRequest pageRequest = PageSort.pageRequest();
             PageRequest pageRequest = PageSort.pageRequest();
-            page = roleQuery.getRoleVOByPage(pageRequest);
+            page = roleService.getByPage(pageRequest, null);
         }
         }
 
 
         model.addAttribute("page", page);
         model.addAttribute("page", page);
@@ -55,7 +53,7 @@ public class RolePageController {
     @ApiOperation("角色编辑页面")
     @ApiOperation("角色编辑页面")
     @GetMapping("/edit/{id}")
     @GetMapping("/edit/{id}")
     public String editRolePage(@PathVariable("id") int id, Model model) {
     public String editRolePage(@PathVariable("id") int id, Model model) {
-        RoleVO vo = roleQuery.getRoleVOById(id);
+        RoleVO vo = roleService.getRoleVOById(id);
         model.addAttribute("role", vo);
         model.addAttribute("role", vo);
         return "/rbac/role/add";
         return "/rbac/role/add";
     }
     }
@@ -63,7 +61,7 @@ public class RolePageController {
     @ApiOperation("角色详细信息页面")
     @ApiOperation("角色详细信息页面")
     @GetMapping("/detail/{id}")
     @GetMapping("/detail/{id}")
     public String roleDetailPage(@PathVariable("id") int id, Model model) {
     public String roleDetailPage(@PathVariable("id") int id, Model model) {
-        RoleVO vo = roleQuery.getRoleVOById(id);
+        RoleVO vo = roleService.getRoleVOById(id);
         model.addAttribute("role", vo);
         model.addAttribute("role", vo);
         return "/rbac/role/detail";
         return "/rbac/role/detail";
     }
     }
@@ -78,7 +76,7 @@ public class RolePageController {
     @ApiOperation("拥有角色的所有用户页面")
     @ApiOperation("拥有角色的所有用户页面")
     @GetMapping("/users/{id}")
     @GetMapping("/users/{id}")
     public String userListWithRole(@PathVariable("id") Integer roleId, Model model) {
     public String userListWithRole(@PathVariable("id") Integer roleId, Model model) {
-        List<User> list = roleQuery.getUsersByRoleId(roleId);
+        List<User> list = roleService.getRoleUsers(roleId);
         model.addAttribute("list", list);
         model.addAttribute("list", list);
         return "/rbac/role/users";
         return "/rbac/role/users";
     }
     }

+ 10 - 10
web/src/main/java/cn/reghao/devops/web/account/controller/page/UserPageController.java

@@ -1,11 +1,11 @@
 package cn.reghao.devops.web.account.controller.page;
 package cn.reghao.devops.web.account.controller.page;
 
 
-import cn.reghao.devops.web.account.db.query.RoleQuery;
 import cn.reghao.devops.web.account.db.query.UserQuery;
 import cn.reghao.devops.web.account.db.query.UserQuery;
 import cn.reghao.devops.web.account.model.po.Role;
 import cn.reghao.devops.web.account.model.po.Role;
 import cn.reghao.devops.web.account.model.po.User;
 import cn.reghao.devops.web.account.model.po.User;
 import cn.reghao.devops.web.account.model.vo.UserVO;
 import cn.reghao.devops.web.account.model.vo.UserVO;
 import cn.reghao.devops.web.account.service.AccountSessionService;
 import cn.reghao.devops.web.account.service.AccountSessionService;
+import cn.reghao.devops.web.account.service.RoleService;
 import cn.reghao.devops.web.account.service.UserContext;
 import cn.reghao.devops.web.account.service.UserContext;
 import cn.reghao.devops.web.util.db.PageSort;
 import cn.reghao.devops.web.util.db.PageSort;
 import cn.reghao.jutil.jdk.converter.DateTimeConverter;
 import cn.reghao.jutil.jdk.converter.DateTimeConverter;
@@ -31,12 +31,12 @@ import java.util.stream.Collectors;
 @Controller
 @Controller
 public class UserPageController {
 public class UserPageController {
     private final UserQuery userQuery;
     private final UserQuery userQuery;
-    private final RoleQuery roleQuery;
+    private final RoleService roleService;
     private final AccountSessionService accountSessionService;
     private final AccountSessionService accountSessionService;
 
 
-    public UserPageController(UserQuery userQuery, RoleQuery roleQuery, AccountSessionService accountSessionService) {
+    public UserPageController(UserQuery userQuery, RoleService roleService, AccountSessionService accountSessionService) {
         this.userQuery = userQuery;
         this.userQuery = userQuery;
-        this.roleQuery = roleQuery;
+        this.roleService = roleService;
         this.accountSessionService = accountSessionService;
         this.accountSessionService = accountSessionService;
     }
     }
 
 
@@ -69,7 +69,7 @@ public class UserPageController {
     @ApiOperation(value = "新增用户页面")
     @ApiOperation(value = "新增用户页面")
     @GetMapping("/add")
     @GetMapping("/add")
     public String addUserPage(Model model) {
     public String addUserPage(Model model) {
-        Set<Role> allRoles = new HashSet<>(new HashSet<>(roleQuery.findAll()));
+        Set<Role> allRoles = new HashSet<>(roleService.getAllRoles());
         Set<Role> userRoles = Collections.emptySet();
         Set<Role> userRoles = Collections.emptySet();
 
 
         model.addAttribute("allRoles", allRoles);
         model.addAttribute("allRoles", allRoles);
@@ -81,8 +81,8 @@ public class UserPageController {
     @GetMapping("/edit/{id}")
     @GetMapping("/edit/{id}")
     @Deprecated
     @Deprecated
     public String editUserPage(@PathVariable("id") User user, Model model) {
     public String editUserPage(@PathVariable("id") User user, Model model) {
-        Set<Role> allRoles = new HashSet<>(roleQuery.findAll());
-        Set<Role> userRoles = userQuery.getUserRoles(user);
+        Set<Role> allRoles = new HashSet<>(roleService.getAllRoles());
+        Set<Role> userRoles = roleService.getUserRoles(user.getId());
 
 
         model.addAttribute("allRoles", allRoles);
         model.addAttribute("allRoles", allRoles);
         model.addAttribute("userRoles", userRoles);
         model.addAttribute("userRoles", userRoles);
@@ -94,7 +94,7 @@ public class UserPageController {
     @GetMapping("/detail/{id}")
     @GetMapping("/detail/{id}")
     public String userDetailPage(@PathVariable("id") int id, Model model) {
     public String userDetailPage(@PathVariable("id") int id, Model model) {
         User user = userQuery.findById(id);
         User user = userQuery.findById(id);
-        Set<Role> roles = userQuery.getUserRoles(user);
+        Set<Role> roles = roleService.getUserRoles(user.getId());
         List<String> names = roles.stream().map(Role::getName).collect(Collectors.toList());
         List<String> names = roles.stream().map(Role::getName).collect(Collectors.toList());
 
 
         model.addAttribute("roles", names.toString());
         model.addAttribute("roles", names.toString());
@@ -124,9 +124,9 @@ public class UserPageController {
     @ApiOperation(value = "用户角色分配页面")
     @ApiOperation(value = "用户角色分配页面")
     @GetMapping("/role/{id}")
     @GetMapping("/role/{id}")
     public String assignRolePage(@PathVariable("id") User user, Model model) {
     public String assignRolePage(@PathVariable("id") User user, Model model) {
-        Set<Role> roles = new HashSet<>(roleQuery.findAll());
+        Set<Role> roles = new HashSet<>(roleService.getAllRoles());
         int userId = user.getId();
         int userId = user.getId();
-        Set<Role> authRoles = userQuery.getUserRoles(userId);
+        Set<Role> authRoles = roleService.getUserRoles(userId);
 
 
         model.addAttribute("id", userId);
         model.addAttribute("id", userId);
         model.addAttribute("list", roles);
         model.addAttribute("list", roles);

+ 0 - 30
web/src/main/java/cn/reghao/devops/web/account/db/query/RoleQuery.java

@@ -1,30 +0,0 @@
-package cn.reghao.devops.web.account.db.query;
-
-import cn.reghao.devops.web.account.model.po.Role;
-import cn.reghao.devops.web.account.model.po.User;
-import cn.reghao.devops.web.account.model.vo.RoleVO;
-import cn.reghao.jutil.jdk.db.BaseQuery;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-
-import java.util.List;
-
-/**
- * @author reghao
- * @date 2021-07-12 15:32:26
- */
-public interface RoleQuery extends BaseQuery<Role> {
-    Role findByName(String name);
-    Page<RoleVO> getRoleVOByPage(PageRequest pageRequest);
-    List<RoleVO> getByMatchName(String name);
-    RoleVO getRoleVOById(Integer id);
-    /**
-     * 获取拥有角色的用户
-     *
-     * @param
-     * @return
-     * @date 2021-07-14 下午2:57
-     */
-    List<User> getUsersByRoleId(Integer id);
-    List<User> getUsersByRole(Role role);
-}

+ 0 - 107
web/src/main/java/cn/reghao/devops/web/account/db/query/RoleQueryImpl.java

@@ -1,107 +0,0 @@
-package cn.reghao.devops.web.account.db.query;
-
-import cn.reghao.devops.web.account.db.repository.RoleRepository;
-import cn.reghao.devops.web.account.db.repository.UserRepository;
-import cn.reghao.devops.web.account.model.po.Role;
-import cn.reghao.devops.web.account.model.po.User;
-import cn.reghao.devops.web.account.model.vo.RoleVO;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.jpa.domain.Specification;
-import org.springframework.stereotype.Service;
-
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.SetJoin;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * @author reghao
- * @date 2021-07-12 15:32:26
- */
-@Service
-public class RoleQueryImpl implements RoleQuery {
-    private final RoleRepository roleRepository;
-    private final UserRepository userRepository;
-
-    public RoleQueryImpl(RoleRepository roleRepository, UserRepository userRepository) {
-        this.roleRepository = roleRepository;
-        this.userRepository = userRepository;
-    }
-
-    @Override
-    public List<Role> findAll() {
-        return roleRepository.findAll();
-    }
-
-    @Override
-    public Role findById(int id) {
-        return roleRepository.findById(id).orElse(null);
-    }
-
-    @Override
-    public Role findByName(String name) {
-        return roleRepository.findByName(name);
-    }
-
-    @Override
-    public Page<RoleVO> getRoleVOByPage(PageRequest pageRequest) {
-        return roleRepository.findAll(pageRequest).map(RoleVO::new);
-    }
-
-    @Override
-    public List<RoleVO> getByMatchName(String name) {
-        Specification<Role> specification = (root, query, cb) -> {
-            String likeQuery = String.format("%%%s%%", name);
-            Predicate predicate = cb.like(root.get("name"), likeQuery);
-            return cb.and(predicate);
-        };
-        return roleRepository.findAll(specification).stream().map(RoleVO::new).collect(Collectors.toList());
-    }
-
-    @Override
-    public RoleVO getRoleVOById(Integer id) {
-        Role role = findById(id);
-        return role != null ? new RoleVO(role) : null;
-    }
-
-    /**
-     * 获取拥有角色的用户
-     *
-     * @param
-     * @return
-     * @date 2021-07-14 下午2:57
-     */
-    @Override
-    public List<User> getUsersByRoleId(Integer id) {
-        Role role = findById(id);
-        return getUsersByRole(role);
-    }
-
-    /**
-     * SQL 语句
-     * select u.*
-     * from role r
-     * inner join user_role ur
-     * inner join `user` u
-     * on r.title=ur.role and ur.user_id=u.id and r.title='ROLE_FRONTEND'
-     *
-     * @param
-     * @return
-     * @date 2023-03-02 17:54:48
-     */
-    @Override
-    public List<User> getUsersByRole(Role role) {
-        String name = role.getName();
-        Specification<User> specification = ((root, query, cb) -> {
-            SetJoin<User, String> setJoin = root.joinSet("role");
-            // User 中 Set 的元素是原始类型
-            Predicate predicate = setJoin.as(String.class).in(name);
-            // User 中的 Set 的元素是某个对象, fieldName 表示对象的某个字段名
-            //Predicate predicate = cb.equal(setJoin.get("fieldName"), title);
-            return cb.and(predicate);
-        });
-
-        return userRepository.findAll(specification);
-    }
-}

+ 0 - 9
web/src/main/java/cn/reghao/devops/web/account/db/query/UserQuery.java

@@ -16,13 +16,4 @@ import java.util.*;
 public interface UserQuery extends BaseQuery<User> {
 public interface UserQuery extends BaseQuery<User> {
     Page<UserVO> getUserVOByPage(PageRequest pageRequest);
     Page<UserVO> getUserVOByPage(PageRequest pageRequest);
     List<UserVO> getByMatchScreenName(String screenName);
     List<UserVO> getByMatchScreenName(String screenName);
-    /**
-     * 获取用户拥有的角色
-     *
-     * @param
-     * @return
-     * @date 2021-09-10 下午11:12
-     */
-    Set<Role> getUserRoles(User user);
-    Set<Role> getUserRoles(Integer userId);
 }
 }

+ 1 - 39
web/src/main/java/cn/reghao/devops/web/account/db/query/UserQueryImpl.java

@@ -1,10 +1,7 @@
 package cn.reghao.devops.web.account.db.query;
 package cn.reghao.devops.web.account.db.query;
 
 
-import cn.reghao.devops.web.account.db.repository.RoleRepository;
 import cn.reghao.devops.web.account.db.repository.UserRepository;
 import cn.reghao.devops.web.account.db.repository.UserRepository;
-import cn.reghao.devops.web.account.model.po.Role;
 import cn.reghao.devops.web.account.model.po.User;
 import cn.reghao.devops.web.account.model.po.User;
-import cn.reghao.devops.web.account.model.po.UserAuthority;
 import cn.reghao.devops.web.account.model.vo.UserVO;
 import cn.reghao.devops.web.account.model.vo.UserVO;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.PageRequest;
@@ -12,10 +9,7 @@ import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Predicate;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.List;
-import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 /**
 /**
@@ -25,11 +19,9 @@ import java.util.stream.Collectors;
 @Service
 @Service
 public class UserQueryImpl implements UserQuery {
 public class UserQueryImpl implements UserQuery {
     private final UserRepository userRepository;
     private final UserRepository userRepository;
-    private final RoleRepository roleRepository;
 
 
-    public UserQueryImpl(UserRepository userRepository, RoleRepository roleRepository) {
+    public UserQueryImpl(UserRepository userRepository) {
         this.userRepository = userRepository;
         this.userRepository = userRepository;
-        this.roleRepository = roleRepository;
     }
     }
 
 
     @Override
     @Override
@@ -51,34 +43,4 @@ public class UserQueryImpl implements UserQuery {
         };
         };
         return userRepository.findAll(specification).stream().map(UserVO::new).collect(Collectors.toList());
         return userRepository.findAll(specification).stream().map(UserVO::new).collect(Collectors.toList());
     }
     }
-
-    /**
-     * 获取用户拥有的角色
-     *
-     * @param
-     * @return
-     * @date 2021-09-10 下午11:12
-     */
-    @Override
-    public Set<Role> getUserRoles(User user) {
-        Set<UserAuthority> set = user.getAuthorities().stream()
-                .map(grantedAuthority -> new UserAuthority(grantedAuthority.getAuthority()))
-                .collect(Collectors.toSet());
-
-        List<String> roles = set.stream()
-                .map(UserAuthority::getAuthority)
-                .collect(Collectors.toList());
-        Specification<Role> spec = ((root, query, criteriaBuilder) -> root.get("name").in(roles));
-        return new HashSet<>(roleRepository.findAll(spec));
-    }
-
-    @Override
-    public Set<Role> getUserRoles(Integer userId) {
-        User user = findById(userId);
-        if (user == null) {
-            return Collections.emptySet();
-        }
-
-        return getUserRoles(user);
-    }
 }
 }

+ 0 - 34
web/src/main/java/cn/reghao/devops/web/account/model/dto/RoleDTO.java

@@ -1,34 +0,0 @@
-package cn.reghao.devops.web.account.model.dto;
-
-import cn.reghao.devops.web.account.model.po.Role;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.hibernate.validator.constraints.Length;
-
-import javax.validation.constraints.Pattern;
-
-/**
- * @author reghao
- * @date 2021-07-14 14:14:07
- */
-@NoArgsConstructor
-@Data
-public class RoleDTO {
-    private Integer roleId;
-    @Pattern(regexp = "^\\w+$", message = "角色只能是数字、英文字符和下划线")
-    private String name;
-    @Length(max = 100, message = "描述的长度不超过 100 个中文字符")
-    private String description;
-    private String createTime;
-
-    public Role to() {
-        Role role = new Role();
-        if (this.getRoleId() != null) {
-            role.setId(this.getRoleId());
-        }
-
-        role.setName("ROLE_" + this.getName());
-        role.setDescription(this.getDescription());
-        return role;
-    }
-}

+ 20 - 0
web/src/main/java/cn/reghao/devops/web/account/model/dto/RoleDto.java

@@ -0,0 +1,20 @@
+package cn.reghao.devops.web.account.model.dto;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.Pattern;
+
+/**
+ * @author reghao
+ * @date 2021-07-14 14:14:07
+ */
+@NoArgsConstructor
+@Data
+public class RoleDto {
+    @Pattern(regexp = "^\\w+$", message = "角色名只能是英文字符")
+    private String name;
+    @Length(max = 100, message = "角色描述的长度不超过 100 个中文字符")
+    private String description;
+}

+ 3 - 3
web/src/main/java/cn/reghao/devops/web/account/model/po/Role.java

@@ -23,11 +23,11 @@ import java.util.Set;
 @Entity
 @Entity
 public class Role extends BaseEntity {
 public class Role extends BaseEntity {
     // TODO 匹配小写英文字符报错
     // TODO 匹配小写英文字符报错
-    // @Pattern(regexp = "^[a-z]+$", message = "角色只能是英文字符")
-    @Pattern(regexp = "^\\w+$", message = "角色只能是英文字符")
+    // @Pattern(regexp = "^[a-z]+$", message = "角色只能是英文字符")
+    @Pattern(regexp = "^\\w+$", message = "角色只能是英文字符")
     @Column(unique = true, nullable = false)
     @Column(unique = true, nullable = false)
     private String name;
     private String name;
-    @Length(max = 100, message = "角色描述的长度不超过 100 个中文字符")
+    @Length(max = 100, message = "角色描述的长度不超过 100 个中文字符")
     private String description;
     private String description;
     // Role 端维护 Role 和 Menu 之间的关系
     // Role 端维护 Role 和 Menu 之间的关系
     @ManyToMany
     @ManyToMany

+ 2 - 2
web/src/main/java/cn/reghao/devops/web/account/model/vo/RoleVO.java

@@ -12,14 +12,14 @@ import java.util.Locale;
  */
  */
 @Data
 @Data
 public class RoleVO {
 public class RoleVO {
-    private Integer roleId;
+    private Integer id;
     private String name;
     private String name;
     private String description;
     private String description;
     private String createTime;
     private String createTime;
     private String updateTime;
     private String updateTime;
 
 
     public RoleVO(Role role) {
     public RoleVO(Role role) {
-        this.roleId = role.getId();
+        this.id = role.getId();
         this.name = role.getName().split("ROLE_")[1].toLowerCase(Locale.ROOT);
         this.name = role.getName().split("ROLE_")[1].toLowerCase(Locale.ROOT);
         this.description = role.getDescription();
         this.description = role.getDescription();
         this.createTime = DateTimeConverter.format(role.getCreateTime());
         this.createTime = DateTimeConverter.format(role.getCreateTime());

+ 4 - 5
web/src/main/java/cn/reghao/devops/web/account/service/HomeService.java

@@ -1,6 +1,5 @@
 package cn.reghao.devops.web.account.service;
 package cn.reghao.devops.web.account.service;
 
 
-import cn.reghao.devops.web.account.db.query.RoleQuery;
 import cn.reghao.devops.web.account.model.po.Menu;
 import cn.reghao.devops.web.account.model.po.Menu;
 import cn.reghao.devops.web.account.model.po.Role;
 import cn.reghao.devops.web.account.model.po.Role;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
@@ -14,10 +13,10 @@ import java.util.stream.Collectors;
  */
  */
 @Service
 @Service
 public class HomeService {
 public class HomeService {
-    private final RoleQuery roleQuery;
+    private final RoleService roleService;
 
 
-    public HomeService(RoleQuery roleQuery) {
-        this.roleQuery = roleQuery;
+    public HomeService(RoleService roleService) {
+        this.roleService = roleService;
     }
     }
 
 
     /**
     /**
@@ -30,7 +29,7 @@ public class HomeService {
     public List<Menu> userMenus(Set<String> roles) {
     public List<Menu> userMenus(Set<String> roles) {
         List<Menu> menus = new ArrayList<>();
         List<Menu> menus = new ArrayList<>();
         roles.forEach(name -> {
         roles.forEach(name -> {
-            Role role = roleQuery.findByName(name);
+            Role role = roleService.getByName(name);
             menus.addAll(role.getMenus().stream().filter(Menu::getEnabled).collect(Collectors.toSet()));
             menus.addAll(role.getMenus().stream().filter(Menu::getEnabled).collect(Collectors.toSet()));
         });
         });
 
 

+ 27 - 1
web/src/main/java/cn/reghao/devops/web/account/service/RoleService.java

@@ -1,8 +1,14 @@
 package cn.reghao.devops.web.account.service;
 package cn.reghao.devops.web.account.service;
 
 
+import cn.reghao.devops.web.account.model.dto.RoleDto;
 import cn.reghao.devops.web.account.model.po.Menu;
 import cn.reghao.devops.web.account.model.po.Menu;
 import cn.reghao.devops.web.account.model.po.Role;
 import cn.reghao.devops.web.account.model.po.Role;
+import cn.reghao.devops.web.account.model.po.User;
+import cn.reghao.devops.web.account.model.vo.RoleVO;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
 
 
+import java.util.List;
 import java.util.Set;
 import java.util.Set;
 
 
 /**
 /**
@@ -11,7 +17,27 @@ import java.util.Set;
  */
  */
 public interface RoleService {
 public interface RoleService {
     void initRole();
     void initRole();
-    void addOrModify(Role role);
+    void addOrUpdate(RoleDto roleDto);
     void delete(Integer roleId);
     void delete(Integer roleId);
     void setRoleMenus(Integer roleId, Set<Menu> menus);
     void setRoleMenus(Integer roleId, Set<Menu> menus);
+    Role getByName(String name);
+    Page<RoleVO> getByPage(PageRequest pageRequest, String name);
+    RoleVO getRoleVOById(Integer roleId);
+    List<Role> getAllRoles();
+    /**
+     * 获取拥有角色的用户
+     *
+     * @param
+     * @return
+     * @date 2021-07-14 下午2:57
+     */
+    List<User> getRoleUsers(Integer roleId);
+    /**
+     * 获取用户拥有的角色
+     *
+     * @param
+     * @return
+     * @date 2021-09-10 下午11:12
+     */
+    Set<Role> getUserRoles(Integer userId);
 }
 }

+ 114 - 8
web/src/main/java/cn/reghao/devops/web/account/service/impl/RoleServiceImpl.java

@@ -1,17 +1,27 @@
 package cn.reghao.devops.web.account.service.impl;
 package cn.reghao.devops.web.account.service.impl;
 
 
-import cn.reghao.devops.web.account.db.query.RoleQuery;
 import cn.reghao.devops.web.account.db.repository.MenuRepository;
 import cn.reghao.devops.web.account.db.repository.MenuRepository;
 import cn.reghao.devops.web.account.db.repository.RoleRepository;
 import cn.reghao.devops.web.account.db.repository.RoleRepository;
+import cn.reghao.devops.web.account.db.repository.UserRepository;
 import cn.reghao.devops.web.account.model.constant.RoleType;
 import cn.reghao.devops.web.account.model.constant.RoleType;
+import cn.reghao.devops.web.account.model.dto.RoleDto;
 import cn.reghao.devops.web.account.model.po.Menu;
 import cn.reghao.devops.web.account.model.po.Menu;
 import cn.reghao.devops.web.account.model.po.Role;
 import cn.reghao.devops.web.account.model.po.Role;
 import cn.reghao.devops.web.account.model.po.User;
 import cn.reghao.devops.web.account.model.po.User;
+import cn.reghao.devops.web.account.model.po.UserAuthority;
+import cn.reghao.devops.web.account.model.vo.RoleVO;
 import cn.reghao.devops.web.account.service.RoleService;
 import cn.reghao.devops.web.account.service.RoleService;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.SetJoin;
 import java.util.*;
 import java.util.*;
+import java.util.stream.Collectors;
 
 
 /**
 /**
  * @author reghao
  * @author reghao
@@ -20,14 +30,14 @@ import java.util.*;
 @Slf4j
 @Slf4j
 @Service
 @Service
 public class RoleServiceImpl implements RoleService {
 public class RoleServiceImpl implements RoleService {
-    private final RoleQuery roleQuery;
     private final RoleRepository roleRepository;
     private final RoleRepository roleRepository;
     private final MenuRepository menuRepository;
     private final MenuRepository menuRepository;
+    private final UserRepository userRepository;
 
 
-    public RoleServiceImpl(RoleQuery roleQuery, RoleRepository roleRepository, MenuRepository menuRepository) {
-        this.roleQuery = roleQuery;
+    public RoleServiceImpl(RoleRepository roleRepository, MenuRepository menuRepository, UserRepository userRepository) {
         this.roleRepository = roleRepository;
         this.roleRepository = roleRepository;
         this.menuRepository = menuRepository;
         this.menuRepository = menuRepository;
+        this.userRepository = userRepository;
     }
     }
 
 
     public void initRole() {
     public void initRole() {
@@ -49,16 +59,22 @@ public class RoleServiceImpl implements RoleService {
     }
     }
 
 
     @Override
     @Override
-    public void addOrModify(Role role) {
-        String title = String.format("ROLE_%s", role.getName());
-        role.setName(title.toUpperCase(Locale.ROOT));
+    public void addOrUpdate(RoleDto roleDto) {
+        String name = String.format("ROLE_%s", roleDto.getName().toUpperCase(Locale.ROOT));
+        Role role = roleRepository.findByName(name);
+        if (role != null) {
+            role.setDescription(roleDto.getDescription());
+        } else {
+            role = new Role(name, roleDto.getDescription());
+        }
+
         roleRepository.save(role);
         roleRepository.save(role);
     }
     }
 
 
     @Override
     @Override
     public void delete(Integer roleId) {
     public void delete(Integer roleId) {
         Role role = roleRepository.getOne(roleId);
         Role role = roleRepository.getOne(roleId);
-        List<User> users = roleQuery.getUsersByRole(role);
+        List<User> users = getRoleUsers(roleId);
         if (!users.isEmpty()) {
         if (!users.isEmpty()) {
             log.error("还有用户分配有本角色");
             log.error("还有用户分配有本角色");
             return;
             return;
@@ -74,4 +90,94 @@ public class RoleServiceImpl implements RoleService {
         role.setMenus(menus);
         role.setMenus(menus);
         roleRepository.save(role);
         roleRepository.save(role);
     }
     }
+
+    @Override
+    public Role getByName(String name) {
+        return roleRepository.findByName(name);
+    }
+
+    @Override
+    public Page<RoleVO> getByPage(PageRequest pageRequest, String name) {
+        Page<Role> rolePage;
+        if (name != null) {
+            Specification<Role> specification = (root, query, cb) -> {
+                String likeQuery = String.format("%%%s%%", name);
+                Predicate predicate = cb.like(root.get("name"), likeQuery);
+                return cb.and(predicate);
+            };
+
+            pageRequest = PageRequest.of(0, 100);
+            rolePage = roleRepository.findAll(specification, pageRequest);
+        } else {
+            rolePage = roleRepository.findAll(pageRequest);
+        }
+
+        List<RoleVO> list = rolePage.getContent().stream().map(RoleVO::new).collect(Collectors.toList());
+        return new PageImpl<>(list, pageRequest, rolePage.getTotalElements());
+    }
+
+    @Override
+    public RoleVO getRoleVOById(Integer roleId) {
+        Role role = roleRepository.findById(roleId).orElse(null);
+        return role != null ? new RoleVO(role) : null;
+    }
+
+    @Override
+    public List<Role> getAllRoles() {
+        PageRequest pageRequest = PageRequest.of(0, 20);
+        Page<Role> page = roleRepository.findAll(pageRequest);
+        return page.getContent();
+    }
+
+    /**
+     * 获取拥有角色的用户
+     * SQL 语句
+     * select u.*
+     * from role r
+     * inner join user_role ur
+     * inner join `user` u
+     * on r.title=ur.role and ur.user_id=u.id and r.title='ROLE_FRONTEND'
+     *
+     * @param
+     * @return
+     * @date 2023-03-02 17:54:48
+     */
+    public List<User> getRoleUsers(Integer roleId) {
+        Role role = roleRepository.findById(roleId).orElse(null);
+        if (role == null) {
+            return Collections.emptyList();
+        }
+
+        String name = role.getName();
+        Specification<User> specification = ((root, query, cb) -> {
+            SetJoin<User, String> setJoin = root.joinSet("role");
+            // User 中 Set 的元素是原始类型
+            Predicate predicate = setJoin.as(String.class).in(name);
+            // User 中的 Set 的元素是某个对象, fieldName 表示对象的某个字段名
+            //Predicate predicate = cb.equal(setJoin.get("fieldName"), title);
+            return cb.and(predicate);
+        });
+
+        PageRequest pageRequest = PageRequest.of(0, 100);
+        Page<User> page = userRepository.findAll(specification, pageRequest);
+        return page.getContent();
+    }
+
+    @Override
+    public Set<Role> getUserRoles(Integer userId) {
+        User user = userRepository.findById(userId).orElse(null);
+        if (user == null) {
+            return Collections.emptySet();
+        }
+
+        Set<UserAuthority> set = user.getAuthorities().stream()
+                .map(grantedAuthority -> new UserAuthority(grantedAuthority.getAuthority()))
+                .collect(Collectors.toSet());
+
+        List<String> roles = set.stream()
+                .map(UserAuthority::getAuthority)
+                .collect(Collectors.toList());
+        Specification<Role> spec = ((root, query, criteriaBuilder) -> root.get("name").in(roles));
+        return new HashSet<>(roleRepository.findAll(spec));
+    }
 }
 }

+ 4 - 4
web/src/main/resources/templates/rbac/role/add.html

@@ -5,22 +5,22 @@
 <body>
 <body>
 <div class="layui-form timo-compile">
 <div class="layui-form timo-compile">
     <form th:action="@{/api/rbac/role}">
     <form th:action="@{/api/rbac/role}">
-        <input type="hidden" name="id" th:if="${role}" th:value="${role?.roleId}"/>
+        <input type="hidden" name="id" th:if="${role}" th:value="${role?.id}"/>
         <div class="layui-form-item">
         <div class="layui-form-item">
-            <label class="layui-form-label required">角色</label>
+            <label class="layui-form-label required">角色</label>
             <div class="layui-input-inline">
             <div class="layui-input-inline">
                 <span th:if="${role} != null">
                 <span th:if="${role} != null">
                     <input class="layui-input" type="text" name="name" readonly th:value="${role?.name}">
                     <input class="layui-input" type="text" name="name" readonly th:value="${role?.name}">
                 </span>
                 </span>
                 <span th:if="${role} == null">
                 <span th:if="${role} == null">
-                    <input class="layui-input" type="text" name="name"  placeholder="请输入角色(只能是小写英文字符)" th:value="${role?.name}">
+                    <input class="layui-input" type="text" name="name"  placeholder="请输入角色(只能是小写英文字符)" th:value="${role?.name}">
                 </span>
                 </span>
             </div>
             </div>
         </div>
         </div>
         <div class="layui-form-item layui-form-text">
         <div class="layui-form-item layui-form-text">
             <label class="layui-form-label required">描述</label>
             <label class="layui-form-label required">描述</label>
             <div class="layui-input-block">
             <div class="layui-input-block">
-                <textarea placeholder="请输入内容" class="layui-textarea" name="description">[[${role?.description}]]</textarea>
+                <textarea placeholder="请输入角色描述" class="layui-textarea" name="description">[[${role?.description}]]</textarea>
             </div>
             </div>
         </div>
         </div>
         <div class="layui-form-item timo-finally">
         <div class="layui-form-item timo-finally">

+ 2 - 2
web/src/main/resources/templates/rbac/role/detail.html

@@ -9,8 +9,8 @@
             <tbody>
             <tbody>
             <tr>
             <tr>
                 <th width='100px'>角色 ID</th>
                 <th width='100px'>角色 ID</th>
-                <td th:text="${role.roleId}"></td>
-                <th width='100px'>角色</th>
+                <td th:text="${role.id}"></td>
+                <th width='100px'>角色</th>
                 <td>[[${role.name}]]</td>
                 <td>[[${role.name}]]</td>
             </tr>
             </tr>
             <tr>
             <tr>

+ 12 - 14
web/src/main/resources/templates/rbac/role/index.html

@@ -5,7 +5,7 @@
 <body class="timo-layout-page">
 <body class="timo-layout-page">
 <div class="layui-card">
 <div class="layui-card">
     <div class="layui-card-header timo-card-header">
     <div class="layui-card-header timo-card-header">
-        <span><i class="fa fa-bars"></i> 角色管理</span>
+        <span><i class="fa fa-bars"></i> 角色列表</span>
         <i class="layui-icon layui-icon-refresh refresh-btn"></i>
         <i class="layui-icon layui-icon-refresh refresh-btn"></i>
     </div>
     </div>
     <div class="layui-card-body">
     <div class="layui-card-body">
@@ -35,8 +35,8 @@
             <table class="layui-table timo-table">
             <table class="layui-table timo-table">
                 <thead>
                 <thead>
                 <tr>
                 <tr>
-                    <th data-field="name">角色</th>
-                    <th data-field="description">描述</th>
+                    <th data-field="name">角色</th>
+                    <th data-field="description">角色描述</th>
                     <th data-field="createTime">创建时间</th>
                     <th data-field="createTime">创建时间</th>
                     <th>拥有角色的用户</th>
                     <th>拥有角色的用户</th>
                     <th>授权资源</th>
                     <th>授权资源</th>
@@ -49,22 +49,20 @@
                     <td th:text="${item.description}">描述</td>
                     <td th:text="${item.description}">描述</td>
                     <td th:text="${item.createTime}">创建时间</td>
                     <td th:text="${item.createTime}">创建时间</td>
                     <td>
                     <td>
-                        <a class="open-popup" data-title="拥有角色的用户"
-                           th:attr="data-url=@{'/rbac/role/users/'+${item.roleId}}" data-size="800,600"
-                           href="#">查看</a>
+                        <a class="open-popup" th:attr="data-title=@{'拥有 ' + ${item.name} + ' 角色的用户'},
+                        data-url=@{'/rbac/role/users/'+${item.id}}" data-size="640,480" href="#">查看</a>
                     </td>
                     </td>
                     <td>
                     <td>
-                        <a class="open-popup" data-title="资源授权"
-                           th:attr="data-url=@{'/rbac/role/menus/'+${item.roleId}}" data-size="800,600"
-                           href="#">设置</a>
+                        <a class="open-popup" th:attr="data-title=@{'授予 ' + ${item.name} + ' 角色资源'},
+                        data-url=@{'/rbac/role/menus/'+${item.id}}" data-size="720,540" href="#">设置</a>
                     </td>
                     </td>
                     <td>
                     <td>
-                        <a class="open-popup" data-title="编辑角色" th:attr="data-url=@{'/rbac/role/edit/'+${item.roleId}}"
-                           data-size="460,357" href="#">编辑</a>
-                        <a class="open-popup" data-title="详细信息" th:attr="data-url=@{'/rbac/role/detail/'+${item.roleId}}"
-                           data-size="800,600" href="#">详细</a>
+                        <a class="open-popup" data-title="修改角色描述" th:attr="data-url=@{'/rbac/role/edit/'+${item.id}}"
+                           data-size="480,320" href="#">编辑</a>
+                        <a class="open-popup" data-title="详细信息" th:attr="data-url=@{'/rbac/role/detail/'+${item.id}}"
+                           data-size="640,480" href="#">详细</a>
                         <a class="ajax-delete" th:attr="data-msg='确定要删除 '+ ${item.name} + '?'"
                         <a class="ajax-delete" th:attr="data-msg='确定要删除 '+ ${item.name} + '?'"
-                           th:href="@{'/api/rbac/role/' + ${item.roleId}}">删除</a>
+                           th:href="@{'/api/rbac/role/' + ${item.id}}">删除</a>
                     </td>
                     </td>
                 </tr>
                 </tr>
                 </tbody>
                 </tbody>

+ 2 - 2
web/src/main/resources/templates/rbac/role/users.html

@@ -16,14 +16,14 @@
         <table class="layui-table">
         <table class="layui-table">
             <thead>
             <thead>
             <tr>
             <tr>
+                <th>登录名</th>
                 <th>用户名</th>
                 <th>用户名</th>
-                <th>操作</th>
             </tr>
             </tr>
             </thead>
             </thead>
             <tbody>
             <tbody>
             <tr th:each="item:${list}">
             <tr th:each="item:${list}">
+                <td>[[${item.username}]]</td>
                 <td>[[${item.screenName}]]</td>
                 <td>[[${item.screenName}]]</td>
-                <td><a th:href="@{'/rbac/user/detail/'+${item.id}}">查看</a></td>
             </tr>
             </tr>
             <tr th:if="${list.isEmpty()}">
             <tr th:if="${list.isEmpty()}">
                 <td style="text-align: center" colspan="3">未有分配该角色的用户</td>
                 <td style="text-align: center" colspan="3">未有分配该角色的用户</td>