Compare commits
7 Commits
9cb77b096e
...
6e6419c116
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e6419c116 | |||
| bcee31495c | |||
| 2fd93463b8 | |||
| 56d4fe5b84 | |||
| e94e5398eb | |||
| 4076097185 | |||
| cdad9edf57 |
232
AGENTS.md
232
AGENTS.md
@@ -2,22 +2,44 @@
|
||||
|
||||
## 项目概述
|
||||
|
||||
基于若依 v3.9.1 的纪检初核系统,Java 21 + Spring Boot 3 + Vue 2
|
||||
本仓库是纪检初核系统主仓库,基于若依 `v3.9.1`,当前技术栈以 `Java 21 + Spring Boot 3 + Vue 2` 为主,并包含独立的流水分析 Mock 服务、Docker 部署文件、SQL 脚本、实施文档与测试文档。
|
||||
|
||||
仓库同时承载以下内容:
|
||||
|
||||
- Java 多模块后端工程
|
||||
- `ruoyi-ui` 前端工程
|
||||
- `lsfx-mock-server` Python FastAPI Mock 服务
|
||||
- `docs/` 正式文档目录
|
||||
- `assets/` 历史设计、测试、接口和实施材料
|
||||
- `sql/` 初始化与增量脚本
|
||||
|
||||
---
|
||||
|
||||
## Build / Lint / Test Commands
|
||||
## 协作约定
|
||||
|
||||
- 使用简体中文进行思考和对话
|
||||
- Git 提交说明使用中文
|
||||
- 根据设计文档产出实施计划时,默认输出两份文档:
|
||||
- 后端实施计划放 `docs/plans/backend/`
|
||||
- 前端实施计划放 `docs/plans/frontend/`
|
||||
- 前端开发直接在当前分支进行,不需要额外创建 git worktree
|
||||
- 测试结束后,自动关闭测试过程中启动的前后端进程
|
||||
- 遇到 MCP 数据库操作时,使用项目配置文件中的数据库连接信息
|
||||
|
||||
---
|
||||
|
||||
## Build / Run / Test Commands
|
||||
|
||||
### 后端 (Maven)
|
||||
|
||||
```bash
|
||||
# 编译项目
|
||||
# 根目录编译全部 Java 模块
|
||||
mvn clean compile
|
||||
|
||||
# 运行应用
|
||||
mvn spring-boot:run
|
||||
# 启动主应用
|
||||
mvn -pl ruoyi-admin spring-boot:run
|
||||
|
||||
# 打包部署
|
||||
# 打包全部模块
|
||||
mvn clean package
|
||||
|
||||
# 运行单个测试类
|
||||
@@ -26,7 +48,7 @@ mvn test -Dtest=ClassName
|
||||
# 运行单个测试方法
|
||||
mvn test -Dtest=ClassName#methodName
|
||||
|
||||
# 跳过测试
|
||||
# 跳过测试打包
|
||||
mvn clean package -DskipTests
|
||||
```
|
||||
|
||||
@@ -38,21 +60,45 @@ cd ruoyi-ui
|
||||
# 安装依赖
|
||||
npm install --registry=https://registry.npmmirror.com
|
||||
|
||||
# 开发服务器
|
||||
# 本地开发
|
||||
npm run dev
|
||||
|
||||
# 生产构建
|
||||
npm run build:prod
|
||||
|
||||
# 预览构建结果
|
||||
npm run preview
|
||||
```
|
||||
|
||||
### API 测试
|
||||
### 流水分析 Mock 服务 (Python / FastAPI)
|
||||
|
||||
```bash
|
||||
# 获取 Token (测试账号: admin/admin123)
|
||||
POST http://localhost:8080/login/test?username=admin&password=admin123
|
||||
cd lsfx-mock-server
|
||||
|
||||
# Swagger 文档
|
||||
http://localhost:8080/swagger-ui/index.html
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 启动服务
|
||||
python main.py
|
||||
|
||||
# 热重载启动
|
||||
uvicorn main:app --reload --host 0.0.0.0 --port 8000
|
||||
|
||||
# 运行测试
|
||||
pytest tests/ -v
|
||||
```
|
||||
|
||||
### API 调试
|
||||
|
||||
```bash
|
||||
# 测试登录(默认测试账号)
|
||||
POST http://localhost:62318/login/test?username=admin&password=admin123
|
||||
|
||||
# 主系统 Swagger
|
||||
http://localhost:62318/swagger-ui.html
|
||||
|
||||
# 流水分析 Mock Swagger
|
||||
http://localhost:8000/docs
|
||||
```
|
||||
|
||||
---
|
||||
@@ -61,10 +107,10 @@ http://localhost:8080/swagger-ui/index.html
|
||||
|
||||
### Java 代码风格
|
||||
|
||||
- **注解**: 使用 Lombok `@Data` 简化实体类
|
||||
- **依赖注入**: 使用 `@Resource` 而非 `@Autowired`
|
||||
- **实体类**: 不继承 BaseEntity,单独添加审计字段
|
||||
- **禁止**: 禁止使用全限定类名 (如 `java.util.List`),必须 import
|
||||
- 实体类优先使用 Lombok `@Data`
|
||||
- 依赖注入使用 `@Resource`,不要使用 `@Autowired`
|
||||
- 实体类不继承 `BaseEntity`,审计字段单独声明
|
||||
- 禁止使用全限定类名,必须通过 `import` 引入
|
||||
|
||||
```java
|
||||
@Data
|
||||
@@ -85,10 +131,13 @@ private ICcdiBaseStaffService baseStaffService;
|
||||
|
||||
### 分层规范
|
||||
|
||||
- **Controller**: 添加 Swagger 注释,分页使用 MyBatis Plus Page
|
||||
- **Service**: 简单 CRUD 用 MyBatis Plus,复杂操作在 XML 写 SQL
|
||||
- **DTO/VO**: 接口传参用独立 DTO,返回用独立 VO,禁止与 entity 混用
|
||||
- **禁止**: 禁止 `extends ServiceImpl<>`
|
||||
- `Controller` 添加 Swagger 注释
|
||||
- 分页查询优先使用 MyBatis Plus `Page`
|
||||
- 简单 CRUD 优先使用 MyBatis Plus
|
||||
- 复杂查询或批量逻辑放到 XML SQL
|
||||
- 接口入参使用独立 DTO,返回使用独立 VO
|
||||
- 禁止 DTO、VO 与 entity 混用
|
||||
- 禁止 `extends ServiceImpl<>`
|
||||
|
||||
### API 响应格式
|
||||
|
||||
@@ -107,43 +156,87 @@ return AjaxResult.success(result);
|
||||
|
||||
### 数据库规范
|
||||
|
||||
- 表名: `ccdi_` 前缀 (如 `ccdi_base_staff`)
|
||||
- 非业务字段 (create_by, create_time 等) 由后端自动处理,前端表单不显示
|
||||
- 业务表统一使用 `ccdi_` 前缀
|
||||
- 非业务字段如 `create_by`、`create_time` 由后端自动维护
|
||||
- 前端表单不要暴露通用审计字段
|
||||
- 新增菜单、字典、初始化数据时,同步补充 SQL 脚本
|
||||
|
||||
### 前端规范
|
||||
|
||||
- **目录结构**: `views/` 按功能模块组织,`api/` 对应后端 Controller
|
||||
- **API 调用**: 使用 `@/utils/request` 封装
|
||||
- **菜单联动**: 添加页面后需同步修改数据库 `sys_menu` 表
|
||||
- 页面放在 `ruoyi-ui/src/views/` 下,按业务域组织
|
||||
- API 文件放在 `ruoyi-ui/src/api/` 下,与后端 Controller 对应
|
||||
- 请求统一使用 `@/utils/request`
|
||||
- 新增页面或功能入口时,同步检查 `sys_menu`、路由、权限标识
|
||||
- 优先延续现有 `ccdi*` 业务目录与命名方式,不随意新造平行目录
|
||||
|
||||
### 导入功能规范
|
||||
|
||||
- 批量操作提高性能
|
||||
- 返回结果只展示失败数据,不展示成功数据
|
||||
- 使用 EasyExcel + 异步处理大数据量导入
|
||||
- 大批量导入优先考虑批量写入
|
||||
- 返回结果仅展示失败数据
|
||||
- 大数据量导入优先采用 EasyExcel + 异步处理
|
||||
|
||||
---
|
||||
|
||||
## 模块架构
|
||||
## 当前仓库结构
|
||||
|
||||
```
|
||||
```text
|
||||
ccdi/
|
||||
├── ruoyi-admin/ # 启动入口
|
||||
├── ruoyi-framework/ # 安全配置
|
||||
├── ruoyi-system/ # 系统模块
|
||||
├── ruoyi-common/ # 通用工具
|
||||
├── ccdi-info-collection/ # 信息采集 (员工、中介、黑名单)
|
||||
├── ccdi-project/ # 项目管理
|
||||
├── ccdi-lsfx/ # 流水分析对接
|
||||
└── ruoyi-ui/ # 前端
|
||||
├── ruoyi-admin/ # Spring Boot 启动入口与 Web 层装配
|
||||
├── ruoyi-framework/ # 安全、权限、配置等基础框架
|
||||
├── ruoyi-system/ # 系统管理模块
|
||||
├── ruoyi-common/ # 通用组件、工具类、基础能力
|
||||
├── ruoyi-quartz/ # 定时任务模块
|
||||
├── ruoyi-generator/ # 代码生成模块
|
||||
├── ccdi-info-collection/ # 信息采集模块(员工、中介、黑名单等)
|
||||
├── ccdi-project/ # 项目管理与项目业务模块
|
||||
├── ccdi-lsfx/ # 流水分析对接模块
|
||||
├── ruoyi-ui/ # Vue 2 前端
|
||||
├── lsfx-mock-server/ # 流水分析平台 Mock 服务(FastAPI)
|
||||
├── docs/ # 正式设计、计划、测试、报告
|
||||
├── assets/ # 历史设计稿、接口材料、测试资料、实施材料
|
||||
├── sql/ # 建表、菜单、字典、修复、迁移脚本
|
||||
├── docker/ # 后端、前端、Mock 服务容器文件
|
||||
├── deploy/ # 部署相关文件
|
||||
├── bin/ # 仓库级辅助脚本目录
|
||||
├── scripts/ # 预留脚本目录(当前基本为空)
|
||||
├── logs/ # 运行日志输出目录
|
||||
└── .worktrees/ # 本地工作树目录
|
||||
```
|
||||
|
||||
### 添加新模块
|
||||
### Maven 模块
|
||||
|
||||
1. 根 pom.xml 添加 `<module>`
|
||||
2. pom.xml 添加 `ruoyi-common` 依赖
|
||||
3. `ruoyi-admin/pom.xml` 添加模块依赖
|
||||
4. 按分层创建 controller/service/mapper/domain 包
|
||||
根 `pom.xml` 当前包含以下 Java 模块:
|
||||
|
||||
1. `ruoyi-admin`
|
||||
2. `ruoyi-framework`
|
||||
3. `ruoyi-system`
|
||||
4. `ruoyi-quartz`
|
||||
5. `ruoyi-generator`
|
||||
6. `ruoyi-common`
|
||||
7. `ccdi-info-collection`
|
||||
8. `ccdi-project`
|
||||
9. `ccdi-lsfx`
|
||||
|
||||
### 主要业务代码分布
|
||||
|
||||
- `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/`
|
||||
- 含 `controller`、`domain`、`mapper`、`service`、`annotation`、`validation` 等目录
|
||||
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/`
|
||||
- 含 `config`、`controller`、`domain`、`mapper`、`service`
|
||||
- `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/`
|
||||
- 含 `client`、`config`、`constants`、`controller`、`domain/request`、`domain/response`
|
||||
- `ruoyi-ui/src/views/`
|
||||
- 当前包含 `ccdi`、`ccdiBaseStaff`、`ccdiProject`、`ccdiPurchaseTransaction`、`ccdiIntermediary`、亲属关系、员工调动、招聘等业务页面
|
||||
- `ruoyi-ui/src/api/ccdi/`
|
||||
- 放置纪检初核业务 API 封装
|
||||
|
||||
### 添加新后端模块时
|
||||
|
||||
1. 在根 `pom.xml` 增加 `<module>`
|
||||
2. 在新模块 `pom.xml` 中声明公共依赖,如 `ruoyi-common`
|
||||
3. 在 `ruoyi-admin/pom.xml` 中引入该业务模块
|
||||
4. 按 `controller/service/mapper/domain` 分层创建代码
|
||||
5. 补充对应 SQL、菜单、权限和前端 API/页面
|
||||
|
||||
---
|
||||
|
||||
@@ -154,12 +247,55 @@ ccdi/
|
||||
| 应用入口 | `ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java` |
|
||||
| 信息采集 Controller | `ccdi-info-collection/src/main/java/com/ruoyi/info/collection/controller/` |
|
||||
| 项目管理 Controller | `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/` |
|
||||
| 前端 API | `ruoyi-ui/src/api/` |
|
||||
| 流水分析对接 Controller | `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/controller/` |
|
||||
| 前端业务 API | `ruoyi-ui/src/api/ccdi/` |
|
||||
| 前端页面 | `ruoyi-ui/src/views/` |
|
||||
| Vue 路由 | `ruoyi-ui/src/router/index.js` |
|
||||
| Vuex | `ruoyi-ui/src/store/` |
|
||||
| Mock 服务入口 | `lsfx-mock-server/main.py` |
|
||||
| Mock 路由 | `lsfx-mock-server/routers/api.py` |
|
||||
| Docker 文件 | `docker/` |
|
||||
| SQL 脚本 | `sql/` |
|
||||
|
||||
---
|
||||
|
||||
## 沟通规范
|
||||
## 文档与资产规范
|
||||
|
||||
- 使用简体中文进行思考和对话
|
||||
- 遇到 MCP 数据库操作时,使用项目配置文件中的数据库
|
||||
### 正式文档目录
|
||||
|
||||
- `docs/design/`:设计文档与设计附属文件
|
||||
- `docs/plans/backend/`:后端实施计划
|
||||
- `docs/plans/frontend/`:前端实施计划
|
||||
- `docs/plans/fullstack/`:综合实施计划、联调计划、通用实施文档
|
||||
- `docs/plans/misc/`:其他计划类文档
|
||||
- `docs/tests/plans/`:测试计划
|
||||
- `docs/tests/records/`:测试记录
|
||||
- `docs/tests/scripts/`:测试脚本与脚本说明
|
||||
- `docs/reports/implementation/`:实施报告
|
||||
- `docs/reports/optimization/`:优化记录
|
||||
- `docs/reports/code-review/`:代码评审报告
|
||||
|
||||
### 历史资料目录
|
||||
|
||||
- `assets/design/`:历史设计材料
|
||||
- `assets/interface-doc/`、`assets/api-docs/`:接口资料
|
||||
- `assets/database/`、`assets/database-docs/`:数据库相关资料
|
||||
- `assets/test-reports/`、`assets/test-scripts/`、`assets/测试文档/`:测试资料
|
||||
- `assets/plans/`、`assets/implementation/`、`assets/实施文档/`:历史实施材料
|
||||
|
||||
### 文档维护要求
|
||||
|
||||
- 新增文档优先落到 `docs/` 下的规范目录,不要继续堆放到 `docs/plans/` 根目录
|
||||
- 只有历史资料或外部原始材料才放入 `assets/`
|
||||
- 如果移动了文档,需同步修正文档内引用路径
|
||||
- 若需求来自设计文档,默认同时沉淀后端与前端两份实施计划
|
||||
|
||||
---
|
||||
|
||||
## 开发与测试提醒
|
||||
|
||||
- `target/`、`node_modules/`、运行日志等目录默认视为构建产物,阅读时注意与源码区分
|
||||
- `lsfx-mock-server` 是独立子项目,除非任务涉及流水分析联调,否则不要把其实现规则混入主 Java 工程
|
||||
- `docker/backend`、`docker/frontend`、`docker/mock` 分别对应三类运行时镜像
|
||||
- `sql/migration/` 用于增量迁移脚本,新增修复脚本优先按日期或功能命名
|
||||
- 启动前后端或 Mock 服务做验证后,结束测试时要主动停止进程,避免残留占用端口
|
||||
|
||||
@@ -502,4 +502,4 @@ head -20 doc/database/backup/ccdi_structure.sql
|
||||
- 表结构文件: `doc/database/backup/ccdi_structure.sql`
|
||||
- 数据文件: `doc/database/backup/ccdi_data.sql`
|
||||
- 排序规则修改脚本: `doc/database/alter_collation_to_general_ci.sql`
|
||||
- 设计文档: `docs/plans/2026-02-28-database-migration-design.md`
|
||||
- 设计文档: `docs/design/2026-02-28-database-migration-design.md`
|
||||
|
||||
@@ -266,7 +266,7 @@ d122e52 config(lsfx): 删除接口5、6配置,更新接口7路径
|
||||
## 参考资料
|
||||
|
||||
- **新版接口文档**: `doc/对接流水分析/兰溪-流水分析对接-新版.md`
|
||||
- **实施计划**: `docs/plans/2026-03-02-lsfx-update-plan.md`
|
||||
- **实施计划**: `docs/plans/fullstack/2026-03-02-lsfx-update-plan.md`
|
||||
- **项目规范**: `CLAUDE.md`
|
||||
|
||||
---
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.ruoyi.common.utils.SecurityUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
@@ -18,6 +19,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
* 项目流水标签控制器
|
||||
*/
|
||||
@Tag(name = "项目流水标签")
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/ccdi/project/tags")
|
||||
public class CcdiBankTagController extends BaseController {
|
||||
@@ -32,6 +34,8 @@ public class CcdiBankTagController extends BaseController {
|
||||
@PostMapping("/rebuild")
|
||||
public AjaxResult rebuild(@Validated @RequestBody CcdiBankTagRebuildDTO dto) {
|
||||
String operator = SecurityUtils.getUsername();
|
||||
log.info("【流水标签】收到手动重算请求: projectId={}, modelCode={}, operator={}",
|
||||
dto.getProjectId(), dto.getModelCode(), operator);
|
||||
return success(bankTagService.submitRebuild(dto, operator));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,13 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 流水标签规则执行参数解析器
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class BankTagRuleConfigResolver {
|
||||
|
||||
@@ -61,11 +64,23 @@ public class BankTagRuleConfigResolver {
|
||||
|
||||
Map<String, String> thresholdValues = new LinkedHashMap<>();
|
||||
Set<String> requiredParamCodes = RULE_PARAM_MAPPING.getOrDefault(ruleMeta.getRuleCode(), Set.of());
|
||||
log.info("【流水标签】解析规则参数: projectId={}, effectiveProjectId={}, ruleCode={}, requiredParams={}",
|
||||
projectId, effectiveProjectId, ruleMeta.getRuleCode(), requiredParamCodes);
|
||||
for (CcdiModelParam param : params) {
|
||||
if (requiredParamCodes.contains(param.getParamCode())) {
|
||||
thresholdValues.put(param.getParamCode(), param.getParamValue());
|
||||
}
|
||||
}
|
||||
log.debug("【流水标签】规则参数解析结果: projectId={}, ruleCode={}, thresholdValues={}",
|
||||
projectId, ruleMeta.getRuleCode(), thresholdValues);
|
||||
|
||||
Set<String> missingParamCodes = requiredParamCodes.stream()
|
||||
.filter(code -> !thresholdValues.containsKey(code))
|
||||
.collect(Collectors.toSet());
|
||||
if (!missingParamCodes.isEmpty()) {
|
||||
log.warn("【流水标签】规则参数缺失: projectId={}, ruleCode={}, missingParams={}",
|
||||
projectId, ruleMeta.getRuleCode(), missingParamCodes);
|
||||
}
|
||||
|
||||
BankTagRuleExecutionConfig config = new BankTagRuleExecutionConfig();
|
||||
config.setProjectId(projectId);
|
||||
|
||||
@@ -24,10 +24,12 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 流水标签服务实现
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class CcdiBankTagServiceImpl implements ICcdiBankTagService {
|
||||
|
||||
@@ -85,16 +87,23 @@ public class CcdiBankTagServiceImpl implements ICcdiBankTagService {
|
||||
* @param triggerType 触发方式
|
||||
*/
|
||||
public Long rebuildProject(Long projectId, String modelCode, String operator, TriggerType triggerType) {
|
||||
long taskStartTime = System.currentTimeMillis();
|
||||
CcdiBankTagTask task = buildRunningTask(projectId, modelCode, operator, triggerType);
|
||||
taskMapper.insertTask(task);
|
||||
log.info("【流水标签】任务创建成功: taskId={}, projectId={}, modelCode={}, triggerType={}, operator={}",
|
||||
task.getId(), projectId, modelCode, triggerType, operator);
|
||||
|
||||
try {
|
||||
List<CcdiBankTagRule> rules = ruleMapper.selectEnabledRules(modelCode);
|
||||
log.info("【流水标签】加载启用规则完成: taskId={}, projectId={}, modelCode={}, ruleCount={}",
|
||||
task.getId(), projectId, modelCode, rules.size());
|
||||
log.info("【流水标签】开始清理历史结果: taskId={}, projectId={}, modelCode={}",
|
||||
task.getId(), projectId, modelCode);
|
||||
resultMapper.deleteByProjectAndModel(projectId, modelCode);
|
||||
|
||||
List<CompletableFuture<List<CcdiBankTagResult>>> futures = rules.stream()
|
||||
.map(rule -> CompletableFuture.supplyAsync(
|
||||
() -> executeRule(projectId, rule, operator),
|
||||
() -> executeRule(task.getId(), projectId, rule, operator),
|
||||
tagRuleExecutor
|
||||
))
|
||||
.toList();
|
||||
@@ -105,6 +114,8 @@ public class CcdiBankTagServiceImpl implements ICcdiBankTagService {
|
||||
.toList();
|
||||
|
||||
if (!allResults.isEmpty()) {
|
||||
log.info("【流水标签】批量写入标签结果: taskId={}, projectId={}, resultCount={}",
|
||||
task.getId(), projectId, allResults.size());
|
||||
resultMapper.insertBatch(allResults);
|
||||
}
|
||||
|
||||
@@ -117,6 +128,9 @@ public class CcdiBankTagServiceImpl implements ICcdiBankTagService {
|
||||
task.setUpdateBy(operator);
|
||||
task.setUpdateTime(new Date());
|
||||
taskMapper.updateTask(task);
|
||||
log.info("【流水标签】任务执行成功: taskId={}, projectId={}, modelCode={}, triggerType={}, ruleCount={}, hitCount={}, costMs={}",
|
||||
task.getId(), projectId, modelCode, triggerType, rules.size(), allResults.size(),
|
||||
System.currentTimeMillis() - taskStartTime);
|
||||
return task.getId();
|
||||
} catch (Exception ex) {
|
||||
task.setStatus(STATUS_FAILED);
|
||||
@@ -126,6 +140,8 @@ public class CcdiBankTagServiceImpl implements ICcdiBankTagService {
|
||||
task.setUpdateBy(operator);
|
||||
task.setUpdateTime(new Date());
|
||||
taskMapper.updateTask(task);
|
||||
log.error("【流水标签】任务执行失败: taskId={}, projectId={}, modelCode={}, triggerType={}, error={}",
|
||||
task.getId(), projectId, modelCode, triggerType, ex.getMessage(), ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
@@ -149,15 +165,35 @@ public class CcdiBankTagServiceImpl implements ICcdiBankTagService {
|
||||
return task;
|
||||
}
|
||||
|
||||
private List<CcdiBankTagResult> executeRule(Long projectId, CcdiBankTagRule rule, String operator) {
|
||||
private List<CcdiBankTagResult> executeRule(Long taskId, Long projectId, CcdiBankTagRule rule, String operator) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("【流水标签】规则开始执行: taskId={}, projectId={}, ruleCode={}, resultType={}",
|
||||
taskId, projectId, rule.getRuleCode(), rule.getResultType());
|
||||
BankTagRuleExecutionConfig config = configResolver.resolve(projectId, rule);
|
||||
log.debug("【流水标签】规则执行参数: taskId={}, ruleCode={}, thresholds={}",
|
||||
taskId, rule.getRuleCode(), config.getThresholdValues());
|
||||
if (RESULT_TYPE_STATEMENT.equals(rule.getResultType())) {
|
||||
List<BankTagStatementHitVO> hits = executeStatementRule(projectId, rule, config);
|
||||
return buildStatementResults(projectId, rule, hits, operator);
|
||||
List<CcdiBankTagResult> results = buildStatementResults(projectId, rule, hits, operator);
|
||||
logRuleCompletion(taskId, projectId, rule.getRuleCode(), results.size(), startTime);
|
||||
return results;
|
||||
}
|
||||
|
||||
List<BankTagObjectHitVO> hits = executeObjectRule(projectId, rule, config);
|
||||
return buildObjectResults(projectId, rule, hits, operator);
|
||||
List<CcdiBankTagResult> results = buildObjectResults(projectId, rule, hits, operator);
|
||||
logRuleCompletion(taskId, projectId, rule.getRuleCode(), results.size(), startTime);
|
||||
return results;
|
||||
}
|
||||
|
||||
private void logRuleCompletion(Long taskId, Long projectId, String ruleCode, int hitCount, long startTime) {
|
||||
long costMs = System.currentTimeMillis() - startTime;
|
||||
if (hitCount == 0) {
|
||||
log.warn("【流水标签】规则无命中: taskId={}, projectId={}, ruleCode={}, costMs={}",
|
||||
taskId, projectId, ruleCode, costMs);
|
||||
return;
|
||||
}
|
||||
log.info("【流水标签】规则执行完成: taskId={}, projectId={}, ruleCode={}, hitCount={}, costMs={}",
|
||||
taskId, projectId, ruleCode, hitCount, costMs);
|
||||
}
|
||||
|
||||
private List<BankTagStatementHitVO> executeStatementRule(Long projectId,
|
||||
|
||||
@@ -679,7 +679,11 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
|
||||
}
|
||||
|
||||
private void handleTagRebuildAfterBatchCompletion(Long projectId, TriggerType triggerType, Boolean anySuccess) {
|
||||
log.info("【流水标签】批处理完成,准备触发自动重算: projectId={}, triggerType={}, anySuccess={}",
|
||||
projectId, triggerType, anySuccess);
|
||||
if (!Boolean.TRUE.equals(anySuccess)) {
|
||||
log.warn("【流水标签】跳过自动重算: projectId={}, triggerType={}, reason=all_records_failed",
|
||||
projectId, triggerType);
|
||||
return;
|
||||
}
|
||||
bankTagService.submitAutoRebuild(projectId, triggerType);
|
||||
|
||||
@@ -9,10 +9,12 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 项目级流水标签重算协调器
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ProjectBankTagRebuildCoordinator {
|
||||
|
||||
@@ -33,7 +35,11 @@ public class ProjectBankTagRebuildCoordinator {
|
||||
* @param operator 操作人
|
||||
*/
|
||||
public void submitManual(Long projectId, String modelCode, String operator) {
|
||||
log.info("【流水标签】手动重算开始排队: projectId={}, modelCode={}, operator={}",
|
||||
projectId, modelCode, operator);
|
||||
if (isProjectRunning(projectId)) {
|
||||
log.warn("【流水标签】项目已有运行中任务,拒绝手动重算: projectId={}, modelCode={}, operator={}",
|
||||
projectId, modelCode, operator);
|
||||
throw new ServiceException("当前项目标签正在重算中,请稍后再试");
|
||||
}
|
||||
|
||||
@@ -49,6 +55,8 @@ public class ProjectBankTagRebuildCoordinator {
|
||||
public void submitAuto(Long projectId, TriggerType triggerType) {
|
||||
CcdiBankTagTask runningTask = taskMapper.selectRunningTaskByProjectId(projectId);
|
||||
if (runningTask != null || runningProjects.containsKey(projectId)) {
|
||||
log.warn("【流水标签】项目正在重算,已标记完成后补跑: projectId={}, runningTaskId={}, triggerType={}",
|
||||
projectId, runningTask != null ? runningTask.getId() : null, triggerType);
|
||||
markNeedRerun(runningTask);
|
||||
return;
|
||||
}
|
||||
@@ -64,12 +72,15 @@ public class ProjectBankTagRebuildCoordinator {
|
||||
|
||||
private void executeWithLock(Long projectId, Runnable action) {
|
||||
if (runningProjects.putIfAbsent(projectId, Boolean.TRUE) != null) {
|
||||
log.warn("【流水标签】项目已有运行中任务,拒绝获取项目锁: projectId={}", projectId);
|
||||
throw new ServiceException("当前项目标签正在重算中,请稍后再试");
|
||||
}
|
||||
log.info("【流水标签】获取项目重算锁成功: projectId={}", projectId);
|
||||
try {
|
||||
action.run();
|
||||
} finally {
|
||||
runningProjects.remove(projectId);
|
||||
log.info("【流水标签】释放项目重算锁: projectId={}", projectId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.ruoyi.ccdi.project.controller;
|
||||
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.read.ListAppender;
|
||||
import com.ruoyi.ccdi.project.domain.dto.CcdiBankTagRebuildDTO;
|
||||
import com.ruoyi.ccdi.project.service.ICcdiBankTagService;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
@@ -10,8 +13,10 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -42,4 +47,32 @@ class CcdiBankTagControllerTest {
|
||||
verify(bankTagService).submitRebuild(dto, "admin");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void rebuild_shouldLogManualRebuildRequest() {
|
||||
CcdiBankTagRebuildDTO dto = new CcdiBankTagRebuildDTO();
|
||||
dto.setProjectId(40L);
|
||||
dto.setModelCode("LARGE_TRANSACTION");
|
||||
|
||||
Logger logger = (Logger) LoggerFactory.getLogger(CcdiBankTagController.class);
|
||||
ListAppender<ILoggingEvent> appender = new ListAppender<>();
|
||||
appender.start();
|
||||
logger.addAppender(appender);
|
||||
|
||||
when(bankTagService.submitRebuild(dto, "admin")).thenReturn("标签重算任务已提交");
|
||||
|
||||
try (MockedStatic<SecurityUtils> mocked = mockStatic(SecurityUtils.class)) {
|
||||
mocked.when(SecurityUtils::getUsername).thenReturn("admin");
|
||||
|
||||
controller.rebuild(dto);
|
||||
|
||||
assertTrue(appender.list.stream().map(ILoggingEvent::getFormattedMessage)
|
||||
.anyMatch(message -> message.contains("收到手动重算请求")
|
||||
&& message.contains("projectId=40")
|
||||
&& message.contains("modelCode=LARGE_TRANSACTION")
|
||||
&& message.contains("operator=admin")));
|
||||
} finally {
|
||||
logger.detachAppender(appender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.ruoyi.ccdi.project.service.impl;
|
||||
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.read.ListAppender;
|
||||
import com.ruoyi.ccdi.project.domain.CcdiModelParam;
|
||||
import com.ruoyi.ccdi.project.domain.CcdiProject;
|
||||
import com.ruoyi.ccdi.project.domain.entity.CcdiBankTagRule;
|
||||
@@ -11,10 +14,12 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@@ -49,6 +54,42 @@ class BankTagRuleConfigResolverTest {
|
||||
assertEquals("1111", config.getThresholdValue("SINGLE_TRANSACTION_AMOUNT"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolve_shouldLogThresholdSourceAndMissingParams() {
|
||||
CcdiProject project = new CcdiProject();
|
||||
project.setProjectId(40L);
|
||||
project.setConfigType("default");
|
||||
when(projectMapper.selectById(40L)).thenReturn(project);
|
||||
when(modelParamMapper.selectByProjectAndModel(0L, "LARGE_TRANSACTION")).thenReturn(List.of(
|
||||
buildParam("LARGE_CASH_DEPOSIT", "50000")
|
||||
));
|
||||
|
||||
CcdiBankTagRule ruleMeta = new CcdiBankTagRule();
|
||||
ruleMeta.setModelCode("LARGE_TRANSACTION");
|
||||
ruleMeta.setRuleCode("FREQUENT_CASH_DEPOSIT");
|
||||
|
||||
Logger logger = (Logger) LoggerFactory.getLogger(BankTagRuleConfigResolver.class);
|
||||
ListAppender<ILoggingEvent> logAppender = new ListAppender<>();
|
||||
logAppender.start();
|
||||
logger.addAppender(logAppender);
|
||||
|
||||
try {
|
||||
resolver.resolve(40L, ruleMeta);
|
||||
|
||||
assertTrue(logAppender.list.stream().map(ILoggingEvent::getFormattedMessage)
|
||||
.anyMatch(message -> message.contains("解析规则参数")
|
||||
&& message.contains("projectId=40")
|
||||
&& message.contains("effectiveProjectId=0")
|
||||
&& message.contains("FREQUENT_CASH_DEPOSIT")));
|
||||
assertTrue(logAppender.list.stream().map(ILoggingEvent::getFormattedMessage)
|
||||
.anyMatch(message -> message.contains("规则参数缺失")
|
||||
&& message.contains("projectId=40")
|
||||
&& message.contains("FREQUENT_CASH_DEPOSIT")));
|
||||
} finally {
|
||||
logger.detachAppender(logAppender);
|
||||
}
|
||||
}
|
||||
|
||||
private CcdiModelParam buildParam(String paramCode, String paramValue) {
|
||||
CcdiModelParam param = new CcdiModelParam();
|
||||
param.setProjectId(0L);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.ruoyi.ccdi.project.service.impl;
|
||||
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.read.ListAppender;
|
||||
import com.ruoyi.ccdi.project.domain.entity.CcdiBankTagRule;
|
||||
import com.ruoyi.ccdi.project.domain.entity.CcdiBankTagTask;
|
||||
import com.ruoyi.ccdi.project.domain.enums.TriggerType;
|
||||
@@ -15,13 +18,17 @@ import org.mockito.InOrder;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -81,4 +88,91 @@ class CcdiBankTagServiceImplTest {
|
||||
inOrder.verify(resultMapper).insertBatch(anyList());
|
||||
verify(taskMapper).insertTask(any(CcdiBankTagTask.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rebuildProject_shouldLogTaskLifecycleAndRuleSummary() {
|
||||
ReflectionTestUtils.setField(service, "tagRuleExecutor", (Executor) Runnable::run);
|
||||
|
||||
CcdiBankTagRule rule = new CcdiBankTagRule();
|
||||
rule.setModelCode("LARGE_TRANSACTION");
|
||||
rule.setModelName("大额交易");
|
||||
rule.setRuleCode("HOUSE_OR_CAR_EXPENSE");
|
||||
rule.setRuleName("房车消费支出交易");
|
||||
rule.setResultType("STATEMENT");
|
||||
|
||||
BankTagRuleExecutionConfig config = new BankTagRuleExecutionConfig();
|
||||
config.setProjectId(40L);
|
||||
config.setRuleMeta(rule);
|
||||
|
||||
BankTagStatementHitVO hit = new BankTagStatementHitVO();
|
||||
hit.setBankStatementId(10L);
|
||||
hit.setGroupId(40);
|
||||
hit.setLogId(40001);
|
||||
hit.setReasonDetail("命中房车消费支出");
|
||||
|
||||
doAnswer(invocation -> {
|
||||
CcdiBankTagTask task = invocation.getArgument(0);
|
||||
task.setId(88L);
|
||||
return 1;
|
||||
}).when(taskMapper).insertTask(any(CcdiBankTagTask.class));
|
||||
|
||||
when(ruleMapper.selectEnabledRules(null)).thenReturn(List.of(rule));
|
||||
when(configResolver.resolve(40L, rule)).thenReturn(config);
|
||||
when(analysisMapper.selectHouseOrCarExpenseStatements(40L)).thenReturn(List.of(hit));
|
||||
|
||||
Logger logger = (Logger) LoggerFactory.getLogger(CcdiBankTagServiceImpl.class);
|
||||
ListAppender<ILoggingEvent> logAppender = new ListAppender<>();
|
||||
logAppender.start();
|
||||
logger.addAppender(logAppender);
|
||||
|
||||
try {
|
||||
service.rebuildProject(40L, null, "admin", TriggerType.MANUAL);
|
||||
|
||||
assertTrue(logAppender.list.stream().map(ILoggingEvent::getFormattedMessage)
|
||||
.anyMatch(message -> message.contains("任务创建成功")
|
||||
&& message.contains("taskId=88")
|
||||
&& message.contains("projectId=40")));
|
||||
assertTrue(logAppender.list.stream().map(ILoggingEvent::getFormattedMessage)
|
||||
.anyMatch(message -> message.contains("规则执行完成")
|
||||
&& message.contains("ruleCode=HOUSE_OR_CAR_EXPENSE")
|
||||
&& message.contains("hitCount=1")));
|
||||
} finally {
|
||||
logger.detachAppender(logAppender);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void rebuildProject_shouldLogFailureSummaryWhenRuleExecutionFails() {
|
||||
ReflectionTestUtils.setField(service, "tagRuleExecutor", (Executor) Runnable::run);
|
||||
|
||||
CcdiBankTagRule rule = new CcdiBankTagRule();
|
||||
rule.setModelCode("LARGE_TRANSACTION");
|
||||
rule.setRuleCode("HOUSE_OR_CAR_EXPENSE");
|
||||
rule.setResultType("STATEMENT");
|
||||
|
||||
doAnswer(invocation -> {
|
||||
CcdiBankTagTask task = invocation.getArgument(0);
|
||||
task.setId(89L);
|
||||
return 1;
|
||||
}).when(taskMapper).insertTask(any(CcdiBankTagTask.class));
|
||||
|
||||
when(ruleMapper.selectEnabledRules(null)).thenReturn(List.of(rule));
|
||||
when(configResolver.resolve(40L, rule)).thenThrow(new RuntimeException("threshold missing"));
|
||||
|
||||
Logger logger = (Logger) LoggerFactory.getLogger(CcdiBankTagServiceImpl.class);
|
||||
ListAppender<ILoggingEvent> logAppender = new ListAppender<>();
|
||||
logAppender.start();
|
||||
logger.addAppender(logAppender);
|
||||
|
||||
try {
|
||||
assertThrows(RuntimeException.class,
|
||||
() -> service.rebuildProject(40L, null, "admin", TriggerType.MANUAL));
|
||||
assertTrue(logAppender.list.stream().map(ILoggingEvent::getFormattedMessage)
|
||||
.anyMatch(message -> message.contains("任务执行失败")
|
||||
&& message.contains("taskId=89")
|
||||
&& message.contains("threshold missing")));
|
||||
} finally {
|
||||
logger.detachAppender(logAppender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -167,6 +167,59 @@ class CcdiFileUploadServiceImplTest {
|
||||
assertFalse(Files.exists(batchLogDir));
|
||||
}
|
||||
|
||||
@Test
|
||||
void handleTagRebuildAfterBatchCompletion_shouldLogSkipWhenAllRecordsFailed() {
|
||||
Logger logger = (Logger) LoggerFactory.getLogger(CcdiFileUploadServiceImpl.class);
|
||||
ListAppender<ILoggingEvent> logAppender = new ListAppender<>();
|
||||
logAppender.start();
|
||||
logger.addAppender(logAppender);
|
||||
|
||||
try {
|
||||
ReflectionTestUtils.invokeMethod(
|
||||
service,
|
||||
"handleTagRebuildAfterBatchCompletion",
|
||||
PROJECT_ID,
|
||||
TriggerType.AUTO_BATCH_UPLOAD,
|
||||
Boolean.FALSE
|
||||
);
|
||||
|
||||
verify(bankTagService, never()).submitAutoRebuild(any(), any());
|
||||
assertTrue(logAppender.list.stream().map(ILoggingEvent::getFormattedMessage)
|
||||
.anyMatch(message -> message.contains("跳过自动重算")
|
||||
&& message.contains("projectId=100")
|
||||
&& message.contains("AUTO_BATCH_UPLOAD")));
|
||||
} finally {
|
||||
logger.detachAppender(logAppender);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void handleTagRebuildAfterBatchCompletion_shouldLogSubmissionWhenAnyRecordSucceeded() {
|
||||
Logger logger = (Logger) LoggerFactory.getLogger(CcdiFileUploadServiceImpl.class);
|
||||
ListAppender<ILoggingEvent> logAppender = new ListAppender<>();
|
||||
logAppender.start();
|
||||
logger.addAppender(logAppender);
|
||||
|
||||
try {
|
||||
ReflectionTestUtils.invokeMethod(
|
||||
service,
|
||||
"handleTagRebuildAfterBatchCompletion",
|
||||
PROJECT_ID,
|
||||
TriggerType.AUTO_PULL_BANK_INFO,
|
||||
Boolean.TRUE
|
||||
);
|
||||
|
||||
verify(bankTagService).submitAutoRebuild(PROJECT_ID, TriggerType.AUTO_PULL_BANK_INFO);
|
||||
assertTrue(logAppender.list.stream().map(ILoggingEvent::getFormattedMessage)
|
||||
.anyMatch(message -> message.contains("准备触发自动重算")
|
||||
&& message.contains("projectId=100")
|
||||
&& message.contains("AUTO_PULL_BANK_INFO")
|
||||
&& message.contains("anySuccess=true")));
|
||||
} finally {
|
||||
logger.detachAppender(logAppender);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void processFileAsync_shouldKeepParsingUntilBankStatementsSaved() throws IOException {
|
||||
List<String> events = new ArrayList<>();
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.ruoyi.ccdi.project.service.impl;
|
||||
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.read.ListAppender;
|
||||
import com.ruoyi.ccdi.project.domain.entity.CcdiBankTagTask;
|
||||
import com.ruoyi.ccdi.project.domain.enums.TriggerType;
|
||||
import com.ruoyi.ccdi.project.mapper.CcdiBankTagTaskMapper;
|
||||
@@ -9,8 +12,10 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -54,4 +59,54 @@ class ProjectBankTagRebuildCoordinatorTest {
|
||||
verify(taskMapper).updateTask(any(CcdiBankTagTask.class));
|
||||
verify(bankTagService, never()).rebuildProject(40L, null, "system", TriggerType.AUTO_BATCH_UPLOAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
void submitManual_shouldLogRejectWhenProjectAlreadyRunning() {
|
||||
CcdiBankTagTask runningTask = new CcdiBankTagTask();
|
||||
runningTask.setId(1L);
|
||||
runningTask.setProjectId(40L);
|
||||
runningTask.setStatus("RUNNING");
|
||||
when(taskMapper.selectRunningTaskByProjectId(40L)).thenReturn(runningTask);
|
||||
|
||||
Logger logger = (Logger) LoggerFactory.getLogger(ProjectBankTagRebuildCoordinator.class);
|
||||
ListAppender<ILoggingEvent> logAppender = new ListAppender<>();
|
||||
logAppender.start();
|
||||
logger.addAppender(logAppender);
|
||||
|
||||
try {
|
||||
assertThrows(ServiceException.class, () -> coordinator.submitManual(40L, null, "admin"));
|
||||
assertTrue(logAppender.list.stream().map(ILoggingEvent::getFormattedMessage)
|
||||
.anyMatch(message -> message.contains("拒绝手动重算")
|
||||
&& message.contains("projectId=40")
|
||||
&& message.contains("operator=admin")));
|
||||
} finally {
|
||||
logger.detachAppender(logAppender);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void submitAuto_shouldLogNeedRerunWhenProjectAlreadyRunning() {
|
||||
CcdiBankTagTask runningTask = new CcdiBankTagTask();
|
||||
runningTask.setId(1L);
|
||||
runningTask.setProjectId(40L);
|
||||
runningTask.setStatus("RUNNING");
|
||||
runningTask.setNeedRerun(0);
|
||||
when(taskMapper.selectRunningTaskByProjectId(40L)).thenReturn(runningTask);
|
||||
|
||||
Logger logger = (Logger) LoggerFactory.getLogger(ProjectBankTagRebuildCoordinator.class);
|
||||
ListAppender<ILoggingEvent> logAppender = new ListAppender<>();
|
||||
logAppender.start();
|
||||
logger.addAppender(logAppender);
|
||||
|
||||
try {
|
||||
coordinator.submitAuto(40L, TriggerType.AUTO_BATCH_UPLOAD);
|
||||
assertTrue(logAppender.list.stream().map(ILoggingEvent::getFormattedMessage)
|
||||
.anyMatch(message -> message.contains("已标记完成后补跑")
|
||||
&& message.contains("projectId=40")
|
||||
&& message.contains("runningTaskId=1")
|
||||
&& message.contains("AUTO_BATCH_UPLOAD")));
|
||||
} finally {
|
||||
logger.detachAppender(logAppender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
25
docs/README.md
Normal file
25
docs/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# docs 目录说明
|
||||
|
||||
本目录按文档类型整理,优先解决历史文档集中堆放在 `docs/plans/` 根目录的问题。
|
||||
|
||||
## 目录结构
|
||||
|
||||
- `design/`: 设计文档与设计附属文件
|
||||
- `plans/backend/`: 后端实施计划
|
||||
- `plans/frontend/`: 前端实施计划
|
||||
- `plans/fullstack/`: 综合实施计划、集成计划与通用实施记录
|
||||
- `plans/misc/`: 计划类杂项文档
|
||||
- `tests/plans/`: 测试计划
|
||||
- `tests/records/`: 测试记录
|
||||
- `tests/scripts/`: 测试脚本与脚本说明
|
||||
- `reports/implementation/`: 实施报告
|
||||
- `reports/optimization/`: 优化记录
|
||||
- `reports/code-review/`: 代码评审报告
|
||||
|
||||
## 归类规则
|
||||
|
||||
- 设计类文档统一放入 `design/`
|
||||
- 明确标注前端或后端的实施计划分别放入 `plans/frontend/`、`plans/backend/`
|
||||
- 不区分前后端的综合方案、集成计划和通用实施文档放入 `plans/fullstack/`
|
||||
- 测试相关文档统一放入 `tests/`
|
||||
- 报告与复盘类文档统一放入 `reports/`
|
||||
@@ -249,7 +249,7 @@ SHOW CREATE TABLE sys_user;
|
||||
3. **表结构文件**: `doc/database/backup/ccdi_structure.sql`
|
||||
4. **数据文件**: `doc/database/backup/ccdi_data.sql`
|
||||
5. **操作指南**: `doc/database/backup/export_guide.md`
|
||||
6. **设计文档**: `docs/plans/2026-02-28-database-migration-design.md`
|
||||
6. **设计文档**: `docs/design/2026-02-28-database-migration-design.md`
|
||||
|
||||
## 时间估算
|
||||
|
||||
@@ -145,11 +145,11 @@ public CcdiProjectVO createProject(CcdiProjectSaveDTO dto) {
|
||||
### 5. 测试脚本 ✅
|
||||
|
||||
**文件**:
|
||||
- `docs/test-scripts/test-project-creation.sh` (Bash)
|
||||
- `docs/test-scripts/test-project-creation.ps1` (PowerShell)
|
||||
- `docs/test-scripts/test-project-creation.bat` (批处理)
|
||||
- `docs/test-scripts/test-simple.sh` (简化版)
|
||||
- `docs/test-scripts/README.md` (文档)
|
||||
- `docs/tests/scripts/test-project-creation.sh` (Bash)
|
||||
- `docs/tests/scripts/test-project-creation.ps1` (PowerShell)
|
||||
- `docs/tests/scripts/test-project-creation.bat` (批处理)
|
||||
- `docs/tests/scripts/test-simple.sh` (简化版)
|
||||
- `docs/tests/scripts/README.md` (文档)
|
||||
|
||||
**Commit**: `206754a` - "test: 添加项目创建功能测试脚本和文档"
|
||||
|
||||
|
||||
@@ -839,7 +839,7 @@ public void saveParams(ModelParamSaveDTO saveDTO) {
|
||||
|
||||
**测试文件:**
|
||||
- `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiModelParamServiceImplTest.java` - 单元测试
|
||||
- `docs/test-scripts/test-param-config.sh` - 集成测试脚本
|
||||
- `docs/tests/scripts/test-param-config.sh` - 集成测试脚本
|
||||
|
||||
### 8.2 参考文档
|
||||
|
||||
@@ -265,7 +265,7 @@ ON DUPLICATE KEY UPDATE
|
||||
本次实现后应同步更新以下文档,避免数据库说明继续失真:
|
||||
|
||||
- `assets/对接流水分析/ccdi_bank_statement.md`
|
||||
- 如有必要,同步 `docs/plans/2026-03-04-bank-statement-entity-design.md` 中的表结构补充说明
|
||||
- 如有必要,同步 `docs/design/2026-03-04-bank-statement-entity-design.md` 中的表结构补充说明
|
||||
|
||||
## 影响范围
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
现有员工亲属关系维护页面 `http://localhost/maintain/staffFmyRelation` 已支持员工亲属关系的新增、编辑、删除、详情、导入导出,但尚不支持维护亲属名下资产信息。
|
||||
|
||||
当前仓库中已有员工资产维护设计文档 [2026-03-12-employee-asset-maintenance-design.md](/D:/ccdi/ccdi/docs/plans/2026-03-12-employee-asset-maintenance-design.md),其核心约束是通过 `family_id` 表示归属员工,通过 `person_id` 表示资产实际持有人。本次需求需要将该能力调整到“员工亲属关系维护页面”中,并明确仅维护亲属资产,不包含员工本人资产。
|
||||
当前仓库中已有员工资产维护设计文档 [2026-03-12-employee-asset-maintenance-design.md](/D:/ccdi/ccdi/docs/design/2026-03-12-employee-asset-maintenance-design.md),其核心约束是通过 `family_id` 表示归属员工,通过 `person_id` 表示资产实际持有人。本次需求需要将该能力调整到“员工亲属关系维护页面”中,并明确仅维护亲属资产,不包含员工本人资产。
|
||||
|
||||
本次设计于 2026-03-12 确认以下业务口径:
|
||||
|
||||
@@ -698,8 +698,8 @@ mvn spring-boot:run
|
||||
**步骤 6: 提交测试记录**
|
||||
|
||||
```bash
|
||||
mkdir -p docs/test-records
|
||||
git add docs/test-records/
|
||||
mkdir -p docs/tests/records
|
||||
git add docs/tests/records/
|
||||
git commit -m "test(ccdi-project): 记录后端接口测试结果"
|
||||
```
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
**Files:**
|
||||
- Create: `sql/2026-03-12_ccdi_asset_info.sql`
|
||||
- Review: `assets/资产信息表.csv`
|
||||
- Review: `docs/plans/2026-03-12-employee-asset-maintenance-design.md`
|
||||
- Review: `docs/design/2026-03-12-employee-asset-maintenance-design.md`
|
||||
|
||||
**Step 1: Write the SQL script**
|
||||
|
||||
@@ -40,7 +40,7 @@ Confirm the script:
|
||||
**Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add sql/2026-03-12_ccdi_asset_info.sql docs/plans/2026-03-12-employee-asset-maintenance-design.md
|
||||
git add sql/2026-03-12_ccdi_asset_info.sql docs/design/2026-03-12-employee-asset-maintenance-design.md
|
||||
git commit -m "新增员工资产信息设计与建表脚本"
|
||||
```
|
||||
|
||||
@@ -349,6 +349,6 @@ Expected: compile succeeds without Java or mapper XML errors.
|
||||
**Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add sql/2026-03-12_ccdi_asset_info.sql ccdi-info-collection/src/main/java/com/ruoyi/info/collection ccdi-info-collection/src/main/resources/mapper/info/collection docs/plans/2026-03-12-employee-asset-maintenance-backend-implementation.md
|
||||
git add sql/2026-03-12_ccdi_asset_info.sql ccdi-info-collection/src/main/java/com/ruoyi/info/collection ccdi-info-collection/src/main/resources/mapper/info/collection docs/plans/backend/2026-03-12-employee-asset-maintenance-backend-implementation.md
|
||||
git commit -m "新增员工资产信息后端实施计划"
|
||||
```
|
||||
@@ -13,7 +13,7 @@
|
||||
### Task 1: Verify backend impact is zero
|
||||
|
||||
**Files:**
|
||||
- Review: `docs/plans/2026-03-12-pull-bank-info-date-limit-design.md`
|
||||
- Review: `docs/design/2026-03-12-pull-bank-info-date-limit-design.md`
|
||||
- Review: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/`
|
||||
- Review: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/`
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
### Task 1: Verify backend impact is zero
|
||||
|
||||
**Files:**
|
||||
- Review: `docs/plans/2026-03-12-pull-bank-info-upload-button-hit-area-design.md`
|
||||
- Review: `docs/design/2026-03-12-pull-bank-info-upload-button-hit-area-design.md`
|
||||
- Review: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/`
|
||||
- Review: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/`
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
**Files:**
|
||||
- Create: `lsfx-mock-server/**`
|
||||
- Modify: `docs/plans/2026-03-13-ccdi-docker-deployment-design.md`
|
||||
- Modify: `docs/design/2026-03-13-ccdi-docker-deployment-design.md`
|
||||
- Test: `lsfx-mock-server/tests/test_api.py`
|
||||
|
||||
**Step 1: 复制并清理运行文件**
|
||||
@@ -110,7 +110,7 @@ Expected: Compose 文件能正常展开且无语法错误
|
||||
### Task 5: 构建与联调验证
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-03-13-ccdi-docker-deployment-design.md`
|
||||
- Modify: `docs/design/2026-03-13-ccdi-docker-deployment-design.md`
|
||||
|
||||
**Step 1: 本地构建后端**
|
||||
|
||||
@@ -131,6 +131,6 @@ Expected: 无错误
|
||||
**Step 4: 提交**
|
||||
|
||||
```bash
|
||||
git add lsfx-mock-server docker docker-compose.yml .env.example deploy docs/plans/2026-03-13-ccdi-docker-deployment-*.md
|
||||
git add lsfx-mock-server docker docker-compose.yml .env.example deploy docs/design/2026-03-13-ccdi-docker-deployment-design.md docs/plans/backend/2026-03-13-ccdi-docker-deployment-backend-implementation.md docs/plans/frontend/2026-03-13-ccdi-docker-deployment-frontend-implementation.md
|
||||
git commit -m "新增Docker后端部署方案"
|
||||
```
|
||||
@@ -214,7 +214,7 @@ git commit -m "实现员工资产导入归属匹配"
|
||||
### Task 5: 执行回归验证
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-03-13-employee-family-asset-import-split-design.md`
|
||||
- Modify: `docs/design/2026-03-13-employee-family-asset-import-split-design.md`
|
||||
|
||||
**Step 1: 运行后端定向测试**
|
||||
|
||||
@@ -248,6 +248,6 @@ Expected:
|
||||
**Step 4: 提交**
|
||||
|
||||
```bash
|
||||
git add docs/plans/2026-03-13-employee-family-asset-import-split-design.md
|
||||
git add docs/design/2026-03-13-employee-family-asset-import-split-design.md
|
||||
git commit -m "完成资产导入拆分后端验证"
|
||||
```
|
||||
@@ -31,7 +31,7 @@
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/plans/2026-03-16-large-transaction-project40-design.md assets/database/2026-03-16-project40-large-transaction-seed.sql
|
||||
git add docs/design/2026-03-16-large-transaction-project40-design.md assets/database/2026-03-16-project40-large-transaction-seed.sql
|
||||
git commit -m "文档: 补充项目40大额交易测试数据设计"
|
||||
```
|
||||
|
||||
@@ -114,7 +114,7 @@ Expected: 每个指标返回至少 1 条命中记录或 1 个命中分组。
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add assets/database/2026-03-16-project40-large-transaction-seed.sql docs/implementation-reports/2026-03-16-project40-large-transaction-report.md
|
||||
git add assets/database/2026-03-16-project40-large-transaction-seed.sql docs/reports/implementation2026-03-16-project40-large-transaction-report.md
|
||||
git commit -m "验证: 完成项目40大额交易测试流水校验"
|
||||
```
|
||||
|
||||
@@ -144,6 +144,6 @@ Expected: `project_id=40` 存在稳定数量的测试流水。
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/implementation-reports/2026-03-16-project40-large-transaction-report.md
|
||||
git add docs/reports/implementation2026-03-16-project40-large-transaction-report.md
|
||||
git commit -m "文档: 完善项目40大额交易测试流水报告"
|
||||
```
|
||||
@@ -214,7 +214,7 @@ git commit -m "refactor: 收敛模型参数服务对齐逻辑"
|
||||
**Files:**
|
||||
- Reference: `sql/ccdi_model_param.sql`
|
||||
- Reference: `sql/2026-03-16-update-ccdi-model-param-defaults.sql`
|
||||
- Optional Record: `docs/test-records/model-param-backend-alignment-test.md`
|
||||
- Optional Record: `docs/tests/records/model-param-backend-alignment-test.md`
|
||||
|
||||
**Step 1: 准备校验项**
|
||||
|
||||
@@ -262,13 +262,13 @@ ORDER BY model_code, sort_order, id;
|
||||
将验证过程写入:
|
||||
|
||||
```text
|
||||
docs/test-records/model-param-backend-alignment-test.md
|
||||
docs/tests/records/model-param-backend-alignment-test.md
|
||||
```
|
||||
|
||||
**Step 5: 提交**
|
||||
|
||||
```bash
|
||||
git add docs/test-records/model-param-backend-alignment-test.md
|
||||
git add docs/tests/records/model-param-backend-alignment-test.md
|
||||
git commit -m "test: 记录模型默认参数后端对齐验证"
|
||||
```
|
||||
|
||||
@@ -348,10 +348,10 @@ POST /ccdi/modelParam/saveAll
|
||||
测试结束后关闭 `mvn spring-boot:run` 启动的进程,再提交测试记录:
|
||||
|
||||
```bash
|
||||
git add docs/test-records/model-param-backend-alignment-test.md
|
||||
git add docs/tests/records/model-param-backend-alignment-test.md
|
||||
git commit -m "test: 完成模型参数后端接口回归验证"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Plan complete and saved to `docs/plans/2026-03-16-model-param-csv-alignment-backend-implementation.md`.
|
||||
Plan complete and saved to `docs/plans/backend/2026-03-16-model-param-csv-alignment-backend-implementation.md`.
|
||||
@@ -13,7 +13,7 @@
|
||||
### Task 1: 确认需求边界
|
||||
|
||||
**Files:**
|
||||
- Review: `docs/plans/2026-03-16-param-save-bar-fixed-bottom-design.md`
|
||||
- Review: `docs/design/2026-03-16-param-save-bar-fixed-bottom-design.md`
|
||||
- Review: `ccdi-project`
|
||||
- Review: `ccdi-info-collection`
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
### Task 2: 回归验证清单
|
||||
|
||||
**Files:**
|
||||
- Review: `docs/plans/2026-03-16-param-save-bar-fixed-bottom-design.md`
|
||||
- Review: `docs/design/2026-03-16-param-save-bar-fixed-bottom-design.md`
|
||||
|
||||
**Step 1: 验证参数查询接口**
|
||||
|
||||
@@ -688,7 +688,7 @@ git commit -m "feat: 接入拉取本行信息完成后的自动流水打标"
|
||||
### Task 12: 完成全量验证
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-03-16-project-bank-statement-tagging-backend-implementation.md`
|
||||
- Modify: `docs/plans/backend/2026-03-16-project-bank-statement-tagging-backend-implementation.md`
|
||||
|
||||
**Step 1: Run focused backend tests**
|
||||
|
||||
@@ -721,7 +721,7 @@ Expected:
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project sql docs/plans/2026-03-16-project-bank-statement-tagging-backend-implementation.md
|
||||
git add ccdi-project sql docs/plans/backend/2026-03-16-project-bank-statement-tagging-backend-implementation.md
|
||||
git commit -m "feat: 完成项目流水标签后端实现"
|
||||
```
|
||||
|
||||
@@ -428,9 +428,9 @@ npm run dev
|
||||
**步骤 6: 提交测试记录**
|
||||
|
||||
```bash
|
||||
mkdir -p docs/test-records
|
||||
echo "## 全局配置页面测试结果\n\n测试时间:$(date)\n\n- [x] 页面显示正确\n- [x] 修改功能正常\n- [x] 保存功能正常\n- [x] 错误处理正常" > docs/test-records/global-config-test.md
|
||||
git add docs/test-records/
|
||||
mkdir -p docs/tests/records
|
||||
echo "## 全局配置页面测试结果\n\n测试时间:$(date)\n\n- [x] 页面显示正确\n- [x] 修改功能正常\n- [x] 保存功能正常\n- [x] 错误处理正常" > docs/tests/records/global-config-test.md
|
||||
git add docs/tests/records/
|
||||
git commit -m "test(ui): 记录全局配置页面测试结果"
|
||||
```
|
||||
|
||||
@@ -745,8 +745,8 @@ git commit -m "feat(ui): 重构项目内模型参数配置页面"
|
||||
**步骤 7: 提交测试记录**
|
||||
|
||||
```bash
|
||||
echo "## 项目配置页面测试结果\n\n测试时间:$(date)\n\n- [x] 页面显示正确\n- [x] 使用默认配置项目测试通过\n- [x] 自定义配置项目测试通过\n- [x] 多模型修改测试通过" > docs/test-records/project-config-test.md
|
||||
git add docs/test-records/
|
||||
echo "## 项目配置页面测试结果\n\n测试时间:$(date)\n\n- [x] 页面显示正确\n- [x] 使用默认配置项目测试通过\n- [x] 自定义配置项目测试通过\n- [x] 多模型修改测试通过" > docs/tests/records/project-config-test.md
|
||||
git add docs/tests/records/
|
||||
git commit -m "test(ui): 记录项目配置页面测试结果"
|
||||
```
|
||||
|
||||
@@ -791,8 +791,8 @@ git commit -m "test(ui): 记录项目配置页面测试结果"
|
||||
**步骤 5: 提交测试报告**
|
||||
|
||||
```bash
|
||||
echo "## 端到端集成测试结果\n\n测试时间:$(date)\n\n### 功能测试\n- [x] 全局配置影响项目配置\n- [x] 项目配置不影响全局配置\n- [x] 并发操作正常\n\n### 性能测试\n- [x] listAll接口响应时间 < 200ms\n- [x] saveAll接口响应时间 < 500ms\n\n### 结论\n前后端集成测试通过,功能正常,性能符合要求。" > docs/test-records/e2e-test.md
|
||||
git add docs/test-records/
|
||||
echo "## 端到端集成测试结果\n\n测试时间:$(date)\n\n### 功能测试\n- [x] 全局配置影响项目配置\n- [x] 项目配置不影响全局配置\n- [x] 并发操作正常\n\n### 性能测试\n- [x] listAll接口响应时间 < 200ms\n- [x] saveAll接口响应时间 < 500ms\n\n### 结论\n前后端集成测试通过,功能正常,性能符合要求。" > docs/tests/records/e2e-test.md
|
||||
git add docs/tests/records/
|
||||
git commit -m "test(ui): 完成端到端集成测试"
|
||||
```
|
||||
|
||||
@@ -574,6 +574,6 @@ Expected: 本地员工信息维护页面可访问
|
||||
**Step 6: 最终提交**
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/api/ccdiBaseStaff.js ruoyi-ui/src/api/ccdiAssetInfo.js ruoyi-ui/src/views/ccdiBaseStaff/index.vue ruoyi-ui/tests/unit docs/plans/2026-03-12-employee-asset-maintenance-frontend-implementation.md
|
||||
git add ruoyi-ui/src/api/ccdiBaseStaff.js ruoyi-ui/src/api/ccdiAssetInfo.js ruoyi-ui/src/views/ccdiBaseStaff/index.vue ruoyi-ui/tests/unit docs/plans/frontend/2026-03-12-employee-asset-maintenance-frontend-implementation.md
|
||||
git commit -m "新增员工资产信息前端实施计划"
|
||||
```
|
||||
@@ -15,7 +15,7 @@
|
||||
**Files:**
|
||||
- Create: `docker/frontend/Dockerfile`
|
||||
- Create: `docker/frontend/nginx.conf`
|
||||
- Modify: `docs/plans/2026-03-13-ccdi-docker-deployment-design.md`
|
||||
- Modify: `docs/design/2026-03-13-ccdi-docker-deployment-design.md`
|
||||
|
||||
**Step 1: 创建前端镜像定义**
|
||||
|
||||
@@ -69,7 +69,7 @@ Expected: 前端服务、依赖与端口映射正确
|
||||
### Task 4: 联调验证
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-03-13-ccdi-docker-deployment-design.md`
|
||||
- Modify: `docs/design/2026-03-13-ccdi-docker-deployment-design.md`
|
||||
|
||||
**Step 1: 检查前端生产产物**
|
||||
|
||||
@@ -84,6 +84,6 @@ Expected: 前端服务、依赖与端口映射正确
|
||||
**Step 3: 提交**
|
||||
|
||||
```bash
|
||||
git add docker/frontend deploy/deploy.ps1 docker-compose.yml .env.example docs/plans/2026-03-13-ccdi-docker-deployment-*.md
|
||||
git add docker/frontend deploy/deploy.ps1 docker-compose.yml .env.example docs/design/2026-03-13-ccdi-docker-deployment-design.md docs/plans/backend/2026-03-13-ccdi-docker-deployment-backend-implementation.md docs/plans/frontend/2026-03-13-ccdi-docker-deployment-frontend-implementation.md
|
||||
git commit -m "新增Docker前端部署方案"
|
||||
```
|
||||
@@ -188,7 +188,7 @@ git commit -m "保护亲属页资产导入交互不回归"
|
||||
### Task 5: 执行前端回归验证
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-03-13-employee-family-asset-import-split-design.md`
|
||||
- Modify: `docs/design/2026-03-13-employee-family-asset-import-split-design.md`
|
||||
|
||||
**Step 1: 运行全部相关静态测试**
|
||||
|
||||
@@ -225,6 +225,6 @@ Expected:
|
||||
**Step 4: 提交**
|
||||
|
||||
```bash
|
||||
git add docs/plans/2026-03-13-employee-family-asset-import-split-design.md
|
||||
git add docs/design/2026-03-13-employee-family-asset-import-split-design.md
|
||||
git commit -m "完成资产导入拆分前端验证"
|
||||
```
|
||||
@@ -28,7 +28,7 @@
|
||||
**Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/implementation-reports/2026-03-16-project40-large-transaction-report.md
|
||||
git add docs/reports/implementation2026-03-16-project40-large-transaction-report.md
|
||||
git commit -m "文档: 补充项目40流水前端验证说明"
|
||||
```
|
||||
|
||||
@@ -53,6 +53,6 @@ git commit -m "文档: 补充项目40流水前端验证说明"
|
||||
**Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/implementation-reports/2026-03-16-project40-large-transaction-report.md
|
||||
git add docs/reports/implementation2026-03-16-project40-large-transaction-report.md
|
||||
git commit -m "文档: 完成项目40流水前端验证清单"
|
||||
```
|
||||
@@ -233,7 +233,7 @@ git commit -m "refactor: 收敛模型参数页修改状态管理"
|
||||
### Task 5: 验证“无千分位设计”和“接口驱动展示”
|
||||
|
||||
**Files:**
|
||||
- Optional Record: `docs/test-records/model-param-frontend-alignment-test.md`
|
||||
- Optional Record: `docs/tests/records/model-param-frontend-alignment-test.md`
|
||||
|
||||
**Step 1: 启动前端开发服务**
|
||||
|
||||
@@ -273,13 +273,13 @@ npm run dev
|
||||
测试结束后关闭 `npm run dev` 启动的进程,并把结果写入:
|
||||
|
||||
```text
|
||||
docs/test-records/model-param-frontend-alignment-test.md
|
||||
docs/tests/records/model-param-frontend-alignment-test.md
|
||||
```
|
||||
|
||||
然后提交:
|
||||
|
||||
```bash
|
||||
git add docs/test-records/model-param-frontend-alignment-test.md
|
||||
git add docs/tests/records/model-param-frontend-alignment-test.md
|
||||
git commit -m "test: 记录模型参数前端动态展示验证"
|
||||
```
|
||||
|
||||
@@ -326,10 +326,10 @@ npm run dev
|
||||
**Step 5: 提交联调记录**
|
||||
|
||||
```bash
|
||||
git add docs/test-records/model-param-frontend-alignment-test.md docs/test-records/model-param-backend-alignment-test.md
|
||||
git add docs/tests/records/model-param-frontend-alignment-test.md docs/tests/records/model-param-backend-alignment-test.md
|
||||
git commit -m "test: 完成模型参数前后端联调验收"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Plan complete and saved to `docs/plans/2026-03-16-model-param-csv-alignment-frontend-implementation.md`.
|
||||
Plan complete and saved to `docs/plans/frontend/2026-03-16-model-param-csv-alignment-frontend-implementation.md`.
|
||||
@@ -13,7 +13,7 @@
|
||||
### Task 1: 明确本期前端范围为零代码接入
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md`
|
||||
- Modify: `docs/plans/frontend/2026-03-16-project-bank-statement-tagging-frontend-implementation.md`
|
||||
|
||||
**Step 1: Write the acceptance checklist**
|
||||
|
||||
@@ -44,14 +44,14 @@ Expected:
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md
|
||||
git add docs/plans/frontend/2026-03-16-project-bank-statement-tagging-frontend-implementation.md
|
||||
git commit -m "docs: 明确流水标签前端一期范围"
|
||||
```
|
||||
|
||||
### Task 2: 记录未来 API 契约占位
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md`
|
||||
- Modify: `docs/plans/frontend/2026-03-16-project-bank-statement-tagging-frontend-implementation.md`
|
||||
|
||||
**Step 1: Define the future API contract**
|
||||
|
||||
@@ -70,7 +70,7 @@ git commit -m "docs: 明确流水标签前端一期范围"
|
||||
Run:
|
||||
|
||||
```bash
|
||||
Get-Content docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md | Select-String "/ccdi/project/tags/rebuild"
|
||||
Get-Content docs/plans/frontend/2026-03-16-project-bank-statement-tagging-frontend-implementation.md | Select-String "/ccdi/project/tags/rebuild"
|
||||
```
|
||||
|
||||
Expected:
|
||||
@@ -84,14 +84,14 @@ Expected:
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md
|
||||
git add docs/plans/frontend/2026-03-16-project-bank-statement-tagging-frontend-implementation.md
|
||||
git commit -m "docs: 补充流水标签前端后续接口契约"
|
||||
```
|
||||
|
||||
### Task 3: 约束后续页面接入位置
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md`
|
||||
- Modify: `docs/plans/frontend/2026-03-16-project-bank-statement-tagging-frontend-implementation.md`
|
||||
|
||||
**Step 1: Write the page integration checklist**
|
||||
|
||||
@@ -125,14 +125,14 @@ Expected:
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md
|
||||
git add docs/plans/frontend/2026-03-16-project-bank-statement-tagging-frontend-implementation.md
|
||||
git commit -m "docs: 约束流水标签前端二期接入位置"
|
||||
```
|
||||
|
||||
### Task 4: 完成本期前端回归检查
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md`
|
||||
- Modify: `docs/plans/frontend/2026-03-16-project-bank-statement-tagging-frontend-implementation.md`
|
||||
|
||||
**Step 1: Run frontend build smoke check**
|
||||
|
||||
@@ -165,7 +165,7 @@ Expected:
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md
|
||||
git add docs/plans/frontend/2026-03-16-project-bank-statement-tagging-frontend-implementation.md
|
||||
git commit -m "docs: 完成流水标签前端一期兼容性核对"
|
||||
```
|
||||
|
||||
@@ -804,12 +804,12 @@ Expected: 前端服务启动成功,访问 http://localhost/ccdiProject
|
||||
```bash
|
||||
# 打开浏览器访问 http://localhost/ccdiProject
|
||||
# 使用截图工具拍摄完整页面截图
|
||||
# 保存为 docs/plans/implementation-screenshot.png
|
||||
# 保存为 docs/plans/fullstack/implementation-screenshot.png
|
||||
```
|
||||
|
||||
**Step 5: 创建验证报告**
|
||||
|
||||
创建文件 `docs/plans/verification-report.md`,记录验证结果:
|
||||
创建文件 `docs/plans/misc/verification-report.md`,记录验证结果:
|
||||
|
||||
```markdown
|
||||
# 项目管理页面重构验证报告
|
||||
@@ -846,7 +846,7 @@ Expected: 前端服务启动成功,访问 http://localhost/ccdiProject
|
||||
|
||||
Run:
|
||||
```bash
|
||||
git add docs/plans/verification-report.md
|
||||
git add docs/plans/misc/verification-report.md
|
||||
git commit -m "docs: 添加项目管理页面重构验证报告"
|
||||
```
|
||||
|
||||
@@ -950,7 +950,7 @@ Expected: 代码已推送到远程仓库
|
||||
|
||||
## 相关文件
|
||||
|
||||
- 设计文档:`docs/plans/2026-02-27-project-management-page-redesign.md`
|
||||
- 设计文档:`docs/plans/fullstack/2026-02-27-project-management-page-redesign.md`
|
||||
- 原型图:`doc/创建项目功能/ScreenShot_2026-02-27_111611_994.png`
|
||||
- 主组件:`ruoyi-ui/src/views/ccdiProject/index.vue`
|
||||
- 搜索组件:`ruoyi-ui/src/views/ccdiProject/components/SearchBar.vue`
|
||||
@@ -482,7 +482,7 @@ Expected:
|
||||
## Task 9: 最终提交和文档更新
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-02-27-project-status-counts-fix-design.md`
|
||||
- Modify: `docs/design/2026-02-27-project-status-counts-fix-design.md`
|
||||
|
||||
**Step 1: 更新设计文档状态**
|
||||
|
||||
@@ -511,7 +511,7 @@ Expected:
|
||||
**Step 3: 提交文档更新**
|
||||
|
||||
```bash
|
||||
git add docs/plans/2026-02-27-project-status-counts-fix-design.md
|
||||
git add docs/design/2026-02-27-project-status-counts-fix-design.md
|
||||
git commit -m "docs: 更新项目状态统计修复设计文档状态为已完成"
|
||||
```
|
||||
|
||||
@@ -573,6 +573,6 @@ git push origin dev
|
||||
|
||||
## 相关文档
|
||||
|
||||
- 设计文档: `docs/plans/2026-02-27-project-status-counts-fix-design.md`
|
||||
- 设计文档: `docs/design/2026-02-27-project-status-counts-fix-design.md`
|
||||
- 若依框架文档: 项目根目录的 `CLAUDE.md`
|
||||
- MyBatis Plus 文档: https://baomidou.com/
|
||||
@@ -1124,7 +1124,7 @@ cp db_config.conf.template db_config.conf
|
||||
- 实际配置: `db_config.conf`
|
||||
- 表结构文件: `doc/database/backup/ccdi_structure.sql`
|
||||
- 数据文件: `doc/database/backup/ccdi_data.sql`
|
||||
- 设计文档: `docs/plans/2026-02-28-database-migration-design.md`
|
||||
- 设计文档: `docs/design/2026-02-28-database-migration-design.md`
|
||||
```
|
||||
|
||||
**Step 2: 提交操作指南**
|
||||
@@ -648,7 +648,7 @@ git commit -m "feat: 添加获取Token响应DTO"
|
||||
|
||||
**步骤 1: 参考设计文档创建各个DTO类**
|
||||
|
||||
根据 `docs/plans/2026-03-02-lsfx-integration-design.md` 中的DTO设计,创建剩余的请求和响应对象。每个DTO都使用 `@Data` 注解,字段根据接口文档定义。
|
||||
根据 `docs/design/2026-03-02-lsfx-integration-design.md` 中的DTO设计,创建剩余的请求和响应对象。每个DTO都使用 `@Data` 注解,字段根据接口文档定义。
|
||||
|
||||
**步骤 2: 提交更改**
|
||||
|
||||
@@ -1041,7 +1041,7 @@ git log --oneline
|
||||
## 参考资料
|
||||
|
||||
- 新版接口文档:`doc/对接流水分析/兰溪-流水分析对接-新版.md`
|
||||
- 设计文档:`docs/plans/2026-03-02-lsfx-integration-design.md`
|
||||
- 设计文档:`docs/design/2026-03-02-lsfx-integration-design.md`
|
||||
- 若依框架规范:`CLAUDE.md`
|
||||
|
||||
---
|
||||
@@ -955,6 +955,6 @@ git push origin dev
|
||||
|
||||
## 文档参考
|
||||
|
||||
- 设计文档: `docs/plans/2026-03-04-project-detail-navigation-menu-design.md`
|
||||
- 设计文档: `docs/design/2026-03-04-project-detail-navigation-menu-design.md`
|
||||
- Element UI Menu 文档: https://element.eleme.cn/#/zh-CN/component/menu
|
||||
- Vue 动态组件: https://cn.vuejs.org/v2/guide/components.html#动态组件
|
||||
@@ -314,7 +314,7 @@ git commit -m "feat(lsfx-mock): 添加银行流水审计字段到 mock 响应
|
||||
## Task 4: 更新文档(可选)
|
||||
|
||||
**Files:**
|
||||
- Update: `docs/plans/2026-03-05-bank-statement-audit-fields-design.md`(已存在)
|
||||
- Update: `docs/design/2026-03-05-bank-statement-audit-fields-design.md`(已存在)
|
||||
|
||||
**Step 1: 验证设计文档完整性**
|
||||
|
||||
@@ -366,7 +366,7 @@ git commit -m "docs: 更新银行流水接口文档,补充审计字段说明"
|
||||
|
||||
## 参考资料
|
||||
|
||||
- 设计文档: `docs/plans/2026-03-05-bank-statement-audit-fields-design.md`
|
||||
- 设计文档: `docs/design/2026-03-05-bank-statement-audit-fields-design.md`
|
||||
- 实体类: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiBankStatement.java`
|
||||
- 项目规范: `CLAUDE.md`
|
||||
- 外部平台接口文档 6.5 节
|
||||
@@ -252,6 +252,6 @@ git commit -m "fix: 补充银行流水接口 uploadSequnceNumber 字段接收和
|
||||
|
||||
## 参考资料
|
||||
|
||||
- 设计文档:`docs/plans/2026-03-05-bank-statement-field-design.md`
|
||||
- 设计文档:`docs/design/2026-03-05-bank-statement-field-design.md`
|
||||
- 字段映射文档:`assets/对接流水分析/ccdi_bank_statement.md`
|
||||
- 接口文档:`assets/对接流水分析/兰溪-流水分析对接-新版.md`
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
**技术栈:** Spring Boot 3.5.8 + MyBatis Plus 3.0.5 + Vue 2.6.12 + Element UI 2.15.14
|
||||
|
||||
**设计文档:** `docs/plans/2026-03-06-model-param-config-optimization-design.md`
|
||||
**设计文档:** `docs/design/2026-03-06-model-param-config-optimization-design.md`
|
||||
|
||||
---
|
||||
|
||||
@@ -675,7 +675,7 @@ mvn spring-boot:run
|
||||
**步骤 5: 提交测试记录**
|
||||
|
||||
```bash
|
||||
git add docs/test-records/
|
||||
git add docs/tests/records/
|
||||
git commit -m "test: 记录后端接口测试结果"
|
||||
```
|
||||
|
||||
@@ -1007,7 +1007,7 @@ npm run dev
|
||||
**步骤 4: 提交测试记录**
|
||||
|
||||
```bash
|
||||
git add docs/test-records/
|
||||
git add docs/tests/records/
|
||||
git commit -m "test: 记录全局配置页面测试结果"
|
||||
```
|
||||
|
||||
@@ -1270,7 +1270,7 @@ git commit -m "feat: 重构项目内模型参数配置页面"
|
||||
**步骤 4: 提交测试记录**
|
||||
|
||||
```bash
|
||||
git add docs/test-records/
|
||||
git add docs/tests/records/
|
||||
git commit -m "test: 记录项目配置页面测试结果"
|
||||
```
|
||||
|
||||
@@ -1295,7 +1295,7 @@ git commit -m "test: 记录项目配置页面测试结果"
|
||||
**步骤 3: 提交测试记录**
|
||||
|
||||
```bash
|
||||
git add docs/test-records/
|
||||
git add docs/tests/records/
|
||||
git commit -m "test: 完成端到端功能测试"
|
||||
```
|
||||
|
||||
@@ -1319,7 +1319,7 @@ git commit -m "test: 完成端到端功能测试"
|
||||
**步骤 4: 提交测试记录**
|
||||
|
||||
```bash
|
||||
git add docs/test-records/
|
||||
git add docs/tests/records/
|
||||
git commit -m "test: 完成性能测试"
|
||||
```
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
**技术栈:** Spring Boot 3.5.8 + MyBatis Plus 3.0.5 + Vue 2.6.12 + Element UI 2.15.14
|
||||
|
||||
**设计文档:** `docs/plans/2026-03-06-model-param-config-optimization-design.md`
|
||||
**设计文档:** `docs/design/2026-03-06-model-param-config-optimization-design.md`
|
||||
|
||||
---
|
||||
|
||||
@@ -683,7 +683,7 @@ mvn spring-boot:run
|
||||
|
||||
记录测试结果并提交(如果需要):
|
||||
```bash
|
||||
git add docs/test-records/
|
||||
git add docs/tests/records/
|
||||
git commit -m "test: 记录后端接口测试结果"
|
||||
```
|
||||
|
||||
@@ -301,4 +301,4 @@ npm run build:prod
|
||||
- `ruoyi-ui/src/settings.js` - 默认配置文件(本次修改)
|
||||
- `ruoyi-ui/src/store/modules/settings.js` - Vuex 状态管理(无需修改)
|
||||
- `ruoyi-ui/src/layout/components/Settings/index.vue` - 设置界面(无需修改)
|
||||
- `docs/plans/2026-03-06-theme-light-default-design.md` - 设计文档
|
||||
- `docs/design/2026-03-06-theme-light-default-design.md` - 设计文档
|
||||
@@ -308,8 +308,8 @@ git commit -m "fix(ccdi-project): cleanup partial bank statements on upload fail
|
||||
### Task 4: 回归验证并整理交付
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-03-09-file-upload-parse-success-after-bank-statement-design.md`
|
||||
- Modify: `docs/plans/2026-03-09-file-upload-parse-success-after-bank-statement.md`
|
||||
- Modify: `docs/design/2026-03-09-file-upload-parse-success-after-bank-statement-design.md`
|
||||
- Modify: `docs/plans/fullstack/2026-03-09-file-upload-parse-success-after-bank-statement.md`
|
||||
|
||||
**Step 1: Run final verification**
|
||||
|
||||
@@ -343,7 +343,7 @@ Expected:
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapper.java ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImplTest.java docs/plans/2026-03-09-file-upload-parse-success-after-bank-statement-design.md docs/plans/2026-03-09-file-upload-parse-success-after-bank-statement.md
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapper.java ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImplTest.java docs/design/2026-03-09-file-upload-parse-success-after-bank-statement-design.md docs/plans/fullstack/2026-03-09-file-upload-parse-success-after-bank-statement.md
|
||||
git commit -m "docs: finalize file upload parse success timing plan"
|
||||
```
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user