Files
ccdi/docs/design/2026-03-29-project-detail-risk-overview-risk-people-pagination-design.md

365 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 项目详情风险总览员工列表分页设计文档
**模块**: 项目详情 - 结果总览 - 风险总览员工列表
**日期**: 2026-03-29
## 一、背景
当前项目详情页 `结果总览 -> 风险总览` 中的员工列表直接消费 `GET /ccdi/project/overview/risk-people` 返回的全量 `overviewList`。页面没有分页能力,项目内风险员工较多时会导致:
1. 单屏信息过长,浏览成本高。
2. 前端一次性渲染全量列表,交互体验不稳定。
3. 接口返回风格与当前结果总览域内其他分页接口不一致。
本轮需求要求为该员工列表增加分页,并固定为每页 5 条。同时,需求明确要求改造现有接口,不采用前端本地切片或新增补丁接口的方式。
## 二、目标
本次设计目标如下:
1.`GET /ccdi/project/overview/risk-people` 改造成真实分页接口。
2. 风险总览员工列表固定每页展示 5 条。
3. 前端翻页时仅刷新员工列表,不影响结果总览内其他区块。
4. 分页接口返回结构对齐项目现有分页风格,统一为 `rows + total + pageNum + pageSize`
## 三、范围
### 3.1 本次范围
- 改造 `risk-people` 接口入参与返回结构
- 为后端风险人员查询增加数据库分页
- 调整项目详情结果总览首屏数据装配
-`RiskPeopleSection.vue` 增加分页条与翻页请求
- 补充本次设计文档、设计记录,以及后续前后端实施计划入口
### 3.2 不在本次范围
- 不修改风险仪表盘接口
- 不修改风险模型卡片与模型命中人员查询
- 不修改风险明细区块
- 不新增筛选条件、搜索条件或排序条件
- 不修改风险等级、命中模型数、核心异常点的业务口径
- 不删除现有 `GET /ccdi/project/overview/top-risk-people`
## 四、现状分析
### 4.1 前端现状
当前 `PreliminaryCheck.vue` 在页面加载时并发请求:
- `GET /ccdi/project/overview/dashboard`
- `GET /ccdi/project/overview/risk-people`
- `GET /ccdi/project/overview/risk-models/cards`
- `GET /ccdi/project/overview/suspicious-transactions`
- `GET /ccdi/project/overview/employee-credit-negative`
其中 `risk-people` 的返回结果被直接注入 `currentData.riskPeople.overviewList``RiskPeopleSection.vue` 直接用该数组渲染表格,没有分页状态,也没有独立二次加载链路。
### 4.2 后端现状
当前 `CcdiProjectOverviewController.getRiskPeople(Long projectId)` 只接收项目 ID。
`CcdiProjectOverviewServiceImpl.getRiskPeopleOverview(Long projectId)` 的实现为:
1. 校验项目存在
2. 调用 `overviewMapper.selectRiskPeopleOverviewByProjectId(projectId)` 查询全量员工结果
3. 在 Java 层逐行映射为 `overviewList`
4. 返回 `CcdiProjectRiskPeopleOverviewVO { overviewList }`
当前 SQL 直接从 `ccdi_project_overview_employee_result` 查询并排序:
- `risk_level_sort asc`
- `model_count desc`
- `rule_count desc`
- `staff_id_card asc`
现状能够提供正确列表语义,但不具备分页能力。
## 五、方案对比
### 5.1 方案 A改造现有 `risk-people` 为标准分页接口
做法:
- 保持接口路径不变
- 入参扩展为 `projectId + pageNum + pageSize`
- 返回结构改为 `rows + total + pageNum + pageSize`
- 后端通过数据库分页查询返回当前页数据
- 前端首屏与翻页统一走该接口
优点:
- 满足“改接口”的明确要求
-`risk-models/people``employee-credit-negative` 的分页风格一致
- 逻辑单一,没有重复接口
- 数据量增大时性能与语义都正确
缺点:
- 需要同步调整前后端契约与测试
### 5.2 方案 B新增 `risk-people/page`,保留原接口不动
做法:
-`risk-people` 继续返回全量列表
- 新增单独分页接口供前端切换
问题:
- 留下两个语义重复的接口
- 不符合“改接口”的要求
- 增加后续维护成本
### 5.3 方案 C后端仍全量查Java 或前端再切页
做法:
- 接口表面返回分页结构
- 实际仍走全量查询后截断
问题:
- 不是真分页
- 数据量增大时性能与语义都不成立
- 属于补丁式方案,不符合最短路径要求
### 5.4 结论
采用方案 A。
## 六、接口设计
### 6.1 接口路径
- `GET /ccdi/project/overview/risk-people`
### 6.2 入参
- `projectId`: 项目 ID必填
- `pageNum`: 页码,非必填,默认 `1`
- `pageSize`: 每页条数,非必填,默认 `5`
说明:
- 前端固定传 `pageSize = 5`
- 后端默认值同样收敛为 `5`,避免前端漏传时行为偏移
### 6.3 返回结构
返回结构统一为:
```json
{
"rows": [
{
"name": "李四",
"idNo": "330000000000000001",
"department": "信息二部",
"riskCount": 5,
"riskLevel": "中风险",
"riskLevelType": "warning",
"modelCount": 4,
"riskPoint": "大额单笔收入、疑似兼职",
"actionLabel": "查看项目"
}
],
"total": 18,
"pageNum": 1,
"pageSize": 5
}
```
说明:
-`overviewList` 字段移除,统一改为 `rows`
- 单行字段保持现有页面绑定语义不变
- 本次不引入额外统计字段
## 七、后端设计
### 7.1 控制器
`CcdiProjectOverviewController.getRiskPeople` 改为接收独立 DTO例如
- `CcdiProjectRiskPeopleQueryDTO`
DTO 仅包含:
- `projectId`
- `pageNum`
- `pageSize`
不额外引入筛选项,保持最短路径。
### 7.2 服务层
`ICcdiProjectOverviewService.getRiskPeopleOverview` 改为接收查询 DTO并返回分页 VO。
服务层职责:
1. 校验项目存在
2. 规范化分页参数,默认 `pageNum=1``pageSize=5`
3. 构造 MyBatis Plus `Page`
4. 调用 mapper 分页查询
5. 将记录映射为现有员工列表行结构
6. 返回 `rows + total + pageNum + pageSize`
### 7.3 VO 调整
`CcdiProjectRiskPeopleOverviewVO` 改为标准分页 VO字段包括
- `List<CcdiProjectRiskPeopleOverviewItemVO> rows`
- `Long total`
- `Long pageNum`
- `Long pageSize`
说明:
- `CcdiProjectRiskPeopleOverviewItemVO` 本身字段不做语义调整
- 既有的风险等级映射与异常点标签来源保持不变
### 7.4 Mapper 与 SQL
Mapper 从“全量列表查询”改为“分页查询”,直接在数据库层完成分页。
排序规则保持现状不变:
- `risk_level_sort asc`
- `model_count desc`
- `rule_count desc`
- `staff_id_card asc`
数据来源继续使用 `ccdi_project_overview_employee_result`,不新增统计口径,不回退到历史复杂聚合链路。
### 7.5 默认值与边界
- `projectId` 为空时沿用现有参数校验/项目不存在校验逻辑
- `pageNum <= 0` 时按 `1` 处理
- `pageSize <= 0` 或为空时按 `5` 处理
- 本次不开放前端修改每页条数,接口虽接收 `pageSize`,但页面固定使用 5
## 八、前端设计
### 8.1 API 封装
`ruoyi-ui/src/api/ccdi/projectOverview.js` 中:
- `getOverviewRiskPeople` 从接收单个 `projectId` 改为接收 `params`
- 透传:
- `projectId`
- `pageNum`
- `pageSize`
### 8.2 首屏加载
`PreliminaryCheck.vue` 首次加载结果总览时,请求:
- `getOverviewRiskPeople({ projectId, pageNum: 1, pageSize: 5 })`
返回结果注入 `currentData.riskPeople` 时,直接保存分页结构:
- `rows`
- `total`
- `pageNum`
- `pageSize`
页面是否进入 `loaded` 状态的判断,从原来的 `overviewList.length` 改为 `rows.length`
### 8.3 风险总览员工列表组件
`RiskPeopleSection.vue` 调整为:
1. 表格数据源从 `sectionData.overviewList` 改为 `sectionData.rows`
2. 在表格下方增加分页组件
3. 分页组件固定:
- `:page-sizes="[5]"`
- `layout="total, prev, pager, next, jumper"`
4. 页码变化时触发独立请求,仅刷新员工列表分页数据
分页条展示规则:
- `total > 0` 时展示
- `total = 0` 时隐藏
### 8.4 页面刷新策略
翻页时只刷新风险总览员工列表,不重新拉取:
- 风险仪表盘
- 风险模型卡片
- 风险明细涉疑交易
- 风险明细员工负面征信
这样可以避免其他区块闪动,也避免把简单翻页放大成整页重载。
### 8.5 交互保持不变
以下内容本次保持不变:
- 表格列顺序
- 风险等级标签渲染
- 核心异常点标签拆分与色板逻辑
- 操作列文案与点击事件
- 空态文案
## 九、测试设计
### 9.1 后端测试
新增或调整以下验证:
1. Controller 测试
- 断言 `/risk-people` 接口改为接收 DTO
- 断言返回 `rows + total + pageNum + pageSize`
2. Service 测试
- 断言服务层使用分页参数构造 `Page`
- 断言现有字段映射未变化
- 断言默认分页参数回落为 `1 / 5`
3. Mapper/SQL 测试
- 断言风险人员查询改为分页查询方法
- 断言排序字段未变化
- 断言数据来源仍为 `ccdi_project_overview_employee_result`
### 9.2 前端测试
新增或调整以下验证:
1. API 封装测试
- 断言 `getOverviewRiskPeople(params)` 透传 `projectId/pageNum/pageSize`
2. 页面接入测试
- 断言 `PreliminaryCheck.vue` 首次加载传 `pageNum: 1`
- 断言固定传 `pageSize: 5`
- 断言风险人员数据改为读取 `rows`
3. 风险总览组件测试
- 断言 `RiskPeopleSection.vue` 存在分页组件
- 断言分页绑定 `rows/total/pageNum/pageSize`
- 断言分页大小固定为 5
## 十、实施文档要求
本次设计确认后,按仓库规范继续产出两份实施计划:
- 后端实施计划:`docs/plans/backend/`
- 前端实施计划:`docs/plans/frontend/`
实施完成后,补充对应实施记录,记录本次真实改动内容。
## 十一、结论
本次需求本质是将结果总览中的风险员工列表从“全量列表展示”升级为“标准分页列表展示”。
最终方案为:
1. 保持 `GET /ccdi/project/overview/risk-people` 路径不变
2. 改为标准分页接口,返回 `rows + total + pageNum + pageSize`
3. 后端在数据库层做真分页,默认每页 5 条
4. 前端首屏和翻页统一走该接口
5. 翻页仅刷新员工列表,不重载结果总览其他区块
该方案满足需求边界明确、链路完整、实现路径最短,且不引入额外补丁接口或兼容分支。