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

377 lines
11 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.
# Project Detail Risk Overview Risk People Pagination 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.
>
> **Repo note:** 本仓库 `AGENTS.md` 明确禁止开启 subagent执行本计划时请在当前会话使用 `superpowers:executing-plans`。
**Goal:** 让项目详情“风险总览”的员工列表改为固定每页 5 条的真实后端分页,并保证翻页时只刷新该列表,不重载结果总览内其他区块。
**Architecture:** 前端继续以 `PreliminaryCheck.vue` 作为结果总览入口,首屏加载第一页风险员工数据并透传给 `RiskPeopleSection.vue``RiskPeopleSection.vue` 接管分页状态、请求 loading 和翻页动作,直接调用 `projectOverview.js` 中改造后的 `getOverviewRiskPeople(params)`,避免在翻页时重新触发整页 `Promise.all`
**Tech Stack:** Vue 2, Element UI, SCSS, axios request 封装, Node `assert` 结构测试
---
### Task 1: 改造风险员工分页 API 封装
**Files:**
- Modify: `ruoyi-ui/src/api/ccdi/projectOverview.js`
- Test: `ruoyi-ui/tests/unit/project-overview-api.test.js`
- [ ] **Step 1: 先写失败测试,锁定 `getOverviewRiskPeople` 改为参数对象透传**
```javascript
[
"getOverviewRiskPeople(params)",
"/ccdi/project/overview/risk-people",
"projectId: params.projectId",
"pageNum: params.pageNum",
"pageSize: params.pageSize",
].forEach((token) => assert(source.includes(token), token));
```
- [ ] **Step 2: 运行 API 契约测试,确认当前仍是旧签名**
Run:
```bash
node ruoyi-ui/tests/unit/project-overview-api.test.js
```
Expected:
- FAIL提示 `getOverviewRiskPeople(projectId)` 仍是旧写法
- [ ] **Step 3: 写最小 API 封装**
```javascript
export function getOverviewRiskPeople(params) {
return request({
url: "/ccdi/project/overview/risk-people",
method: "get",
params: {
projectId: params.projectId,
pageNum: params.pageNum,
pageSize: params.pageSize,
},
});
}
```
- [ ] **Step 4: 回跑 API 测试**
Run:
```bash
node ruoyi-ui/tests/unit/project-overview-api.test.js
```
Expected: PASS
- [ ] **Step 5: 提交本任务**
```bash
git add ruoyi-ui/src/api/ccdi/projectOverview.js \
ruoyi-ui/tests/unit/project-overview-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`
- Modify: `ruoyi-ui/tests/unit/preliminary-check-api-integration.test.js`
- Create: `ruoyi-ui/tests/unit/preliminary-check-risk-people-pagination-load.test.js`
- [ ] **Step 1: 先写失败测试,锁定父组件首屏请求第一页且固定 5 条**
```javascript
[
"getOverviewRiskPeople({",
"projectId: this.projectId",
"pageNum: 1",
"pageSize: 5",
"riskPeopleData.rows",
].forEach((token) => assert(source.includes(token), token));
```
```javascript
assert(source.includes("pageNum"), "riskPeople 应保存首屏页码");
assert(source.includes("pageSize"), "riskPeople 应保存首屏页长");
assert(source.includes("total"), "riskPeople 应保存总数");
```
- [ ] **Step 2: 运行入口页测试,确认当前还在读取 `overviewList`**
Run:
```bash
node ruoyi-ui/tests/unit/preliminary-check-api-integration.test.js
node ruoyi-ui/tests/unit/preliminary-check-risk-people-pagination-load.test.js
```
Expected:
- FAIL提示首屏没有传 `pageNum/pageSize`
- FAIL提示 `riskPeopleData.rows` 未被使用
- [ ] **Step 3: 写最小首屏加载与 mock 归一化**
```javascript
const [dashboardRes, riskPeopleRes, riskModelCardsRes, suspiciousRes, creditNegativeRes] = await Promise.all([
getOverviewDashboard(this.projectId),
getOverviewRiskPeople({ projectId: this.projectId, pageNum: 1, pageSize: 5 }),
getOverviewRiskModelCards(this.projectId),
getOverviewSuspiciousTransactions({ projectId: this.projectId, suspiciousType: "ALL", pageNum: 1, pageSize: 5 }),
getOverviewEmployeeCreditNegative({ projectId: this.projectId, pageNum: 1, pageSize: 5 }),
]);
```
```javascript
riskPeople: {
...mockOverviewData.riskPeople,
rows: Array.isArray(riskPeopleData && riskPeopleData.rows) ? riskPeopleData.rows : [],
total: riskPeopleData && riskPeopleData.total ? riskPeopleData.total : 0,
pageNum: riskPeopleData && riskPeopleData.pageNum ? riskPeopleData.pageNum : 1,
pageSize: riskPeopleData && riskPeopleData.pageSize ? riskPeopleData.pageSize : 5,
}
```
- [ ] **Step 4: 回跑入口页测试**
Run:
```bash
node ruoyi-ui/tests/unit/preliminary-check-api-integration.test.js
node ruoyi-ui/tests/unit/preliminary-check-risk-people-pagination-load.test.js
```
Expected: PASS
- [ ] **Step 5: 提交本任务**
```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-api-integration.test.js \
ruoyi-ui/tests/unit/preliminary-check-risk-people-pagination-load.test.js
git commit -m "接通风险总览员工列表首屏分页数据"
```
### Task 3: 在 `RiskPeopleSection` 中接管独立翻页与局部刷新
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue`
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/RiskPeopleSection.vue`
- Modify: `ruoyi-ui/tests/unit/preliminary-check-risk-people-binding.test.js`
- Create: `ruoyi-ui/tests/unit/preliminary-check-risk-people-pagination.test.js`
- [ ] **Step 1: 先写失败测试,锁定组件读取 `rows`、存在分页条、固定 5 条一页**
```javascript
[
"sectionData.rows",
"pageNum",
"pageSize",
"total",
"<pagination",
':page-sizes="[5]"',
"handlePageChange",
"loadRiskPeoplePage",
"getOverviewRiskPeople",
].forEach((token) => assert(source.includes(token), token));
```
```javascript
assert(!source.includes("sectionData.overviewList"), "风险人员列表不应再绑定 overviewList");
```
- [ ] **Step 2: 运行风险人员组件测试,确认当前没有分页状态和独立翻页逻辑**
Run:
```bash
node ruoyi-ui/tests/unit/preliminary-check-risk-people-binding.test.js
node ruoyi-ui/tests/unit/preliminary-check-risk-people-pagination.test.js
```
Expected:
- FAIL提示缺少 `rows / total / pageNum / pageSize`
- FAIL提示缺少分页组件和翻页方法
- [ ] **Step 3: 写最小局部分页实现**
`PreliminaryCheck.vue` 里给子组件补传 `project-id`
```vue
<risk-people-section
:project-id="projectId"
:section-data="currentData.riskPeople"
@view-project-analysis="handleRiskPeopleProjectAnalysis"
/>
```
`RiskPeopleSection.vue` 里维护局部分页状态与请求:
```javascript
data() {
return {
pageNum: 1,
pageSize: 5,
total: 0,
tableLoading: false,
localRows: [],
};
},
```
```javascript
watch: {
sectionData: {
immediate: true,
deep: true,
handler(data) {
this.localRows = normalizeOverviewRows(data && data.rows);
this.total = (data && data.total) || 0;
this.pageNum = (data && data.pageNum) || 1;
this.pageSize = (data && data.pageSize) || 5;
},
},
},
```
```javascript
async loadRiskPeoplePage(pageNum) {
this.tableLoading = true;
const response = await getOverviewRiskPeople({
projectId: this.projectId,
pageNum,
pageSize: 5,
});
const data = (response && response.data) || {};
this.localRows = normalizeOverviewRows(data.rows);
this.total = data.total || 0;
this.pageNum = data.pageNum || pageNum;
this.pageSize = data.pageSize || 5;
this.tableLoading = false;
}
```
```javascript
handlePageChange({ page }) {
if (page === this.pageNum) {
return;
}
this.loadRiskPeoplePage(page);
}
```
```vue
<pagination
v-show="total > 0"
:total="total"
:page.sync="pageNum"
:limit.sync="pageSize"
:page-sizes="[5]"
layout="total, prev, pager, next, jumper"
@pagination="handlePageChange"
/>
```
- [ ] **Step 4: 回跑风险人员组件测试**
Run:
```bash
node ruoyi-ui/tests/unit/preliminary-check-risk-people-binding.test.js
node ruoyi-ui/tests/unit/preliminary-check-risk-people-pagination.test.js
```
Expected:
- PASS
- 核心异常点标签逻辑、风险等级标签逻辑和操作列逻辑不回归
- [ ] **Step 5: 提交本任务**
```bash
git add ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue \
ruoyi-ui/src/views/ccdiProject/components/detail/RiskPeopleSection.vue \
ruoyi-ui/tests/unit/preliminary-check-risk-people-binding.test.js \
ruoyi-ui/tests/unit/preliminary-check-risk-people-pagination.test.js
git commit -m "支持风险总览员工列表独立分页翻页"
```
### Task 4: 补齐前端验证记录与实施记录
**Files:**
- Create: `docs/tests/records/2026-03-29-project-detail-risk-overview-risk-people-pagination-frontend-verification.md`
- Create: `docs/reports/implementation/2026-03-29-project-detail-risk-overview-risk-people-pagination-frontend-implementation.md`
- Verify: `docs/design/2026-03-29-project-detail-risk-overview-risk-people-pagination-design.md`
- [ ] **Step 1: 运行本需求前端最小回归**
Run:
```bash
node ruoyi-ui/tests/unit/project-overview-api.test.js
node ruoyi-ui/tests/unit/preliminary-check-api-integration.test.js
node ruoyi-ui/tests/unit/preliminary-check-risk-people-pagination-load.test.js
node ruoyi-ui/tests/unit/preliminary-check-risk-people-binding.test.js
node ruoyi-ui/tests/unit/preliminary-check-risk-people-pagination.test.js
```
Expected:
- 全部 PASS
- 风险人员区首屏读取分页结构,翻页逻辑存在
- [ ] **Step 2: 写前端验证记录**
`docs/tests/records/2026-03-29-project-detail-risk-overview-risk-people-pagination-frontend-verification.md` 记录:
- 执行命令
- 执行日期
- 测试结果
- 结论:风险总览员工列表已固定 5 条一页,翻页仅刷新当前列表
- [ ] **Step 3: 写前端实施记录**
`docs/reports/implementation/2026-03-29-project-detail-risk-overview-risk-people-pagination-frontend-implementation.md` 记录:
- API 封装如何改造
- `PreliminaryCheck.vue` 首屏如何注入分页结构
- `RiskPeopleSection.vue` 如何局部翻页
- 本次未改动风险模型区和风险明细区
- [ ] **Step 4: 检查暂存区仅包含本任务文件**
Run:
```bash
git status --short
git diff --cached --name-only
```
Expected:
- 暂存区只出现本任务相关前端源码、测试和文档
- [ ] **Step 5: 提交本任务**
```bash
git add docs/tests/records/2026-03-29-project-detail-risk-overview-risk-people-pagination-frontend-verification.md \
docs/reports/implementation/2026-03-29-project-detail-risk-overview-risk-people-pagination-frontend-implementation.md
git commit -m "补充风险总览员工列表前端分页实施记录"
```
## Done When
- 首屏通过 `getOverviewRiskPeople({ projectId, pageNum: 1, pageSize: 5 })` 获取第一页
- `riskPeople` 数据结构改为 `rows + total + pageNum + pageSize`
- `RiskPeopleSection.vue` 存在固定 5 条分页条
- 翻页只刷新风险总览员工列表,不重载其他结果总览区块
- 前端验证记录与实施记录已补齐