365 lines
10 KiB
Markdown
365 lines
10 KiB
Markdown
# 项目详情风险总览员工列表分页设计文档
|
||
|
||
**模块**: 项目详情 - 结果总览 - 风险总览员工列表
|
||
**日期**: 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. 翻页仅刷新员工列表,不重载结果总览其他区块
|
||
|
||
该方案满足需求边界明确、链路完整、实现路径最短,且不引入额外补丁接口或兼容分支。
|