# Risk Detail Employee Credit Negative 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:** 在结果总览“风险明细”中新增“员工负面征信信息”区块,按项目维度展示员工负面征信分页列表,并与现有涉疑交易区块并列呈现。 **Architecture:** 前端继续以 `PreliminaryCheck.vue` 作为结果总览入口,通过 `projectOverview.js` 新增员工负面征信接口封装,并在初次加载时注入 `riskDetails` 初始数据。`RiskDetailSection.vue` 负责渲染员工负面征信表格、空态和独立分页,并在后续翻页时直接调用结果总览专用接口,不复用全局征信维护页面或弹窗链路。 **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: 先写 API 契约测试,锁定接口名、路由和参数透传** ```javascript [ "getOverviewEmployeeCreditNegative", "/ccdi/project/overview/employee-credit-negative", "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,提示缺少 `getOverviewEmployeeCreditNegative` - [ ] **Step 3: 写最小 API 封装** ```javascript export function getOverviewEmployeeCreditNegative(params) { return request({ url: "/ccdi/project/overview/employee-credit-negative", 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-credit-negative-load.test.js` - [ ] **Step 1: 先写失败测试,锁定父组件并发请求和 `riskDetails` 注入结构** ```javascript assert(source.includes("getOverviewEmployeeCreditNegative"), "结果总览应加载员工负面征信接口"); assert(source.includes("employeeCreditNegativeList"), "riskDetails 应注入员工负面征信初始列表"); assert(source.includes("employeeCreditNegativeTotal"), "riskDetails 应注入员工负面征信总数"); ``` - [ ] **Step 2: 运行测试,确认当前入口页尚未接入该数据源** Run: ```bash node ruoyi-ui/tests/unit/preliminary-check-api-integration.test.js node ruoyi-ui/tests/unit/preliminary-check-credit-negative-load.test.js ``` Expected: - `preliminary-check-api-integration.test.js` 仍只有 4 个并发请求 - 新测试提示缺少员工负面征信数据装配 - [ ] **Step 3: 在父组件中并行加载新接口,并改造 mock 归一化结构** ```javascript const [dashboardRes, riskPeopleRes, riskModelCardsRes, suspiciousRes, creditNegativeRes] = await Promise.all([ getOverviewDashboard(this.projectId), getOverviewRiskPeople(this.projectId), getOverviewRiskModelCards(this.projectId), getOverviewSuspiciousTransactions({ projectId: this.projectId, suspiciousType: "ALL", pageNum: 1, pageSize: 5 }), getOverviewEmployeeCreditNegative({ projectId: this.projectId, pageNum: 1, pageSize: 5 }), ]); ``` ```javascript riskDetails: { projectId, suspiciousTransactionList: normalizeSuspiciousTransactions(suspiciousData && suspiciousData.rows), suspiciousType: "ALL", total: suspiciousData && suspiciousData.total ? suspiciousData.total : 0, employeeCreditNegativeList: normalizeEmployeeCreditNegativeRows(creditNegativeData && creditNegativeData.rows), employeeCreditNegativeTotal: creditNegativeData && creditNegativeData.total ? creditNegativeData.total : 0, abnormalAccountList: [], } ``` - [ ] **Step 4: 回跑入口页相关测试** Run: ```bash node ruoyi-ui/tests/unit/preliminary-check-api-integration.test.js node ruoyi-ui/tests/unit/preliminary-check-credit-negative-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-credit-negative-load.test.js git commit -m "接通结果总览员工负面征信初始加载" ``` ### Task 3: 在 RiskDetailSection 中新增员工负面征信区块与独立分页 **Files:** - Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/RiskDetailSection.vue` - Modify: `ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-layout.test.js` - Create: `ruoyi-ui/tests/unit/risk-detail-employee-credit-negative-layout.test.js` - Create: `ruoyi-ui/tests/unit/risk-detail-employee-credit-negative-pagination.test.js` - [ ] **Step 1: 先写失败测试,锁定新区块标题、列定义、空态和独立分页状态** ```javascript [ "员工负面征信信息", "展示当前项目员工的负面征信信息", "员工姓名", "身份证号", "最近征信查询日期", "民事案件笔数", "民事案件金额", "强制执行笔数", "强制执行金额", "行政处罚笔数", "行政处罚金额", "当前项目暂无员工负面征信信息", ].forEach((token) => assert(source.includes(token), token)); ``` ```javascript [ "employeeCreditNegativeList", "employeeCreditNegativeTotal", "employeeCreditNegativePageNum", "employeeCreditNegativePageSize", "loadEmployeeCreditNegative", "handleEmployeeCreditNegativePageChange", ].forEach((token) => assert(source.includes(token), token)); ``` - [ ] **Step 2: 运行测试,确认当前风险明细组件还没有该区块** Run: ```bash node ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-layout.test.js node ruoyi-ui/tests/unit/risk-detail-employee-credit-negative-layout.test.js node ruoyi-ui/tests/unit/risk-detail-employee-credit-negative-pagination.test.js ``` Expected: - 新测试 FAIL,提示缺少员工负面征信区块和独立分页状态 - [ ] **Step 3: 写最小 UI 与分页实现** ```vue