补充结果总览详情弹窗实施计划
This commit is contained in:
@@ -0,0 +1,405 @@
|
||||
# Results Overview Project Analysis Dialog Real Detail Backend Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED: Use superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 为结果总览“项目分析”弹窗新增真实详情后端接口,统一返回员工基础信息与按类型分组的异常明细,支撑前端弹窗脱离本地 mock 展示真实数据。
|
||||
|
||||
**Architecture:** 延续 `CcdiProjectOverviewController + ICcdiProjectOverviewService + CcdiProjectOverviewServiceImpl + CcdiProjectOverviewMapper.xml` 的结果总览域链路,不新建平行控制器。详情接口内部统一完成项目存在性校验、员工主数据查询、风险等级补齐、流水型异常归并和 `OBJECT` 型摘要组装;流水字段尽量复用现有 `CcdiBankStatement*VO` 口径,避免再造一套详情专用字段体系。
|
||||
|
||||
**Tech Stack:** Java 21, Spring Boot 3, MyBatis XML, Maven, JUnit 5
|
||||
|
||||
---
|
||||
|
||||
### Task 1: 补齐详情接口契约与服务结构测试
|
||||
|
||||
**Files:**
|
||||
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewController.java`
|
||||
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiProjectOverviewService.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectPersonAnalysisDetailQueryDTO.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisDetailVO.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisBasicInfoVO.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisAbnormalDetailVO.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisAbnormalGroupVO.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisObjectRecordVO.java`
|
||||
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerContractTest.java`
|
||||
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectOverviewServiceStructureTest.java`
|
||||
|
||||
- [ ] **Step 1: Write the failing contract assertions**
|
||||
|
||||
在 `CcdiProjectOverviewControllerContractTest.java` 和 `CcdiProjectOverviewServiceStructureTest.java` 追加静态或反射断言,锁定以下边界:
|
||||
|
||||
- 控制器新增 `GET /ccdi/project/overview/person-analysis/detail`
|
||||
- 入参 DTO 只包含 `projectId` 和 `staffIdCard`
|
||||
- 服务接口新增 `getPersonAnalysisDetail(CcdiProjectPersonAnalysisDetailQueryDTO queryDTO)`
|
||||
- 详情返回 VO 至少包含:
|
||||
- `basicInfo`
|
||||
- `abnormalDetail.groups`
|
||||
- `abnormalDetail.groups[*].groupType` 只按本轮设计承载 `BANK_STATEMENT` 和 `OBJECT`
|
||||
|
||||
示例断言片段:
|
||||
|
||||
```java
|
||||
assertTrue(source.contains("@GetMapping(\"/person-analysis/detail\")"));
|
||||
assertTrue(source.contains("CcdiProjectPersonAnalysisDetailVO getPersonAnalysisDetail"));
|
||||
assertTrue(source.contains("private Long projectId;"));
|
||||
assertTrue(source.contains("private String staffIdCard;"));
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewControllerContractTest,CcdiProjectOverviewServiceStructureTest
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `FAIL`
|
||||
- 原因是详情接口、DTO、VO 和服务签名尚未存在
|
||||
|
||||
- [ ] **Step 3: Write the minimal contract code**
|
||||
|
||||
补齐 DTO、VO 和服务方法签名,控制器新增接口但先只接线到服务,不在此步写完整查询逻辑。
|
||||
|
||||
DTO 结构示例:
|
||||
|
||||
```java
|
||||
@Data
|
||||
public class CcdiProjectPersonAnalysisDetailQueryDTO implements Serializable {
|
||||
private Long projectId;
|
||||
private String staffIdCard;
|
||||
}
|
||||
```
|
||||
|
||||
服务接口签名示例:
|
||||
|
||||
```java
|
||||
CcdiProjectPersonAnalysisDetailVO getPersonAnalysisDetail(CcdiProjectPersonAnalysisDetailQueryDTO queryDTO);
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewControllerContractTest,CcdiProjectOverviewServiceStructureTest
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `PASS`
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewController.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiProjectOverviewService.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectPersonAnalysisDetailQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisDetailVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisBasicInfoVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisAbnormalDetailVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisAbnormalGroupVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisObjectRecordVO.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerContractTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectOverviewServiceStructureTest.java
|
||||
git commit -m "补充结果总览详情接口契约"
|
||||
```
|
||||
|
||||
### Task 2: 先写服务层失败测试,锁定基础信息与分组口径
|
||||
|
||||
**Files:**
|
||||
- Modify: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImplTest.java`
|
||||
- Modify: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerTest.java`
|
||||
|
||||
- [ ] **Step 1: Write the failing service test**
|
||||
|
||||
在 `CcdiProjectOverviewServiceImplTest.java` 新增测试,锁定:
|
||||
|
||||
- 项目不存在时抛出 `ServiceException("项目不存在")`
|
||||
- 员工基础信息优先从员工信息表读取
|
||||
- 风险等级来自结果总览员工结果口径
|
||||
- 返回结果中同时存在 `BANK_STATEMENT` 和 `OBJECT` 分组时,顺序保持稳定
|
||||
- 从模型人员入口进入与否不影响“返回全部异常明细”的后端查询口径,因为接口不接收当前模型参数
|
||||
|
||||
示例测试骨架:
|
||||
|
||||
```java
|
||||
@Test
|
||||
void getPersonAnalysisDetail_shouldReturnBasicInfoAndGroupedAbnormalDetail() {
|
||||
CcdiProjectPersonAnalysisDetailQueryDTO queryDTO = new CcdiProjectPersonAnalysisDetailQueryDTO();
|
||||
queryDTO.setProjectId(1L);
|
||||
queryDTO.setStaffIdCard("330101199001010011");
|
||||
|
||||
CcdiProjectPersonAnalysisDetailVO result = service.getPersonAnalysisDetail(queryDTO);
|
||||
|
||||
assertEquals("张三", result.getBasicInfo().getName());
|
||||
assertEquals("高风险", result.getBasicInfo().getRiskLevel());
|
||||
assertEquals("BANK_STATEMENT", result.getAbnormalDetail().getGroups().get(0).getGroupType());
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Write the failing controller test**
|
||||
|
||||
在 `CcdiProjectOverviewControllerTest.java` 新增控制器单测,锁定:
|
||||
|
||||
- 控制器能接收 `projectId` 和 `staffIdCard`
|
||||
- `AjaxResult.success(data)` 返回值里包含 `basicInfo` 和 `abnormalDetail`
|
||||
|
||||
- [ ] **Step 3: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewServiceImplTest,CcdiProjectOverviewControllerTest
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `FAIL`
|
||||
- 原因是服务实现和控制器查询逻辑尚未完成
|
||||
|
||||
- [ ] **Step 4: Add the minimal service/controller scaffolding**
|
||||
|
||||
在 `CcdiProjectOverviewServiceImpl.java` 中先新增空实现骨架与必要的私有辅助方法声明,例如:
|
||||
|
||||
```java
|
||||
@Override
|
||||
public CcdiProjectPersonAnalysisDetailVO getPersonAnalysisDetail(CcdiProjectPersonAnalysisDetailQueryDTO queryDTO) {
|
||||
ensureProjectExists(queryDTO.getProjectId());
|
||||
return new CcdiProjectPersonAnalysisDetailVO();
|
||||
}
|
||||
```
|
||||
|
||||
控制器中完成调用接线。
|
||||
|
||||
- [ ] **Step 5: Re-run the same tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewServiceImplTest,CcdiProjectOverviewControllerTest
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 仍可能 `FAIL`,但失败点应收敛到“数据查询为空/字段未组装”,不再是找不到方法或类
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImpl.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImplTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerTest.java
|
||||
git commit -m "搭建结果总览详情服务骨架"
|
||||
```
|
||||
|
||||
### Task 3: 补齐 Mapper 查询与 XML 结构测试
|
||||
|
||||
**Files:**
|
||||
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapper.java`
|
||||
- Modify: `ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectOverviewMapper.xml`
|
||||
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapperSqlTest.java`
|
||||
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapperXmlTest.java`
|
||||
|
||||
- [ ] **Step 1: Write the failing mapper SQL assertions**
|
||||
|
||||
在 `CcdiProjectOverviewMapperSqlTest.java` 追加断言,锁定 mapper XML 必须新增以下查询:
|
||||
|
||||
- 查询员工基础信息及部门名
|
||||
- 查询人员在项目下的流水型异常明细
|
||||
- 查询人员在项目下的 `OBJECT` 型异常摘要原始行
|
||||
|
||||
静态断言可直接检查 XML 中存在的 SQL id,例如:
|
||||
|
||||
```java
|
||||
assertTrue(source.contains("selectPersonAnalysisBasicInfo"));
|
||||
assertTrue(source.contains("selectPersonAnalysisStatementRows"));
|
||||
assertTrue(source.contains("selectPersonAnalysisObjectRows"));
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewMapperSqlTest,CcdiBankStatementMapperXmlTest
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `FAIL`
|
||||
|
||||
- [ ] **Step 3: Implement mapper methods and XML**
|
||||
|
||||
在 mapper 接口与 XML 中新增最小查询:
|
||||
|
||||
- `selectPersonAnalysisBasicInfo(projectId, staffIdCard)`
|
||||
- `selectPersonAnalysisStatementRows(projectId, staffIdCard)`
|
||||
- `selectPersonAnalysisObjectRows(projectId, staffIdCard)`
|
||||
|
||||
要求:
|
||||
|
||||
- 基础信息查询关联 `ccdi_project_overview_employee_result` 获取风险等级
|
||||
- 流水查询字段与 `CcdiBankStatementListVO` 口径对齐
|
||||
- `OBJECT` 查询只取前端摘要卡需要的最小字段,不做整对象平铺
|
||||
|
||||
SQL 方向示例:
|
||||
|
||||
```xml
|
||||
<select id="selectPersonAnalysisStatementRows" resultType="com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO">
|
||||
SELECT DISTINCT
|
||||
s.bank_statement_id,
|
||||
s.trx_date,
|
||||
s.le_account_no,
|
||||
s.le_account_name,
|
||||
s.customer_account_name,
|
||||
s.customer_account_no,
|
||||
s.user_memo,
|
||||
s.cash_type,
|
||||
s.display_amount
|
||||
FROM ccdi_bank_statement s
|
||||
...
|
||||
</select>
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Re-run the same tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewMapperSqlTest,CcdiBankStatementMapperXmlTest
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `PASS`
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapper.java ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectOverviewMapper.xml ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapperSqlTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapperXmlTest.java
|
||||
git commit -m "补充结果总览详情查询SQL"
|
||||
```
|
||||
|
||||
### Task 4: 实现服务组装逻辑并打通真实详情返回
|
||||
|
||||
**Files:**
|
||||
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImpl.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisObjectFieldVO.java`
|
||||
- Modify: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImplTest.java`
|
||||
- Modify: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerTest.java`
|
||||
|
||||
- [ ] **Step 1: Implement basic info assembly**
|
||||
|
||||
在服务层把基础信息统一组装为:
|
||||
|
||||
- `name`
|
||||
- `idNo`
|
||||
- `staffCode`
|
||||
- `department`
|
||||
- `phone`
|
||||
- `riskLevel`
|
||||
- `projectName`
|
||||
|
||||
若员工主数据查不到:
|
||||
|
||||
- 不抛异常
|
||||
- 返回空 `basicInfo` 字段并继续组装异常明细
|
||||
|
||||
- [ ] **Step 2: Implement grouped abnormal detail assembly**
|
||||
|
||||
在服务层把异常明细统一收敛为 `groups`:
|
||||
|
||||
- 流水型异常组:
|
||||
- `groupCode = BANK_STATEMENT`
|
||||
- `groupType = BANK_STATEMENT`
|
||||
- 对象型异常组:
|
||||
- `groupType = OBJECT`
|
||||
- 记录内只保留 `title/subtitle/riskTags/summary/extraFields`
|
||||
|
||||
推荐新增私有方法:
|
||||
|
||||
```java
|
||||
private CcdiProjectPersonAnalysisAbnormalGroupVO buildBankStatementGroup(...);
|
||||
private CcdiProjectPersonAnalysisAbnormalGroupVO buildObjectGroup(...);
|
||||
private List<CcdiProjectPersonAnalysisObjectFieldVO> buildObjectExtraFields(...);
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Reuse statement hit tags**
|
||||
|
||||
流水组装时不要重新发明标签结构,直接复用现有流水标签查询方式:
|
||||
|
||||
- 可复用 `CcdiBankTagResultMapper`
|
||||
- 或复用 `CcdiBankStatementServiceImpl` 当前的标签附着逻辑思路
|
||||
|
||||
但不要在服务层直接复制整段重复代码;若出现重复,抽一个结果总览域内部私有辅助方法即可。
|
||||
|
||||
- [ ] **Step 4: Run focused tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewServiceImplTest,CcdiProjectOverviewControllerTest,CcdiProjectOverviewMapperSqlTest
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `PASS`
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImpl.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisObjectFieldVO.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImplTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerTest.java
|
||||
git commit -m "实现结果总览详情数据组装"
|
||||
```
|
||||
|
||||
### Task 5: 做后端回归、写验证记录和实施记录
|
||||
|
||||
**Files:**
|
||||
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerContractTest.java`
|
||||
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerTest.java`
|
||||
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImplTest.java`
|
||||
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapperSqlTest.java`
|
||||
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapperRiskModelPeopleTest.java`
|
||||
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapperRiskModelCardsTest.java`
|
||||
- Create: `docs/tests/records/2026-03-25-results-overview-project-analysis-dialog-real-detail-backend-verification.md`
|
||||
- Create: `docs/reports/implementation/2026-03-25-results-overview-project-analysis-dialog-real-detail-backend-implementation.md`
|
||||
- Verify: `docs/design/2026-03-25-results-overview-project-analysis-dialog-real-detail-design.md`
|
||||
|
||||
- [ ] **Step 1: Run full focused regression**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewControllerContractTest,CcdiProjectOverviewControllerTest,CcdiProjectOverviewServiceImplTest,CcdiProjectOverviewMapperSqlTest,CcdiProjectOverviewMapperRiskModelPeopleTest,CcdiProjectOverviewMapperRiskModelCardsTest
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 全部 `PASS`
|
||||
|
||||
- [ ] **Step 2: Write verification record**
|
||||
|
||||
在 `docs/tests/records/2026-03-25-results-overview-project-analysis-dialog-real-detail-backend-verification.md` 记录:
|
||||
|
||||
- 执行命令
|
||||
- 执行时间
|
||||
- 关键通过项
|
||||
- 结论:详情接口已返回真实基础信息和分组异常明细
|
||||
|
||||
- [ ] **Step 3: Write implementation record**
|
||||
|
||||
在 `docs/reports/implementation/2026-03-25-results-overview-project-analysis-dialog-real-detail-backend-implementation.md` 记录:
|
||||
|
||||
- 新增接口、DTO、VO、Mapper 查询
|
||||
- 服务层如何组装 `BANK_STATEMENT` / `OBJECT`
|
||||
- 验证结果
|
||||
|
||||
- [ ] **Step 4: Review changed files**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
git diff --name-only
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 只包含本次后端实现、测试和文档文件
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewController.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiProjectOverviewService.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImpl.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapper.java ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectOverviewMapper.xml ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectPersonAnalysisDetailQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisDetailVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisBasicInfoVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisAbnormalDetailVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisAbnormalGroupVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisObjectRecordVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectPersonAnalysisObjectFieldVO.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerContractTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectOverviewServiceStructureTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImplTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapperSqlTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapperXmlTest.java docs/tests/records/2026-03-25-results-overview-project-analysis-dialog-real-detail-backend-verification.md docs/reports/implementation/2026-03-25-results-overview-project-analysis-dialog-real-detail-backend-implementation.md
|
||||
git commit -m "实现结果总览详情弹窗后端接口"
|
||||
```
|
||||
@@ -0,0 +1,422 @@
|
||||
# Results Overview Project Analysis Dialog Real Detail Frontend Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED: Use superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 将结果总览“项目分析”弹窗从静态高保真壳子升级为真实详情工作台,支持加宽弹窗、请求真实详情接口、展示员工基础信息、按类型渲染流水表格与对象摘要卡。
|
||||
|
||||
**Architecture:** 保持 `PreliminaryCheck.vue` 为结果总览唯一入口,不新增路由。`projectOverview.js` 新增详情接口方法,`PreliminaryCheck.vue` 继续统一维护弹窗开关、来源上下文和外层命中模型摘要;`ProjectAnalysisDialog.vue` 负责请求详情、处理加载与错误态,`ProjectAnalysisSidebar.vue` 只消费“真实基础信息 + 外层透传模型摘要”,`ProjectAnalysisAbnormalTab.vue` 按 `BANK_STATEMENT` / `OBJECT` 两种分组类型拆分展示。
|
||||
|
||||
**Tech Stack:** Vue 2, Element UI, SCSS, Node.js
|
||||
|
||||
---
|
||||
|
||||
### Task 1: 先锁定 API 契约与入口状态流
|
||||
|
||||
**Files:**
|
||||
- Modify: `ruoyi-ui/src/api/ccdi/projectOverview.js`
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue`
|
||||
- Test: `ruoyi-ui/tests/unit/preliminary-check-api-integration.test.js`
|
||||
- Test: `ruoyi-ui/tests/unit/preliminary-check-project-analysis-source-context.test.js`
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
补充断言,锁定以下内容:
|
||||
|
||||
- `projectOverview.js` 新增 `getOverviewPersonAnalysisDetail`
|
||||
- 请求路径为 `/ccdi/project/overview/person-analysis/detail`
|
||||
- `PreliminaryCheck.vue` 在打开弹窗时仍会保存:
|
||||
- 当前人员
|
||||
- 当前来源
|
||||
- 外层命中模型摘要
|
||||
- 详情请求所需的 `projectId` 和 `staffIdCard` 可从入口上下文中拿到
|
||||
|
||||
示例断言片段:
|
||||
|
||||
```js
|
||||
assert(source.includes('getOverviewPersonAnalysisDetail'), '缺少详情 API');
|
||||
assert(source.includes('/ccdi/project/overview/person-analysis/detail'), '详情接口路径错误');
|
||||
assert(source.includes('projectAnalysisSource'), '缺少弹窗来源状态');
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
node tests/unit/preliminary-check-api-integration.test.js
|
||||
node tests/unit/preliminary-check-project-analysis-source-context.test.js
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `FAIL`
|
||||
|
||||
- [ ] **Step 3: Write minimal implementation**
|
||||
|
||||
在 `projectOverview.js` 中新增:
|
||||
|
||||
```js
|
||||
export function getOverviewPersonAnalysisDetail(params) {
|
||||
return request({
|
||||
url: '/ccdi/project/overview/person-analysis/detail',
|
||||
method: 'get',
|
||||
params: {
|
||||
projectId: params.projectId,
|
||||
staffIdCard: params.staffIdCard
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
在 `PreliminaryCheck.vue` 中:
|
||||
|
||||
- 保持现有打开弹窗入口不变
|
||||
- 明确存储 `projectAnalysisPerson`、`projectAnalysisSource`
|
||||
- 新增或整理 `projectAnalysisModelSummary`
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
node tests/unit/preliminary-check-api-integration.test.js
|
||||
node tests/unit/preliminary-check-project-analysis-source-context.test.js
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `PASS`
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/api/ccdi/projectOverview.js ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue ruoyi-ui/tests/unit/preliminary-check-api-integration.test.js ruoyi-ui/tests/unit/preliminary-check-project-analysis-source-context.test.js
|
||||
git commit -m "补充结果总览详情弹窗前端接线"
|
||||
```
|
||||
|
||||
### Task 2: 锁定弹窗宽度、加载态和错误态
|
||||
|
||||
**Files:**
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisDialog.vue`
|
||||
- Test: `ruoyi-ui/tests/unit/project-analysis-dialog-layout.test.js`
|
||||
- Test: `ruoyi-ui/tests/unit/project-analysis-dialog-default-tab.test.js`
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
在现有弹窗测试中补充断言,锁定:
|
||||
|
||||
- 弹窗宽度由 `1280px` 调整为 `1440px`
|
||||
- 侧栏宽度调到 `340px`
|
||||
- 弹窗打开时触发详情请求
|
||||
- 存在详情加载态
|
||||
- 存在错误提示与重试入口
|
||||
- 再次打开时仍回到 `异常明细`
|
||||
|
||||
示例断言片段:
|
||||
|
||||
```js
|
||||
assert(source.includes('width="1440px"'), '弹窗未加宽到 1440px');
|
||||
assert(source.includes('fetchDetailData'), '缺少详情请求方法');
|
||||
assert(source.includes('detailLoading'), '缺少详情加载态');
|
||||
assert(source.includes('handleRetryDetail'), '缺少重试方法');
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
node tests/unit/project-analysis-dialog-layout.test.js
|
||||
node tests/unit/project-analysis-dialog-default-tab.test.js
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `FAIL`
|
||||
|
||||
- [ ] **Step 3: Write minimal implementation**
|
||||
|
||||
在 `ProjectAnalysisDialog.vue` 中完成:
|
||||
|
||||
- 宽度调为 `1440px`
|
||||
- 新增 `detailLoading`、`detailError`
|
||||
- 打开弹窗时调用 `fetchDetailData`
|
||||
- 重试时再次调用同一详情接口
|
||||
- 关闭时重置 `activeTab`、`detailLoading`、`detailError`、`detailData`
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
node tests/unit/project-analysis-dialog-layout.test.js
|
||||
node tests/unit/project-analysis-dialog-default-tab.test.js
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `PASS`
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisDialog.vue ruoyi-ui/tests/unit/project-analysis-dialog-layout.test.js ruoyi-ui/tests/unit/project-analysis-dialog-default-tab.test.js
|
||||
git commit -m "完善结果总览详情弹窗状态"
|
||||
```
|
||||
|
||||
### Task 3: 将侧栏改为真实基础信息 + 外层模型摘要
|
||||
|
||||
**Files:**
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisSidebar.vue`
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisDialog.vue`
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/preliminaryCheck.mock.js`
|
||||
- Test: `ruoyi-ui/tests/unit/project-analysis-dialog-sidebar.test.js`
|
||||
- Test: `ruoyi-ui/tests/unit/project-analysis-dialog-empty-field.test.js`
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
锁定侧栏展示边界:
|
||||
|
||||
- `人员基础信息` 来自真实详情接口返回的 `basicInfo`
|
||||
- `命中模型摘要` 来自外层透传,不依赖详情接口
|
||||
- `排查记录摘要` 仍为占位文案
|
||||
- 基础信息缺失时统一展示 `-`
|
||||
- 异常标签为空时展示“暂无异常标签”
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
node tests/unit/project-analysis-dialog-sidebar.test.js
|
||||
node tests/unit/project-analysis-dialog-empty-field.test.js
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `FAIL`
|
||||
|
||||
- [ ] **Step 3: Write minimal implementation**
|
||||
|
||||
在 `ProjectAnalysisDialog.vue` 中把弹窗数据源拆成两部分:
|
||||
|
||||
- `detailData.basicInfo`
|
||||
- `sourceSummary/modelSummary`
|
||||
|
||||
在 `ProjectAnalysisSidebar.vue` 中只负责渲染:
|
||||
|
||||
- 真实 `basicInfo`
|
||||
- 外层传入的 `modelSummary`
|
||||
- 静态 `recordSummary`
|
||||
|
||||
在 `preliminaryCheck.mock.js` 中保留:
|
||||
|
||||
- 占位页签
|
||||
- 默认空结构
|
||||
|
||||
移除对真实基础信息和异常明细的 mock 拼装依赖。
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
node tests/unit/project-analysis-dialog-sidebar.test.js
|
||||
node tests/unit/project-analysis-dialog-empty-field.test.js
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `PASS`
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisSidebar.vue ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisDialog.vue ruoyi-ui/src/views/ccdiProject/components/detail/preliminaryCheck.mock.js ruoyi-ui/tests/unit/project-analysis-dialog-sidebar.test.js ruoyi-ui/tests/unit/project-analysis-dialog-empty-field.test.js
|
||||
git commit -m "改造结果总览详情弹窗侧栏数据源"
|
||||
```
|
||||
|
||||
### Task 4: 把异常明细主视图改为分组渲染
|
||||
|
||||
**Files:**
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisAbnormalTab.vue`
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisDialog.vue`
|
||||
- Test: `ruoyi-ui/tests/unit/project-analysis-dialog-abnormal-tab.test.js`
|
||||
- Test: `ruoyi-ui/tests/unit/project-analysis-dialog-source-highlight.test.js`
|
||||
- Test: `ruoyi-ui/tests/unit/detail-query-hit-tags-list.test.js`
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
锁定异常明细渲染规则:
|
||||
|
||||
- 遍历 `abnormalDetail.groups`
|
||||
- `BANK_STATEMENT` 分组渲染表格
|
||||
- 表格字段贴近流水明细查询:
|
||||
- 交易时间
|
||||
- 本方账户
|
||||
- 对方账户
|
||||
- 摘要 / 交易类型
|
||||
- 异常标签
|
||||
- 交易金额
|
||||
- `OBJECT` 分组渲染摘要卡
|
||||
- 来源于模型列表时仍显示“当前命中模型”强调,但异常明细不按当前模型过滤
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
node tests/unit/project-analysis-dialog-abnormal-tab.test.js
|
||||
node tests/unit/project-analysis-dialog-source-highlight.test.js
|
||||
node tests/unit/detail-query-hit-tags-list.test.js
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `FAIL`
|
||||
|
||||
- [ ] **Step 3: Write minimal implementation**
|
||||
|
||||
在 `ProjectAnalysisAbnormalTab.vue` 中按类型拆分渲染:
|
||||
|
||||
- `BANK_STATEMENT`
|
||||
- 复用 `DetailQuery.vue` 里的表格字段节奏和金额/标签展示样式
|
||||
- `OBJECT`
|
||||
- 输出卡片列表
|
||||
- 每张卡只展示 `title/subtitle/riskTags/summary/extraFields`
|
||||
|
||||
若某个分组没有记录:
|
||||
|
||||
- 不单独渲染空壳卡片
|
||||
|
||||
若全部分组为空:
|
||||
|
||||
- 渲染统一空态
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
node tests/unit/project-analysis-dialog-abnormal-tab.test.js
|
||||
node tests/unit/project-analysis-dialog-source-highlight.test.js
|
||||
node tests/unit/detail-query-hit-tags-list.test.js
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `PASS`
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisAbnormalTab.vue ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisDialog.vue ruoyi-ui/tests/unit/project-analysis-dialog-abnormal-tab.test.js ruoyi-ui/tests/unit/project-analysis-dialog-source-highlight.test.js ruoyi-ui/tests/unit/detail-query-hit-tags-list.test.js
|
||||
git commit -m "实现结果总览详情弹窗异常分组展示"
|
||||
```
|
||||
|
||||
### Task 5: 做前端回归、手工验证和文档沉淀
|
||||
|
||||
**Files:**
|
||||
- Test: `ruoyi-ui/tests/unit/preliminary-check-summary-and-people.test.js`
|
||||
- Test: `ruoyi-ui/tests/unit/preliminary-check-model-linkage-flow.test.js`
|
||||
- Test: `ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js`
|
||||
- Test: `ruoyi-ui/tests/unit/project-analysis-dialog-layout.test.js`
|
||||
- Test: `ruoyi-ui/tests/unit/project-analysis-dialog-sidebar.test.js`
|
||||
- Test: `ruoyi-ui/tests/unit/project-analysis-dialog-abnormal-tab.test.js`
|
||||
- Create: `docs/tests/records/2026-03-25-results-overview-project-analysis-dialog-real-detail-frontend-verification.md`
|
||||
- Create: `docs/reports/implementation/2026-03-25-results-overview-project-analysis-dialog-real-detail-frontend-implementation.md`
|
||||
- Verify: `docs/design/2026-03-25-results-overview-project-analysis-dialog-real-detail-design.md`
|
||||
|
||||
- [ ] **Step 1: Run focused regression**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
node tests/unit/preliminary-check-summary-and-people.test.js
|
||||
node tests/unit/preliminary-check-model-linkage-flow.test.js
|
||||
node tests/unit/preliminary-check-model-and-detail.test.js
|
||||
node tests/unit/project-analysis-dialog-layout.test.js
|
||||
node tests/unit/project-analysis-dialog-sidebar.test.js
|
||||
node tests/unit/project-analysis-dialog-abnormal-tab.test.js
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 全部 `PASS`
|
||||
|
||||
- [ ] **Step 2: Run production build**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
npm run build:prod
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `BUILD SUCCESS` 或等价成功输出
|
||||
|
||||
- [ ] **Step 3: Manual verification**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
npm run dev
|
||||
```
|
||||
|
||||
手工检查:
|
||||
|
||||
- 结果总览两个入口都能打开同一个弹窗
|
||||
- 弹窗宽度已加宽
|
||||
- 打开时先看到加载态,再展示真实数据
|
||||
- 基础信息为真实员工信息
|
||||
- 模型摘要仍取自外层入口
|
||||
- 流水型异常显示表格
|
||||
- `OBJECT` 型异常显示摘要卡
|
||||
|
||||
验证完成后主动关闭前端开发进程。
|
||||
|
||||
- [ ] **Step 4: Write verification and implementation records**
|
||||
|
||||
在 `docs/tests/records/2026-03-25-results-overview-project-analysis-dialog-real-detail-frontend-verification.md` 记录:
|
||||
|
||||
- 单测命令
|
||||
- build 命令
|
||||
- 手工验证步骤与结果
|
||||
|
||||
在 `docs/reports/implementation/2026-03-25-results-overview-project-analysis-dialog-real-detail-frontend-implementation.md` 记录:
|
||||
|
||||
- API 接线
|
||||
- 弹窗状态改造
|
||||
- 侧栏真实数据与外层摘要拆分
|
||||
- 分组展示实现
|
||||
|
||||
- [ ] **Step 5: Review changed files and commit**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
git diff --name-only
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 只包含本次前端实现、测试和文档文件
|
||||
|
||||
Commit:
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/api/ccdi/projectOverview.js ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisDialog.vue ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisSidebar.vue ruoyi-ui/src/views/ccdiProject/components/detail/ProjectAnalysisAbnormalTab.vue ruoyi-ui/src/views/ccdiProject/components/detail/preliminaryCheck.mock.js ruoyi-ui/tests/unit/preliminary-check-api-integration.test.js ruoyi-ui/tests/unit/preliminary-check-project-analysis-source-context.test.js ruoyi-ui/tests/unit/project-analysis-dialog-layout.test.js ruoyi-ui/tests/unit/project-analysis-dialog-default-tab.test.js ruoyi-ui/tests/unit/project-analysis-dialog-sidebar.test.js ruoyi-ui/tests/unit/project-analysis-dialog-empty-field.test.js ruoyi-ui/tests/unit/project-analysis-dialog-abnormal-tab.test.js ruoyi-ui/tests/unit/project-analysis-dialog-source-highlight.test.js ruoyi-ui/tests/unit/detail-query-hit-tags-list.test.js docs/tests/records/2026-03-25-results-overview-project-analysis-dialog-real-detail-frontend-verification.md docs/reports/implementation/2026-03-25-results-overview-project-analysis-dialog-real-detail-frontend-implementation.md
|
||||
git commit -m "实现结果总览详情弹窗前端接线"
|
||||
```
|
||||
@@ -0,0 +1,30 @@
|
||||
# 结果总览项目分析弹窗真实详情实施计划记录
|
||||
|
||||
## 变更概述
|
||||
|
||||
- 基于已确认的真实详情设计文档,新增后端实施计划 1 份。
|
||||
- 基于已确认的真实详情设计文档,新增前端实施计划 1 份。
|
||||
- 本轮计划覆盖详情接口、侧栏真实数据接入、异常明细分组展示和验证记录沉淀。
|
||||
- 本轮仅完成实施计划沉淀,尚未进入代码实现阶段。
|
||||
|
||||
## 新增文件
|
||||
|
||||
- `docs/plans/backend/2026-03-25-results-overview-project-analysis-dialog-real-detail-backend-implementation.md`
|
||||
- `docs/plans/frontend/2026-03-25-results-overview-project-analysis-dialog-real-detail-frontend-implementation.md`
|
||||
|
||||
## 计划结论
|
||||
|
||||
- 后端计划聚焦结果总览域内新增详情接口,统一返回:
|
||||
- 员工基础信息
|
||||
- `BANK_STATEMENT` 流水型异常分组
|
||||
- `OBJECT` 对象型摘要分组
|
||||
- 前端计划聚焦:
|
||||
- 详情 API 接线
|
||||
- 弹窗宽度与状态管理调整
|
||||
- 侧栏真实基础信息与外层命中模型摘要拆分
|
||||
- 流水表格与对象摘要卡分组渲染
|
||||
|
||||
## 说明
|
||||
|
||||
- 本次按仓库规范,将实施计划分别落到 `docs/plans/backend/` 与 `docs/plans/frontend/`。
|
||||
- 由于仓库约定不启用 subagent,后续执行阶段应在当前会话按计划顺序推进。
|
||||
Reference in New Issue
Block a user