# 结果总览模型区联动筛选后端验证记录

## 验证范围

- 风险模型卡片接口结构与卡片统计 SQL
- 风险模型人员分页接口结构与分页 SQL
- 多模型 `ANY / ALL` 匹配模式
- 服务层卡片封装、分页封装与默认 `actionLabel`

## 验证命令

```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewControllerContractTest
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewMapperRiskModelCardsTest
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewMapperRiskModelPeopleTest
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewServiceImplTest
mvn test -pl ccdi-project '-Dtest=CcdiProjectOverview*'
mvn -pl ruoyi-admin -am package -DskipTests
java -jar ruoyi-admin/target/ruoyi-admin.jar --server.port=62319
```

## 验证结果

- 2026-03-20 11:05 执行 `CcdiProjectOverviewControllerContractTest` 红灯验证，确认缺少 `getRiskModelCards` 方法和 `CcdiProjectRiskModelPeopleQueryDTO` 类型。
- 2026-03-20 11:06 重新执行 `CcdiProjectOverviewControllerContractTest`，3 个测试全部通过。
- 2026-03-20 11:07 执行 `CcdiProjectOverviewMapperRiskModelCardsTest` 红灯验证，确认缺少卡片 mapper 方法与统计 SQL。
- 2026-03-20 11:08 重新执行 `CcdiProjectOverviewMapperRiskModelCardsTest`，2 个测试全部通过。
- 2026-03-20 11:11 执行 `CcdiProjectOverviewMapperRiskModelPeopleTest` 红灯验证，确认缺少分页 mapper 方法与 `ANY / ALL` SQL 片段。
- 2026-03-20 11:12 修正测试断言后重新执行 `CcdiProjectOverviewMapperRiskModelPeopleTest`，2 个测试全部通过。
- 2026-03-20 11:14 执行 `CcdiProjectOverviewServiceImplTest` 红灯验证，确认服务层尚未完成项目校验、分页封装和默认 `ANY` 逻辑。
- 2026-03-20 11:15 重新执行 `CcdiProjectOverviewServiceImplTest`，9 个测试全部通过。
- 2026-03-20 11:16 执行结果总览相关总体验证命令 `mvn test -pl ccdi-project '-Dtest=CcdiProjectOverview*'`，共 22 个测试全部通过，0 failure，0 error。
- 2026-03-20 11:59 根据线上异常日志补充 `CcdiProjectOverviewMapperRiskModelPeopleTest` 红灯断言，确认 `selectRiskModelPeoplePage` 缺少 `query.projectId -> projectId` 绑定桥接。
- 2026-03-20 11:59 在 `selectRiskModelPeoplePage` 增加 `<bind name="projectId" value="query.projectId"/>` 后重新执行 `CcdiProjectOverviewMapperRiskModelPeopleTest`，2 个测试全部通过。
- 2026-03-20 12:00 再次执行结果总览相关总体验证命令 `mvn test -pl ccdi-project '-Dtest=CcdiProjectOverview*'`，共 22 个测试全部通过，0 failure，0 error。
- 2026-03-20 12:05 根据线上异常日志补充 `CcdiProjectOverviewMapperRiskModelPeopleTest` 红灯断言，确认 `selectRiskModelNamesByScope` 存在 `distinct + order by 非 select 列` 的 MySQL 兼容性问题。
- 2026-03-20 12:05 将 `selectRiskModelNamesByScope` 调整为 `group by scoped.model_code, scoped.model_name` 后重新执行 `CcdiProjectOverviewMapperRiskModelPeopleTest`，2 个测试全部通过。
- 2026-03-20 12:05 再次执行结果总览相关总体验证命令 `mvn test -pl ccdi-project '-Dtest=CcdiProjectOverview*'`，共 22 个测试全部通过，0 failure，0 error。
- 2026-03-20 12:19 根据真实接口 `matchMode=ALL` 的 500 日志补充 `CcdiProjectOverviewMapperRiskModelPeopleTest` 红灯断言，确认 `having count(distinct base.model_code) = #{query.modelCodes.size}` 会在 MyBatis `CollectionWrapper.get("size")` 阶段触发 `UnsupportedOperationException`。
- 2026-03-20 12:20 将 `ALL` 条件改为绑定 `#{query.modelCodesCount}` 后重新执行 `mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewMapperRiskModelPeopleTest`，2 个测试全部通过。
- 2026-03-20 12:20 再次执行结果总览相关总体验证命令 `mvn test -pl ccdi-project '-Dtest=CcdiProjectOverview*'`，共 22 个测试全部通过，0 failure，0 error。
- 2026-03-20 12:21 执行 `mvn -pl ruoyi-admin -am package -DskipTests`，主应用重新打包成功。
- 2026-03-20 12:56 启动临时后端实例 `java -jar ruoyi-admin/target/ruoyi-admin.jar --server.port=62319` 后，实际调用以下接口均返回 `code=200`：
  - `/ccdi/project/overview/risk-models/cards?projectId=42`
  - `/ccdi/project/overview/risk-models/people?projectId=42&pageNum=1&pageSize=5`
  - `/ccdi/project/overview/risk-models/people?projectId=42&modelCodes=LARGE_TRANSACTION&matchMode=ANY&pageNum=1&pageSize=5`
  - `/ccdi/project/overview/risk-models/people?projectId=42&modelCodes=LARGE_TRANSACTION&matchMode=ALL&pageNum=1&pageSize=5`
- 2026-03-20 13:33 根据“模型触发次数为 0 也要展示卡片”的新要求，先修改 `CcdiProjectOverviewMapperRiskModelCardsTest` 让其红灯，锁定卡片 SQL 必须以 `ccdi_bank_tag_rule` 为全量模型源并对 `warningCount/peopleCount` 做 `0` 值回填。
- 2026-03-20 13:34 将 `selectRiskModelCardsByProjectId` 改为 `ccdi_bank_tag_rule` 主表左连当前项目命中聚合后，重新执行 `mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewMapperRiskModelCardsTest`，2 个测试全部通过。
- 2026-03-20 13:34 再次执行结果总览相关总体验证命令 `mvn test -pl ccdi-project '-Dtest=CcdiProjectOverview*'`，共 22 个测试全部通过，0 failure，0 error。
- 2026-03-20 13:34 查询数据库确认 `ccdi_bank_tag_rule` 启用模型数为 `10`，项目 `42` 命中过的模型数为 `1`，具备“0 次卡片”真实回归条件。
- 2026-03-20 13:34 执行 `mvn -pl ruoyi-admin -am package -DskipTests`，主应用重新打包成功。
- 2026-03-20 13:34 启动临时后端实例 `java -jar ruoyi-admin/target/ruoyi-admin.jar --server.port=62319`，调用 `/ccdi/project/overview/risk-models/cards?projectId=42` 返回 `10` 张卡片，其中 `LARGE_TRANSACTION` 为 `warningCount=2552, peopleCount=1`，其余 `9` 张卡片均为 `warningCount=0, peopleCount=0`。

## 结论

- 结果总览模型区后端已补齐两个新接口：模型卡片统计与模型命中人员分页。
- 人员分页查询已覆盖多模型 `ANY / ALL`、姓名/工号关键字、部门筛选，以及筛选上下文内的 `modelNames`/`hitTagList` 聚合。
- 风险模型人员分页 SQL 已补齐 `projectId` 绑定桥接，避免公共 SQL 片段在分页查询场景下触发 MyBatis `Parameter 'projectId' not found` 异常。
- 风险模型名称子查询已移除 `distinct + 非 select 列排序` 组合，避免 MySQL 8 在 `ONLY_FULL_GROUP_BY` 兼容校验下抛出 3065 异常。
- 风险模型人员分页 `ALL` 条件已改为绑定 DTO 显式计数字段 `modelCodesCount`，避免 MyBatis 在读取 `query.modelCodes.size` 时触发 `UnsupportedOperationException`。
- 风险模型卡片统计已改为从 `ccdi_bank_tag_rule` 的启用模型定义出发，再左连项目命中聚合，因此命中次数为 `0` 的模型也会展示卡片并返回 `warningCount=0`、`peopleCount=0`。
- 服务层已统一完成项目存在性校验、空列表封装和“查看详情”动作文案赋值。
- 本轮验证除 Maven 测试外，还启动了临时后端实例 `62319` 做真实接口回归；验证结束后已关闭该临时进程。
