Browse Source

commit

master
luoweijian 1 month ago
parent
commit
ceaff54863
  1. 97
      .qoder/repowiki/zh/content/API参考文档/API参考文档.md
  2. 183
      .qoder/repowiki/zh/content/开发指南/开发规范.md
  3. 271
      .qoder/repowiki/zh/content/数据模型/数据模型.md
  4. 144
      .qoder/repowiki/zh/content/架构设计/安全架构设计/安全架构设计.md
  5. 160
      .qoder/repowiki/zh/content/认证服务/认证服务.md
  6. 161
      .qoder/repowiki/zh/content/部署指南.md
  7. 221
      .qoder/repowiki/zh/content/配置指南/配置指南.md
  8. 572
      .qoder/repowiki/zh/content/项目概览/模块说明/基础框架模块(crm-base)/基础框架模块(crm-base).md
  9. 266
      .qoder/repowiki/zh/content/项目概览/模块说明/模块说明.md
  10. 2
      .qoder/repowiki/zh/meta/repowiki-metadata.json
  11. 2
      crm-app/target/classes/application.yml
  12. BIN
      crm-app/target/classes/com/crm/app/CrmAppApplication.class
  13. 1
      crm-auth/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
  14. BIN
      crm-base/target/classes/com/crm/base/advice/GlobalExceptionHandlerAdvice.class
  15. BIN
      crm-base/target/classes/com/crm/base/config/CorsConfig.class
  16. BIN
      crm-base/target/classes/com/crm/base/config/CrmSqlInjector.class
  17. BIN
      crm-base/target/classes/com/crm/base/config/CustomIdGenerator.class
  18. BIN
      crm-base/target/classes/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.class
  19. BIN
      crm-base/target/classes/com/crm/base/config/JacksonConfig.class
  20. BIN
      crm-base/target/classes/com/crm/base/config/Knife4jConfig.class
  21. BIN
      crm-base/target/classes/com/crm/base/config/MetaObjectFillHandler.class
  22. BIN
      crm-base/target/classes/com/crm/base/config/MybatisPlusConfig.class
  23. BIN
      crm-base/target/classes/com/crm/base/config/RedisConfig.class
  24. BIN
      crm-base/target/classes/com/crm/base/config/ScheduledTaskProperties.class
  25. BIN
      crm-base/target/classes/com/crm/base/config/SnowflakeIdWorker.class
  26. BIN
      crm-base/target/classes/com/crm/base/config/SnowflakeProperties.class
  27. BIN
      crm-base/target/classes/com/crm/base/constant/CommonConstants.class
  28. BIN
      crm-base/target/classes/com/crm/base/domain/dto/BaseDTO.class
  29. BIN
      crm-base/target/classes/com/crm/base/domain/entity/BaseEntity.class
  30. BIN
      crm-base/target/classes/com/crm/base/domain/entity/OwnedEntity.class
  31. BIN
      crm-base/target/classes/com/crm/base/domain/enums/HasValueEnum.class
  32. BIN
      crm-base/target/classes/com/crm/base/domain/enums/StatusEnum.class
  33. BIN
      crm-base/target/classes/com/crm/base/domain/exception/BusinessErrorException.class
  34. BIN
      crm-base/target/classes/com/crm/base/domain/exception/MissingParameterException.class
  35. BIN
      crm-base/target/classes/com/crm/base/domain/exception/PermissionErrorException.class
  36. BIN
      crm-base/target/classes/com/crm/base/domain/exception/ResourceNotExistException.class
  37. BIN
      crm-base/target/classes/com/crm/base/domain/param/BaseParam.class
  38. BIN
      crm-base/target/classes/com/crm/base/domain/result/PageResult.class
  39. BIN
      crm-base/target/classes/com/crm/base/domain/result/Result.class
  40. BIN
      crm-base/target/classes/com/crm/base/domain/result/ResultCodeEnum.class
  41. BIN
      crm-base/target/classes/com/crm/base/filter/TraceIdFilter.class
  42. BIN
      crm-base/target/classes/com/crm/base/mapper/CrmBaseMapper.class
  43. BIN
      crm-base/target/classes/com/crm/base/security/DataOwnership.class
  44. BIN
      crm-base/target/classes/com/crm/base/security/DataScopeHelper.class
  45. BIN
      crm-base/target/classes/com/crm/base/security/DataScopeLevel.class
  46. BIN
      crm-base/target/classes/com/crm/base/security/DataVisibility.class
  47. BIN
      crm-base/target/classes/com/crm/base/security/DataVisibilityContext.class
  48. BIN
      crm-base/target/classes/com/crm/base/security/SecurityUtils.class
  49. BIN
      crm-base/target/classes/com/crm/base/security/VisibilityScope$Kind.class
  50. BIN
      crm-base/target/classes/com/crm/base/security/VisibilityScope.class
  51. BIN
      crm-base/target/classes/com/crm/base/service/IBaseService.class
  52. BIN
      crm-base/target/classes/com/crm/base/service/impl/BaseServiceImpl.class
  53. BIN
      crm-base/target/classes/com/crm/base/utils/AssertUtils.class
  54. BIN
      crm-base/target/classes/com/crm/base/utils/BeanCopyUtils.class
  55. BIN
      crm-base/target/classes/com/crm/base/utils/EnumUtils.class
  56. BIN
      crm-base/target/classes/com/crm/base/utils/ExcelUtil.class
  57. BIN
      crm-base/target/classes/com/crm/base/utils/PageConverter.class
  58. BIN
      crm-base/target/classes/com/crm/base/utils/ServletUtils.class
  59. BIN
      crm-base/target/classes/com/crm/base/utils/TreeUtils.class
  60. 30
      crm-base/target/surefire-reports/TEST-com.crm.base.security.DataVisibilityTest.xml
  61. 2
      crm-base/target/surefire-reports/com.crm.base.security.DataVisibilityTest.txt
  62. BIN
      crm-base/target/test-classes/com/crm/base/security/DataVisibilityTest.class
  63. 72
      mcp_call.py

97
.qoder/repowiki/zh/content/API参考文档/API参考文档.md

@ -31,10 +31,21 @@
- [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java) - [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java)
- [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java) - [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java)
- [FileDownloadDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileDownloadDTO.java) - [FileDownloadDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileDownloadDTO.java)
- [ThumbnailDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/ThumbnailDTO.java)
- [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
</cite> </cite>
## 更新摘要
**变更内容**
- 新增缩略图获取API端点 `/api/file/thumbnail` 的详细文档
- 添加缩略图生成功能的完整说明
- 更新文件服务模块的API清单
- 补充缩略图相关的错误处理和状态码说明
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
2. [项目结构](#项目结构) 2. [项目结构](#项目结构)
@ -55,7 +66,7 @@
- crm-app:应用启动入口与全局配置 - crm-app:应用启动入口与全局配置
- crm-auth:认证鉴权与系统管理(用户、角色、菜单、部门) - crm-auth:认证鉴权与系统管理(用户、角色、菜单、部门)
- crm-base:通用基础能力(统一响应、异常处理、安全上下文、分页等) - crm-base:通用基础能力(统一响应、异常处理、安全上下文、分页等)
- crm-file:文件服务(分片上传、断点续传、预览、下载) - crm-file:文件服务(分片上传、断点续传、预览、下载、缩略图生成
```mermaid ```mermaid
graph TB graph TB
@ -69,7 +80,7 @@ subgraph "基础能力"
BASE["crm-base<br/>通用组件/异常/结果封装"] BASE["crm-base<br/>通用组件/异常/结果封装"]
end end
subgraph "文件服务" subgraph "文件服务"
FILE["crm-file<br/>文件上传/下载/预览"] FILE["crm-file<br/>文件上传/下载/预览/缩略图"]
end end
APP --> AUTH APP --> AUTH
APP --> FILE APP --> FILE
@ -92,8 +103,10 @@ FILE --> BASE
- 安全上下文 LoginUser/AuthLoginUser:当前登录用户信息与权限范围 - 安全上下文 LoginUser/AuthLoginUser:当前登录用户信息与权限范围
- TokenService:JWT签发、解析、刷新与黑名单管理 - TokenService:JWT签发、解析、刷新与黑名单管理
- JwtAuthenticationFilter:请求级JWT校验与上下文注入 - JwtAuthenticationFilter:请求级JWT校验与上下文注入
- FileApi/FileApiImpl:文件上传下载、分片、预览、清理等能力抽象与实现 - FileApi/FileApiImpl:文件上传下载、分片、预览、清理、缩略图生成等能力抽象与实现
- FileInfoService:文件元数据持久化与查询 - FileInfoService:文件元数据持久化与查询
- ThumbnailGenerationTask:异步缩略图生成任务
- ThumbnailPlaceholderService:动态生成文件类型占位图
章节来源 章节来源
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
@ -105,9 +118,11 @@ FILE --> BASE
- [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java) - [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java)
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
- [FileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java) - [FileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java)
## 架构总览 ## 架构总览
整体调用链路:客户端通过HTTP访问Controller,Controller调用Service完成业务逻辑,Service通过Mapper访问数据库或调用外部存储(如MinIO)。认证流程由Spring Security过滤器链拦截,基于JWT进行鉴权;权限控制通过注解与数据权限拦截器实现。 整体调用链路:客户端通过HTTP访问Controller,Controller调用Service完成业务逻辑,Service通过Mapper访问数据库或调用外部存储(如MinIO)。认证流程由Spring Security过滤器链拦截,基于JWT进行鉴权;权限控制通过注解与数据权限拦截器实现。缩略图功能采用异步生成+同步兜底的策略,确保用户体验。
```mermaid ```mermaid
sequenceDiagram sequenceDiagram
@ -115,22 +130,35 @@ participant Client as "客户端"
participant AuthF as "JwtAuthenticationFilter" participant AuthF as "JwtAuthenticationFilter"
participant Controller as "Controller" participant Controller as "Controller"
participant Service as "Service" participant Service as "Service"
participant Task as "ThumbnailGenerationTask"
participant DB as "数据库/对象存储" participant DB as "数据库/对象存储"
Client->>AuthF : "携带Authorization : Bearer <token>" Client->>AuthF : "携带Authorization : Bearer <token>"
AuthF->>AuthF : "校验签名/过期时间" AuthF->>AuthF : "校验签名/过期时间"
AuthF-->>Client : "未通过则返回401" AuthF-->>Client : "未通过则返回401"
AuthF->>Controller : "通过则注入登录用户上下文" AuthF->>Controller : "通过则注入登录用户上下文"
Controller->>Service : "执行业务方法" Controller->>Service : "执行业务方法"
alt 缩略图请求
Service->>Task : "检查缩略图状态"
alt 需要生成
Task->>DB : "异步生成缩略图"
Service-->>Client : "返回占位图或等待"
else 已有缩略图
Service->>DB : "读取缩略图"
Service-->>Client : "返回缩略图"
end
else 其他操作
Service->>DB : "读写数据/文件元信息" Service->>DB : "读写数据/文件元信息"
DB-->>Service : "返回结果" DB-->>Service : "返回结果"
Service-->>Controller : "业务结果" Service-->>Controller : "业务结果"
Controller-->>Client : "统一Result包装响应" Controller-->>Client : "统一Result包装响应"
end
``` ```
图表来源 图表来源
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
## 详细组件分析 ## 详细组件分析
@ -241,6 +269,20 @@ JwtAuthenticationFilter --> TokenService : "校验"
- 响应:HTML预览页面或重定向到在线预览地址 - 响应:HTML预览页面或重定向到在线预览地址
- 状态码:200成功;404文件不存在;403无权限 - 状态码:200成功;404文件不存在;403无权限
- **新增:缩略图获取**
- 缩略图:GET /api/file/thumbnail
- 请求参数:fileId(必填,文件ID)
- 响应:二进制图片流(image/jpeg或image/png)
- 状态码:200成功(已就绪或占位图);202接受(正在生成中)
- 缓存控制:根据缩略图状态自动设置Cache-Control头
- cacheable=true:max-age=86400(强缓存1天)
- cacheable=false:no-cache(不缓存)
- 功能特性:
- 智能状态检测:READY直接返回缩略图,PENDING触发异步生成
- 同步兜底:首次请求时尝试同步生成,避免长时间等待
- 占位图降级:UNSUPPORTED/FAILED/读取失败时返回动态占位图
- 分布式锁:防止并发重复生成,提高性能
- 文件元数据管理 - 文件元数据管理
- 列表:GET /file/list - 列表:GET /file/list
- 查询参数:page、size、keyword、type、ownerId等 - 查询参数:page、size、keyword、type、ownerId等
@ -283,6 +325,10 @@ Error --> End
- [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java) - [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java)
- [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java) - [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java)
- [FileDownloadDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileDownloadDTO.java) - [FileDownloadDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileDownloadDTO.java)
- [ThumbnailDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/ThumbnailDTO.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java)
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
@ -309,6 +355,7 @@ Error --> End
- 控制器依赖服务接口,服务实现依赖数据访问与外部存储 - 控制器依赖服务接口,服务实现依赖数据访问与外部存储
- 认证过滤器依赖TokenService进行JWT校验 - 认证过滤器依赖TokenService进行JWT校验
- 文件服务依赖MinIO配置与属性配置 - 文件服务依赖MinIO配置与属性配置
- 缩略图功能依赖ThumbnailGenerationTask进行异步生成
- 统一异常处理贯穿各模块 - 统一异常处理贯穿各模块
```mermaid ```mermaid
@ -320,8 +367,10 @@ FC["FileController"] --> FApi["FileApi"]
FApi --> FImpl["FileApiImpl"] FApi --> FImpl["FileApiImpl"]
FImpl --> FInfoSvc["IFileInfoService"] FImpl --> FInfoSvc["IFileInfoService"]
FInfoSvc --> FInfoImpl["FileInfoServiceImpl"] FInfoSvc --> FInfoImpl["FileInfoServiceImpl"]
FImpl --> TGT["ThumbnailGenerationTask"]
Tok --> Sec["JwtAuthenticationFilter"] Tok --> Sec["JwtAuthenticationFilter"]
FImpl --> Minio["MinIO(外部存储)"] FImpl --> Minio["MinIO(外部存储)"]
TGT --> Minio
``` ```
图表来源 图表来源
@ -335,6 +384,7 @@ FImpl --> Minio["MinIO(外部存储)"]
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
- [FileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java) - [FileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java)
- [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
章节来源 章节来源
@ -343,6 +393,7 @@ FImpl --> Minio["MinIO(外部存储)"]
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
## 性能考虑 ## 性能考虑
@ -356,6 +407,12 @@ FImpl --> Minio["MinIO(外部存储)"]
- 分页查询 - 分页查询
- 使用合理的page/size,避免大偏移量查询 - 使用合理的page/size,避免大偏移量查询
- 对常用查询条件建立索引 - 对常用查询条件建立索引
- **缩略图优化**
- 异步生成:上传完成后后台异步生成,不阻塞主流程
- 分布式锁:防止并发重复生成,提高系统稳定性
- 智能缓存:根据状态设置合适的缓存策略,减少重复请求
- 占位图降级:生成失败或类型不支持时快速返回占位图
- 同步兜底:首次请求时尝试同步生成,提升用户体验
## 故障排查指南 ## 故障排查指南
- 401 未认证 - 401 未认证
@ -370,15 +427,21 @@ FImpl --> Minio["MinIO(外部存储)"]
- 调整服务端最大文件大小配置 - 调整服务端最大文件大小配置
- 400 参数校验失败 - 400 参数校验失败
- 检查必填字段、格式与长度限制 - 检查必填字段、格式与长度限制
- **缩略图相关问题**
- 202 Accepted:缩略图正在生成中,稍后重试即可
- 占位图显示:文件类型不支持或生成失败,属于正常降级
- 缓存问题:检查Cache-Control头设置是否符合预期
- 生成超时:检查缩略图生成任务的执行时间和重试配置
章节来源 章节来源
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java) - [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java)
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
## 结论 ## 结论
本文档从架构到接口细节全面梳理了CRM后端的认证鉴权、系统管理与文件服务三大模块的API规范。通过统一的响应与异常处理、严格的权限控制与健壮的分片上传机制,为前端提供了稳定可靠的集成基础。建议在前端集成时严格遵循参数校验与错误处理规范,并结合测试用例验证关键流程。 本文档从架构到接口细节全面梳理了CRM后端的认证鉴权、系统管理与文件服务三大模块的API规范。通过统一的响应与异常处理、严格的权限控制与健壮的分片上传机制,为前端提供了稳定可靠的集成基础。**新增的缩略图功能**进一步增强了文件处理能力,支持多种文件类型的缩略图生成,具备智能缓存控制和完善的降级机制。建议在前端集成时严格遵循参数校验与错误处理规范,并结合测试用例验证关键流程。
## 附录 ## 附录
@ -409,6 +472,11 @@ FImpl --> Minio["MinIO(外部存储)"]
- 响应:二进制流 - 响应:二进制流
- GET /file/preview/{fileId} - GET /file/preview/{fileId}
- 响应:HTML预览或重定向 - 响应:HTML预览或重定向
- **GET /api/file/thumbnail?fileId={fileId}**
- 请求参数:fileId(必填)
- 响应:二进制图片流(image/jpeg或image/png)
- 状态码:200成功;202接受(生成中)
- 缓存头:Cache-Control根据状态自动设置
- GET /file/list?page=1&size=10&keyword=... - GET /file/list?page=1&size=10&keyword=...
- 响应:Result~PageResult~FileInfoDTO~ - 响应:Result~PageResult~FileInfoDTO~
@ -429,6 +497,10 @@ FImpl --> Minio["MinIO(外部存储)"]
- 分页查询 - 分页查询
- page>=1,size<=100(可配置) - page>=1,size<=100(可配置)
- keyword:模糊匹配,长度<=100 - keyword:模糊匹配,长度<=100
- **缩略图请求**
- fileId:必填,必须是有效的文件ID
- 支持的文件类型:图片、PDF、Office文档等(取决于渲染器配置)
- 缓存策略:自动生成,无需手动控制
### 接口测试用例(示例) ### 接口测试用例(示例)
- 登录成功 - 登录成功
@ -443,6 +515,13 @@ FImpl --> Minio["MinIO(外部存储)"]
- 权限不足 - 权限不足
- 步骤:使用低权限token访问/system/role/* - 步骤:使用低权限token访问/system/role/*
- 期望:code=403,message提示权限不足 - 期望:code=403,message提示权限不足
- **缩略图测试**
- 已就绪文件:GET /api/file/thumbnail?fileId={ready_file_id}
- 期望:200状态码,返回image/jpeg缩略图,Cache-Control: max-age=86400
- 生成中文件:GET /api/file/thumbnail?fileId={pending_file_id}
- 期望:可能返回202状态码,Cache-Control: no-cache,稍后重试
- 不支持类型:GET /api/file/thumbnail?fileId={unsupported_file_id}
- 期望:200状态码,返回image/png占位图,Cache-Control: no-cache
### 常见问题解答 ### 常见问题解答
- Q:如何获取并保存token? - Q:如何获取并保存token?
@ -452,4 +531,10 @@ FImpl --> Minio["MinIO(外部存储)"]
- Q:分片上传失败如何恢复? - Q:分片上传失败如何恢复?
- A:记录已上传的分片序号,合并前校验MD5,缺失分片继续上传 - A:记录已上传的分片序号,合并前校验MD5,缺失分片继续上传
- Q:如何限制文件类型与大小? - Q:如何限制文件类型与大小?
- A:在FileProperties中配置允许的类型与大小上限,并在前端做二次校验 - A:在FileProperties中配置允许的类型与大小上限,并在前端做二次校验
- **Q:缩略图加载慢怎么办?**
- A:首次请求会触发异步生成,后续请求会命中缓存;如果持续慢,检查缩略图生成任务的执行情况和MinIO性能
- **Q:为什么有些文件没有缩略图?**
- A:可能是文件类型不支持,或者缩略图生成失败;系统会自动返回占位图作为降级处理
- **Q:如何优化缩略图的缓存效果?**
- A:系统已自动设置合适的Cache-Control头;对于已就绪的缩略图会设置1天的强缓存,对于生成中的文件使用no-cache

183
.qoder/repowiki/zh/content/开发指南/开发规范.md

@ -58,9 +58,25 @@
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
- [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java)
- [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java)
- [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
- [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java)
- [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
- [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java)
- [UserListDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserListDTO.java)
- [RoleDetailVO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/RoleDetailVO.java)
- [UserStatsVO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserStatsVO.java)
- [pom.xml](file://pom.xml) - [pom.xml](file://pom.xml)
</cite> </cite>
## 更新摘要
**变更内容**
- 更新了数据传输对象设计规范章节,增加了DictGroupVO和DictItemVO的实践案例
- 完善了DTO设计模式说明,展示了如何避免直接暴露实体内部结构
- 增强了BaseDTO设计原则的实际应用示例
- 补充了VO与Entity分离的最佳实践指导
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
2. [项目结构](#项目结构) 2. [项目结构](#项目结构)
@ -82,6 +98,7 @@
- crm-base:基础能力(通用实体、DTO/Param/Result、安全上下文、数据权限、异常、工具类、MyBatis Plus 配置) - crm-base:基础能力(通用实体、DTO/Param/Result、安全上下文、数据权限、异常、工具类、MyBatis Plus 配置)
- crm-auth:认证授权与系统管理(用户、角色、菜单、部门、第三方登录等) - crm-auth:认证授权与系统管理(用户、角色、菜单、部门、第三方登录等)
- crm-file:文件服务(上传、分片、预览、清理任务等) - crm-file:文件服务(上传、分片、预览、清理任务等)
- crm-dict:数据字典服务(分组、项管理、引用计数等)
```mermaid ```mermaid
graph TB graph TB
@ -91,14 +108,17 @@ end
subgraph "业务域" subgraph "业务域"
AUTH["crm-auth<br/>认证与系统管理"] AUTH["crm-auth<br/>认证与系统管理"]
FILE["crm-file<br/>文件服务"] FILE["crm-file<br/>文件服务"]
DICT["crm-dict<br/>数据字典服务"]
end end
subgraph "基础能力" subgraph "基础能力"
BASE["crm-base<br/>通用实体/DTO/Param/Result<br/>安全上下文/异常/工具/配置"] BASE["crm-base<br/>通用实体/DTO/Param/Result<br/>安全上下文/异常/工具/配置"]
end end
APP --> AUTH APP --> AUTH
APP --> FILE APP --> FILE
APP --> DICT
AUTH --> BASE AUTH --> BASE
FILE --> BASE FILE --> BASE
DICT --> BASE
``` ```
**图示来源** **图示来源**
@ -194,7 +214,7 @@ AuthCtrl-->>Client : "登录成功响应"
- 使用方式:所有持久化实体继承 BaseEntity;配合元数据填充处理器自动设置审计字段 - 使用方式:所有持久化实体继承 BaseEntity;配合元数据填充处理器自动设置审计字段
- 复杂度:O(1) 字段赋值,填充发生在插入/更新前 - 复杂度:O(1) 字段赋值,填充发生在插入/更新前
- OwnedEntity - OwnedEntity
- 职责:在 BaseEntity 基础上增加“数据所有者”字段,用于数据隔离与权限过滤 - 职责:在 BaseEntity 基础上增加"数据所有者"字段,用于数据隔离与权限过滤
- 使用方式:需要数据归属控制的实体继承 OwnedEntity;结合 DataOwnership/DataScope 注解与上下文进行行级过滤 - 使用方式:需要数据归属控制的实体继承 OwnedEntity;结合 DataOwnership/DataScope 注解与上下文进行行级过滤
- 注意:避免在批量操作中遗漏数据所有者,确保上下文正确设置 - 注意:避免在批量操作中遗漏数据所有者,确保上下文正确设置
@ -221,12 +241,17 @@ BaseEntity <|-- OwnedEntity : "继承"
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
### 数据传输对象设计(DTO、Param、Result) ### 数据传输对象设计(DTO、Param、Result)
**更新** 数据传输对象设计规范得到实践验证,通过 DictGroupVO 和 DictItemVO 的重构展示了如何避免直接暴露实体内部结构,遵循了 BaseDTO 的设计原则。
- BaseDTO - BaseDTO
- 用途:作为通用 DTO 基类,承载接口返回数据或跨层传输数据 - 用途:作为通用 DTO 基类,承载接口返回数据或跨层传输数据
- 建议:仅包含必要字段,避免直接暴露实体内部结构 - 建议:仅包含必要字段,避免直接暴露实体内部结构
- 特性:支持 Entity 到 DTO 的自动转换,包含序列化支持和状态字段
- BaseParam - BaseParam
- 用途:作为通用请求参数基类,承载入参校验与封装 - 用途:作为通用请求参数基类,承载入参校验与封装
- 建议:与表单/查询参数一一对应,必要时使用分组校验 - 建议:与表单/查询参数一一对应,必要时使用分组校验
- 特性:内置分页参数、关键字搜索、排序功能
- Result/PageResult - Result/PageResult
- 用途:统一 API 响应包装,包含状态码、消息、数据体;PageResult 扩展分页信息 - 用途:统一 API 响应包装,包含状态码、消息、数据体;PageResult 扩展分页信息
- 建议:保持响应结构一致,便于前端解析与错误处理 - 建议:保持响应结构一致,便于前端解析与错误处理
@ -234,37 +259,106 @@ BaseEntity <|-- OwnedEntity : "继承"
- ResultCodeEnum:统一错误码定义,避免硬编码 - ResultCodeEnum:统一错误码定义,避免硬编码
- 业务枚举:集中定义于 domain/enums 包下,保证一致性 - 业务枚举:集中定义于 domain/enums 包下,保证一致性
#### 实践案例:DictGroupVO 和 DictItemVO
DictGroupVO 和 DictItemVO 是数据传输对象设计规范的优秀实践案例:
**DictGroupVO** - 字典分组视图对象
- 独立字段设计:不继承实体,只暴露前端需要的业务字段
- 排除敏感字段:不包含审计字段(creatorId/updaterId/updateTime/deleted)和软删内部字段(deleteKey)
- 业务增强字段:包含 itemCount(分组下未删除的字典项数量)
- 适用场景:分页列表展示
**DictItemVO** - 字典项视图对象
- 独立字段设计:不继承实体,只暴露前端需要的业务字段
- 排除敏感字段:不包含审计字段和软删内部字段
- 业务增强字段:包含 groupName(所属分组名称)、isDefault(是否为分组默认项)、referenced(是否被业务引用)、effectiveSelectable(是否有效可选)
- 实时数据:referenced 字段读取实时引用计数,不进入缓存
- 适用场景:分页列表展示
```mermaid ```mermaid
classDiagram classDiagram
class BaseDTO { class BaseEntity {
+通用DTO字段 +id : Long
+creatorId : String
+createTime : LocalDateTime
+updaterId : String
+updateTime : LocalDateTime
+deleted : Boolean
} }
class BaseParam { class DictGroup {
+通用参数字段 +name : String
+校验规则 +code : String
+sortNo : Integer
+status : Integer
+description : String
+builtin : Boolean
+deleteKey : Long
} }
class Result { class DictItem {
+状态码 +groupId : Long
+消息 +name : String
+数据体 +code : String
+value : String
+sortNo : Integer
+status : Integer
+description : String
+builtin : Boolean
+deleteKey : Long
} }
class PageResult { class DictGroupVO {
+分页信息 +id : Long
+数据列表 +name : String
+code : String
+sortNo : Integer
+status : Integer
+description : String
+builtin : Boolean
+createTime : LocalDateTime
+itemCount : Long
} }
class ResultCodeEnum { class DictItemVO {
+错误码定义 +id : Long
+groupId : Long
+name : String
+code : String
+value : String
+sortNo : Integer
+status : Integer
+description : String
+builtin : Boolean
+createTime : LocalDateTime
+groupName : String
+isDefault : Boolean
+referenced : Boolean
+effectiveSelectable : Boolean
} }
Result --> ResultCodeEnum : "引用" BaseEntity <|-- DictGroup : "继承"
PageResult --> Result : "扩展" BaseEntity <|-- DictItem : "继承"
DictGroup --> DictGroupVO : "转换为"
DictItem --> DictItemVO : "转换为"
``` ```
**图示来源** **图示来源**
- [BaseDTO.java](file://crm-base/src/main/java/com/crm/base/domain/dto/BaseDTO.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [BaseParam.java](file://crm-base/src/main/java/com/crm/base/domain/param/BaseParam.java) - [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java)
- [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
#### DTO 转换机制
服务层使用 toDTO 方法进行实体到 DTO 的转换:
```java
// DictGroupServiceImpl 中的使用示例
PageResult<DictGroupVO> result = new PageResult<>(page)
.convert(g -> g.toDTO(DictGroupVO::new));
// DictItemServiceImpl 中的使用示例
PageResult<DictItemVO> result = new PageResult<>(page)
.convert(i -> i.toDTO(DictItemVO::new));
```
**章节来源** **章节来源**
- [BaseDTO.java](file://crm-base/src/main/java/com/crm/base/domain/dto/BaseDTO.java) - [BaseDTO.java](file://crm-base/src/main/java/com/crm/base/domain/dto/BaseDTO.java)
@ -272,6 +366,10 @@ PageResult --> Result : "扩展"
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
- [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java)
- [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java)
- [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
- [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
- [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java)
### 认证与鉴权流程 ### 认证与鉴权流程
- 登录流程 - 登录流程
@ -389,17 +487,19 @@ ExecQuery --> Return["返回受控结果"]
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
## 依赖分析 ## 依赖分析
模块间依赖关系清晰,遵循“上层依赖下层”的原则: 模块间依赖关系清晰,遵循"上层依赖下层"的原则:
- crm-app 依赖 crm-auth 与 crm-file - crm-app 依赖 crm-auth、crm-file 与 crm-dict
- crm-auth 与 crm-file 均依赖 crm-base - crm-auth、crm-file 与 crm-dict 均依赖 crm-base
- 各模块内按 controller -> service -> mapper 分层依赖 - 各模块内按 controller -> service -> mapper 分层依赖
```mermaid ```mermaid
graph LR graph LR
APP["crm-app"] --> AUTH["crm-auth"] APP["crm-app"] --> AUTH["crm-auth"]
APP --> FILE["crm-file"] APP --> FILE["crm-file"]
APP --> DICT["crm-dict"]
AUTH --> BASE["crm-base"] AUTH --> BASE["crm-base"]
FILE --> BASE FILE --> BASE
DICT --> BASE
``` ```
**图示来源** **图示来源**
@ -414,8 +514,7 @@ FILE --> BASE
- 数据权限:尽量将数据权限条件下推到 SQL 层,减少内存过滤 - 数据权限:尽量将数据权限条件下推到 SQL 层,减少内存过滤
- 缓存与限流:对热点数据(如部门树、菜单)考虑引入缓存;对外部调用(如第三方登录、文件预览)增加超时与重试策略 - 缓存与限流:对热点数据(如部门树、菜单)考虑引入缓存;对外部调用(如第三方登录、文件预览)增加超时与重试策略
- 分页查询:合理使用分页,避免一次性加载大量数据 - 分页查询:合理使用分页,避免一次性加载大量数据
- DTO 优化:通过独立的 VO 对象减少数据传输量,避免暴露不必要的实体字段
[本节为通用指导,不直接分析具体文件]
## 故障排查指南 ## 故障排查指南
- 全局异常处理 - 全局异常处理
@ -438,7 +537,7 @@ FILE --> BASE
- [TraceIdFilter.java](file://crm-base/src/main/java/com/crm/base/filter/TraceIdFilter.java) - [TraceIdFilter.java](file://crm-base/src/main/java/com/crm/base/filter/TraceIdFilter.java)
## 结论 ## 结论
本规范从代码风格、命名约定、包结构到实体与 DTO 设计、异常与日志、Git 工作流与代码审查,提供了完整的开发标准。遵循这些规范有助于提升代码质量、降低协作成本,并为后续扩展与维护奠定基础。 本规范从代码风格、命名约定、包结构到实体与 DTO 设计、异常与日志、Git 工作流与代码审查,提供了完整的开发标准。通过 DictGroupVO 和 DictItemVO 的实践案例,进一步验证了数据传输对象设计规范的有效性。遵循这些规范有助于提升代码质量、降低协作成本,并为后续扩展与维护奠定基础。
## 附录 ## 附录
@ -471,10 +570,28 @@ FILE --> BASE
- 字段注释完整,便于文档生成与理解 - 字段注释完整,便于文档生成与理解
### DTO、Param、Result 设计模式 ### DTO、Param、Result 设计模式
- DTO:面向接口输出,精简字段,避免泄露内部结构
- Param:面向输入,严格校验,必要时使用分组校验 **更新** 数据传输对象设计模式的实践验证:
- Result/PageResult:统一响应格式,便于前端解析
- 枚举:集中定义,避免魔法值 - **DTO 设计原则**
- 面向接口输出,精简字段,避免泄露内部结构
- 独立字段设计,不直接继承实体,按需组合业务字段
- 排除敏感字段(审计字段、软删字段等)
- 支持 Entity 到 DTO 的自动转换
- **实践案例**
- DictGroupVO:仅包含前端需要的分组展示字段和业务增强字段
- DictItemVO:包含字典项基本信息和运行时计算的业务字段
- UserListDTO:反范式组装,后端批量填充关联数据
- **Param 设计原则**
- 面向输入,严格校验,必要时使用分组校验
- 继承 BaseParam 获得通用分页和搜索功能
- **Result 设计原则**
- 统一响应格式,便于前端解析
- PageResult 扩展分页信息
- 枚举:集中定义,避免魔法值
### 异常处理规范 ### 异常处理规范
- 自定义异常分类:业务异常、参数异常、权限异常、资源不存在异常 - 自定义异常分类:业务异常、参数异常、权限异常、资源不存在异常
@ -494,7 +611,7 @@ FILE --> BASE
### Git 提交信息规范 ### Git 提交信息规范
- 格式:<type>(<scope>): <subject> - 格式:<type>(<scope>): <subject>
- type:feat、fix、docs、style、refactor、test、chore - type:feat、fix、docs、style、refactor、test、chore
- scope:模块或功能范围(如 auth、file、base) - scope:模块或功能范围(如 auth、file、base、dict
- subject:简洁明了,不超过 50 字符 - subject:简洁明了,不超过 50 字符
### 分支管理策略 ### 分支管理策略

271
.qoder/repowiki/zh/content/数据模型/数据模型.md

@ -1,3 +1,5 @@
现在我已经收集了足够的信息来更新数据模型文档。基于分析,FileInfo实体确实新增了thumbnail_status和thumbnail_retry_count两个字段,用于跟踪缩略图生成状态和重试次数。让我更新文档:
# 数据模型 # 数据模型
<cite> <cite>
@ -11,6 +13,11 @@
- [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java) - [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java)
- [AuthIdentity.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthIdentity.java) - [AuthIdentity.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthIdentity.java)
- [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java)
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [ThumbnailRetryTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailRetryTask.java)
- [ThumbnailDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/ThumbnailDTO.java)
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java)
- [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java)
@ -33,12 +40,11 @@
## 更新摘要 ## 更新摘要
**变更内容** **变更内容**
- 增强了角色管理系统的验证规则和约束条件 - FileInfo实体新增缩略图状态跟踪机制,包含thumbnail_status和thumbnail_retry_count两个新字段
- 新增数据范围限制(1-4范围),排除自定义数据范围(CUSTOM=5) - 实现完整的缩略图生命周期管理,支持PENDING、READY、FAILED、UNSUPPORTED四种状态
- 实现内置角色保护机制,防止删除和修改内置角色编码 - 添加缩略图生成失败重试机制,支持配置化重试次数限制
- 强化角色编码唯一性校验,支持跨ID的唯一性检查 - 新增缩略图异步生成任务和定时重试任务
- 新增VALID_DATA_SCOPE_VALUES集合用于API操作的数据范围验证 - 完善文件元数据结构,增强文件预览和缩略图功能
- 完善角色管理的错误码定义和业务异常处理
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
@ -55,13 +61,13 @@
## 简介 ## 简介
本文件为 CRM 后端的数据模型文档,面向数据库管理员与后端开发者。内容覆盖用户、角色、菜单、部门、身份认证、文件等核心实体的字段定义、数据类型、约束与业务含义;提供实体关系图(ER)与类图;说明主键策略、外键关联、索引设计、数据完整性约束;给出数据字典、枚举值定义、默认值设置;并补充数据迁移策略、版本兼容性与备份恢复方案。 本文件为 CRM 后端的数据模型文档,面向数据库管理员与后端开发者。内容覆盖用户、角色、菜单、部门、身份认证、文件等核心实体的字段定义、数据类型、约束与业务含义;提供实体关系图(ER)与类图;说明主键策略、外键关联、索引设计、数据完整性约束;给出数据字典、枚举值定义、默认值设置;并补充数据迁移策略、版本兼容性与备份恢复方案。
**更新** 本次更新重点反映了角色管理系统的增强功能,包括新的验证规则、数据范围限制、内置角色保护机制和角色编码唯一性强制校验 **更新** 本次更新重点反映了文件模块的缩略图功能增强,包括FileInfo实体的新字段、缩略图状态机、重试机制和异步处理流程
## 项目结构 ## 项目结构
本项目采用多模块架构: 本项目采用多模块架构:
- crm-base:基础能力(通用实体、配置、工具、异常、分页、结果封装等) - crm-base:基础能力(通用实体、配置、工具、异常、分页、结果封装等)
- crm-auth:认证授权与系统管理(用户、角色、菜单、部门、权限、数据范围等) - crm-auth:认证授权与系统管理(用户、角色、菜单、部门、权限、数据范围等)
- crm-file:文件服务(上传、分片、预览、清理任务等) - crm-file:文件服务(上传、分片、预览、清理任务、缩略图等)
- crm-app:应用启动入口与全局配置 - crm-app:应用启动入口与全局配置
```mermaid ```mermaid
@ -73,7 +79,7 @@ subgraph "认证授权"
auth["crm-auth<br/>用户/角色/菜单/部门/权限"] auth["crm-auth<br/>用户/角色/菜单/部门/权限"]
end end
subgraph "文件服务" subgraph "文件服务"
file["crm-file<br/>文件元数据/分片/预览"] file["crm-file<br/>文件元数据/分片/预览/缩略图"]
end end
subgraph "应用" subgraph "应用"
app["crm-app<br/>启动与配置"] app["crm-app<br/>启动与配置"]
@ -187,13 +193,14 @@ datetime update_time
} }
FILE_INFO { FILE_INFO {
bigint id PK bigint id PK
string bucket string original_name
string object_key string object_key
string file_name
long file_size long file_size
string mime_type string content_type
string md5 string biz_domain
int status string file_hash
string thumbnail_status
int thumbnail_retry_count
bigint create_by bigint create_by
bigint update_by bigint update_by
datetime create_time datetime create_time
@ -265,7 +272,7 @@ SYS_DEPT ||--o{ SYS_USER_DEPT : "包含"
- [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java)
- [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java)
### 角色实体(SysRole)- **已更新** ### 角色实体(SysRole)
- 字段与类型 - 字段与类型
- 主键:id(bigint,雪花ID) - 主键:id(bigint,雪花ID)
- 角色名称:roleName(varchar(50),非空) - 角色名称:roleName(varchar(50),非空)
@ -283,13 +290,6 @@ SYS_DEPT ||--o{ SYS_USER_DEPT : "包含"
- 权限集合的载体,与菜单进行多对多关联 - 权限集合的载体,与菜单进行多对多关联
- 支持数据范围控制(本人、本部门、本部门及子部门、全部数据) - 支持数据范围控制(本人、本部门、本部门及子部门、全部数据)
- 内置角色保护机制,防止误删和编码修改 - 内置角色保护机制,防止误删和编码修改
- **新增验证规则**
- dataScope必须在1-4范围内,禁止使用CUSTOM(5)
- 内置角色(builtin=true)禁止删除和修改roleCode
- 创建角色时不允许设置builtin=true
- roleCode必须全局唯一(跨ID检查)
**更新** 角色实体新增了builtin字段和增强的验证规则,包括数据范围限制和内置角色保护机制。
**章节来源** **章节来源**
- [SysRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java) - [SysRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java)
@ -377,26 +377,43 @@ SYS_DEPT ||--o{ SYS_USER_DEPT : "包含"
- [AuthIdentity.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthIdentity.java) - [AuthIdentity.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthIdentity.java)
- [IdentityTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/IdentityTypeEnum.java) - [IdentityTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/IdentityTypeEnum.java)
### 文件元数据(FileInfo) ### 文件元数据(FileInfo)- **已更新**
- 字段与类型 - 字段与类型
- 主键:id(bigint) - 主键:id(bigint)
- 存储桶:bucket(varchar) - 原始文件名:originalName(varchar(255))
- 对象键:objectKey(varchar,唯一) - 对象键:objectKey(varchar(500),唯一)
- 文件名:fileName(varchar) - 文件大小:fileSize(bigint)
- 大小:fileSize(bigint) - MIME类型:contentType(varchar(255))
- MIME类型:mimeType(varchar) - 业务域:bizDomain(varchar(64))
- 哈希:md5(varchar) - 文件哈希:fileHash(varchar(64),秒传占位字段)
- 状态:status(int,参考 StatusEnum) - **缩略图状态:thumbnailStatus(varchar(16),默认'PENDING')**
- **缩略图重试计数:thumbnailRetryCount(int,默认0)**
- 审计字段:createBy、updateBy、createTime、updateTime - 审计字段:createBy、updateBy、createTime、updateTime
- 约束与索引 - 约束与索引
- 主键:id - 主键:id
- 唯一索引:objectKey - 唯一索引:objectKey
- 建议索引:md5(去重校验)、status(过滤查询) - 建议索引:md5(去重校验)、status(过滤查询)、biz_domain(业务域查询)
- 业务含义 - 业务含义
- 记录文件在对象存储中的元数据,支撑上传、下载、预览与生命周期管理 - 记录文件在对象存储中的元数据,支撑上传、下载、预览与生命周期管理
- **新增缩略图状态跟踪机制,支持异步生成和失败重试**
- **缩略图状态机**
- PENDING:待生成(初始状态)
- READY:已生成成功
- FAILED:重试耗尽后失败
- UNSUPPORTED:文件类型不支持缩略图生成
- **重试机制**
- 支持配置化重试次数限制(默认3次)
- 失败时自动递增重试计数
- 达到重试上限后标记为FAILED
- 定时任务可重置FAILED状态重新尝试
**更新** FileInfo实体新增了thumbnail_status和thumbnail_retry_count两个字段,实现了完整的缩略图生命周期管理和失败重试机制。
**章节来源** **章节来源**
- [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java)
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [ThumbnailRetryTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailRetryTask.java)
### 类图(实体与基类关系) ### 类图(实体与基类关系)
```mermaid ```mermaid
@ -459,13 +476,14 @@ class AuthIdentity {
} }
class FileInfo { class FileInfo {
+long id +long id
+string bucket +string originalName
+string objectKey +string objectKey
+string fileName
+long fileSize +long fileSize
+string mimeType +string contentType
+string md5 +string bizDomain
+int status +string fileHash
+string thumbnailStatus
+int thumbnailRetryCount
} }
class SysUserRole { class SysUserRole {
+long id +long id
@ -517,10 +535,11 @@ OwnedEntity <|-- FileInfo
- 数据完整性 - 数据完整性
- 逻辑删除由 CrmSqlInjector 启用,避免物理删除导致关联断裂 - 逻辑删除由 CrmSqlInjector 启用,避免物理删除导致关联断裂
- 审计字段由 MetaObjectFillHandler 统一填充,确保一致性 - 审计字段由 MetaObjectFillHandler 统一填充,确保一致性
- **角色管理验证依赖** - **缩略图状态管理依赖**
- VALID_DATA_SCOPE_VALUES集合用于数据范围验证 - FileConstants定义缩略图状态常量(PENDING、READY、FAILED、UNSUPPORTED)
- 内置角色保护机制确保系统稳定性 - ThumbnailGenerationTask负责异步生成和状态转换
- 角色编码唯一性校验防止数据冲突 - ThumbnailRetryTask定时扫描FAILED状态并重试
- FileProperties配置缩略图生成参数和重试策略
```mermaid ```mermaid
graph LR graph LR
@ -531,8 +550,9 @@ AuthUser -- "N:M" --> SysDept
SysMenu -- "自引用" --> SysMenu SysMenu -- "自引用" --> SysMenu
SysDept -- "自引用" --> SysDept SysDept -- "自引用" --> SysDept
FileInfo -- "独立" --> "*" FileInfo -- "独立" --> "*"
SysRoleServiceImpl -- "验证规则" --> DataScopeEnum ThumbnailGenerationTask -- "状态管理" --> FileInfo
SysRoleServiceImpl -- "内置保护" --> SysRole ThumbnailRetryTask -- "定时重试" --> FileInfo
FileConstants -- "状态常量" --> FileInfo
``` ```
**图表来源** **图表来源**
@ -542,8 +562,9 @@ SysRoleServiceImpl -- "内置保护" --> SysRole
- [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java) - [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java)
- [AuthIdentity.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthIdentity.java) - [AuthIdentity.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthIdentity.java)
- [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java)
- [SysRoleServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java) - [ThumbnailRetryTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailRetryTask.java)
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
**章节来源** **章节来源**
- [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java)
@ -558,12 +579,12 @@ SysRoleServiceImpl -- "内置保护" --> SysRole
- 大文件元数据(FileInfo)建议按状态分区或归档,保持热数据表轻量 - 大文件元数据(FileInfo)建议按状态分区或归档,保持热数据表轻量
- 批量操作使用 InsertBatchOnDuplicateKeyUpdate 减少往返次数 - 批量操作使用 InsertBatchOnDuplicateKeyUpdate 减少往返次数
- 合理索引:唯一索引优先,普通索引按需添加,避免过度索引影响写入 - 合理索引:唯一索引优先,普通索引按需添加,避免过度索引影响写入
- **角色管理性能优化** - **缩略图性能优化**
- 角色编码唯一性检查使用LambdaQueryWrapper优化查询性能 - 异步生成避免阻塞上传链路
- 祖先节点补全采用批量查询+内存映射,避免逐节点查库 - Redis分布式锁防止重复生成
- 事务保护确保级联操作的原子性 - 失败重试机制提高成功率
- 定时任务批量处理失败记录
[本节为通用指导,不直接分析具体文件] - 配置化超时和重试参数适应不同场景
## 故障排查指南 ## 故障排查指南
- ID重复或生成失败 - ID重复或生成失败
@ -576,11 +597,11 @@ SysRoleServiceImpl -- "内置保护" --> SysRole
- 检查 CrmSqlInjector 是否启用,@TableLogic 注解是否正确 - 检查 CrmSqlInjector 是否启用,@TableLogic 注解是否正确
- 唯一约束冲突 - 唯一约束冲突
- 核对业务唯一字段(username、roleCode、menuCode、deptCode、objectKey)的输入校验 - 核对业务唯一字段(username、roleCode、menuCode、deptCode、objectKey)的输入校验
- **角色管理相关故障** - **缩略图相关故障**
- 数据范围验证失败:检查dataScope是否在1-4范围内 - 状态卡住:检查ThumbnailGenerationTask执行日志和Redis锁状态
- 内置角色保护错误:确认角色builtin标志位设置 - 重试不生效:确认retryLimit配置和ThumbnailRetryTask调度
- 角色编码重复:检查是否存在相同roleCode的其他角色 - 生成失败:查看渲染引擎(LibreOffice等)可用性和配置
- 级联删除失败:确认事务配置和关联表完整性 - 内存溢出:调整缩略图尺寸配置和JVM堆大小
**章节来源** **章节来源**
- [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java)
@ -588,13 +609,13 @@ SysRoleServiceImpl -- "内置保护" --> SysRole
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
- [SysRoleServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java) - [SysRoleServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [ThumbnailRetryTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailRetryTask.java)
## 结论 ## 结论
本数据模型以雪花ID为主键,结合 MyBatis-Plus 的自动填充与SQL增强,实现了统一的审计、逻辑删除与批量操作能力。用户、角色、菜单、部门、身份与文件等核心实体通过明确的关联表与索引设计,满足权限控制、组织架构与文件管理的业务需求。 本数据模型以雪花ID为主键,结合 MyBatis-Plus 的自动填充与SQL增强,实现了统一的审计、逻辑删除与批量操作能力。用户、角色、菜单、部门、身份与文件等核心实体通过明确的关联表与索引设计,满足权限控制、组织架构与文件管理的业务需求。
**更新** 角色管理系统的增强功能显著提升了数据完整性和系统安全性,包括严格的数据范围验证、内置角色保护机制和角色编码唯一性强制校验。这些改进确保了系统在面对恶意操作和误操作时的鲁棒性,为后续的业务发展奠定了坚实的基础。建议在后续演进中持续完善索引与缓存策略,保障性能与可维护性。 **更新** 文件模块的缩略图功能显著增强了系统的文件处理能力,包括完整的状态机管理、异步处理机制和失败重试策略。这些改进确保了文件预览功能的稳定性和可靠性,为用户提供了更好的体验。建议在后续演进中持续监控缩略图生成性能和资源使用情况,优化配置参数以适应不同的业务场景。
[本节为总结性内容,不直接分析具体文件]
## 附录 ## 附录
@ -607,7 +628,7 @@ SysRoleServiceImpl -- "内置保护" --> SysRole
- phone:手机,可选唯一 - phone:手机,可选唯一
- status:状态(参考 StatusEnum) - status:状态(参考 StatusEnum)
- 审计字段:create_by、update_by、create_time、update_time - 审计字段:create_by、update_by、create_time、update_time
- 角色(SysRole)- **已更新** - 角色(SysRole)
- id:主键,雪花ID - id:主键,雪花ID
- roleName:角色名称,非空 - roleName:角色名称,非空
- roleCode:角色编码,唯一,非空 - roleCode:角色编码,唯一,非空
@ -645,18 +666,19 @@ SysRoleServiceImpl -- "内置保护" --> SysRole
- openId、unionId:第三方标识 - openId、unionId:第三方标识
- status:状态(参考 StatusEnum) - status:状态(参考 StatusEnum)
- 审计字段:同上 - 审计字段:同上
- 文件(FileInfo) - 文件(FileInfo)- **已更新**
- id:主键,雪花ID - id:主键,雪花ID
- bucket:存储桶 - originalName:原始文件名
- objectKey:对象键,唯一 - objectKey:对象键,唯一
- fileName:文件名
- fileSize:文件大小 - fileSize:文件大小
- mimeType:MIME类型 - contentType:MIME类型
- md5:文件哈希 - bizDomain:业务域
- status:状态(参考 StatusEnum) - fileHash:文件哈希(秒传占位)
- **thumbnailStatus:缩略图状态(PENDING/READY/FAILED/UNSUPPORTED),默认PENDING**
- **thumbnailRetryCount:缩略图重试计数,默认0**
- 审计字段:同上 - 审计字段:同上
**更新** 角色实体新增了builtin字段和数据范围验证规则 **更新** FileInfo实体新增了缩略图状态和重试计数字段,支持完整的缩略图生命周期管理
**章节来源** **章节来源**
- [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java) - [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java)
@ -671,33 +693,31 @@ SysRoleServiceImpl -- "内置保护" --> SysRole
- HasValueEnum:通用布尔值(是/否) - HasValueEnum:通用布尔值(是/否)
- MenuTypeEnum:菜单类型(如目录、菜单、按钮) - MenuTypeEnum:菜单类型(如目录、菜单、按钮)
- IdentityTypeEnum:身份类型(如手机号、邮箱、第三方账号) - IdentityTypeEnum:身份类型(如手机号、邮箱、第三方账号)
- **DataScopeEnum**:数据范围枚举 - **缩略图状态常量(FileConstants)**
- SELF(1):仅本人 - THUMBNAIL_STATUS_PENDING = "PENDING":待生成
- DEPT(2):本部门 - THUMBNAIL_STATUS_READY = "READY":已生成
- DEPT_AND_CHILD(3):本部门及子部门 - THUMBNAIL_STATUS_FAILED = "FAILED":重试耗尽
- ALL(4):全部数据 - THUMBNAIL_STATUS_UNSUPPORTED = "UNSUPPORTED":不支持
- CUSTOM(5):自定义(API操作禁止使用)
**更新** 数据范围枚举新增了CUSTOM选项,但在API操作中通过VALID_DATA_SCOPE_VALUES集合排除 **更新** 新增了缩略图状态常量定义,完善了文件模块的状态管理
**章节来源** **章节来源**
- [StatusEnum.java](file://crm-base/src/main/java/com/crm/base/domain/enums/StatusEnum.java) - [StatusEnum.java](file://crm-base/src/main/java/com/crm/base/domain/enums/StatusEnum.java)
- [HasValueEnum.java](file://crm-base/src/main/java/com/crm/base/domain/enums/HasValueEnum.java) - [HasValueEnum.java](file://crm-base/src/main/java/com/crm/base/domain/enums/HasValueEnum.java)
- [MenuTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuTypeEnum.java) - [MenuTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuTypeEnum.java)
- [IdentityTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/IdentityTypeEnum.java) - [IdentityTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/IdentityTypeEnum.java)
- [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java) - [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
### 默认值与填充策略 ### 默认值与填充策略
- 主键:雪花ID(CustomIdGenerator + SnowflakeIdWorker) - 主键:雪花ID(CustomIdGenerator + SnowflakeIdWorker)
- 审计字段:create_by、update_by、create_time、update_time(MetaObjectFillHandler) - 审计字段:create_by、update_by、create_time、update_time(MetaObjectFillHandler)
- 逻辑删除:enabled(CrmSqlInjector) - 逻辑删除:enabled(CrmSqlInjector)
- 批量插入去重:InsertBatchOnDuplicateKeyUpdate - 批量插入去重:InsertBatchOnDuplicateKeyUpdate
- **角色默认值** - **缩略图默认值**
- dataScope:默认1(仅本人) - thumbnailStatus:默认'PENDING'
- sort:默认0 - thumbnailRetryCount:默认0
- builtin:默认false
**更新** 角色实体新增了builtin字段的默认值策略 **更新** 新增了缩略图字段的默认值策略,确保数据一致性
**章节来源** **章节来源**
- [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java)
@ -705,38 +725,57 @@ SysRoleServiceImpl -- "内置保护" --> SysRole
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
- [InsertBatchOnDuplicateKeyUpdate.java](file://crm-base/src/main/java/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.java) - [InsertBatchOnDuplicateKeyUpdate.java](file://crm-base/src/main/java/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.java)
- [SysRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java)
### 角色管理验证规则 - **新增章节** ### 缩略图状态机 - **新增章节**
- **数据范围验证** - **状态转换规则**
- 允许的dataScope值:1-4(SELF、DEPT、DEPT_AND_CHILD、ALL) - PENDING → READY:缩略图生成成功
- 禁止的值:5(CUSTOM) - PENDING → FAILED:重试次数耗尽
- 验证方式:VALID_DATA_SCOPE_VALUES集合检查 - PENDING → UNSUPPORTED:文件类型不支持
- **内置角色保护** - FAILED → PENDING:定时任务重置重试
- 禁止通过接口创建builtin=true的角色 - **状态初始化**
- 禁止删除builtin=true的角色 - 上传时根据文件类型判断:支持的类型设为PENDING,不支持的设为UNSUPPORTED
- 禁止修改builtin=true角色的roleCode - 通过ThumbnailGenerationTask.assignInitialStatus()方法设置
- **角色编码唯一性** - **状态查询优化**
- 全局唯一性检查(跨ID) - 支持按状态过滤查询
- 保存时查询数据库验证 - 建议为thumbnail_status字段建立索引
- **参数校验** - **并发控制**
- roleName和roleCode非空校验 - 使用Redis分布式锁防止重复生成
- dataScope范围校验 - 锁TTL大于最慢渲染时间
- 内置角色标志位校验
**章节来源** **章节来源**
- [SysRoleServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [AuthConstants.java](file://crm-auth/src/main/java/com/crm/auth/constant/AuthConstants.java) - [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
### 缩略图重试机制 - **新增章节**
- **重试策略**
- 配置化重试次数(默认3次)
- 每次失败递增retry_count
- 达到上限后标记FAILED
- **自动重试**
- 定时任务每天凌晨4点扫描FAILED记录
- 重置状态为PENDING并重试计数归零
- 重新提交异步生成任务
- **错误处理**
- 渲染异常捕获并记录日志
- 不影响其他文件的缩略图生成
- 任务自身异常不影响下次执行
**章节来源**
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [ThumbnailRetryTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailRetryTask.java)
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
### 数据迁移策略与版本兼容性 ### 数据迁移策略与版本兼容性
- 使用数据库迁移工具(如 Flyway/Liquibase)管理DDL变更,确保环境一致性 - 使用数据库迁移工具(如 Flyway/Liquibase)管理DDL变更,确保环境一致性
- 新增字段时提供默认值与向后兼容的查询逻辑 - 新增字段时提供默认值与向后兼容的查询逻辑
- 修改唯一约束前评估历史数据,必要时先清洗再变更 - 修改唯一约束前评估历史数据,必要时先清洗再变更
- 灰度发布:先在测试环境验证,再逐步上线生产 - 灰度发布:先在测试环境验证,再逐步上线生产
- **角色管理迁移注意事项** - **缩略图功能迁移注意事项**
- 新增builtin字段需设置默认值false - 新增thumbnail_status字段需设置默认值'PENDING'
- 现有角色数据无需特殊处理 - 新增thumbnail_retry_count字段需设置默认值0
- API端点迁移从SystemController到RoleController - 现有文件数据无需特殊处理,首次访问时触发缩略图生成
- 建议为新字段建立适当的索引以提升查询性能
[本节为通用指导,不直接分析具体文件] [本节为通用指导,不直接分析具体文件]
@ -745,9 +784,27 @@ SysRoleServiceImpl -- "内置保护" --> SysRole
- 关键表(用户、角色、菜单、部门、文件元数据)提高备份频率 - 关键表(用户、角色、菜单、部门、文件元数据)提高备份频率
- 恢复演练:定期执行恢复演练,验证备份有效性 - 恢复演练:定期执行恢复演练,验证备份有效性
- 灾难恢复:制定RTO/RPO目标,明确恢复流程与责任人 - 灾难恢复:制定RTO/RPO目标,明确恢复流程与责任人
- **角色管理数据保护** - **缩略图数据保护**
- 重点关注sys_role表的builtin字段数据 - 重点关注crn_file_info表的缩略图状态字段
- 角色权限分配数据(sys_role_menu)的完整性保护 - MinIO中thumbnails目录的缩略图文件备份
- 用户角色关联数据(sys_user_role)的一致性维护 - Redis中缩略图分布式锁的临时数据无需持久化
[本节为通用指导,不直接分析具体文件]
[本节为通用指导,不直接分析具体文件] ### 缩略图配置参数 - **新增章节**
- **基本配置**
- width:缩略图宽度(默认200px)
- maxHeight:最大高度(默认400px)
- format:输出格式(默认jpeg)
- **同步等待配置**
- syncWaitTimeout:同步兜底等待超时(默认10秒)
- lockTtl:分布式锁TTL(默认150秒)
- **重试配置**
- retryLimit:最大重试次数(默认3次)
- retryCron:失败重试cron表达式(默认每天凌晨4点)
- **渲染引擎配置**
- libreofficePath:LibreOffice可执行文件路径
- officeConvertTimeout:单次转换超时(默认120秒)
**章节来源**
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)

144
.qoder/repowiki/zh/content/架构设计/安全架构设计/安全架构设计.md

@ -18,8 +18,19 @@
- [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java) - [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
- [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java)
- [Application.yml](file://crm-app/src/main/resources/application.yml) - [Application.yml](file://crm-app/src/main/resources/application.yml)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
- [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java)
</cite> </cite>
## 更新摘要
**变更内容**
- 新增审计字段防篡改机制说明,强调客户端传入的审计字段必须显式清空
- 增强字典模块数据完整性保护,防止恶意用户伪造创建时间、创建人等审计信息
- 完善MyBatis-Plus自动填充机制与安全边界说明
- 补充服务层审计字段处理的最佳实践
## 目录 ## 目录
1. [引言](#引言) 1. [引言](#引言)
2. [项目结构](#项目结构) 2. [项目结构](#项目结构)
@ -38,12 +49,14 @@
- RBAC权限模型与数据权限控制(DataScope) - RBAC权限模型与数据权限控制(DataScope)
- SecurityConfig配置类、JwtAuthenticationFilter过滤器链、TokenService令牌管理服务 - SecurityConfig配置类、JwtAuthenticationFilter过滤器链、TokenService令牌管理服务
- 第三方登录集成(钉钉)与密码加密策略、会话管理 - 第三方登录集成(钉钉)与密码加密策略、会话管理
- **新增:审计字段防篡改机制与数据完整性保护**
- 关键流程图与权限判断逻辑图 - 关键流程图与权限判断逻辑图
## 项目结构 ## 项目结构
安全相关代码主要分布在以下模块: 安全相关代码主要分布在以下模块:
- crm-auth:认证授权、RBAC、数据权限拦截器、第三方登录客户端 - crm-auth:认证授权、RBAC、数据权限拦截器、第三方登录客户端
- crm-base:通用安全上下文、数据可见性工具、注解定义 - crm-base:通用安全上下文、数据可见性工具、注解定义、审计字段自动填充
- crm-dict:字典管理模块,包含增强的审计字段保护机制
- crm-app:应用入口与全局配置(如application.yml) - crm-app:应用入口与全局配置(如application.yml)
```mermaid ```mermaid
@ -68,6 +81,13 @@ ANNO_DSCOPE["DataScope注解"]
DSCOPE_CTX["DataVisibilityContext"] DSCOPE_CTX["DataVisibilityContext"]
DSCOPE_HELPER["DataScopeHelper"] DSCOPE_HELPER["DataScopeHelper"]
LOGIN_USER["LoginUser"] LOGIN_USER["LoginUser"]
META_FILL["MetaObjectFillHandler"]
BASE_ENTITY["BaseEntity"]
end
subgraph "字典模块(crm-dict)"
DICT_GROUP_SVC["DictGroupServiceImpl"]
DICT_ITEM_SVC["DictItemServiceImpl"]
AUDIT_PROTECT["审计字段保护机制"]
end end
APP --> SEC_CFG APP --> SEC_CFG
APP --> YML APP --> YML
@ -78,9 +98,12 @@ DSCOPE_INT --> DSCOPE_CTX
DSCOPE_INT --> DSCOPE_HELPER DSCOPE_INT --> DSCOPE_HELPER
DING --> TP_FACTORY DING --> TP_FACTORY
AUTH_SVC --> DING AUTH_SVC --> DING
META_FILL --> BASE_ENTITY
DICT_GROUP_SVC --> AUDIT_PROTECT
DICT_ITEM_SVC --> AUDIT_PROTECT
``` ```
图表来源 **图表来源**
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
@ -96,22 +119,10 @@ AUTH_SVC --> DING
- [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java) - [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
- [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java)
- [Application.yml](file://crm-app/src/main/resources/application.yml) - [Application.yml](file://crm-app/src/main/resources/application.yml)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
章节来源 - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
- [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java)
- [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java)
- [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
- [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java)
- [Application.yml](file://crm-app/src/main/resources/application.yml)
## 核心组件 ## 核心组件
- SecurityConfig:统一安全配置,注册过滤器链、跨域、白名单、鉴权规则等 - SecurityConfig:统一安全配置,注册过滤器链、跨域、白名单、鉴权规则等
@ -120,8 +131,10 @@ AUTH_SVC --> DING
- DataScope注解与拦截器:在SQL层面注入数据范围条件,实现行级数据权限 - DataScope注解与拦截器:在SQL层面注入数据范围条件,实现行级数据权限
- 第三方登录客户端:以钉钉为例,封装OAuth流程与用户信息映射 - 第三方登录客户端:以钉钉为例,封装OAuth流程与用户信息映射
- LoginUser与上下文:承载当前登录用户、角色、权限、数据可见范围 - LoginUser与上下文:承载当前登录用户、角色、权限、数据可见范围
- **新增:MetaObjectFillHandler审计字段自动填充处理器**
- **新增:BaseEntity实体基类,定义标准审计字段结构**
章节来源 **章节来源**
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
@ -130,9 +143,11 @@ AUTH_SVC --> DING
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
## 架构总览 ## 架构总览
下图展示认证授权主流程与数据权限拦截的关键交互。 下图展示认证授权主流程与数据权限拦截的关键交互,以及新增的审计字段保护机制
```mermaid ```mermaid
sequenceDiagram sequenceDiagram
@ -142,6 +157,7 @@ participant Filter as "JwtAuthenticationFilter"
participant TokenSvc as "TokenService" participant TokenSvc as "TokenService"
participant SecCfg as "SecurityConfig" participant SecCfg as "SecurityConfig"
participant DScopeInt as "DataScopeInterceptor" participant DScopeInt as "DataScopeInterceptor"
participant MetaFill as "MetaObjectFillHandler"
participant DB as "数据库" participant DB as "数据库"
Client->>AuthCtl : "POST /auth/login (用户名/密码或第三方code)" Client->>AuthCtl : "POST /auth/login (用户名/密码或第三方code)"
AuthCtl->>TokenSvc : "签发JWT(含用户、角色、权限、数据范围)" AuthCtl->>TokenSvc : "签发JWT(含用户、角色、权限、数据范围)"
@ -154,15 +170,20 @@ Filter->>SecCfg : "按白名单/路径规则放行或继续鉴权"
SecCfg-->>Filter : "决定是否进入业务方法" SecCfg-->>Filter : "决定是否进入业务方法"
Filter->>DScopeInt : "进入数据权限拦截" Filter->>DScopeInt : "进入数据权限拦截"
DScopeInt->>DB : "根据DataScope注解注入WHERE条件" DScopeInt->>DB : "根据DataScope注解注入WHERE条件"
Note over MetaFill,DB : 审计字段保护机制<br/>客户端传入的createTime/creatorId/updaterId被显式清空
Client->>AuthCtl : "保存字典分组/项"
AuthCtl->>MetaFill : "调用save操作"
MetaFill->>DB : "仅填充null值的审计字段"
DB-->>Client : "返回受限数据集" DB-->>Client : "返回受限数据集"
``` ```
图表来源 **图表来源**
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
## 详细组件分析 ## 详细组件分析
@ -188,13 +209,13 @@ Allow --> End
Deny --> End Deny --> End
``` ```
图表来源 **图表来源**
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
章节来源 **章节来源**
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
@ -234,20 +255,50 @@ DataScopeInterceptor --> DataScopeHelper : "生成条件"
DataScopeInterceptor --> DataScopeTables : "表字段映射" DataScopeInterceptor --> DataScopeTables : "表字段映射"
``` ```
图表来源 **图表来源**
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
章节来源 **章节来源**
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
### 审计字段防篡改机制
**新增功能**:为防止客户端伪造审计信息,系统在字典模块中实现了严格的审计字段保护机制。
- **审计字段定义**:BaseEntity定义了标准的审计字段(createTime、createTime、updaterId、updateTime)
- **自动填充机制**:MetaObjectFillHandler使用strictInsertFill和strictUpdateFill,仅填充null值
- **客户端输入防护**:在DictGroupServiceImpl和DictItemServiceImpl中,显式将客户端传入的审计字段设置为null
- **安全边界**:确保只有服务端能够设置审计信息,防止恶意用户伪造创建时间、创建人等敏感信息
```mermaid
flowchart TD
ClientReq["客户端请求"] --> ClearAudit["清空审计字段<br/>createTime=null<br/>creatorId=null<br/>updaterId=null<br/>updateTime=null"]
ClearAudit --> ServiceLayer["服务层处理"]
ServiceLayer --> MyBatisFill["MyBatis-Plus自动填充"]
MyBatisFill --> StrictFill["strictInsertFill/strictUpdateFill<br/>仅填充null值"]
StrictFill --> ServerAudit["服务端设置审计信息<br/>createTime=当前时间<br/>creatorId=当前用户ID"]
ServerAudit --> Database["持久化到数据库"]
```
**图表来源**
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
- [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java)
**章节来源**
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
- [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java)
### 第三方登录集成(钉钉) ### 第三方登录集成(钉钉)
- DingTalkAuthClient封装钉钉OAuth2流程,获取access_token与用户信息 - DingTalkAuthClient封装钉钉OAuth2流程,获取access_token与用户信息
- ThirdPartyAuthClientFactory统一管理第三方登录客户端实例 - ThirdPartyAuthClientFactory统一管理第三方登录客户端实例
@ -274,7 +325,7 @@ Token-->>AuthCtl : "token"
AuthCtl-->>Client : "响应{token}" AuthCtl-->>Client : "响应{token}"
``` ```
图表来源 **图表来源**
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java) - [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java)
- [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java) - [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java)
@ -283,7 +334,7 @@ AuthCtl-->>Client : "响应{token}"
- [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
章节来源 **章节来源**
- [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java) - [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java)
- [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java) - [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java)
- [ThirdPartyUserInfo.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyUserInfo.java) - [ThirdPartyUserInfo.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyUserInfo.java)
@ -296,16 +347,19 @@ AuthCtl-->>Client : "响应{token}"
- 密码加密:建议采用强哈希算法(如BCrypt),避免明文存储;在用户注册/修改密码时进行加盐哈希 - 密码加密:建议采用强哈希算法(如BCrypt),避免明文存储;在用户注册/修改密码时进行加盐哈希
- 会话管理:无状态JWT为主,必要时结合Redis记录黑名单或刷新令牌;登出时将token加入黑名单或失效缓存 - 会话管理:无状态JWT为主,必要时结合Redis记录黑名单或刷新令牌;登出时将token加入黑名单或失效缓存
- 安全配置:通过SecurityConfig启用CSRF防护、CORS策略、最小化暴露端点 - 安全配置:通过SecurityConfig启用CSRF防护、CORS策略、最小化暴露端点
- **新增:审计字段安全**:通过严格的服务端审计字段控制,确保数据完整性和可追溯性
章节来源 **章节来源**
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [Application.yml](file://crm-app/src/main/resources/application.yml) - [Application.yml](file://crm-app/src/main/resources/application.yml)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
## 依赖关系分析 ## 依赖关系分析
- 认证链路:AuthController依赖TokenService与第三方客户端;JwtAuthenticationFilter依赖TokenService与SecurityConfig - 认证链路:AuthController依赖TokenService与第三方客户端;JwtAuthenticationFilter依赖TokenService与SecurityConfig
- 数据权限:DataScopeInterceptor依赖DataScope注解、DataVisibilityContext、DataScopeHelper与DataScopeTables - 数据权限:DataScopeInterceptor依赖DataScope注解、DataVisibilityContext、DataScopeHelper与DataScopeTables
- 第三方登录:AuthController通过工厂模式获取具体第三方客户端,再交由服务层处理用户绑定 - 第三方登录:AuthController通过工厂模式获取具体第三方客户端,再交由服务层处理用户绑定
- **新增:审计字段依赖**:MetaObjectFillHandler依赖SecurityUtils获取当前用户信息,BaseEntity定义标准审计字段结构
```mermaid ```mermaid
graph LR graph LR
@ -318,9 +372,12 @@ DScopeInt["DataScopeInterceptor"] --> DSCOPE["DataScope注解"]
DScopeInt --> Ctx["DataVisibilityContext"] DScopeInt --> Ctx["DataVisibilityContext"]
DScopeInt --> Helper["DataScopeHelper"] DScopeInt --> Helper["DataScopeHelper"]
DScopeInt --> Tbls["DataScopeTables"] DScopeInt --> Tbls["DataScopeTables"]
MetaFill["MetaObjectFillHandler"] --> SecUtils["SecurityUtils"]
MetaFill --> BaseEntity["BaseEntity"]
DictSvc["DictServiceImpl"] --> MetaFill
``` ```
图表来源 **图表来源**
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java) - [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java)
@ -332,8 +389,10 @@ DScopeInt --> Tbls["DataScopeTables"]
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
章节来源 **章节来源**
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java) - [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java)
@ -345,14 +404,15 @@ DScopeInt --> Tbls["DataScopeTables"]
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
## 性能考虑 ## 性能考虑
- JWT无状态校验:减少服务端会话存储压力,适合水平扩展 - JWT无状态校验:减少服务端会话存储压力,适合水平扩展
- 数据权限SQL注入:尽量使用预编译与索引优化,避免全表扫描 - 数据权限SQL注入:尽量使用预编译与索引优化,避免全表扫描
- 第三方登录限流:对钉钉回调接口做速率限制与重试退避 - 第三方登录限流:对钉钉回调接口做速率限制与重试退避
- 缓存热点数据:菜单、角色、权限、部门树可缓存以提升鉴权速度 - 缓存热点数据:菜单、角色、权限、部门树可缓存以提升鉴权速度
- **新增:审计字段性能**:strictInsertFill/strictUpdateFill仅在null值时填充,避免不必要的数据库操作
[本节为通用指导,不直接分析具体文件]
## 故障排查指南 ## 故障排查指南
- 认证失败 - 认证失败
@ -367,8 +427,12 @@ DScopeInt --> Tbls["DataScopeTables"]
- 第三方登录问题 - 第三方登录问题
- 校验钉钉回调地址与密钥配置 - 校验钉钉回调地址与密钥配置
- 检查ThirdPartyUserInfo映射字段是否完整 - 检查ThirdPartyUserInfo映射字段是否完整
- **新增:审计字段问题**
- 检查MetaObjectFillHandler是否正确配置
- 确认业务代码是否显式清空了客户端传入的审计字段
- 验证BaseEntity中的审计字段注解配置
章节来源 **章节来源**
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
@ -376,20 +440,24 @@ DScopeInt --> Tbls["DataScopeTables"]
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java) - [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java)
- [ThirdPartyUserInfo.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyUserInfo.java) - [ThirdPartyUserInfo.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyUserInfo.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
## 结论 ## 结论
本安全架构以JWT为核心,结合RBAC与DataScope数据权限,形成“身份认证—权限校验—数据隔离”的闭环。通过统一的SecurityConfig与过滤器链,保证安全策略的可配置性与可扩展性;通过第三方登录工厂与上下文工具,提升集成效率与可维护性。建议在后续迭代中持续完善令牌刷新、审计日志与动态权限下发能力。 本安全架构以JWT为核心,结合RBAC与DataScope数据权限,形成"身份认证—权限校验—数据隔离"的闭环。通过统一的SecurityConfig与过滤器链,保证安全策略的可配置性与可扩展性;通过第三方登录工厂与上下文工具,提升集成效率与可维护性。**新增的审计字段防篡改机制进一步增强了数据完整性保护,确保所有审计信息的真实性和不可伪造性**。建议在后续迭代中持续完善令牌刷新、审计日志与动态权限下发能力。
[本节为总结性内容,不直接分析具体文件]
## 附录 ## 附录
- 术语说明 - 术语说明
- JWT:JSON Web Token,用于无状态身份传递 - JWT:JSON Web Token,用于无状态身份传递
- RBAC:基于角色的访问控制 - RBAC:基于角色的访问控制
- DataScope:数据范围注解,限定查询数据的可见范围 - DataScope:数据范围注解,限定查询数据的可见范围
- **新增:审计字段**:记录数据创建和修改的时间、用户等元数据
- 最佳实践 - 最佳实践
- 敏感操作二次确认与审计 - 敏感操作二次确认与审计
- 最小权限原则与接口级鉴权 - 最小权限原则与接口级鉴权
- 定期轮换密钥与审查第三方接入 - 定期轮换密钥与审查第三方接入
- **新增:在服务层显式清空客户端传入的审计字段,确保数据安全**
[本节为补充信息,不直接分析具体文件] - **新增:审计字段安全规范**
- 所有继承BaseEntity的实体都受审计字段保护
- 业务代码不得直接设置createTime、creatorId、updaterId、updateTime字段
- 使用MyBatis-Plus的strictInsertFill和strictUpdateFill机制进行安全填充

160
.qoder/repowiki/zh/content/认证服务/认证服务.md

@ -4,6 +4,7 @@
**本文引用的文件** **本文引用的文件**
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [application.yml](file://crm-auth/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
@ -11,6 +12,7 @@
- [DataInitializer.java](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java) - [DataInitializer.java](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java)
- [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java) - [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java)
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)
- [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java) - [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java)
- [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.java) - [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.java)
- [LoginResultDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/LoginResultDTO.java) - [LoginResultDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/LoginResultDTO.java)
@ -87,6 +89,13 @@
- [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java) - [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java)
</cite> </cite>
## 更新摘要
**变更内容**
- 新增调试令牌端点章节,详细介绍DebugTokenController功能
- 更新安全配置章节,说明verify profile和三层护栏机制
- 新增验证环境专用配置说明
- 更新部署指南,包含verify profile的使用说明
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
2. [项目结构](#项目结构) 2. [项目结构](#项目结构)
@ -102,9 +111,11 @@
## 简介 ## 简介
本技术文档围绕认证服务的用户认证、授权管理、权限控制等核心能力展开,涵盖JWT令牌机制、RBAC角色权限模型、数据权限控制、第三方登录集成等特性。同时提供用户管理、角色管理、菜单权限、部门管理等业务功能的API接口说明与使用示例,并解释安全过滤器链、异常处理、会话管理等安全机制,最后给出完整的配置指南与最佳实践建议。 本技术文档围绕认证服务的用户认证、授权管理、权限控制等核心能力展开,涵盖JWT令牌机制、RBAC角色权限模型、数据权限控制、第三方登录集成等特性。同时提供用户管理、角色管理、菜单权限、部门管理等业务功能的API接口说明与使用示例,并解释安全过滤器链、异常处理、会话管理等安全机制,最后给出完整的配置指南与最佳实践建议。
**重要更新**:新增了验证环境专用的调试令牌端点,用于在验证环境中快速生成JWT令牌进行接口调试,该功能通过@Profile("verify")严格限制仅在验证环境激活。
## 项目结构 ## 项目结构
认证服务由应用启动模块与认证功能模块组成: 认证服务由应用启动模块与认证功能模块组成:
- crm-app:应用入口与全局配置 - crm-app:应用入口与全局配置(包含verify profile专用配置)
- crm-auth:认证与权限核心实现(控制器、服务、安全、领域模型、枚举、参数与DTO) - crm-auth:认证与权限核心实现(控制器、服务、安全、领域模型、枚举、参数与DTO)
- crm-base:通用基础能力(异常、结果封装、安全上下文、数据可见性、工具类、配置等) - crm-base:通用基础能力(异常、结果封装、安全上下文、数据可见性、工具类、配置等)
@ -112,12 +123,14 @@
graph TB graph TB
subgraph "应用层" subgraph "应用层"
App["CrmAppApplication<br/>应用启动"] App["CrmAppApplication<br/>应用启动"]
VerifyCfg["application-verify.yml<br/>验证环境配置"]
end end
subgraph "认证模块(crm-auth)" subgraph "认证模块(crm-auth)"
AuthApp["AuthApplication<br/>认证应用启动"] AuthApp["AuthApplication<br/>认证应用启动"]
SecCfg["SecurityConfig<br/>安全配置"] SecCfg["SecurityConfig<br/>安全配置"]
PermCfg["PermissionConfig<br/>权限配置"] PermCfg["PermissionConfig<br/>权限配置"]
CtlAuth["AuthController<br/>认证接口"] CtlAuth["AuthController<br/>认证接口"]
CtlDebug["DebugTokenController<br/>调试令牌接口"]
CtlSys["SystemController<br/>系统接口"] CtlSys["SystemController<br/>系统接口"]
SvcAuth["AuthServiceImpl<br/>认证服务"] SvcAuth["AuthServiceImpl<br/>认证服务"]
SvcUser["AuthUserServiceImpl<br/>用户服务"] SvcUser["AuthUserServiceImpl<br/>用户服务"]
@ -139,10 +152,13 @@ Jackson["JacksonConfig<br/>序列化配置"]
Snow["SnowflakeIdWorker<br/>雪花ID生成"] Snow["SnowflakeIdWorker<br/>雪花ID生成"]
end end
App --> AuthApp App --> AuthApp
App --> VerifyCfg
AuthApp --> SecCfg AuthApp --> SecCfg
SecCfg --> JwtF SecCfg --> JwtF
JwtF --> TokS JwtF --> TokS
CtlAuth --> SvcAuth CtlAuth --> SvcAuth
CtlDebug --> SvcUser
CtlDebug --> TokS
CtlSys --> SvcUser CtlSys --> SvcUser
CtlSys --> SvcRole CtlSys --> SvcRole
CtlSys --> SvcMenu CtlSys --> SvcMenu
@ -162,8 +178,10 @@ SvcDept --> SecCtx
**图表来源** **图表来源**
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
@ -185,6 +203,7 @@ SvcDept --> SecCtx
**章节来源** **章节来源**
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
- [application.yml](file://crm-auth/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml)
@ -200,6 +219,8 @@ SvcDept --> SecCtx
- ISysRoleService/SysRoleServiceImpl:角色CRUD、角色-用户关联 - ISysRoleService/SysRoleServiceImpl:角色CRUD、角色-用户关联
- ISysMenuService/SysMenuServiceImpl:菜单树、按钮权限、角色-菜单关联 - ISysMenuService/SysMenuServiceImpl:菜单树、按钮权限、角色-菜单关联
- ISysDeptService/SysDeptServiceImpl:部门树、用户-部门关联 - ISysDeptService/SysDeptServiceImpl:部门树、用户-部门关联
- **调试令牌端点**
- DebugTokenController:验证环境专用的JWT令牌生成接口,通过@Profile("verify")严格限制
- 数据权限控制 - 数据权限控制
- DataScopeInterceptor:基于注解的数据范围注入SQL片段 - DataScopeInterceptor:基于注解的数据范围注入SQL片段
- DataScopeHelper/DataVisibilityContext:数据可见性上下文与计算 - DataScopeHelper/DataVisibilityContext:数据可见性上下文与计算
@ -228,6 +249,7 @@ SvcDept --> SecCtx
- [SysMenuServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysMenuServiceImpl.java) - [SysMenuServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysMenuServiceImpl.java)
- [ISysDeptService.java](file://crm-auth/src/main/java/com/crm/auth/service/ISysDeptService.java) - [ISysDeptService.java](file://crm-auth/src/main/java/com/crm/auth/service/ISysDeptService.java)
- [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java)
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
@ -248,7 +270,7 @@ SvcDept --> SecCtx
## 架构总览 ## 架构总览
认证服务采用分层架构与模块化设计: 认证服务采用分层架构与模块化设计:
- 表现层:控制器暴露REST API - 表现层:控制器暴露REST API(包括调试令牌端点)
- 服务层:业务编排与领域逻辑 - 服务层:业务编排与领域逻辑
- 安全层:过滤器链、令牌服务、权限校验、数据范围拦截 - 安全层:过滤器链、令牌服务、权限校验、数据范围拦截
- 数据层:MyBatis Plus映射与数据库交互 - 数据层:MyBatis Plus映射与数据库交互
@ -258,7 +280,8 @@ SvcDept --> SecCtx
sequenceDiagram sequenceDiagram
participant Client as "客户端" participant Client as "客户端"
participant Filter as "JwtAuthenticationFilter" participant Filter as "JwtAuthenticationFilter"
participant Controller as "AuthController" participant DebugCtl as "DebugTokenController"
participant AuthCtl as "AuthController"
participant Service as "AuthServiceImpl" participant Service as "AuthServiceImpl"
participant Token as "TokenService" participant Token as "TokenService"
participant DB as "数据库" participant DB as "数据库"
@ -266,19 +289,28 @@ participant Cache as "Redis"
Client->>Filter : "携带Authorization请求" Client->>Filter : "携带Authorization请求"
Filter->>Filter : "解析JWT并校验签名" Filter->>Filter : "解析JWT并校验签名"
Filter-->>Client : "未通过则拒绝访问" Filter-->>Client : "未通过则拒绝访问"
Client->>Controller : "POST /auth/login" Note over DebugCtl : verify profile激活时可用
Controller->>Service : "login(LoginParam)" Client->>DebugCtl : "POST /api/auth/debug/token?userId=xxx"
DebugCtl->>DB : "查询用户信息"
DB-->>DebugCtl : "用户实体"
DebugCtl->>Token : "生成JWT(复用正式登录逻辑)"
Token->>Cache : "写入会话/黑名单(可选)"
Token-->>DebugCtl : "返回token"
DebugCtl-->>Client : "200 OK {token}"
Client->>AuthCtl : "POST /auth/login"
AuthCtl->>Service : "login(LoginParam)"
Service->>DB : "查询用户与身份" Service->>DB : "查询用户与身份"
DB-->>Service : "用户实体与角色/菜单" DB-->>Service : "用户实体与角色/菜单"
Service->>Token : "生成JWT(含用户、角色、权限)" Service->>Token : "生成JWT(含用户、角色、权限)"
Token->>Cache : "写入会话/黑名单(可选)" Token->>Cache : "写入会话/黑名单(可选)"
Token-->>Service : "返回token" Token-->>Service : "返回token"
Service-->>Controller : "LoginResultDTO" Service-->>AuthCtl : "LoginResultDTO"
Controller-->>Client : "200 OK {token, userInfo}" AuthCtl-->>Client : "200 OK {token, userInfo}"
``` ```
**图表来源** **图表来源**
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
@ -290,6 +322,9 @@ Controller-->>Client : "200 OK {token, userInfo}"
- JwtAuthenticationFilter:从请求头提取JWT,调用TokenService完成校验与上下文填充 - JwtAuthenticationFilter:从请求头提取JWT,调用TokenService完成校验与上下文填充
- TokenService:负责JWT的创建、解析、续期、撤销;支持将令牌或黑名单存入Redis - TokenService:负责JWT的创建、解析、续期、撤销;支持将令牌或黑名单存入Redis
- 数据范围拦截器:在方法执行前注入数据范围条件,影响后续SQL - 数据范围拦截器:在方法执行前注入数据范围条件,影响后续SQL
- **verify profile配置**:通过AuthProperties.ignoreUrls配置额外放行路径,支持动态配置
**更新**:新增了verify profile专用的安全配置机制,允许在验证环境中动态添加放行路径。
```mermaid ```mermaid
classDiagram classDiagram
@ -313,7 +348,13 @@ class DataScopeInterceptor {
+preHandle(request,response,handler) +preHandle(request,response,handler)
+buildScopeCondition() +buildScopeCondition()
} }
class AuthProperties {
+String[] ignoreUrls
+Jwt jwt
+DingTalk dingtalk
}
SecurityConfig --> JwtAuthenticationFilter : "注册" SecurityConfig --> JwtAuthenticationFilter : "注册"
SecurityConfig --> AuthProperties : "读取配置"
JwtAuthenticationFilter --> TokenService : "校验令牌" JwtAuthenticationFilter --> TokenService : "校验令牌"
SecurityConfig --> DataScopeInterceptor : "注册" SecurityConfig --> DataScopeInterceptor : "注册"
``` ```
@ -323,18 +364,60 @@ SecurityConfig --> DataScopeInterceptor : "注册"
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
- [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java)
**章节来源** **章节来源**
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
- [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java)
### 调试令牌端点(验证环境专用)
**新增功能**:DebugTokenController是专门为验证环境设计的调试接口,允许通过userId直接生成JWT令牌,绕过正常的登录流程。
**核心特性**:
- **严格的环境隔离**:通过@Profile("verify")确保仅在验证环境激活
- **三层安全防护**
1. @Profile("verify") - Bean级别的条件注册
2. application-verify.yml中的ignore-urls配置 - URL级别的放行
3. 启动期WARN日志 - 审计追踪
- **功能复用**:完全复用TokenService.createToken方法,生成的令牌与正常登录完全一致
- **安全警告**:启动时打印明显的警告日志,提醒开发者这是后门接口
```mermaid
flowchart TD
Start(["应用启动"]) --> CheckProfile{"verify profile激活?"}
CheckProfile --> |否| Skip["跳过DebugTokenController注册"]
CheckProfile --> |是| Register["注册DebugTokenController"]
Register --> WarnLog["打印启动警告日志"]
WarnLog --> Ready["接口就绪"]
Ready --> Request["接收POST /api/auth/debug/token?userId=xxx"]
Request --> ValidateUser["验证userId存在"]
ValidateUser --> |不存在| Error["返回错误"]
ValidateUser --> |存在| BuildUser["构建AuthLoginUser"]
BuildUser --> GenToken["调用TokenService.createToken"]
GenToken --> LogAudit["记录审计日志"]
LogAudit --> Return["返回JWT令牌"]
Error --> End(["结束"])
Return --> End
Skip --> End
```
**图表来源**
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
**章节来源**
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
### 认证流程与JWT令牌机制 ### 认证流程与JWT令牌机制
- 登录流程:验证用户名/密码或第三方凭证,加载用户、角色、菜单权限,生成JWT并返回 - 登录流程:验证用户名/密码或第三方凭证,加载用户、角色、菜单权限,生成JWT并返回
- 令牌内容:包含用户标识、角色集合、权限点集合、过期时间等 - 令牌内容:包含用户标识、角色集合、权限点集合、过期时间等
- 令牌校验:过滤器自动解析并填充安全上下文,后续接口无需重复鉴权 - 令牌校验:过滤器自动解析并填充安全上下文,后续接口无需重复鉴权
- 令牌刷新与注销:支持刷新过期令牌、主动注销使令牌失效 - 令牌刷新与注销:支持刷新过期令牌、主动注销使令牌失效
- **调试令牌生成**:验证环境下可通过userId直接生成标准JWT令牌
```mermaid ```mermaid
flowchart TD flowchart TD
@ -567,6 +650,7 @@ SysCtl-->>Admin : "Result<List<Dept>>"
- 控制器依赖服务层,服务层依赖领域模型与Mapper - 控制器依赖服务层,服务层依赖领域模型与Mapper
- 安全过滤器依赖令牌服务与安全上下文 - 安全过滤器依赖令牌服务与安全上下文
- 数据范围拦截器依赖数据可见性上下文 - 数据范围拦截器依赖数据可见性上下文
- **调试令牌端点依赖用户服务和令牌服务**
- 模块间依赖 - 模块间依赖
- crm-auth依赖crm-base提供的异常、结果、安全上下文、工具类与配置 - crm-auth依赖crm-base提供的异常、结果、安全上下文、工具类与配置
- crm-app作为应用入口聚合各模块 - crm-app作为应用入口聚合各模块
@ -579,12 +663,15 @@ Svc --> Mapper["数据访问层"]
Filter["安全过滤器"] --> Token["令牌服务"] Filter["安全过滤器"] --> Token["令牌服务"]
Filter --> Ctx["安全上下文"] Filter --> Ctx["安全上下文"]
Intc["数据范围拦截器"] --> Vis["数据可见性"] Intc["数据范围拦截器"] --> Vis["数据可见性"]
DebugCtl["调试令牌控制器"] --> UserSvc["用户服务"]
DebugCtl --> Token
AuthMod["crm-auth"] --> BaseMod["crm-base"] AuthMod["crm-auth"] --> BaseMod["crm-base"]
AppMod["crm-app"] --> AuthMod AppMod["crm-app"] --> AuthMod
``` ```
**图表来源** **图表来源**
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)
- [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
@ -593,6 +680,7 @@ AppMod["crm-app"] --> AuthMod
**章节来源** **章节来源**
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)
- [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
@ -614,24 +702,31 @@ AppMod["crm-app"] --> AuthMod
- 权限不足:确认用户是否具备所需角色与菜单权限 - 权限不足:确认用户是否具备所需角色与菜单权限
- 数据不可见:检查@DataScope注解与用户所属部门/角色数据范围 - 数据不可见:检查@DataScope注解与用户所属部门/角色数据范围
- 令牌无效:检查Authorization头格式、令牌是否过期或被注销 - 令牌无效:检查Authorization头格式、令牌是否过期或被注销
- **调试令牌接口404**:检查verify profile是否正确激活
- 日志与追踪 - 日志与追踪
- 使用TraceIdFilter贯穿请求链路,便于定位问题 - 使用TraceIdFilter贯穿请求链路,便于定位问题
- 全局异常处理器统一捕获并返回结构化错误信息 - 全局异常处理器统一捕获并返回结构化错误信息
- **调试令牌接口会打印WARN日志**,可用于验证profile激活状态
- 调试建议 - 调试建议
- 开启Knife4j接口文档,快速验证接口行为 - 开启Knife4j接口文档,快速验证接口行为
- 检查Redis中令牌与黑名单状态 - 检查Redis中令牌与黑名单状态
- 查看数据库关联表(用户-角色、角色-菜单、用户-部门)一致性 - 查看数据库关联表(用户-角色、角色-菜单、用户-部门)一致性
- **验证环境检查**:确认application-verify.yml配置正确
**章节来源** **章节来源**
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [TraceIdFilter.java](file://crm-base/src/main/java/com/crm/base/filter/TraceIdFilter.java) - [TraceIdFilter.java](file://crm-base/src/main/java/com/crm/base/filter/TraceIdFilter.java)
- [SecurityExceptionHandlers.java](file://crm-auth/src/main/java/com/crm/auth/security/SecurityExceptionHandlers.java) - [SecurityExceptionHandlers.java](file://crm-auth/src/main/java/com/crm/auth/security/SecurityExceptionHandlers.java)
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
- [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java)
## 结论 ## 结论
认证服务以JWT为核心,结合RBAC与数据权限控制,提供了完整的安全体系。通过模块化设计与清晰的分层架构,实现了用户认证、授权管理、权限控制与第三方登录集成的统一方案。配合统一的异常处理、结果封装与缓存策略,具备良好的可扩展性与可维护性。 认证服务以JWT为核心,结合RBAC与数据权限控制,提供了完整的安全体系。通过模块化设计与清晰的分层架构,实现了用户认证、授权管理、权限控制与第三方登录集成的统一方案。配合统一的异常处理、结果封装与缓存策略,具备良好的可扩展性与可维护性。
**重要更新**:新增的调试令牌端点为验证环境提供了极大的便利性,通过严格的@Profile("verify")机制确保了生产环境的安全性。这一设计体现了在开发便利性与生产安全性之间的平衡考虑。
[本节为总结性内容,不直接分析具体文件] [本节为总结性内容,不直接分析具体文件]
## 附录 ## 附录
@ -639,6 +734,7 @@ AppMod["crm-app"] --> AuthMod
### 配置指南 ### 配置指南
- 应用配置 - 应用配置
- application.yml:设置端口、数据库、Redis、JWT密钥与过期时间等 - application.yml:设置端口、数据库、Redis、JWT密钥与过期时间等
- **application-verify.yml**:验证环境专用配置,包含调试令牌接口的放行规则
- AuthProperties:认证相关自定义配置项 - AuthProperties:认证相关自定义配置项
- 安全配置 - 安全配置
- SecurityConfig:配置白名单、鉴权规则、跨域、异常处理器 - SecurityConfig:配置白名单、鉴权规则、跨域、异常处理器
@ -649,8 +745,11 @@ AppMod["crm-app"] --> AuthMod
- JacksonConfig:日期、空值序列化策略 - JacksonConfig:日期、空值序列化策略
- SnowflakeIdWorker:分布式ID生成策略 - SnowflakeIdWorker:分布式ID生成策略
**更新**:新增了application-verify.yml配置文件,用于验证环境的特殊配置。
**章节来源** **章节来源**
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [application.yml](file://crm-auth/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml)
- [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java) - [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
@ -664,6 +763,7 @@ AppMod["crm-app"] --> AuthMod
- 令牌安全 - 令牌安全
- 使用强密钥与合理的过期时间 - 使用强密钥与合理的过期时间
- 敏感操作二次校验(如密码修改、支付) - 敏感操作二次校验(如密码修改、支付)
- **严禁在生产环境激活verify profile**
- 权限设计 - 权限设计
- 最小权限原则,按需分配角色与菜单 - 最小权限原则,按需分配角色与菜单
- 数据范围粒度适中,避免过度复杂 - 数据范围粒度适中,避免过度复杂
@ -673,5 +773,49 @@ AppMod["crm-app"] --> AuthMod
- 监控与审计 - 监控与审计
- 记录登录、登出、权限变更等关键事件 - 记录登录、登出、权限变更等关键事件
- 使用TraceId串联日志,便于问题定位 - 使用TraceId串联日志,便于问题定位
- **调试令牌接口使用需记录审计日志**
- **验证环境管理**
- 确保CI/CD流程不会在生产环境激活verify profile
- 定期检查verify profile的配置安全性
- 使用环境变量隔离不同环境的配置
**更新**:新增了验证环境管理的相关最佳实践建议。
[本节为通用指导,不直接分析具体文件]
### 验证环境使用说明
**新增章节**:详细说明验证环境专用调试令牌端点的使用方法。
#### 环境准备
1. 确保docker-compose配置中包含verify profile
2. 确认application-verify.yml已正确配置
3. 验证Spring Boot应用以verify profile启动
#### 使用步骤
1. **获取用户ID**:从数据库中查询现有用户的ID
```bash
docker compose exec mysql mysql -uroot -pverify123 -e "SELECT id, username FROM crm.crm_auth_user LIMIT 5;"
```
2. **调用调试接口**:使用userId获取JWT令牌
```bash
curl -X POST 'http://localhost:8080/api/auth/debug/token?userId=<用户ID>'
```
3. **使用令牌**:将返回的JWT放入Authorization头进行其他接口调用
```bash
curl -X GET 'http://localhost:8080/api/file/upload' \
-H "Authorization: Bearer <JWT令牌>"
```
#### 安全注意事项
- **仅限验证环境使用**:该接口绝对不能在生产环境激活
- **审计日志**:每次调用都会记录WARN级别的审计日志
- **令牌有效性**:生成的JWT与正常登录产生的令牌完全一致
- **配置隔离**:通过@Profile("verify")确保端点只在验证环境可用
[本节为通用指导,不直接分析具体文件] **章节来源**
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [deploy-verify.md](file://docs/deploy-verify.md)
- [0014-verify-profile-debug-token-endpoint.md](file://docs/adr/0014-verify-profile-debug-token-endpoint.md)

161
.qoder/repowiki/zh/content/部署指南.md

@ -7,8 +7,13 @@
- [crm-auth/pom.xml](file://crm-auth/pom.xml) - [crm-auth/pom.xml](file://crm-auth/pom.xml)
- [crm-base/pom.xml](file://crm-base/pom.xml) - [crm-base/pom.xml](file://crm-base/pom.xml)
- [crm-file/pom.xml](file://crm-file/pom.xml) - [crm-file/pom.xml](file://crm-file/pom.xml)
- [Dockerfile](file://Dockerfile)
- [docker-compose.yml](file://docker-compose.yml)
- [.dockerignore](file://.dockerignore)
- [settings.xml](file://settings.xml)
- [crm-app/src/main/java/com/crm/app/CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [crm-app/src/main/java/com/crm/app/CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [crm-app/src/main/resources/application.yml](file://crm-app/src/main/resources/application.yml) - [crm-app/src/main/resources/application.yml](file://crm-app/src/main/resources/application.yml)
- [crm-app/src/main/resources/application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [crm-auth/src/main/java/com/crm/auth/AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [crm-auth/src/main/java/com/crm/auth/AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [crm-auth/src/main/resources/application.yml](file://crm-auth/src/main/resources/application.yml) - [crm-auth/src/main/resources/application.yml](file://crm-auth/src/main/resources/application.yml)
- [crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
@ -25,6 +30,14 @@
- [crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) - [crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java)
</cite> </cite>
## 更新摘要
**所做更改**
- 新增完整的Docker容器化部署支持章节
- 添加docker-compose一键部署配置说明
- 更新配置文件管理部分,包含verify环境配置
- 增强Docker镜像构建和优化说明
- 添加容器编排和服务依赖管理指导
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
2. [项目结构](#项目结构) 2. [项目结构](#项目结构)
@ -41,7 +54,7 @@
本指南面向运维与交付团队,提供CRM后端系统的完整部署与运维手册。内容覆盖: 本指南面向运维与交付团队,提供CRM后端系统的完整部署与运维手册。内容覆盖:
- 环境准备与依赖服务安装(MySQL、Redis、MinIO) - 环境准备与依赖服务安装(MySQL、Redis、MinIO)
- 多模块构建与打包 - 多模块构建与打包
- Docker容器化部署 - **新增** Docker容器化部署(含docker-compose一键启动)
- Kubernetes集群部署 - Kubernetes集群部署
- 传统服务器部署 - 传统服务器部署
- 配置文件管理、数据库初始化与服务启动顺序 - 配置文件管理、数据库初始化与服务启动顺序
@ -82,13 +95,13 @@ FILE --> REDIS
FILE --> MINIO FILE --> MINIO
``` ```
图表来源 **图表来源**
- [pom.xml:1-200](file://pom.xml#L1-L200) - [pom.xml:1-200](file://pom.xml#L1-L200)
- [crm-app/src/main/java/com/crm/app/CrmAppApplication.java:1-50](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L50) - [crm-app/src/main/java/com/crm/app/CrmAppApplication.java:1-50](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L50)
- [crm-auth/src/main/java/com/crm/auth/AuthApplication.java:1-50](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L50) - [crm-auth/src/main/java/com/crm/auth/AuthApplication.java:1-50](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L50)
- [crm-file/src/main/java/com/crm/file/config/MinioConfig.java:1-80](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java#L1-L80) - [crm-file/src/main/java/com/crm/file/config/MinioConfig.java:1-80](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java#L1-L80)
章节来源 **章节来源**
- [pom.xml:1-200](file://pom.xml#L1-L200) - [pom.xml:1-200](file://pom.xml#L1-L200)
- [crm-app/pom.xml:1-100](file://crm-app/pom.xml#L1-L100) - [crm-app/pom.xml:1-100](file://crm-app/pom.xml#L1-L100)
- [crm-auth/pom.xml:1-100](file://crm-auth/pom.xml#L1-L100) - [crm-auth/pom.xml:1-100](file://crm-auth/pom.xml#L1-L100)
@ -105,7 +118,7 @@ FILE --> MINIO
- Redis:会话、缓存、分布式锁、限流等 - Redis:会话、缓存、分布式锁、限流等
- MinIO:对象存储,用于文件与附件存储 - MinIO:对象存储,用于文件与附件存储
章节来源 **章节来源**
- [crm-app/src/main/java/com/crm/app/CrmAppApplication.java:1-50](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L50) - [crm-app/src/main/java/com/crm/app/CrmAppApplication.java:1-50](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L50)
- [crm-auth/src/main/java/com/crm/auth/AuthApplication.java:1-50](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L50) - [crm-auth/src/main/java/com/crm/auth/AuthApplication.java:1-50](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L50)
- [crm-base/src/main/java/com/crm/base/config/RedisConfig.java:1-80](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java#L1-L80) - [crm-base/src/main/java/com/crm/base/config/RedisConfig.java:1-80](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java#L1-L80)
@ -127,7 +140,7 @@ FileSrv --> Cache
FileSrv --> OSS["MinIO"] FileSrv --> OSS["MinIO"]
``` ```
图表来源 **图表来源**
- [crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L120)
- [crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L120)
- [crm-file/src/main/java/com/crm/file/config/MinioConfig.java:1-80](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java#L1-L80) - [crm-file/src/main/java/com/crm/file/config/MinioConfig.java:1-80](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java#L1-L80)
@ -170,13 +183,13 @@ A->>D : "业务查询(可选)"
A-->>C : "响应" A-->>C : "响应"
``` ```
图表来源 **图表来源**
- [crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L120)
- [crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L120)
- [crm-auth/src/main/java/com/crm/auth/security/TokenService.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/security/TokenService.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java#L1-L120)
- [crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java#L1-L120)
章节来源 **章节来源**
- [crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L120)
- [crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L120)
- [crm-auth/src/main/java/com/crm/auth/security/TokenService.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/security/TokenService.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java#L1-L120)
@ -211,12 +224,12 @@ SaveMeta --> Done(["结束"])
Wait --> Done Wait --> Done
``` ```
图表来源 **图表来源**
- [crm-file/src/main/java/com/crm/file/config/FileProperties.java:1-80](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java#L1-L80) - [crm-file/src/main/java/com/crm/file/config/FileProperties.java:1-80](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java#L1-L80)
- [crm-file/src/main/java/com/crm/file/config/MinioConfig.java:1-80](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java#L1-L80) - [crm-file/src/main/java/com/crm/file/config/MinioConfig.java:1-80](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java#L1-L80)
- [crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java:1-80](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java#L1-L80) - [crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java:1-80](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java#L1-L80)
章节来源 **章节来源**
- [crm-file/src/main/java/com/crm/file/config/FileProperties.java:1-80](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java#L1-L80) - [crm-file/src/main/java/com/crm/file/config/FileProperties.java:1-80](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java#L1-L80)
- [crm-file/src/main/java/com/crm/file/config/MinioConfig.java:1-80](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java#L1-L80) - [crm-file/src/main/java/com/crm/file/config/MinioConfig.java:1-80](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java#L1-L80)
- [crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java:1-80](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java#L1-L80) - [crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java:1-80](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java#L1-L80)
@ -231,7 +244,7 @@ Wait --> Done
- 作用 - 作用
- 为各业务模块提供统一的配置、工具与安全能力 - 为各业务模块提供统一的配置、工具与安全能力
章节来源 **章节来源**
- [crm-base/src/main/java/com/crm/base/config/RedisConfig.java:1-80](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java#L1-L80) - [crm-base/src/main/java/com/crm/base/config/RedisConfig.java:1-80](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java#L1-L80)
- [crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java:1-80](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java#L1-L80) - [crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java:1-80](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java#L1-L80)
- [crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java:1-80](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java#L1-L80) - [crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java:1-80](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java#L1-L80)
@ -262,14 +275,14 @@ FILE --> REDIS
FILE --> MINIO["MinIO"] FILE --> MINIO["MinIO"]
``` ```
图表来源 **图表来源**
- [pom.xml:1-200](file://pom.xml#L1-L200) - [pom.xml:1-200](file://pom.xml#L1-L200)
- [crm-app/pom.xml:1-100](file://crm-app/pom.xml#L1-L100) - [crm-app/pom.xml:1-100](file://crm-app/pom.xml#L1-L100)
- [crm-auth/pom.xml:1-100](file://crm-auth/pom.xml#L1-L100) - [crm-auth/pom.xml:1-100](file://crm-auth/pom.xml#L1-L100)
- [crm-base/pom.xml:1-100](file://crm-base/pom.xml#L1-L100) - [crm-base/pom.xml:1-100](file://crm-base/pom.xml#L1-L100)
- [crm-file/pom.xml:1-100](file://crm-file/pom.xml#L1-L100) - [crm-file/pom.xml:1-100](file://crm-file/pom.xml#L1-L100)
章节来源 **章节来源**
- [pom.xml:1-200](file://pom.xml#L1-L200) - [pom.xml:1-200](file://pom.xml#L1-L200)
## 性能与容量规划 ## 性能与容量规划
@ -288,8 +301,6 @@ FILE --> MINIO["MinIO"]
- 无状态服务多副本部署 - 无状态服务多副本部署
- 会话与缓存一致性保障 - 会话与缓存一致性保障
[本节为通用指导,不直接引用具体文件]
## 故障排查指南 ## 故障排查指南
- 常见问题定位 - 常见问题定位
- 认证失败:检查JWT密钥、Redis连通性、过滤器链配置 - 认证失败:检查JWT密钥、Redis连通性、过滤器链配置
@ -304,15 +315,13 @@ FILE --> MINIO["MinIO"]
- 灰度发布与快速回滚 - 灰度发布与快速回滚
- 数据快照与增量备份 - 数据快照与增量备份
章节来源 **章节来源**
- [crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java:1-120](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java#L1-L120)
- [crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java:1-80](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java#L1-L80) - [crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java:1-80](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java#L1-L80)
## 结论 ## 结论
通过模块化设计与清晰的依赖边界,结合容器化与Kubernetes编排,可实现高可用、易扩展的CRM后端部署。配合完善的监控、日志与备份策略,能够保障生产环境的稳定性与可恢复性。 通过模块化设计与清晰的依赖边界,结合容器化与Kubernetes编排,可实现高可用、易扩展的CRM后端部署。配合完善的监控、日志与备份策略,能够保障生产环境的稳定性与可恢复性。
[本节为总结性内容,不直接引用具体文件]
## 附录 ## 附录
### 一、环境准备与依赖服务安装 ### 一、环境准备与依赖服务安装
@ -324,7 +333,7 @@ FILE --> MINIO["MinIO"]
- Redis:设置密码、最大内存、持久化策略 - Redis:设置密码、最大内存、持久化策略
- MinIO:创建桶、访问密钥、网络可达性 - MinIO:创建桶、访问密钥、网络可达性
章节来源 **章节来源**
- [crm-base/src/main/java/com/crm/base/config/RedisConfig.java:1-80](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java#L1-L80) - [crm-base/src/main/java/com/crm/base/config/RedisConfig.java:1-80](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java#L1-L80)
- [crm-file/src/main/java/com/crm/file/config/MinioConfig.java:1-80](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java#L1-L80) - [crm-file/src/main/java/com/crm/file/config/MinioConfig.java:1-80](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java#L1-L80)
@ -335,7 +344,7 @@ FILE --> MINIO["MinIO"]
- 构建优化 - 构建优化
- 并行构建、跳过测试、依赖缓存 - 并行构建、跳过测试、依赖缓存
章节来源 **章节来源**
- [pom.xml:1-200](file://pom.xml#L1-L200) - [pom.xml:1-200](file://pom.xml#L1-L200)
- [crm-app/pom.xml:1-100](file://crm-app/pom.xml#L1-L100) - [crm-app/pom.xml:1-100](file://crm-app/pom.xml#L1-L100)
- [crm-auth/pom.xml:1-100](file://crm-auth/pom.xml#L1-L100) - [crm-auth/pom.xml:1-100](file://crm-auth/pom.xml#L1-L100)
@ -346,14 +355,17 @@ FILE --> MINIO["MinIO"]
- 配置分层 - 配置分层
- 应用级application.yml - 应用级application.yml
- 环境级配置(dev/test/prod) - 环境级配置(dev/test/prod)
- **新增** verify专用配置文件(application-verify.yml)
- 外部化配置(环境变量、配置中心) - 外部化配置(环境变量、配置中心)
- 关键配置项 - 关键配置项
- 数据库连接、Redis连接、MinIO端点与凭据 - 数据库连接、Redis连接、MinIO端点与凭据
- JWT密钥、跨域、接口文档开关 - JWT密钥、跨域、接口文档开关
- 文件分片大小、超时、重试策略 - 文件分片大小、超时、重试策略
- **新增** verify环境下的调试接口白名单配置
章节来源 **章节来源**
- [crm-app/src/main/resources/application.yml:1-200](file://crm-app/src/main/resources/application.yml#L1-L200) - [crm-app/src/main/resources/application.yml:1-76](file://crm-app/src/main/resources/application.yml#L1-L76)
- [crm-app/src/main/resources/application-verify.yml:1-13](file://crm-app/src/main/resources/application-verify.yml#L1-L13)
- [crm-auth/src/main/resources/application.yml:1-200](file://crm-auth/src/main/resources/application.yml#L1-L200) - [crm-auth/src/main/resources/application.yml:1-200](file://crm-auth/src/main/resources/application.yml#L1-L200)
- [crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java#L1-L120)
- [crm-file/src/main/java/com/crm/file/config/FileProperties.java:1-80](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java#L1-L80) - [crm-file/src/main/java/com/crm/file/config/FileProperties.java:1-80](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java#L1-L80)
@ -367,22 +379,66 @@ FILE --> MINIO["MinIO"]
- 再启动crm-auth与crm-file - 再启动crm-auth与crm-file
- 最后启动crm-app(若作为聚合入口) - 最后启动crm-app(若作为聚合入口)
章节来源 **章节来源**
- [crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java#L1-L120) - [crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java:1-120](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java#L1-L120)
- [crm-app/src/main/java/com/crm/app/CrmAppApplication.java:1-50](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L50) - [crm-app/src/main/java/com/crm/app/CrmAppApplication.java:1-50](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java#L1-L50)
- [crm-auth/src/main/java/com/crm/auth/AuthApplication.java:1-50](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L50) - [crm-auth/src/main/java/com/crm/auth/AuthApplication.java:1-50](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java#L1-L50)
### 五、Docker容器化部署 ### 五、Docker容器化部署(新增)
- 镜像构建 - **镜像构建**
- 使用多阶段构建减小镜像体积 - 使用多阶段构建减小镜像体积
- 将JAR包与外部配置分离 - 第一阶段:Maven编译打包(基于maven:3.9-eclipse-temurin-17)
- 容器编排 - 第二阶段:运行环境(基于eclipse-temurin:17-jre + LibreOffice headless)
- 定义环境变量、挂载卷(日志、配置) - 包含LibreOffice headless用于Office文档缩略图生成
- 健康检查与资源限制 - 预装中文字体支持CJK渲染
- 示例流程 - **容器编排**
- 构建镜像 → 推送仓库 → 拉取运行 → 验证健康 - docker-compose.yml定义完整服务栈
- 自动拉起MySQL、Redis、MinIO和CRM应用
- 健康检查确保服务依赖正确启动顺序
- 数据卷持久化存储
- **环境变量配置**
- 通过环境变量注入中间件连接信息
- SPRING_PROFILES_ACTIVE=verify激活验证环境
- 数据库、Redis、MinIO连接参数配置
- **构建优化**
- .dockerignore排除不必要的文件
- Maven依赖缓存利用Docker层缓存
- 阿里云Maven镜像加速依赖下载
**新增** Docker部署架构图:
```mermaid
graph TB
subgraph "Docker Compose 服务栈"
MYSQL["MySQL 8.4.8<br/>端口: 13306"]
REDIS["Redis 7 Alpine<br/>端口: 6379"]
MINIO["MinIO<br/>控制台: 9001"]
MINIO_INIT["MinIO初始化<br/>创建bucket"]
CRM_APP["CRM应用<br/>端口: 8080<br/>verify profile"]
end
MYSQL -.健康检查.-> CRM_APP
REDIS -.健康检查.-> CRM_APP
MINIO -.健康检查.-> MINIO_INIT
MINIO_INIT -.健康检查.-> CRM_APP
subgraph "数据持久化"
MYSQL_DATA["mysql-data"]
REDIS_DATA["redis-data"]
MINIO_DATA["minio-data"]
end
MYSQL --- MYSQL_DATA
REDIS --- REDIS_DATA
MINIO --- MINIO_DATA
```
**图表来源**
- [docker-compose.yml:1-100](file://docker-compose.yml#L1-L100)
- [Dockerfile:1-27](file://Dockerfile#L1-L27)
[本节为通用指导,不直接引用具体文件] **章节来源**
- [Dockerfile:1-27](file://Dockerfile#L1-L27)
- [docker-compose.yml:1-100](file://docker-compose.yml#L1-L100)
- [.dockerignore:1-14](file://.dockerignore#L1-L14)
- [settings.xml:1-14](file://settings.xml#L1-L14)
### 六、Kubernetes集群部署 ### 六、Kubernetes集群部署
- 部署清单 - 部署清单
@ -396,8 +452,6 @@ FILE --> MINIO["MinIO"]
- 日志落盘与远端收集 - 日志落盘与远端收集
- 文件服务对接MinIO PVC或外部存储 - 文件服务对接MinIO PVC或外部存储
[本节为通用指导,不直接引用具体文件]
### 七、传统服务器部署 ### 七、传统服务器部署
- 进程管理 - 进程管理
- 使用systemd或supervisor管理服务生命周期 - 使用systemd或supervisor管理服务生命周期
@ -406,8 +460,6 @@ FILE --> MINIO["MinIO"]
- 日志轮转 - 日志轮转
- logrotate配置,保留策略与压缩 - logrotate配置,保留策略与压缩
[本节为通用指导,不直接引用具体文件]
### 八、生产环境优化配置 ### 八、生产环境优化配置
- JVM调优 - JVM调优
- 堆大小、GC选择、元空间、线程栈大小 - 堆大小、GC选择、元空间、线程栈大小
@ -418,8 +470,6 @@ FILE --> MINIO["MinIO"]
- 文件服务优化 - 文件服务优化
- MinIO节点横向扩展、分片大小与并发限制 - MinIO节点横向扩展、分片大小与并发限制
[本节为通用指导,不直接引用具体文件]
### 九、监控告警设置 ### 九、监控告警设置
- 指标采集 - 指标采集
- JVM、GC、线程、连接池、QPS、延迟 - JVM、GC、线程、连接池、QPS、延迟
@ -429,8 +479,6 @@ FILE --> MINIO["MinIO"]
- 可视化 - 可视化
- 仪表盘与告警通知渠道 - 仪表盘与告警通知渠道
[本节为通用指导,不直接引用具体文件]
### 十、日志收集方案 ### 十、日志收集方案
- 应用日志 - 应用日志
- 结构化输出、TraceId贯穿、分级输出 - 结构化输出、TraceId贯穿、分级输出
@ -439,8 +487,6 @@ FILE --> MINIO["MinIO"]
- 日志策略 - 日志策略
- 保留周期、脱敏、采样与压缩 - 保留周期、脱敏、采样与压缩
[本节为通用指导,不直接引用具体文件]
### 十一、备份恢复策略 ### 十一、备份恢复策略
- 数据库备份 - 数据库备份
- 全量+增量、异地备份、加密与校验 - 全量+增量、异地备份、加密与校验
@ -449,8 +495,6 @@ FILE --> MINIO["MinIO"]
- 恢复演练 - 恢复演练
- 定期演练恢复流程,验证RTO/RPO - 定期演练恢复流程,验证RTO/RPO
[本节为通用指导,不直接引用具体文件]
### 十二、负载均衡、SSL证书与域名绑定 ### 十二、负载均衡、SSL证书与域名绑定
- 负载均衡 - 负载均衡
- Nginx/Ingress分发、健康检查、权重与灰度 - Nginx/Ingress分发、健康检查、权重与灰度
@ -459,4 +503,33 @@ FILE --> MINIO["MinIO"]
- 域名绑定 - 域名绑定
- DNS解析、CDN加速、WAF防护 - DNS解析、CDN加速、WAF防护
[本节为通用指导,不直接引用具体文件] ### 十三、Docker部署快速开始(新增)
- **前置条件**
- Docker Engine ≥ 20.10
- Docker Compose ≥ 2.x
- 至少6GB可用磁盘空间(LibreOffice镜像约1.5GB)
- 网络连接(拉取Maven依赖和Docker镜像)
- **一键启动**
```bash
# 首次构建并启动所有服务
docker compose up -d --build
# 查看应用日志
docker compose logs -f crm-app
# 停止并清理所有资源
docker compose down -v
```
- **服务访问**
- CRM应用:http://localhost:8080
- MinIO控制台:http://localhost:9001(minioadmin/minioadmin)
- MySQL:localhost:13306(root/verify123)
- **验证环境特性**
- verify profile启用了调试token接口
- 支持免鉴权访问缩略图接口
- 自动创建数据库表和MinIO bucket
**章节来源**
- [docker-compose.yml:1-100](file://docker-compose.yml#L1-L100)
- [docs/deploy-verify.md:1-168](file://docs/deploy-verify.md#L1-L168)
- [crm-app/src/main/resources/application-verify.yml:1-13](file://crm-app/src/main/resources/application-verify.yml#L1-L13)

221
.qoder/repowiki/zh/content/配置指南/配置指南.md

@ -3,7 +3,7 @@
<cite> <cite>
**本文引用的文件** **本文引用的文件**
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
- [application.yml](file://crm-auth/src/main/resources/application.yml) - [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
@ -24,8 +24,22 @@
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java) - [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [ThumbnailRetryTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailRetryTask.java)
- [ImageThumbnailRenderer.java](file://crm-file/src/main/java/com/crm/file/service/impl/ImageThumbnailRenderer.java)
- [OfficeThumbnailRenderer.java](file://crm-file/src/main/java/com/crm/file/service/impl/OfficeThumbnailRenderer.java)
- [PdfThumbnailRenderer.java](file://crm-file/src/main/java/com/crm/file/service/impl/PdfThumbnailRenderer.java)
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
</cite> </cite>
## 更新摘要
**变更内容**
- 新增缩略图配置类 FileProperties.Thumbnail,包含完整的缩略图生成配置选项
- 新增 application-verify.yml 验证环境配置文件,支持调试和测试场景
- 完善缩略图渲染器配置(图片、PDF、Office文档)
- 增强定时任务配置(缩略图生成、失败重试)
- 扩展环境变量覆盖机制
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
2. [项目结构](#项目结构) 2. [项目结构](#项目结构)
@ -43,7 +57,9 @@
- 所有关键配置项的含义、默认值、环境变量覆盖方式 - 所有关键配置项的含义、默认值、环境变量覆盖方式
- 动态配置更新机制(如适用) - 动态配置更新机制(如适用)
- 数据库连接、Redis 缓存、MinIO 文件存储、JWT 安全、日志级别等核心配置 - 数据库连接、Redis 缓存、MinIO 文件存储、JWT 安全、日志级别等核心配置
- 不同环境的配置模板(开发、测试、生产) - **新增:缩略图生成配置(尺寸、格式、重试策略、LibreOffice路径)**
- **新增:验证环境专用配置(调试接口、权限豁免)**
- 不同环境的配置模板(开发、测试、生产、验证)
- 配置验证规则、热更新机制、最佳实践、性能调优参数与故障排查 - 配置验证规则、热更新机制、最佳实践、性能调优参数与故障排查
## 项目结构 ## 项目结构
@ -51,7 +67,7 @@
- crm-app:应用启动入口与全局应用配置 - crm-app:应用启动入口与全局应用配置
- crm-auth:认证授权与安全相关配置 - crm-auth:认证授权与安全相关配置
- crm-base:公共基础配置(Redis、Jackson、MyBatis-Plus、跨域、接口文档等) - crm-base:公共基础配置(Redis、Jackson、MyBatis-Plus、跨域、接口文档等)
- crm-file:文件服务(MinIO、分片上传、定时清理任务) - crm-file:文件服务(MinIO、分片上传、缩略图生成、定时清理任务)
```mermaid ```mermaid
graph TB graph TB
@ -62,16 +78,19 @@ FILE["crm-file<br/>文件服务"]
end end
subgraph "基础能力" subgraph "基础能力"
BASE["crm-base<br/>通用配置与工具"] BASE["crm-base<br/>通用配置与工具"]
THUMB["缩略图系统<br/>渲染器+任务调度"]
end end
APP --> AUTH APP --> AUTH
APP --> FILE APP --> FILE
AUTH --> BASE AUTH --> BASE
FILE --> BASE FILE --> BASE
FILE --> THUMB
``` ```
**图表来源** **图表来源**
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
**章节来源** **章节来源**
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
@ -82,6 +101,7 @@ FILE --> BASE
- 数据访问:MyBatis-Plus 配置、元对象填充、自定义 ID 生成器 - 数据访问:MyBatis-Plus 配置、元对象填充、自定义 ID 生成器
- 缓存:Redis 客户端配置与序列化策略 - 缓存:Redis 客户端配置与序列化策略
- 文件存储:MinIO 客户端与文件属性绑定 - 文件存储:MinIO 客户端与文件属性绑定
- **缩略图系统:缩略图生成配置、渲染器、异步任务、失败重试**
- 安全:Spring Security + JWT 过滤器与令牌服务 - 安全:Spring Security + JWT 过滤器与令牌服务
- 调度:任务调度开关与属性 - 调度:任务调度开关与属性
- 接口文档:Knife4j 配置 - 接口文档:Knife4j 配置
@ -90,28 +110,20 @@ FILE --> BASE
**章节来源** **章节来源**
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
- [application.yml](file://crm-auth/src/main/resources/application.yml) - [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [ThumbnailRetryTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailRetryTask.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java)
- [ScheduledTaskProperties.java](file://crm-base/src/main/java/com/crm/base/config/ScheduledTaskProperties.java)
- [JacksonConfig.java](file://crm-base/src/main/java/com/crm/base/config/JacksonConfig.java)
- [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java)
- [Knife4jConfig.java](file://crm-base/src/main/java/com/crm/base/config/Knife4jConfig.java)
## 架构总览 ## 架构总览
下图展示了配置加载与运行时依赖关系:应用启动时读取 application.yml,注入各配置类;业务组件通过 @ConfigurationProperties@Value 获取配置;安全、缓存、文件、调度等子系统按配置初始化。 下图展示了配置加载与运行时依赖关系:应用启动时读取 application.yml,注入各配置类;业务组件通过 @ConfigurationProperties@Value 获取配置;安全、缓存、文件、调度、缩略图等子系统按配置初始化。
```mermaid ```mermaid
graph LR graph LR
YML["application.yml<br/>配置文件"] --> BOOT["Spring Boot 容器"] YML["application.yml<br/>配置文件"] --> BOOT["Spring Boot 容器"]
BOOT --> PROPS_AUTH["AuthProperties<br/>认证属性"] BOOT --> PROPS_AUTH["AuthProperties<br/>认证属性"]
BOOT --> PROPS_FILE["FileProperties<br/>文件属性"] BOOT --> PROPS_FILE["FileProperties<br/>文件属性"]
BOOT --> PROPS_THUMB["Thumbnail<br/>缩略图配置"]
BOOT --> CFG_BASE["Base 配置集合<br/>Redis/MyBatis-Plus/Jackson/CORS/Knife4j"] BOOT --> CFG_BASE["Base 配置集合<br/>Redis/MyBatis-Plus/Jackson/CORS/Knife4j"]
BOOT --> CFG_SEC["SecurityConfig<br/>安全配置"] BOOT --> CFG_SEC["SecurityConfig<br/>安全配置"]
BOOT --> CFG_MINIO["MinioConfig<br/>MinIO 客户端"] BOOT --> CFG_MINIO["MinioConfig<br/>MinIO 客户端"]
@ -121,29 +133,29 @@ FILTER --> TOKEN["TokenService<br/>令牌服务"]
CFG_MINIO --> FILE_SVC["文件服务"] CFG_MINIO --> FILE_SVC["文件服务"]
CFG_BASE --> REDIS["Redis 缓存"] CFG_BASE --> REDIS["Redis 缓存"]
CFG_BASE --> DB["数据库(MyBatis-Plus)"] CFG_BASE --> DB["数据库(MyBatis-Plus)"]
PROPS_THUMB --> THUMB_TASK["缩略图任务<br/>生成+重试"]
THUMB_TASK --> RENDERERS["渲染器<br/>图片/PDF/Office"]
RENDERERS --> LIBREOFFICE["LibreOffice<br/>文档转换"]
``` ```
**图表来源** **图表来源**
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
- [application.yml](file://crm-auth/src/main/resources/application.yml) - [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java)
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [OfficeThumbnailRenderer.java](file://crm-file/src/main/java/com/crm/file/service/impl/OfficeThumbnailRenderer.java)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java)
## 详细组件分析 ## 详细组件分析
### 应用与模块入口 ### 应用与模块入口
- 应用启动类负责扫描包与启用自动配置,确保各模块的配置类被加载 - 应用启动类负责扫描包与启用自动配置,确保各模块的配置类被加载
- 多模块共享 application.yml,可按模块拆分 profile - 多模块共享 application.yml,可按模块拆分 profile
- **新增:验证环境专用配置,支持调试接口和权限豁免**
**章节来源** **章节来源**
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
### 数据库连接配置(MyBatis-Plus) ### 数据库连接配置(MyBatis-Plus)
- 数据源 URL、用户名、密码、驱动、连接池参数由 application.yml 提供 - 数据源 URL、用户名、密码、驱动、连接池参数由 application.yml 提供
@ -176,6 +188,7 @@ EnablePlugins --> Ready(["就绪"])
### Redis 缓存配置 ### Redis 缓存配置
- Redis 主机、端口、密码、数据库索引、超时时间、序列化策略在 application.yml 中定义 - Redis 主机、端口、密码、数据库索引、超时时间、序列化策略在 application.yml 中定义
- RedisConfig 负责创建 RedisTemplate 并配置序列化器,保证与 JSON 的一致性 - RedisConfig 负责创建 RedisTemplate 并配置序列化器,保证与 JSON 的一致性
- **缩略图分布式锁使用 Redis 实现,TTL 配置需大于最慢渲染时间**
```mermaid ```mermaid
classDiagram classDiagram
@ -185,13 +198,20 @@ class RedisConfig {
} }
class FileProperties { class FileProperties {
+redis相关字段 +redis相关字段
+thumbnail.lockTtl : Duration
}
class ThumbnailGenerationTask {
+generateWithLock(fileId)
+lockTtl配置
} }
RedisConfig <.. FileProperties : "使用Redis进行会话/缓存" RedisConfig <.. FileProperties : "使用Redis进行会话/缓存"
RedisConfig <.. ThumbnailGenerationTask : "分布式锁"
``` ```
**图表来源** **图表来源**
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
**章节来源** **章节来源**
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
@ -201,6 +221,7 @@ RedisConfig <.. FileProperties : "使用Redis进行会话/缓存"
### MinIO 文件存储配置 ### MinIO 文件存储配置
- MinIO 端点、AccessKey、SecretKey、Bucket 名称、URL 前缀等由 application.yml 提供 - MinIO 端点、AccessKey、SecretKey、Bucket 名称、URL 前缀等由 application.yml 提供
- FileProperties 绑定文件相关配置(如分片大小、路径策略),MinioConfig 初始化客户端 - FileProperties 绑定文件相关配置(如分片大小、路径策略),MinioConfig 初始化客户端
- **缩略图存储在 thumbnails/{fileId}.jpg 路径下**
```mermaid ```mermaid
sequenceDiagram sequenceDiagram
@ -213,11 +234,13 @@ App->>Minio : 初始化客户端
Minio->>Client : 构建连接(端点/密钥/Bucket) Minio->>Client : 构建连接(端点/密钥/Bucket)
Client-->>Minio : 客户端实例 Client-->>Minio : 客户端实例
Minio-->>App : 返回可用客户端 Minio-->>App : 返回可用客户端
Note over Client : 缩略图存储 : thumbnails/{fileId}.jpg
``` ```
**图表来源** **图表来源**
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
**章节来源** **章节来源**
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
@ -228,6 +251,7 @@ Minio-->>App : 返回可用客户端
### JWT 安全配置 ### JWT 安全配置
- Spring Security 与 JWT 过滤器协同工作,TokenService 负责令牌签发、校验与刷新 - Spring Security 与 JWT 过滤器协同工作,TokenService 负责令牌签发、校验与刷新
- AuthProperties 可能包含 JWT 密钥、过期时间、白名单等 - AuthProperties 可能包含 JWT 密钥、过期时间、白名单等
- **验证环境支持调试接口和缩略图接口权限豁免**
```mermaid ```mermaid
sequenceDiagram sequenceDiagram
@ -240,6 +264,7 @@ Filter->>Token : 解析并校验令牌
Token-->>Filter : 校验结果 Token-->>Filter : 校验结果
Filter->>Sec : 设置认证上下文 Filter->>Sec : 设置认证上下文
Sec-->>Client : 放行或拒绝 Sec-->>Client : 放行或拒绝
Note over Sec : 验证环境 : /api/file/thumbnail 豁免鉴权
``` ```
**图表来源** **图表来源**
@ -247,9 +272,11 @@ Sec-->>Client : 放行或拒绝
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java) - [AuthProperties.java](file://crm-auth/src/main/java/com/crm/auth/config/AuthProperties.java)
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
**章节来源** **章节来源**
- [application.yml](file://crm-auth/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml)
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
@ -278,11 +305,84 @@ Sec-->>Client : 放行或拒绝
- [ScheduledTaskProperties.java](file://crm-base/src/main/java/com/crm/base/config/ScheduledTaskProperties.java) - [ScheduledTaskProperties.java](file://crm-base/src/main/java/com/crm/base/config/ScheduledTaskProperties.java)
- [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java) - [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java)
### 缩略图配置系统(新增)
**更新** 新增完整的缩略图配置类,支持多种文件类型的缩略图生成
#### 缩略图基本配置
- **width**: 缩略图固定宽度(px),默认 200,等比缩放
- **maxHeight**: 缩略图等比缩放上限高度(px),防止超长截图,默认 400
- **format**: 输出格式(jpeg/png),默认 jpeg
- **syncWaitTimeout**: 同步兜底等待超时,PENDING 状态获锁失败后的轮询上限,默认 10秒
#### 缩略图重试策略
- **retryLimit**: 最大重试次数,达到后标记 FAILED,默认 3次
- **retryCron**: FAILED 重试扫描周期(cron),默认每天凌晨 4点
- **lockTtl**: 生成分布式锁 TTL,必须大于 officeConvertTimeout,默认 150秒
#### LibreOffice 配置
- **libreofficePath**: LibreOffice 可执行文件路径,默认 soffice
- **officeConvertTimeout**: LibreOffice 单次转换超时(大文档首页渲染可能较慢),默认 120秒
```mermaid
flowchart TD
Upload["文件上传"] --> CheckType{"文件类型检查"}
CheckType --> |图片| ImgThumb["图片缩略图<br/>ImageThumbnailRenderer"]
CheckType --> |PDF| PdfThumb["PDF缩略图<br/>PdfThumbnailRenderer"]
CheckType --> |Office| OfficeThumb["Office缩略图<br/>OfficeThumbnailRenderer"]
CheckType --> |不支持| Unsupported["UNSUPPORTED<br/>跳过生成"]
ImgThumb --> AsyncGen["异步生成<br/>ThumbnailGenerationTask"]
PdfThumb --> AsyncGen
OfficeThumb --> AsyncGen
AsyncGen --> Success{"生成成功?"}
Success --> |是| Ready["READY<br/>存储到MinIO"]
Success --> |否| RetryCount{"重试次数<br/>未达上限?"}
RetryCount --> |是| Pending["PENDING<br/>等待下次重试"]
RetryCount --> |否| Failed["FAILED<br/>标记失败"]
Pending --> RetryTask["ThumbnailRetryTask<br/>定时重试"]
RetryTask --> AsyncGen
```
**图表来源**
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [ThumbnailRetryTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailRetryTask.java)
- [ImageThumbnailRenderer.java](file://crm-file/src/main/java/com/crm/file/service/impl/ImageThumbnailRenderer.java)
- [PdfThumbnailRenderer.java](file://crm-file/src/main/java/com/crm/file/service/impl/PdfThumbnailRenderer.java)
- [OfficeThumbnailRenderer.java](file://crm-file/src/main/java/com/crm/file/service/impl/OfficeThumbnailRenderer.java)
**章节来源**
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [ThumbnailRetryTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailRetryTask.java)
- [ImageThumbnailRenderer.java](file://crm-file/src/main/java/com/crm/file/service/impl/ImageThumbnailRenderer.java)
- [PdfThumbnailRenderer.java](file://crm-file/src/main/java/com/crm/file/service/impl/PdfThumbnailRenderer.java)
- [OfficeThumbnailRenderer.java](file://crm-file/src/main/java/com/crm/file/service/impl/OfficeThumbnailRenderer.java)
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
### 验证环境配置(新增)
**更新** 新增 application-verify.yml 验证环境专用配置
#### 验证环境特性
- **Profile**: verify 专用环境,严禁用于生产
- **调试接口**: /api/auth/debug/token 直接签发 JWT,绕过钉钉扫码
- **权限豁免**: /api/file/thumbnail 缩略图接口无需鉴权
- **部署环境**: 内网验证环境 172.16.204.61 的 docker-compose
#### 安全护栏
- @Profile("verify") 注解确保生产环境不激活
- 启动期打印 WARN 日志留审计痕迹
- 端点在 ignore-urls 中明确放行
**章节来源**
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)
## 依赖关系分析 ## 依赖关系分析
- 配置类之间低耦合,主要通过 application.yml 解耦 - 配置类之间低耦合,主要通过 application.yml 解耦
- 安全模块依赖 Redis(可选用于黑名单/限流)、JWT(无状态) - 安全模块依赖 Redis(可选用于黑名单/限流)、JWT(无状态)
- 文件模块依赖 MinIO 与 Redis(分片会话) - 文件模块依赖 MinIO 与 Redis(分片会话、缩略图锁
- 数据访问模块依赖 MyBatis-Plus 与数据库 - 数据访问模块依赖 MyBatis-Plus 与数据库
- **缩略图系统依赖渲染器列表、Redis 分布式锁、MinIO 存储**
```mermaid ```mermaid
graph TB graph TB
@ -292,6 +392,10 @@ FILE["文件模块"] --> MINIO["MinIO"]
FILE --> REDIS FILE --> REDIS
DB["数据访问模块"] --> MP["MyBatis-Plus"] DB["数据访问模块"] --> MP["MyBatis-Plus"]
MP --> MYSQL["数据库"] MP --> MYSQL["数据库"]
THUMB["缩略图系统"] --> RENDERERS["渲染器"]
THUMB --> REDIS
THUMB --> MINIO
RENDERERS --> LIBREOFFICE["LibreOffice"]
``` ```
**图表来源** **图表来源**
@ -301,6 +405,8 @@ MP --> MYSQL["数据库"]
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
- [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java)
- [OfficeThumbnailRenderer.java](file://crm-file/src/main/java/com/crm/file/service/impl/OfficeThumbnailRenderer.java)
**章节来源** **章节来源**
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
@ -313,8 +419,7 @@ MP --> MYSQL["数据库"]
- Jackson:关闭不必要的序列化特性,减少 CPU 消耗 - Jackson:关闭不必要的序列化特性,减少 CPU 消耗
- 日志:生产环境降低日志级别,避免 I/O 瓶颈 - 日志:生产环境降低日志级别,避免 I/O 瓶颈
- 调度:避免高频任务导致资源争用 - 调度:避免高频任务导致资源争用
- **缩略图:合理设置 width/maxHeight 平衡清晰度与性能,调整 retryLimit 避免无限重试,优化 lockTtl 防止重复生成**
[本节为通用指导,不直接分析具体文件]
## 故障排查指南 ## 故障排查指南
- 数据库连接失败:检查 URL、用户名、密码、驱动、网络连通性;查看连接池报错 - 数据库连接失败:检查 URL、用户名、密码、驱动、网络连通性;查看连接池报错
@ -322,6 +427,7 @@ MP --> MYSQL["数据库"]
- MinIO 上传失败:校验端点、AccessKey/SecretKey、Bucket 权限;检查网络与代理 - MinIO 上传失败:校验端点、AccessKey/SecretKey、Bucket 权限;检查网络与代理
- JWT 鉴权失败:检查密钥一致性、过期时间、白名单配置;查看过滤器日志 - JWT 鉴权失败:检查密钥一致性、过期时间、白名单配置;查看过滤器日志
- 日志过多:临时提升日志级别定位问题,恢复后回退到生产级别 - 日志过多:临时提升日志级别定位问题,恢复后回退到生产级别
- **缩略图生成失败:检查 LibreOffice 路径配置、文件格式支持、渲染器可用性;查看重试计数和失败状态**
**章节来源** **章节来源**
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
@ -330,11 +436,10 @@ MP --> MYSQL["数据库"]
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
- [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java)
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
## 结论 ## 结论
通过统一的 application.yml 与各模块配置类,本项目实现了可维护、可扩展的配置管理。结合环境变量覆盖与合理的默认值,可在不同环境中快速部署与调优。建议在生产环境严格校验配置、限制敏感信息暴露,并结合监控告警保障稳定性。 通过统一的 application.yml 与各模块配置类,本项目实现了可维护、可扩展的配置管理。**新增的缩略图配置系统提供了完整的文件预览能力,支持多种文件格式的智能生成和重试机制**。结合环境变量覆盖与合理的默认值,可在不同环境中快速部署与调优。建议在生产环境严格校验配置、限制敏感信息暴露,并结合监控告警保障稳定性。
[本节为总结,不直接分析具体文件]
## 附录 ## 附录
@ -344,26 +449,35 @@ MP --> MYSQL["数据库"]
[本节为概念性说明,不直接分析具体文件] [本节为概念性说明,不直接分析具体文件]
### 配置模板(开发、测试、生产) ### 配置模板(开发、测试、生产、验证
以下为推荐的环境模板要点(示例,非代码片段): 以下为推荐的环境模板要点(示例,非代码片段):
- 开发环境 - 开发环境
- 数据库:本地 MySQL,调试模式开启,SQL 打印 - 数据库:本地 MySQL,调试模式开启,SQL 打印
- Redis:本地或开发集群,连接池较小 - Redis:本地或开发集群,连接池较小
- MinIO:本地 MinIO,Bucket 自动创建 - MinIO:本地 MinIO,Bucket 自动创建
- JWT:短过期时间,宽松白名单 - JWT:短过期时间,宽松白名单
- 缩略图:LibreOffice 本地安装,宽度和高度适中
- 日志:DEBUG - 日志:DEBUG
- 测试环境 - 测试环境
- 数据库:独立测试库,隔离数据 - 数据库:独立测试库,隔离数据
- Redis:测试集群,禁用持久化 - Redis:测试集群,禁用持久化
- MinIO:测试桶,预置样例文件 - MinIO:测试桶,预置样例文件
- JWT:中等过期时间,严格白名单 - JWT:中等过期时间,严格白名单
- 缩略图:LibreOffice 容器化部署,优化转换超时
- 日志:INFO - 日志:INFO
- 生产环境 - 生产环境
- 数据库:高可用集群,连接池优化,慢查询日志 - 数据库:高可用集群,连接池优化,慢查询日志
- Redis:生产集群,连接池与序列化优化 - Redis:生产集群,连接池与序列化优化
- MinIO:生产桶,CDN 加速,访问审计 - MinIO:生产桶,CDN 加速,访问审计
- JWT:长过期时间+刷新机制,强校验 - JWT:长过期时间+刷新机制,强校验
- 缩略图:LibreOffice 集群部署,合理配置重试和超时
- 日志:WARN/ERROR,集中采集 - 日志:WARN/ERROR,集中采集
- **验证环境**
- Profile:verify 专用环境
- 调试接口:启用 /api/auth/debug/token
- 权限豁免:缩略图接口无需鉴权
- 部署:docker-compose 一键部署
- 安全:仅限内网验证环境使用
[本节为概念性说明,不直接分析具体文件] [本节为概念性说明,不直接分析具体文件]
@ -371,6 +485,7 @@ MP --> MYSQL["数据库"]
- 必填项校验:数据库 URL、用户名、密码;MinIO 端点、密钥、Bucket;JWT 密钥 - 必填项校验:数据库 URL、用户名、密码;MinIO 端点、密钥、Bucket;JWT 密钥
- 类型校验:端口为整数、超时时间为正数、布尔开关合法 - 类型校验:端口为整数、超时时间为正数、布尔开关合法
- 范围校验:连接池大小、分片大小、过期时间区间 - 范围校验:连接池大小、分片大小、过期时间区间
- **缩略图校验:width/maxHeight 为正数、retryLimit ≥ 1、lockTtl > officeConvertTimeout**
- 建议:在启动阶段进行配置校验,失败则快速失败并给出明确错误信息 - 建议:在启动阶段进行配置校验,失败则快速失败并给出明确错误信息
[本节为概念性说明,不直接分析具体文件] [本节为概念性说明,不直接分析具体文件]
@ -379,6 +494,7 @@ MP --> MYSQL["数据库"]
- 引入配置中心:Nacos/Apollo/Spring Cloud Config - 引入配置中心:Nacos/Apollo/Spring Cloud Config
- 使用 @RefreshScope 刷新 Bean 或监听配置变更事件 - 使用 @RefreshScope 刷新 Bean 或监听配置变更事件
- 对敏感配置(密钥)采用加密存储与动态轮换 - 对敏感配置(密钥)采用加密存储与动态轮换
- **缩略图配置热更新:支持运行时调整生成参数和重试策略**
[本节为概念性说明,不直接分析具体文件] [本节为概念性说明,不直接分析具体文件]
@ -388,5 +504,46 @@ MP --> MYSQL["数据库"]
- 版本化管理:配置文件纳入版本控制,变更留痕 - 版本化管理:配置文件纳入版本控制,变更留痕
- 监控与告警:连接失败、超时、鉴权失败等指标接入监控 - 监控与告警:连接失败、超时、鉴权失败等指标接入监控
- 灰度发布:先小流量验证配置变更效果 - 灰度发布:先小流量验证配置变更效果
- **缩略图最佳实践:根据业务需求调整尺寸和格式,合理配置重试策略,监控 LibreOffice 资源使用情况**
[本节为概念性说明,不直接分析具体文件] [本节为概念性说明,不直接分析具体文件]
### 缩略图配置详解
**更新** 详细的缩略图配置项说明:
#### 基本配置项
- `crm.file.thumbnail.width`: 缩略图宽度(像素),默认 200
- `crm.file.thumbnail.maxHeight`: 最大高度(像素),默认 400
- `crm.file.thumbnail.format`: 输出格式,支持 jpeg/png,默认 jpeg
- `crm.file.thumbnail.syncWaitTimeout`: 同步等待超时,默认 10秒
#### 重试策略配置
- `crm.file.thumbnail.retryLimit`: 最大重试次数,默认 3
- `crm.file.thumbnail.retryCron`: 重试任务 cron 表达式,默认 "0 0 4 * * ?"
- `crm.file.thumbnail.lockTtl`: 分布式锁 TTL,默认 150秒
#### LibreOffice 配置
- `crm.file.thumbnail.libreofficePath`: LibreOffice 路径,默认 soffice
- `crm.file.thumbnail.officeConvertTimeout`: 转换超时,默认 120秒
**章节来源**
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
- [application.yml](file://crm-app/src/main/resources/application.yml)
### 验证环境配置详解
**更新** 验证环境专用配置说明:
#### 环境特性
- 激活方式:SPRING_PROFILES_ACTIVE=verify
- 调试接口:/api/auth/debug/token 直接签发 JWT
- 权限豁免:/api/file/thumbnail 无需鉴权
- 安全警告:启动期打印 WARN 日志
#### 部署说明
- 目标环境:172.16.204.61 内网验证环境
- 部署方式:docker-compose 一键部署
- 数据安全:验证完毕后可清理容器和数据卷
**章节来源**
- [application-verify.yml](file://crm-app/src/main/resources/application-verify.yml)
- [DebugTokenController.java](file://crm-auth/src/main/java/com/crm/auth/controller/DebugTokenController.java)

572
.qoder/repowiki/zh/content/项目概览/模块说明/基础框架模块(crm-base)/基础框架模块(crm-base).md

@ -46,8 +46,30 @@
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
- [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java)
- [DictGroupDefault.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroupDefault.java)
- [DictRefCount.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictRefCount.java)
- [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
- [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java)
- [DictItemController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictItemController.java)
- [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java)
- [IDictItemService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictItemService.java)
- [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
- [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java)
- [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java)
- [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java)
- [DictConstants.java](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java)
</cite> </cite>
## 更新摘要
**变更内容**
- 更新了数据字典模块的VO设计架构,DictGroupVO和DictItemVO现在使用独立字段定义而非继承实体类
- 增强了API设计的清晰度和安全性,通过明确的字段暴露控制敏感信息
- 优化了服务层实现以适配新的VO结构,提升了数据转换效率
- 完善了VO设计模式的最佳实践说明
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
2. [项目结构](#项目结构) 2. [项目结构](#项目结构)
@ -63,6 +85,8 @@
## 简介 ## 简介
本模块为 CRM 后端的基础设施层,提供通用实体、分页与结果封装、全局异常处理、数据访问层封装、工具类以及 MyBatis Plus、Redis、雪花ID等关键配置。通过统一的设计模式与约定,降低业务模块重复开发成本,提升一致性与可维护性。 本模块为 CRM 后端的基础设施层,提供通用实体、分页与结果封装、全局异常处理、数据访问层封装、工具类以及 MyBatis Plus、Redis、雪花ID等关键配置。通过统一的设计模式与约定,降低业务模块重复开发成本,提升一致性与可维护性。
**更新** 新增 crm-dict 数据字典模块,作为独立的服务模块提供平台级键值字典管理能力,支持分组管理、字典项管理、引用计数和权限集成等功能。该模块采用了先进的VO设计模式,通过独立的视图对象定义提升了API的安全性和清晰度。
## 项目结构 ## 项目结构
crm-base 采用分层组织: crm-base 采用分层组织:
- domain:通用实体、DTO、参数、枚举、异常、结果封装 - domain:通用实体、DTO、参数、枚举、异常、结果封装
@ -72,72 +96,60 @@ crm-base 采用分层组织:
- security:数据权限控制、可见性上下文、登录用户模型与安全工具 - security:数据权限控制、可见性上下文、登录用户模型与安全工具
- utils:通用工具集(断言、拷贝、枚举、Excel、分页转换、Servlet、树形结构) - utils:通用工具集(断言、拷贝、枚举、Excel、分页转换、Servlet、树形结构)
**更新** crm-dict 模块结构:
- controller:字典分组和字典项的管理接口
- service:字典查询、引用计数、分组和字典项的业务逻辑
- domain:字典实体、DTO、参数定义,采用独立VO设计模式
- config:内置数据初始化、权限种子化配置
- constant:字典模块常量定义
```mermaid ```mermaid
graph TB graph TB
subgraph "领域模型" subgraph "基础框架 (crm-base)"
A["BaseEntity / OwnedEntity"] A["BaseEntity / OwnedEntity"]
B["BaseDTO / BaseParam"] B["BaseDTO / BaseParam"]
C["Result / PageResult / ResultCodeEnum"] C["Result / PageResult / ResultCodeEnum"]
D["StatusEnum / HasValueEnum"] D["StatusEnum / HasValueEnum"]
E["MybatisPlusConfig / CrmSqlInjector"]
F["RedisConfig / JacksonConfig"]
G["GlobalExceptionHandlerAdvice"]
H["DataScope / SecurityUtils"]
end end
subgraph "数据访问" subgraph "数据字典 (crm-dict)"
E["CrmBaseMapper"] I["DictGroup / DictItem"]
F["IBaseService / BaseServiceImpl"] J["DictGroupVO / DictItemVO"]
G["MybatisPlusConfig / CrmSqlInjector / MetaObjectFillHandler"] K["DictGroupController / DictItemController"]
H["CustomIdGenerator / SnowflakeIdWorker"] L["IDictGroupService / IDictItemService"]
end M["DictDataInitializer / DictPermissionInitializer"]
subgraph "运行时配置" N["DictConstants"]
I["RedisConfig"]
J["JacksonConfig"]
K["Knife4jConfig"]
L["CorsConfig"]
M["InsertBatchOnDuplicateKeyUpdate"]
end end
subgraph "横切关注点" A --> L
N["GlobalExceptionHandlerAdvice"] B --> L
O["TraceIdFilter"] C --> K
P["DataScope / DataScopeHelper / DataVisibilityContext"] E --> L
Q["SecurityUtils / LoginUser"] F --> M
end G --> K
A --> F H --> K
B --> F I --> J
C --> F J --> K
E --> F L --> E
G --> E M --> I
H --> G N --> L
I --> F
J --> F
K --> F
L --> F
M --> G
N --> F
O --> F
P --> F
Q --> P
``` ```
图表来源 **图表来源**
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java)
- [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java)
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
- [JacksonConfig.java](file://crm-base/src/main/java/com/crm/base/config/JacksonConfig.java)
- [Knife4jConfig.java](file://crm-base/src/main/java/com/crm/base/config/Knife4jConfig.java)
- [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java)
- [InsertBatchOnDuplicateKeyUpdate.java](file://crm-base/src/main/java/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.java)
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [TraceIdFilter.java](file://crm-base/src/main/java/com/crm/base/filter/TraceIdFilter.java)
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
章节来源
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java)
- [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
- [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java)
- [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java)
- [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java)
**章节来源**
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
@ -175,7 +187,15 @@ Q --> P
- 工具类 - 工具类
- AssertUtils、BeanCopyUtils、EnumUtils、ExcelUtil、PageConverter、ServletUtils、TreeUtils。 - AssertUtils、BeanCopyUtils、EnumUtils、ExcelUtil、PageConverter、ServletUtils、TreeUtils。
章节来源 **更新** 数据字典核心组件:
- 字典实体:DictGroup(分组)、DictItem(字典项)、DictGroupDefault(默认项)、DictRefCount(引用计数)
- **VO设计模式**:DictGroupVO和DictItemVO采用独立字段定义,不继承实体类,提供更清晰的API契约
- 控制器:DictGroupController、DictItemController 提供 RESTful API
- 服务层:IDictGroupService、IDictItemService 定义业务接口
- 初始化器:DictDataInitializer(内置数据)、DictPermissionInitializer(权限种子)
- 常量定义:DictConstants 包含状态码、权限码、缓存配置等
**章节来源**
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java)
- [BaseDTO.java](file://crm-base/src/main/java/com/crm/base/domain/dto/BaseDTO.java) - [BaseDTO.java](file://crm-base/src/main/java/com/crm/base/domain/dto/BaseDTO.java)
@ -209,14 +229,37 @@ Q --> P
- [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java)
- [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java) - [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java)
- [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java) - [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java)
- [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java)
- [DictGroupDefault.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroupDefault.java)
- [DictRefCount.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictRefCount.java)
- [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
- [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java)
- [DictItemController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictItemController.java)
- [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java)
- [IDictItemService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictItemService.java)
- [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
- [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java)
- [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java)
- [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java)
- [DictConstants.java](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java)
## 架构总览 ## 架构总览
基础框架围绕“实体-服务-Mapper”三层展开,辅以配置中心与横切能力: 基础框架围绕"实体-服务-Mapper"三层展开,辅以配置中心与横切能力:
- 实体层:BaseEntity/OwnedEntity 提供统一字段与审计;OwnedEntity 承载数据归属。 - 实体层:BaseEntity/OwnedEntity 提供统一字段与审计;OwnedEntity 承载数据归属。
- 服务层:IBaseService/BaseServiceImpl 提供 CRUD、分页、批量操作与事务边界。 - 服务层:IBaseService/BaseServiceImpl 提供 CRUD、分页、批量操作与事务边界。
- 数据层:CrmBaseMapper 扩展通用 SQL;MyBatis Plus 插件负责分页、填充、ID 生成。 - 数据层:CrmBaseMapper 扩展通用 SQL;MyBatis Plus 插件负责分页、填充、ID 生成。
- 横切:全局异常、数据权限、请求追踪、序列化、缓存、API 文档、跨域。 - 横切:全局异常、数据权限、请求追踪、序列化、缓存、API 文档、跨域。
**更新** 新增 crm-dict 模块架构:
- 独立服务模块:基于 crm-base 构建,不依赖 crm-auth 具体实现
- 两级字典结构:分组 → 字典项,支持内置和用户字典分离
- **VO设计模式**:采用独立的视图对象(DictGroupVO、DictItemVO)替代实体继承,提升API安全性和清晰度
- 引用计数机制:跟踪字典项使用情况,防止误删
- 权限集成:通过权限码契约与 crm-auth 解耦集成
- 本地缓存:使用 Caffeine 提供高性能字典查询缓存
```mermaid ```mermaid
classDiagram classDiagram
class BaseEntity { class BaseEntity {
@ -229,25 +272,58 @@ class OwnedEntity {
+ownerId +ownerId
+deptId +deptId
} }
class BaseDTO class DictGroup {
class BaseParam { +code
+pageNo +name
+pageSize +status
+orderBy +builtin
+deleteKey
} }
class Result~T~ { class DictItem {
+groupId
+code +code
+message +name
+data +value
+status
+builtin
+deleteKey
} }
class PageResult~T~ { class DictGroupVO {
+records +id
+total +name
+pages +code
+current +sortNo
+size +status
+description
+builtin
+createTime
+itemCount
}
class DictItemVO {
+id
+groupId
+name
+code
+value
+sortNo
+status
+description
+builtin
+createTime
+groupName
+isDefault
+referenced
+effectiveSelectable
}
class DictGroupDefault {
+groupId
+itemId
}
class DictRefCount {
+groupCode
+itemCode
+refCount
} }
class CrmBaseMapper
class IBaseService~T~ { class IBaseService~T~ {
+save(entity) +save(entity)
+updateById(entity) +updateById(entity)
@ -257,58 +333,47 @@ class IBaseService~T~ {
+page(param) +page(param)
+batchSave(list) +batchSave(list)
} }
class BaseServiceImpl~T~ { class IDictGroupService {
+mapper +pageGroups(param)
+save() +saveGroup(group)
+updateById() +deleteGroup(id)
+removeById() +updateGroupStatus(id, status)
+getById() +listEnabled()
+list()
+page()
+batchSave()
} }
class MybatisPlusConfig class IDictItemService {
class MetaObjectFillHandler +pageItems(param)
class CustomIdGenerator +saveItem(item)
class SnowflakeIdWorker +deleteItem(id)
class RedisConfig +forceDeleteItem(id)
class GlobalExceptionHandlerAdvice +updateItemStatus(id, status)
class DataScopeHelper +setDefault(groupId, itemId)
class DataVisibilityContext }
class SecurityUtils class DictDataInitializer
class LoginUser class DictPermissionInitializer
OwnedEntity --|> BaseEntity OwnedEntity --|> BaseEntity
BaseServiceImpl --> CrmBaseMapper : "使用" DictGroup --> DictGroupDefault : "一对多"
BaseServiceImpl --> IBaseService : "实现" DictItem --> DictRefCount : "引用计数"
MybatisPlusConfig --> MetaObjectFillHandler : "注册" IDictGroupService --> IBaseService : "继承"
MybatisPlusConfig --> CustomIdGenerator : "注册" IDictItemService --> IBaseService : "继承"
CustomIdGenerator --> SnowflakeIdWorker : "调用" DictDataInitializer --> DictGroup : "初始化"
BaseServiceImpl --> RedisConfig : "可选缓存" DictDataInitializer --> DictItem : "初始化"
GlobalExceptionHandlerAdvice --> Result : "返回" DictPermissionInitializer --> DictGroup : "权限绑定"
DataScopeHelper --> DataVisibilityContext : "读写上下文"
SecurityUtils --> LoginUser : "获取用户"
``` ```
图表来源 **图表来源**
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java)
- [BaseDTO.java](file://crm-base/src/main/java/com/crm/base/domain/dto/BaseDTO.java) - [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [BaseParam.java](file://crm-base/src/main/java/com/crm/base/domain/param/BaseParam.java) - [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java)
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
- [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [DictGroupDefault.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroupDefault.java)
- [DictRefCount.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictRefCount.java)
- [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java)
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [IDictItemService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictItemService.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java)
- [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java)
- [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java)
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
## 详细组件分析 ## 详细组件分析
@ -332,11 +397,11 @@ class OwnedEntity {
OwnedEntity --|> BaseEntity OwnedEntity --|> BaseEntity
``` ```
图表来源 **图表来源**
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java)
章节来源 **章节来源**
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
@ -355,7 +420,7 @@ Convert --> Wrap["包装为 PageResult"]
Wrap --> Return["返回 Result.success(PageResult)"] Wrap --> Return["返回 Result.success(PageResult)"]
``` ```
图表来源 **图表来源**
- [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java)
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
- [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java)
@ -363,7 +428,7 @@ Wrap --> Return["返回 Result.success(PageResult)"]
- [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java)
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
章节来源 **章节来源**
- [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java)
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
- [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java)
@ -388,13 +453,13 @@ MP-->>S : "分页对象"
S-->>C : "PageResult" S-->>C : "PageResult"
``` ```
图表来源 **图表来源**
- [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java)
- [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java)
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
章节来源 **章节来源**
- [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java)
- [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java)
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
@ -415,7 +480,7 @@ Catch --> Map["映射为 Result.error(code,message)"]
Map --> End(["返回统一响应"]) Map --> End(["返回统一响应"])
``` ```
图表来源 **图表来源**
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java) - [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java)
- [MissingParameterException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/MissingParameterException.java) - [MissingParameterException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/MissingParameterException.java)
@ -423,7 +488,7 @@ Map --> End(["返回统一响应"])
- [ResourceNotExistException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/ResourceNotExistException.java) - [ResourceNotExistException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/ResourceNotExistException.java)
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
章节来源 **章节来源**
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java) - [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java)
- [MissingParameterException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/MissingParameterException.java) - [MissingParameterException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/MissingParameterException.java)
@ -449,14 +514,14 @@ DS-->>S : "返回过滤条件片段"
S-->>U : "返回受限数据集合" S-->>U : "返回受限数据集合"
``` ```
图表来源 **图表来源**
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java)
- [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java)
章节来源 **章节来源**
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
@ -481,7 +546,7 @@ Fill --> Audit["自动填充审计字段"]
Inject --> SQL["扩展通用 SQL"] Inject --> SQL["扩展通用 SQL"]
``` ```
图表来源 **图表来源**
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
@ -489,7 +554,7 @@ Inject --> SQL["扩展通用 SQL"]
- [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java)
- [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java) - [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java)
章节来源 **章节来源**
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
- [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
@ -510,10 +575,10 @@ RConf --> TTL["设置默认过期策略"]
App --> Use["业务模块使用 RedisTemplate"] App --> Use["业务模块使用 RedisTemplate"]
``` ```
图表来源 **图表来源**
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
章节来源 **章节来源**
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
### Jackson 与 API 文档、跨域 ### Jackson 与 API 文档、跨域
@ -521,7 +586,7 @@ App --> Use["业务模块使用 RedisTemplate"]
- Knife4jConfig:增强 Swagger 文档体验。 - Knife4jConfig:增强 Swagger 文档体验。
- CorsConfig:允许跨域访问,便于前后端分离开发。 - CorsConfig:允许跨域访问,便于前后端分离开发。
章节来源 **章节来源**
- [JacksonConfig.java](file://crm-base/src/main/java/com/crm/base/config/JacksonConfig.java) - [JacksonConfig.java](file://crm-base/src/main/java/com/crm/base/config/JacksonConfig.java)
- [Knife4jConfig.java](file://crm-base/src/main/java/com/crm/base/config/Knife4jConfig.java) - [Knife4jConfig.java](file://crm-base/src/main/java/com/crm/base/config/Knife4jConfig.java)
- [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java) - [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java)
@ -535,7 +600,7 @@ App --> Use["业务模块使用 RedisTemplate"]
- ServletUtils:HTTP 请求辅助。 - ServletUtils:HTTP 请求辅助。
- TreeUtils:树形结构构建。 - TreeUtils:树形结构构建。
章节来源 **章节来源**
- [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java) - [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java)
- [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java) - [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java)
- [EnumUtils.java](file://crm-base/src/main/java/com/crm/base/utils/EnumUtils.java) - [EnumUtils.java](file://crm-base/src/main/java/com/crm/base/utils/EnumUtils.java)
@ -544,12 +609,203 @@ App --> Use["业务模块使用 RedisTemplate"]
- [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java) - [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java)
- [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java) - [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java)
### 数据字典模块详解
#### VO设计模式重构
**更新** 数据字典模块采用了先进的VO设计模式,DictGroupVO和DictItemVO现在使用独立的字段定义而非继承实体类,显著提升了API设计的清晰度和安全性。
- **DictGroupVO**:专门用于分页列表展示的视图对象,只暴露前端需要的业务字段(id、name、code、sortNo、status、description、builtin、createTime、itemCount),排除了敏感的审计字段(creatorId/updaterId/updateTime/deleted)和软删内部字段(deleteKey)。
- **DictItemVO**:字典项视图对象,包含丰富的展示字段(groupName、isDefault、referenced、effectiveSelectable),其中referenced字段实时读取引用计数,绝不进缓存,确保数据准确性。
```mermaid
classDiagram
class BaseEntity {
+id
+createTime
+updateTime
+deleted
}
class DictGroup {
+code
+name
+status
+builtin
+deleteKey
}
class DictItem {
+groupId
+code
+name
+value
+status
+builtin
+deleteKey
}
class DictGroupVO {
+id
+name
+code
+sortNo
+status
+description
+builtin
+createTime
+itemCount
}
class DictItemVO {
+id
+groupId
+name
+code
+value
+sortNo
+status
+description
+builtin
+createTime
+groupName
+isDefault
+referenced
+effectiveSelectable
}
DictGroup --> DictGroupVO : "toDTO()"
DictItem --> DictItemVO : "toDTO()"
```
**图表来源**
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java)
- [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
#### 核心实体设计
- **DictGroup(字典分组)**:字典的第一级容器,具有全局唯一编码,创建后不可修改。支持内置标记区分平台内置和用户自定义字典。
- **DictItem(字典项)**:字典的第二级键值条目,身份由{分组ID, 编码}确定,创建后不可修改。支持字典值同组唯一约束。
- **DictGroupDefault(分组默认项)**:通过主键约束保证每组最多一个默认项,独立表存储避免污染字典项实体。
- **DictRefCount(引用计数)**:跟踪字典项被业务数据引用的次数,防止误删已使用的字典项。
```mermaid
classDiagram
class DictGroup {
+Long id
+String code
+String name
+Integer sortNo
+Integer status
+Boolean builtin
+Long deleteKey
}
class DictItem {
+Long id
+Long groupId
+String code
+String name
+String value
+Integer sortNo
+Integer status
+Boolean builtin
+Long deleteKey
}
class DictGroupDefault {
+Long groupId
+Long itemId
}
class DictRefCount {
+String groupCode
+String itemCode
+Integer refCount
}
DictGroup "1" --> "0..*" DictItem : "拥有"
DictGroup "1" --> "0..1" DictGroupDefault : "默认项"
DictItem "1" --> "0..1" DictRefCount : "引用计数"
```
**图表来源**
- [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java)
- [DictGroupDefault.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroupDefault.java)
- [DictRefCount.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictRefCount.java)
#### 控制器与服务层
- **DictGroupController**:提供分组管理的 RESTful API,包括分页查询、新建编辑、删除、启停等操作。
- **DictItemController**:提供字典项管理的 RESTful API,支持分页查询、CRUD、默认项设置、强制删除等功能。
- **IDictGroupService/IDictItemService**:定义业务接口,继承 IBaseService 获得通用 CRUD 能力。
- **DictGroupServiceImpl**:实现分组业务逻辑,包含数据验证、权限检查、事务管理等。
```mermaid
sequenceDiagram
participant Client as "客户端"
participant Controller as "DictGroupController"
participant Service as "IDictGroupService"
participant DB as "数据库"
Client->>Controller : POST /api/dict/group/saveOrUpdate
Controller->>Service : saveGroup(DictGroup)
Service->>Service : 数据验证与权限检查
Service->>DB : INSERT/UPDATE dict_group
DB-->>Service : 操作结果
Service-->>Controller : 业务结果
Controller-->>Client : Result.success()
```
**图表来源**
- [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java)
- [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java)
- [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
#### 初始化与权限集成
- **DictDataInitializer**:应用启动时执行内置字典的幂等初始化,支持 Excel 替换口,保护用户字典不被覆盖。
- **DictPermissionInitializer**:权限种子化,将 10 个 dict:* 权限点注入到权限资源树,并与管理员角色绑定。
- **DictConstants**:集中定义状态码、权限码、缓存配置、错误码等常量。
```mermaid
flowchart TD
Startup["应用启动"] --> DataInit["DictDataInitializer.run()"]
Startup --> PermInit["DictPermissionInitializer.run()"]
DataInit --> Validate["校验种子数据"]
Validate --> UpsertGroup["upsertGroup()"]
UpsertGroup --> UpsertItem["upsertItem()"]
UpsertItem --> SetDefault["setDefaultIfAbsent()"]
PermInit --> CreateMenu["创建菜单节点"]
CreateMenu --> CreateButtons["创建权限按钮"]
CreateButtons --> BindRole["绑定管理员角色"]
```
**图表来源**
- [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java)
- [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java)
- [DictConstants.java](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java)
**章节来源**
- [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java)
- [DictGroupDefault.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroupDefault.java)
- [DictRefCount.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictRefCount.java)
- [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
- [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java)
- [DictItemController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictItemController.java)
- [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java)
- [IDictItemService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictItemService.java)
- [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
- [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java)
- [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java)
- [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java)
- [DictConstants.java](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java)
## 依赖关系分析 ## 依赖关系分析
- 实体与服务:BaseEntity/OwnedEntity 被 BaseServiceImpl 广泛使用;IBaseService 定义契约。 - 实体与服务:BaseEntity/OwnedEntity 被 BaseServiceImpl 广泛使用;IBaseService 定义契约。
- 数据访问:CrmBaseMapper 被 BaseServiceImpl 依赖;MyBatis Plus 插件贯穿整个数据层。 - 数据访问:CrmBaseMapper 被 BaseServiceImpl 依赖;MyBatis Plus 插件贯穿整个数据层。
- 横切:GlobalExceptionHandlerAdvice 作用于所有 Controller;DataScopeHelper 与 DataVisibilityContext 影响查询条件。 - 横切:GlobalExceptionHandlerAdvice 作用于所有 Controller;DataScopeHelper 与 DataVisibilityContext 影响查询条件。
- 外部依赖:Redis 用于缓存;Jackson 用于序列化;Knife4j 用于文档;Cors 用于跨域。 - 外部依赖:Redis 用于缓存;Jackson 用于序列化;Knife4j 用于文档;Cors 用于跨域。
**更新** 新增 crm-dict 模块依赖关系:
- crm-dict 仅依赖 crm-base,不直接依赖 crm-auth,通过权限码契约解耦
- 使用 Caffeine 本地缓存提升字典查询性能
- 通过 CommandLineRunner 实现启动时初始化
- 与 crm-auth 通过权限资源树间接集成
- **VO设计模式**:通过独立的视图对象减少了实体与API的直接耦合
```mermaid ```mermaid
graph LR graph LR
Entity["BaseEntity/OwnedEntity"] --> Service["IBaseService/BaseServiceImpl"] Entity["BaseEntity/OwnedEntity"] --> Service["IBaseService/BaseServiceImpl"]
@ -561,9 +817,15 @@ Service --> Cache["RedisConfig"]
Controller["业务Controller"] --> Service Controller["业务Controller"] --> Service
Controller --> Exception["GlobalExceptionHandlerAdvice"] Controller --> Exception["GlobalExceptionHandlerAdvice"]
Service --> Scope["DataScopeHelper/DataVisibilityContext"] Service --> Scope["DataScopeHelper/DataVisibilityContext"]
DictModule["crm-dict 模块"] --> BaseModule["crm-base 模块"]
DictModule --> Caffeine["Caffeine 缓存"]
DictModule --> AuthContract["权限码契约"]
AuthContract --> AuthModule["crm-auth 模块"]
DictModule --> VOPattern["VO设计模式"]
VOPattern --> APIClear["清晰的API契约"]
``` ```
图表来源 **图表来源**
- [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java)
- [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java)
- [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java)
@ -577,12 +839,14 @@ Service --> Scope["DataScopeHelper/DataVisibilityContext"]
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java)
- [pom.xml](file://crm-dict/pom.xml)
章节来源 **章节来源**
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [pom.xml](file://crm-dict/pom.xml)
## 性能考量 ## 性能考量
- 分页查询:优先使用 MyBatis Plus 分页插件,避免全表扫描;合理设计索引。 - 分页查询:优先使用 MyBatis Plus 分页插件,避免全表扫描;合理设计索引。
@ -591,6 +855,14 @@ Service --> Scope["DataScopeHelper/DataVisibilityContext"]
- 序列化:Jackson 配置统一时区与空值策略,减少序列化开销。 - 序列化:Jackson 配置统一时区与空值策略,减少序列化开销。
- 审计填充:MetaObjectFillHandler 仅在必要时填充,避免多余数据库写操作。 - 审计填充:MetaObjectFillHandler 仅在必要时填充,避免多余数据库写操作。
**更新** 数据字典性能优化:
- 使用 Caffeine 本地缓存提供 10s TTL 的字典查询缓存
- 空结果缓存 2s 防穿透,避免缓存击穿
- 引用计数表不缓存,保证数据一致性
- 聚合查询优化:分组分页时一次性查询字典项数量
- 默认排序优化:sort_no IS NULL, sort_no ASC, create_time ASC
- **VO设计优化**:通过独立的VO对象减少数据传输量,提升网络传输效率
[本节为通用指导,不直接分析具体文件] [本节为通用指导,不直接分析具体文件]
## 故障排查指南 ## 故障排查指南
@ -601,7 +873,15 @@ Service --> Scope["DataScopeHelper/DataVisibilityContext"]
- 缓存问题:检查 Redis 连接与序列化配置,确认 key 命名规范与过期策略。 - 缓存问题:检查 Redis 连接与序列化配置,确认 key 命名规范与过期策略。
- 跨域与文档:验证 CorsConfig 与 Knife4jConfig 配置是否符合前端需求。 - 跨域与文档:验证 CorsConfig 与 Knife4jConfig 配置是否符合前端需求。
章节来源 **更新** 数据字典故障排查:
- 初始化失败:检查 DictDataInitializer 的种子数据合法性,确认 fail-fast 机制
- 权限问题:验证 DictPermissionInitializer 是否正确创建菜单和权限点
- 缓存不一致:检查 Caffeine 缓存配置,确认 TTL 设置合理
- 引用计数异常:监控 DictRefCount 表的计数准确性,必要时使用强制删除功能
- 内置字典保护:确认 builtin=true 的字典项无法被删除或修改关键字段
- **VO设计问题**:检查DictGroupVO和DictItemVO的字段映射是否正确,确保toDTO方法正常工作
**章节来源**
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
@ -609,10 +889,14 @@ Service --> Scope["DataScopeHelper/DataVisibilityContext"]
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
- [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java) - [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java)
- [Knife4jConfig.java](file://crm-base/src/main/java/com/crm/base/config/Knife4jConfig.java) - [Knife4jConfig.java](file://crm-base/src/main/java/com/crm/base/config/Knife4jConfig.java)
- [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java)
- [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java)
## 结论 ## 结论
crm-base 提供了完善的基础设施能力,涵盖实体设计、CRUD 封装、分页与结果统一、全局异常、数据权限、MyBatis Plus 扩展、Redis 缓存、雪花 ID 生成等。遵循本模块约定,可显著提升业务模块的开发效率与一致性。 crm-base 提供了完善的基础设施能力,涵盖实体设计、CRUD 封装、分页与结果统一、全局异常、数据权限、MyBatis Plus 扩展、Redis 缓存、雪花 ID 生成等。遵循本模块约定,可显著提升业务模块的开发效率与一致性。
**更新** 新增 crm-dict 数据字典模块作为独立的基础设施服务,提供平台级的键值字典管理能力。该模块通过先进的VO设计模式重构,实现了更清晰的API契约和更高的安全性,同时通过解耦设计与权限码契约,实现了与认证模块的松耦合集成。VO设计模式的采用使得数据展示更加灵活可控,有效避免了敏感信息的泄露风险。
[本节为总结性内容,不直接分析具体文件] [本节为总结性内容,不直接分析具体文件]
## 附录 ## 附录
@ -633,6 +917,14 @@ crm-base 提供了完善的基础设施能力,涵盖实体设计、CRUD 封装
- 工具类 - 工具类
- 使用 AssertUtils 做前置校验;使用 BeanCopyUtils 进行对象转换;使用 PageConverter 转换分页对象。 - 使用 AssertUtils 做前置校验;使用 BeanCopyUtils 进行对象转换;使用 PageConverter 转换分页对象。
**更新** 数据字典最佳实践:
- 字典设计:优先使用内置字典,用户字典用于个性化需求
- 编码规范:字典编码使用有意义的英文标识,避免使用数字 ID
- 引用管理:业务代码中正确使用引用计数增减,避免内存泄漏
- 缓存策略:利用 Caffeine 本地缓存提升查询性能,注意缓存失效时机
- 权限控制:通过权限码进行细粒度控制,避免硬编码权限判断
- **VO设计模式**:采用独立的视图对象定义API契约,避免直接暴露实体字段,提升安全性和灵活性
[本节为通用指导,不直接分析具体文件] [本节为通用指导,不直接分析具体文件]
### 扩展开发指南 ### 扩展开发指南
@ -647,4 +939,12 @@ crm-base 提供了完善的基础设施能力,涵盖实体设计、CRUD 封装
- 新增全局异常类型 - 新增全局异常类型
- 定义新的异常类,并在 GlobalExceptionHandlerAdvice 中添加对应的处理分支。 - 定义新的异常类,并在 GlobalExceptionHandlerAdvice 中添加对应的处理分支。
**更新** 数据字典扩展指南:
- 新增字典分组:通过 DictGroupController 的 saveOrUpdate 接口创建新分组
- 新增字典项:使用 DictItemController 的 saveOrUpdate 接口添加字典项
- 扩展内置数据:修改 DictDataInitializer 中的 SEED_GROUPS 列表
- 新增权限点:在 DictPermissionInitializer 中添加新的权限点种子
- 自定义缓存策略:扩展 DictConstants 中的缓存配置参数
- **VO扩展**:如需新增展示字段,应在DictGroupVO和DictItemVO中定义独立字段,而非修改实体类
[本节为通用指导,不直接分析具体文件] [本节为通用指导,不直接分析具体文件]

266
.qoder/repowiki/zh/content/项目概览/模块说明/模块说明.md

@ -98,8 +98,31 @@
- [MultipartInitDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/MultipartInitDTO.java) - [MultipartInitDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/MultipartInitDTO.java)
- [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java) - [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java)
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java) - [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
- [DictApplication.java](file://crm-dict/src/main/java/com/crm/dict/DictApplication.java)
- [pom.xml](file://crm-dict/pom.xml)
- [CONTEXT.md](file://crm-dict/CONTEXT.md)
- [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java)
- [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
- [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java)
- [IDictItemService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictItemService.java)
- [DictQueryService.java](file://crm-dict/src/main/java/com/crm/dict/service/DictQueryService.java)
- [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java)
- [DictItemController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictItemController.java)
- [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java)
- [DictConstants.java](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java)
- [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
- [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java)
</cite> </cite>
## 更新摘要
**变更内容**
- 更新了数据字典模块的VO设计说明,强调内部实体模型与外部API契约的明确分离
- 增强了分层架构设计的描述,体现更好的领域边界划分
- 补充了VO类的设计理念和字段暴露策略
- 更新了数据字典组件分析章节,包含VO设计优化的详细说明
## 目录 ## 目录
1. [简介](#简介) 1. [简介](#简介)
2. [项目结构](#项目结构) 2. [项目结构](#项目结构)
@ -117,6 +140,7 @@
- crm-auth(认证服务):负责用户认证、权限管理、第三方登录集成。 - crm-auth(认证服务):负责用户认证、权限管理、第三方登录集成。
- crm-base(基础框架):提供通用能力,如分页、异常处理、数据权限、统一结果封装、工具类等。 - crm-base(基础框架):提供通用能力,如分页、异常处理、数据权限、统一结果封装、工具类等。
- crm-file(文件服务):提供文件上传、下载、预览及分片断点续传等能力。 - crm-file(文件服务):提供文件上传、下载、预览及分片断点续传等能力。
- crm-dict(数据字典):提供两级平铺字典管理(分组→字典项),支持缓存、引用计数和内置字典初始化。
- crm-app(应用入口):作为统一启动入口,聚合各模块并加载配置。 - crm-app(应用入口):作为统一启动入口,聚合各模块并加载配置。
文档将从模块职责、包结构、核心类与接口、依赖关系、通信方式、配置项、扩展点与自定义开发等方面进行全面说明,帮助开发者快速上手并进行深度定制。 文档将从模块职责、包结构、核心类与接口、依赖关系、通信方式、配置项、扩展点与自定义开发等方面进行全面说明,帮助开发者快速上手并进行深度定制。
@ -132,25 +156,27 @@ end
subgraph "业务模块" subgraph "业务模块"
AUTH["crm-auth<br/>认证与权限"] AUTH["crm-auth<br/>认证与权限"]
FILE["crm-file<br/>文件服务"] FILE["crm-file<br/>文件服务"]
DICT["crm-dict<br/>数据字典"]
end end
subgraph "基础模块" subgraph "基础模块"
BASE["crm-base<br/>通用能力"] BASE["crm-base<br/>通用能力"]
end end
APP --> AUTH APP --> AUTH
APP --> FILE APP --> FILE
APP --> DICT
AUTH --> BASE AUTH --> BASE
FILE --> BASE FILE --> BASE
DICT --> BASE
``` ```
图表来源 **图表来源**
- [pom.xml](file://pom.xml) - [pom.xml:21-28](file://pom.xml#L21-L28)
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [application.yml](file://crm-app/src/main/resources/application.yml) - [DictApplication.java](file://crm-dict/src/main/java/com/crm/dict/DictApplication.java)
- [application.yml](file://crm-auth/src/main/resources/application.yml)
章节来源 **章节来源**
- [pom.xml](file://pom.xml) - [pom.xml:21-28](file://pom.xml#L21-L28)
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
@ -167,33 +193,43 @@ FILE --> BASE
- crm-file(文件服务) - crm-file(文件服务)
- 职责:文件上传(含分片)、下载、预览(对接kkFileView)、元信息持久化、定时清理孤儿分片。 - 职责:文件上传(含分片)、下载、预览(对接kkFileView)、元信息持久化、定时清理孤儿分片。
- 关键包:api、config、constant、controller、domain、mapper、service、task。 - 关键包:api、config、constant、controller、domain、mapper、service、task。
- crm-dict(数据字典)
- 职责:两级平铺字典管理(分组→字典项)、内置字典幂等初始化、本地缓存、引用计数、权限控制。
- 关键包:config、constant、controller、domain、mapper、service。
- 核心特性:Caffeine本地缓存(10s TTL)、软删除复用键、内置字典保护、引用计数机制。
- **VO设计优化**:明确区分内部实体模型(Entity)和外部API契约(VO),提供更好的分层架构设计。
- crm-app(应用入口) - crm-app(应用入口)
- 职责:聚合模块、加载应用配置、启动Spring Boot应用。 - 职责:聚合模块、加载应用配置、启动Spring Boot应用。
章节来源 **章节来源**
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [DictApplication.java](file://crm-dict/src/main/java/com/crm/dict/DictApplication.java)
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
- [application.yml](file://crm-auth/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml)
## 架构总览 ## 架构总览
下图展示模块间依赖与请求流转:应用入口聚合认证与文件模块,认证模块依赖基础框架的通用能力;文件模块同样依赖基础框架 下图展示模块间依赖与请求流转:应用入口聚合认证、文件和字典模块,各业务模块依赖基础框架的通用能力
```mermaid ```mermaid
graph TB graph TB
Client["客户端"] --> App["crm-app<br/>CrmAppApplication"] Client["客户端"] --> App["crm-app<br/>CrmAppApplication"]
App --> Auth["crm-auth<br/>认证服务"] App --> Auth["crm-auth<br/>认证服务"]
App --> File["crm-file<br/>文件服务"] App --> File["crm-file<br/>文件服务"]
App --> Dict["crm-dict<br/>数据字典"]
Auth --> Base["crm-base<br/>基础框架"] Auth --> Base["crm-base<br/>基础框架"]
File --> Base File --> Base
Dict --> Base
Auth --> DB["数据库"] Auth --> DB["数据库"]
File --> MinIO["对象存储"] File --> MinIO["对象存储"]
File --> KK["kkFileView<br/>预览服务"] File --> KK["kkFileView<br/>预览服务"]
Dict --> Cache["Caffeine<br/>本地缓存"]
``` ```
图表来源 **图表来源**
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [DictApplication.java](file://crm-dict/src/main/java/com/crm/dict/DictApplication.java)
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
- [application.yml](file://crm-auth/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml)
@ -229,7 +265,7 @@ C->>DS : "触发数据权限拦截"
DS-->>C : "根据数据范围过滤查询" DS-->>C : "根据数据范围过滤查询"
``` ```
图表来源 **图表来源**
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java) - [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
- [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java)
@ -254,7 +290,7 @@ ThirdPartyAuthClient <|-- DingTalkAuthClient
ThirdPartyAuthClientFactory --> ThirdPartyAuthClient : "创建/获取" ThirdPartyAuthClientFactory --> ThirdPartyAuthClient : "创建/获取"
``` ```
图表来源 **图表来源**
- [ThirdPartyAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClient.java) - [ThirdPartyAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClient.java)
- [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java) - [DingTalkAuthClient.java](file://crm-auth/src/main/java/com/crm/auth/service/client/DingTalkAuthClient.java)
- [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java) - [ThirdPartyAuthClientFactory.java](file://crm-auth/src/main/java/com/crm/auth/service/client/ThirdPartyAuthClientFactory.java)
@ -272,7 +308,7 @@ Inject --> Proceed
Proceed --> End(["返回结果"]) Proceed --> End(["返回结果"])
``` ```
图表来源 **图表来源**
- [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java)
- [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)
- [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java)
@ -303,14 +339,14 @@ AuthUser --> SysDept : "多对多"
AuthUser --> AuthIdentity : "一对多" AuthUser --> AuthIdentity : "一对多"
``` ```
图表来源 **图表来源**
- [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java) - [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java)
- [SysRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java) - [SysRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java)
- [SysMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java) - [SysMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java)
- [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java) - [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java)
- [AuthIdentity.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthIdentity.java) - [AuthIdentity.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthIdentity.java)
章节来源 **章节来源**
- [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java)
- [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java) - [SystemController.java](file://crm-auth/src/main/java/com/crm/auth/controller/SystemController.java)
- [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java) - [IAuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java)
@ -400,7 +436,7 @@ DataScopeHelper --> DataVisibilityContext : "使用"
SecurityUtils --> LoginUser : "获取上下文" SecurityUtils --> LoginUser : "获取上下文"
``` ```
图表来源 **图表来源**
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java)
- [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java)
@ -414,7 +450,7 @@ SecurityUtils --> LoginUser : "获取上下文"
- [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java)
- [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java)
章节来源 **章节来源**
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java)
- [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java)
@ -490,7 +526,7 @@ C->>KK : "请求预览链接"
KK-->>C : "返回预览地址" KK-->>C : "返回预览地址"
``` ```
图表来源 **图表来源**
- [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java)
- [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java) - [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java)
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
@ -501,7 +537,7 @@ KK-->>C : "返回预览地址"
- [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java) - [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java)
- [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java)
章节来源 **章节来源**
- [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java)
- [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java) - [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java)
- [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java)
@ -520,47 +556,191 @@ KK-->>C : "返回预览地址"
- [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java) - [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java)
- [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java) - [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java)
### 数据字典(crm-dict)
- 包结构与职责
- config:内置字典初始化、权限初始化。
- constant:常量定义、权限码、错误码。
- controller:分组和字典项的管理接口。
- domain:实体(分组、字典项、默认项、引用计数)、DTO、参数。
- mapper:数据访问映射。
- service:分组服务、字典项服务、查询服务、引用服务。
- 核心特性
- 两级平铺结构:分组(第一级)→ 字典项(第二级)
- 内置字典保护:builtin=true的字典不可删除,支持幂等初始化
- 引用计数机制:跟踪字典项被业务数据引用的次数
- 本地缓存:Caffeine缓存,10秒TTL,空结果2秒防穿透
- 软删除复用键:delete_key=id,支持编码复用
- **VO设计优化**:明确区分内部实体模型和外部API契约,体现更好的分层架构设计
- **DictGroupVO**:分页列表展示专用视图对象,仅暴露前端需要的业务字段 + createTime,排除审计字段和软删内部字段
- **DictItemVO**:分页列表展示专用视图对象,包含实时引用计数(referenced)和有效可选标记(effectiveSelectable)
- **设计原则**:VO独立字段(不继承实体),只暴露必要的业务字段,避免泄露内部实现细节
- 数据模型关系
```mermaid
classDiagram
class DictGroup {
+ "分组名称"
+ "分组编码(全局唯一)"
+ "状态"
+ "排序号"
+ "内置标记"
+ "描述"
}
class DictItem {
+ "所属分组ID"
+ "字典名称"
+ "字典编码(组内唯一)"
+ "字典值(同组唯一)"
+ "状态"
+ "排序号"
+ "内置标记"
+ "描述"
}
class DictGroupDefault {
+ "分组ID"
+ "字典项ID"
}
class DictRefCount {
+ "分组编码"
+ "字典编码"
+ "引用计数"
}
class DictGroupVO {
+ "分组业务字段"
+ "createTime"
+ "itemCount"
}
class DictItemVO {
+ "字典项业务字段"
+ "groupName"
+ "isDefault"
+ "referenced"
+ "effectiveSelectable"
}
DictGroup --> DictItem : "一对多"
DictGroup --> DictGroupDefault : "一对一"
DictItem --> DictGroupDefault : "一对一"
DictItem --> DictRefCount : "一对一"
DictGroup --> DictGroupVO : "转换"
DictItem --> DictItemVO : "转换"
```
**图表来源**
- [DictGroup.java:17-51](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java#L17-L51)
- [DictItem.java:17-61](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java#L17-L61)
- [DictGroupVO.java:14-34](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java#L14-L34)
- [DictItemVO.java:16-49](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java#L16-L49)
- 内置字典初始化流程
```mermaid
sequenceDiagram
participant INIT as "DictDataInitializer"
participant GROUP as "DictGroupMapper"
participant ITEM as "DictItemMapper"
participant DEFAULT as "DictGroupDefaultMapper"
INIT->>INIT : "验证种子数据合法性"
loop "遍历种子分组"
INIT->>GROUP : "upsert分组(仅内置)"
GROUP-->>INIT : "返回或创建分组"
loop "遍历分组下的字典项"
INIT->>ITEM : "upsert字典项(仅内置)"
ITEM-->>INIT : "返回或创建字典项"
INIT->>DEFAULT : "设置默认项(仅当无默认时)"
DEFAULT-->>INIT : "完成默认设置"
end
end
INIT-->>INIT : "初始化完成"
```
**图表来源**
- [DictDataInitializer.java:70-94](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java#L70-L94)
- [DictDataInitializer.java:141-236](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java#L141-L236)
- 字典查询缓存机制
```mermaid
flowchart TD
A["查询请求"] --> B{"缓存命中?"}
B --> |是| C["返回缓存数据"]
B --> |否| D["查询数据库"]
D --> E{"有结果?"}
E --> |是| F["写入缓存(10s TTL)"]
F --> G["返回数据"]
E --> |否| H["写入空缓存(2s TTL)"]
H --> I["返回null"]
```
**图表来源**
- [DictQueryService.java:7-31](file://crm-dict/src/main/java/com/crm/dict/service/DictQueryService.java#L7-L31)
- [DictConstants.java:24-30](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java#L24-L30)
**章节来源**
- [DictApplication.java](file://crm-dict/src/main/java/com/crm/dict/DictApplication.java)
- [pom.xml](file://crm-dict/pom.xml)
- [CONTEXT.md](file://crm-dict/CONTEXT.md)
- [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java)
- [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java)
- [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
- [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java)
- [IDictItemService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictItemService.java)
- [DictQueryService.java](file://crm-dict/src/main/java/com/crm/dict/service/DictQueryService.java)
- [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java)
- [DictItemController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictItemController.java)
- [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java)
- [DictConstants.java](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java)
- [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java)
- [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java)
### 应用入口(crm-app) ### 应用入口(crm-app)
- 职责:聚合模块、加载配置文件、启动Spring Boot应用。 - 职责:聚合模块、加载配置文件、启动Spring Boot应用。
- 关键点:确保扫描到各模块的包路径,正确引入依赖。 - 关键点:确保扫描到各模块的包路径,正确引入依赖。
章节来源 **章节来源**
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
## 依赖关系分析 ## 依赖关系分析
- 模块依赖 - 模块依赖
- crm-app 依赖 crm-auth、crm-file。 - crm-app 依赖 crm-auth、crm-file、crm-dict。
- crm-auth、crm-file 均依赖 crm-base。 - crm-auth、crm-file、crm-dict 均依赖 crm-base。
- crm-dict 仅依赖 crm-base,不依赖 crm-auth(通过权限码字符串契约解耦)。
- 运行时依赖 - 运行时依赖
- crm-auth 依赖数据库(MyBatis-Plus)、Redis(可选用于缓存)、JWT库。 - crm-auth 依赖数据库(MyBatis-Plus)、Redis(可选用于缓存)、JWT库。
- crm-file 依赖对象存储(MinIO)、外部预览服务(kkFileView)。 - crm-file 依赖对象存储(MinIO)、外部预览服务(kkFileView)。
- crm-dict 依赖数据库(MyBatis-Plus)、Caffeine本地缓存。
- 内部通信 - 内部通信
- 通过REST API暴露接口,模块间通过Spring Bean注入协作。 - 通过REST API暴露接口,模块间通过Spring Bean注入协作。
- 认证模块通过安全上下文传递登录用户信息,供其他模块读取。 - 认证模块通过安全上下文传递登录用户信息,供其他模块读取。
- 数据字典模块通过权限码字符串与认证模块解耦耦合。
```mermaid ```mermaid
graph LR graph LR
APP["crm-app"] --> AUTH["crm-auth"] APP["crm-app"] --> AUTH["crm-auth"]
APP --> FILE["crm-file"] APP --> FILE["crm-file"]
APP --> DICT["crm-dict"]
AUTH --> BASE["crm-base"] AUTH --> BASE["crm-base"]
FILE --> BASE FILE --> BASE
DICT --> BASE
AUTH --> DB["数据库"] AUTH --> DB["数据库"]
FILE --> MINIO["MinIO"] FILE --> MINIO["MinIO"]
FILE --> KK["kkFileView"] FILE --> KK["kkFileView"]
DICT --> CACHE["Caffeine缓存"]
``` ```
图表来源 **图表来源**
- [pom.xml](file://pom.xml) - [pom.xml:21-28](file://pom.xml#L21-L28)
- [pom.xml:48-74](file://pom.xml#L48-L74)
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [DictApplication.java](file://crm-dict/src/main/java/com/crm/dict/DictApplication.java)
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
- [application.yml](file://crm-auth/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml)
章节来源 **章节来源**
- [pom.xml](file://pom.xml) - [pom.xml:21-28](file://pom.xml#L21-L28)
- [pom.xml:48-74](file://pom.xml#L48-L74)
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java)
- [DictApplication.java](file://crm-dict/src/main/java/com/crm/dict/DictApplication.java)
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)
- [application.yml](file://crm-auth/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml)
@ -576,8 +756,12 @@ FILE --> KK["kkFileView"]
- 分片上传提升大文件稳定性与并发;合并后落盘MinIO,减轻本地磁盘压力。 - 分片上传提升大文件稳定性与并发;合并后落盘MinIO,减轻本地磁盘压力。
- 定时清理孤儿分片,防止存储空间泄漏。 - 定时清理孤儿分片,防止存储空间泄漏。
- 预览通过kkFileView异步或直链方式,避免阻塞主线程。 - 预览通过kkFileView异步或直链方式,避免阻塞主线程。
- 数据字典模块
[本节为通用指导,不直接分析具体文件] - Caffeine本地缓存:10秒正结果缓存 + 2秒空结果防穿透,大幅降低数据库压力。
- 软删除复用键:支持编码无限次删除重建,避免主键冲突。
- 引用计数机制:O(1)复杂度判断是否可删除,避免复杂关联查询。
- 内置字典幂等初始化:部署时快速完成种子数据导入,支持Excel替换。
- **VO设计优化**:通过独立的VO对象减少数据传输冗余,提高序列化性能,避免泄露内部实现细节。
## 故障排查指南 ## 故障排查指南
- 认证相关问题 - 认证相关问题
@ -588,12 +772,18 @@ FILE --> KK["kkFileView"]
- 上传失败:检查MinIO连接、分片大小限制、临时目录权限。 - 上传失败:检查MinIO连接、分片大小限制、临时目录权限。
- 预览失败:检查kkFileView服务可达性与配置。 - 预览失败:检查kkFileView服务可达性与配置。
- 空间占用异常:检查OrphanChunkCleanupTask是否正常运行。 - 空间占用异常:检查OrphanChunkCleanupTask是否正常运行。
- 数据字典相关问题
- 内置字典无法修改:检查builtin标记,内置字典只允许改名、改描述、调排序、启停用。
- 字典项无法删除:检查引用计数是否为0,或被引用后字典值是否被修改。
- 缓存不一致:等待10秒TTL过期,或重启服务刷新缓存。
- 初始化失败:检查种子数据合法性,查看控制台日志中的fail-fast错误信息。
- VO数据不完整:检查服务层的toDTO转换逻辑,确保必要字段已正确映射。
- 基础框架问题 - 基础框架问题
- 统一异常未捕获:检查GlobalExceptionHandlerAdvice是否生效。 - 统一异常未捕获:检查GlobalExceptionHandlerAdvice是否生效。
- 分页异常:检查PageConverter与前端分页参数一致性。 - 分页异常:检查PageConverter与前端分页参数一致性。
- 审计字段缺失:检查MetaObjectFillHandler是否启用。 - 审计字段缺失:检查MetaObjectFillHandler是否启用。
章节来源 **章节来源**
- [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java)
- [SecurityExceptionHandlers.java](file://crm-auth/src/main/java/com/crm/auth/security/SecurityExceptionHandlers.java) - [SecurityExceptionHandlers.java](file://crm-auth/src/main/java/com/crm/auth/security/SecurityExceptionHandlers.java)
- [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java)
@ -603,11 +793,11 @@ FILE --> KK["kkFileView"]
- [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java)
- [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java)
- [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java)
- [DictDataInitializer.java:96-137](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java#L96-L137)
- [DictItemServiceImpl.java:218-238](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java#L218-L238)
## 结论 ## 结论
本CRM后端采用清晰的多模块架构,认证、文件与基础框架职责边界明确,具备良好的可扩展性与可维护性。通过统一的异常处理、分页、数据权限与工具集,开发者可以快速构建业务功能。建议在新增第三方登录或文件存储时,遵循现有扩展点与配置约定,保持模块内聚与低耦合。 本CRM后端采用清晰的多模块架构,认证、文件、数据字典与基础框架职责边界明确,具备良好的可扩展性与可维护性。通过统一的异常处理、分页、数据权限与工具集,开发者可以快速构建业务功能。新增的数据字典模块提供了稳定的键值管理能力,支持内置字典保护和引用计数机制。**特别是VO设计的优化,通过明确区分内部实体模型和外部API契约,体现了更好的分层架构设计,提高了系统的可维护性和安全性**。建议在新增第三方登录、文件存储或业务字典时,遵循现有扩展点与配置约定,保持模块内聚与低耦合。
[本节为总结,不直接分析具体文件]
## 附录:配置与扩展点 ## 附录:配置与扩展点
- 认证模块配置 - 认证模块配置
@ -626,11 +816,18 @@ FILE --> KK["kkFileView"]
- 调度任务:SchedulingConfig、OrphanChunkCleanupTask。 - 调度任务:SchedulingConfig、OrphanChunkCleanupTask。
- 文件属性:FileProperties。 - 文件属性:FileProperties。
- 预览服务:KkFileViewClient。 - 预览服务:KkFileViewClient。
- 数据字典模块配置
- 内置字典初始化:DictDataInitializer,支持Excel替换口。
- 权限初始化:DictPermissionInitializer,将权限点注入权限资源树。
- 缓存配置:Caffeine本地缓存,10秒TTL,空结果2秒防穿透。
- 权限码常量:DictConstants中定义的dict:*权限点。
- 扩展点:新增内置字典可通过SEED_GROUPS列表或Excel文件扩展。
- **VO设计扩展**:新增VO时应遵循独立字段原则,仅暴露必要的业务字段,避免继承实体类。
- 应用入口配置 - 应用入口配置
- 统一启动:CrmAppApplication。 - 统一启动:CrmAppApplication。
- 应用配置:application.yml。 - 应用配置:application.yml。
章节来源 **章节来源**
- [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java) - [SecurityConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/SecurityConfig.java)
- [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java) - [PermissionConfig.java](file://crm-auth/src/main/java/com/crm/auth/config/PermissionConfig.java)
- [DataInitializer.java](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java) - [DataInitializer.java](file://crm-auth/src/main/java/com/crm/auth/config/DataInitializer.java)
@ -655,5 +852,10 @@ FILE --> KK["kkFileView"]
- [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java)
- [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java)
- [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java)
- [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java)
- [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java)
- [DictConstants.java](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java)
- [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java)
- [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java)
- [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java)
- [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-app/src/main/resources/application.yml)

2
.qoder/repowiki/zh/meta/repowiki-metadata.json

File diff suppressed because one or more lines are too long

2
crm-app/target/classes/application.yml

@ -51,7 +51,7 @@ crm:
client-secret: "VVlS2GaBdibboTi3l80wvXufTaYxlCHWaLDtJKd9APT37td2II-cosFE_-WkVGIU" client-secret: "VVlS2GaBdibboTi3l80wvXufTaYxlCHWaLDtJKd9APT37td2II-cosFE_-WkVGIU"
file: file:
minio: minio:
endpoint: http://127.0.0.1:9000 # 内网地址,浏览器永不直接接触 MinIO endpoint: ${CRM_MINIO_ENDPOINT:http://127.0.0.1:9000} # 内网地址,浏览器永不直接接触 MinIO(compose 指向容器服务名 minio:9000)
access-key: ${CRM_MINIO_AK:} # 凭证走环境变量注入,不进 git access-key: ${CRM_MINIO_AK:} # 凭证走环境变量注入,不进 git
secret-key: ${CRM_MINIO_SK:} secret-key: ${CRM_MINIO_SK:}
bucket: crm bucket: crm

BIN
crm-app/target/classes/com/crm/app/CrmAppApplication.class

Binary file not shown.

1
crm-auth/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

@ -6,6 +6,7 @@ D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\config\SecurityConf
D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\config\WebMvcConfig.java D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\config\WebMvcConfig.java
D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\constant\AuthConstants.java D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\constant\AuthConstants.java
D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\controller\AuthController.java D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\controller\AuthController.java
D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\controller\DebugTokenController.java
D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\controller\ResourceController.java D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\controller\ResourceController.java
D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\controller\RoleController.java D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\controller\RoleController.java
D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\controller\SystemController.java D:\code\crm-backend-matt\crm-auth\src\main\java\com\crm\auth\controller\SystemController.java

BIN
crm-base/target/classes/com/crm/base/advice/GlobalExceptionHandlerAdvice.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/CorsConfig.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/CrmSqlInjector.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/CustomIdGenerator.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/JacksonConfig.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/Knife4jConfig.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/MetaObjectFillHandler.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/MybatisPlusConfig.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/RedisConfig.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/ScheduledTaskProperties.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/SnowflakeIdWorker.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/config/SnowflakeProperties.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/constant/CommonConstants.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/dto/BaseDTO.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/entity/BaseEntity.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/entity/OwnedEntity.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/enums/HasValueEnum.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/enums/StatusEnum.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/exception/BusinessErrorException.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/exception/MissingParameterException.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/exception/PermissionErrorException.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/exception/ResourceNotExistException.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/param/BaseParam.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/result/PageResult.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/result/Result.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/domain/result/ResultCodeEnum.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/filter/TraceIdFilter.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/mapper/CrmBaseMapper.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/security/DataOwnership.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/security/DataScopeHelper.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/security/DataScopeLevel.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/security/DataVisibility.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/security/DataVisibilityContext.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/security/SecurityUtils.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/security/VisibilityScope$Kind.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/security/VisibilityScope.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/service/IBaseService.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/service/impl/BaseServiceImpl.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/utils/AssertUtils.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/utils/BeanCopyUtils.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/utils/EnumUtils.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/utils/ExcelUtil.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/utils/PageConverter.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/utils/ServletUtils.class

Binary file not shown.

BIN
crm-base/target/classes/com/crm/base/utils/TreeUtils.class

Binary file not shown.

30
crm-base/target/surefire-reports/TEST-com.crm.base.security.DataVisibilityTest.xml

File diff suppressed because one or more lines are too long

2
crm-base/target/surefire-reports/com.crm.base.security.DataVisibilityTest.txt

@ -1,4 +1,4 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Test set: com.crm.base.security.DataVisibilityTest Test set: com.crm.base.security.DataVisibilityTest
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Tests run: 17, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.162 s -- in com.crm.base.security.DataVisibilityTest Tests run: 17, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.099 s -- in com.crm.base.security.DataVisibilityTest

BIN
crm-base/target/test-classes/com/crm/base/security/DataVisibilityTest.class

Binary file not shown.

72
mcp_call.py

@ -0,0 +1,72 @@
import sys, json, urllib.request
URL = "http://127.0.0.1:8000/mcp"
HEADERS = {
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream",
}
def post(body, session=None, timeout=1200):
h = dict(HEADERS)
if session:
h["mcp-session-id"] = session
data = json.dumps(body).encode()
req = urllib.request.Request(URL, data=data, headers=h, method="POST")
resp = urllib.request.urlopen(req, timeout=timeout)
sid = resp.headers.get("mcp-session-id", session)
# read SSE stream
result = None
for raw in resp:
line = raw.decode("utf-8", "replace").strip()
if not line or line.startswith(":"):
continue
if line.startswith("data:"):
payload = line[5:].strip()
try:
d = json.loads(payload)
except Exception:
continue
if isinstance(d, dict) and ("result" in d or "error" in d):
result = d
break
return sid, result
def main():
tool = sys.argv[1]
args = json.loads(sys.argv[2])
outfile = sys.argv[3] if len(sys.argv) > 3 else None
# init
sid, _ = post({"jsonrpc":"2.0","id":1,"method":"initialize",
"params":{"protocolVersion":"2024-11-05","capabilities":{},
"clientInfo":{"name":"pi","version":"1.0"}}}, timeout=30)
# initialized notification (no response expected)
try:
h = dict(HEADERS); h["mcp-session-id"] = sid
req = urllib.request.Request(URL,
data=json.dumps({"jsonrpc":"2.0","method":"notifications/initialized"}).encode(),
headers=h, method="POST")
urllib.request.urlopen(req, timeout=15).read()
except Exception:
pass
# call tool
_, res = post({"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":tool,"arguments":args}}, session=sid, timeout=1800)
if res is None:
print("NO_RESULT")
return
if "error" in res:
print("ERROR:", json.dumps(res["error"], ensure_ascii=False))
return
texts = []
for c in res["result"].get("content", []):
if c.get("type") == "text":
texts.append(c["text"])
output = "\n\n".join(texts)
if outfile:
open(outfile, "w", encoding="utf-8").write(output)
print("WROTE", len(output), "chars to", outfile)
else:
print(output)
main()
Loading…
Cancel
Save