现在我已经收集了足够的信息来更新数据模型文档。基于分析,FileInfo实体确实新增了thumbnail_status和thumbnail_retry_count两个字段,用于跟踪缩略图生成状态和重试次数。让我更新文档: # 数据模型 **本文引用的文件** - [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) - [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) - [SysUserRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserRole.java) - [SysRoleMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRoleMenu.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) - [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) - [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) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java) - [IdentityTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/IdentityTypeEnum.java) - [MenuTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuTypeEnum.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) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.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) - [InsertBatchOnDuplicateKeyUpdate.java](file://crm-base/src/main/java/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.java) - [SysRoleServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java) - [RoleController.java](file://crm-auth/src/main/java/com/crm/auth/controller/RoleController.java) - [AuthConstants.java](file://crm-auth/src/main/java/com/crm/auth/constant/AuthConstants.java) - [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml) ## 更新摘要 **变更内容** - FileInfo实体新增缩略图状态跟踪机制,包含thumbnail_status和thumbnail_retry_count两个新字段 - 实现完整的缩略图生命周期管理,支持PENDING、READY、FAILED、UNSUPPORTED四种状态 - 添加缩略图生成失败重试机制,支持配置化重试次数限制 - 新增缩略图异步生成任务和定时重试任务 - 完善文件元数据结构,增强文件预览和缩略图功能 ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件为 CRM 后端的数据模型文档,面向数据库管理员与后端开发者。内容覆盖用户、角色、菜单、部门、身份认证、文件等核心实体的字段定义、数据类型、约束与业务含义;提供实体关系图(ER)与类图;说明主键策略、外键关联、索引设计、数据完整性约束;给出数据字典、枚举值定义、默认值设置;并补充数据迁移策略、版本兼容性与备份恢复方案。 **更新** 本次更新重点反映了文件模块的缩略图功能增强,包括FileInfo实体的新字段、缩略图状态机、重试机制和异步处理流程。 ## 项目结构 本项目采用多模块架构: - crm-base:基础能力(通用实体、配置、工具、异常、分页、结果封装等) - crm-auth:认证授权与系统管理(用户、角色、菜单、部门、权限、数据范围等) - crm-file:文件服务(上传、分片、预览、清理任务、缩略图等) - crm-app:应用启动入口与全局配置 ```mermaid graph TB subgraph "基础层" base["crm-base
通用实体/配置/工具"] end subgraph "认证授权" auth["crm-auth
用户/角色/菜单/部门/权限"] end subgraph "文件服务" file["crm-file
文件元数据/分片/预览/缩略图"] end subgraph "应用" app["crm-app
启动与配置"] end app --> auth app --> file auth --> base file --> base ``` **图表来源** - [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-auth/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) ## 核心组件 - 通用基类 - BaseEntity:统一审计字段(如创建时间、更新时间等),配合自动填充处理器实现默认值与审计信息注入 - OwnedEntity:扩展数据所有权字段(如创建人、所属组织等),用于数据可见性控制 - 主键生成器 - SnowflakeIdWorker:雪花算法分布式ID生成 - CustomIdGenerator:MyBatis-Plus 自定义ID生成器,将雪花ID注入到实体主键 - 自动填充与SQL注入 - MetaObjectFillHandler:MyBatis-Plus 自动填充处理器,统一处理审计字段与默认值 - CrmSqlInjector:MyBatis-Plus SQL 注入器,启用逻辑删除、乐观锁等增强功能 - InsertBatchOnDuplicateKeyUpdate:批量插入去重更新支持 **章节来源** - [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) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.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) - [InsertBatchOnDuplicateKeyUpdate.java](file://crm-base/src/main/java/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.java) ## 架构总览 下图展示核心实体之间的关系与职责边界,包括用户、角色、菜单、部门、身份与文件的关联。 ```mermaid erDiagram AUTH_USER { bigint id PK string username UK string nickname string email string phone int status bigint create_by bigint update_by datetime create_time datetime update_time } SYS_ROLE { bigint id PK string role_code UK string role_name int data_scope int sort boolean builtin int status bigint create_by bigint update_by datetime create_time datetime update_time } SYS_MENU { bigint id PK string menu_code UK string menu_name int type string path string component int sort int status bigint parent_id bigint create_by bigint update_by datetime create_time datetime update_time } SYS_DEPT { bigint id PK string dept_code UK string dept_name int sort int status bigint parent_id bigint create_by bigint update_by datetime create_time datetime update_time } AUTH_IDENTITY { bigint id PK string identity_type string identity_value bigint user_id FK string provider string open_id string union_id int status bigint create_by bigint update_by datetime create_time datetime update_time } FILE_INFO { bigint id PK string original_name string object_key long file_size string content_type string biz_domain string file_hash string thumbnail_status int thumbnail_retry_count bigint create_by bigint update_by datetime create_time datetime update_time } SYS_USER_ROLE { bigint id PK bigint user_id FK bigint role_id FK unique uk_user_role } SYS_ROLE_MENU { bigint id PK bigint role_id FK bigint menu_id FK unique uk_role_menu } SYS_USER_DEPT { bigint id PK bigint user_id FK bigint dept_id FK unique uk_user_dept } AUTH_USER ||--o{ AUTH_IDENTITY : "拥有" AUTH_USER ||--o{ SYS_USER_ROLE : "属于" SYS_ROLE ||--o{ SYS_USER_ROLE : "分配给" SYS_ROLE ||--o{ SYS_ROLE_MENU : "包含" SYS_MENU ||--o{ SYS_ROLE_MENU : "被包含" AUTH_USER ||--o{ SYS_USER_DEPT : "归属" SYS_DEPT ||--o{ SYS_USER_DEPT : "包含" ``` **图表来源** - [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) - [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) - [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) - [SysUserRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserRole.java) - [SysRoleMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRoleMenu.java) - [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java) ## 详细组件分析 ### 用户实体(AuthUser) - 字段与类型 - 主键:id(bigint,雪花ID) - 用户名:username(varchar,唯一) - 昵称:nickname(varchar) - 邮箱:email(varchar,可选唯一) - 手机:phone(varchar,可选唯一) - 状态:status(int,参考 StatusEnum) - 审计字段:create_by、update_by、create_time、update_time(继承自 BaseEntity) - 约束与索引 - 主键:id - 唯一索引:username - 可选唯一索引:email、phone(按业务需要开启) - 业务含义 - 系统登录与鉴权的核心主体,支持第三方身份绑定(通过 AuthIdentity) - 默认值与填充 - 审计字段由 MetaObjectFillHandler 自动填充 - 主键由 CustomIdGenerator + SnowflakeIdWorker 生成 **章节来源** - [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.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) - [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) ### 角色实体(SysRole) - 字段与类型 - 主键:id(bigint,雪花ID) - 角色名称:roleName(varchar(50),非空) - 角色编码:roleCode(varchar(50),非空,唯一) - 数据范围:dataScope(tinyint,默认1,范围1-4) - 排序:sort(int,默认0) - 备注:remark(varchar(200)) - 内置标记:builtin(boolean,默认false) - 审计字段:create_by、update_by、create_time、update_time - 约束与索引 - 主键:id - 唯一索引:roleCode - 默认值:dataScope=1, sort=0, builtin=false - 业务含义 - 权限集合的载体,与菜单进行多对多关联 - 支持数据范围控制(本人、本部门、本部门及子部门、全部数据) - 内置角色保护机制,防止误删和编码修改 **章节来源** - [SysRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java) - [SysRoleServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java) ### 菜单实体(SysMenu) - 字段与类型 - 主键:id(bigint,雪花ID) - 菜单编码:menuCode(varchar,唯一) - 菜单名称:menuName(varchar) - 类型:type(int,参考 MenuTypeEnum) - 路径:path(varchar) - 组件:component(varchar) - 排序:sort(int) - 状态:status(int,参考 StatusEnum) - 父级:parentId(bigint,自引用树形结构) - 审计字段:createBy、updateBy、createTime、updateTime - 约束与索引 - 主键:id - 唯一索引:menuCode - 建议索引:parentId(树形查询优化) - 业务含义 - 前端路由与按钮权限的控制点,支持多级菜单 **章节来源** - [SysMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java) - [MenuTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuTypeEnum.java) ### 部门实体(SysDept) - 字段与类型 - 主键:id(bigint,雪花ID) - 部门编码:deptCode(varchar,唯一) - 部门名称:deptName(varchar) - 排序:sort(int) - 状态:status(int,参考 StatusEnum) - 父级:parentId(bigint,自引用树形结构) - 审计字段:createBy、updateBy、createTime、updateTime - 约束与索引 - 主键:id - 唯一索引:deptCode - 建议索引:parentId(树形查询优化) - 业务含义 - 组织架构维度,用于数据范围与资源归属 **章节来源** - [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java) ### 用户-角色-菜单-部门关联表 - SysUserRole(用户-角色) - 主键:id(bigint) - 外键:userId(AUTH_USER.id)、roleId(SYS_ROLE.id) - 唯一约束:(userId, roleId) - SysRoleMenu(角色-菜单) - 主键:id(bigint) - 外键:roleId(SYS_ROLE.id)、menuId(SYS_MENU.id) - 唯一约束:(roleId, menuId) - SysUserDept(用户-部门) - 主键:id(bigint) - 外键:userId(AUTH_USER.id)、deptId(SYS_DEPT.id) - 唯一约束:(userId, deptId) **章节来源** - [SysUserRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserRole.java) - [SysRoleMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRoleMenu.java) - [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java) ### 身份认证(AuthIdentity) - 字段与类型 - 主键:id(bigint) - 身份类型:identityType(int,参考 IdentityTypeEnum) - 身份值:identityValue(varchar,唯一或组合唯一) - 用户:userId(AUTH_USER.id) - 提供方:provider(varchar,如钉钉、企业微信等) - 开放ID:openId、unionId(varchar) - 状态:status(int,参考 StatusEnum) - 审计字段:createBy、updateBy、createTime、updateTime - 约束与索引 - 主键:id - 唯一索引:identityValue(或按 provider+openId 组合唯一) - 建议索引:userId、provider - 业务含义 - 统一第三方登录与账号绑定,支持多身份聚合到同一用户 **章节来源** - [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) ### 文件元数据(FileInfo)- **已更新** - 字段与类型 - 主键:id(bigint) - 原始文件名:originalName(varchar(255)) - 对象键:objectKey(varchar(500),唯一) - 文件大小:fileSize(bigint) - MIME类型:contentType(varchar(255)) - 业务域:bizDomain(varchar(64)) - 文件哈希:fileHash(varchar(64),秒传占位字段) - **缩略图状态:thumbnailStatus(varchar(16),默认'PENDING')** - **缩略图重试计数:thumbnailRetryCount(int,默认0)** - 审计字段:createBy、updateBy、createTime、updateTime - 约束与索引 - 主键:id - 唯一索引:objectKey - 建议索引: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) - [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 classDiagram class BaseEntity { +long createBy +long updateBy +datetime createTime +datetime updateTime } class OwnedEntity { +long ownerDeptId +long ownerUserId } class AuthUser { +long id +string username +string nickname +string email +string phone +int status } class SysRole { +long id +string roleName +string roleCode +int dataScope +int sort +boolean builtin +int status } class SysMenu { +long id +string menuCode +string menuName +int type +string path +string component +int sort +int status +long parentId } class SysDept { +long id +string deptCode +string deptName +int sort +int status +long parentId } class AuthIdentity { +long id +string identityType +string identityValue +long userId +string provider +string openId +string unionId +int status } class FileInfo { +long id +string originalName +string objectKey +long fileSize +string contentType +string bizDomain +string fileHash +string thumbnailStatus +int thumbnailRetryCount } class SysUserRole { +long id +long userId +long roleId } class SysRoleMenu { +long id +long roleId +long menuId } class SysUserDept { +long id +long userId +long deptId } BaseEntity <|-- OwnedEntity OwnedEntity <|-- AuthUser OwnedEntity <|-- SysRole OwnedEntity <|-- SysMenu OwnedEntity <|-- SysDept OwnedEntity <|-- AuthIdentity OwnedEntity <|-- FileInfo ``` **图表来源** - [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) - [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) - [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) - [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) - [SysUserRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserRole.java) - [SysRoleMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRoleMenu.java) - [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java) ## 依赖关系分析 - 主键策略 - 所有实体主键使用雪花ID,避免集中式ID冲突,提升写入性能 - CustomIdGenerator 集成 MyBatis-Plus,自动注入雪花ID - 外键与关联 - 通过中间表实现多对多(用户-角色、角色-菜单、用户-部门) - 自引用树形结构(菜单、部门)通过 parentId 维护层级 - 索引设计 - 唯一索引保证业务唯一性(用户名、角色编码、菜单编码、部门编码、对象键) - 建议为高频查询字段建立普通索引(如 status、parentId、userId、md5) - 数据完整性 - 逻辑删除由 CrmSqlInjector 启用,避免物理删除导致关联断裂 - 审计字段由 MetaObjectFillHandler 统一填充,确保一致性 - **缩略图状态管理依赖** - FileConstants定义缩略图状态常量(PENDING、READY、FAILED、UNSUPPORTED) - ThumbnailGenerationTask负责异步生成和状态转换 - ThumbnailRetryTask定时扫描FAILED状态并重试 - FileProperties配置缩略图生成参数和重试策略 ```mermaid graph LR AuthUser -- "1:N" --> AuthIdentity AuthUser -- "N:M" --> SysRole SysRole -- "N:M" --> SysMenu AuthUser -- "N:M" --> SysDept SysMenu -- "自引用" --> SysMenu SysDept -- "自引用" --> SysDept FileInfo -- "独立" --> "*" ThumbnailGenerationTask -- "状态管理" --> FileInfo ThumbnailRetryTask -- "定时重试" --> FileInfo FileConstants -- "状态常量" --> FileInfo ``` **图表来源** - [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) - [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) - [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) - [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) - [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) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.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) - [SysRoleServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysRoleServiceImpl.java) ## 性能考虑 - 主键选择雪花ID,减少热点与锁竞争,适合高并发写入 - 树形结构(菜单、部门)建议缓存根节点与常用分支,降低递归查询开销 - 大文件元数据(FileInfo)建议按状态分区或归档,保持热数据表轻量 - 批量操作使用 InsertBatchOnDuplicateKeyUpdate 减少往返次数 - 合理索引:唯一索引优先,普通索引按需添加,避免过度索引影响写入 - **缩略图性能优化** - 异步生成避免阻塞上传链路 - Redis分布式锁防止重复生成 - 失败重试机制提高成功率 - 定时任务批量处理失败记录 - 配置化超时和重试参数适应不同场景 ## 故障排查指南 - ID重复或生成失败 - 检查 SnowflakeIdWorker 时钟回拨与节点ID配置 - 确认 CustomIdGenerator 已正确注册到 MyBatis-Plus - 审计字段未填充 - 检查 MetaObjectFillHandler 是否生效,字段命名是否符合约定 - 确认 BaseEntity/OwenedEntity 的字段映射正确 - 逻辑删除失效 - 检查 CrmSqlInjector 是否启用,@TableLogic 注解是否正确 - 唯一约束冲突 - 核对业务唯一字段(username、roleCode、menuCode、deptCode、objectKey)的输入校验 - **缩略图相关故障** - 状态卡住:检查ThumbnailGenerationTask执行日志和Redis锁状态 - 重试不生效:确认retryLimit配置和ThumbnailRetryTask调度 - 生成失败:查看渲染引擎(LibreOffice等)可用性和配置 - 内存溢出:调整缩略图尺寸配置和JVM堆大小 **章节来源** - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.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) - [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增强,实现了统一的审计、逻辑删除与批量操作能力。用户、角色、菜单、部门、身份与文件等核心实体通过明确的关联表与索引设计,满足权限控制、组织架构与文件管理的业务需求。 **更新** 文件模块的缩略图功能显著增强了系统的文件处理能力,包括完整的状态机管理、异步处理机制和失败重试策略。这些改进确保了文件预览功能的稳定性和可靠性,为用户提供了更好的体验。建议在后续演进中持续监控缩略图生成性能和资源使用情况,优化配置参数以适应不同的业务场景。 ## 附录 ### 数据字典(核心实体) - 用户(AuthUser) - id:主键,雪花ID - username:用户名,唯一 - nickname:昵称 - email:邮箱,可选唯一 - phone:手机,可选唯一 - status:状态(参考 StatusEnum) - 审计字段:create_by、update_by、create_time、update_time - 角色(SysRole) - id:主键,雪花ID - roleName:角色名称,非空 - roleCode:角色编码,唯一,非空 - dataScope:数据范围,1-4(本人、本部门、本部门及子部门、全部),默认1 - sort:排序,默认0 - remark:备注 - builtin:内置标记,默认false,true表示系统内置不可删除 - status:状态(参考 StatusEnum) - 审计字段:create_by、update_by、create_time、update_time - 菜单(SysMenu) - id:主键,雪花ID - menuCode:菜单编码,唯一 - menuName:菜单名称 - type:类型(参考 MenuTypeEnum) - path:路由路径 - component:前端组件 - sort:排序 - status:状态(参考 StatusEnum) - parentId:父级ID - 审计字段:同上 - 部门(SysDept) - id:主键,雪花ID - deptCode:部门编码,唯一 - deptName:部门名称 - sort:排序 - status:状态(参考 StatusEnum) - parentId:父级ID - 审计字段:同上 - 身份(AuthIdentity) - id:主键,雪花ID - identityType:身份类型(参考 IdentityTypeEnum) - identityValue:身份值,唯一或组合唯一 - userId:用户ID - provider:提供方 - openId、unionId:第三方标识 - status:状态(参考 StatusEnum) - 审计字段:同上 - 文件(FileInfo)- **已更新** - id:主键,雪花ID - originalName:原始文件名 - objectKey:对象键,唯一 - fileSize:文件大小 - contentType:MIME类型 - bizDomain:业务域 - fileHash:文件哈希(秒传占位) - **thumbnailStatus:缩略图状态(PENDING/READY/FAILED/UNSUPPORTED),默认PENDING** - **thumbnailRetryCount:缩略图重试计数,默认0** - 审计字段:同上 **更新** FileInfo实体新增了缩略图状态和重试计数字段,支持完整的缩略图生命周期管理。 **章节来源** - [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) - [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) - [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) ### 枚举值定义 - StatusEnum:通用状态(如启用/禁用) - HasValueEnum:通用布尔值(是/否) - MenuTypeEnum:菜单类型(如目录、菜单、按钮) - IdentityTypeEnum:身份类型(如手机号、邮箱、第三方账号) - **缩略图状态常量(FileConstants)** - THUMBNAIL_STATUS_PENDING = "PENDING":待生成 - THUMBNAIL_STATUS_READY = "READY":已生成 - THUMBNAIL_STATUS_FAILED = "FAILED":重试耗尽 - THUMBNAIL_STATUS_UNSUPPORTED = "UNSUPPORTED":不支持 **更新** 新增了缩略图状态常量定义,完善了文件模块的状态管理。 **章节来源** - [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) - [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) - [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java) ### 默认值与填充策略 - 主键:雪花ID(CustomIdGenerator + SnowflakeIdWorker) - 审计字段:create_by、update_by、create_time、update_time(MetaObjectFillHandler) - 逻辑删除:enabled(CrmSqlInjector) - 批量插入去重:InsertBatchOnDuplicateKeyUpdate - **缩略图默认值** - thumbnailStatus:默认'PENDING' - thumbnailRetryCount:默认0 **更新** 新增了缩略图字段的默认值策略,确保数据一致性。 **章节来源** - [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) - [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) - [InsertBatchOnDuplicateKeyUpdate.java](file://crm-base/src/main/java/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) ### 缩略图状态机 - **新增章节** - **状态转换规则** - PENDING → READY:缩略图生成成功 - PENDING → FAILED:重试次数耗尽 - PENDING → UNSUPPORTED:文件类型不支持 - FAILED → PENDING:定时任务重置重试 - **状态初始化** - 上传时根据文件类型判断:支持的类型设为PENDING,不支持的设为UNSUPPORTED - 通过ThumbnailGenerationTask.assignInitialStatus()方法设置 - **状态查询优化** - 支持按状态过滤查询 - 建议为thumbnail_status字段建立索引 - **并发控制** - 使用Redis分布式锁防止重复生成 - 锁TTL大于最慢渲染时间 **章节来源** - [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) ### 缩略图重试机制 - **新增章节** - **重试策略** - 配置化重试次数(默认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变更,确保环境一致性 - 新增字段时提供默认值与向后兼容的查询逻辑 - 修改唯一约束前评估历史数据,必要时先清洗再变更 - 灰度发布:先在测试环境验证,再逐步上线生产 - **缩略图功能迁移注意事项** - 新增thumbnail_status字段需设置默认值'PENDING' - 新增thumbnail_retry_count字段需设置默认值0 - 现有文件数据无需特殊处理,首次访问时触发缩略图生成 - 建议为新字段建立适当的索引以提升查询性能 [本节为通用指导,不直接分析具体文件] ### 备份恢复方案 - 定期全量备份(每日)与增量备份(每小时) - 关键表(用户、角色、菜单、部门、文件元数据)提高备份频率 - 恢复演练:定期执行恢复演练,验证备份有效性 - 灾难恢复:制定RTO/RPO目标,明确恢复流程与责任人 - **缩略图数据保护** - 重点关注crn_file_info表的缩略图状态字段 - MinIO中thumbnails目录的缩略图文件备份 - 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)