提交结果总览模型卡片联动筛选实施计划文档

This commit is contained in:
wkc
2026-03-20 10:58:44 +08:00
parent 190ad21bbd
commit d29e243aaf
3 changed files with 668 additions and 0 deletions

View File

@@ -0,0 +1,297 @@
# Results Overview Risk Model Linkage Backend Implementation Plan
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 为结果总览模型区新增真实后端接口,支持模型卡片统计、人员分页查询,以及多卡片下“任意触发 / 同时触发”两种筛选方式。
**Architecture:** 继续沿用 `CcdiProjectOverviewController + Service + Mapper` 的结果总览链路,复用现有“员工本人 + 亲属归并到员工名下”的基础聚合 SQL不新建平行模块或补丁式接口。模型卡片统计与人员列表查询都建立在同一套员工归并口径上保证模型区与风险人员区统计一致。
**Tech Stack:** Java 21, Spring Boot 3, MyBatis XML, Maven, JUnit 5
---
### Task 1: 定义接口、DTO 与 VO 结构
**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/CcdiProjectRiskModelPeopleQueryDTO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectRiskModelCardVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectRiskModelCardsVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectRiskModelPeopleItemVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectRiskModelPeopleVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectRiskHitTagVO.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerContractTest.java`
- [ ] **Step 1: Write the failing test**
为控制器契约补静态/反射测试,锁定以下方法和路径:
- `GET /ccdi/project/overview/risk-models/cards`
- `GET /ccdi/project/overview/risk-models/people`
并锁定 DTO 字段:
- `projectId`
- `modelCodes`
- `matchMode`
- `keyword`
- `deptId`
- `pageNum`
- `pageSize`
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewControllerContractTest
```
Expected:
- `FAIL`
- 原因是接口与类型尚未创建
- [ ] **Step 3: Write minimal implementation**
补齐控制器、服务接口、DTO 与 VO。
DTO 关键约束:
- `modelCodes` 为多值条件
- `matchMode` 只允许 `ANY``ALL`
- `modelCodes` 为空时忽略 `matchMode`
VO 关键字段:
- 卡片:`modelCode``modelName``warningCount``peopleCount`
- 列表:`staffName``staffCode``idNo``department``modelNames``hitTagList``actionLabel`
- 标签:`ruleCode``ruleName``riskLevel`
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewControllerContractTest
```
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/CcdiProjectRiskModelPeopleQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectRiskModelCardVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectRiskModelCardsVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectRiskModelPeopleItemVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectRiskModelPeopleVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectRiskHitTagVO.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerContractTest.java
git commit -m "定义结果总览模型区接口结构"
```
### Task 2: 扩展模型卡片统计 SQL
**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/CcdiProjectOverviewMapperRiskModelCardsTest.java`
- [ ] **Step 1: Write the failing test**
为模型卡片统计新增 mapper 测试,锁定以下口径:
- `warningCount` = 当前项目、当前模型的命中结果数
- `peopleCount` = 当前模型归并后的员工人数
- 排序按 `warningCount desc, model_code asc`
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewMapperRiskModelCardsTest
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
`CcdiProjectOverviewMapper.xml` 中:
- 复用 `resolvedEmployeeRiskBaseSql`
- 新增模型卡片查询
- 预警次数直接以标签命中记录计数
- 涉及人数按 `staff_id_card` 去重
不要新增新表、不要引入额外统计口径。
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewMapperRiskModelCardsTest
```
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/CcdiProjectOverviewMapperRiskModelCardsTest.java
git commit -m "补充结果总览模型卡片统计查询"
```
### Task 3: 实现人员分页查询与匹配模式
**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/CcdiProjectOverviewMapperRiskModelPeopleTest.java`
- [ ] **Step 1: Write the failing test**
新增列表查询测试,覆盖:
- 不选模型时返回全部模型命中人员
- 多模型 `ANY` 时按并集返回
- 多模型 `ALL` 时按交集返回
- `keyword` 同时匹配姓名与工号
- `deptId` 精确筛选
- `hitTagList``modelNames` 只返回当前筛选上下文内的数据
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewMapperRiskModelPeopleTest
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
列表查询要求:
- 补齐员工工号字段映射;如果员工表实际字段不是 `staff_code`,按真实字段落地
- `ANY`:命中任一所选模型即可
- `ALL`:员工命中的所选模型去重数必须等于所选模型数
- `modelNames` 只拼接当前所选模型范围内的模型名称
- `hitTagList` 只返回当前所选模型范围内的标签
- 标签排序按风险等级、规则编码稳定输出
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewMapperRiskModelPeopleTest
```
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/CcdiProjectOverviewMapperRiskModelPeopleTest.java
git commit -m "补充结果总览模型区人员分页查询"
```
### Task 4: 完成服务组装与控制器返回
**Files:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImpl.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImplTest.java`
- [ ] **Step 1: Write the failing test**
在服务测试中补充:
- 项目不存在时抛出统一异常
- 卡片接口返回 `cardList`
- 人员接口返回 `rows + total`
- 空列表返回空数组,不返回 `null`
- `actionLabel` 固定为“查看详情”
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewServiceImplTest
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
在服务层:
- 统一做项目存在性校验
- 卡片接口直接封装 `cardList`
- 人员接口封装 `rows``total`
- `matchMode` 默认值为 `ANY`
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectOverviewServiceImplTest
```
Expected:
- `PASS`
- [ ] **Step 5: 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
git commit -m "完成结果总览模型区服务组装"
```
### Task 5: 后端回归验证与实施记录
**Files:**
- Modify: `docs/plans/backend/2026-03-20-results-overview-risk-model-linkage-backend-implementation.md`
- Create: `docs/tests/records/2026-03-20-results-overview-risk-model-linkage-backend-verification.md`
- Create: `docs/reports/implementation/2026-03-20-results-overview-risk-model-linkage-backend-implementation.md`
- [ ] **Step 1: Run backend verification**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectOverview*
```
Expected:
- `PASS`
- [ ] **Step 2: Write verification and implementation records**
记录:
- 模型卡片接口
- 人员分页接口
- `ANY / ALL` 两种匹配方式
- 验证命令与结论
- [ ] **Step 3: Commit**
```bash
git add docs/plans/backend/2026-03-20-results-overview-risk-model-linkage-backend-implementation.md docs/tests/records/2026-03-20-results-overview-risk-model-linkage-backend-verification.md docs/reports/implementation/2026-03-20-results-overview-risk-model-linkage-backend-implementation.md
git commit -m "补充结果总览模型区后端实施记录"
```

View File

@@ -0,0 +1,338 @@
# Results Overview Risk Model Linkage Frontend Implementation Plan
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 将结果总览模型区接入真实接口,支持多卡片联动、任意触发/同时触发切换、员工姓名或工号与部门筛选,以及异常标签展示。
**Architecture:** 保持 `PreliminaryCheck.vue` 作为结果总览页面主入口,不新增路由或二级页面。模型卡片接口与人员列表接口分开请求,`RiskModelSection.vue` 内统一维护卡片选择、匹配模式、关键词、部门和分页状态,列表按状态组合查询。
**Tech Stack:** Vue 2, Element UI, Axios (`@/utils/request`), Node.js
---
### Task 1: 补模型区 API 封装
**Files:**
- Modify: `ruoyi-ui/src/api/ccdi/projectOverview.js`
- Test: `ruoyi-ui/tests/unit/preliminary-check-model-api.test.js`
- [ ] **Step 1: Write the failing test**
新增接口静态断言,锁定以下方法与路径:
- `getOverviewRiskModelCards`
- `getOverviewRiskModelPeople`
- `/ccdi/project/overview/risk-models/cards`
- `/ccdi/project/overview/risk-models/people`
- `matchMode`
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
cd ruoyi-ui
node tests/unit/preliminary-check-model-api.test.js
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
在 API 模块中新增:
- `getOverviewRiskModelCards(projectId)`
- `getOverviewRiskModelPeople(params)`
列表接口需透传:
- `projectId`
- `modelCodes`
- `matchMode`
- `keyword`
- `deptId`
- `pageNum`
- `pageSize`
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
cd ruoyi-ui
node tests/unit/preliminary-check-model-api.test.js
```
Expected:
- `PASS`
- [ ] **Step 5: Commit**
```bash
git add ruoyi-ui/src/api/ccdi/projectOverview.js ruoyi-ui/tests/unit/preliminary-check-model-api.test.js
git commit -m "补充结果总览模型区前端接口封装"
```
### Task 2: 在入口页接入模型区真实数据
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue`
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/preliminaryCheck.mock.js`
- Test: `ruoyi-ui/tests/unit/preliminary-check-model-data-loading.test.js`
- [ ] **Step 1: Write the failing test**
新增入口页静态断言,要求:
- `PreliminaryCheck.vue` 引入 `getOverviewRiskModelCards`
- 模型区真实数据不再只依赖旧 mock
- 页面仍保留 `loading / empty / loaded` 状态结构
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
cd ruoyi-ui
node tests/unit/preliminary-check-model-data-loading.test.js
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
`PreliminaryCheck.vue` 中:
- 拉取模型卡片真实数据
- 将模型区交给 `RiskModelSection.vue` 内部继续请求列表接口
- 清理 `preliminaryCheck.mock.js` 中模型区旧的 `warningTypeOptions`、旧 `filterValues.model` 依赖
- 保留空态 mock 作为兜底展示结构,不新增业务逻辑兜底
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
cd ruoyi-ui
node tests/unit/preliminary-check-model-data-loading.test.js
```
Expected:
- `PASS`
- [ ] **Step 5: Commit**
```bash
git add ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue ruoyi-ui/src/views/ccdiProject/components/detail/preliminaryCheck.mock.js ruoyi-ui/tests/unit/preliminary-check-model-data-loading.test.js
git commit -m "接入结果总览模型卡片真实数据"
```
### Task 3: 改造模型卡片多选与触发方式切换
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/RiskModelSection.vue`
- Test: `ruoyi-ui/tests/unit/preliminary-check-model-multiselect.test.js`
- Test: `ruoyi-ui/tests/unit/preliminary-check-model-match-mode.test.js`
- [ ] **Step 1: Write the failing test**
新增组件静态/行为断言,锁定:
- 卡片支持多选
- 再次点击已选卡片可取消
- 存在 `matchMode`
- 页面出现“任意触发”“同时触发”文案
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
cd ruoyi-ui
node tests/unit/preliminary-check-model-multiselect.test.js
node tests/unit/preliminary-check-model-match-mode.test.js
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
`RiskModelSection.vue` 中新增状态:
- `selectedModelCodes`
- `matchMode`
- `keyword`
- `deptId`
- `pageNum`
- `pageSize`
- `cardLoading`
- `tableLoading`
交互规则:
- 默认 `selectedModelCodes = []`
- 默认 `matchMode = "ANY"`
- 选中多张卡片时允许切换 `ANY / ALL`
- 不选卡片或仅选一张时,切换模式不报错,仍按当前接口语义请求
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
cd ruoyi-ui
node tests/unit/preliminary-check-model-multiselect.test.js
node tests/unit/preliminary-check-model-match-mode.test.js
```
Expected:
- `PASS`
- [ ] **Step 5: Commit**
```bash
git add ruoyi-ui/src/views/ccdiProject/components/detail/RiskModelSection.vue ruoyi-ui/tests/unit/preliminary-check-model-multiselect.test.js ruoyi-ui/tests/unit/preliminary-check-model-match-mode.test.js
git commit -m "补充结果总览模型卡片联动交互"
```
### Task 4: 替换筛选条与人员列表列
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/RiskModelSection.vue`
- Test: `ruoyi-ui/tests/unit/preliminary-check-model-filters.test.js`
- Test: `ruoyi-ui/tests/unit/preliminary-check-model-table-columns.test.js`
- [ ] **Step 1: Write the failing test**
锁定以下变更:
- 删除“筛查模型”
- 删除“预警类型”
- 新增“员工姓名或工号”
- 新增“部门”
- 新增“任意触发”“同时触发”
- 删除“预警类型”列
- 新增“工号”列
- 新增“异常标签”列
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
cd ruoyi-ui
node tests/unit/preliminary-check-model-filters.test.js
node tests/unit/preliminary-check-model-table-columns.test.js
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
在筛选区:
- 保留 `查询 / 重置`
- 关键词输入框支持姓名或工号
- 部门优先复用仓库现有部门选项接口
- 重置时恢复:
- `selectedModelCodes = []`
- `matchMode = "ANY"`
- `keyword = ""`
- `deptId = undefined`
- `pageNum = 1`
在表格列:
- 删除 `warningType`
- 增加 `staffCode`
- `modelNames` 显示当前上下文模型名称摘要
- `hitTagList``el-tag` 展示 `ruleName`
- 颜色映射复用 `DetailQuery.vue` 风险等级映射方式
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
cd ruoyi-ui
node tests/unit/preliminary-check-model-filters.test.js
node tests/unit/preliminary-check-model-table-columns.test.js
```
Expected:
- `PASS`
- [ ] **Step 5: Commit**
```bash
git add ruoyi-ui/src/views/ccdiProject/components/detail/RiskModelSection.vue ruoyi-ui/tests/unit/preliminary-check-model-filters.test.js ruoyi-ui/tests/unit/preliminary-check-model-table-columns.test.js
git commit -m "调整结果总览模型区筛选与列表列"
```
### Task 5: 前端联调验证与实施记录
**Files:**
- Modify: `ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js`
- Create: `ruoyi-ui/tests/unit/preliminary-check-model-linkage-flow.test.js`
- Modify: `docs/plans/frontend/2026-03-20-results-overview-risk-model-linkage-frontend-implementation.md`
- Create: `docs/tests/records/2026-03-20-results-overview-risk-model-linkage-frontend-verification.md`
- Create: `docs/reports/implementation/2026-03-20-results-overview-risk-model-linkage-frontend-implementation.md`
- [ ] **Step 1: Write linkage flow assertions**
覆盖以下联动流:
- 默认全部模型
- 选中一张卡片
- 同时选中多张卡片 + `ANY`
- 同时选中多张卡片 + `ALL`
- 取消部分卡片
- 全部取消恢复默认
- 关键词 + 部门 + 多卡片叠加
- [ ] **Step 2: Run final frontend verification**
Run:
```bash
cd ruoyi-ui
node tests/unit/preliminary-check-model-api.test.js
node tests/unit/preliminary-check-model-data-loading.test.js
node tests/unit/preliminary-check-model-multiselect.test.js
node tests/unit/preliminary-check-model-match-mode.test.js
node tests/unit/preliminary-check-model-filters.test.js
node tests/unit/preliminary-check-model-table-columns.test.js
node tests/unit/preliminary-check-model-linkage-flow.test.js
```
Expected:
- `PASS`
- [ ] **Step 3: Write verification and implementation records**
记录:
- 模型区真实接口接入
- 多卡片联动
- 任意触发 / 同时触发切换
- 关键词、部门、分页联动验证
- [ ] **Step 4: Commit**
```bash
git add ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js ruoyi-ui/tests/unit/preliminary-check-model-linkage-flow.test.js docs/plans/frontend/2026-03-20-results-overview-risk-model-linkage-frontend-implementation.md docs/tests/records/2026-03-20-results-overview-risk-model-linkage-frontend-verification.md docs/reports/implementation/2026-03-20-results-overview-risk-model-linkage-frontend-implementation.md
git commit -m "补充结果总览模型区前端实施记录"
```

View File

@@ -0,0 +1,33 @@
# 结果总览模型卡片联动筛选计划记录
## 变更概述
- 新增结果总览模型区后端实施计划 1 份。
- 新增结果总览模型区前端实施计划 1 份。
- 本次计划已纳入模型卡片多选联动,以及“任意触发 / 同时触发”两种筛选模式。
- 本轮仅完成实施计划沉淀,尚未进入代码实现阶段。
## 新增文件
- `docs/plans/backend/2026-03-20-results-overview-risk-model-linkage-backend-implementation.md`
- `docs/plans/frontend/2026-03-20-results-overview-risk-model-linkage-frontend-implementation.md`
## 计划结论
- 后端计划聚焦结果总览模型区两个接口:模型卡片统计、命中模型人员分页。
- 人员分页查询统一支持:
- 多模型选择
- `ANY` 任意触发
- `ALL` 同时触发
- 员工姓名或工号查询
- 部门筛选
- 前端计划聚焦:
- 模型卡片多选
- 触发方式切换
- 列表筛选项替换
- 异常标签展示
## 说明
- 本次按仓库规范,将实施计划分别落到 `docs/plans/backend/``docs/plans/frontend/`
- 因本轮需求是补充与提交文档,故同步新增本计划记录,作为本次改动的实施文档。