diff --git a/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/api/user/dto/AdminUserRespDTO.java b/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/api/user/dto/AdminUserRespDTO.java index 6d8e3ff..29b5cf8 100644 --- a/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/api/user/dto/AdminUserRespDTO.java +++ b/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/api/user/dto/AdminUserRespDTO.java @@ -4,9 +4,7 @@ import com.fhs.core.trans.vo.VO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import java.util.Set; - -@Schema(description = "RPC 服务 - Admin 用户 Response DTO") +@Schema(description = "RPC 服务 - 管理后台用户 Response DTO") @Data public class AdminUserRespDTO implements VO { @@ -22,8 +20,8 @@ public class AdminUserRespDTO implements VO { @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long deptId; - @Schema(description = "岗位编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 3]") - private Set postIds; + @Schema(description = "主岗位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long positionId; @Schema(description = "手机号码", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300") private String mobile; diff --git a/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ApiConstants.java b/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ApiConstants.java index c337b57..2cb507f 100644 --- a/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ApiConstants.java +++ b/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ApiConstants.java @@ -14,7 +14,7 @@ public class ApiConstants { * * 注意,需要保证和 spring.application.name 保持一致 */ - public static final String NAME = "system-server"; + public static final String NAME = "rdms-system-server"; public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/system"; diff --git a/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ErrorCodeConstants.java b/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ErrorCodeConstants.java index e43aec0..6417e70 100644 --- a/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ErrorCodeConstants.java +++ b/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ErrorCodeConstants.java @@ -52,8 +52,10 @@ public interface ErrorCodeConstants { ErrorCode DEPT_NOT_FOUND = new ErrorCode(1_002_004_002, "当前部门不存在"); ErrorCode DEPT_EXITS_CHILDREN = new ErrorCode(1_002_004_003, "存在子部门,无法删除"); ErrorCode DEPT_PARENT_ERROR = new ErrorCode(1_002_004_004, "不能设置自己为父部门"); + ErrorCode DEPT_CODE_DUPLICATE = new ErrorCode(1_002_004_005, "已经存在编码为【{}】的部门"); ErrorCode DEPT_NOT_ENABLE = new ErrorCode(1_002_004_006, "部门({})不处于开启状态,不允许选择"); ErrorCode DEPT_PARENT_IS_CHILD = new ErrorCode(1_002_004_007, "不能设置自己的子部门为父部门"); + ErrorCode DEPT_ORG_TYPE_INVALID = new ErrorCode(1_002_004_008, "组织类型({})不合法"); // ========== 岗位模块 1-002-005-000 ========== ErrorCode POST_NOT_FOUND = new ErrorCode(1_002_005_000, "当前岗位不存在"); diff --git a/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/dept/DeptOrgTypeEnum.java b/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/dept/DeptOrgTypeEnum.java new file mode 100644 index 0000000..6ce5648 --- /dev/null +++ b/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/dept/DeptOrgTypeEnum.java @@ -0,0 +1,33 @@ +package com.njcn.rdms.module.system.enums.dept; + +import java.util.Arrays; + +/** + * 组织节点类型枚举 + */ +public enum DeptOrgTypeEnum { + + COMPANY("company"), + DEPT("dept"), + DIRECTION("direction"), + TEAM("team"); + + private final String type; + + DeptOrgTypeEnum(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public static boolean isValid(String type) { + return Arrays.stream(values()).anyMatch(item -> item.type.equals(type)); + } + + public static String defaultType() { + return DEPT.type; + } + +} diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java index a9661c9..14c1a16 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java @@ -1,21 +1,21 @@ package com.njcn.rdms.module.system.controller.admin.auth.vo; - import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; import lombok.Data; import org.hibernate.validator.constraints.Length; -@Schema(description = "管理后台 - Register Request VO") +@Schema(description = "管理后台 - 注册 Request VO") @Data public class AuthRegisterReqVO extends CaptchaVerificationReqVO { @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "rdms") @NotBlank(message = "用户账号不能为空") - @Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成") + @Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由数字、字母组成") @Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符") private String username; @@ -24,8 +24,16 @@ public class AuthRegisterReqVO extends CaptchaVerificationReqVO { @Size(max = 30, message = "用户昵称长度不能超过 30 个字符") private String nickname; + @Schema(description = "所属部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "所属部门不能为空") + private Long deptId; + + @Schema(description = "主岗位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "主岗位不能为空") + private Long positionId; + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") @NotEmpty(message = "密码不能为空") @Length(min = 4, max = 16, message = "密码长度为 4-16 位") private String password; -} \ No newline at end of file +} diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptListReqVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptListReqVO.java index 60b5ed3..d833320 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptListReqVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptListReqVO.java @@ -10,6 +10,9 @@ public class DeptListReqVO { @Schema(description = "部门名称,模糊匹配", example = "灿能") private String name; + @Schema(description = "组织节点类型", example = "dept") + private String orgType; + @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") private Integer status; diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptRespVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptRespVO.java index 344661c..5182435 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptRespVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptRespVO.java @@ -18,6 +18,18 @@ public class DeptRespVO { @Schema(description = "父部门 ID", example = "1024") private Long parentId; + @Schema(description = "组织节点类型", example = "dept") + private String orgType; + + @Schema(description = "组织物化路径", example = "/100/101/103/") + private String path; + + @Schema(description = "组织层级", example = "3") + private Integer level; + + @Schema(description = "组织编码", example = "RD_CENTER") + private String code; + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Integer sort; diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java index 1864a55..c16d019 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java @@ -24,6 +24,14 @@ public class DeptSaveReqVO { @Schema(description = "父部门 ID", example = "1024") private Long parentId; + @Schema(description = "组织节点类型", example = "dept") + @Size(max = 20, message = "组织节点类型长度不能超过 20 个字符") + private String orgType; + + @Schema(description = "组织编码", example = "RD_CENTER") + @Size(max = 64, message = "组织编码长度不能超过 64 个字符") + private String code; + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @NotNull(message = "显示顺序不能为空") private Integer sort; diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptSimpleRespVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptSimpleRespVO.java index 7fb4287..0fd7772 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptSimpleRespVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/dept/DeptSimpleRespVO.java @@ -20,4 +20,7 @@ public class DeptSimpleRespVO { @Schema(description = "父部门 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long parentId; + @Schema(description = "组织节点类型", example = "dept") + private String orgType; + } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/post/PostRespVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/post/PostRespVO.java index 3065a45..53e456a 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/post/PostRespVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/post/PostRespVO.java @@ -1,10 +1,10 @@ package com.njcn.rdms.module.system.controller.admin.dept.vo.post; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import com.njcn.rdms.framework.excel.core.annotations.DictFormat; import com.njcn.rdms.framework.excel.core.convert.DictConvert; import com.njcn.rdms.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -19,15 +19,23 @@ public class PostRespVO { @ExcelProperty("岗位序号") private Long id; - @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆") + @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "后端开发工程师") @ExcelProperty("岗位名称") private String name; - @Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "rdms") + @Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "backend") @ExcelProperty("岗位编码") private String code; - @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @Schema(description = "岗位类型", example = "technical") + @ExcelProperty("岗位类型") + private String postType; + + @Schema(description = "岗位级别", example = "8") + @ExcelProperty("岗位级别") + private Integer levelRank; + + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @ExcelProperty("岗位排序") private Integer sort; @@ -36,7 +44,7 @@ public class PostRespVO { @DictFormat(DictTypeConstants.COMMON_STATUS) private Integer status; - @Schema(description = "备注", example = "快乐的备注") + @Schema(description = "备注", example = "技术序列岗位") private String remark; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/post/PostSaveReqVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/post/PostSaveReqVO.java index 9434c7f..3362473 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/post/PostSaveReqVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/dept/vo/post/PostSaveReqVO.java @@ -15,17 +15,24 @@ public class PostSaveReqVO { @Schema(description = "岗位编号", example = "1024") private Long id; - @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆") + @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "后端开发工程师") @NotBlank(message = "岗位名称不能为空") @Size(max = 50, message = "岗位名称长度不能超过 50 个字符") private String name; - @Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "rdms") + @Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "backend") @NotBlank(message = "岗位编码不能为空") - @Size(max = 64, message = "岗位编码长度不能超过64个字符") + @Size(max = 64, message = "岗位编码长度不能超过 64 个字符") private String code; - @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @Schema(description = "岗位类型", example = "technical") + @Size(max = 20, message = "岗位类型长度不能超过 20 个字符") + private String postType; + + @Schema(description = "岗位级别", example = "8") + private Integer levelRank; + + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "显示顺序不能为空") private Integer sort; @@ -33,7 +40,7 @@ public class PostSaveReqVO { @InEnum(CommonStatusEnum.class) private Integer status; - @Schema(description = "备注", example = "快乐的备注") + @Schema(description = "备注", example = "技术序列岗位") private String remark; -} \ No newline at end of file +} diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/oauth2/OAuth2UserController.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/oauth2/OAuth2UserController.java index 38da20e..f23cd36 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/oauth2/OAuth2UserController.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/oauth2/OAuth2UserController.java @@ -1,6 +1,5 @@ package com.njcn.rdms.module.system.controller.admin.oauth2; -import cn.hutool.core.collection.CollUtil; import com.njcn.rdms.framework.common.pojo.CommonResult; import com.njcn.rdms.framework.common.util.object.BeanUtils; import com.njcn.rdms.module.system.controller.admin.oauth2.vo.user.OAuth2UserInfoRespVO; @@ -14,14 +13,16 @@ import com.njcn.rdms.module.system.service.dept.PostService; import com.njcn.rdms.module.system.service.user.AdminUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import java.util.List; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import static com.njcn.rdms.framework.common.pojo.CommonResult.success; import static com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -50,7 +51,7 @@ public class OAuth2UserController { @GetMapping("/get") @Operation(summary = "获得用户基本信息") - @PreAuthorize("@ss.hasScope('user.read')") // + @PreAuthorize("@ss.hasScope('user.read')") public CommonResult getUserInfo() { // 获得用户基本信息 AdminUserDO user = userService.getUser(getLoginUserId()); @@ -60,10 +61,10 @@ public class OAuth2UserController { DeptDO dept = deptService.getDept(user.getDeptId()); resp.setDept(BeanUtils.toBean(dept, OAuth2UserInfoRespVO.Dept.class)); } - // 获得岗位信息 - if (CollUtil.isNotEmpty(user.getPostIds())) { - List posts = postService.getPostList(user.getPostIds()); - resp.setPosts(BeanUtils.toBean(posts, OAuth2UserInfoRespVO.Post.class)); + // 获得主岗位信息 + if (user.getPositionId() != null) { + PostDO position = postService.getPost(user.getPositionId()); + resp.setPosition(BeanUtils.toBean(position, OAuth2UserInfoRespVO.Post.class)); } return success(resp); } @@ -72,8 +73,7 @@ public class OAuth2UserController { @Operation(summary = "更新用户基本信息") @PreAuthorize("@ss.hasScope('user.write')") public CommonResult updateUserInfo(@Valid @RequestBody OAuth2UserUpdateReqVO reqVO) { - // 这里将 UserProfileUpdateReqVO =》UserProfileUpdateReqVO 对象,实现接口的复用。 - // 主要是,AdminUserService 没有自己的 BO 对象,所以复用只能这么做 + // 这里将 OAuth2UserUpdateReqVO 转成 UserProfileUpdateReqVO,实现接口复用 userService.updateUserProfile(getLoginUserId(), BeanUtils.toBean(reqVO, UserProfileUpdateReqVO.class)); return success(true); } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java index 1d36ea5..c05f28b 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java @@ -5,8 +5,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import java.util.List; - @Schema(description = "管理后台 - OAuth2 获得用户基本信息 Response VO") @Data @NoArgsConstructor @@ -24,6 +22,7 @@ public class OAuth2UserInfoRespVO { @Schema(description = "用户邮箱", example = "rdms@iocoder.cn") private String email; + @Schema(description = "手机号码", example = "15601691300") private String mobile; @@ -39,9 +38,9 @@ public class OAuth2UserInfoRespVO { private Dept dept; /** - * 所属岗位数组 + * 主岗位 */ - private List posts; + private Post position; @Schema(description = "部门") @Data diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/UserController.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/UserController.java index ed75f98..f6c8c18 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/UserController.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/UserController.java @@ -7,12 +7,21 @@ import com.njcn.rdms.framework.common.pojo.CommonResult; import com.njcn.rdms.framework.common.pojo.PageParam; import com.njcn.rdms.framework.common.pojo.PageResult; import com.njcn.rdms.framework.excel.core.util.ExcelUtils; -import com.njcn.rdms.module.system.controller.admin.user.vo.user.*; +import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserImportExcelVO; +import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserImportRespVO; +import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserPageReqVO; +import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserRespVO; +import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserSaveReqVO; +import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserSimpleRespVO; +import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserUpdatePasswordReqVO; +import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserUpdateStatusReqVO; import com.njcn.rdms.module.system.convert.user.UserConvert; import com.njcn.rdms.module.system.dal.dataobject.dept.DeptDO; +import com.njcn.rdms.module.system.dal.dataobject.dept.PostDO; import com.njcn.rdms.module.system.dal.dataobject.user.AdminUserDO; import com.njcn.rdms.module.system.enums.common.SexEnum; import com.njcn.rdms.module.system.service.dept.DeptService; +import com.njcn.rdms.module.system.service.dept.PostService; import com.njcn.rdms.module.system.service.user.AdminUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -23,7 +32,14 @@ import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; @@ -45,6 +61,8 @@ public class UserController { private AdminUserService userService; @Resource private DeptService deptService; + @Resource + private PostService postService; @PostMapping("/create") @Operation(summary = "新增用户") @@ -105,11 +123,10 @@ public class UserController { if (CollUtil.isEmpty(pageResult.getList())) { return success(new PageResult<>(pageResult.getTotal())); } - // 拼接数据 - Map deptMap = deptService.getDeptMap( - convertList(pageResult.getList(), AdminUserDO::getDeptId)); - return success(new PageResult<>(UserConvert.INSTANCE.convertList(pageResult.getList(), deptMap), - pageResult.getTotal())); + // 拼接部门、主岗位信息 + Map deptMap = deptService.getDeptMap(convertList(pageResult.getList(), AdminUserDO::getDeptId)); + Map postMap = postService.getPostMap(convertList(pageResult.getList(), AdminUserDO::getPositionId)); + return success(new PageResult<>(UserConvert.INSTANCE.convertList(pageResult.getList(), deptMap, postMap), pageResult.getTotal())); } @GetMapping({"/list-all-simple", "/simple-list"}) @@ -117,8 +134,7 @@ public class UserController { public CommonResult> getSimpleUserList() { List list = userService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus()); // 拼接数据 - Map deptMap = deptService.getDeptMap( - convertList(list, AdminUserDO::getDeptId)); + Map deptMap = deptService.getDeptMap(convertList(list, AdminUserDO::getDeptId)); return success(UserConvert.INSTANCE.convertSimpleList(list, deptMap)); } @@ -133,22 +149,22 @@ public class UserController { } // 拼接数据 DeptDO dept = deptService.getDept(user.getDeptId()); - return success(UserConvert.INSTANCE.convert(user, dept)); + PostDO position = user.getPositionId() != null ? postService.getPost(user.getPositionId()) : null; + return success(UserConvert.INSTANCE.convert(user, dept, position)); } @GetMapping("/export-excel") @Operation(summary = "导出用户") @PreAuthorize("@ss.hasPermission('system:user:export')") @ApiAccessLog(operateType = EXPORT) - public void exportUserList(@Validated UserPageReqVO exportReqVO, - HttpServletResponse response) throws IOException { + public void exportUserList(@Validated UserPageReqVO exportReqVO, HttpServletResponse response) throws IOException { exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); List list = userService.getUserPage(exportReqVO).getList(); // 输出 Excel - Map deptMap = deptService.getDeptMap( - convertList(list, AdminUserDO::getDeptId)); + Map deptMap = deptService.getDeptMap(convertList(list, AdminUserDO::getDeptId)); + Map postMap = postService.getPostMap(convertList(list, AdminUserDO::getPositionId)); ExcelUtils.write(response, "用户数据.xls", "数据", UserRespVO.class, - UserConvert.INSTANCE.convertList(list, deptMap)); + UserConvert.INSTANCE.convertList(list, deptMap, postMap)); } @GetMapping("/get-import-template") @@ -156,9 +172,9 @@ public class UserController { public void importTemplate(HttpServletResponse response) throws IOException { // 手动创建导出 demo List list = Arrays.asList( - UserImportExcelVO.builder().username("yunai").deptId(1L).email("yunai@iocoder.cn").mobile("15601691300") + UserImportExcelVO.builder().username("yunai").deptId(1L).positionId(1L).email("yunai@iocoder.cn").mobile("15601691300") .nickname("灿能").status(CommonStatusEnum.ENABLE.getStatus()).sex(SexEnum.MALE.getSex()).build(), - UserImportExcelVO.builder().username("yuanma").deptId(2L).email("yuanma@iocoder.cn").mobile("15601701300") + UserImportExcelVO.builder().username("yuanma").deptId(2L).positionId(2L).email("yuanma@iocoder.cn").mobile("15601701300") .nickname("源码").status(CommonStatusEnum.DISABLE.getStatus()).sex(SexEnum.FEMALE.getSex()).build() ); // 输出 @@ -168,7 +184,7 @@ public class UserController { @PostMapping("/import") @Operation(summary = "导入用户") @Parameters({ - @Parameter(name = "file", description = "Excel 文件", required = true), + @Parameter(name = "file", description = "导入文件", required = true), @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true") }) @PreAuthorize("@ss.hasPermission('system:user:import')") diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/UserProfileController.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/UserProfileController.java index 736db57..202bce7 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/UserProfileController.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/UserProfileController.java @@ -1,6 +1,5 @@ package com.njcn.rdms.module.system.controller.admin.user; -import cn.hutool.core.collection.CollUtil; import com.njcn.rdms.framework.common.pojo.CommonResult; import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileRespVO; import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; @@ -21,7 +20,11 @@ import jakarta.annotation.Resource; import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.List; @@ -55,9 +58,9 @@ public class UserProfileController { List userRoles = roleService.getRoleListFromCache(permissionService.getUserRoleIdListByUserId(user.getId())); // 获得部门信息 DeptDO dept = user.getDeptId() != null ? deptService.getDept(user.getDeptId()) : null; - // 获得岗位信息 - List posts = CollUtil.isNotEmpty(user.getPostIds()) ? postService.getPostList(user.getPostIds()) : null; - return success(UserConvert.INSTANCE.convert(user, userRoles, dept, posts)); + // 获得主岗位信息 + PostDO position = user.getPositionId() != null ? postService.getPost(user.getPositionId()) : null; + return success(UserConvert.INSTANCE.convert(user, userRoles, dept, position)); } @PutMapping("/update") diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java index ba1975b..b30dcc2 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java @@ -47,13 +47,15 @@ public class UserProfileRespVO { * 所属角色 */ private List roles; + /** * 所在部门 */ private DeptSimpleRespVO dept; + /** - * 所属岗位数组 + * 主岗位 */ - private List posts; + private PostSimpleRespVO position; } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserImportExcelVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserImportExcelVO.java index 0327aa6..4bbae50 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserImportExcelVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserImportExcelVO.java @@ -1,9 +1,9 @@ package com.njcn.rdms.module.system.controller.admin.user.vo.user; +import cn.idev.excel.annotation.ExcelProperty; import com.njcn.rdms.framework.excel.core.annotations.DictFormat; import com.njcn.rdms.framework.excel.core.convert.DictConvert; import com.njcn.rdms.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -27,6 +27,9 @@ public class UserImportExcelVO { @ExcelProperty("部门编号") private Long deptId; + @ExcelProperty("主岗位编号") + private Long positionId; + @ExcelProperty("用户邮箱") private String email; diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserRespVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserRespVO.java index 06bba51..839a761 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserRespVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserRespVO.java @@ -1,20 +1,19 @@ package com.njcn.rdms.module.system.controller.admin.user.vo.user; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import com.njcn.rdms.framework.excel.core.annotations.DictFormat; import com.njcn.rdms.framework.excel.core.convert.DictConvert; import com.njcn.rdms.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; -import java.util.Set; @Schema(description = "管理后台 - 用户信息 Response VO") @Data @ExcelIgnoreUnannotated -public class UserRespVO{ +public class UserRespVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @ExcelProperty("用户编号") @@ -31,14 +30,19 @@ public class UserRespVO{ @Schema(description = "备注", example = "我是一个用户") private String remark; - @Schema(description = "部门ID", example = "我是一个用户") + @Schema(description = "部门编号", example = "1") private Long deptId; + @Schema(description = "部门名称", example = "IT 部") @ExcelProperty("部门名称") private String deptName; - @Schema(description = "岗位编号数组", example = "1") - private Set postIds; + @Schema(description = "主岗位编号", example = "1") + private Long positionId; + + @Schema(description = "主岗位名称", example = "后端开发工程师") + @ExcelProperty("主岗位") + private String positionName; @Schema(description = "用户邮箱", example = "rdms@iocoder.cn") @ExcelProperty("用户邮箱") @@ -65,6 +69,9 @@ public class UserRespVO{ @ExcelProperty("最后登录IP") private String loginIp; + @Schema(description = "离职时间", example = "2026-03-19 00:00:00") + private LocalDateTime resignedAt; + @Schema(description = "最后登录时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") @ExcelProperty("最后登录时间") private LocalDateTime loginDate; diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserSaveReqVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserSaveReqVO.java index ed757d8..63f10b8 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserSaveReqVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserSaveReqVO.java @@ -1,18 +1,23 @@ package com.njcn.rdms.module.system.controller.admin.user.vo.user; import cn.hutool.core.util.ObjectUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.mzt.logapi.starter.annotation.DiffLogField; import com.njcn.rdms.framework.common.validation.Mobile; import com.njcn.rdms.module.system.framework.operatelog.core.DeptParseFunction; import com.njcn.rdms.module.system.framework.operatelog.core.PostParseFunction; import com.njcn.rdms.module.system.framework.operatelog.core.SexParseFunction; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.*; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; import lombok.Data; import org.hibernate.validator.constraints.Length; -import java.util.Set; +import java.time.LocalDateTime; @Schema(description = "管理后台 - 用户创建/修改 Request VO") @Data @@ -23,13 +28,13 @@ public class UserSaveReqVO { @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "rdms") @NotBlank(message = "用户账号不能为空") - @Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成") + @Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由数字、字母组成") @Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符") @DiffLogField(name = "用户账号") private String username; @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "awen") - @Size(max = 30, message = "用户昵称长度不能超过30个字符") + @Size(max = 30, message = "用户昵称长度不能超过 30 个字符") @DiffLogField(name = "用户昵称") private String nickname; @@ -37,13 +42,19 @@ public class UserSaveReqVO { @DiffLogField(name = "备注") private String remark; - @Schema(description = "部门编号", example = "我是一个用户") + @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "部门不能为空") @DiffLogField(name = "部门", function = DeptParseFunction.NAME) private Long deptId; - @Schema(description = "岗位编号数组", example = "1") - @DiffLogField(name = "岗位", function = PostParseFunction.NAME) - private Set postIds; + @Schema(description = "主岗位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "主岗位不能为空") + @DiffLogField(name = "主岗位", function = PostParseFunction.NAME) + private Long positionId; + + @Schema(description = "离职时间", example = "2026-03-19 00:00:00") + @DiffLogField(name = "离职时间") + private LocalDateTime resignedAt; @Schema(description = "用户邮箱", example = "rdms@iocoder.cn") @Email(message = "邮箱格式不正确") @@ -74,7 +85,7 @@ public class UserSaveReqVO { @JsonIgnore public boolean isPasswordValid() { return id != null // 修改时,不需要传递 - || (ObjectUtil.isAllNotEmpty(password)); // 新增时,必须都传递 password + || ObjectUtil.isAllNotEmpty(password); // 新增时,必须传递 password } } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/convert/user/UserConvert.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/convert/user/UserConvert.java index ccb03af..b7c0f02 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/convert/user/UserConvert.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/convert/user/UserConvert.java @@ -24,15 +24,18 @@ public interface UserConvert { UserConvert INSTANCE = Mappers.getMapper(UserConvert.class); - default List convertList(List list, Map deptMap) { - return CollectionUtils.convertList(list, user -> convert(user, deptMap.get(user.getDeptId()))); + default List convertList(List list, Map deptMap, Map postMap) { + return CollectionUtils.convertList(list, user -> convert(user, deptMap.get(user.getDeptId()), postMap.get(user.getPositionId()))); } - default UserRespVO convert(AdminUserDO user, DeptDO dept) { + default UserRespVO convert(AdminUserDO user, DeptDO dept, PostDO position) { UserRespVO userVO = BeanUtils.toBean(user, UserRespVO.class); if (dept != null) { userVO.setDeptName(dept.getName()); } + if (position != null) { + userVO.setPositionName(position.getName()); + } return userVO; } @@ -44,12 +47,11 @@ public interface UserConvert { }); } - default UserProfileRespVO convert(AdminUserDO user, List userRoles, - DeptDO dept, List posts) { + default UserProfileRespVO convert(AdminUserDO user, List userRoles, DeptDO dept, PostDO position) { UserProfileRespVO userVO = BeanUtils.toBean(user, UserProfileRespVO.class); userVO.setRoles(BeanUtils.toBean(userRoles, RoleSimpleRespVO.class)); userVO.setDept(BeanUtils.toBean(dept, DeptSimpleRespVO.class)); - userVO.setPosts(BeanUtils.toBean(posts, PostSimpleRespVO.class)); + userVO.setPosition(BeanUtils.toBean(position, PostSimpleRespVO.class)); return userVO; } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/dept/DeptDO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/dept/DeptDO.java index 5117a1d..c4ebb1f 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/dept/DeptDO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/dept/DeptDO.java @@ -36,6 +36,22 @@ public class DeptDO extends BaseDO { * 关联 {@link #id} */ private Long parentId; + /** + * 组织节点类型 + */ + private String orgType; + /** + * 组织物化路径 + */ + private String path; + /** + * 组织层级 + */ + private Integer level; + /** + * 组织编码 + */ + private String code; /** * 显示顺序 */ diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/dept/PostDO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/dept/PostDO.java index 7c66c3e..47632ef 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/dept/PostDO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/dept/PostDO.java @@ -1,9 +1,9 @@ package com.njcn.rdms.module.system.dal.dataobject.dept; -import com.njcn.rdms.framework.common.enums.CommonStatusEnum; -import com.njcn.rdms.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.njcn.rdms.framework.common.enums.CommonStatusEnum; +import com.njcn.rdms.framework.mybatis.core.dataobject.BaseDO; import lombok.Data; import lombok.EqualsAndHashCode; @@ -17,29 +17,41 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) public class PostDO extends BaseDO { - /** - * 岗位序号 - */ @TableId private Long id; + /** * 岗位名称 */ private String name; + /** * 岗位编码 */ private String code; + + /** + * 岗位类型 + */ + private String postType; + + /** + * 岗位级别 + */ + private Integer levelRank; + /** * 岗位排序 */ private Integer sort; + /** * 状态 * * 枚举 {@link CommonStatusEnum} */ private Integer status; + /** * 备注 */ diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/user/AdminUserDO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/user/AdminUserDO.java index c763704..8056969 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/user/AdminUserDO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/dataobject/user/AdminUserDO.java @@ -1,17 +1,18 @@ package com.njcn.rdms.module.system.dal.dataobject.user; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; import com.njcn.rdms.framework.common.enums.CommonStatusEnum; import com.njcn.rdms.framework.mybatis.core.dataobject.BaseDO; import com.njcn.rdms.module.system.enums.common.SexEnum; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import java.time.LocalDateTime; -import java.util.Set; /** * 管理后台的用户 DO @@ -27,65 +28,82 @@ import java.util.Set; public class AdminUserDO extends BaseDO { /** - * 用户ID + * 用户 ID */ @TableId private Long id; + /** * 用户账号 */ private String username; + /** * 加密后的密码 * * 因为目前使用 {@link BCryptPasswordEncoder} 加密器,所以无需自己处理 salt 盐 */ private String password; + /** * 用户昵称 */ private String nickname; + /** * 备注 */ private String remark; + /** * 部门 ID */ private Long deptId; + /** - * 岗位编号数组 + * 主岗位编号 */ - @TableField(typeHandler = JacksonTypeHandler.class) - private Set postIds; + private Long positionId; + + /** + * 离职时间 + */ + private LocalDateTime resignedAt; + /** * 用户邮箱 */ private String email; + /** * 手机号码 */ private String mobile; + /** * 用户性别 * * 枚举类 {@link SexEnum} */ private Integer sex; + /** * 用户头像 */ private String avatar; + /** * 帐号状态 * * 枚举 {@link CommonStatusEnum} */ private Integer status; + /** - * 最后登录IP + * 最后登录 IP */ private String loginIp; + /** * 最后登录时间 */ diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/dept/DeptMapper.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/dept/DeptMapper.java index 06986e0..db89053 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/dept/DeptMapper.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/dept/DeptMapper.java @@ -15,6 +15,7 @@ public interface DeptMapper extends BaseMapperX { default List selectList(DeptListReqVO reqVO) { return selectList(new LambdaQueryWrapperX() .likeIfPresent(DeptDO::getName, reqVO.getName()) + .eqIfPresent(DeptDO::getOrgType, reqVO.getOrgType()) .eqIfPresent(DeptDO::getStatus, reqVO.getStatus())); } @@ -22,6 +23,10 @@ public interface DeptMapper extends BaseMapperX { return selectOne(DeptDO::getParentId, parentId, DeptDO::getName, name); } + default DeptDO selectByCode(String code) { + return selectOne(DeptDO::getCode, code); + } + default Long selectCountByParentId(Long parentId) { return selectCount(DeptDO::getParentId, parentId); } @@ -34,4 +39,8 @@ public interface DeptMapper extends BaseMapperX { return selectList(DeptDO::getLeaderUserId, id); } + default List selectListByPathPrefix(String pathPrefix) { + return selectList(new LambdaQueryWrapperX().likeRight(DeptDO::getPath, pathPrefix)); + } + } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/user/AdminUserMapper.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/user/AdminUserMapper.java index 1eb11dd..bcf3a53 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/user/AdminUserMapper.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/dal/mysql/user/AdminUserMapper.java @@ -48,4 +48,8 @@ public interface AdminUserMapper extends BaseMapperX { return selectList(AdminUserDO::getDeptId, deptIds); } + default List selectListByPositionIds(Collection positionIds) { + return selectList(AdminUserDO::getPositionId, positionIds); + } + } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/dept/DeptServiceImpl.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/dept/DeptServiceImpl.java index c99d918..957ebf0 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/dept/DeptServiceImpl.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/dept/DeptServiceImpl.java @@ -2,6 +2,7 @@ package com.njcn.rdms.module.system.service.dept; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import com.njcn.rdms.framework.common.enums.CommonStatusEnum; import com.njcn.rdms.framework.common.util.object.BeanUtils; import com.njcn.rdms.module.system.controller.admin.dept.vo.dept.DeptListReqVO; @@ -9,15 +10,24 @@ import com.njcn.rdms.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO; import com.njcn.rdms.module.system.dal.dataobject.dept.DeptDO; import com.njcn.rdms.module.system.dal.mysql.dept.DeptMapper; import com.njcn.rdms.module.system.dal.redis.RedisKeyConstants; +import com.njcn.rdms.module.system.enums.dept.DeptOrgTypeEnum; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.njcn.rdms.framework.common.util.collection.CollectionUtils.convertSet; @@ -37,40 +47,50 @@ public class DeptServiceImpl implements DeptService { private DeptMapper deptMapper; @Override + @Transactional(rollbackFor = Exception.class) @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存 public Long createDept(DeptSaveReqVO createReqVO) { - if (createReqVO.getParentId() == null) { - createReqVO.setParentId(DeptDO.PARENT_ID_ROOT); - } + normalizeDeptCreateReq(createReqVO); // 校验父部门的有效性 validateParentDept(null, createReqVO.getParentId()); // 校验部门名的唯一性 validateDeptNameUnique(null, createReqVO.getParentId(), createReqVO.getName()); + // 校验组织编码唯一性 + validateDeptCodeUnique(null, createReqVO.getCode()); + // 校验组织节点类型 + validateDeptOrgType(createReqVO.getOrgType()); // 插入部门 DeptDO dept = BeanUtils.toBean(createReqVO, DeptDO.class); deptMapper.insert(dept); + fillDeptTreeFields(dept, createReqVO.getParentId()); + deptMapper.updateById(dept); return dept.getId(); } @Override + @Transactional(rollbackFor = Exception.class) @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存 public void updateDept(DeptSaveReqVO updateReqVO) { - if (updateReqVO.getParentId() == null) { - updateReqVO.setParentId(DeptDO.PARENT_ID_ROOT); - } // 校验自己存在 - validateDeptExists(updateReqVO.getId()); + DeptDO oldDept = validateDeptExists(updateReqVO.getId()); + normalizeDeptUpdateReq(updateReqVO, oldDept); // 校验父部门的有效性 validateParentDept(updateReqVO.getId(), updateReqVO.getParentId()); // 校验部门名的唯一性 validateDeptNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); + // 校验组织编码唯一性 + validateDeptCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + // 校验组织节点类型 + validateDeptOrgType(updateReqVO.getOrgType()); // 更新部门 DeptDO updateObj = BeanUtils.toBean(updateReqVO, DeptDO.class); + fillDeptTreeFields(updateObj, updateReqVO.getParentId()); deptMapper.updateById(updateObj); + updateChildDeptTree(updateObj.getId(), oldDept.getPath(), oldDept.getLevel(), updateObj.getPath(), updateObj.getLevel()); } @Override @@ -103,14 +123,15 @@ public class DeptServiceImpl implements DeptService { } @VisibleForTesting - void validateDeptExists(Long id) { + DeptDO validateDeptExists(Long id) { if (id == null) { - return; + return null; } DeptDO dept = deptMapper.selectById(id); if (dept == null) { throw exception(DEPT_NOT_FOUND); } + return dept; } @VisibleForTesting @@ -163,6 +184,27 @@ public class DeptServiceImpl implements DeptService { } } + @VisibleForTesting + void validateDeptCodeUnique(Long id, String code) { + if (StrUtil.isBlank(code)) { + return; + } + DeptDO dept = deptMapper.selectByCode(code); + if (dept == null) { + return; + } + if (id == null || ObjectUtil.notEqual(dept.getId(), id)) { + throw exception(DEPT_CODE_DUPLICATE, code); + } + } + + @VisibleForTesting + void validateDeptOrgType(String orgType) { + if (!DeptOrgTypeEnum.isValid(orgType)) { + throw exception(DEPT_ORG_TYPE_INVALID, orgType); + } + } + @Override public DeptDO getDept(Long id) { return deptMapper.selectById(id); @@ -179,7 +221,7 @@ public class DeptServiceImpl implements DeptService { @Override public List getDeptList(DeptListReqVO reqVO) { List list = deptMapper.selectList(reqVO); - list.sort(Comparator.comparing(DeptDO::getSort)); + list.sort(Comparator.comparing(DeptDO::getSort).thenComparing(DeptDO::getId)); return list; } @@ -233,4 +275,59 @@ public class DeptServiceImpl implements DeptService { }); } + private void normalizeDeptCreateReq(DeptSaveReqVO reqVO) { + if (reqVO.getParentId() == null) { + reqVO.setParentId(DeptDO.PARENT_ID_ROOT); + } + if (StrUtil.isBlank(reqVO.getOrgType())) { + reqVO.setOrgType(DeptOrgTypeEnum.defaultType()); + } + if (StrUtil.isBlank(reqVO.getCode())) { + reqVO.setCode(null); + } + } + + private void normalizeDeptUpdateReq(DeptSaveReqVO reqVO, DeptDO oldDept) { + if (reqVO.getParentId() == null) { + reqVO.setParentId(DeptDO.PARENT_ID_ROOT); + } + if (StrUtil.isBlank(reqVO.getOrgType())) { + reqVO.setOrgType(StrUtil.blankToDefault(oldDept.getOrgType(), DeptOrgTypeEnum.defaultType())); + } + if (StrUtil.isBlank(reqVO.getCode())) { + reqVO.setCode(oldDept.getCode()); + } + } + + private void fillDeptTreeFields(DeptDO dept, Long parentId) { + String parentPath = "/"; + int parentLevel = 0; + if (!DeptDO.PARENT_ID_ROOT.equals(parentId)) { + DeptDO parentDept = deptMapper.selectById(parentId); + if (parentDept != null) { + parentPath = StrUtil.blankToDefault(parentDept.getPath(), "/" + parentDept.getId() + "/"); + parentLevel = ObjectUtil.defaultIfNull(parentDept.getLevel(), 1); + } + } + dept.setPath(parentPath + dept.getId() + "/"); + dept.setLevel(parentLevel + 1); + } + + private void updateChildDeptTree(Long deptId, String oldPath, Integer oldLevel, String newPath, Integer newLevel) { + if (StrUtil.equals(oldPath, newPath) && Objects.equals(oldLevel, newLevel)) { + return; + } + List children = deptMapper.selectListByPathPrefix(oldPath); + children.removeIf(dept -> Objects.equals(dept.getId(), deptId)); + if (CollUtil.isEmpty(children)) { + return; + } + int levelDiff = ObjectUtil.defaultIfNull(newLevel, 1) - ObjectUtil.defaultIfNull(oldLevel, 1); + children.forEach(child -> { + child.setPath(newPath + StrUtil.removePrefix(child.getPath(), oldPath)); + child.setLevel(ObjectUtil.defaultIfNull(child.getLevel(), 1) + levelDiff); + }); + deptMapper.updateBatch(children); + } + } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/dept/PostService.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/dept/PostService.java index dfb598e..c5a6a78 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/dept/PostService.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/dept/PostService.java @@ -1,13 +1,17 @@ package com.njcn.rdms.module.system.service.dept; +import cn.hutool.core.collection.CollUtil; import com.njcn.rdms.framework.common.pojo.PageResult; +import com.njcn.rdms.framework.common.util.collection.CollectionUtils; import com.njcn.rdms.module.system.controller.admin.dept.vo.post.PostPageReqVO; import com.njcn.rdms.module.system.controller.admin.dept.vo.post.PostSaveReqVO; import com.njcn.rdms.module.system.dal.dataobject.dept.PostDO; import org.springframework.lang.Nullable; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * 岗位 Service 接口 @@ -49,7 +53,7 @@ public interface PostService { * 获得岗位列表 * * @param ids 岗位编号数组 - * @return 部门列表 + * @return 岗位列表 */ List getPostList(@Nullable Collection ids); @@ -58,16 +62,15 @@ public interface PostService { * * @param ids 岗位编号数组。如果为空,不进行筛选 * @param statuses 状态数组。如果为空,不进行筛选 - * @return 部门列表 + * @return 岗位列表 */ - List getPostList(@Nullable Collection ids, - @Nullable Collection statuses); + List getPostList(@Nullable Collection ids, @Nullable Collection statuses); /** * 获得岗位分页列表 * * @param reqVO 分页条件 - * @return 部门分页列表 + * @return 岗位分页列表 */ PageResult getPostPage(PostPageReqVO reqVO); @@ -79,6 +82,19 @@ public interface PostService { */ PostDO getPost(Long id); + /** + * 获得岗位 Map + * + * @param ids 岗位编号数组 + * @return 岗位 Map + */ + default Map getPostMap(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return new HashMap<>(); + } + return CollectionUtils.convertMap(getPostList(ids), PostDO::getId); + } + /** * 校验岗位们是否有效。如下情况,视为无效: * 1. 岗位编号不存在 diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/user/AdminUserService.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/user/AdminUserService.java index b3fa622..d113c14 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/user/AdminUserService.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/user/AdminUserService.java @@ -49,10 +49,10 @@ public interface AdminUserService { void updateUser(@Valid UserSaveReqVO updateReqVO); /** - * 更新用户的最后登陆信息 + * 更新用户的最后登录信息 * * @param id 用户编号 - * @param loginIp 登陆 IP + * @param loginIp 登录 IP */ void updateUserLogin(Long id, String loginIp); @@ -75,7 +75,7 @@ public interface AdminUserService { /** * 修改密码 * - * @param id 用户编号 + * @param id 用户编号 * @param password 密码 */ void updateUserPassword(Long id, String password); @@ -83,7 +83,7 @@ public interface AdminUserService { /** * 修改状态 * - * @param id 用户编号 + * @param id 用户编号 * @param status 状态 */ void updateUserStatus(Long id, Integer status); @@ -129,7 +129,7 @@ public interface AdminUserService { /** * 通过用户 ID 查询用户 * - * @param id 用户ID + * @param id 用户 ID * @return 用户对象信息 */ AdminUserDO getUser(Long id); @@ -191,7 +191,7 @@ public interface AdminUserService { /** * 批量导入用户 * - * @param importUsers 导入用户列表 + * @param importUsers 导入用户列表 * @param isUpdateSupport 是否支持更新 * @return 导入结果 */ diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/user/AdminUserServiceImpl.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/user/AdminUserServiceImpl.java index aeac95b..2ca4df5 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/user/AdminUserServiceImpl.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/user/AdminUserServiceImpl.java @@ -1,9 +1,12 @@ package com.njcn.rdms.module.system.service.user; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; +import com.google.common.annotations.VisibleForTesting; +import com.mzt.logapi.context.LogRecordContext; +import com.mzt.logapi.service.impl.DiffParseFunction; +import com.mzt.logapi.starter.annotation.LogRecord; import com.njcn.rdms.framework.common.enums.CommonStatusEnum; import com.njcn.rdms.framework.common.enums.UserTypeEnum; import com.njcn.rdms.framework.common.exception.ServiceException; @@ -11,7 +14,6 @@ import com.njcn.rdms.framework.common.pojo.PageResult; import com.njcn.rdms.framework.common.util.collection.CollectionUtils; import com.njcn.rdms.framework.common.util.object.BeanUtils; import com.njcn.rdms.framework.common.util.validation.ValidationUtils; -import com.njcn.rdms.module.system.api.config.ConfigApi; import com.njcn.rdms.module.system.controller.admin.auth.vo.AuthRegisterReqVO; import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; @@ -19,20 +21,15 @@ import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserImportExcel import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserImportRespVO; import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserPageReqVO; import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserSaveReqVO; +import com.njcn.rdms.module.system.dal.dataobject.config.ConfigDO; import com.njcn.rdms.module.system.dal.dataobject.dept.DeptDO; -import com.njcn.rdms.module.system.dal.dataobject.dept.UserPostDO; import com.njcn.rdms.module.system.dal.dataobject.user.AdminUserDO; -import com.njcn.rdms.module.system.dal.mysql.dept.UserPostMapper; import com.njcn.rdms.module.system.dal.mysql.user.AdminUserMapper; +import com.njcn.rdms.module.system.service.config.ConfigService; import com.njcn.rdms.module.system.service.dept.DeptService; import com.njcn.rdms.module.system.service.dept.PostService; import com.njcn.rdms.module.system.service.oauth2.OAuth2TokenService; import com.njcn.rdms.module.system.service.permission.PermissionService; - -import com.google.common.annotations.VisibleForTesting; -import com.mzt.logapi.context.LogRecordContext; -import com.mzt.logapi.service.impl.DiffParseFunction; -import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; import jakarta.validation.ConstraintViolationException; import lombok.extern.slf4j.Slf4j; @@ -42,13 +39,35 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.exception; -import static com.njcn.rdms.framework.common.util.collection.CollectionUtils.*; -import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.*; -import static com.njcn.rdms.module.system.enums.LogRecordConstants.*; +import static com.njcn.rdms.framework.common.util.collection.CollectionUtils.singleton; +import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_EMAIL_EXISTS; +import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_IMPORT_INIT_PASSWORD; +import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_IMPORT_LIST_IS_EMPTY; +import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_IS_DISABLE; +import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_MOBILE_EXISTS; +import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; +import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_PASSWORD_FAILED; +import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_REGISTER_DISABLED; +import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.USER_USERNAME_EXISTS; +import static com.njcn.rdms.module.system.enums.LogRecordConstants.SYSTEM_USER_CREATE_SUB_TYPE; +import static com.njcn.rdms.module.system.enums.LogRecordConstants.SYSTEM_USER_CREATE_SUCCESS; +import static com.njcn.rdms.module.system.enums.LogRecordConstants.SYSTEM_USER_DELETE_SUB_TYPE; +import static com.njcn.rdms.module.system.enums.LogRecordConstants.SYSTEM_USER_DELETE_SUCCESS; +import static com.njcn.rdms.module.system.enums.LogRecordConstants.SYSTEM_USER_TYPE; +import static com.njcn.rdms.module.system.enums.LogRecordConstants.SYSTEM_USER_UPDATE_PASSWORD_SUB_TYPE; +import static com.njcn.rdms.module.system.enums.LogRecordConstants.SYSTEM_USER_UPDATE_PASSWORD_SUCCESS; +import static com.njcn.rdms.module.system.enums.LogRecordConstants.SYSTEM_USER_UPDATE_SUB_TYPE; +import static com.njcn.rdms.module.system.enums.LogRecordConstants.SYSTEM_USER_UPDATE_SUCCESS; /** * 后台用户 Service 实现类 @@ -60,12 +79,10 @@ import static com.njcn.rdms.module.system.enums.LogRecordConstants.*; public class AdminUserServiceImpl implements AdminUserService { static final String USER_INIT_PASSWORD_KEY = "system.user.init-password"; - static final String USER_REGISTER_ENABLED_KEY = "system.user.register-enabled"; @Resource private AdminUserMapper userMapper; - @Resource private DeptService deptService; @Resource @@ -74,36 +91,25 @@ public class AdminUserServiceImpl implements AdminUserService { private PermissionService permissionService; @Resource private PasswordEncoder passwordEncoder; - @Resource - @Lazy // 懒加载,避免循环依赖 + @Lazy private OAuth2TokenService oauth2TokenService; - @Resource - private UserPostMapper userPostMapper; - - @Resource - private ConfigApi configApi; + private ConfigService configService; @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}", success = SYSTEM_USER_CREATE_SUCCESS) public Long createUser(UserSaveReqVO createReqVO) { - // 1.1 校验正确性 - validateUserForCreateOrUpdate(null, createReqVO.getUsername(), - createReqVO.getMobile(), createReqVO.getEmail(), createReqVO.getDeptId(), createReqVO.getPostIds()); - // 2.1 插入用户 + // 1. 校验正确性 + validateUserForCreateOrUpdate(null, createReqVO.getUsername(), createReqVO.getMobile(), + createReqVO.getEmail(), createReqVO.getDeptId(), createReqVO.getPositionId()); + // 2. 插入用户 AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class); user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 user.setPassword(encodePassword(createReqVO.getPassword())); // 加密密码 userMapper.insert(user); - // 2.2 插入关联岗位 - if (CollectionUtil.isNotEmpty(user.getPostIds())) { - userPostMapper.insertBatch(convertList(user.getPostIds(), - postId -> new UserPostDO().setUserId(user.getId()).setPostId(postId))); - } - // 3. 记录操作日志上下文 LogRecordContext.putVariable("user", user); return user.getId(); @@ -112,12 +118,12 @@ public class AdminUserServiceImpl implements AdminUserService { @Override public Long registerUser(AuthRegisterReqVO registerReqVO) { // 1.1 校验是否开启注册 - if (ObjUtil.notEqual(configApi.getConfigValueByKey(USER_REGISTER_ENABLED_KEY).getCheckedData(), "true")) { + if (ObjUtil.notEqual(getConfigValue(USER_REGISTER_ENABLED_KEY), "true")) { throw exception(USER_REGISTER_DISABLED); } // 1.2 校验正确性 - validateUserForCreateOrUpdate(null, registerReqVO.getUsername(), null, null, null, null); - + validateUserForCreateOrUpdate(null, registerReqVO.getUsername(), null, null, + registerReqVO.getDeptId(), registerReqVO.getPositionId()); // 2. 插入用户 AdminUserDO user = BeanUtils.toBean(registerReqVO, AdminUserDO.class); user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 @@ -134,36 +140,15 @@ public class AdminUserServiceImpl implements AdminUserService { updateReqVO.setPassword(null); // 特殊:此处不更新密码 // 1. 校验正确性 AdminUserDO oldUser = validateUserForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getUsername(), - updateReqVO.getMobile(), updateReqVO.getEmail(), updateReqVO.getDeptId(), updateReqVO.getPostIds()); - - // 2.1 更新用户 + updateReqVO.getMobile(), updateReqVO.getEmail(), updateReqVO.getDeptId(), updateReqVO.getPositionId()); + // 2. 更新用户 AdminUserDO updateObj = BeanUtils.toBean(updateReqVO, AdminUserDO.class); userMapper.updateById(updateObj); - // 2.2 更新岗位 - updateUserPost(updateReqVO, updateObj); - // 3. 记录操作日志上下文 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldUser, UserSaveReqVO.class)); LogRecordContext.putVariable("user", oldUser); } - private void updateUserPost(UserSaveReqVO reqVO, AdminUserDO updateObj) { - Long userId = reqVO.getId(); - Set dbPostIds = convertSet(userPostMapper.selectListByUserId(userId), UserPostDO::getPostId); - // 计算新增和删除的岗位编号 - Set postIds = CollUtil.emptyIfNull(updateObj.getPostIds()); - Collection createPostIds = CollUtil.subtract(postIds, dbPostIds); - Collection deletePostIds = CollUtil.subtract(dbPostIds, postIds); - // 执行新增和删除。对于已经授权的岗位,不用做任何处理 - if (!CollectionUtil.isEmpty(createPostIds)) { - userPostMapper.insertBatch(convertList(createPostIds, - postId -> new UserPostDO().setUserId(userId).setPostId(postId))); - } - if (!CollectionUtil.isEmpty(deletePostIds)) { - userPostMapper.deleteByUserIdAndPostId(userId, deletePostIds); - } - } - @Override public void updateUserLogin(Long id, String loginIp) { userMapper.updateById(new AdminUserDO().setId(id).setLoginIp(loginIp).setLoginDate(LocalDateTime.now())); @@ -181,7 +166,7 @@ public class AdminUserServiceImpl implements AdminUserService { @Override public void updateUserPassword(Long id, UserProfileUpdatePasswordReqVO reqVO) { - // 校验旧密码密码 + // 校验旧密码 validateOldPassword(id, reqVO.getOldPassword()); // 执行更新 AdminUserDO updateObj = new AdminUserDO().setId(id); @@ -195,13 +180,11 @@ public class AdminUserServiceImpl implements AdminUserService { public void updateUserPassword(Long id, String password) { // 1. 校验用户存在 AdminUserDO user = validateUserExists(id); - // 2. 更新密码 AdminUserDO updateObj = new AdminUserDO(); updateObj.setId(id); updateObj.setPassword(encodePassword(password)); // 加密密码 userMapper.updateById(updateObj); - // 3. 记录操作日志上下文 LogRecordContext.putVariable("user", user); LogRecordContext.putVariable("newPassword", updateObj.getPassword()); @@ -216,7 +199,6 @@ public class AdminUserServiceImpl implements AdminUserService { updateObj.setId(id); updateObj.setStatus(status); userMapper.updateById(updateObj); - // 如果是禁用用户,则删除其 Token 信息 if (CommonStatusEnum.isDisable(status)) { oauth2TokenService.removeAccessToken(id, UserTypeEnum.ADMIN.getValue()); @@ -230,14 +212,9 @@ public class AdminUserServiceImpl implements AdminUserService { public void deleteUser(Long id) { // 1. 校验用户存在 AdminUserDO user = validateUserExists(id); - - // 2.1 删除用户 + // 2. 删除用户及其关联数据 userMapper.deleteById(id); - // 2.2 删除用户关联数据 permissionService.processUserDeleted(id); - // 2.2 删除用户岗位 - userPostMapper.deleteByUserId(id); - // 3. 记录操作日志上下文 LogRecordContext.putVariable("user", user); } @@ -247,12 +224,8 @@ public class AdminUserServiceImpl implements AdminUserService { public void deleteUserList(List ids) { // 1. 批量删除用户 userMapper.deleteByIds(ids); - // 2. 批量删除用户关联数据 - ids.forEach(id -> { - permissionService.processUserDeleted(id); - userPostMapper.deleteByUserId(id); - }); + ids.forEach(permissionService::processUserDeleted); } @Override @@ -275,7 +248,6 @@ public class AdminUserServiceImpl implements AdminUserService { return PageResult.empty(); } } - // 分页查询 return userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()), userIds); } @@ -298,11 +270,7 @@ public class AdminUserServiceImpl implements AdminUserService { if (CollUtil.isEmpty(postIds)) { return Collections.emptyList(); } - Set userIds = convertSet(userPostMapper.selectListByPostIds(postIds), UserPostDO::getUserId); - if (CollUtil.isEmpty(userIds)) { - return Collections.emptyList(); - } - return userMapper.selectByIds(userIds); + return userMapper.selectListByPositionIds(postIds); } @Override @@ -318,7 +286,7 @@ public class AdminUserServiceImpl implements AdminUserService { if (CollUtil.isEmpty(ids)) { return; } - // 获得岗位信息 + // 获得用户信息 List users = userMapper.selectByIds(ids); Map userMap = CollectionUtils.convertMap(users, AdminUserDO::getId); // 校验 @@ -348,26 +316,26 @@ public class AdminUserServiceImpl implements AdminUserService { if (deptId == null) { return Collections.emptySet(); } - Set deptIds = convertSet(deptService.getChildDeptList(deptId), DeptDO::getId); + Set deptIds = CollectionUtils.convertSet(deptService.getChildDeptList(deptId), DeptDO::getId); deptIds.add(deptId); // 包括自身 return deptIds; } private AdminUserDO validateUserForCreateOrUpdate(Long id, String username, String mobile, String email, - Long deptId, Set postIds) { - // 校验用户存在 - AdminUserDO user = validateUserExists(id); - // 校验用户名唯一 - validateUsernameUnique(id, username); - // 校验手机号唯一 - validateMobileUnique(id, mobile); - // 校验邮箱唯一 - validateEmailUnique(id, email); - // 校验部门处于开启状态 - deptService.validateDeptList(CollectionUtils.singleton(deptId)); - // 校验岗位处于开启状态 - postService.validatePostList(postIds); - return user; + Long deptId, Long positionId) { + // 校验用户存在 + AdminUserDO user = validateUserExists(id); + // 校验用户名唯一 + validateUsernameUnique(id, username); + // 校验手机号唯一 + validateMobileUnique(id, mobile); + // 校验邮箱唯一 + validateEmailUnique(id, email); + // 校验部门处于开启状态 + deptService.validateDeptList(singleton(deptId)); + // 校验主岗位处于开启状态 + postService.validatePostList(singleton(positionId)); + return user; } @VisibleForTesting @@ -392,10 +360,7 @@ public class AdminUserServiceImpl implements AdminUserService { return; } // 如果 id 为空,说明不用比较是否为相同 id 的用户 - if (id == null) { - throw exception(USER_USERNAME_EXISTS); - } - if (!user.getId().equals(id)) { + if (id == null || !user.getId().equals(id)) { throw exception(USER_USERNAME_EXISTS); } } @@ -410,10 +375,7 @@ public class AdminUserServiceImpl implements AdminUserService { return; } // 如果 id 为空,说明不用比较是否为相同 id 的用户 - if (id == null) { - throw exception(USER_EMAIL_EXISTS); - } - if (!user.getId().equals(id)) { + if (id == null || !user.getId().equals(id)) { throw exception(USER_EMAIL_EXISTS); } } @@ -428,17 +390,15 @@ public class AdminUserServiceImpl implements AdminUserService { return; } // 如果 id 为空,说明不用比较是否为相同 id 的用户 - if (id == null) { - throw exception(USER_MOBILE_EXISTS); - } - if (!user.getId().equals(id)) { + if (id == null || !user.getId().equals(id)) { throw exception(USER_MOBILE_EXISTS); } } /** * 校验旧密码 - * @param id 用户 id + * + * @param id 用户 ID * @param oldPassword 旧密码 */ @VisibleForTesting @@ -453,19 +413,18 @@ public class AdminUserServiceImpl implements AdminUserService { } @Override - @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 + @Transactional(rollbackFor = Exception.class) public UserImportRespVO importUserList(List importUsers, boolean isUpdateSupport) { // 1.1 参数校验 if (CollUtil.isEmpty(importUsers)) { throw exception(USER_IMPORT_LIST_IS_EMPTY); } // 1.2 初始化密码不能为空 - String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY).getCheckedData(); + String initPassword = getConfigValue(USER_INIT_PASSWORD_KEY); if (StrUtil.isEmpty(initPassword)) { throw exception(USER_IMPORT_INIT_PASSWORD); } - - // 2. 遍历,逐个创建 or 更新 + // 2. 遍历,逐个创建或更新 UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>()) .updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build(); AtomicInteger index = new AtomicInteger(1); @@ -479,20 +438,19 @@ public class AdminUserServiceImpl implements AdminUserService { respVO.getFailureUsernames().put(key, ex.getMessage()); return; } - // 2.1.2 校验,判断是否有不符合的原因 + // 2.1.2 校验业务约束 try { validateUserForCreateOrUpdate(null, null, importUser.getMobile(), importUser.getEmail(), - importUser.getDeptId(), null); + importUser.getDeptId(), importUser.getPositionId()); } catch (ServiceException ex) { respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage()); return; } - - // 2.2.1 判断如果不存在,在进行插入 + // 2.2.1 判断如果不存在,则插入 AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername()); if (existUser == null) { userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class) - .setPassword(encodePassword(initPassword)).setPostIds(new HashSet<>())); // 设置默认密码及空岗位编号数组 + .setPassword(encodePassword(initPassword))); respVO.getCreateUsernames().add(importUser.getUsername()); return; } @@ -529,4 +487,15 @@ public class AdminUserServiceImpl implements AdminUserService { return passwordEncoder.encode(password); } + /** + * 读取 system 模块内部参数配置,避免同服务自调用 Feign。 + * + * @param key 配置键 + * @return 配置值 + */ + private String getConfigValue(String key) { + ConfigDO config = configService.getConfigByKey(key); + return config != null ? config.getValue() : null; + } + } diff --git a/rdms-system/rdms-system-boot/src/main/resources/sql/permission-v2/system_dept.sql b/rdms-system/rdms-system-boot/src/main/resources/sql/permission-v2/system_dept.sql new file mode 100644 index 0000000..c752020 --- /dev/null +++ b/rdms-system/rdms-system-boot/src/main/resources/sql/permission-v2/system_dept.sql @@ -0,0 +1,649 @@ +/* + Navicat Premium Dump SQL + + Source Server : localMysql + Source Server Type : MySQL + Source Server Version : 80043 (8.0.43) + Source Host : localhost:13306 + Source Schema : rdms + + Target Server Type : MySQL + Target Server Version : 80043 (8.0.43) + File Encoding : 65001 + + Date: 19/03/2026 14:23:55 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for system_dept +-- ---------------------------- +DROP TABLE IF EXISTS `system_dept`; +CREATE TABLE `system_dept` ( + `id` bigint NOT NULL COMMENT '部门id', + `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '部门名称', + `parent_id` bigint NOT NULL DEFAULT 0 COMMENT '父部门id', + `org_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'dept' COMMENT '组织节点类型:company/dept/direction/team', + `path` varchar(1024) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '/' COMMENT '组织物化路径,格式如 /1/2/3/', + `level` int NOT NULL DEFAULT 1 COMMENT '组织层级,根节点为 1', + `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '组织编码', + `sort` int NOT NULL DEFAULT 0 COMMENT '显示顺序', + `leader_user_id` bigint NULL DEFAULT NULL COMMENT '负责人', + `phone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '联系电话', + `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '邮箱', + `status` tinyint NOT NULL COMMENT '部门状态(0正常 1停用)', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uk_system_dept_code`(`code` ASC) USING BTREE, + INDEX `idx_system_dept_parent_id`(`parent_id` ASC) USING BTREE, + INDEX `idx_system_dept_org_type`(`org_type` ASC) USING BTREE, + INDEX `idx_system_dept_path`(`path`(191) ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '部门表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of system_dept +-- ---------------------------- +INSERT INTO `system_dept` VALUES (100, '灿能源码', 0, 'dept', '/100/', 1, NULL, 0, 1, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2026-03-19 13:58:49', b'0'); +INSERT INTO `system_dept` VALUES (101, '深圳总公司', 100, 'dept', '/100/101/', 2, NULL, 1, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2026-03-19 14:22:19', b'0'); +INSERT INTO `system_dept` VALUES (103, '研发部门', 101, 'dept', '/100/101/103/', 3, NULL, 1, 1, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2026-03-19 13:58:49', b'0'); +INSERT INTO `system_dept` VALUES (107, '运维部门', 101, 'dept', '/100/101/107/', 3, NULL, 5, 1, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2026-03-19 13:58:49', b'0'); +INSERT INTO `system_dept` VALUES (112, '产品部门', 101, 'dept', '/100/101/112/', 3, NULL, 100, 1, NULL, NULL, 1, '1', '2023-12-02 09:45:13', '1', '2026-03-19 13:58:49', b'0'); + +-- ---------------------------- +-- Table structure for system_menu +-- ---------------------------- +DROP TABLE IF EXISTS `system_menu`; +CREATE TABLE `system_menu` ( + `id` bigint NOT NULL COMMENT '菜单ID', + `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '菜单名称', + `permission` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '权限标识', + `type` tinyint NOT NULL COMMENT '菜单类型', + `sort` int NOT NULL DEFAULT 0 COMMENT '显示顺序', + `parent_id` bigint NOT NULL DEFAULT 0 COMMENT '父菜单ID', + `path` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '路由地址', + `icon` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '#' COMMENT '菜单图标', + `component` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '组件路径', + `component_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '组件名', + `status` tinyint NOT NULL DEFAULT 0 COMMENT '菜单状态', + `visible` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否可见', + `keep_alive` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否缓存', + `always_show` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否总是显示', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of system_menu +-- ---------------------------- +INSERT INTO `system_menu` VALUES (1, '系统管理', '', 1, 10, 0, '/system', 'ep:tools', NULL, NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2025-03-15 21:30:27', b'0'); +INSERT INTO `system_menu` VALUES (2, '基础设施', '', 1, 20, 0, '/infra', 'ep:monitor', NULL, NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-03-01 08:28:40', b'0'); +INSERT INTO `system_menu` VALUES (5, 'OA 示例', '', 1, 40, 1185, 'oa', 'fa:road', NULL, NULL, 0, b'1', b'1', b'1', 'admin', '2021-09-20 16:26:19', '1', '2024-02-29 12:38:13', b'0'); +INSERT INTO `system_menu` VALUES (100, '用户管理', 'system:user:list', 2, 1, 1, 'user', 'ep:avatar', 'system/user/index', 'SystemUser', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2025-03-15 21:30:41', b'0'); +INSERT INTO `system_menu` VALUES (101, '角色管理', '', 2, 2, 1, 'role', 'ep:user', 'system/role/index', 'SystemRole', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-05-01 18:35:29', b'0'); +INSERT INTO `system_menu` VALUES (102, '菜单管理', '', 2, 3, 1, 'menu', 'ep:menu', 'system/menu/index', 'SystemMenu', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:03:50', b'0'); +INSERT INTO `system_menu` VALUES (103, '部门管理', '', 2, 4, 1, 'dept', 'fa:address-card', 'system/dept/index', 'SystemDept', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:06:28', b'0'); +INSERT INTO `system_menu` VALUES (104, '岗位管理', '', 2, 5, 1, 'post', 'fa:address-book-o', 'system/post/index', 'SystemPost', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:06:39', b'0'); +INSERT INTO `system_menu` VALUES (105, '字典管理', '', 2, 6, 1, 'dict', 'ep:collection', 'system/dict/index', 'SystemDictType', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:07:12', b'0'); +INSERT INTO `system_menu` VALUES (106, '配置管理', '', 2, 8, 2, 'config', 'fa:connectdevelop', 'infra/config/index', 'InfraConfig', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-04-23 00:02:45', b'0'); +INSERT INTO `system_menu` VALUES (108, '审计日志', '', 1, 9, 1, 'log', 'ep:document-copy', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:08:30', b'0'); +INSERT INTO `system_menu` VALUES (109, '令牌管理', '', 2, 2, 1261, 'token', 'fa:key', 'system/oauth2/token/index', 'SystemTokenClient', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:13:48', b'0'); +INSERT INTO `system_menu` VALUES (111, 'MySQL 监控', '', 2, 1, 2740, 'druid', 'fa-solid:box', 'infra/druid/index', 'InfraDruid', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-04-23 00:05:58', b'0'); +INSERT INTO `system_menu` VALUES (112, 'Java 监控', '', 2, 3, 2740, 'admin-server', 'ep:coffee-cup', 'infra/server/index', 'InfraAdminServer', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-04-23 00:06:57', b'0'); +INSERT INTO `system_menu` VALUES (113, 'Redis 监控', '', 2, 2, 2740, 'redis', 'fa:reddit-square', 'infra/redis/index', 'InfraRedis', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-04-23 00:06:09', b'0'); +INSERT INTO `system_menu` VALUES (114, '表单构建', 'infra:build:list', 2, 2, 2, 'build', 'fa:wpforms', 'infra/build/index', 'InfraBuild', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 08:51:35', b'0'); +INSERT INTO `system_menu` VALUES (116, 'API 接口', 'infra:swagger:list', 2, 3, 2, 'swagger', 'fa:fighter-jet', 'infra/swagger/index', 'InfraSwagger', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-04-23 00:01:24', b'0'); +INSERT INTO `system_menu` VALUES (500, '操作日志', '', 2, 1, 108, 'operate-log', 'ep:position', 'system/operatelog/index', 'SystemOperateLog', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:09:59', b'0'); +INSERT INTO `system_menu` VALUES (501, '登录日志', '', 2, 2, 108, 'login-log', 'ep:promotion', 'system/loginlog/index', 'SystemLoginLog', 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2024-02-29 01:10:29', b'0'); +INSERT INTO `system_menu` VALUES (1001, '用户查询', 'system:user:query', 3, 1, 100, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1002, '用户新增', 'system:user:create', 3, 2, 100, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1003, '用户修改', 'system:user:update', 3, 3, 100, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1004, '用户删除', 'system:user:delete', 3, 4, 100, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1005, '用户导出', 'system:user:export', 3, 5, 100, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1006, '用户导入', 'system:user:import', 3, 6, 100, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1007, '重置密码', 'system:user:update-password', 3, 7, 100, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1008, '角色查询', 'system:role:query', 3, 1, 101, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1009, '角色新增', 'system:role:create', 3, 2, 101, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1010, '角色修改', 'system:role:update', 3, 3, 101, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1011, '角色删除', 'system:role:delete', 3, 4, 101, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1012, '角色导出', 'system:role:export', 3, 5, 101, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1013, '菜单查询', 'system:menu:query', 3, 1, 102, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1014, '菜单新增', 'system:menu:create', 3, 2, 102, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1015, '菜单修改', 'system:menu:update', 3, 3, 102, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1016, '菜单删除', 'system:menu:delete', 3, 4, 102, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1017, '部门查询', 'system:dept:query', 3, 1, 103, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1018, '部门新增', 'system:dept:create', 3, 2, 103, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1019, '部门修改', 'system:dept:update', 3, 3, 103, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1020, '部门删除', 'system:dept:delete', 3, 4, 103, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1021, '岗位查询', 'system:post:query', 3, 1, 104, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1022, '岗位新增', 'system:post:create', 3, 2, 104, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1023, '岗位修改', 'system:post:update', 3, 3, 104, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1024, '岗位删除', 'system:post:delete', 3, 4, 104, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1025, '岗位导出', 'system:post:export', 3, 5, 104, '', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1026, '字典查询', 'system:dict:query', 3, 1, 105, '#', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1027, '字典新增', 'system:dict:create', 3, 2, 105, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1028, '字典修改', 'system:dict:update', 3, 3, 105, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1029, '字典删除', 'system:dict:delete', 3, 4, 105, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1030, '字典导出', 'system:dict:export', 3, 5, 105, '#', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1031, '配置查询', 'infra:config:query', 3, 1, 106, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1032, '配置新增', 'infra:config:create', 3, 2, 106, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1033, '配置修改', 'infra:config:update', 3, 3, 106, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1034, '配置删除', 'infra:config:delete', 3, 4, 106, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1035, '配置导出', 'infra:config:export', 3, 5, 106, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1040, '操作查询', 'system:operate-log:query', 3, 1, 500, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1042, '日志导出', 'system:operate-log:export', 3, 2, 500, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1043, '登录查询', 'system:login-log:query', 3, 1, 501, '#', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1045, '日志导出', 'system:login-log:export', 3, 3, 501, '#', '#', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1046, '令牌列表', 'system:oauth2-token:page', 3, 1, 109, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-05-09 23:54:42', b'0'); +INSERT INTO `system_menu` VALUES (1048, '令牌删除', 'system:oauth2-token:delete', 3, 2, 109, '', '', '', NULL, 0, b'1', b'1', b'1', 'admin', '2021-01-05 17:03:48', '1', '2022-05-09 23:54:53', b'0'); +INSERT INTO `system_menu` VALUES (1063, '设置角色菜单权限', 'system:permission:assign-role-menu', 3, 6, 101, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-01-06 17:53:44', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1064, '设置角色数据权限', 'system:permission:assign-role-data-scope', 3, 7, 101, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-01-06 17:56:31', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1065, '设置用户角色', 'system:permission:assign-user-role', 3, 8, 101, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-01-07 10:23:28', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1066, '获得 Redis 监控信息', 'infra:redis:get-monitor-info', 3, 1, 113, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-01-26 01:02:31', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1067, '获得 Redis Key 列表', 'infra:redis:get-key-list', 3, 2, 113, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-01-26 01:02:52', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1070, '代码生成案例', '', 1, 1, 2, 'demo', 'ep:aim', 'infra/testDemo/index', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2023-11-15 23:45:53', b'0'); +INSERT INTO `system_menu` VALUES (1077, '链路追踪', '', 2, 4, 2740, 'skywalking', 'fa:eye', 'infra/skywalking/index', 'InfraSkyWalking', 0, b'1', b'1', b'1', '', '2021-02-08 20:41:31', '1', '2024-04-23 00:07:15', b'0'); +INSERT INTO `system_menu` VALUES (1078, '访问日志', '', 2, 1, 1083, 'api-access-log', 'ep:place', 'infra/apiAccessLog/index', 'InfraApiAccessLog', 0, b'1', b'1', b'1', '', '2021-02-26 01:32:59', '1', '2024-02-29 08:54:57', b'0'); +INSERT INTO `system_menu` VALUES (1082, '日志导出', 'infra:api-access-log:export', 3, 2, 1078, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-26 01:32:59', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1083, 'API 日志', '', 2, 4, 2, 'log', 'fa:tasks', NULL, NULL, 0, b'1', b'1', b'1', '', '2021-02-26 02:18:24', '1', '2024-04-22 23:58:36', b'0'); +INSERT INTO `system_menu` VALUES (1084, '错误日志', 'infra:api-error-log:query', 2, 2, 1083, 'api-error-log', 'ep:warning-filled', 'infra/apiErrorLog/index', 'InfraApiErrorLog', 0, b'1', b'1', b'1', '', '2021-02-26 07:53:20', '1', '2024-02-29 08:55:17', b'0'); +INSERT INTO `system_menu` VALUES (1085, '日志处理', 'infra:api-error-log:update-status', 3, 2, 1084, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-26 07:53:20', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1086, '日志导出', 'infra:api-error-log:export', 3, 3, 1084, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-26 07:53:20', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1088, '日志查询', 'infra:api-access-log:query', 3, 1, 1078, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2021-03-10 01:28:04', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1089, '日志查询', 'infra:api-error-log:query', 3, 1, 1084, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2021-03-10 01:29:09', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1090, '文件列表', '', 2, 5, 1243, 'file', 'ep:upload-filled', 'infra/file/index', 'InfraFile', 0, b'1', b'1', b'1', '', '2021-03-12 20:16:20', '1', '2024-02-29 08:53:02', b'0'); +INSERT INTO `system_menu` VALUES (1091, '文件查询', 'infra:file:query', 3, 1, 1090, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-03-12 20:16:20', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1092, '文件删除', 'infra:file:delete', 3, 4, 1090, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-03-12 20:16:20', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1118, '请假查询', '', 2, 0, 5, 'leave', 'fa:leanpub', 'bpm/oa/leave/index', 'BpmOALeave', 0, b'1', b'1', b'1', '', '2021-09-20 08:51:03', '1', '2024-02-29 12:38:21', b'0'); +INSERT INTO `system_menu` VALUES (1119, '请假申请查询', 'bpm:oa-leave:query', 3, 1, 1118, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-09-20 08:51:03', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1120, '请假申请创建', 'bpm:oa-leave:create', 3, 2, 1118, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-09-20 08:51:03', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1185, '工作流程', '', 1, 50, 0, '/bpm', 'fa:medium', NULL, NULL, 0, b'1', b'1', b'1', '1', '2021-12-30 20:26:36', '1', '2024-02-29 12:43:43', b'0'); +INSERT INTO `system_menu` VALUES (1186, '流程管理', '', 1, 10, 1185, 'manager', 'fa:dedent', NULL, NULL, 0, b'1', b'1', b'1', '1', '2021-12-30 20:28:30', '1', '2024-02-29 12:36:02', b'0'); +INSERT INTO `system_menu` VALUES (1187, '流程表单', '', 2, 2, 1186, 'form', 'fa:hdd-o', 'bpm/form/index', 'BpmForm', 0, b'1', b'1', b'1', '', '2021-12-30 12:38:22', '1', '2024-03-19 12:25:25', b'0'); +INSERT INTO `system_menu` VALUES (1188, '表单查询', 'bpm:form:query', 3, 1, 1187, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-30 12:38:22', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1189, '表单创建', 'bpm:form:create', 3, 2, 1187, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-30 12:38:22', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1190, '表单更新', 'bpm:form:update', 3, 3, 1187, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-30 12:38:22', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1191, '表单删除', 'bpm:form:delete', 3, 4, 1187, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-30 12:38:22', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1192, '表单导出', 'bpm:form:export', 3, 5, 1187, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-12-30 12:38:22', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1193, '流程模型', '', 2, 1, 1186, 'model', 'fa-solid:project-diagram', 'bpm/model/index', 'BpmModel', 0, b'1', b'1', b'1', '1', '2021-12-31 23:24:58', '1', '2024-03-19 12:25:19', b'0'); +INSERT INTO `system_menu` VALUES (1194, '模型查询', 'bpm:model:query', 3, 1, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-03 19:01:10', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1195, '模型创建', 'bpm:model:create', 3, 2, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-03 19:01:24', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1197, '模型更新', 'bpm:model:update', 3, 4, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-03 19:02:28', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1198, '模型删除', 'bpm:model:delete', 3, 5, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-03 19:02:43', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1199, '模型发布', 'bpm:model:deploy', 3, 6, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-03 19:03:24', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1200, '审批中心', '', 2, 20, 1185, 'task', 'fa:tasks', NULL, NULL, 0, b'1', b'1', b'1', '1', '2022-01-07 23:51:48', '1', '2024-03-21 00:33:15', b'0'); +INSERT INTO `system_menu` VALUES (1201, '我的流程', '', 2, 1, 1200, 'my', 'fa-solid:book', 'bpm/processInstance/index', 'BpmProcessInstanceMy', 0, b'1', b'1', b'1', '', '2022-01-07 15:53:44', '1', '2024-03-21 23:52:12', b'0'); +INSERT INTO `system_menu` VALUES (1202, '流程实例的查询', 'bpm:process-instance:query', 3, 1, 1201, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-01-07 15:53:44', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1207, '待办任务', '', 2, 10, 1200, 'todo', 'fa:slack', 'bpm/task/todo/index', 'BpmTodoTask', 0, b'1', b'1', b'1', '1', '2022-01-08 10:33:37', '1', '2024-02-29 12:37:39', b'0'); +INSERT INTO `system_menu` VALUES (1208, '已办任务', '', 2, 20, 1200, 'done', 'fa:delicious', 'bpm/task/done/index', 'BpmDoneTask', 0, b'1', b'1', b'1', '1', '2022-01-08 10:34:13', '1', '2024-02-29 12:37:54', b'0'); +INSERT INTO `system_menu` VALUES (1209, '用户分组', '', 2, 4, 1186, 'user-group', 'fa:user-secret', 'bpm/group/index', 'BpmUserGroup', 0, b'1', b'1', b'1', '', '2022-01-14 02:14:20', '1', '2024-03-21 23:55:29', b'0'); +INSERT INTO `system_menu` VALUES (1210, '用户组查询', 'bpm:user-group:query', 3, 1, 1209, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-01-14 02:14:20', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1211, '用户组创建', 'bpm:user-group:create', 3, 2, 1209, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-01-14 02:14:20', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1212, '用户组更新', 'bpm:user-group:update', 3, 3, 1209, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-01-14 02:14:20', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1213, '用户组删除', 'bpm:user-group:delete', 3, 4, 1209, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-01-14 02:14:20', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1215, '流程定义查询', 'bpm:process-definition:query', 3, 10, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-23 00:21:43', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1216, '流程任务分配规则查询', 'bpm:task-assign-rule:query', 3, 20, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-23 00:26:53', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1217, '流程任务分配规则创建', 'bpm:task-assign-rule:create', 3, 21, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-23 00:28:15', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1218, '流程任务分配规则更新', 'bpm:task-assign-rule:update', 3, 22, 1193, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-23 00:28:41', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1219, '流程实例的创建', 'bpm:process-instance:create', 3, 2, 1201, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-23 00:36:15', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1220, '流程实例的取消', 'bpm:process-instance:cancel', 3, 3, 1201, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-23 00:36:33', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1221, '流程任务的查询', 'bpm:task:query', 3, 1, 1207, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-23 00:38:52', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1222, '流程任务的更新', 'bpm:task:update', 3, 2, 1207, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2022-01-23 00:39:24', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1237, '文件配置', '', 2, 0, 1243, 'file-config', 'fa-solid:file-signature', 'infra/fileConfig/index', 'InfraFileConfig', 0, b'1', b'1', b'1', '', '2022-03-15 14:35:28', '1', '2024-02-29 08:52:54', b'0'); +INSERT INTO `system_menu` VALUES (1238, '文件配置查询', 'infra:file-config:query', 3, 1, 1237, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-03-15 14:35:28', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1239, '文件配置创建', 'infra:file-config:create', 3, 2, 1237, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-03-15 14:35:28', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1240, '文件配置更新', 'infra:file-config:update', 3, 3, 1237, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-03-15 14:35:28', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1241, '文件配置删除', 'infra:file-config:delete', 3, 4, 1237, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-03-15 14:35:28', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1242, '文件配置导出', 'infra:file-config:export', 3, 5, 1237, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-03-15 14:35:28', '', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` VALUES (1243, '文件管理', '', 2, 6, 2, 'file', 'ep:files', NULL, '', 0, b'1', b'1', b'1', '1', '2022-03-16 23:47:40', '1', '2024-04-23 00:02:11', b'0'); +INSERT INTO `system_menu` VALUES (1261, 'OAuth 2.0', '', 2, 10, 1, 'oauth2', 'fa:dashcube', NULL, NULL, 0, b'1', b'1', b'1', '1', '2022-05-09 23:38:17', '1', '2024-02-29 01:12:08', b'0'); +INSERT INTO `system_menu` VALUES (1263, '应用管理', '', 2, 0, 1261, 'oauth2/application', 'fa:hdd-o', 'system/oauth2/client/index', 'SystemOAuth2Client', 0, b'1', b'1', b'1', '', '2022-05-10 16:26:33', '1', '2024-02-29 01:13:14', b'0'); +INSERT INTO `system_menu` VALUES (1264, '客户端查询', 'system:oauth2-client:query', 3, 1, 1263, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:06', b'0'); +INSERT INTO `system_menu` VALUES (1265, '客户端创建', 'system:oauth2-client:create', 3, 2, 1263, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:23', b'0'); +INSERT INTO `system_menu` VALUES (1266, '客户端更新', 'system:oauth2-client:update', 3, 3, 1263, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:28', b'0'); +INSERT INTO `system_menu` VALUES (1267, '客户端删除', 'system:oauth2-client:delete', 3, 4, 1263, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:33', b'0'); +INSERT INTO `system_menu` VALUES (2083, '地区管理', '', 2, 14, 1, 'area', 'fa:map-marker', 'system/area/index', 'SystemArea', 0, b'1', b'1', b'1', '1', '2022-12-23 17:35:05', '1', '2024-02-29 08:50:28', b'0'); +INSERT INTO `system_menu` VALUES (2472, '主子表(内嵌)', '', 2, 12, 1070, 'demo03-inner', 'fa:power-off', 'infra/demo/demo03/inner/index', 'Demo03StudentInner', 0, b'1', b'1', b'1', '', '2023-11-13 04:39:51', '1', '2023-11-16 23:53:46', b'0'); +INSERT INTO `system_menu` VALUES (2478, '单表(增删改查)', '', 2, 1, 1070, 'demo01-contact', 'ep:bicycle', 'infra/demo/demo01/index', 'Demo01Contact', 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '1', '2023-11-16 20:34:40', b'0'); +INSERT INTO `system_menu` VALUES (2479, '示例联系人查询', 'infra:demo01-contact:query', 3, 1, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0'); +INSERT INTO `system_menu` VALUES (2480, '示例联系人创建', 'infra:demo01-contact:create', 3, 2, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0'); +INSERT INTO `system_menu` VALUES (2481, '示例联系人更新', 'infra:demo01-contact:update', 3, 3, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0'); +INSERT INTO `system_menu` VALUES (2482, '示例联系人删除', 'infra:demo01-contact:delete', 3, 4, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0'); +INSERT INTO `system_menu` VALUES (2483, '示例联系人导出', 'infra:demo01-contact:export', 3, 5, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0'); +INSERT INTO `system_menu` VALUES (2484, '树表(增删改查)', '', 2, 2, 1070, 'demo02-category', 'fa:tree', 'infra/demo/demo02/index', 'Demo02Category', 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '1', '2023-11-16 20:35:01', b'0'); +INSERT INTO `system_menu` VALUES (2485, '示例分类查询', 'infra:demo02-category:query', 3, 1, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0'); +INSERT INTO `system_menu` VALUES (2486, '示例分类创建', 'infra:demo02-category:create', 3, 2, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0'); +INSERT INTO `system_menu` VALUES (2487, '示例分类更新', 'infra:demo02-category:update', 3, 3, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0'); +INSERT INTO `system_menu` VALUES (2488, '示例分类删除', 'infra:demo02-category:delete', 3, 4, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0'); +INSERT INTO `system_menu` VALUES (2489, '示例分类导出', 'infra:demo02-category:export', 3, 5, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0'); +INSERT INTO `system_menu` VALUES (2490, '主子表(标准)', '', 2, 10, 1070, 'demo03-normal', 'fa:battery-3', 'infra/demo/demo03/normal/index', 'Demo03StudentNormal', 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '1', '2023-11-16 23:10:03', b'0'); +INSERT INTO `system_menu` VALUES (2491, '学生查询', 'infra:demo03-student:query', 3, 1, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0'); +INSERT INTO `system_menu` VALUES (2492, '学生创建', 'infra:demo03-student:create', 3, 2, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0'); +INSERT INTO `system_menu` VALUES (2493, '学生更新', 'infra:demo03-student:update', 3, 3, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0'); +INSERT INTO `system_menu` VALUES (2494, '学生删除', 'infra:demo03-student:delete', 3, 4, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0'); +INSERT INTO `system_menu` VALUES (2495, '学生导出', 'infra:demo03-student:export', 3, 5, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0'); +INSERT INTO `system_menu` VALUES (2497, '主子表(ERP)', '', 2, 11, 1070, 'demo03-erp', 'ep:calendar', 'infra/demo/demo03/erp/index', 'Demo03StudentERP', 0, b'1', b'1', b'1', '', '2023-11-16 15:50:59', '1', '2023-11-17 13:19:56', b'0'); +INSERT INTO `system_menu` VALUES (2525, 'WebSocket', '', 2, 5, 2, 'websocket', 'ep:connection', 'infra/webSocket/index', 'InfraWebSocket', 0, b'1', b'1', b'1', '1', '2023-11-23 19:41:55', '1', '2024-04-23 00:02:00', b'0'); +INSERT INTO `system_menu` VALUES (2713, '抄送我的', 'bpm:process-instance-cc:query', 2, 30, 1200, 'copy', 'ep:copy-document', 'bpm/task/copy/index', 'BpmProcessInstanceCopy', 0, b'1', b'1', b'1', '1', '2024-03-17 21:50:23', '1', '2024-04-24 19:55:12', b'0'); +INSERT INTO `system_menu` VALUES (2714, '流程分类', '', 2, 3, 1186, 'category', 'fa:object-ungroup', 'bpm/category/index', 'BpmCategory', 0, b'1', b'1', b'1', '', '2024-03-08 02:00:51', '1', '2024-03-21 23:51:18', b'0'); +INSERT INTO `system_menu` VALUES (2715, '分类查询', 'bpm:category:query', 3, 1, 2714, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-03-08 02:00:51', '1', '2024-03-19 14:36:25', b'0'); +INSERT INTO `system_menu` VALUES (2716, '分类创建', 'bpm:category:create', 3, 2, 2714, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-03-08 02:00:51', '1', '2024-03-19 14:36:31', b'0'); +INSERT INTO `system_menu` VALUES (2717, '分类更新', 'bpm:category:update', 3, 3, 2714, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-03-08 02:00:51', '1', '2024-03-19 14:36:35', b'0'); +INSERT INTO `system_menu` VALUES (2718, '分类删除', 'bpm:category:delete', 3, 4, 2714, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-03-08 02:00:51', '1', '2024-03-19 14:36:41', b'0'); +INSERT INTO `system_menu` VALUES (2720, '发起流程', '', 2, 0, 1200, 'create', 'fa-solid:grin-stars', 'bpm/processInstance/create/index', 'BpmProcessInstanceCreate', 0, b'1', b'0', b'1', '1', '2024-03-19 19:46:05', '1', '2024-03-23 19:03:42', b'0'); +INSERT INTO `system_menu` VALUES (2721, '流程实例', '', 2, 10, 1186, 'process-instance/manager', 'fa:square', 'bpm/processInstance/manager/index', 'BpmProcessInstanceManager', 0, b'1', b'1', b'1', '1', '2024-03-21 23:57:30', '1', '2024-03-21 23:57:30', b'0'); +INSERT INTO `system_menu` VALUES (2722, '流程实例的查询(管理员)', 'bpm:process-instance:manager-query', 3, 1, 2721, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-03-22 08:18:27', '1', '2024-03-22 08:19:05', b'0'); +INSERT INTO `system_menu` VALUES (2723, '流程实例的取消(管理员)', 'bpm:process-instance:cancel-by-admin', 3, 2, 2721, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-03-22 08:19:25', '1', '2024-03-22 08:19:25', b'0'); +INSERT INTO `system_menu` VALUES (2724, '流程任务', '', 2, 11, 1186, 'process-tasnk', 'ep:collection-tag', 'bpm/task/manager/index', 'BpmManagerTask', 0, b'1', b'1', b'1', '1', '2024-03-22 08:43:22', '1', '2024-03-22 08:43:27', b'0'); +INSERT INTO `system_menu` VALUES (2725, '流程任务的查询(管理员)', 'bpm:task:mananger-query', 3, 1, 2724, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-03-22 08:43:49', '1', '2024-03-22 08:43:49', b'0'); +INSERT INTO `system_menu` VALUES (2726, '流程监听器', '', 2, 5, 1186, 'process-listener', 'fa:assistive-listening-systems', 'bpm/processListener/index', 'BpmProcessListener', 0, b'1', b'1', b'1', '', '2024-03-09 16:05:34', '1', '2024-03-23 13:13:38', b'0'); +INSERT INTO `system_menu` VALUES (2727, '流程监听器查询', 'bpm:process-listener:query', 3, 1, 2726, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-03-09 16:05:34', '', '2024-03-09 16:05:34', b'0'); +INSERT INTO `system_menu` VALUES (2728, '流程监听器创建', 'bpm:process-listener:create', 3, 2, 2726, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-03-09 16:05:34', '', '2024-03-09 16:05:34', b'0'); +INSERT INTO `system_menu` VALUES (2729, '流程监听器更新', 'bpm:process-listener:update', 3, 3, 2726, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-03-09 16:05:34', '', '2024-03-09 16:05:34', b'0'); +INSERT INTO `system_menu` VALUES (2730, '流程监听器删除', 'bpm:process-listener:delete', 3, 4, 2726, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-03-09 16:05:34', '', '2024-03-09 16:05:34', b'0'); +INSERT INTO `system_menu` VALUES (2731, '流程表达式', '', 2, 6, 1186, 'process-expression', 'fa:wpexplorer', 'bpm/processExpression/index', 'BpmProcessExpression', 0, b'1', b'1', b'1', '', '2024-03-09 22:35:08', '1', '2024-03-23 19:43:05', b'0'); +INSERT INTO `system_menu` VALUES (2732, '流程表达式查询', 'bpm:process-expression:query', 3, 1, 2731, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-03-09 22:35:08', '', '2024-03-09 22:35:08', b'0'); +INSERT INTO `system_menu` VALUES (2733, '流程表达式创建', 'bpm:process-expression:create', 3, 2, 2731, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-03-09 22:35:08', '', '2024-03-09 22:35:08', b'0'); +INSERT INTO `system_menu` VALUES (2734, '流程表达式更新', 'bpm:process-expression:update', 3, 3, 2731, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-03-09 22:35:08', '', '2024-03-09 22:35:08', b'0'); +INSERT INTO `system_menu` VALUES (2735, '流程表达式删除', 'bpm:process-expression:delete', 3, 4, 2731, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-03-09 22:35:08', '', '2024-03-09 22:35:08', b'0'); +INSERT INTO `system_menu` VALUES (2740, '监控中心', '', 1, 10, 2, 'monitors', 'ep:monitor', '', '', 0, b'1', b'1', b'1', '1', '2024-04-23 00:04:44', '1', '2024-04-23 00:04:44', b'0'); +INSERT INTO `system_menu` VALUES (2913, '流程清理', 'bpm:model:clean', 3, 7, 1193, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-01-17 19:32:06', '1', '2025-01-17 19:32:06', b'0'); +INSERT INTO `system_menu` VALUES (900000, '系统管理', '', 1, 10, 0, '/system', 'ep:tools', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900001, '用户管理', 'system:user:list', 2, 1, 900000, 'user', 'ep:avatar', 'system/user/index', 'SystemUser', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900002, '角色管理', '', 2, 2, 900000, 'role', 'ep:user', 'system/role/index', 'SystemRole', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900003, '菜单管理', '', 2, 3, 900000, 'menu', 'ep:menu', 'system/menu/index', 'SystemMenu', 0, b'1', b'1', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900004, '模板参考', '', 1, 900, 0, '/template-reference', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900005, '异常页', '', 1, 7, 900004, '/exception', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900006, '403', '', 2, 0, 900005, '/exception/403', 'mdi:file-document-multiple-outline', 'exception/403/index', 'Exception403', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900007, '404', '', 2, 0, 900005, '/exception/404', 'mdi:file-document-multiple-outline', 'exception/404/index', 'Exception404', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900008, '500', '', 2, 0, 900005, '/exception/500', 'mdi:file-document-multiple-outline', 'exception/500/index', 'Exception500', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900009, '文档', '', 1, 2, 900004, '/document', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900010, 'Ant Design Vue文档', '', 2, 7, 900009, '/document/antd', 'mdi:file-document-multiple-outline', 'document/antd/index', 'DocumentAntd', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900011, 'Naive UI文档', '', 2, 6, 900009, '/document/naive', 'mdi:file-document-multiple-outline', 'document/naive/index', 'DocumentNaive', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900012, 'Element Plus文档', '', 2, 7, 900009, '/document/element-plus', 'mdi:file-document-multiple-outline', 'document/element-plus/index', 'DocumentElementPlus', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900013, 'Alova文档', '', 2, 8, 900009, '/document/alova', 'mdi:file-document-multiple-outline', 'document/alova/index', 'DocumentAlova', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900014, 'UnoCSS文档', '', 2, 5, 900009, '/document/unocss', 'mdi:file-document-multiple-outline', 'document/unocss/index', 'DocumentUnocss', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900015, 'Vite文档', '', 2, 4, 900009, '/document/vite', 'mdi:file-document-multiple-outline', 'document/vite/index', 'DocumentVite', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900016, 'Vue文档', '', 2, 3, 900009, '/document/vue', 'mdi:file-document-multiple-outline', 'document/vue/index', 'DocumentVue', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900017, '关于', '', 2, 10, 900004, '/about', 'mdi:file-document-multiple-outline', 'about/index', 'About', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900018, 'alova示例', '', 1, 7, 900004, '/alova', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900019, 'alova请求', '', 2, 1, 900018, '/alova/request', 'mdi:file-document-multiple-outline', 'alova/request/index', 'AlovaRequest', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900020, '场景化请求', '', 2, 3, 900018, '/alova/scenes', 'mdi:file-document-multiple-outline', 'alova/scenes/index', 'AlovaScenes', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900021, '用户列表', '', 2, 2, 900018, '/alova/user', 'mdi:file-document-multiple-outline', 'alova/user/index', 'AlovaUser', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900022, '系统功能', '', 1, 6, 900004, '/function', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900023, '请求', '', 2, 3, 900022, '/function/request', 'mdi:file-document-multiple-outline', 'function/request/index', 'FunctionRequest', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900024, '超级管理员可见', '', 2, 5, 900022, '/function/super-page', 'mdi:file-document-multiple-outline', 'function/super-page/index', 'FunctionSuperPage', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900025, '标签页', '', 2, 1, 900022, '/function/tab', 'mdi:file-document-multiple-outline', 'function/tab/index', 'FunctionTab', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900026, '切换权限', '', 2, 4, 900022, '/function/toggle-auth', 'mdi:file-document-multiple-outline', 'function/toggle-auth/index', 'FunctionToggleAuth', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900027, '首页', '', 2, 1, 900004, '/home', 'mdi:file-document-multiple-outline', 'home/index', 'Home', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900028, '多级菜单', '', 1, 8, 900004, '/multi-menu', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900029, '菜单一', '', 1, 1, 900028, '/multi-menu/first', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900030, '菜单一子菜单', '', 2, 0, 900029, '/multi-menu/first/child', 'mdi:file-document-multiple-outline', 'multi-menu/first/child/index', 'MultiMenuFirstChild', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900031, '菜单二', '', 1, 2, 900028, '/multi-menu/second', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900032, '菜单二子菜单', '', 1, 0, 900031, '/multi-menu/second/child', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900033, '菜单二子菜单首页', '', 2, 0, 900032, '/multi-menu/second/child/home', 'mdi:file-document-multiple-outline', 'multi-menu/second/child/home/index', 'MultiMenuSecondChildHome', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:02', 'admin', '2026-03-18 13:42:02', b'0'); +INSERT INTO `system_menu` VALUES (900034, '插件示例', '', 1, 7, 900004, '/plugin', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900035, '条形码', '', 2, 0, 900034, '/plugin/barcode', 'mdi:file-document-multiple-outline', 'plugin/barcode/index', 'PluginBarcode', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900036, '图表', '', 1, 0, 900034, '/plugin/charts', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900037, 'AntV', '', 2, 0, 900036, '/plugin/charts/antv', 'mdi:file-document-multiple-outline', 'plugin/charts/antv/index', 'PluginChartsAntv', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900038, 'ECharts', '', 2, 0, 900036, '/plugin/charts/echarts', 'mdi:file-document-multiple-outline', 'plugin/charts/echarts/index', 'PluginChartsEcharts', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900039, 'VChart', '', 2, 0, 900036, '/plugin/charts/vchart', 'mdi:file-document-multiple-outline', 'plugin/charts/vchart/index', 'PluginChartsVchart', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900040, '剪贴板', '', 2, 0, 900034, '/plugin/copy', 'mdi:file-document-multiple-outline', 'plugin/copy/index', 'PluginCopy', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900041, '编辑器', '', 1, 0, 900034, '/plugin/editor', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900042, 'MD 编辑器', '', 2, 0, 900041, '/plugin/editor/markdown', 'mdi:file-document-multiple-outline', 'plugin/editor/markdown/index', 'PluginEditorMarkdown', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900043, '富文本编辑器', '', 2, 0, 900041, '/plugin/editor/quill', 'mdi:file-document-multiple-outline', 'plugin/editor/quill/index', 'PluginEditorQuill', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900044, 'Excel', '', 2, 0, 900034, '/plugin/excel', 'mdi:file-document-multiple-outline', 'plugin/excel/index', 'PluginExcel', 0, b'1', b'1', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900045, '甘特图', '', 1, 0, 900034, '/plugin/gantt', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900046, 'dhtmlxGantt', '', 2, 0, 900045, '/plugin/gantt/dhtmlx', 'mdi:file-document-multiple-outline', 'plugin/gantt/dhtmlx/index', 'PluginGanttDhtmlx', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900047, 'VTableGantt', '', 2, 0, 900045, '/plugin/gantt/vtable', 'mdi:file-document-multiple-outline', 'plugin/gantt/vtable/index', 'PluginGanttVtable', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900048, '图标', '', 2, 0, 900034, '/plugin/icon', 'mdi:file-document-multiple-outline', 'plugin/icon/index', 'PluginIcon', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900049, '地图', '', 2, 0, 900034, '/plugin/map', 'mdi:file-document-multiple-outline', 'plugin/map/index', 'PluginMap', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900050, 'PDF 预览', '', 2, 0, 900034, '/plugin/pdf', 'mdi:file-document-multiple-outline', 'plugin/pdf/index', 'PluginPdf', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900051, '拼音', '', 2, 0, 900034, '/plugin/pinyin', 'mdi:file-document-multiple-outline', 'plugin/pinyin/index', 'PluginPinyin', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900052, '打印', '', 2, 0, 900034, '/plugin/print', 'mdi:file-document-multiple-outline', 'plugin/print/index', 'PluginPrint', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900053, 'Swiper', '', 2, 0, 900034, '/plugin/swiper', 'mdi:file-document-multiple-outline', 'plugin/swiper/index', 'PluginSwiper', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900054, '表格', '', 1, 0, 900034, '/plugin/tables', 'mdi:file-document-multiple-outline', NULL, NULL, 0, b'1', b'0', b'1', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900055, 'VTable', '', 2, 0, 900054, '/plugin/tables/vtable', 'mdi:file-document-multiple-outline', 'plugin/tables/vtable/index', 'PluginTablesVtable', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900056, '打字机', '', 2, 0, 900034, '/plugin/typeit', 'mdi:file-document-multiple-outline', 'plugin/typeit/index', 'PluginTypeit', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_menu` VALUES (900057, '视频', '', 2, 0, 900034, '/plugin/video', 'mdi:file-document-multiple-outline', 'plugin/video/index', 'PluginVideo', 0, b'1', b'0', b'0', 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); + +-- ---------------------------- +-- Table structure for system_post +-- ---------------------------- +DROP TABLE IF EXISTS `system_post`; +CREATE TABLE `system_post` ( + `id` bigint NOT NULL COMMENT '岗位ID', + `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '岗位编码', + `post_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '岗位类型:management/technical/business', + `level_rank` int NULL DEFAULT NULL COMMENT '岗位等级排序,越大级别越高', + `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '岗位名称', + `sort` int NOT NULL COMMENT '显示顺序', + `status` tinyint NOT NULL COMMENT '状态(0正常 1停用)', + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_system_post_type`(`post_type` ASC) USING BTREE, + INDEX `idx_system_post_level_rank`(`level_rank` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '岗位信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of system_post +-- ---------------------------- +INSERT INTO `system_post` VALUES (2, 'se', NULL, NULL, '项目经理', 2, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2023-11-15 09:18:20', b'0'); + +-- ---------------------------- +-- Table structure for system_role +-- ---------------------------- +DROP TABLE IF EXISTS `system_role`; +CREATE TABLE `system_role` ( + `id` bigint NOT NULL COMMENT '角色ID', + `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '角色名称', + `code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '角色权限字符串', + `sort` int NOT NULL COMMENT '显示顺序', + `data_scope` tinyint NOT NULL DEFAULT 1 COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', + `data_scope_dept_ids` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '数据范围(指定部门数组)', + `status` tinyint NOT NULL COMMENT '角色状态(0正常 1停用)', + `type` tinyint NOT NULL COMMENT '角色类型', + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of system_role +-- ---------------------------- +INSERT INTO `system_role` VALUES (1, '超级管理员', 'super_admin', 1, 1, '', 0, 1, '超级管理员', 'admin', '2021-01-05 17:03:48', '', '2022-02-22 05:08:21', b'0'); +INSERT INTO `system_role` VALUES (2, '普通角色', 'common', 2, 2, '', 0, 1, '普通角色', 'admin', '2021-01-05 17:03:48', '', '2022-02-22 05:08:20', b'0'); + +-- ---------------------------- +-- Table structure for system_role_menu +-- ---------------------------- +DROP TABLE IF EXISTS `system_role_menu`; +CREATE TABLE `system_role_menu` ( + `id` bigint NOT NULL COMMENT '自增编号', + `role_id` bigint NOT NULL COMMENT '角色ID', + `menu_id` bigint NOT NULL COMMENT '菜单ID', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色和菜单关联表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of system_role_menu +-- ---------------------------- +INSERT INTO `system_role_menu` VALUES (434, 2, 1, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', b'0'); +INSERT INTO `system_role_menu` VALUES (477, 2, 100, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', b'0'); +INSERT INTO `system_role_menu` VALUES (478, 2, 101, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', b'0'); +INSERT INTO `system_role_menu` VALUES (479, 2, 102, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', b'0'); +INSERT INTO `system_role_menu` VALUES (481, 2, 103, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', b'0'); +INSERT INTO `system_role_menu` VALUES (483, 2, 104, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', b'0'); +INSERT INTO `system_role_menu` VALUES (485, 2, 105, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', b'0'); +INSERT INTO `system_role_menu` VALUES (490, 2, 108, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', b'0'); +INSERT INTO `system_role_menu` VALUES (492, 2, 109, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', b'0'); +INSERT INTO `system_role_menu` VALUES (541, 2, 500, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', b'0'); +INSERT INTO `system_role_menu` VALUES (543, 2, 501, '1', '2022-02-22 13:09:12', '1', '2022-02-22 13:09:12', b'0'); +INSERT INTO `system_role_menu` VALUES (675, 2, 2, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0'); +INSERT INTO `system_role_menu` VALUES (689, 2, 1077, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0'); +INSERT INTO `system_role_menu` VALUES (690, 2, 1078, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0'); +INSERT INTO `system_role_menu` VALUES (692, 2, 1083, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0'); +INSERT INTO `system_role_menu` VALUES (693, 2, 1084, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0'); +INSERT INTO `system_role_menu` VALUES (699, 2, 1090, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0'); +INSERT INTO `system_role_menu` VALUES (703, 2, 106, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0'); +INSERT INTO `system_role_menu` VALUES (705, 2, 111, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0'); +INSERT INTO `system_role_menu` VALUES (706, 2, 112, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0'); +INSERT INTO `system_role_menu` VALUES (707, 2, 113, '1', '2022-02-22 13:16:57', '1', '2022-02-22 13:16:57', b'0'); +INSERT INTO `system_role_menu` VALUES (1991, 2, 1024, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (1992, 2, 1025, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (1993, 2, 1026, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (1994, 2, 1027, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (1995, 2, 1028, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (1996, 2, 1029, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (1997, 2, 1030, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (1998, 2, 1031, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (1999, 2, 1032, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2000, 2, 1033, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2001, 2, 1034, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2002, 2, 1035, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2007, 2, 1040, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2008, 2, 1042, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2009, 2, 1043, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2010, 2, 1045, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2011, 2, 1046, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2012, 2, 1048, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2021, 2, 2083, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2024, 2, 1063, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2025, 2, 1064, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2026, 2, 1065, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2027, 2, 1066, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2028, 2, 1067, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2029, 2, 1070, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2036, 2, 1082, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2037, 2, 1085, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2038, 2, 1086, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2040, 2, 1088, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2041, 2, 1089, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2042, 2, 1091, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2043, 2, 1092, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2072, 2, 114, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2076, 2, 116, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2103, 2, 1237, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2104, 2, 1238, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2105, 2, 1239, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2106, 2, 1240, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2107, 2, 1241, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2108, 2, 1242, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2109, 2, 1243, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2123, 2, 1261, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2124, 2, 1263, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2125, 2, 1264, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2126, 2, 1265, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2127, 2, 1266, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2128, 2, 1267, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2129, 2, 1001, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2130, 2, 1002, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2131, 2, 1003, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2132, 2, 1004, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2133, 2, 1005, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2134, 2, 1006, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2135, 2, 1007, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2136, 2, 1008, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2137, 2, 1009, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2138, 2, 1010, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2139, 2, 1011, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2140, 2, 1012, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2141, 2, 1013, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2143, 2, 1015, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2145, 2, 1017, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2146, 2, 1018, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2147, 2, 1019, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2148, 2, 1020, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2149, 2, 1021, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2150, 2, 1022, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (2151, 2, 1023, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0'); +INSERT INTO `system_role_menu` VALUES (5780, 2, 2740, '1', '2024-07-07 20:39:38', '1', '2024-07-07 20:39:38', b'0'); +INSERT INTO `system_role_menu` VALUES (990000, 1, 900000, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990001, 1, 900001, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990002, 1, 900002, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990003, 1, 900003, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990004, 1, 900004, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990005, 1, 900005, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990006, 1, 900006, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990007, 1, 900007, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990008, 1, 900008, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990009, 1, 900009, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990010, 1, 900010, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990011, 1, 900011, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990012, 1, 900012, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990013, 1, 900013, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990014, 1, 900014, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990015, 1, 900015, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990016, 1, 900016, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990017, 1, 900017, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990018, 1, 900018, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990019, 1, 900019, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990020, 1, 900020, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990021, 1, 900021, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990022, 1, 900022, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990023, 1, 900023, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990024, 1, 900024, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990025, 1, 900025, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990026, 1, 900026, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990027, 1, 900027, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990028, 1, 900028, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990029, 1, 900029, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990030, 1, 900030, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990031, 1, 900031, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990032, 1, 900032, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990033, 1, 900033, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990034, 1, 900034, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990035, 1, 900035, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990036, 1, 900036, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990037, 1, 900037, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990038, 1, 900038, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990039, 1, 900039, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990040, 1, 900040, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990041, 1, 900041, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990042, 1, 900042, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990043, 1, 900043, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990044, 1, 900044, 'admin', '2026-03-18 13:42:03', 'admin', '2026-03-18 13:42:03', b'0'); +INSERT INTO `system_role_menu` VALUES (990045, 1, 900045, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990046, 1, 900046, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990047, 1, 900047, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990048, 1, 900048, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990049, 1, 900049, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990050, 1, 900050, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990051, 1, 900051, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990052, 1, 900052, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990053, 1, 900053, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990054, 1, 900054, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990055, 1, 900055, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990056, 1, 900056, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); +INSERT INTO `system_role_menu` VALUES (990057, 1, 900057, 'admin', '2026-03-18 13:42:04', 'admin', '2026-03-18 13:42:04', b'0'); + +-- ---------------------------- +-- Table structure for system_user_post +-- ---------------------------- +DROP TABLE IF EXISTS `system_user_post`; +CREATE TABLE `system_user_post` ( + `id` bigint NOT NULL COMMENT 'id', + `user_id` bigint NOT NULL DEFAULT 0 COMMENT '用户ID', + `post_id` bigint NOT NULL DEFAULT 0 COMMENT '岗位ID', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户岗位表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of system_user_post +-- ---------------------------- +INSERT INTO `system_user_post` VALUES (112, 1, 1, 'admin', '2022-05-02 07:25:24', 'admin', '2022-05-02 07:25:24', b'0'); +INSERT INTO `system_user_post` VALUES (125, 1, 2, '1', '2024-07-13 22:31:39', '1', '2024-07-13 22:31:39', b'0'); + +-- ---------------------------- +-- Table structure for system_user_role +-- ---------------------------- +DROP TABLE IF EXISTS `system_user_role`; +CREATE TABLE `system_user_role` ( + `id` bigint NOT NULL COMMENT '自增编号', + `user_id` bigint NOT NULL COMMENT '用户ID', + `role_id` bigint NOT NULL COMMENT '角色ID', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户和角色关联表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of system_user_role +-- ---------------------------- +INSERT INTO `system_user_role` VALUES (1, 1, 1, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:17', b'0'); +INSERT INTO `system_user_role` VALUES (18, 1, 2, '1', '2022-05-12 20:39:29', '1', '2022-05-12 20:39:29', b'0'); + +-- ---------------------------- +-- Table structure for system_user_visibility_config +-- ---------------------------- +DROP TABLE IF EXISTS `system_user_visibility_config`; +CREATE TABLE `system_user_visibility_config` ( + `id` bigint NOT NULL COMMENT '主键ID', + `user_id` bigint NOT NULL COMMENT '用户ID', + `visibility_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '可见范围类型:all/directions/projects', + `visible_direction_ids` json NULL COMMENT '补充可见方向ID集合', + `visible_project_ids` json NULL COMMENT '补充可见项目ID集合', + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uk_visibility_user`(`user_id` ASC) USING BTREE, + INDEX `idx_visibility_type`(`visibility_type` ASC) USING BTREE, + CONSTRAINT `chk_visibility_type` CHECK (`visibility_type` in (_utf8mb4'all',_utf8mb4'directions',_utf8mb4'projects')) +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户补充可见范围配置表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of system_user_visibility_config +-- ---------------------------- + +-- ---------------------------- +-- Table structure for system_users +-- ---------------------------- +DROP TABLE IF EXISTS `system_users`; +CREATE TABLE `system_users` ( + `id` bigint NOT NULL COMMENT '用户ID', + `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户账号', + `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '密码', + `nickname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户昵称', + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', + `dept_id` bigint NULL DEFAULT NULL COMMENT '部门ID', + `position_id` bigint NULL DEFAULT NULL COMMENT '主岗位ID', + `resigned_at` datetime NULL DEFAULT NULL COMMENT '离职时间', + `post_ids` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '岗位编号数组', + `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '用户邮箱', + `mobile` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '手机号码', + `sex` tinyint NULL DEFAULT 0 COMMENT '用户性别', + `avatar` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '头像地址', + `status` tinyint NOT NULL DEFAULT 0 COMMENT '帐号状态(0正常 1停用)', + `login_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '最后登录IP', + `login_date` datetime NULL DEFAULT NULL COMMENT '最后登录时间', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_system_users_dept_id`(`dept_id` ASC) USING BTREE, + INDEX `idx_system_users_position_id`(`position_id` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of system_users +-- ---------------------------- +INSERT INTO `system_users` VALUES (1, 'admin', '$2a$04$KljJDa/LK7QfDm0lF5OhuePhlPfjRH3tB2Wu351Uidz.oQGJXevPi', '灿能源码', '管理员', 103, 2, NULL, '[1,2]', '11aoteman@126.com', '18818260272', 2, 'http://test.rdms.iocoder.cn/20250921/avatar_1758423875594.png', 0, '192.168.2.125', '2026-03-18 16:18:02', 'admin', '2021-01-05 17:03:47', 'system', '2026-03-19 13:59:04', b'0'); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/rdms-system/rdms-system-boot/src/表结构调整建议.md b/rdms-system/rdms-system-boot/src/表结构调整建议.md new file mode 100644 index 0000000..5cd2a7a --- /dev/null +++ b/rdms-system/rdms-system-boot/src/表结构调整建议.md @@ -0,0 +1,556 @@ +# 表结构调整建议 + +## 1. 先说结论 + +这个项目按“新项目、严格对齐设计文档”落地,不考虑历史兼容、降级或兜底。要满足《权限设计方案》,至少要做这 4 类调整: + +1. `system_dept` 从“普通部门表”升级成“可表达多层组织树的组织节点表”。 +2. 把“组织负责人”“直接管理关系”“特殊可见范围”从主表字段里拆出去,改成独立关系表。 +3. 把 `system_users` 的“多岗位逗号字段”改成“主岗位单字段”,否则和设计文档的“一人一岗”冲突。 +4. `system_role` 只保留 RBAC 角色能力,不引入设计文档中没有的 `data_scope` 一类字段,避免混淆数据范围模型。 + +其中 `system_dept.leader_user_id` 的最终处理原则是: + +- 不保留在最终模型中 +- 直接从 `system_dept` 删除 +- 组织负责人统一改由 `system_org_leader_relation` 维护 +- 后续所有权限判断都不再读取 `leader_user_id` + +--- + +## 2. 现有表和设计文档的主要冲突 + +### 2.1 `system_dept` 的问题 + +现状:[`system_dept.sql`](/C:/code/gitee/rdms-requirements-compilation/04-设计阶段/权限设计/system_dept.sql) 第 24 行开始的 `system_dept` 只有 `parent_id`,没有物化路径、组织类型;并且用 `leader_user_id` 单字段存负责人。 + +对应设计文档: +- 组织树需要 `path` 物化路径,见 [`权限设计方案.md`](/C:/code/gitee/rdms-requirements-compilation/04-设计阶段/权限设计/权限设计方案.md#L93) +- 负责人要独立成 `system_org_leader_relation`,支持一人负责多个节点、一个节点多个负责人、且支持生效失效时间,见 [`权限设计方案.md`](/C:/code/gitee/rdms-requirements-compilation/04-设计阶段/权限设计/权限设计方案.md#L104) 和 [`权限设计方案.md`](/C:/code/gitee/rdms-requirements-compilation/04-设计阶段/权限设计/权限设计方案.md#L218) + +结论: +- `leader_user_id` 不应出现在最终模型中,需要从 `system_dept` 直接删除,组织负责人统一改由 `system_org_leader_relation` 维护。 +- 后续所有权限判断都不再读取 `leader_user_id`。 +- `system_dept` 至少要补 `path`、`org_type`、`code`。 +- `org_type` 是“组织节点类型”,不是“研发专属方向类型”。 + +### 2.2 `system_users` 的问题 + +现状:[`system_dept.sql`](/C:/code/gitee/rdms-requirements-compilation/04-设计阶段/权限设计/system_dept.sql#L161) 的 `system_users` 里有: +- `dept_id` +- `post_ids` + +同时还有 [`system_user_post`](/C:/code/gitee/rdms-requirements-compilation/04-设计阶段/权限设计/system_dept.sql#L129) 关联表。 + +对应设计文档: +- 用户主组织归属只有一个:`department_id` +- 岗位是单值:`users.position_id` +- 岗位不等于负责人身份,见 [`权限设计方案.md`](/C:/code/gitee/rdms-requirements-compilation/04-设计阶段/权限设计/权限设计方案.md#L118) 和 [`权限设计方案.md`](/C:/code/gitee/rdms-requirements-compilation/04-设计阶段/权限设计/权限设计方案.md#L188) + +结论: +- `dept_id` 可以保留,但语义要改成“主组织归属”。 +- `post_ids` 和 `system_user_post` 与当前设计冲突,最终模型中应删除。 +- 用户岗位的唯一事实来源改成 `position_id`。 + +### 2.3 `system_role` 的问题 + +现状:[`system_role`](/C:/code/gitee/rdms-requirements-compilation/04-设计阶段/权限设计/system_dept.sql#L91) 是通用 RBAC 角色表。 + +对应设计文档: +- RBAC 角色只决定“能不能进模块” +- 数据范围由“自己参与项目 + 组织负责人关系 + 特殊可见性配置”决定 +- 角色与数据范围无直接绑定,见 [`权限设计方案.md`](/C:/code/gitee/rdms-requirements-compilation/04-设计阶段/权限设计/权限设计方案.md#L301) 和 [`权限设计方案.md`](/C:/code/gitee/rdms-requirements-compilation/04-设计阶段/权限设计/权限设计方案.md#L1132) + +结论: +- `system_role` 在本项目中只承担 RBAC 角色定义。 +- 设计文档中没有的 `data_scope`、`data_scope_dept_ids` 不进入最终模型。 +- 数据范围全部由 `system_project_member`、`system_org_leader_relation`、`system_user_visibility_config` 体系计算。 + +### 2.4 缺失的核心表 + +设计文档明确依赖但当前 SQL 中没有、且最终落库应统一使用 `system_` 前缀的表: + +- `system_org_leader_relation` +- `system_user_management_relation` +- `system_user_visibility_config` +- `system_project_member` + +这 4 张表是本方案真正的核心。 + +--- + +## 3. 推荐的目标模型 + +最终落库表名统一使用 `system_*` 前缀;设计文档中的无前缀名称仅作为业务别名理解,不作为最终建表名称。 + +### 3.1 保留并改造 + +- `system_dept` +- `system_users` +- `system_post` +- `system_role` +- `system_user_role` +- `system_menu` +- `system_role_menu` + +### 3.2 新增 + +- `system_org_leader_relation` +- `system_user_management_relation` +- `system_user_visibility_config` +- `system_project_member` + +--- + +## 4. 建议如何改表 + +## 4.1 `system_dept` + +### 建议保留字段 + +- `id` +- `name` +- `parent_id` +- `sort` +- `status` +- 审计字段 + +### 建议新增字段 + +```sql +ALTER TABLE system_dept + ADD COLUMN org_type VARCHAR(20) NOT NULL DEFAULT 'dept' COMMENT '组织节点类型: company/dept/direction/team', + ADD COLUMN path VARCHAR(1024) CHARACTER SET ascii NOT NULL DEFAULT '/' COMMENT '物化路径,如 /1/3/6/,适配雪花ID场景', + ADD COLUMN level INT NOT NULL DEFAULT 1 COMMENT '层级,从1开始', + ADD COLUMN code VARCHAR(64) NULL COMMENT '组织编码,可选,用于标识具体方向或组织节点', + ADD KEY idx_parent_id (parent_id), + ADD KEY idx_org_type (org_type), + ADD KEY idx_path (path(191)), + ADD UNIQUE KEY uk_dept_code (code); +``` + +### 字段口径 + +- `org_type` 必填,默认值建议为 `dept` +- `code` 非必填 +- `code` 如果填写,必须唯一 + +### `org_type` 如何理解 + +`org_type` 表示“组织树中的节点层级”,不是“研发部专属分类”。 + +推荐枚举: + +- `company`:公司 +- `dept`:部门,例如研发部、工程部、财务部 +- `direction`:部门下的业务/专业方向,例如系统方向、嵌入式方向、电气方向、结构方向 +- `team`:更细的小组,例如前端组、后端组、技术支持组 + +这意味着: + +- 研发部下面可以有 `direction` +- 工程部下面也可以有 `direction` +- 财务部如果没有方向层,直接挂在 `dept` 即可 + +### 如何区分“系统方向 / 嵌入式方向 / 电力电子方向” + +区分方式不是只靠 `org_type`,而是三者一起看: + +- `org_type`:说明它是一个方向节点 +- `name`:说明它叫“系统方向”还是“嵌入式方向” +- `code`:提供更稳定的程序识别标识 + +例如: + +```text +研发部 org_type=dept code=NULL +系统方向 org_type=direction code=RD_SYS +嵌入式方向 org_type=direction code=RD_EMBEDDED +电力电子方向 org_type=direction code=RD_POWER_ELEC +工程部 org_type=dept code=NULL +电气方向 org_type=direction code=ENG_ELEC +``` + +结论: + +- `org_type` 负责表达层级 +- `code` 负责表达“具体是谁” +- 对没有稳定编码需求的普通部门,`code` 可以为空 + +### `path` 为什么仍然建议使用 ID + +- 即使当前主键使用雪花 ID,组织树层级通常也不会太深,`VARCHAR(1024)` 足够承载 +- `path` 使用主键 ID 最稳定,不受名称修改、编码调整影响 +- `path` 只包含数字和 `/`,建议使用 `ascii` 字符集即可 + +### 建议删除字段 + +- `leader_user_id` + +原因: +- 一个节点可能有多个负责人。 +- 负责人需要带时效。 +- 负责人关系不应写死在组织节点表中。 + +最终要求: +- `system_dept` 不再保存负责人字段。 +- 负责人全部通过 `system_org_leader_relation` 表达。 + +--- + +## 4.2 `system_users` + +### 建议保留字段 + +- `id` +- `username` +- `password` +- `nickname` +- `dept_id` +- `email` +- `mobile` +- `status` +- 审计字段 + +### 建议新增字段 + +```sql +ALTER TABLE system_users + ADD COLUMN position_id BIGINT NULL COMMENT '主岗位ID', + ADD COLUMN resigned_at DATETIME NULL COMMENT '离职时间', + ADD KEY idx_user_dept (dept_id), + ADD KEY idx_user_position (position_id); +``` + +### 建议调整语义 + +- `dept_id`:从“部门ID”调整为“主组织归属ID” +- `status`:继续表示账号可用性 +- `resigned_at`:表示内部员工离职时间 + +这样可以区分: +- 账号被禁用 +- 人员已离职(通过 `resigned_at` 标识) + +### 用户状态判断建议 + +- `status`:手工控制是否停用 +- `resigned_at`:只表示“是否离职” + +建议判定口径: + +```text +账号可用 = + status = 正常 + 且 (resigned_at 为空 或 resigned_at > 当前时间) +``` + +离职状态判断建议: + +- 如果 `resigned_at` 为空:未离职 +- 如果 `resigned_at` 大于当前时间:未离职,但表示未来计划离职 +- 如果 `resigned_at` 小于等于当前时间:已离职 + +说明: + +- 可以通过定时任务在 `resigned_at <= 当前时间` 时自动把 `status` 更新为停用 +- `resigned_at` 不再承担临时账号到期语义 + +### 建议删除字段 + +- `post_ids` + +原因: +- 设计文档明确是一人一岗。 +- 逗号字段无法做约束,也不利于查询和迁移。 + +### `system_user_post` 怎么处理 + +按设计文档,直接删除,不进入最终模型。 + +原因: +- 设计文档定义的是“一人一岗”。 +- 岗位是正式职位,不是可叠加的临时职责。 +- 组织负责人、项目负责人、产品经理等身份,分别由: + - `system_org_leader_relation` + - `system_project_member.project_role` + 来表达,不应复用岗位表。 + +--- + +## 4.3 `system_post` + +当前 `system_post` 可以保留,但建议补齐岗位属性,便于表达文档里的“岗位体系”和职级。 + +```sql +ALTER TABLE system_post + ADD COLUMN post_type VARCHAR(20) NULL COMMENT '岗位类型: management/technical', + ADD COLUMN level_rank INT NULL COMMENT '职级,如 4/5/6/7/8/9/10'; +``` + +说明: +- 岗位仍然只表达正式职位。 +- 不表达“某方向 Leader”这类组织负责关系。 + +--- + +## 4.4 `system_role` + +`system_role` 继续保留给 RBAC 使用,但职责要收敛: + +- `system_role` 负责菜单、接口、模块访问权限 +- 不再负责 RDMS 项目数据范围计算 + +最终要求: + +- `system_role` 只保留 RBAC 必需字段 +- `data_scope` 直接删除 +- `data_scope_dept_ids` 直接删除 +- 字段裁剪如有需要,后续根据部门或角色做展示层/查询层控制,不混入 RBAC 主模型 + +--- + +## 5. 建议新增的关系表 + +## 5.1 `system_org_leader_relation` + +用于替代 `system_dept.leader_user_id`。 + +```sql +CREATE TABLE system_org_leader_relation ( + id BIGINT NOT NULL COMMENT '主键', + dept_id BIGINT NOT NULL COMMENT '组织节点ID', + user_id BIGINT NOT NULL COMMENT '负责人用户ID', + effective_from DATETIME NULL COMMENT '生效时间', + effective_until DATETIME NULL COMMENT '失效时间', + remark VARCHAR(500) NULL COMMENT '备注', + creator VARCHAR(64) NULL DEFAULT '' COMMENT '创建者', + create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updater VARCHAR(64) NULL DEFAULT '' COMMENT '更新者', + update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + deleted BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (id), + KEY idx_org_leader_user (user_id, deleted, effective_from, effective_until), + KEY idx_org_leader_dept (dept_id, deleted, effective_from, effective_until), + UNIQUE KEY uk_org_leader_once (dept_id, user_id, effective_from) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='组织负责人关系表'; +``` + +说明: +- 支持一个人负责多个组织节点。 +- 支持一个组织节点多个负责人。 +- 权限计算时只取当前有效记录。 + +--- + +## 5.2 `system_user_management_relation` + +用于“直接管理谁”,只支撑“看人”视图,不支撑项目可见范围反推。 + +```sql +CREATE TABLE system_user_management_relation ( + id BIGINT NOT NULL COMMENT '主键', + manager_user_id BIGINT NOT NULL COMMENT '直接管理者', + subordinate_user_id BIGINT NOT NULL COMMENT '被管理者', + effective_from DATETIME NULL COMMENT '生效时间', + effective_until DATETIME NULL COMMENT '失效时间', + remark VARCHAR(500) NULL COMMENT '备注', + creator VARCHAR(64) NULL DEFAULT '' COMMENT '创建者', + create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updater VARCHAR(64) NULL DEFAULT '' COMMENT '更新者', + update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + deleted BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (id), + KEY idx_mgr_user (manager_user_id, deleted, effective_from, effective_until), + KEY idx_sub_user (subordinate_user_id, deleted, effective_from, effective_until), + UNIQUE KEY uk_mgr_sub_once (manager_user_id, subordinate_user_id, effective_from) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户直接管理关系表'; +``` + +--- + +## 5.3 `system_user_visibility_config` + +这里应严格对齐设计文档,不再拆成主表+明细表,直接使用单表配置模型。 + +```sql +CREATE TABLE system_user_visibility_config ( + id BIGINT NOT NULL COMMENT '主键', + user_id BIGINT NOT NULL COMMENT '用户ID', + visibility_type VARCHAR(20) NOT NULL COMMENT 'all/directions/projects', + visible_direction_ids JSON NULL COMMENT '补充可见方向ID列表', + visible_project_ids JSON NULL COMMENT '补充可见项目ID列表', + remark VARCHAR(500) NULL COMMENT '配置原因说明', + creator VARCHAR(64) NULL DEFAULT '' COMMENT '创建者', + create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updater VARCHAR(64) NULL DEFAULT '' COMMENT '更新者', + update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + deleted BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (id), + UNIQUE KEY uk_visibility_user (user_id), + KEY idx_visibility_type (visibility_type) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户补充可见范围配置表'; +``` + +### 字段口径 + +- `visibility_type = 'all'` + - 表示补充全部项目可见范围 + - `visible_direction_ids`、`visible_project_ids` 应为空 + +- `visibility_type = 'directions'` + - 表示补充指定方向可见范围 + - `visible_direction_ids` 必填 + - `visible_project_ids` 应为空 + +- `visibility_type = 'projects'` + - 表示补充指定项目可见范围 + - `visible_project_ids` 必填 + - `visible_direction_ids` 应为空 + +### 约束原则 + +- 一人一条配置记录 +- 只做补充,不做减权 +- 不用这张表表达组织负责人关系 +- 不用这张表表达项目内操作权限 +- 已经通过 `system_project_member` 或 `system_org_leader_relation` 默认可见的项目,不再重复写入 `visible_project_ids` +- `visibility_type = 'projects'` 只用于补充“默认权限链路拿不到,但业务上需要额外查看”的项目 + +### JSON 规模判断 + +- `visibility_type = 'all'` 时不使用 JSON 列表 +- `visibility_type = 'directions'` 时,方向数量通常很少 +- `visibility_type = 'projects'` 时,只记录补充项目,不记录项目成员或组织负责人本来就可见的项目 + +因此在当前设计下,`visible_direction_ids` 和 `visible_project_ids` 的规模通常都会比较小,当前阶段没有必要为了低概率的大规模列表场景提前拆表。 + +--- + +## 5.4 `system_project_member` + +这张表是项目权限的事实来源,必须单独建。 + +```sql +CREATE TABLE system_project_member ( + id BIGINT NOT NULL COMMENT '主键', + project_id BIGINT NOT NULL COMMENT '项目ID', + user_id BIGINT NOT NULL COMMENT '用户ID', + project_role VARCHAR(20) NOT NULL COMMENT 'pm/product/developer/tester/viewer', + member_type VARCHAR(20) NOT NULL DEFAULT 'core' COMMENT 'core/support', + joined_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '加入时间', + left_at DATETIME NULL COMMENT '离开时间,NULL表示当前成员', + remark VARCHAR(500) NULL COMMENT '备注', + creator VARCHAR(64) NULL DEFAULT '' COMMENT '创建者', + create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updater VARCHAR(64) NULL DEFAULT '' COMMENT '更新者', + update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + deleted BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + active_user_id BIGINT GENERATED ALWAYS AS ( + CASE WHEN left_at IS NULL THEN user_id ELSE NULL END + ) STORED, + active_pm_project_id BIGINT GENERATED ALWAYS AS ( + CASE WHEN project_role = 'pm' AND left_at IS NULL THEN project_id ELSE NULL END + ) STORED, + PRIMARY KEY (id), + UNIQUE KEY uk_project_active_member (project_id, active_user_id), + UNIQUE KEY uk_project_active_pm (active_pm_project_id), + KEY idx_pm_user_active (user_id, left_at), + KEY idx_pm_project_role_active (project_id, project_role, left_at), + CONSTRAINT chk_project_role CHECK (project_role IN ('pm', 'product', 'developer', 'tester', 'viewer')), + CONSTRAINT chk_member_type CHECK (member_type IN ('core', 'support')) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='项目成员表'; +``` + +### 这里有一个关键点 + +设计文档中的这段 SQL: + +```sql +CREATE UNIQUE INDEX uk_one_pm_per_project +ON system_project_member(project_id) +WHERE project_role = 'pm' AND left_at IS NULL; +``` + +在 MySQL 8 里不能直接这样写,因为 MySQL 不支持带 `WHERE` 的部分唯一索引。 + +所以推荐用上面的“生成列 + 唯一索引”实现: +- `active_pm_project_id` +- `UNIQUE KEY uk_project_active_pm (active_pm_project_id)` + +这是这份设计文档里最需要提前修正的一个点。 + +--- + +## 6. 最终建议的职责边界 + +### 6.1 组织与人员 + +- `system_dept`:组织树节点 +- `system_users.dept_id`:用户主组织归属 +- `system_users.position_id`:用户主岗位 +- `system_org_leader_relation`:组织负责人关系 +- `system_user_management_relation`:直接管理关系 + +### 6.2 功能权限 + +- `system_role` +- `system_user_role` +- `system_menu` +- `system_role_menu` + +只管“能不能访问模块/菜单/接口”。 + +### 6.3 数据范围 + +- `system_project_member` +- `system_org_leader_relation` +- `system_user_visibility_config` + +只管“能看哪些项目/哪些人的数据”。 + +--- + +## 7. 推荐迁移顺序 + +### 第一阶段:建立正确主模型 + +1. 给 `system_dept` 增加 `org_type`、`path`、`level` +2. 给 `system_users` 增加 `position_id`、`employment_status`、`resigned_at` +3. 给 `system_post` 增加 `post_type`、`level_rank` + +### 第二阶段:建立关系表 + +1. 新建 `system_org_leader_relation` +2. 把 `system_dept.leader_user_id` 迁移进去 +3. 新建 `system_user_management_relation` +4. 新建 `system_user_visibility_config` + +### 第三阶段:建立项目权限模型 + +1. 新建 `system_project_member` +2. 所有项目角色改从 `system_project_member` 读取 +3. 所有项目可见范围改从“自己参与 + 组织负责人 + 特殊配置”计算 + +### 第四阶段:按最终模型收口 + +1. 删除 `system_dept.leader_user_id` +2. 删除 `system_users.post_ids` +3. 删除 `system_user_post` +4. 保持 `system_role` 仅承载 RBAC 角色定义 + +--- + +## 8. 你这次最应该优先改的地方 + +如果你想最小成本先把模型拉正,我建议优先级按下面来: + +1. `system_dept` 补 `path`、`org_type`、`code`,删除 `leader_user_id` +2. `system_users` 增加 `position_id`,删除 `post_ids` +3. 新建 `system_org_leader_relation` +4. 新建 `system_project_member` +5. 新建 `system_user_visibility_config` 体系 +6. 删除 `system_user_post`,并让岗位只保留单一事实来源 +7. 保持 `system_role` 精简,只保留设计文档需要的 RBAC 能力 + +这 7 步做完,表结构才算真正和当前权限设计文档一致。