Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
package com.ruoyi.ccdi.project.mapper;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.io.StringReader;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@@ -39,6 +42,15 @@ class CcdiBankTagAnalysisMapperXmlTest {
|
||||
assertTrue(xml.contains("selectLargeTransferStatements"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void analysisMapperXml_shouldBeWellFormed() throws Exception {
|
||||
String xml = readXml(RESOURCE);
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(false);
|
||||
factory.setValidating(false);
|
||||
factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
|
||||
}
|
||||
|
||||
private String readXml(String resource) throws Exception {
|
||||
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(resource)) {
|
||||
return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
|
||||
|
||||
566
docs/plans/2026-03-16-project-bank-statement-tagging-design.md
Normal file
566
docs/plans/2026-03-16-project-bank-statement-tagging-design.md
Normal file
@@ -0,0 +1,566 @@
|
||||
# 项目流水标签功能设计
|
||||
|
||||
## 背景
|
||||
|
||||
当前项目已经具备两条银行流水入库链路:
|
||||
|
||||
- 批量上传他行流水文件:`/ccdi/file-upload/batch`
|
||||
- 拉取本行信息:`/ccdi/file-upload/pull-bank-info`
|
||||
|
||||
两条链路最终都会把流水写入 `ccdi_bank_statement`,但系统还没有对项目内流水执行统一打标,也没有独立的手动重算能力。
|
||||
|
||||
本次需求要求:
|
||||
|
||||
- 在异步批量上传流水文件全部处理完成后,自动对项目内流水进行打标
|
||||
- 在拉取本行信息任务全部处理完成后,也自动对项目内流水进行打标
|
||||
- 提供手动接口,支持重新计算项目内标签
|
||||
- 根据 [assets/大额交易.csv](../../assets/大额交易.csv) 中的模型信息实现第一批规则
|
||||
- 避免重复打标
|
||||
- 同时支持两类结果:
|
||||
- 单条流水异常:对具体流水打标
|
||||
- 对象区间异常:对项目中的对象打标
|
||||
- 打标结果中保留足够的异常原因信息,便于后续页面清晰展示
|
||||
|
||||
## 目标
|
||||
|
||||
- 为项目建立可扩展的流水标签能力,而不是只为“大额交易”写一次性逻辑
|
||||
- 支持自动触发和手动触发两种标签重算方式
|
||||
- 用代码中的 Mapper XML 固化技术口径 SQL,不做运行时 SQL 配置化
|
||||
- 通过统一结果表保存标签命中结果和异常原因快照
|
||||
- 保证同一项目不会同时触发多个重算任务
|
||||
- 使用线程池并行执行规则,提高重算效率
|
||||
|
||||
## 非目标
|
||||
|
||||
- 本期不新增前端页面展示
|
||||
- 本期不实现动态 SQL 配置平台
|
||||
- 本期不把标签计算失败与流水导入失败绑定为同一事务
|
||||
- 本期不实现除大额交易外的其他模型
|
||||
- 本期不实现对象级结果到具体来源批次的多来源追溯
|
||||
|
||||
## 现状分析
|
||||
|
||||
### 流水导入现状
|
||||
|
||||
批量上传主链路位于:
|
||||
|
||||
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java`
|
||||
|
||||
当前关键行为:
|
||||
|
||||
- 每个文件独立异步上传、轮询解析、拉取流水、写入 `ccdi_bank_statement`
|
||||
- 文件全部提交后,调度线程立即结束
|
||||
- 没有“当前批次所有异步任务完成后的收尾回调”
|
||||
|
||||
拉取本行信息主链路同样位于 `CcdiFileUploadServiceImpl`,每个身份证号会生成一条上传记录并异步拉取流水,但也没有“全部任务完成后”的统一收尾逻辑。
|
||||
|
||||
### 参数配置现状
|
||||
|
||||
模型参数位于:
|
||||
|
||||
- `ccdi_model_param`
|
||||
- `CcdiModelParamServiceImpl`
|
||||
|
||||
系统已经支持:
|
||||
|
||||
- 项目默认参数与自定义参数切换
|
||||
- 通过 `project_id = 0` 读取系统默认参数
|
||||
- 通过 `project_id = 当前项目` 读取项目自定义参数
|
||||
|
||||
因此阈值类规则可以直接复用现有参数体系。
|
||||
|
||||
### 流水查询现状
|
||||
|
||||
流水明细能力位于:
|
||||
|
||||
- `CcdiBankStatementMapper.xml`
|
||||
- `CcdiBankStatementController`
|
||||
- `CcdiBankStatementServiceImpl`
|
||||
|
||||
当前流水表中已经具备标签计算所需的一部分字段:
|
||||
|
||||
- `project_id`
|
||||
- `group_id`
|
||||
- `batch_id`,其业务语义可作为 `log_id`
|
||||
- `bank_statement_id`
|
||||
- `cret_no`
|
||||
|
||||
## 方案对比
|
||||
|
||||
### 方案一:把每个规则直接写死在 Service 中
|
||||
|
||||
优点:
|
||||
|
||||
- 开发速度快
|
||||
- 初期实现简单
|
||||
|
||||
缺点:
|
||||
|
||||
- 第二个模型接入时会迅速膨胀为大段 `if/else`
|
||||
- SQL、规则元数据、结果写入逻辑会散落在多个类里
|
||||
- 不利于后续维护和测试
|
||||
|
||||
### 方案二:规则元数据入库,SQL 写在 Mapper XML 中
|
||||
|
||||
优点:
|
||||
|
||||
- 规则展示信息可配置
|
||||
- 技术口径 SQL 保持在代码中,便于评审和测试
|
||||
- 后续新增模型的扩展路径清晰
|
||||
|
||||
缺点:
|
||||
|
||||
- 第一版需要同时补规则表、结果表、任务表和执行框架
|
||||
|
||||
### 方案三:规则元数据和 SQL 都配置化
|
||||
|
||||
优点:
|
||||
|
||||
- 表面上扩展灵活
|
||||
|
||||
缺点:
|
||||
|
||||
- 动态 SQL 的安全性、可测试性、可维护性都较差
|
||||
- 与当前项目代码式 MyBatis 规则体系不一致
|
||||
- 不符合本次“SQL 用 Mapper + XML 实现”的约束
|
||||
|
||||
## 最终方案
|
||||
|
||||
采用方案二:
|
||||
|
||||
- 规则元数据入库
|
||||
- 技术口径 SQL 固化在 `Mapper + XML`
|
||||
- 统一结果表保存标签命中
|
||||
- 统一任务调度器管理自动触发、手动触发和项目级互斥
|
||||
- 规则级任务在线程池中并行执行
|
||||
|
||||
## 详细设计
|
||||
|
||||
### 一、数据模型设计
|
||||
|
||||
#### 1. 标签规则定义表
|
||||
|
||||
建议新增:`ccdi_bank_tag_rule`
|
||||
|
||||
建议字段:
|
||||
|
||||
- `id`
|
||||
- `model_code`
|
||||
- `model_name`
|
||||
- `rule_code`
|
||||
- `rule_name`
|
||||
- `indicator_code`
|
||||
- `result_type`:`STATEMENT` / `OBJECT`
|
||||
- `risk_level`
|
||||
- `business_caliber`
|
||||
- `enabled`
|
||||
- `sort_order`
|
||||
- `create_by`
|
||||
- `create_time`
|
||||
- `update_by`
|
||||
- `update_time`
|
||||
- `remark`
|
||||
|
||||
用途:
|
||||
|
||||
- 保存展示和业务元数据
|
||||
- 不保存技术 SQL
|
||||
- 作为结果表中的规则元信息来源
|
||||
|
||||
第一版初始化“大额交易” 8 条规则元数据:
|
||||
|
||||
- 房车消费支出交易
|
||||
- 税务支出交易
|
||||
- 大额单笔收入
|
||||
- 累计收入超限
|
||||
- 年流水交易额超限
|
||||
- 大额存现交易
|
||||
- 短时间多次存现
|
||||
- 大额转账交易
|
||||
|
||||
#### 2. 标签结果表
|
||||
|
||||
建议新增:`ccdi_bank_statement_tag_result`
|
||||
|
||||
建议字段:
|
||||
|
||||
- `id`
|
||||
- `project_id`
|
||||
- `model_code`
|
||||
- `model_name`
|
||||
- `rule_code`
|
||||
- `rule_name`
|
||||
- `indicator_code`
|
||||
- `result_type`
|
||||
- `risk_level`
|
||||
- `bank_statement_id`
|
||||
- `object_type`
|
||||
- `object_key`
|
||||
- `group_id`
|
||||
- `log_id`
|
||||
- `reason_detail`
|
||||
- `business_caliber_snapshot`
|
||||
- `hit_value_snapshot`
|
||||
- `create_by`
|
||||
- `create_time`
|
||||
- `update_by`
|
||||
- `update_time`
|
||||
- `remark`
|
||||
|
||||
字段约束:
|
||||
|
||||
- 流水级结果必须保存:
|
||||
- `bank_statement_id`
|
||||
- `group_id`
|
||||
- `log_id`
|
||||
- 对象级结果必须保存:
|
||||
- `object_type`
|
||||
- `object_key`
|
||||
- 对象级结果不写:
|
||||
- `group_id`
|
||||
- `log_id`
|
||||
- `bank_statement_id`
|
||||
|
||||
唯一约束建议拆分为两组:
|
||||
|
||||
- 流水级唯一键:`project_id + rule_code + bank_statement_id`
|
||||
- 对象级唯一键:`project_id + rule_code + object_type + object_key`
|
||||
|
||||
用途:
|
||||
|
||||
- 防止重复打标
|
||||
- 保留足够的异常原因快照,供后续页面展示
|
||||
|
||||
#### 3. 标签任务执行表
|
||||
|
||||
建议新增:`ccdi_bank_tag_task`
|
||||
|
||||
建议字段:
|
||||
|
||||
- `id`
|
||||
- `project_id`
|
||||
- `trigger_type`:`AUTO_BATCH_UPLOAD` / `AUTO_PULL_BANK_INFO` / `MANUAL`
|
||||
- `model_code`
|
||||
- `status`:`RUNNING` / `SUCCESS` / `PARTIAL_FAILED` / `FAILED`
|
||||
- `need_rerun`
|
||||
- `success_rule_count`
|
||||
- `failed_rule_count`
|
||||
- `hit_count`
|
||||
- `error_message`
|
||||
- `start_time`
|
||||
- `end_time`
|
||||
- `create_by`
|
||||
- `create_time`
|
||||
- `update_by`
|
||||
- `update_time`
|
||||
|
||||
用途:
|
||||
|
||||
- 记录当前项目是否存在正在执行的重算任务
|
||||
- 承接“自动触发补跑”标记
|
||||
- 为后续前端展示最近一次打标状态预留基础
|
||||
|
||||
### 二、规则分型设计
|
||||
|
||||
第一版大额交易 8 条规则按结果类型分为两类。
|
||||
|
||||
#### 1. 流水级规则
|
||||
|
||||
返回具体流水 `bank_statement_id`,并从流水表带出 `group_id`、`batch_id(log_id)`。
|
||||
|
||||
包括:
|
||||
|
||||
- 房车消费支出交易
|
||||
- 税务支出交易
|
||||
- 大额单笔收入
|
||||
- 大额存现交易
|
||||
- 大额转账交易
|
||||
|
||||
#### 2. 对象级规则
|
||||
|
||||
返回对象主键和原因摘要,不绑定单条流水。
|
||||
|
||||
包括:
|
||||
|
||||
- 累计收入超限
|
||||
- 年流水交易额超限
|
||||
- 短时间多次存现
|
||||
|
||||
对象级结果建议使用:
|
||||
|
||||
- `object_type = STAFF_ID_CARD`
|
||||
- `object_key = 身份证号`
|
||||
|
||||
后续如果出现亲属、账号、企业等对象级命中,可以继续扩展 `object_type`。
|
||||
|
||||
### 三、技术实现设计
|
||||
|
||||
#### 1. SQL 落点
|
||||
|
||||
所有规则 SQL 均通过 `Mapper + XML` 实现。
|
||||
|
||||
建议新增:
|
||||
|
||||
- `CcdiBankTagRuleMapper`
|
||||
- `CcdiBankTagResultMapper`
|
||||
- `CcdiBankTagTaskMapper`
|
||||
- `CcdiBankTagAnalysisMapper`
|
||||
- 对应 XML
|
||||
|
||||
其中规则筛选 Mapper 方法按规则拆分,例如:
|
||||
|
||||
- `selectHouseOrCarExpenseStatements`
|
||||
- `selectTaxExpenseStatements`
|
||||
- `selectSingleLargeIncomeStatements`
|
||||
- `selectCumulativeIncomeObjects`
|
||||
- `selectAnnualTurnoverObjects`
|
||||
- `selectLargeCashDepositStatements`
|
||||
- `selectFrequentCashDepositObjects`
|
||||
- `selectLargeTransferStatements`
|
||||
|
||||
#### 2. 参数读取
|
||||
|
||||
阈值类规则通过现有 `ccdi_model_param` 获取项目当前有效参数:
|
||||
|
||||
- 若项目 `config_type = default`,读取 `project_id = 0`
|
||||
- 若项目 `config_type = custom`,读取当前 `project_id`
|
||||
|
||||
第一版涉及参数包括:
|
||||
|
||||
- `SINGLE_TRANSACTION_AMOUNT`
|
||||
- `CUMULATIVE_TRANSACTION_AMOUNT`
|
||||
- `annual_turnover`
|
||||
- `LARGE_CASH_DEPOSIT`
|
||||
- `FREQUENT_CASH_DEPOSIT`
|
||||
- `FREQUENT_TRANSFER`
|
||||
|
||||
#### 3. 结果写入
|
||||
|
||||
重算开始前,先按范围删除旧结果:
|
||||
|
||||
- 手动全量:删除当前项目全部结果
|
||||
- 手动按模型:删除当前项目指定模型结果
|
||||
- 自动触发:按当前项目全部结果重算,保持结果与最新流水一致
|
||||
|
||||
删除完成后,再按规则并行写入结果。
|
||||
|
||||
每条规则线程内部只做:
|
||||
|
||||
- 查询命中结果
|
||||
- 构建结果实体
|
||||
- 批量插入结果表
|
||||
|
||||
规则线程内部不允许再删旧结果,避免并发线程相互覆盖。
|
||||
|
||||
### 四、触发流程设计
|
||||
|
||||
#### 1. 批量上传自动触发
|
||||
|
||||
触发入口:
|
||||
|
||||
- `CcdiFileUploadServiceImpl.batchUploadFiles`
|
||||
|
||||
改造方向:
|
||||
|
||||
- 当前 `submitTasksAsync` 需要改为收集每个文件的 `CompletableFuture`
|
||||
- 使用 `CompletableFuture.allOf(...)` 在所有文件处理完成后统一执行批次收尾
|
||||
- 若本批次至少有一份文件成功落库流水,则申请一次项目级标签重算
|
||||
|
||||
#### 2. 拉取本行信息自动触发
|
||||
|
||||
触发入口:
|
||||
|
||||
- `CcdiFileUploadServiceImpl.submitPullBankInfo`
|
||||
|
||||
改造方向:
|
||||
|
||||
- 当前 `submitPullBankInfoTasks` 同样收集每个身份证任务的 `CompletableFuture`
|
||||
- 所有任务处理完成后统一执行批次收尾
|
||||
- 若本批次至少有一条成功入库流水,则申请一次项目级标签重算
|
||||
|
||||
#### 3. 手动触发
|
||||
|
||||
新增接口:
|
||||
|
||||
- `POST /ccdi/project/tags/rebuild`
|
||||
|
||||
请求体:
|
||||
|
||||
- `projectId` 必填
|
||||
- `modelCode` 选填
|
||||
|
||||
规则:
|
||||
|
||||
- 未传 `modelCode`:重算当前项目全部模型
|
||||
- 传 `modelCode`:只重算指定模型
|
||||
|
||||
### 五、并发控制设计
|
||||
|
||||
#### 1. 项目级互斥
|
||||
|
||||
要求:
|
||||
|
||||
- 同一项目任意时刻只允许一个标签重算任务运行
|
||||
|
||||
实现建议:
|
||||
|
||||
- 新增 `ProjectTagRebuildCoordinator`
|
||||
- 以 `projectId` 作为互斥粒度
|
||||
- 结合任务表 `RUNNING` 状态和进程内互斥结构控制
|
||||
|
||||
行为规则:
|
||||
|
||||
- 自动触发时若已有任务在运行:
|
||||
- 不启动新的重算
|
||||
- 仅把当前运行任务标记为 `need_rerun = true`
|
||||
- 手动触发时若已有任务在运行:
|
||||
- 直接返回“当前项目标签正在重算中,请稍后再试”
|
||||
|
||||
#### 2. 自动补跑
|
||||
|
||||
若自动触发期间项目已有重算任务在运行:
|
||||
|
||||
- 当前任务结束后检查 `need_rerun`
|
||||
- 若为 `true`,自动再执行一轮项目级全量重算
|
||||
- 补跑结束后清空 `need_rerun`
|
||||
|
||||
这样可以同时满足:
|
||||
|
||||
- 防止并发重算
|
||||
- 不丢失导入完成后的自动重算机会
|
||||
|
||||
### 六、线程池设计
|
||||
|
||||
采用两层调度模型。
|
||||
|
||||
#### 1. 项目级任务
|
||||
|
||||
每个项目的重算由一个总任务负责:
|
||||
|
||||
- 控制任务生命周期
|
||||
- 统一删旧结果
|
||||
- 提交规则级任务
|
||||
- 汇总执行结果
|
||||
|
||||
#### 2. 规则级任务
|
||||
|
||||
每条规则使用线程池并行处理。
|
||||
|
||||
建议新增独立线程池:
|
||||
|
||||
- `tagRuleExecutor`
|
||||
|
||||
规则级线程任务职责:
|
||||
|
||||
- 读取规则元数据
|
||||
- 查询阈值参数
|
||||
- 执行 Mapper SQL
|
||||
- 批量写入结果表
|
||||
- 返回命中数和执行状态
|
||||
|
||||
优点:
|
||||
|
||||
- 多条规则之间互不阻塞
|
||||
- 后续新增模型时可复用同一套并行框架
|
||||
|
||||
### 七、失败处理设计
|
||||
|
||||
#### 1. 自动触发失败
|
||||
|
||||
- 不影响流水已成功入库的数据
|
||||
- 标签任务状态标记为 `FAILED` 或 `PARTIAL_FAILED`
|
||||
- 记录失败规则和错误信息
|
||||
- 不回滚已经成功写入的流水
|
||||
|
||||
#### 2. 手动触发失败
|
||||
|
||||
- 接口直接返回失败
|
||||
- 任务状态记录失败原因
|
||||
- 已成功完成的规则结果保留
|
||||
|
||||
#### 3. 单规则失败
|
||||
|
||||
- 不中断其他规则执行
|
||||
- 整个任务按“部分失败”汇总
|
||||
|
||||
### 八、异常原因快照设计
|
||||
|
||||
结果表中的 `reason_detail` 必须能直接解释标签来源。
|
||||
|
||||
建议格式:
|
||||
|
||||
- 流水级:
|
||||
- `摘要命中“购买房产首付款”,对手方“杭州贝壳房地产经纪有限公司”,支出金额 680000.00 元`
|
||||
- 对象级:
|
||||
- `同一交易对手累计流入 60300000.00 元,超过阈值 50000001.00 元,对手方:浙江远望贸易有限公司`
|
||||
|
||||
额外保存:
|
||||
|
||||
- `business_caliber_snapshot`
|
||||
- `hit_value_snapshot`
|
||||
|
||||
用于后续页面直接展示“规则口径 + 命中值”。
|
||||
|
||||
## 接口设计
|
||||
|
||||
### 1. 手动重算接口
|
||||
|
||||
- 路径:`POST /ccdi/project/tags/rebuild`
|
||||
- 请求体:
|
||||
- `projectId`
|
||||
- `modelCode` 可选
|
||||
- 返回:
|
||||
- 成功:`AjaxResult.success("标签重算任务已提交")`
|
||||
- 失败:`AjaxResult.error("当前项目标签正在重算中,请稍后再试")`
|
||||
|
||||
### 2. 结果查询接口
|
||||
|
||||
本期不做前端展示,结果查询接口可暂缓;但后续建议预留:
|
||||
|
||||
- 项目标签汇总查询
|
||||
- 项目标签明细查询
|
||||
- 项目标签任务状态查询
|
||||
|
||||
## 测试设计
|
||||
|
||||
后端至少覆盖以下场景:
|
||||
|
||||
- 批量上传所有文件完成后会申请一次项目级重算
|
||||
- 拉取本行信息所有任务完成后会申请一次项目级重算
|
||||
- 手动接口支持全量重算
|
||||
- 手动接口支持按模型重算
|
||||
- 同一项目正在重算时,手动接口会被拒绝
|
||||
- 同一项目自动触发期间再次触发时会标记补跑
|
||||
- 流水级结果写入时会保存 `group_id + log_id`
|
||||
- 对象级结果写入时不会保存 `group_id + log_id`
|
||||
- 重复重算不会出现重复结果
|
||||
- 参数修改后再次重算,结果会随阈值变化
|
||||
- 单条规则失败时任务状态为 `PARTIAL_FAILED`
|
||||
|
||||
## 风险与缓解
|
||||
|
||||
### 风险一:同项目高频导入导致连续补跑
|
||||
|
||||
缓解:
|
||||
|
||||
- 自动触发期间只维护一个 `need_rerun` 标记,避免无限累积队列
|
||||
|
||||
### 风险二:规则级并行导致数据库写入压力上升
|
||||
|
||||
缓解:
|
||||
|
||||
- 为规则线程池设置合理核心线程数和队列长度
|
||||
- 批量插入结果,避免逐条写入
|
||||
|
||||
### 风险三:对象级结果原因信息不足
|
||||
|
||||
缓解:
|
||||
|
||||
- 在 XML 查询阶段直接拼出可展示的原因摘要字段
|
||||
|
||||
## 后续扩展方向
|
||||
|
||||
- 新增项目标签汇总页和明细页
|
||||
- 结合 `ccdi_project` 回写项目风险人数统计
|
||||
- 支持更多模型接入
|
||||
- 支持对象级结果下钻到关联流水集合
|
||||
@@ -0,0 +1,206 @@
|
||||
# Project Bank Statement Tagging Frontend Implementation Plan
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** 在本期“仅做后端能力、不改页面展示”的范围下,明确前端暂不接入流水标签展示,同时补齐后续接入所需的接口契约文档与回归检查,确保后端发布不会误伤现有项目详情页。
|
||||
|
||||
**Architecture:** 本期前端不新增 UI、不改造 `UploadData.vue`、`DetailQuery.vue`、`PreliminaryCheck.vue`、`SpecialCheck.vue`。前端实施计划聚焦于两件事:一是确认现有页面对新增后端能力保持兼容,二是在 API 层和页面待办文档中记录未来接入点,避免后续二次梳理。
|
||||
|
||||
**Tech Stack:** Vue 2, Element UI, Axios request wrapper, npm, Node
|
||||
|
||||
---
|
||||
|
||||
### Task 1: 明确本期前端范围为零代码接入
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md`
|
||||
|
||||
**Step 1: Write the acceptance checklist**
|
||||
|
||||
先把本期前端边界写清楚:
|
||||
|
||||
- 不新增标签展示页面
|
||||
- 不新增标签查询按钮
|
||||
- 不修改上传数据页现有轮询行为
|
||||
- 不修改流水明细查询页现有筛选交互
|
||||
- 不修改结果总览和专项排查占位页面
|
||||
|
||||
**Step 2: Run a repository grep to verify no mandatory frontend dependency exists**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
Get-ChildItem -Recurse -File ruoyi-ui/src | Select-String -Pattern "project/tags|bank-tag|标签重算" | Measure-Object
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 当前为 `0`,说明前端尚未被后端新能力反向强依赖
|
||||
|
||||
**Step 3: Keep implementation minimal**
|
||||
|
||||
不修改任何前端业务文件,仅在计划文档中记录本期范围。
|
||||
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/plans/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`
|
||||
|
||||
**Step 1: Define the future API contract**
|
||||
|
||||
在计划中补充后续前端接入时将消费的后端接口:
|
||||
|
||||
- `POST /ccdi/project/tags/rebuild`
|
||||
- 后续可能新增:
|
||||
- `GET /ccdi/project/tags/summary`
|
||||
- `GET /ccdi/project/tags/list`
|
||||
- `GET /ccdi/project/tags/task/latest`
|
||||
|
||||
并记录请求与响应最小示例。
|
||||
|
||||
**Step 2: Run a smoke review**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
Get-Content docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md | Select-String "/ccdi/project/tags/rebuild"
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 能检索到接口说明
|
||||
|
||||
**Step 3: Keep implementation minimal**
|
||||
|
||||
仅补充文档,不提前创建未使用的前端 API 文件,避免本期产生无效代码。
|
||||
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/plans/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`
|
||||
|
||||
**Step 1: Write the page integration checklist**
|
||||
|
||||
在计划中明确二期前端接入位置:
|
||||
|
||||
- `ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue`
|
||||
- 适合展示项目级标签汇总、模型触发概览
|
||||
- `ruoyi-ui/src/views/ccdiProject/components/detail/SpecialCheck.vue`
|
||||
- 适合展示对象级异常标签列表
|
||||
- `ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue`
|
||||
- 适合展示流水级标签明细与异常原因
|
||||
- `ruoyi-ui/src/api/`
|
||||
- 预留 `ccdiProjectTag.js`
|
||||
|
||||
**Step 2: Run a path existence smoke check**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
@(Test-Path 'ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue'), @(Test-Path 'ruoyi-ui/src/views/ccdiProject/components/detail/SpecialCheck.vue'), @(Test-Path 'ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue')
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 三个结果均为 `True`
|
||||
|
||||
**Step 3: Keep implementation minimal**
|
||||
|
||||
仅记录接入点和职责边界,不提前改页面。
|
||||
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/plans/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`
|
||||
|
||||
**Step 1: Run frontend build smoke check**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
npm run build:prod
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 构建成功
|
||||
- 说明后端新能力引入后没有要求前端同步改动
|
||||
|
||||
**Step 2: Run upload/detail page manual checklist**
|
||||
|
||||
手工验证:
|
||||
|
||||
- 上传数据页可正常进入
|
||||
- 批量上传弹窗行为不变
|
||||
- 拉取本行信息弹窗行为不变
|
||||
- 流水明细查询页可正常打开
|
||||
- 结果总览和专项排查仍保持占位状态
|
||||
|
||||
**Step 3: Update verification notes**
|
||||
|
||||
在计划末尾补充本期前端“不变更但已验证兼容”的结论和后续待接入项。
|
||||
|
||||
**Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add docs/plans/2026-03-16-project-bank-statement-tagging-frontend-implementation.md
|
||||
git commit -m "docs: 完成流水标签前端一期兼容性核对"
|
||||
```
|
||||
|
||||
## Future API Contract
|
||||
|
||||
本期不接入,但二期前端可直接按以下契约接入:
|
||||
|
||||
- `POST /ccdi/project/tags/rebuild`
|
||||
- 请求体:
|
||||
|
||||
```json
|
||||
{
|
||||
"projectId": 40,
|
||||
"modelCode": "LARGE_TRANSACTION"
|
||||
}
|
||||
```
|
||||
|
||||
- 成功响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "标签重算任务已提交"
|
||||
}
|
||||
```
|
||||
|
||||
- 后续推荐新增:
|
||||
- `GET /ccdi/project/tags/task/latest?projectId=40`
|
||||
- `GET /ccdi/project/tags/summary?projectId=40`
|
||||
- `GET /ccdi/project/tags/list?projectId=40&resultType=STATEMENT`
|
||||
|
||||
## Verification Notes
|
||||
|
||||
本期前端计划的核心结论是:
|
||||
|
||||
- 按当前需求不做页面实现是合理的
|
||||
- 需要保证后端独立发布不影响现有项目详情页
|
||||
- 后续若要展示标签结果,建议优先接入 `PreliminaryCheck.vue`、`SpecialCheck.vue`、`DetailQuery.vue`
|
||||
Reference in New Issue
Block a user