feat:提交ai模块

This commit is contained in:
Kris 2026-01-26 10:19:48 +08:00
parent dc885151a8
commit 26c55685e6
7 changed files with 1496 additions and 68 deletions

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.datai</groupId>
<artifactId>datai-scene-salesforce</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>datai-salesforce-ai</artifactId>
<properties>
<maven.compiler.source>22</maven.compiler.source>
<maven.compiler.target>22</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -38,6 +38,10 @@
<groupId>com.datai</groupId>
<artifactId>datai-salesforce-metadata</artifactId>
</dependency>
<dependency>
<groupId>com.datai</groupId>
<artifactId>datai-salesforce-ai</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -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 注解记录操作日志。
## 决策
### 决策 1ORM 框架选择
**选定方案**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<SysLanguage>` 接口,使用 MyBatis Plus 提供的通用方法
- 继承 `ServiceImpl<LanguageMapper, SysLanguage>` 类,使用 MyBatis Plus 提供的通用实现
- 使用 `LambdaQueryWrapper``LambdaUpdateWrapper` 进行条件查询和更新
**放弃方案的原因**
**方案 AMyBatis**
- **放弃原因**
- 需要手动编写 XML 映射文件,开发成本高
- 需要手动编写 CRUD 方法,代码重复
- 不支持条件构造器,代码不够简洁
- 不提供分页插件,需要手动实现分页
- 与若依框架集成度低,框架一致性差
**方案 BJPA/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 注解确保数据库和缓存的一致性
**放弃方案的原因**
**方案 ACaffeine 本地缓存**
- **放弃原因**
- 本地缓存无法在分布式环境下共享,多实例数据不一致
- 需要引入额外依赖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 表达式,无法进行复杂的权限判断
- 与若依框架集成度低,框架一致性差
- 权限校验逻辑分散,难以统一管理
**方案 BAOP 切面**
- **放弃原因**
- 需要手动编写切面逻辑,开发成本高
- 需要手动解析权限标识,代码复杂
- 不支持权限缓存,性能较差
- 与若依框架集成度低,框架一致性差
- 权限校验逻辑分散,难以统一管理
### 决策 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)` 注解记录其他操作
**放弃方案的原因**
**方案 AAOP 切面**
- **放弃原因**
- 需要手动编写切面逻辑,开发成本高
- 需要手动解析操作类型,代码复杂
- 与若依框架集成度低,框架一致性差
- 日志记录逻辑分散,难以统一管理
**方案 B手动记录**
- **放弃原因**
- 需要手动编写日志记录逻辑,代码重复
- 容易遗漏日志记录,导致审计日志不完整
- 日志记录逻辑分散,难以统一管理
- 维护成本高,修改日志记录逻辑需要修改多处代码
### 决策 6API 文档方式选择
**选定方案**Swagger/OpenAPI 3.0SpringDoc
**选择理由**
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()` 方法返回分页数据
**放弃方案的原因**
**方案 AMyBatis 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 架构师
- **审核人**:技术负责人

View File

@ -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<SysLanguage> {
/**
* 查询语言列表
*
* @param language 语言信息
* @return 语言列表
*/
List<SysLanguage> 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<SysLanguage> 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<SysLanguage> | 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)

View File

@ -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/)
- **描述**: 包含提供给前端调用的接口文档和定时任务文档

View File

@ -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. 默认语言缓存到 RedisTTL 为 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<SysLanguage>
├─ 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)

View File

@ -22,6 +22,7 @@
<module>datai-salesforce-auth</module>
<module>datai-salesforce-integration</module>
<module>datai-salesforce-metadata</module>
<module>datai-salesforce-ai</module>
</modules>
<dependencyManagement>
@ -51,6 +52,11 @@
<artifactId>datai-salesforce-metadata</artifactId>
<version>${datai.version}</version>
</dependency>
<dependency>
<groupId>com.datai</groupId>
<artifactId>datai-salesforce-ai</artifactId>
<version>${datai.version}</version>
</dependency>
</dependencies>
</dependencyManagement>