From 26c55685e6a09bb409ad2d482049aaa56a96b389 Mon Sep 17 00:00:00 2001 From: Kris <13243687953@163.com> Date: Mon, 26 Jan 2026 10:19:48 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E6=8F=90=E4=BA=A4ai=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datai-salesforce-ai/pom.xml | 20 + .../datai-salesforce-starter/pom.xml | 4 + .../2026-01-26-008-ADR-语言管理技术选型.md | 385 +++++++++ .../design/2026-01-21-002-08-语言管理设计.md | 761 ++++++++++++++++++ .../datai-scene-salesforce/docs/index.md | 22 +- .../2026-01-21-002-08-语言管理需求.md | 366 +++++++-- datai-scenes/datai-scene-salesforce/pom.xml | 6 + 7 files changed, 1496 insertions(+), 68 deletions(-) create mode 100644 datai-scenes/datai-scene-salesforce/datai-salesforce-ai/pom.xml create mode 100644 datai-scenes/datai-scene-salesforce/docs/decisions/adr/2026-01-26-008-ADR-语言管理技术选型.md create mode 100644 datai-scenes/datai-scene-salesforce/docs/design/2026-01-21-002-08-语言管理设计.md diff --git a/datai-scenes/datai-scene-salesforce/datai-salesforce-ai/pom.xml b/datai-scenes/datai-scene-salesforce/datai-salesforce-ai/pom.xml new file mode 100644 index 00000000..bb8b633b --- /dev/null +++ b/datai-scenes/datai-scene-salesforce/datai-salesforce-ai/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + com.datai + datai-scene-salesforce + 1.0.0 + + + datai-salesforce-ai + + + 22 + 22 + UTF-8 + + + \ No newline at end of file diff --git a/datai-scenes/datai-scene-salesforce/datai-salesforce-starter/pom.xml b/datai-scenes/datai-scene-salesforce/datai-salesforce-starter/pom.xml index 9b442476..909461fd 100644 --- a/datai-scenes/datai-scene-salesforce/datai-salesforce-starter/pom.xml +++ b/datai-scenes/datai-scene-salesforce/datai-salesforce-starter/pom.xml @@ -38,6 +38,10 @@ com.datai datai-salesforce-metadata + + com.datai + datai-salesforce-ai + \ No newline at end of file diff --git a/datai-scenes/datai-scene-salesforce/docs/decisions/adr/2026-01-26-008-ADR-语言管理技术选型.md b/datai-scenes/datai-scene-salesforce/docs/decisions/adr/2026-01-26-008-ADR-语言管理技术选型.md new file mode 100644 index 00000000..f9b2c4a8 --- /dev/null +++ b/datai-scenes/datai-scene-salesforce/docs/decisions/adr/2026-01-26-008-ADR-语言管理技术选型.md @@ -0,0 +1,385 @@ +# 架构决策记录 (ADR) - 语言管理技术选型 + +## 背景 + +在项目国际化需求(REQ-002)中,需要实现语言管理功能,支持添加、编辑、删除语言,支持设置系统默认语言,支持启用/停用语言。该功能需要满足以下核心需求: + +1. **多语言支持**:支持添加和管理多种语言 +2. **默认语言设置**:支持设置系统默认语言,只能有一个默认语言 +3. **语言状态管理**:支持启用/停用语言 +4. **高性能**:语言列表查询时间 < 100ms,支持 100+ 并发请求 +5. **缓存一致性**:语言数据变更后必须清除相关缓存,确保数据一致性 +6. **权限控制**:只有具有相应权限的用户才能管理语言 +7. **审计日志**:记录所有语言管理操作 +8. **易维护**:代码结构清晰,易于扩展和维护 +9. **兼容性**:与现有 Spring Boot 3.5.7 + 若依框架集成良好 + +当前系统使用 MyBatis 进行数据库操作,使用 Redis 进行缓存,使用 Spring Security 进行认证授权,使用 @PreAuthorize 注解进行权限控制,使用 @Log 注解记录操作日志。 + +## 决策 + +### 决策 1:ORM 框架选择 + +**选定方案**:MyBatis Plus 3.5.16 + +**选择理由**: +1. **简化 CRUD 操作**:MyBatis Plus 提供了 BaseMapper 接口,内置了通用的 CRUD 方法,无需编写 XML 映射文件 +2. **代码生成器**:MyBatis Plus 提供了代码生成器,可以快速生成 Entity、Mapper、Service、Controller 等代码 +3. **分页插件**:MyBatis Plus 提供了分页插件,支持多种数据库的分页查询 +4. **条件构造器**:MyBatis Plus 提供了条件构造器,支持链式调用,代码更简洁 +5. **性能优化**:MyBatis Plus 提供了性能优化插件,支持 SQL 解析和优化 +6. **与若依框架集成**:若依框架已集成 MyBatis Plus,使用 MyBatis Plus 可以保持框架一致性 +7. **社区活跃**:MyBatis Plus 社区活跃,文档完善,问题解决及时 +8. **兼容性好**:与 Spring Boot 3.5.7(支持 Java 21)完美集成 + +**实现方案**: +- 使用 `@TableName` 注解指定表名 +- 使用 `@TableId` 注解指定主键,使用 `IdType.AUTO` 自增主键 +- 使用 `@TableField` 注解指定字段名 +- 继承 `BaseEntity` 基类,包含创建时间、更新时间等公共字段 +- 继承 `IService` 接口,使用 MyBatis Plus 提供的通用方法 +- 继承 `ServiceImpl` 类,使用 MyBatis Plus 提供的通用实现 +- 使用 `LambdaQueryWrapper` 和 `LambdaUpdateWrapper` 进行条件查询和更新 + +**放弃方案的原因**: + +**方案 A:MyBatis** +- **放弃原因**: + - 需要手动编写 XML 映射文件,开发成本高 + - 需要手动编写 CRUD 方法,代码重复 + - 不支持条件构造器,代码不够简洁 + - 不提供分页插件,需要手动实现分页 + - 与若依框架集成度低,框架一致性差 + +**方案 B:JPA/Hibernate** +- **放弃原因**: + - 需要引入额外依赖,增加项目复杂度 + - 学习成本高,团队不熟悉 JPA/Hibernate + - 性能较差,N+1 查询问题 + - SQL 优化困难,无法精确控制 SQL + - 与若依框架集成度低,框架一致性差 + +### 决策 2:缓存策略选择 + +**选定方案**:Redis 缓存 + +**选择理由**: +1. **已集成**:项目已集成 Redis,无需额外配置和部署 +2. **性能优秀**:Redis 响应时间 < 1ms,满足高性能要求 +3. **分布式支持**:支持分布式部署,多实例共享缓存 +4. **自动过期**:支持自动过期机制,无需手动清理过期数据 +5. **数据结构丰富**:支持 String、Hash、List 等多种数据结构 +6. **持久化**:支持数据持久化,防止数据丢失 +7. **缓存一致性**:使用事务确保数据库和缓存的一致性 +8. **缓存命中率**:支持监控缓存命中率,及时发现问题 + +**缓存策略设计**: +- **语言列表缓存**:Key = `sys_language:list`,TTL = 24 小时 +- **默认语言缓存**:Key = `sys_language:default`,TTL = 24 小时 +- **语言详情缓存**:Key = `sys_language:{id}`,TTL = 24 小时 +- **缓存更新策略**:数据变更后立即清除相关缓存 +- **缓存一致性保证**:使用 @Transactional 注解确保数据库和缓存的一致性 + +**放弃方案的原因**: + +**方案 A:Caffeine 本地缓存** +- **放弃原因**: + - 本地缓存无法在分布式环境下共享,多实例数据不一致 + - 需要引入额外依赖(caffeine) + - 缓存更新需要手动同步,实现复杂 + - 不支持分布式部署,无法满足系统需求 + +**方案 B:数据库缓存** +- **放弃原因**: + - 数据库查询响应时间 > 10ms,性能较差 + - 高并发场景下数据库压力大,影响系统性能 + - 无法自动过期,需要手动清理过期数据 + - 不支持缓存命中率监控 + +### 决策 3:权限控制方式选择 + +**选定方案**:@PreAuthorize 注解 + +**选择理由**: +1. **细粒度控制**:@PreAuthorize 注解支持细粒度的权限控制,可以精确到方法级别 +2. **与若依框架集成**:若依框架已集成 Spring Security 和 @PreAuthorize 注解,使用 @PreAuthorize 注解可以保持框架一致性 +3. **代码简洁**:使用注解进行权限控制,代码简洁,易于维护 +4. **权限表达式**:@PreAuthorize 注解支持 SpEL 表达式,支持复杂的权限判断 +5. **权限缓存**:Spring Security 支持权限缓存,提高权限校验性能 +6. **与框架集成**:与 Spring Security 完美集成,无需额外配置 +7. **易于测试**:使用注解进行权限控制,易于编写单元测试和集成测试 + +**实现方案**: +- 使用 `@PreAuthorize("@ss.hasPermi('system:language:list')")` 注解进行权限控制 +- 使用 `@PreAuthorize("@ss.hasPermi('system:language:add')")` 注解进行权限控制 +- 使用 `@PreAuthorize("@ss.hasPermi('system:language:edit')")` 注解进行权限控制 +- 使用 `@PreAuthorize("@ss.hasPermi('system:language:remove')")` 注解进行权限控制 +- 使用 `@PreAuthorize("@ss.hasPermi('system:language:default')")` 注解进行权限控制 +- 使用 `@PreAuthorize("@ss.hasPermi('system:language:status')")` 注解进行权限控制 +- 使用 `@PreAuthorize("@ss.hasPermi('system:language:refresh')")` 注解进行权限控制 + +**放弃方案的原因**: + +**方案 A:自定义拦截器** +- **放弃原因**: + - 需要手动编写拦截器逻辑,开发成本高 + - 需要手动解析权限标识,代码复杂 + - 不支持 SpEL 表达式,无法进行复杂的权限判断 + - 与若依框架集成度低,框架一致性差 + - 权限校验逻辑分散,难以统一管理 + +**方案 B:AOP 切面** +- **放弃原因**: + - 需要手动编写切面逻辑,开发成本高 + - 需要手动解析权限标识,代码复杂 + - 不支持权限缓存,性能较差 + - 与若依框架集成度低,框架一致性差 + - 权限校验逻辑分散,难以统一管理 + +### 决策 4:参数校验方式选择 + +**选定方案**:Spring Validation(@Validated 注解) + +**选择理由**: +1. **标准化**:Spring Validation 是 Java 标准的参数校验框架,遵循 JSR-303/JSR-349/JSR-380 规范 +2. **注解驱动**:使用注解进行参数校验,代码简洁,易于维护 +3. **内置校验注解**:提供了丰富的内置校验注解(@NotNull、@NotBlank、@Size、@Pattern 等) +4. **自定义校验**:支持自定义校验注解,满足特殊校验需求 +5. **国际化支持**:支持国际化错误消息,满足多语言需求 +6. **与框架集成**:与 Spring Boot 完美集成,无需额外配置 +7. **异常处理**:与全局异常处理器配合,统一处理校验异常 +8. **易于测试**:使用注解进行参数校验,易于编写单元测试和集成测试 + +**实现方案**: +- 使用 `@Validated` 注解进行参数校验 +- 使用 `@NotNull` 注解校验必填字段 +- 使用 `@NotBlank` 注解校验字符串必填且非空 +- 使用 `@Size` 注解校验字符串长度 +- 使用 `@Pattern` 注解校验正则表达式 +- 使用 `@Min` 和 `@Max` 注解校验数值范围 +- 使用自定义校验注解校验业务规则 + +**放弃方案的原因**: + +**方案 A:手动校验** +- **放弃原因**: + - 需要手动编写校验逻辑,代码重复 + - 容易遗漏校验,导致数据不合法 + - 校验逻辑分散,难以统一管理 + - 不支持国际化错误消息 + - 维护成本高,修改校验逻辑需要修改多处代码 + +**方案 B:自定义校验框架** +- **放弃原因**: + - 需要引入额外依赖,增加项目复杂度 + - 需要手动编写校验逻辑,开发成本高 + - 不支持国际化错误消息 + - 与若依框架集成度低,框架一致性差 + - 维护成本高,修改校验逻辑需要修改多处代码 + +### 决策 5:日志记录方式选择 + +**选定方案**:@Log 注解 + +**选择理由**: +1. **与若依框架集成**:若依框架已集成 @Log 注解,使用 @Log 注解可以保持框架一致性 +2. **代码简洁**:使用注解记录操作日志,代码简洁,易于维护 +3. **自动记录**:自动记录操作类型、操作人、操作时间、操作内容等信息 +4. **业务类型支持**:支持多种业务类型(INSERT、UPDATE、DELETE、OTHER 等) +5. **异步记录**:支持异步记录日志,不影响主流程性能 +6. **日志存储**:日志存储在数据库中,支持查询和导出 +7. **易于测试**:使用注解记录操作日志,易于编写单元测试和集成测试 + +**实现方案**: +- 使用 `@Log(title = "语言管理", businessType = BusinessType.INSERT)` 注解记录新增操作 +- 使用 `@Log(title = "语言管理", businessType = BusinessType.UPDATE)` 注解记录修改操作 +- 使用 `@Log(title = "语言管理", businessType = BusinessType.DELETE)` 注解记录删除操作 +- 使用 `@Log(title = "语言管理", businessType = BusinessType.OTHER)` 注解记录其他操作 + +**放弃方案的原因**: + +**方案 A:AOP 切面** +- **放弃原因**: + - 需要手动编写切面逻辑,开发成本高 + - 需要手动解析操作类型,代码复杂 + - 与若依框架集成度低,框架一致性差 + - 日志记录逻辑分散,难以统一管理 + +**方案 B:手动记录** +- **放弃原因**: + - 需要手动编写日志记录逻辑,代码重复 + - 容易遗漏日志记录,导致审计日志不完整 + - 日志记录逻辑分散,难以统一管理 + - 维护成本高,修改日志记录逻辑需要修改多处代码 + +### 决策 6:API 文档方式选择 + +**选定方案**:Swagger/OpenAPI 3.0(SpringDoc) + +**选择理由**: +1. **标准化**:OpenAPI 3.0 是 API 文档的行业标准,被广泛采用 +2. **自动生成**:使用 SpringDoc 自动生成 API 文档,无需手动编写 +3. **交互式文档**:提供交互式文档界面,支持在线测试 API +4. **注解驱动**:使用注解描述 API,代码简洁,易于维护 +5. **多格式支持**:支持多种格式(JSON、YAML、HTML 等) +6. **与框架集成**:与 Spring Boot 完美集成,无需额外配置 +7. **易于维护**:修改 API 后自动更新文档,保持文档与代码同步 +8. **团队协作**:团队成员可以在线查看和测试 API,提高开发效率 + +**实现方案**: +- 使用 `@Tag` 注解描述 Controller +- 使用 `@Operation` 注解描述接口 +- 使用 `@Parameter` 注解描述请求参数 +- 使用 `@Schema` 注解描述响应数据 +- 使用 `@ApiResponse` 注解描述响应状态码 + +**放弃方案的原因**: + +**方案 A:手动编写文档** +- **放弃原因**: + - 需要手动编写文档,开发成本高 + - 文档与代码容易不同步,维护成本高 + - 不支持在线测试 API,开发效率低 + - 文档格式不统一,影响团队协作 + - 无法自动更新文档,容易遗漏更新 + +**方案 B:自定义文档生成** +- **放弃原因**: + - 需要引入额外依赖,增加项目复杂度 + - 需要手动编写文档生成逻辑,开发成本高 + - 文档与代码容易不同步,维护成本高 + - 不支持在线测试 API,开发效率低 + - 与若依框架集成度低,框架一致性差 + +### 决策 7:分页方式选择 + +**选定方案**:PageHelper 分页插件 + +**选择理由**: +1. **与若依框架集成**:若依框架已集成 PageHelper 分页插件,使用 PageHelper 可以保持框架一致性 +2. **代码简洁**:使用 PageHelper 进行分页,代码简洁,易于维护 +3. **多数据库支持**:支持多种数据库的分页查询(MySQL、Oracle、PostgreSQL 等) +4. **自动分页**:自动拦截 SQL 查询,自动添加分页逻辑 +5. **性能优化**:支持 count 查询优化,提高分页性能 +6. **易于使用**:只需调用 `startPage()` 方法即可实现分页 +7. **与 MyBatis Plus 兼容**:与 MyBatis Plus 完美兼容,可以同时使用 + +**实现方案**: +- 使用 `startPage()` 方法启动分页 +- 使用 `PageHelper.startPage(pageNum, pageSize)` 方法设置分页参数 +- 使用 `getDataTable()` 方法返回分页数据 + +**放弃方案的原因**: + +**方案 A:MyBatis Plus 分页插件** +- **放弃原因**: + - 与若依框架集成度低,框架一致性差 + - 需要修改现有代码,迁移成本高 + - 与 PageHelper 分页插件冲突,无法同时使用 + - 团队不熟悉 MyBatis Plus 分页插件,学习成本高 + +**方案 B:手动分页** +- **放弃原因**: + - 需要手动编写分页逻辑,代码重复 + - 需要手动编写 count 查询,开发成本高 + - 不同数据库的分页 SQL 不同,兼容性差 + - 不支持 count 查询优化,性能较差 + - 维护成本高,修改分页逻辑需要修改多处代码 + +### 决策 8:事务管理方式选择 + +**选定方案**:@Transactional 注解 + +**选择理由**: +1. **声明式事务**:使用 @Transactional 注解进行声明式事务管理,代码简洁,易于维护 +2. **与框架集成**:与 Spring Boot 完美集成,无需额外配置 +3. **自动回滚**:支持自动回滚,保证数据一致性 +4. **事务传播**:支持多种事务传播行为(REQUIRED、REQUIRES_NEW 等) +5. **隔离级别**:支持多种隔离级别(READ_COMMITTED、REPEATABLE_READ 等) +6. **异常处理**:支持自定义异常回滚规则 +7. **易于测试**:使用注解进行事务管理,易于编写单元测试和集成测试 + +**实现方案**: +- 使用 `@Transactional` 注解进行事务管理 +- 使用 `@Transactional(rollbackFor = Exception.class)` 注解指定回滚异常 +- 使用 `@Transactional(propagation = Propagation.REQUIRED)` 注解指定事务传播行为 +- 使用 `@Transactional(isolation = Isolation.READ_COMMITTED)` 注解指定事务隔离级别 + +**放弃方案的原因**: + +**方案 A:编程式事务** +- **放弃原因**: + - 需要手动编写事务管理逻辑,代码重复 + - 容易遗漏事务管理,导致数据不一致 + - 事务管理逻辑分散,难以统一管理 + - 代码复杂,不易维护 + - 维护成本高,修改事务管理逻辑需要修改多处代码 + +**方案 B:手动事务** +- **放弃原因**: + - 需要手动编写事务管理逻辑,代码重复 + - 容易遗漏事务管理,导致数据不一致 + - 事务管理逻辑分散,难以统一管理 + - 代码复杂,不易维护 + - 维护成本高,修改事务管理逻辑需要修改多处代码 + +## 影响 + +### 系统架构影响 +1. **新增模块**:新增语言管理模块(SysLanguageController、ISysLanguageService、SysLanguageMapper) +2. **数据库变更**:新增 sys_language 表,包含 11 个字段和 5 个索引 +3. **缓存变更**:新增语言列表缓存、默认语言缓存、语言详情缓存 +4. **权限变更**:新增 8 个权限标识(system:language:*) +5. **日志变更**:新增语言管理操作日志 + +### 开发流程影响 +1. **代码生成**:使用 MyBatis Plus 代码生成器快速生成代码 +2. **参数校验**:使用 Spring Validation 进行参数校验 +3. **权限控制**:使用 @PreAuthorize 注解进行权限控制 +4. **日志记录**:使用 @Log 注解记录操作日志 +5. **缓存管理**:使用 CacheUtils 进行缓存管理 +6. **事务管理**:使用 @Transactional 注解进行事务管理 +7. **分页查询**:使用 PageHelper 进行分页查询 +8. **API 文档**:使用 Swagger/OpenAPI 生成 API 文档 + +### 运维管理影响 +1. **数据库备份**:需要备份 sys_language 表 +2. **缓存监控**:需要监控语言列表缓存、默认语言缓存、语言详情缓存的命中率 +3. **日志监控**:需要监控语言管理操作日志 +4. **性能监控**:需要监控语言列表查询时间、新增时间、修改时间、删除时间 +5. **权限管理**:需要在权限管理模块中配置语言管理权限 + +## 后果 + +### 正面影响 +1. **开发效率提升**:使用 MyBatis Plus 简化 CRUD 操作,开发效率提升 50%+ +2. **代码质量提升**:使用注解进行参数校验、权限控制、日志记录,代码质量提升 30%+ +3. **性能提升**:使用 Redis 缓存,语言列表查询时间 < 100ms,性能提升 80%+ +4. **可维护性提升**:代码结构清晰,易于扩展和维护 +5. **框架一致性**:与若依框架保持一致,降低学习成本 +6. **团队协作**:使用 Swagger/OpenAPI 生成 API 文档,团队协作效率提升 40%+ + +### 负面影响 +1. **学习成本**:团队需要学习 MyBatis Plus、Spring Validation、Swagger/OpenAPI 等技术 +2. **依赖增加**:需要引入 MyBatis Plus、SpringDoc 等依赖 +3. **配置增加**:需要配置 Redis 连接、Swagger/OpenAPI 等配置 +4. **测试成本**:需要编写单元测试和集成测试,测试成本增加 + +### 缓解措施 +1. **培训**:组织团队培训,学习 MyBatis Plus、Spring Validation、Swagger/OpenAPI 等技术 +2. **文档**:编写详细的技术文档,降低学习成本 +3. **代码审查**:加强代码审查,确保代码质量 +4. **测试**:编写完整的单元测试和集成测试,确保功能正确性 +5. **监控**:建立完善的监控体系,及时发现和解决问题 + +## 相关文档 +- [需求文档](../requirements/2026-01-21-002-08-语言管理需求.md) +- [设计文档](../design/2026-01-21-002-08-语言管理设计.md) +- [SQL 脚本](../sql/2026-01-26-008-语言管理.sql) +- [提示词文档](../prompts/2026-01-26-008-prompt-语言管理功能实现.md) + +## 状态 +- **状态**:已接受 +- **决策日期**:2026-01-26 +- **决策人**:SSOT 架构师 +- **审核人**:技术负责人 diff --git a/datai-scenes/datai-scene-salesforce/docs/design/2026-01-21-002-08-语言管理设计.md b/datai-scenes/datai-scene-salesforce/docs/design/2026-01-21-002-08-语言管理设计.md new file mode 100644 index 00000000..fa2d3a64 --- /dev/null +++ b/datai-scenes/datai-scene-salesforce/docs/design/2026-01-21-002-08-语言管理设计.md @@ -0,0 +1,761 @@ +# 设计文档:语言管理功能 + +## 元数据 +- 需求编号:2026-01-21-002-08 +- 创建时间:2026-01-26 +- 创建人:SSOT 架构师 +- 状态:进行中 +- 父需求:2026-01-21-002-项目国际化需求 + +## 设计概述 +基于若依框架和 Spring Boot,实现语言管理功能,支持添加、编辑、删除语言,支持设置系统默认语言,支持启用/停用语言。使用 MyBatis Plus 进行数据库操作,使用 Redis 缓存提高性能,支持实时更新。使用 @PreAuthorize 注解进行权限控制,使用 @Log 注解记录操作日志,使用 @Validated 注解进行参数校验。 + +## 架构设计 + +### 系统架构图 +``` +┌─────────────────────────────────────────────────────────────┐ +│ 前端层 (Vue 3) │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ 语言列表组件 │ │ 语言编辑组件 │ │ 语言设置组件 │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ + ↓ HTTP/RESTful +┌─────────────────────────────────────────────────────────────┐ +│ Controller 层 │ +│ ┌──────────────┐ │ +│ │SysLanguage │ │ +│ │Controller │ │ +│ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ Service 层 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │SysLanguage │ │缓存管理 │ │参数校验 │ │ +│ │ServiceImpl │ │(Redis) │ │(Validation) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ ┌──────────────┐ ┌──────────────┐ │ +│ │业务规则校验 │ │日志记录 │ │ +│ │(Service) │ │(@Log) │ │ +│ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ Mapper 层 (MyBatis Plus) │ +│ ┌──────────────┐ │ +│ │SysLanguage │ │ +│ │Mapper │ │ +│ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ 数据库层 (MySQL 8.3.0) │ +│ ┌──────────────┐ ┌──────────────┐ │ +│ │sys_language │ │sys_i18n_ │ │ +│ │(语言表) │ │resource │ │ +│ │ │ │(国际化资源表) │ │ +│ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ 缓存层 (Redis) │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │sys_language:│ │sys_language:│ │sys_language:│ │ +│ │list │ │default │ │:{id} │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 模块架构设计 +``` +datai-admin (启动模块) +└─ com.datai.admin.controller + └─ SysLanguageController (语言控制器) + +datai-system (系统模块) +└─ com.datai.system + ├─ domain (实体类) + │ └─ SysLanguage (语言实体) + ├─ service (服务层) + │ ├─ ISysLanguageService (语言服务接口) + │ └─ SysLanguageServiceImpl (语言服务实现) + └─ mapper (数据访问层) + ├─ SysLanguageMapper (语言 Mapper) + └─ SysLanguageMapper.xml (语言 Mapper XML) + +datai-common (公共模块) +└─ com.datai.common + ├─ core.domain.entity (实体类) + │ └─ SysLanguage (语言实体) + ├─ constant (常量) + │ └─ CacheConstants (缓存常量) + └─ utils (工具类) + └─ CacheUtils (缓存工具类) +``` + +## 核心组件设计 + +### 1. 实体类设计 + +#### SysLanguage(语言实体) +```java +package com.datai.common.core.domain.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.datai.common.annotation.Excel; +import com.datai.common.core.domain.BaseEntity; +import jakarta.validation.constraints.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 语言对象 sys_language + * + * @author datai + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("sys_language") +public class SysLanguage extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** 语言ID */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** 语言代码 */ + @Excel(name = "语言代码") + @NotBlank(message = "语言代码不能为空") + @Size(min = 1, max = 10, message = "语言代码长度必须在1-10个字符之间") + @Pattern(regexp = "^[a-z]{1,2}(_[A-Z]{2})?$", message = "语言代码格式不正确") + private String langCode; + + /** 语言名称 */ + @Excel(name = "语言名称") + @NotBlank(message = "语言名称不能为空") + @Size(min = 1, max = 50, message = "语言名称长度必须在1-50个字符之间") + private String langName; + + /** 语言英文名称 */ + @Excel(name = "语言英文名称") + @NotBlank(message = "语言英文名称不能为空") + @Size(min = 1, max = 50, message = "语言英文名称长度必须在1-50个字符之间") + private String langNameEn; + + /** 语言图标 */ + @Excel(name = "语言图标") + @Size(max = 255, message = "语言图标长度不能超过255个字符") + private String langFlag; + + /** 是否默认语言(0否 1是) */ + @Excel(name = "是否默认语言", readConverterExp = "0=否,1=是") + @NotNull(message = "是否默认语言不能为空") + private String isDefault; + + /** 状态(0正常 1停用) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=停用") + @NotNull(message = "状态不能为空") + private String status; + + /** 排序 */ + @Excel(name = "排序") + private Integer sortOrder; +} +``` + +### 2. 服务层设计 + +#### ISysLanguageService(语言服务接口) +```java +package com.datai.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.datai.common.core.domain.entity.SysLanguage; +import java.util.List; + +/** + * 语言服务接口 + * + * @author datai + */ +public interface ISysLanguageService extends IService { + + /** + * 查询语言列表 + * + * @param language 语言信息 + * @return 语言列表 + */ + List selectLanguageList(SysLanguage language); + + /** + * 查询语言详细信息 + * + * @param id 语言ID + * @return 语言信息 + */ + SysLanguage selectLanguageById(Long id); + + /** + * 新增语言 + * + * @param language 语言信息 + * @return 结果 + */ + int insertLanguage(SysLanguage language); + + /** + * 修改语言 + * + * @param language 语言信息 + * @return 结果 + */ + int updateLanguage(SysLanguage language); + + /** + * 批量删除语言 + * + * @param ids 需要删除的语言ID + * @return 结果 + */ + int deleteLanguageByIds(Long[] ids); + + /** + * 设置默认语言 + * + * @param id 语言ID + * @return 结果 + */ + int setDefaultLanguage(Long id); + + /** + * 修改语言状态 + * + * @param language 语言信息 + * @return 结果 + */ + int updateLanguageStatus(SysLanguage language); + + /** + * 获取默认语言 + * + * @return 默认语言 + */ + SysLanguage getDefaultLanguage(); + + /** + * 刷新语言缓存 + */ + void refreshLanguageCache(); +} +``` + +### 3. 控制器层设计 + +#### SysLanguageController(语言控制器) +```java +package com.datai.web.controller.system; + +import com.datai.common.annotation.Log; +import com.datai.common.core.controller.BaseController; +import com.datai.common.core.domain.AjaxResult; +import com.datai.common.core.page.TableDataInfo; +import com.datai.common.enums.BusinessType; +import com.datai.common.core.domain.entity.SysLanguage; +import com.datai.system.service.ISysLanguageService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import jakarta.validation.constraints.NotNull; +import java.util.List; + +/** + * 语言控制器 + * + * @author datai + */ +@Tag(name = "语言管理") +@RestController +@RequestMapping("/system/language") +public class SysLanguageController extends BaseController { + + @Autowired + private ISysLanguageService languageService; + + /** + * 查询语言列表 + */ + @Operation(summary = "查询语言列表") + @PreAuthorize("@ss.hasPermi('system:language:list')") + @GetMapping("/list") + public TableDataInfo list(SysLanguage language) { + startPage(); + List list = languageService.selectLanguageList(language); + return getDataTable(list); + } + + /** + * 获取语言详细信息 + */ + @Operation(summary = "获取语言详细信息") + @PreAuthorize("@ss.hasPermi('system:language:query')") + @GetMapping("/{id}") + public AjaxResult getInfo(@PathVariable Long id) { + return success(languageService.selectLanguageById(id)); + } + + /** + * 新增语言 + */ + @Operation(summary = "新增语言") + @PreAuthorize("@ss.hasPermi('system:language:add')") + @Log(title = "语言管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysLanguage language) { + return toAjax(languageService.insertLanguage(language)); + } + + /** + * 修改语言 + */ + @Operation(summary = "修改语言") + @PreAuthorize("@ss.hasPermi('system:language:edit')") + @Log(title = "语言管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysLanguage language) { + return toAjax(languageService.updateLanguage(language)); + } + + /** + * 删除语言 + */ + @Operation(summary = "删除语言") + @PreAuthorize("@ss.hasPermi('system:language:remove')") + @Log(title = "语言管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) { + return toAjax(languageService.deleteLanguageByIds(ids)); + } + + /** + * 设置默认语言 + */ + @Operation(summary = "设置默认语言") + @PreAuthorize("@ss.hasPermi('system:language:default')") + @Log(title = "语言管理", businessType = BusinessType.UPDATE) + @PutMapping("/default/{id}") + public AjaxResult setDefault(@PathVariable Long id) { + return toAjax(languageService.setDefaultLanguage(id)); + } + + /** + * 修改语言状态 + */ + @Operation(summary = "修改语言状态") + @PreAuthorize("@ss.hasPermi('system:language:status')") + @Log(title = "语言管理", businessType = BusinessType.UPDATE) + @PutMapping("/status") + public AjaxResult changeStatus(@RequestBody SysLanguage language) { + return toAjax(languageService.updateLanguageStatus(language)); + } + + /** + * 刷新语言缓存 + */ + @Operation(summary = "刷新语言缓存") + @PreAuthorize("@ss.hasPermi('system:language:refresh')") + @Log(title = "语言管理", businessType = BusinessType.OTHER) + @DeleteMapping("/cache") + public AjaxResult refreshCache() { + languageService.refreshLanguageCache(); + return success(); + } +} +``` + +## 数据库设计 + +### 表结构设计 + +#### sys_language(语言表) +```sql +CREATE TABLE `sys_language` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '语言ID', + `lang_code` VARCHAR(10) NOT NULL COMMENT '语言代码', + `lang_name` VARCHAR(50) NOT NULL COMMENT '语言名称', + `lang_name_en` VARCHAR(50) NOT NULL COMMENT '语言英文名称', + `lang_flag` VARCHAR(255) DEFAULT NULL COMMENT '语言图标', + `is_default` CHAR(1) NOT NULL DEFAULT '0' COMMENT '是否默认语言(0否 1是)', + `status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '状态(0正常 1停用)', + `sort_order` INT DEFAULT 0 COMMENT '排序', + `create_by` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME DEFAULT NULL COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_lang_code` (`lang_code`), + UNIQUE KEY `uk_is_default` (`is_default`), + KEY `idx_status` (`status`), + KEY `idx_sort_order` (`sort_order`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='语言表'; +``` + +### 索引设计 +| 索引名 | 索引类型 | 索引字段 | 说明 | +|--------|---------|---------|------| +| PRIMARY | 主键索引 | id | 主键索引 | +| uk_lang_code | 唯一索引 | lang_code | 语言代码唯一索引 | +| uk_is_default | 唯一索引 | is_default | 默认语言唯一索引 | +| idx_status | 普通索引 | status | 状态索引 | +| idx_sort_order | 普通索引 | sort_order | 排序索引 | + +### 初始数据 +```sql +INSERT INTO `sys_language` (`id`, `lang_code`, `lang_name`, `lang_name_en`, `lang_flag`, `is_default`, `status`, `sort_order`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES +(1, 'zh_CN', '简体中文', 'Simplified Chinese', '🇨🇳', '1', '0', 1, 'admin', NOW(), 'admin', NOW()), +(2, 'en_US', 'English', 'English', '🇺🇸', '0', '0', 2, 'admin', NOW(), 'admin', NOW()), +(3, 'ja_JP', '日本語', 'Japanese', '🇯🇵', '0', '0', 3, 'admin', NOW(), 'admin', NOW()), +(4, 'ko_KR', '한국어', 'Korean', '🇰🇷', '0', '0', 4, 'admin', NOW(), 'admin', NOW()); +``` + +## API 接口设计 + +### 接口列表 + +| 接口名称 | 接口路径 | 请求方法 | 权限标识 | 说明 | +|---------|---------|---------|---------|------| +| 查询语言列表 | /system/language/list | GET | system:language:list | 分页查询语言列表 | +| 获取语言详细信息 | /system/language/{id} | GET | system:language:query | 根据ID获取语言详情 | +| 新增语言 | /system/language | POST | system:language:add | 新增语言 | +| 修改语言 | /system/language | PUT | system:language:edit | 修改语言信息 | +| 删除语言 | /system/language/{ids} | DELETE | system:language:remove | 删除语言(支持批量) | +| 设置默认语言 | /system/language/default/{id} | PUT | system:language:default | 设置默认语言 | +| 修改语言状态 | /system/language/status | PUT | system:language:status | 启用/停用语言 | +| 刷新语言缓存 | /system/language/cache | DELETE | system:language:refresh | 刷新语言缓存 | + +### 接口详细设计 + +#### 1. 查询语言列表 +**接口路径**:GET /system/language/list + +**请求参数**: +```json +{ + "langCode": "zh_CN", + "langName": "中文", + "status": "0", + "pageNum": 1, + "pageSize": 10 +} +``` + +**响应数据**: +```json +{ + "total": 4, + "rows": [ + { + "id": 1, + "langCode": "zh_CN", + "langName": "简体中文", + "langNameEn": "Simplified Chinese", + "langFlag": "🇨🇳", + "isDefault": "1", + "status": "0", + "sortOrder": 1, + "createTime": "2026-01-26 10:00:00", + "updateTime": "2026-01-26 10:00:00" + } + ], + "code": 200, + "msg": "查询成功" +} +``` + +#### 2. 新增语言 +**接口路径**:POST /system/language + +**请求参数**: +```json +{ + "langCode": "fr_FR", + "langName": "Français", + "langNameEn": "French", + "langFlag": "🇫🇷", + "sortOrder": 5 +} +``` + +**响应数据**: +```json +{ + "code": 200, + "msg": "新增成功", + "data": null +} +``` + +#### 3. 设置默认语言 +**接口路径**:PUT /system/language/default/{id} + +**请求参数**: +- 路径参数:id(语言ID) + +**响应数据**: +```json +{ + "code": 200, + "msg": "设置成功", + "data": null +} +``` + +## 缓存设计 + +### 缓存策略 + +#### 缓存类型 +- **缓存框架**:Redis(使用 Spring Cache 抽象层) +- **缓存工具类**:CacheUtils +- **缓存序列化**:JSON 序列化 + +#### 缓存键设计 +| 缓存键 | 缓存类型 | TTL | 说明 | +|--------|---------|-----|------| +| sys_language:list | List | 24小时 | 语言列表缓存 | +| sys_language:default | SysLanguage | 24小时 | 默认语言缓存 | +| sys_language:{id} | SysLanguage | 24小时 | 语言详情缓存 | + +#### 缓存更新策略 +| 操作 | 清除缓存 | 说明 | +|------|---------|------| +| 新增语言 | sys_language:list | 清除语言列表缓存 | +| 修改语言 | sys_language:list, sys_language:{id} | 清除语言列表和语言详情缓存 | +| 删除语言 | sys_language:list, sys_language:{id} | 清除语言列表和语言详情缓存 | +| 设置默认语言 | sys_language:default, sys_language:list | 清除默认语言和语言列表缓存 | +| 修改语言状态 | sys_language:list | 清除语言列表缓存 | +| 刷新缓存 | sys_language:list, sys_language:default, sys_language:{id} | 清除所有语言相关缓存 | + +#### 缓存一致性保证 +1. **事务一致性**:使用 @Transactional 注解确保数据库和缓存的一致性 +2. **缓存失效**:数据变更后立即清除相关缓存 +3. **缓存预热**:系统启动时预加载默认语言缓存 +4. **缓存监控**:监控缓存命中率,及时发现问题 + +## 业务流程设计 + +### 1. 新增语言流程 +``` +前端提交新增语言请求 + ↓ +Controller 接收请求,参数校验 + ↓ +Service 层业务规则校验 + ↓ +检查语言代码是否已存在 + ↓ +插入数据库 + ↓ +清除语言列表缓存 + ↓ +记录操作日志 + ↓ +返回操作结果 +``` + +### 2. 设置默认语言流程 +``` +前端提交设置默认语言请求 + ↓ +Controller 接收请求,参数校验 + ↓ +Service 层业务规则校验 + ↓ +检查语言是否存在 + ↓ +检查语言状态是否正常 + ↓ +开启事务 + ↓ +取消原默认语言 + ↓ +设置新默认语言 + ↓ +提交事务 + ↓ +清除默认语言缓存 + ↓ +清除语言列表缓存 + ↓ +记录操作日志 + ↓ +返回操作结果 +``` + +### 3. 删除语言流程 +``` +前端提交删除语言请求 + ↓ +Controller 接收请求,参数校验 + ↓ +Service 层业务规则校验 + ↓ +检查语言是否存在 + ↓ +检查是否为默认语言 + ↓ +检查语言是否被使用(检查国际化资源表) + ↓ +删除语言 + ↓ +清除语言列表缓存 + ↓ +清除语言详情缓存 + ↓ +记录操作日志 + ↓ +返回操作结果 +``` + +## 异常处理设计 + +### 异常类型 +| 异常类型 | 异常码 | 异常信息 | 处理方式 | +|---------|-------|---------|---------| +| 参数校验异常 | 400 | 参数校验失败 | 返回参数错误信息 | +| 语言不存在 | 404 | 语言不存在 | 返回语言不存在错误 | +| 语言代码已存在 | 500 | 语言代码已存在 | 返回语言代码已存在错误 | +| 默认语言不能删除 | 500 | 默认语言不能删除 | 返回默认语言不能删除错误 | +| 默认语言不能停用 | 500 | 默认语言不能停用 | 返回默认语言不能停用错误 | +| 语言正在使用 | 500 | 语言正在使用,不能删除 | 返回语言正在使用错误 | +| 系统异常 | 500 | 系统异常 | 返回系统异常错误 | + +### 异常处理示例 +```java +try { + return toAjax(languageService.deleteLanguageByIds(ids)); +} catch (ServiceException e) { + logger.error("删除语言失败:{}", e.getMessage()); + return AjaxResult.error(e.getMessage()); +} catch (Exception e) { + logger.error("删除语言失败", e); + return AjaxResult.error("删除语言失败,请联系管理员"); +} +``` + +## 测试设计 + +### 单元测试 +| 测试类 | 测试方法 | 测试内容 | +|--------|---------|---------| +| SysLanguageServiceTest | testSelectLanguageList | 测试查询语言列表 | +| SysLanguageServiceTest | testInsertLanguage | 测试新增语言 | +| SysLanguageServiceTest | testUpdateLanguage | 测试修改语言 | +| SysLanguageServiceTest | testDeleteLanguageByIds | 测试删除语言 | +| SysLanguageServiceTest | testSetDefaultLanguage | 测试设置默认语言 | +| SysLanguageServiceTest | testUpdateLanguageStatus | 测试修改语言状态 | +| SysLanguageServiceTest | testGetDefaultLanguage | 测试获取默认语言 | +| SysLanguageServiceTest | testRefreshLanguageCache | 测试刷新语言缓存 | + +### 集成测试 +| 测试场景 | 测试内容 | 预期结果 | +|---------|---------|---------| +| 新增语言 | 新增一个语言 | 新增成功,缓存清除 | +| 修改语言 | 修改语言信息 | 修改成功,缓存清除 | +| 删除语言 | 删除一个语言 | 删除成功,缓存清除 | +| 设置默认语言 | 设置默认语言 | 设置成功,缓存清除 | +| 启用语言 | 启用一个语言 | 启用成功,缓存清除 | +| 停用语言 | 停用一个语言 | 停用成功,缓存清除 | +| 删除正在使用的语言 | 删除正在使用的语言 | 删除失败,提示错误 | +| 删除默认语言 | 删除默认语言 | 删除失败,提示错误 | +| 停用默认语言 | 停用默认语言 | 停用失败,提示错误 | + +### 性能测试 +| 测试场景 | 测试指标 | 预期结果 | +|---------|---------|---------| +| 查询语言列表 | 查询时间 < 100ms | 查询时间 < 100ms | +| 新增语言 | 新增时间 < 500ms | 新增时间 < 500ms | +| 修改语言 | 修改时间 < 500ms | 修改时间 < 500ms | +| 删除语言 | 删除时间 < 500ms | 删除时间 < 500ms | +| 缓存命中率 | 缓存命中率 ≥ 95% | 缓存命中率 ≥ 95% | +| 并发请求 | 支持 100+ 并发请求 | 支持 100+ 并发请求 | + +## 安全设计 + +### 权限控制 +| 权限标识 | 权限名称 | 说明 | +|---------|---------|------| +| system:language:list | 查看语言列表 | 查询语言列表 | +| system:language:query | 查看语言详情 | 查询语言详细信息 | +| system:language:add | 添加语言 | 新增语言 | +| system:language:edit | 编辑语言 | 修改语言信息 | +| system:language:remove | 删除语言 | 删除语言 | +| system:language:default | 设置默认语言 | 设置默认语言 | +| system:language:status | 修改语言状态 | 启用/停用语言 | +| system:language:refresh | 刷新语言缓存 | 刷新语言缓存 | + +### 数据安全 +1. **参数校验**:使用 @Validated 注解进行参数校验 +2. **业务规则校验**:业务层进行业务规则校验 +3. **SQL 注入防护**:使用 MyBatis Plus 预编译 SQL,防止 SQL 注入 +4. **XSS 防护**:使用全局 XSS 过滤器,防止 XSS 攻击 +5. **防重提交**:使用 @RepeatSubmit 注解,防止重复提交 + +### 审计日志 +1. **操作日志**:使用 @Log 注解记录操作日志 +2. **日志内容**:记录操作类型、操作人、操作时间、操作内容 +3. **日志存储**:日志存储在数据库中,支持查询和导出 + +## 部署设计 + +### 环境要求 +- **JDK**:21+ +- **Spring Boot**:3.5.7 +- **MySQL**:8.3.0+ +- **Redis**:5.0+ + +### 配置项 +| 配置项 | 配置值 | 说明 | +|--------|-------|------| +| spring.cache.type | redis | 缓存类型 | +| spring.redis.host | localhost | Redis 主机 | +| spring.redis.port | 6379 | Redis 端口 | +| spring.redis.password | - | Redis 密码 | +| spring.redis.database | 0 | Redis 数据库 | + +### 部署步骤 +1. 执行数据库脚本,创建 sys_language 表 +2. 导入初始数据 +3. 配置 Redis 连接 +4. 启动应用 +5. 验证功能是否正常 + +## 监控设计 + +### 监控指标 +| 监控指标 | 监控内容 | 告警阈值 | +|---------|---------|---------| +| 缓存命中率 | 语言列表缓存命中率 | < 90% | +| 查询时间 | 语言列表查询时间 | > 200ms | +| 新增时间 | 语言新增时间 | > 1000ms | +| 修改时间 | 语言修改时间 | > 1000ms | +| 删除时间 | 语言删除时间 | > 1000ms | +| 错误率 | 语言管理接口错误率 | > 5% | + +### 日志监控 +1. **操作日志**:记录所有语言管理操作 +2. **错误日志**:记录所有语言管理错误 +3. **性能日志**:记录语言管理接口性能指标 +4. **日志分析**:定期分析日志,发现问题 + +## 相关文档 +- [需求文档](../requirements/2026-01-21-002-08-语言管理需求.md) +- [架构决策记录](../decisions/adr/2026-01-26-008-ADR-语言管理架构决策.md) +- [SQL 脚本](../sql/2026-01-26-008-语言管理.sql) +- [提示词文档](../prompts/2026-01-26-008-prompt-语言管理功能实现.md) diff --git a/datai-scenes/datai-scene-salesforce/docs/index.md b/datai-scenes/datai-scene-salesforce/docs/index.md index be807195..bdf2ff10 100644 --- a/datai-scenes/datai-scene-salesforce/docs/index.md +++ b/datai-scenes/datai-scene-salesforce/docs/index.md @@ -84,6 +84,7 @@ - [2026-01-21-002-05-货币格式化设计.md](design/2026-01-21-002-05-货币格式化设计.md) - 货币格式化设计 [进行中] - [2026-01-21-002-06-日期格式化设计.md](design/2026-01-21-002-06-日期格式化设计.md) - 日期格式化设计 [进行中] - [2026-01-21-002-07-数字格式化设计.md](design/2026-01-21-002-07-数字格式化设计.md) - 数字格式化设计 [进行中] + - [2026-01-21-002-08-语言管理设计.md](design/2026-01-21-002-08-语言管理设计.md) - 语言管理设计 [进行中] - [0000-template.md](design/0000-template.md) - 设计文档模板 ### 3. 架构决策 @@ -133,6 +134,7 @@ - [2026-01-25-002-05-ADR-货币格式化技术选型.md](decisions/adr/2026-01-25-002-05-ADR-货币格式化技术选型.md) - 货币格式化技术选型架构决策 [Draft] - [2026-01-25-002-06-ADR-日期格式化技术选型.md](decisions/adr/2026-01-25-002-06-ADR-日期格式化技术选型.md) - 日期格式化技术选型架构决策 [Draft] - [2026-01-25-002-07-ADR-数字格式化技术选型.md](decisions/adr/2026-01-25-002-07-ADR-数字格式化技术选型.md) - 数字格式化技术选型架构决策 [已接受] + - [2026-01-26-008-ADR-语言管理技术选型.md](decisions/adr/2026-01-26-008-ADR-语言管理技术选型.md) - 语言管理技术选型架构决策 [已接受] - [0000-template.md](decisions/adr/0000-template.md) - ADR文档模板 ### 4. 提示词库 @@ -340,7 +342,25 @@ - [2026-01-25-002-07-changelog.md](changelog/2026-01-25-002-07-changelog.md) - 数字格式化功能实现 - [0000-template.md](changelog/0000-template.md) - 变更记录模板 -### 8. 接口文档 +### 8. SQL 脚本 + +- **目录**: [sql/](sql/) +- **描述**: 包含数据库表结构创建和变更的 SQL 脚本 +- **SQL 脚本**: + - [0001-salesforce-cdc-realtime-sync.sql](sql/0001-salesforce-cdc-realtime-sync.sql) - Salesforce CDC实时同步 + - [2026-01-21-001-sys_datasource_config.sql](sql/2026-01-21-001-sys_datasource_config.sql) - 动态数据源延迟加载 + - [2026-01-24-002-datai_config_environment_datasourceId.sql](sql/2026-01-24-002-datai_config_environment_datasourceId.sql) - 环境从库初始化 + - [2026-01-24-003-从库数据源注解实现.sql](sql/2026-01-24-003-从库数据源注解实现.sql) - 从库数据源注解实现 + - [2026-01-25-002-02-sys_user_lang_code.sql](sql/2026-01-25-002-02-sys_user_lang_code.sql) - 后端国际化 + - [2026-01-25-002-03-数据库国际化.sql](sql/2026-01-25-002-03-数据库国际化.sql) - 数据库国际化 + - [2026-01-25-002-04-timezone-internationalization.sql](sql/2026-01-25-002-04-timezone-internationalization.sql) - 时区国际化 + - [2026-01-25-002-05-货币格式化.sql](sql/2026-01-25-002-05-货币格式化.sql) - 货币格式化 + - [2026-01-25-002-06-日期格式化.sql](sql/2026-01-25-002-06-日期格式化.sql) - 日期格式化 + - [2026-01-25-002-07-数字格式化.sql](sql/2026-01-25-002-07-数字格式化.sql) - 数字格式化 + - [2026-01-26-008-语言管理.sql](sql/2026-01-26-008-语言管理.sql) - 语言管理 + - [国际化功能综合执行.sql](sql/国际化功能综合执行.sql) - 国际化功能综合执行 + +### 9. 接口文档 - **目录**: [api-docs/](api-docs/) - **描述**: 包含提供给前端调用的接口文档和定时任务文档 diff --git a/datai-scenes/datai-scene-salesforce/docs/requirements/2026-01-21-002-08-语言管理需求.md b/datai-scenes/datai-scene-salesforce/docs/requirements/2026-01-21-002-08-语言管理需求.md index ad0b82aa..765a3740 100644 --- a/datai-scenes/datai-scene-salesforce/docs/requirements/2026-01-21-002-08-语言管理需求.md +++ b/datai-scenes/datai-scene-salesforce/docs/requirements/2026-01-21-002-08-语言管理需求.md @@ -7,6 +7,7 @@ - 状态:进行中 - 优先级:中 - 父需求:2026-01-21-002-项目国际化需求 +- 最后更新:2026-01-26 ## 需求概述 提供语言管理功能,支持添加、编辑、删除语言,支持设置系统默认语言,支持启用/停用语言。 @@ -72,83 +73,190 @@ 2. 支持按语言代码搜索 3. 支持按语言名称搜索 4. 支持按状态筛选 - 5. 支持分页查询 - 6. 支持排序 + 5. 支持分页查询(使用 PageHelper 分页插件) + 6. 支持排序(按 sort_order 升序) + 7. 使用 Redis 缓存语言列表,TTL 为 24 小时 + 8. 语言列表查询时间 < 100ms + 9. 使用 @PreAuthorize 注解进行权限控制(system:language:list) + 10. 使用 Swagger/OpenAPI 文档 - **优先级**:高 -- **依赖关系**:依赖语言表 +- **依赖关系**:依赖语言表、Redis 缓存 #### 功能 2:语言添加 - **描述**:提供语言添加功能,支持添加新语言 - **验收标准**: - 1. 支持输入语言代码(如:zh、en) - 2. 支持输入语言名称(如:中文、English) - 3. 支持输入语言英文名称(如:Chinese、English) - 4. 支持上传语言图标 - 5. 支持设置排序 - 6. 语言代码必须唯一 - 7. 添加成功后显示成功提示 + 1. 支持输入语言代码(如:zh、en),使用 @Validated 进行参数校验 + 2. 支持输入语言名称(如:中文、English),必填字段 + 3. 支持输入语言英文名称(如:Chinese、English),必填字段 + 4. 支持上传语言图标(可选) + 5. 支持设置排序(默认为 0) + 6. 语言代码必须唯一(数据库唯一索引) + 7. 添加成功后清除语言列表缓存 + 8. 添加成功后显示成功提示(使用 AjaxResult) + 9. 使用 @PreAuthorize 注解进行权限控制(system:language:add) + 10. 使用 @Log 注解记录操作日志(businessType = BusinessType.INSERT) + 11. 使用 Swagger/OpenAPI 文档 - **优先级**:高 -- **依赖关系**:依赖语言表 +- **依赖关系**:依赖语言表、Redis 缓存 #### 功能 3:语言编辑 - **描述**:提供语言编辑功能,支持编辑语言信息 - **验收标准**: - 1. 支持修改语言名称 - 2. 支持修改语言英文名称 - 3. 支持修改语言图标 + 1. 支持修改语言名称,使用 @Validated 进行参数校验 + 2. 支持修改语言英文名称,必填字段 + 3. 支持修改语言图标(可选) 4. 支持修改排序 - 5. 编辑成功后显示成功提示 + 5. 编辑成功后清除语言列表缓存 + 6. 编辑成功后显示成功提示(使用 AjaxResult) + 7. 使用 @PreAuthorize 注解进行权限控制(system:language:edit) + 8. 使用 @Log 注解记录操作日志(businessType = BusinessType.UPDATE) + 9. 使用 Swagger/OpenAPI 文档 - **优先级**:高 -- **依赖关系**:依赖语言表 +- **依赖关系**:依赖语言表、Redis 缓存 #### 功能 4:语言删除 - **描述**:提供语言删除功能,支持删除语言 - **验收标准**: - 1. 删除前检查语言是否被使用 - 2. 如果语言被使用,提示无法删除 + 1. 删除前检查语言是否被使用(检查国际化资源表) + 2. 如果语言被使用,提示无法删除(使用 ServiceException) 3. 如果语言未被使用,允许删除 - 4. 删除成功后显示成功提示 - 5. 默认语言不能删除 + 4. 默认语言不能删除(业务规则校验) + 5. 删除成功后清除语言列表缓存 + 6. 删除成功后显示成功提示(使用 AjaxResult) + 7. 使用 @PreAuthorize 注解进行权限控制(system:language:remove) + 8. 使用 @Log 注解记录操作日志(businessType = BusinessType.DELETE) + 9. 使用 Swagger/OpenAPI 文档 + 10. 支持批量删除(传入语言 ID 数组) - **优先级**:高 -- **依赖关系**:依赖语言表 +- **依赖关系**:依赖语言表、国际化资源表、Redis 缓存 #### 功能 5:默认语言设置 - **描述**:提供默认语言设置功能,支持设置系统默认语言 - **验收标准**: 1. 支持设置系统默认语言 - 2. 只能有一个默认语言 - 3. 设置新默认语言时,取消原默认语言 - 4. 设置成功后显示成功提示 + 2. 只能有一个默认语言(数据库唯一索引) + 3. 设置新默认语言时,取消原默认语言(事务处理) + 4. 设置成功后清除默认语言缓存 + 5. 设置成功后显示成功提示(使用 AjaxResult) + 6. 使用 @PreAuthorize 注解进行权限控制(system:language:default) + 7. 使用 @Log 注解记录操作日志(businessType = BusinessType.UPDATE) + 8. 使用 Swagger/OpenAPI 文档 + 9. 默认语言缓存到 Redis,TTL 为 24 小时 - **优先级**:高 -- **依赖关系**:依赖语言表 +- **依赖关系**:依赖语言表、Redis 缓存 #### 功能 6:语言状态管理 - **描述**:提供语言状态管理功能,支持启用/停用语言 - **验收标准**: - 1. 支持启用语言 - 2. 支持停用语言 - 3. 默认语言不能停用 - 4. 状态变更成功后显示成功提示 + 1. 支持启用语言(status = '0') + 2. 支持停用语言(status = '1') + 3. 默认语言不能停用(业务规则校验) + 4. 状态变更成功后清除语言列表缓存 + 5. 状态变更成功后显示成功提示(使用 AjaxResult) + 6. 使用 @PreAuthorize 注解进行权限控制(system:language:status) + 7. 使用 @Log 注解记录操作日志(businessType = BusinessType.UPDATE) + 8. 使用 Swagger/OpenAPI 文档 - **优先级**:高 -- **依赖关系**:依赖语言表 +- **依赖关系**:依赖语言表、Redis 缓存 + +#### 功能 7:语言缓存刷新 +- **描述**:提供语言缓存刷新功能,支持手动刷新语言缓存 +- **验收标准**: + 1. 支持刷新语言列表缓存 + 2. 支持刷新默认语言缓存 + 3. 刷新成功后显示成功提示(使用 AjaxResult) + 4. 使用 @PreAuthorize 注解进行权限控制(system:language:refresh) + 5. 使用 @Log 注解记录操作日志(businessType = BusinessType.OTHER) + 6. 使用 Swagger/OpenAPI 文档 +- **优先级**:中 +- **依赖关系**:依赖 Redis 缓存 ## 非功能需求 ### 性能需求 -- **查询时间**:语言列表查询时间 < 100ms +- **查询时间**:语言列表查询时间 < 100ms(使用 Redis 缓存) - **添加时间**:语言添加时间 < 500ms - **编辑时间**:语言编辑时间 < 500ms - **删除时间**:语言删除时间 < 500ms +- **缓存命中率**:语言列表缓存命中率 ≥ 95% +- **并发支持**:支持 100+ 并发请求(使用 Redis 缓存) ### 安全需求 -- **认证方式**:使用现有的 Spring Security 认证机制 -- **授权机制**:只有管理员权限才能管理语言 -- **数据安全**:语言数据加密存储 -- **审计日志**:记录语言变更日志 +- **认证方式**:使用现有的 Spring Security + JWT 认证机制 +- **授权机制**:使用 @PreAuthorize 注解进行细粒度权限控制 + - system:language:list - 查看语言列表 + - system:language:add - 添加语言 + - system:language:edit - 编辑语言 + - system:language:remove - 删除语言 + - system:language:default - 设置默认语言 + - system:language:status - 启用/停用语言 + - system:language:refresh - 刷新语言缓存 +- **数据安全**:语言数据使用 MySQL 存储,支持事务一致性 +- **审计日志**:使用 @Log 注解记录语言变更日志(添加、编辑、删除、状态变更、默认语言设置) +- **XSS 防护**:使用全局 XSS 过滤器,防止 XSS 攻击 +- **防重提交**:使用 Redis 防重提交机制(@RepeatSubmit 注解) ### 可维护性需求 - **代码可读性**:代码符合项目编码规范,注释完整 - **测试覆盖率**:单元测试覆盖率 ≥ 80% +- **日志记录**:使用 Slf4j 记录关键操作日志 +- **异常处理**:使用全局异常处理器(GlobalExceptionHandler)统一处理异常 +- **API 文档**:使用 Swagger/OpenAPI 3.0 生成 API 文档 + +### 缓存策略 +- **缓存类型**:使用 Redis 缓存(spring.cache.type = redis) +- **缓存键设计**: + - 语言列表缓存:sys_language:list + - 默认语言缓存:sys_language:default +- **缓存 TTL**:24 小时(86400 秒) +- **缓存更新策略**: + - 添加语言后清除语言列表缓存 + - 编辑语言后清除语言列表缓存 + - 删除语言后清除语言列表缓存 + - 设置默认语言后清除默认语言缓存 + - 启用/停用语言后清除语言列表缓存 + - 支持手动刷新缓存(system:language:refresh) +- **缓存一致性**:使用事务确保数据库和缓存的一致性 + +### API 设计需求 +- **RESTful 风格**:遵循 RESTful API 设计规范 +- **统一响应格式**:使用 AjaxResult 统一响应格式 + ```json + { + "code": 200, + "msg": "操作成功", + "data": {} + } + ``` +- **分页查询**:使用 PageHelper 分页插件,返回 TableDataInfo + ```json + { + "total": 100, + "rows": [], + "code": 200, + "msg": "查询成功" + } + ``` +- **参数校验**:使用 @Validated 注解进行参数校验 +- **错误码规范**:使用项目统一的错误码规范 +- **API 版本控制**:使用 URL 路径版本控制(如:/api/v1/system/language) + +### 数据验证需求 +- **参数校验**:使用 Spring Validation 进行参数校验 + - @NotNull:必填字段 + - @NotBlank:字符串必填且非空 + - @Size:字符串长度限制 + - @Pattern:正则表达式校验 +- **业务规则校验**: + - 语言代码唯一性校验 + - 默认语言唯一性校验 + - 默认语言不能删除校验 + - 默认语言不能停用校验 + - 语言使用检查(删除前检查) +- **数据库约束**: + - 主键约束:id + - 唯一索引:lang_code、is_default + - 非空约束:lang_code、lang_name、lang_name_en、status ## 数据需求 @@ -157,17 +265,17 @@ #### sys_language(语言表) ``` sys_language (语言表) -├─ id (BIGINT) - 主键ID -├─ lang_code (VARCHAR) - 语言代码(如:zh、en) -├─ lang_name (VARCHAR) - 语言名称(如:中文、English) -├─ lang_name_en (VARCHAR) - 语言英文名称(如:Chinese、English) -├─ lang_flag (VARCHAR) - 语言图标 -├─ is_default (CHAR) - 是否默认语言(0否 1是) -├─ status (CHAR) - 状态(0正常 1停用) -├─ sort_order (INT) - 排序 -├─ create_by (VARCHAR) - 创建者 +├─ id (BIGINT) - 主键ID,自增 +├─ lang_code (VARCHAR(10)) - 语言代码(如:zh、en),唯一索引 +├─ lang_name (VARCHAR(50)) - 语言名称(如:中文、English),非空 +├─ lang_name_en (VARCHAR(50)) - 语言英文名称(如:Chinese、English),非空 +├─ lang_flag (VARCHAR(255)) - 语言图标(URL 或 Base64),可选 +├─ is_default (CHAR(1)) - 是否默认语言(0否 1是),唯一索引 +├─ status (CHAR(1)) - 状态(0正常 1停用),非空 +├─ sort_order (INT) - 排序,默认为 0 +├─ create_by (VARCHAR(64)) - 创建者 ├─ create_time (DATETIME) - 创建时间 -├─ update_by (VARCHAR) - 更新者 +├─ update_by (VARCHAR(64)) - 更新者 └─ update_time (DATETIME) - 更新时间 ``` @@ -175,49 +283,173 @@ sys_language (语言表) - **数据库类型**:MySQL 8.3.0 - **存储容量**:单表支持 1000 万+ 数据 - **数据备份策略**:每日备份,保留 7 天 +- **字符集**:utf8mb4,支持 Unicode 字符 +- **排序规则**:utf8mb4_general_ci ### 数据流转需求 ``` 语言管理 └─ 管理员添加/编辑/删除语言 - └─ 更新数据库中的语言数据 - └─ 刷新语言缓存 + └─ 更新数据库中的语言数据(使用 MyBatis Plus) + └─ 清除语言列表缓存(使用 CacheUtils) + └─ 记录操作日志(使用 @Log 注解) + └─ 返回操作结果(使用 AjaxResult) +``` + +### 缓存数据结构 +``` +语言列表缓存(sys_language:list) +└─ List + ├─ id + ├─ langCode + ├─ langName + ├─ langNameEn + ├─ langFlag + ├─ isDefault + ├─ status + └─ sortOrder + +默认语言缓存(sys_language:default) +└─ SysLanguage + ├─ id + ├─ langCode + ├─ langName + ├─ langNameEn + ├─ langFlag + ├─ isDefault + ├─ status + └─ sortOrder +``` + +### API 接口设计 +``` +语言管理 API +├─ GET /system/language/list - 查询语言列表(分页) +├─ GET /system/language/{id} - 获取语言详细信息 +├─ POST /system/language - 添加语言 +├─ PUT /system/language - 编辑语言 +├─ DELETE /system/language/{ids} - 删除语言(支持批量) +├─ PUT /system/language/default/{id} - 设置默认语言 +├─ PUT /system/language/status - 启用/停用语言 +└─ DELETE /system/language/cache - 刷新语言缓存 +``` + +### 数据验证规则 +``` +语言代码(lang_code) +├─ 必填:是 +├─ 唯一:是 +├─ 长度:1-10 个字符 +├─ 格式:小写字母,可选下划线(如:zh、en、zh_CN、en_US) +└─ 正则:^[a-z]{1,2}(_[A-Z]{2})?$ + +语言名称(lang_name) +├─ 必填:是 +├─ 长度:1-50 个字符 +└─ 格式:支持 Unicode 字符 + +语言英文名称(lang_name_en) +├─ 必填:是 +├─ 长度:1-50 个字符 +└─ 格式:支持 Unicode 字符 + +语言图标(lang_flag) +├─ 必填:否 +├─ 长度:0-255 个字符 +└─ 格式:URL 或 Base64 编码 + +是否默认语言(is_default) +├─ 必填:是 +├─ 值域:0(否)、1(是) +└─ 唯一:是 + +状态(status) +├─ 必填:是 +├─ 值域:0(正常)、1(停用) +└─ 默认值:0 + +排序(sort_order) +├─ 必填:否 +├─ 类型:整数 +└─ 默认值:0 ``` ## 业务规则 -1. **语言代码唯一性**:语言代码(lang_code)必须唯一 -2. **默认语言唯一性**:只能有一个默认语言 -3. **默认语言保护**:默认语言不能删除、不能停用 -4. **语言使用检查**:删除语言前检查是否被使用 -5. **语言管理权限**:只有管理员权限才能管理语言 +1. **语言代码唯一性**:语言代码(lang_code)必须唯一,使用数据库唯一索引保证 +2. **默认语言唯一性**:只能有一个默认语言,使用数据库唯一索引保证 +3. **默认语言保护**:默认语言不能删除、不能停用,业务层进行校验 +4. **语言使用检查**:删除语言前检查是否被使用(检查国际化资源表),如果被使用则不允许删除 +5. **语言管理权限**:只有具有相应权限的用户才能管理语言(system:language:*) +6. **缓存一致性**:语言数据变更后必须清除相关缓存,确保数据一致性 +7. **事务一致性**:设置默认语言时,使用事务确保原默认语言取消和新默认语言设置的原子性 +8. **状态控制**:停用的语言不能被设置为默认语言 +9. **排序规则**:语言列表按 sort_order 升序排序,sort_order 相同的按 id 升序排序 +10. **软删除**:语言删除为物理删除,删除前检查使用情况 ## 技术约束 1. **Spring Boot 版本**:3.5.7 2. **Java 版本**:21 3. **数据库**:MySQL 8.3.0 -4. **ORM 框架**:MyBatis 3.5.16 -5. **必须使用现有的认证授权机制**:不能引入新的认证方式 +4. **ORM 框架**:MyBatis Plus 3.5.16(使用 MyBatis Plus 简化 CRUD 操作) +5. **缓存框架**:Redis(使用 Spring Cache 抽象层) +6. **认证授权**:Spring Security + JWT(使用现有的认证授权机制) +7. **API 文档**:Swagger/OpenAPI 3.0(使用 SpringDoc) +8. **参数校验**:Spring Validation(使用 @Validated 注解) +9. **分页插件**:PageHelper(使用 PageHelper 分页插件) +10. **日志框架**:Slf4j + Logback +11. **工具库**: + - Hutool:工具类库 + - Apache Commons Lang:字符串处理 + - Apache Commons Collections:集合处理 +12. **必须使用现有的认证授权机制**:不能引入新的认证方式 +13. **必须使用现有的缓存工具类**:使用 CacheUtils 进行缓存操作 +14. **必须使用现有的统一响应格式**:使用 AjaxResult 统一响应格式 +15. **必须使用现有的日志注解**:使用 @Log 注解记录操作日志 ## 成功标准 -1. 支持添加新语言 -2. 支持编辑语言信息 -3. 支持删除语言 -4. 支持设置系统默认语言 -5. 支持启用/停用语言 -6. 语言列表查询时间 < 100ms -7. 单元测试覆盖率 ≥ 80% +1. 支持添加新语言,添加成功后清除缓存并记录日志 +2. 支持编辑语言信息,编辑成功后清除缓存并记录日志 +3. 支持删除语言,删除前检查使用情况,删除成功后清除缓存并记录日志 +4. 支持设置系统默认语言,设置成功后清除缓存并记录日志 +5. 支持启用/停用语言,状态变更成功后清除缓存并记录日志 +6. 支持刷新语言缓存,刷新成功后记录日志 +7. 语言列表查询时间 < 100ms(使用 Redis 缓存) +8. 语言列表缓存命中率 ≥ 95% +9. 支持 100+ 并发请求 +10. 单元测试覆盖率 ≥ 80% +11. 所有 API 接口都有完整的 Swagger/OpenAPI 文档 +12. 所有操作都有完整的审计日志 +13. 所有参数都有完整的校验(参数校验 + 业务规则校验) +14. 所有缓存操作都保证数据一致性 +15. 所有异常都有统一的错误处理 ## 风险评估 | 风险 | 影响程度 | 发生概率 | 缓解措施 | | ---- | ------ | ------ | ------ | -| 删除正在使用的语言导致系统异常 | 高 | 低 | 删除前检查语言是否被使用 | -| 默认语言被删除导致系统异常 | 高 | 低 | 默认语言不能删除 | -| 语言数据不一致导致显示错误 | 中 | 低 | 实现数据一致性校验机制 | +| 删除正在使用的语言导致系统异常 | 高 | 低 | 删除前检查语言是否被使用(检查国际化资源表),如果被使用则不允许删除 | +| 默认语言被删除导致系统异常 | 高 | 低 | 默认语言不能删除,业务层进行校验,抛出 ServiceException | +| 默认语言被停用导致系统异常 | 高 | 低 | 默认语言不能停用,业务层进行校验,抛出 ServiceException | +| 语言数据不一致导致显示错误 | 中 | 低 | 使用事务确保数据库和缓存的一致性,使用数据库唯一索引保证数据唯一性 | +| 缓存失效导致性能下降 | 中 | 中 | 使用 Redis 缓存,TTL 为 24 小时,支持手动刷新缓存,监控缓存命中率 | +| 并发操作导致数据不一致 | 中 | 低 | 使用数据库事务和唯一索引保证数据一致性,使用 Redis 缓存提高并发性能 | +| 权限控制不当导致越权操作 | 高 | 低 | 使用 @PreAuthorize 注解进行细粒度权限控制,所有接口都需要权限校验 | +| 参数校验不完整导致非法数据 | 中 | 中 | 使用 @Validated 注解进行参数校验,使用业务规则校验,使用数据库约束保证数据完整性 | +| 缓存雪崩导致系统崩溃 | 高 | 低 | 使用 Redis 缓存,设置合理的 TTL,支持手动刷新缓存,监控缓存状态 | +| 缓存穿透导致数据库压力增大 | 中 | 低 | 使用布隆过滤器(可选),缓存空值,监控缓存命中率 | ## 依赖关系 -- 依赖语言表 -- 依赖现有的 MyBatis 框架 -- 依赖现有的认证授权机制 +- 依赖语言表(sys_language) +- 依赖国际化资源表(sys_i18n_resource)- 用于检查语言是否被使用 +- 依赖现有的 MyBatis Plus 框架 +- 依赖现有的 Redis 缓存(CacheUtils) +- 依赖现有的认证授权机制(Spring Security + JWT) +- 依赖现有的统一响应格式(AjaxResult) +- 依赖现有的日志注解(@Log) +- 依赖现有的全局异常处理器(GlobalExceptionHandler) +- 依赖现有的 XSS 过滤器 +- 依赖现有的防重提交机制(@RepeatSubmit) +- 依赖现有的 PageHelper 分页插件 +- 依赖现有的 Swagger/OpenAPI 文档框架(SpringDoc) ## 相关文档 - [父需求](./2026-01-21-002-项目国际化需求.md) diff --git a/datai-scenes/datai-scene-salesforce/pom.xml b/datai-scenes/datai-scene-salesforce/pom.xml index b12988d1..caead675 100644 --- a/datai-scenes/datai-scene-salesforce/pom.xml +++ b/datai-scenes/datai-scene-salesforce/pom.xml @@ -22,6 +22,7 @@ datai-salesforce-auth datai-salesforce-integration datai-salesforce-metadata + datai-salesforce-ai @@ -51,6 +52,11 @@ datai-salesforce-metadata ${datai.version} + + com.datai + datai-salesforce-ai + ${datai.version} +