Explorar o código

新增 部门
新增 构造用户菜单树、角色信息
修改 updater、creator 更改为 update_by 、create_by

18339543638 %!s(int64=2) %!d(string=hai) anos
pai
achega
e134ee8b2f
Modificáronse 37 ficheiros con 990 adicións e 63 borrados
  1. 2 2
      tr-framework/src/main/java/cn/tr/core/constant/MybatisConstant.java
  2. 3 3
      tr-framework/src/main/java/cn/tr/core/utils/TreeUtil.java
  3. 25 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/mapper/user/SysDeptMapper.java
  4. 3 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/mapper/user/SysMenuMapper.java
  5. 27 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/mapper/user/SysUserRoleMapper.java
  6. 20 9
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/oauth2/controller/CurrentUserController.java
  7. 1 1
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/oauth2/controller/OAuth2ServerController.java
  8. 16 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/constant/MenuConstants.java
  9. 86 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/controller/SysDeptController.java
  10. 52 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysDeptDTO.java
  11. 26 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysDeptQueryDTO.java
  12. 4 1
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysMenuDTO.java
  13. 16 16
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysUserDTO.java
  14. 18 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysUserRoleDTO.java
  15. 23 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/enums/MenuEnum.java
  16. 47 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/po/SysDeptPO.java
  17. 1 1
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/po/SysMenuPO.java
  18. 25 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/po/SysUserRolePO.java
  19. 18 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/repository/SysDeptRepository.java
  20. 10 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/repository/SysRoleRepository.java
  21. 18 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/repository/SysUserRoleRepository.java
  22. 74 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/ISysDeptService.java
  23. 1 4
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/ISysMenuService.java
  24. 7 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/ISysRoleMenuService.java
  25. 43 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/ISysRoleService.java
  26. 30 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/ISysUserRoleService.java
  27. 82 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/impl/SysDeptServiceImpl.java
  28. 25 4
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/impl/SysMenuServiceImpl.java
  29. 14 2
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/impl/SysRoleMenuServiceImpl.java
  30. 103 9
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/impl/SysRoleServiceImpl.java
  31. 55 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/impl/SysUserRoleServiceImpl.java
  32. 39 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/vo/RouteItemVO.java
  33. 49 0
      tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/vo/RouteMetoVO.java
  34. 6 3
      tr-modules/tr-module-system/src/main/resources/mapper/user/SysMenuMapper.xml
  35. 16 0
      tr-modules/tr-module-system/src/main/resources/mapper/user/SysRoleMapper.xml
  36. 3 6
      tr-modules/tr-module-system/src/main/resources/mapper/user/SysUserMapper.xml
  37. 2 2
      tr-plugins/tr-spring-boot-starter-plugin-mybatis/src/main/java/cn/tr/plugin/mybatis/pojo/BasePO.java

+ 2 - 2
tr-framework/src/main/java/cn/tr/core/constant/MybatisConstant.java

@@ -19,11 +19,11 @@ public class MybatisConstant {
     /**
      * 创建人字段名称
      */
-    public static final String CREATE_BY = "creator";
+    public static final String CREATE_BY = "create_by";
     /**
      * 更新人字段名称
      */
-    public static final String UPDATE_BY = "updater";
+    public static final String UPDATE_BY = "update_by";
 
     /**
      * 租户id字段名称

+ 3 - 3
tr-framework/src/main/java/cn/tr/core/utils/TreeUtil.java

@@ -53,11 +53,11 @@ public class TreeUtil {
      * @param sources
      * @return
      */
-    public static  List<TreeNode> buildTree(Collection<TreeNode> sources){
+    public static <Node extends TreeNode> List<Node> buildTree(Collection<Node> sources){
         return buildTree(sources,null);
     };
 
-    public static  <D extends TreeNode> List<D> buildTree(Collection<D > sources, List<String> excludeNodeIds){
+    public static  <Node extends TreeNode> List<Node> buildTree(Collection<Node > sources, List<String> excludeNodeIds){
         if(CollectionUtil.isNotEmpty(excludeNodeIds)){
             sources=sources.stream()
                     .filter(source->!excludeNodeIds.contains(source.getId()))
@@ -65,7 +65,7 @@ public class TreeUtil {
         }
         //找到顶级节点
         sources.stream().filter(source-> ObjectUtil.isNull(source.getSort())).forEach(source->source.setSort(999));
-        List<D> result = sources.stream()
+        List<Node> result = sources.stream()
                 .filter(node -> StrUtil.equals("0",String.valueOf(node.getParentId())))
                 .collect(Collectors.toList());
         if(CollectionUtil.isEmpty(result)){

+ 25 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/mapper/user/SysDeptMapper.java

@@ -0,0 +1,25 @@
+package cn.tr.module.sys.mapper.user;
+
+import cn.tr.module.sys.user.dto.SysDeptDTO;
+import cn.tr.module.sys.user.po.SysDeptPO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * @ClassName : SysDeptMapper
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年03月31日
+ */
+@Mapper
+public interface SysDeptMapper {
+    SysDeptMapper INSTANCE = Mappers.getMapper(SysDeptMapper.class);
+
+    List<SysDeptDTO> toSysDeptDTOList(List<SysDeptPO> source);
+
+    SysDeptDTO toSysDeptDTO(SysDeptPO source);
+
+    SysDeptPO toSysDeptPO(SysDeptDTO source);
+}

+ 3 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/mapper/user/SysMenuMapper.java

@@ -2,6 +2,7 @@ package cn.tr.module.sys.mapper.user;
 
 import cn.tr.module.sys.user.dto.SysMenuDTO;
 import cn.tr.module.sys.user.po.SysMenuPO;
+import cn.tr.module.sys.user.vo.RouteItemVO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
 
@@ -22,4 +23,6 @@ public interface SysMenuMapper {
     SysMenuDTO toSysMenuDTO(SysMenuPO source);
 
     SysMenuPO toSysMenuPO(SysMenuDTO source);
+
+    RouteItemVO toRouteItemVO(SysMenuDTO source);
 }

+ 27 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/mapper/user/SysUserRoleMapper.java

@@ -0,0 +1,27 @@
+package cn.tr.module.sys.mapper.user;
+
+import cn.tr.module.sys.user.dto.SysUserRoleDTO;
+import cn.tr.module.sys.user.po.SysUserRolePO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * @ClassName : SysUserRoleMapper
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年03月31日
+ */
+@Mapper
+public interface SysUserRoleMapper {
+    SysUserRoleMapper INSTANCE = Mappers.getMapper(SysUserRoleMapper.class);
+
+    List<SysUserRoleDTO> toSysUserRoleDTOList(List<SysUserRolePO> source);
+
+    List<SysUserRolePO> toSysUserRolePOList(List<SysUserRoleDTO> source);
+
+    SysUserRoleDTO toSysUserRoleDTO(SysUserRolePO source);
+
+    SysUserRolePO toSysUserRolePO(SysUserRoleDTO source);
+}

+ 20 - 9
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/oauth2/controller/CurrentUserController.java

@@ -1,11 +1,18 @@
 package cn.tr.module.sys.oauth2.controller;
 
+import cn.hutool.core.util.StrUtil;
 import cn.tr.core.exception.ServiceException;
 import cn.tr.core.exception.TRExcCode;
 import cn.tr.core.pojo.CommonResult;
+import cn.tr.core.utils.TreeUtil;
 import cn.tr.module.sys.oauth2.psw.operator.AbstractOAuth2PswUserOperator;
 import cn.tr.module.sys.oauth2.psw.operator.OAuth2PswUserOperatorManager;
+import cn.tr.module.sys.user.dto.SysMenuDTO;
+import cn.tr.module.sys.user.enums.MenuEnum;
+import cn.tr.module.sys.user.service.ISysRoleService;
+import cn.tr.module.sys.user.vo.RouteItemVO;
 import cn.tr.plugin.security.context.LoginUserContextHolder;
+import cn.tr.plugin.security.utils.SaTokenUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
@@ -13,6 +20,11 @@ import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 /**
  * @ClassName : CurrentUserController
  * @Description :
@@ -25,8 +37,9 @@ import org.springframework.web.bind.annotation.RestController;
 @AllArgsConstructor
 public class CurrentUserController {
     private final OAuth2PswUserOperatorManager pswUserOperatorManager;
+    private final ISysRoleService roleService;
     @ApiOperation("当前用户的登陆信息")
-    @GetMapping("/login-info")
+    @GetMapping("/loginInfo")
     public CommonResult accountInfo(){
         String stpType = LoginUserContextHolder.getStpType();
         AbstractOAuth2PswUserOperator operator = pswUserOperatorManager.matchLoginType(stpType);
@@ -36,18 +49,16 @@ public class CurrentUserController {
         return CommonResult.success(operator.getUserLoginInfo());
     }
 
-    @GetMapping("/get-permission-info")
+    @GetMapping("/getPermissionInfo")
     @ApiOperation( "获取登录用户的权限信息")
-    public CommonResult getPermissionInfo() {
-        // 拼接结果返回
-
-        return CommonResult.success(null);
+    public CommonResult<Set<String>> getPermissionInfo() {
+        return CommonResult.success( roleService.findUserPermission(String.valueOf(SaTokenUtils.getStpUtil().getLoginId())));
     }
 
-    @GetMapping("/list-menus")
+    @GetMapping("/listMenus")
     @ApiOperation("获得登录用户的菜单列表")
-    public CommonResult getMenus() {
-        return CommonResult.success(null);
+    public CommonResult<List<RouteItemVO>> getMenus() {
+        return CommonResult.success(TreeUtil.buildTree( roleService.findUserRouteMenus(String.valueOf(SaTokenUtils.getStpUtil().getLoginId()))));
     }
 
 }

+ 1 - 1
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/oauth2/controller/OAuth2ServerController.java

@@ -78,7 +78,7 @@ public class OAuth2ServerController {
 
     @ApiOperationSupport(author = "lf")
     @ApiOperation("更新当前用户密码")
-    @PostMapping("/update-psw")
+    @PostMapping("/updatePsw")
     @SaIgnore
     public CommonResult<Boolean> updatePsw(@RequestBody @Validated OAuth2UpdatePswDTO psw){
         SaClientModel cm = SaOAuth2Handle.currClientModel();

+ 16 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/constant/MenuConstants.java

@@ -0,0 +1,16 @@
+package cn.tr.module.sys.user.constant;
+
+/**
+ * 菜单常量类
+ *
+ * @author Kevin
+ */
+public interface MenuConstants {
+
+    String LAYOUT = "LAYOUT";
+
+    String IFRAME = "IFrame";
+
+    String GET_PARENT_LAYOUT = "getParentLayout('%s')";
+
+}

+ 86 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/controller/SysDeptController.java

@@ -0,0 +1,86 @@
+package cn.tr.module.sys.user.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.tr.core.pojo.CommonResult;
+import cn.tr.core.pojo.TableDataInfo;
+import cn.tr.core.utils.TreeUtil;
+import cn.tr.core.validation.Insert;
+import cn.tr.core.validation.Update;
+import cn.tr.module.sys.user.dto.SysDeptDTO;
+import cn.tr.module.sys.user.dto.SysDeptQueryDTO;
+import cn.tr.module.sys.user.service.ISysDeptService;
+import cn.tr.plugin.mybatis.base.BaseController;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+/**
+ * @ClassName : SysDeptController
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年03月24日
+ */
+@RestController
+@RequestMapping("/sys/dept")
+@Api(tags = "部门")
+@AllArgsConstructor
+public class SysDeptController extends BaseController {
+    private final ISysDeptService deptService;
+
+    @PostMapping("/query/tree")
+    @ApiOperationSupport(author = "lf")
+    @ApiOperation(value = "根据条件查询部门树",notes = "权限: 无")
+    public CommonResult<List<SysDeptDTO>> selectTree(@RequestBody SysDeptQueryDTO query){
+        return CommonResult.success(TreeUtil.buildTree(deptService.selectSysDeptList(query)));
+    }
+
+
+    @PostMapping("/query/page")
+    @ApiOperationSupport(author = "lf")
+    @ApiOperation(value = "根据条件查询部门",notes = "权限: sys:dept:query")
+    @SaCheckPermission("sys:dept:query")
+    public TableDataInfo<SysDeptDTO> selectList(@RequestBody SysDeptQueryDTO query){
+        startPage();
+        return getDataTable(deptService.selectSysDeptList(query));
+    }
+
+    @GetMapping("/detail/{id}")
+    @ApiOperationSupport(author = "lf")
+    @ApiOperation(value = "根据id查询部门",notes = "权限: sys:dept:query")
+    @SaCheckPermission("sys:dept:query")
+    public CommonResult<SysDeptDTO> findById(@PathVariable("id") String id){
+        return CommonResult.success(deptService.selectSysDeptById(id));
+    }
+
+    @PostMapping("/edit")
+    @ApiOperationSupport(author = "lf")
+    @SaCheckPermission("sys:Dept:edit")
+    @ApiOperation(value = "根据id更新部门",notes = "权限: sys:Dept:edit")
+    public CommonResult<Boolean> edit(@RequestBody@Validated(Update.class) SysDeptDTO source){
+        return CommonResult.success(deptService.updateSysDeptById(source));
+    }
+
+    @PostMapping("/add")
+    @ApiOperationSupport(author = "lf")
+    @SaCheckPermission("sys:Dept:add")
+    @ApiOperation(value = "新增部门",notes = "权限: sys:Dept:add")
+    public CommonResult<Boolean> add(@RequestBody@Validated(Insert.class) SysDeptDTO source){
+        return CommonResult.success(deptService.insertSysDept(source));
+    }
+    
+    @PostMapping("/deleteByIds")
+    @ApiOperationSupport(author = "lf")
+    @ApiOperation(value = "删除部门",notes = "权限: sys:Dept:del")
+    @SaCheckPermission("sys:Dept:del")
+    public CommonResult<Integer> deleteByIds(@RequestBody Collection<String> ids){
+        return CommonResult.success(deptService.deleteSysDeptByIds(ids));
+    }
+    
+
+    //todo 导出
+
+}

+ 52 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysDeptDTO.java

@@ -0,0 +1,52 @@
+package cn.tr.module.sys.user.dto;
+
+import cn.tr.core.tree.TreeNode;
+import cn.tr.core.validation.Insert;
+import cn.tr.core.validation.Update;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 部门对象 sys_menu
+ *
+ * @author tr
+ * @date 2022-11-23 15:34:37
+ */
+@Data
+@ApiModel("部门对象")
+public class SysDeptDTO extends TreeNode<String> {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键")
+    @NotNull(message = "主键不能为空",groups = {Update.class})
+    private String id;
+
+    @ApiModelProperty(value = "父级id 顶级目录的父级id为0")
+    private String parentId;
+
+    @ApiModelProperty(value = "排序",required = true)
+    @NotNull(message = "排序不能为空",groups = {Insert.class, Update.class})
+    private Integer sort;
+
+    @ApiModelProperty(value = "部门名称",required = true)
+    @NotNull(message = "部门名称不能为空",groups = {Insert.class, Update.class})
+    private String name;
+
+    @ApiModelProperty(value = "部门电话")
+    private String phone;
+
+    @ApiModelProperty(value = "部门领导人")
+    private String leaderUserId;
+    
+    @ApiModelProperty(value = "部门邮箱")
+    private String email;
+
+    @ApiModelProperty(value = "状态 0正常;1停用",required = true)
+    @NotNull(message = "部门状态不能为空",groups = {Insert.class, Update.class})
+    private Boolean disable;
+
+}

+ 26 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysDeptQueryDTO.java

@@ -0,0 +1,26 @@
+package cn.tr.module.sys.user.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.io.Serializable;
+
+/**
+ * @ClassName : SysRoleQueryDTO
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年04月01日
+ */
+@Data
+@ApiModel("部门查询参数")
+public class SysDeptQueryDTO implements Serializable {
+    private static final long serialVersionUID = -262693810220247854L;
+    @ApiModelProperty(value = "父级部门id")
+    private String parentId;
+
+    @ApiModelProperty(value = "部门名称")
+    private String name;
+
+    @ApiModelProperty(value = "是否启用 0、启用 1、关闭")
+    private Boolean disable;
+}

+ 4 - 1
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysMenuDTO.java

@@ -36,6 +36,9 @@ public class SysMenuDTO extends TreeNode<String> {
     @NotEmpty(message = "排序不能为空",groups = {Update.class, Insert.class})
     private Integer sort;
 
+    /**
+     * {@link cn.tr.module.sys.user.enums.MenuEnum}
+     */
     @ApiModelProperty(value = "菜单类型 dir目录;menu菜单;button按钮",required = true)
     @NotEmpty(message = "菜单类型不能为空",groups = {Update.class, Insert.class})
     private String menuType;
@@ -85,7 +88,7 @@ public class SysMenuDTO extends TreeNode<String> {
 
 
     @ApiModelProperty(value = "备注")
-    private String remarks;
+    private String remark;
 
 
     @ApiModelProperty(value = "状态 0正常;1停用",required = true)

+ 16 - 16
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysUserDTO.java

@@ -1,9 +1,12 @@
 package cn.tr.module.sys.user.dto;
 
-import cn.hutool.core.date.DatePattern;
-import cn.tr.plugin.excel.annotation.Excel;
+import cn.tr.core.validation.Insert;
+import cn.tr.core.validation.Update;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
 import java.util.Date;
 
 /**
@@ -17,18 +20,19 @@ public class SysUserDTO {
     /**
      * 用户主键Id
      */
+    @ApiModelProperty(value = "用户id")
     private String userId;
 
     /**
      * 用户名
      */
-    @Excel(name = "用户名")
+    @ApiModelProperty(value = "用户名",required = true)
     private String username;
 
     /**
      * 昵称
      */
-    @Excel(name = "昵称")
+    @ApiModelProperty(value = "昵称")
     private String nickname;
 
     /**
@@ -40,30 +44,29 @@ public class SysUserDTO {
     /**
      * 性别
      */
-    @Excel(name = "性别",dictCode = "gender")
+    @ApiModelProperty(value = "性别")
     private String gender;
 
     /**
      * 部门id
      */
+    @ApiModelProperty(value = "部门id")
+    @NotEmpty(message = "部门不能为空",groups = {Insert.class, Update.class})
     private String deptId;
 
     /**
      * 手机号
      */
-    @Excel(name = "手机号")
     private String phone;
 
     /**
      * 邮箱地址
      */
-    @Excel(name = "邮箱")
     private String email;
 
     /**
      * 出生日期
      */
-    @Excel(name = "出生日期",dateFormat = DatePattern.CHINESE_DATE_TIME_PATTERN)
     private Date birthday;
 
     /**
@@ -74,33 +77,30 @@ public class SysUserDTO {
     /**
      * 用户头像
      */
-    @Excel(name = "用户头像")
     private String avatar;
 
     /**
      * 用户状态
      */
+    @ApiModelProperty(value = "用户状态",required = true)
+    @NotEmpty(message = "用户状态",groups = {Insert.class, Update.class})
     private String status;
 
     /**
      * 最后登录IP
      */
-    @Excel(name = "最后登录IP")
+    @JsonIgnoreProperties(allowGetters = true)
     private String lastLoginIp;
 
-    @Excel(name = "最后登录地址")
+    @JsonIgnoreProperties(allowGetters = true)
     private String lastLoginAddress;
 
-    /**
-     * 最后登录时间
-     */
-    @Excel(name = "最后登录时间",dateFormat = DatePattern.CHINESE_DATE_TIME_PATTERN)
+    @JsonIgnoreProperties(allowGetters = true)
     private Date lastLoginDate;
 
     /**
      * 备注
      */
-    @Excel(name = "备注")
     private String remark;
 
 }

+ 18 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/dto/SysUserRoleDTO.java

@@ -0,0 +1,18 @@
+package cn.tr.module.sys.user.dto;
+
+import lombok.Data;
+
+/**
+ * @ClassName : SysRoleMenuPO
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年04月04日
+ */
+@Data
+public class SysUserRoleDTO {
+    private String id;
+
+    private String roleId;
+
+    private String userId;
+}

+ 23 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/enums/MenuEnum.java

@@ -0,0 +1,23 @@
+package cn.tr.module.sys.user.enums;
+
+/**
+ * @ClassName : MenuEnum
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年04月04日
+ */
+
+public enum  MenuEnum {
+    /**
+     * 目录
+     */
+    dir,
+    /**
+     * 菜单
+     */
+    menu,
+    /**
+     * 按钮
+     */
+    button
+}

+ 47 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/po/SysDeptPO.java

@@ -0,0 +1,47 @@
+package cn.tr.module.sys.user.po;
+
+import cn.tr.core.annotation.Comment;
+import cn.tr.plugin.mybatis.pojo.BasePO;
+import cn.tr.plugin.mybatis.pojo.TenantPO;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.ToString;
+
+/**
+ * 部门对象 sys_menu
+ *
+ * @author tr
+ * @date 2022-11-23 15:34:37
+ */
+@Data
+@TableName(value = "sys_dept",autoResultMap = true)
+@ToString
+public class SysDeptPO extends TenantPO {
+
+    private static final long serialVersionUID = 1L;
+
+    @Comment(value = "主键")
+    private String id;
+
+    @Comment(value = "父级id 顶级目录的父级id为0")
+    private String parentId;
+
+    @Comment("排序")
+    private Integer sort;
+
+    @Comment(value = "部门名称")
+    private String name;
+
+    @Comment(value = "部门电话")
+    private String phone;
+
+    @Comment(value = "部门领导人")
+    private String leaderUserId;
+    
+    @Comment(value = "部门邮箱")
+    private String email;
+
+    @Comment(value = "状态 0正常;1停用")
+    private Boolean disable;
+
+}

+ 1 - 1
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/po/SysMenuPO.java

@@ -73,7 +73,7 @@ public class SysMenuPO extends BasePO {
 
 
     @ApiModelProperty(value = "备注")
-    private String remarks;
+    private String remark;
 
 
     @ApiModelProperty(value = "状态 0正常;1停用")

+ 25 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/po/SysUserRolePO.java

@@ -0,0 +1,25 @@
+package cn.tr.module.sys.user.po;
+
+import cn.tr.core.annotation.Comment;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * @ClassName : SysRoleMenuPO
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年04月04日
+ */
+@Data
+@TableName("sys_user_role")
+public class SysUserRolePO {
+    @TableId
+    private String id;
+
+    @Comment("角色id")
+    private String roleId;
+
+    @Comment("用户id")
+    private String userId;
+}

+ 18 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/repository/SysDeptRepository.java

@@ -0,0 +1,18 @@
+package cn.tr.module.sys.user.repository;
+
+import cn.tr.module.sys.user.po.SysDeptPO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * @ClassName : SysRoleMenuRepository
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年03月31日
+ */
+@Mapper
+@Repository
+public interface SysDeptRepository extends BaseMapper<SysDeptPO> {
+
+}

+ 10 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/repository/SysRoleRepository.java

@@ -1,10 +1,14 @@
 package cn.tr.module.sys.user.repository;
 
+import cn.tr.module.sys.user.po.SysMenuPO;
 import cn.tr.module.sys.user.po.SysRolePO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 /**
  * @ClassName : SysUserRepository
  * @Description :
@@ -14,4 +18,10 @@ import org.springframework.stereotype.Repository;
 @Mapper
 @Repository
 public interface SysRoleRepository extends BaseMapper<SysRolePO> {
+    /**
+     * 找到用户下的所有角色信息
+     * @param userId 用户id
+     * @return
+     */
+    List<SysRolePO> findAllRoleByUserId(@Param("userId") String userId);
 }

+ 18 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/repository/SysUserRoleRepository.java

@@ -0,0 +1,18 @@
+package cn.tr.module.sys.user.repository;
+
+import cn.tr.module.sys.user.po.SysUserRolePO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * @ClassName : SysRoleMenuRepository
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年03月31日
+ */
+@Mapper
+@Repository
+public interface SysUserRoleRepository extends BaseMapper<SysUserRolePO> {
+
+}

+ 74 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/ISysDeptService.java

@@ -0,0 +1,74 @@
+package cn.tr.module.sys.user.service;
+
+import cn.tr.module.sys.user.dto.SysDeptDTO;
+import cn.tr.module.sys.user.dto.SysDeptQueryDTO;
+import cn.tr.plugin.mybatis.service.ITreeService;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @ClassName : ISysDeptService
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年03月31日
+ */
+
+public interface ISysDeptService extends ITreeService {
+
+    /**
+     * 根据条件查询构造树结构
+     * @param query 查询参数
+     * @return
+     */
+    default List<SysDeptDTO> selectSysDeptTree(SysDeptQueryDTO query){
+        return buildTree(selectSysDeptList(query));
+    };
+
+    /**
+     * 根据条件查询构造树结构
+     * @param query 查询参数
+     * @param excludeIds 构造树时排除的节点id
+     * @return
+     */
+    default List<SysDeptDTO> selectSysDeptTree(SysDeptQueryDTO query, List<String> excludeIds){
+        return buildTree(selectSysDeptList(query),excludeIds);
+    };
+
+    /**
+     * 根据条件查询
+     * @param query 查询参数
+     * @return
+     */
+    List<SysDeptDTO> selectSysDeptList(SysDeptQueryDTO query);
+
+
+    /**
+     * 根据id查询操作部门
+     * @param id 部门id
+     * @return 部门
+     */
+    SysDeptDTO selectSysDeptById(String id);
+
+    /**
+     * 更新部门
+     * @param source 更新部门
+     * @return true:更新成功
+     */
+    boolean updateSysDeptById(SysDeptDTO source);
+
+    /**
+     * 新增部门
+     * @param source 新增部门
+     * @return true:新增成功
+     */
+    boolean insertSysDept(SysDeptDTO source);
+
+    /**
+     * 根据id删除部门
+     * @param ids 部门id
+     * @return 删除数量
+     */
+    int deleteSysDeptByIds(Collection<String> ids);
+
+}

+ 1 - 4
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/ISysMenuService.java

@@ -1,7 +1,5 @@
 package cn.tr.module.sys.user.service;
 
-import cn.tr.module.sys.user.dto.SysMenuDTO;
-import cn.tr.module.sys.user.dto.SysMenuQueryDTO;
 import cn.tr.module.sys.user.dto.SysMenuDTO;
 import cn.tr.module.sys.user.dto.SysMenuQueryDTO;
 import cn.tr.plugin.mybatis.service.ITreeService;
@@ -75,7 +73,6 @@ public interface ISysMenuService extends ITreeService {
      */
     int deleteSysMenuByIds(Collection<String> ids);
 
-
     /**
      * 找到角色id下的所有菜单信息
      * @param roleId
@@ -86,7 +83,7 @@ public interface ISysMenuService extends ITreeService {
 
 
     @CacheEvict(value = "sys:rolemenu",key = "#roleId")
-    default void delCache(String roleId){
+    default void delRoleMenusCache(String roleId){
 
     };
 

+ 7 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/ISysRoleMenuService.java

@@ -20,4 +20,11 @@ public interface ISysRoleMenuService {
      */
     void assignRoleMenu(List<SysRoleMenuDTO> source);
 
+
+    /**
+     * 通过菜单id找到所有持有该菜单的角色
+     * @param menuId
+     * @return
+     */
+    Set<String> findRoleByMenuId(String menuId);
 }

+ 43 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/ISysRoleService.java

@@ -1,11 +1,19 @@
 package cn.tr.module.sys.user.service;
 
+import cn.hutool.core.util.StrUtil;
+import cn.tr.module.sys.user.dto.SysMenuDTO;
 import cn.tr.module.sys.user.dto.SysRoleDTO;
 import cn.tr.module.sys.user.dto.SysRoleQueryDTO;
+import cn.tr.module.sys.user.vo.RouteItemVO;
 import cn.tr.plugin.mybatis.service.ITreeService;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * @ClassName : ISysRoleService
@@ -23,6 +31,33 @@ public interface ISysRoleService {
      */
     List<SysRoleDTO> selectSysRoleList(SysRoleQueryDTO query);
 
+    /**
+     * 查询用户的菜单
+     * @param userId 用户id
+     * @return
+     */
+    Set<SysMenuDTO>  findUserMenus(String userId);
+
+    /**
+     * 查询用户的路由菜单
+     * @param userId 用户id
+     * @return
+     */
+    List<RouteItemVO>  findUserRouteMenus(String userId);
+
+    /**
+     * 查询用户的权限
+     * @param userId 用户id
+     * @return
+     */
+    default Set<String>  findUserPermission(String userId){
+        return findUserMenus(userId)
+                .stream()
+                .filter(Objects::nonNull)
+                .map(SysMenuDTO::getPermission)
+                .filter(StrUtil::isNotEmpty)
+                .collect(Collectors.toSet());
+    };
 
     /**
      * 根据id查询操作角色
@@ -51,4 +86,12 @@ public interface ISysRoleService {
      * @return 删除数量
      */
     int deleteSysRoleByIds(Collection<String> ids);
+
+    @Cacheable(value = "sys:user:role",key = "#userId")
+    List<SysRoleDTO> findAllRolesByUserId(String userId);
+
+    @CacheEvict(value = "sys:user:role",key = "#userId")
+    default void delUserRoleCache(String userId){
+
+    };
 }

+ 30 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/ISysUserRoleService.java

@@ -0,0 +1,30 @@
+package cn.tr.module.sys.user.service;
+
+import cn.tr.module.sys.user.dto.SysUserRoleDTO;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @ClassName : ISysRoleMenuService
+ * @Description : 角色菜单关联关系
+ * @Author : LF
+ * @Date: 2023年03月31日
+ */
+
+public interface ISysUserRoleService {
+
+    /**
+     * 为用户分配角色
+     * @param source 角色菜单关联信息
+     * @return
+     */
+    void assignUserRole(List<SysUserRoleDTO> source);
+
+    /**
+     * 通过角色id找到所有持有该角色的用户
+     * @param roleId
+     * @return
+     */
+    Set<String> findUserByRoleId(String roleId);
+}

+ 82 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/impl/SysDeptServiceImpl.java

@@ -0,0 +1,82 @@
+package cn.tr.module.sys.user.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.tr.core.exception.ServiceException;
+import cn.tr.core.exception.TRExcCode;
+import cn.tr.core.utils.JsonUtils;
+import cn.tr.module.sys.mapper.user.SysDeptMapper;
+import cn.tr.module.sys.user.dto.SysDeptDTO;
+import cn.tr.module.sys.user.dto.SysDeptQueryDTO;
+import cn.tr.module.sys.user.po.SysDeptPO;
+import cn.tr.module.sys.user.po.SysUserPO;
+import cn.tr.module.sys.user.repository.SysDeptRepository;
+import cn.tr.module.sys.user.repository.SysUserRepository;
+import cn.tr.module.sys.user.service.ISysDeptService;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @ClassName : SysDeptServiceImpl
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年03月31日
+ */
+@Service
+public class SysDeptServiceImpl implements ISysDeptService {
+    @Autowired
+    private SysDeptRepository deptRepository;
+    @Autowired
+    private SysUserRepository userRepository;
+
+    @Override
+    public List<SysDeptDTO> selectSysDeptList(SysDeptQueryDTO query) {
+        return SysDeptMapper.INSTANCE.toSysDeptDTOList(deptRepository.selectList(new LambdaQueryWrapper<SysDeptPO>()
+                .like(StrUtil.isNotEmpty(query.getName()),SysDeptPO::getName,query.getName())
+                .eq(StrUtil.isNotEmpty(query.getParentId()),SysDeptPO::getParentId,query.getParentId())
+                .eq(ObjectUtil.isNotNull(query.getDisable()),SysDeptPO::getDisable,query.getDisable()))
+        );
+    }
+
+    @Override
+    public SysDeptDTO selectSysDeptById(String id) {
+        return SysDeptMapper.INSTANCE.toSysDeptDTO(deptRepository.selectById(id));
+    }
+
+    @Override
+    public boolean updateSysDeptById(SysDeptDTO source) {
+        return deptRepository.updateById(SysDeptMapper.INSTANCE.toSysDeptPO(source))!=0;
+    }
+    @Override
+    public boolean insertSysDept(SysDeptDTO source) {
+        return deptRepository.insert(SysDeptMapper.INSTANCE.toSysDeptPO(source))!=0;
+    }
+
+    @Override
+    public int deleteSysDeptByIds(Collection<String> ids) {
+        List<SysDeptPO> depts = deptRepository.selectBatchIds(ids);
+        if(CollectionUtil.isEmpty(depts)){
+            return CollectionUtil.size(ids);
+        }
+        List<SysUserPO> deptUsers = userRepository.selectList(new LambdaQueryWrapper<SysUserPO>()
+                .in(SysUserPO::getDeptId, ids));
+        if(CollectionUtil.isNotEmpty(deptUsers)){
+            //部门用户
+            Map<String, SysDeptPO> deptMap = depts.stream().collect(Collectors.groupingBy(SysDeptPO::getId, Collectors.collectingAndThen(Collectors.toList(), CollectionUtil::getFirst)));
+            Set<String> userDeptIds = deptUsers.stream().map(SysUserPO::getDeptId).collect(Collectors.toSet());
+            Set<String> existName = userDeptIds.stream()
+                    .map(deptMap::get)
+                    .filter(Objects::nonNull)
+                    .map(SysDeptPO::getName)
+                    .collect(Collectors.toSet());
+            throw new ServiceException(TRExcCode.SYSTEM_ERROR_B0001,String.format("部门 %s 下存在用户,不可删除", JsonUtils.toJsonString(existName)));
+
+        }
+        return deptRepository.deleteBatchIds(ids);
+    }
+}

+ 25 - 4
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/impl/SysMenuServiceImpl.java

@@ -1,5 +1,6 @@
 package cn.tr.module.sys.user.service.impl;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.tr.module.sys.mapper.user.SysMenuMapper;
@@ -8,12 +9,15 @@ import cn.tr.module.sys.user.dto.SysMenuQueryDTO;
 import cn.tr.module.sys.user.po.SysMenuPO;
 import cn.tr.module.sys.user.repository.SysMenuRepository;
 import cn.tr.module.sys.user.service.ISysMenuService;
+import cn.tr.module.sys.user.service.ISysRoleMenuService;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 /**
  * @ClassName : SysMenuServiceImpl
@@ -22,9 +26,15 @@ import java.util.List;
  * @Date: 2023年03月31日
  */
 @Service
-@AllArgsConstructor
 public class SysMenuServiceImpl implements ISysMenuService {
-    private final SysMenuRepository menuRepository;
+    @Autowired
+    private SysMenuRepository menuRepository;
+    @Autowired
+    @Lazy
+    private ISysRoleMenuService roleMenuService;
+    @Autowired
+    @Lazy
+    private ISysMenuService self;
     @Override
     public List<SysMenuDTO> selectSysMenuList(SysMenuQueryDTO query) {
         return SysMenuMapper.INSTANCE.toSysMenuDTOList(menuRepository.selectList(new LambdaQueryWrapper<SysMenuPO>()
@@ -40,15 +50,26 @@ public class SysMenuServiceImpl implements ISysMenuService {
 
     @Override
     public boolean updateSysMenuById(SysMenuDTO source) {
+        Set<String> roleIds = roleMenuService.findRoleByMenuId(source.getId());
+        roleIds.parallelStream().forEach(self::delRoleMenusCache);
         return menuRepository.updateById(SysMenuMapper.INSTANCE.toSysMenuPO(source))!=0;
     }
     @Override
     public boolean insertSysMenu(SysMenuDTO source) {
-        return false;
+        return menuRepository.insert(SysMenuMapper.INSTANCE.toSysMenuPO(source))!=0;
     }
 
     @Override
     public int deleteSysMenuByIds(Collection<String> ids) {
+        List<SysMenuPO> menus = menuRepository.selectBatchIds(ids);
+        if(CollectionUtil.isEmpty(menus)){
+            return CollectionUtil.size(ids);
+        }
+        menus.parallelStream()
+                .map(SysMenuPO::getId)
+                .map(roleMenuService::findRoleByMenuId)
+                .flatMap(Collection::stream)
+                .forEach(self::delRoleMenusCache);
         return menuRepository.deleteBatchIds(ids);
     }
 

+ 14 - 2
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/impl/SysRoleMenuServiceImpl.java

@@ -1,7 +1,9 @@
 package cn.tr.module.sys.user.service.impl;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.tr.module.sys.mapper.user.SysRoleMenuMapper;
 import cn.tr.module.sys.user.dto.SysRoleMenuDTO;
+import cn.tr.module.sys.user.po.SysMenuPO;
 import cn.tr.module.sys.user.po.SysRoleMenuPO;
 import cn.tr.module.sys.user.repository.SysRoleMenuRepository;
 import cn.tr.module.sys.user.service.ISysMenuService;
@@ -14,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -35,9 +38,18 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuRepository,Sy
                 .collect(Collectors.groupingBy(SysRoleMenuPO::getRoleId));
         collect.forEach((k,relations)->{
             baseMapper.delete(new LambdaQueryWrapper<SysRoleMenuPO>().eq(SysRoleMenuPO::getRoleId,k));
-            saveBatch(relations);
             //清除角色缓存
-            menuService.delCache(k);
+            menuService.delRoleMenusCache(k);
+            if(CollectionUtil.isEmpty(relations)){
+                return;
+            }
+            saveBatch(relations);
         });
     }
+
+    @Override
+    public Set<String> findRoleByMenuId(String menuId) {
+        List<SysRoleMenuPO> roleMenus = this.list(new LambdaQueryWrapper<SysRoleMenuPO>().eq(SysRoleMenuPO::getMenuId, menuId));
+        return roleMenus.stream().map(SysRoleMenuPO::getRoleId).collect(Collectors.toSet());
+    }
 }

+ 103 - 9
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/impl/SysRoleServiceImpl.java

@@ -1,23 +1,32 @@
 package cn.tr.module.sys.user.service.impl;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.tr.core.exception.ServiceException;
 import cn.tr.core.exception.TRExcCode;
+import cn.tr.module.sys.mapper.user.SysMenuMapper;
 import cn.tr.module.sys.mapper.user.SysRoleMapper;
+import cn.tr.module.sys.user.constant.MenuConstants;
+import cn.tr.module.sys.user.dto.SysMenuDTO;
 import cn.tr.module.sys.user.dto.SysRoleDTO;
 import cn.tr.module.sys.user.dto.SysRoleQueryDTO;
+import cn.tr.module.sys.user.enums.MenuEnum;
 import cn.tr.module.sys.user.po.SysRolePO;
 import cn.tr.module.sys.user.repository.SysRoleRepository;
+import cn.tr.module.sys.user.service.ISysMenuService;
 import cn.tr.module.sys.user.service.ISysRoleService;
+import cn.tr.module.sys.user.service.ISysUserRoleService;
+import cn.tr.module.sys.user.vo.RouteItemVO;
+import cn.tr.module.sys.user.vo.RouteMetoVO;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @ClassName : SysRoleServiceImpl
@@ -26,9 +35,20 @@ import java.util.Optional;
  * @Date: 2023年03月31日
  */
 @Service
-@AllArgsConstructor
 public class SysRoleServiceImpl implements ISysRoleService {
-    private final SysRoleRepository roleRepository;
+    @Autowired
+    private SysRoleRepository roleRepository;
+
+    @Autowired
+    @Lazy
+    private ISysMenuService menuService;
+    @Autowired
+    @Lazy
+    private ISysUserRoleService userRoleService;
+
+    @Autowired
+    @Lazy
+    private ISysRoleService self;
     @Override
     public List<SysRoleDTO> selectSysRoleList(SysRoleQueryDTO query) {
         return SysRoleMapper.INSTANCE.toSysRoleDTOList(roleRepository.selectList(new LambdaQueryWrapper<SysRolePO>()
@@ -38,6 +58,33 @@ public class SysRoleServiceImpl implements ISysRoleService {
         ));
     }
 
+    @Override
+    public Set<SysMenuDTO>  findUserMenus(String userId){
+        List<SysRoleDTO> roles = self.findAllRolesByUserId(userId);
+        if (CollectionUtil.isEmpty(roles)) {
+            return new HashSet<>();
+        }
+        return roles.stream()
+                .filter(Objects::nonNull)
+                .filter(role->Boolean.FALSE.equals(role.getDisable()))
+                .map(SysRoleDTO::getId)
+                .map(menuService::findAllMenuByRoleId)
+                .flatMap(Collection::stream)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+    }
+
+    @Override
+    public List<RouteItemVO> findUserRouteMenus(String userId) {
+        Set<SysMenuDTO> userMenus = findUserMenus(userId);
+        return userMenus.stream()
+                .filter(menu->!StrUtil.equals(MenuEnum.button.name(),menu.getMenuType()))
+                .map(this::convertToRoute)
+                .collect(Collectors.toList());
+    }
+
+    ;
+
     @Override
     public SysRoleDTO selectSysRoleById(String id) {
         return SysRoleMapper.INSTANCE.toSysRoleDTO(roleRepository.selectById(id));
@@ -47,6 +94,8 @@ public class SysRoleServiceImpl implements ISysRoleService {
     public boolean updateSysRoleById(SysRoleDTO source) {
         SysRolePO po = SysRoleMapper.INSTANCE.toSysRolePO(source);
         validateRoleSource(po);
+        Set<String> userIds = userRoleService.findUserByRoleId(source.getId());
+        userIds.parallelStream().forEach(self::delUserRoleCache);
         return roleRepository.updateById(po)!=0;
     }
 
@@ -60,9 +109,14 @@ public class SysRoleServiceImpl implements ISysRoleService {
 
     @Override
     public int deleteSysRoleByIds(Collection<String> ids) {
-        //todo 校验
-        List<SysRolePO> role = roleRepository.selectBatchIds(ids);
-        Optional<SysRolePO> adminRole = role.stream()
+        List<SysRolePO> roles = roleRepository.selectBatchIds(ids);
+        for (SysRolePO role : roles) {
+            Set<String> userIds = userRoleService.findUserByRoleId(role.getId());
+            if(CollectionUtil.isNotEmpty(userIds)){
+                throw new ServiceException(TRExcCode.SYSTEM_ERROR_B0001,String.format("角色编码{%s}已被使用,无法删除",role.getRoleCode()));
+            }
+        }
+        Optional<SysRolePO> adminRole = roles.stream()
                 .filter(po->Boolean.TRUE.equals(po.getAdmin()))
                 .findFirst();
         if(adminRole.isPresent()){
@@ -71,6 +125,11 @@ public class SysRoleServiceImpl implements ISysRoleService {
         return roleRepository.deleteBatchIds(ids);
     }
 
+    @Override
+    public List<SysRoleDTO> findAllRolesByUserId(String userId) {
+        return SysRoleMapper.INSTANCE.toSysRoleDTOList(roleRepository.findAllRoleByUserId(userId));
+    }
+
     private void validateRoleSource(SysRolePO source){
         SysRolePO role = roleRepository.selectOne(new LambdaQueryWrapper<SysRolePO>()
                 .eq(SysRolePO::getRoleName, source.getRoleName())
@@ -90,4 +149,39 @@ public class SysRoleServiceImpl implements ISysRoleService {
             }
         }
     }
+
+
+    private RouteItemVO convertToRoute(SysMenuDTO item) {
+        RouteItemVO node = SysMenuMapper.INSTANCE.toRouteItemVO(item);
+        node.setPath(item.getRoutePath());
+        node.setName(item.getRoutePath());
+        // 一级目录
+        if (Objects.equals(item.getMenuType(), MenuEnum.dir.name()) && (StrUtil.equals(item.getParentId(),"0")||StrUtil.isEmpty(item.getParentId()))) {
+            node.setPath("/" + item.getRoutePath());
+            node.setComponent(MenuConstants.LAYOUT);
+        }
+        // 外部链接
+        if (Objects.equals(item.getMenuType(), MenuEnum.menu.name()) && Boolean.TRUE.equals(item.getLinkExternal())) {
+            node.setComponent(MenuConstants.IFRAME);
+        }
+        RouteMetoVO routeMetoVO = new RouteMetoVO();
+        routeMetoVO.setTitle(item.getName());
+        routeMetoVO.setIcon(item.getIcon());
+        routeMetoVO.setHideMenu(!Boolean.TRUE.equals(item.getVisible()));
+        // 菜单
+        if (Objects.equals(item.getMenuType(), MenuEnum.menu.name())) {
+            routeMetoVO.setIgnoreKeepAlive(!Boolean.TRUE.equals(item.getKeepalive()));
+        }
+        // 外部链接
+        if (Objects.equals(item.getMenuType(), MenuEnum.menu.name()) && Boolean.TRUE.equals(item.getLinkExternal())) {
+            // 内嵌
+            if (Boolean.TRUE.equals(item.getFrame())) {
+                routeMetoVO.setFrameSrc(item.getLinkUrl());
+            }else {
+                node.setPath(item.getLinkUrl());
+            }
+        }
+        node.setMeta(routeMetoVO);
+        return node;
+    }
 }

+ 55 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/service/impl/SysUserRoleServiceImpl.java

@@ -0,0 +1,55 @@
+package cn.tr.module.sys.user.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.tr.module.sys.mapper.user.SysUserRoleMapper;
+import cn.tr.module.sys.user.dto.SysUserRoleDTO;
+import cn.tr.module.sys.user.po.SysUserRolePO;
+import cn.tr.module.sys.user.repository.SysUserRoleRepository;
+import cn.tr.module.sys.user.service.ISysRoleService;
+import cn.tr.module.sys.user.service.ISysUserRoleService;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @ClassName : SysRoleMenuServiceImpl
+ * @Description :
+ * @Author : LF
+ * @Date: 2023年04月04日
+ */
+@Service
+public class SysUserRoleServiceImpl extends ServiceImpl<SysUserRoleRepository, SysUserRolePO> implements ISysUserRoleService {
+    @Autowired
+    @Lazy
+    private ISysRoleService roleService;
+
+    @Override
+    public void assignUserRole(List<SysUserRoleDTO> source) {
+        List<SysUserRolePO> userRoles = SysUserRoleMapper.INSTANCE.toSysUserRolePOList(source);
+        Map<String, List<SysUserRolePO>> collect = userRoles.stream()
+                .collect(Collectors.groupingBy(SysUserRolePO::getUserId));
+        collect.forEach((userId,relations)->{
+            baseMapper.delete(new LambdaQueryWrapper<SysUserRolePO>().eq(SysUserRolePO::getUserId,userId));
+            //清除角色缓存
+            roleService.delUserRoleCache(userId);
+            if (CollectionUtil.isEmpty(relations)) {
+                return;
+            }
+            saveBatch(relations);
+        });
+    }
+
+    @Override
+    public Set<String> findUserByRoleId(String roleId) {
+        List<SysUserRolePO> userRoles = this.list(new LambdaQueryWrapper<SysUserRolePO>().eq(SysUserRolePO::getRoleId, roleId));
+        return userRoles.stream().map(SysUserRolePO::getUserId).collect(Collectors.toSet());
+    }
+}

+ 39 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/vo/RouteItemVO.java

@@ -0,0 +1,39 @@
+package cn.tr.module.sys.user.vo;
+
+import cn.tr.core.tree.TreeNode;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 路由项VO
+ *
+ * @author Kevin
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class RouteItemVO extends TreeNode<String> {
+
+    private static final long serialVersionUID = -8702833845192553835L;
+    @JsonIgnore
+    private String id;
+
+    private String path;
+
+    private String component;
+
+    private String icon;
+
+    private RouteMetoVO meta;
+
+    private String name;
+
+    private String redirect;
+    @Override
+    @JsonIgnore
+    public String getParentId() {
+        return super.getParentId();
+    }
+}

+ 49 - 0
tr-modules/tr-module-system/src/main/java/cn/tr/module/sys/user/vo/RouteMetoVO.java

@@ -0,0 +1,49 @@
+package cn.tr.module.sys.user.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 路由MetoVO
+ *
+ * @author Kevin
+ */
+@Data
+public class RouteMetoVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String title;
+
+    private Boolean ignoreAuth;
+
+    private String roles;
+
+    private Boolean ignoreKeepAlive;
+
+    private Boolean affix;
+
+    private String icon;
+
+    private String frameSrc;
+
+    private String transitionName;
+
+    private Boolean hideBreadcrumb;
+
+    private Boolean hideChildrenInMenu;
+
+    private Boolean carryParam;
+
+    private Boolean single;
+
+    private String currentActiveMenu;
+
+    private Boolean hideTab;
+
+    private Boolean hideMenu;
+
+    private Boolean isLink;
+
+}

+ 6 - 3
tr-modules/tr-module-system/src/main/resources/mapper/user/SysMenuMapper.xml

@@ -2,11 +2,14 @@
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="cn.tr.module.sys.user.repository.SysUserRepository">
+<mapper namespace="cn.tr.module.sys.user.repository.SysMenuRepository">
 
 
-    <select id="selectUserByUsernameIgnoreDel" resultType="cn.tr.module.sys.user.po.SysUserPO">
-        select * from sys_user where username=#{username}
+    <select id="findAllMenuByRoleId" resultType="cn.tr.module.sys.user.po.SysMenuPO" parameterType="java.lang.String">
+            select m.*
+            from (select * from sys_role where id=#{roleId}) as r
+            left join sys_role_menu  as rm on rm.role_id=r.id
+            left join sys_menu as m on m.id = rm.menu_id
     </select>
 
 

+ 16 - 0
tr-modules/tr-module-system/src/main/resources/mapper/user/SysRoleMapper.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.tr.module.sys.user.repository.SysRoleRepository">
+
+
+    <select id="findAllRoleByUserId" resultType="cn.tr.module.sys.user.po.SysRolePO">
+         select r.*
+            from (select * from sys_user where user_id=#{userId}) as u
+            left join sys_user_role  as ur on ur.user_id=u.user_id
+            left join sys_role as r on r.id = ur.role_id
+    </select>
+
+
+</mapper>

+ 3 - 6
tr-modules/tr-module-system/src/main/resources/mapper/user/SysUserMapper.xml

@@ -2,14 +2,11 @@
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="cn.tr.module.sys.user.repository.SysMenuRepository">
+<mapper namespace="cn.tr.module.sys.user.repository.SysUserRepository">
 
 
-    <select id="findAllMenuByRoleId" resultType="cn.tr.module.sys.user.po.SysMenuPO" parameterType="java.lang.String">
-            select m.*
-            from (select * from sys_role where id=#{roleId}) as r
-            left join sys_role_menu  as rm on rm.role_id=r.id
-            left join sys_menu as m on m.id = rm.menu_id
+    <select id="selectUserByUsernameIgnoreDel" resultType="cn.tr.module.sys.user.po.SysUserPO">
+        select * from sys_user where username=#{username}
     </select>
 
 

+ 2 - 2
tr-plugins/tr-spring-boot-starter-plugin-mybatis/src/main/java/cn/tr/plugin/mybatis/pojo/BasePO.java

@@ -41,7 +41,7 @@ public class BasePO implements Serializable {
      */
     @Comment("创建人")
     @TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.VARCHAR)
-    private String creator;
+    private String create_by;
     /**
      * 更新者,目前使用 SysUser 的 id 编号
      *
@@ -49,7 +49,7 @@ public class BasePO implements Serializable {
      */
     @Comment("更新人")
     @TableField(fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR)
-    private String updater;
+    private String update_by;
 
 //    /**
 //     * 是否删除