Files
ccdi/docs/plans/frontend/2026-03-23-credit-info-maintenance-frontend-implementation.md
2026-03-23 22:39:15 +08:00

547 lines
13 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.
# Credit Info Maintenance 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:**`ruoyi-ui` 中新增“征信维护”页面,支持批量上传征信 HTML、展示员工维度征信摘要列表、查看详情并删除员工当前征信数据。
**Architecture:** 复用现有若依列表页模式和 Element UI 弹窗交互,新页面独立放在 `ccdiCreditInfo/index.vue`,不改造现有员工维护页。页面通过单独 API 文件调用后端业务接口,顶部负责文件上传和过滤查询,中部列表展示员工聚合摘要,详情弹窗展示负债明细与负面信息,删除操作按员工维度执行。
**Tech Stack:** Vue 2, Element UI, Axios request 封装, Node.js 源码契约测试, npm
---
## 文件结构与职责
**新增文件**
- `ruoyi-ui/src/api/ccdiCreditInfo.js`
封装上传、列表、详情、删除接口。
- `ruoyi-ui/src/views/ccdiCreditInfo/index.vue`
征信维护页面。
- `ruoyi-ui/tests/unit/credit-info-api-contract.test.js`
锁定 API 文件与路径契约。
- `ruoyi-ui/tests/unit/credit-info-page-layout.test.js`
锁定页面主结构、查询区、列表列和操作列。
- `ruoyi-ui/tests/unit/credit-info-upload-ui.test.js`
锁定批量上传弹窗、上传结果汇总和失败清单展示。
- `ruoyi-ui/tests/unit/credit-info-detail-ui.test.js`
锁定详情弹窗和删除交互结构。
- `docs/reports/implementation/2026-03-23-credit-info-maintenance-frontend-implementation.md`
前端实施记录。
**修改文件**
- 无强制修改路由文件;菜单由后端 `sys_menu` 动态下发。
**参考文件**
- `docs/design/2026-03-23-credit-info-maintenance-design.md`
- `ruoyi-ui/src/views/ccdiBaseStaff/index.vue`
- `ruoyi-ui/src/views/ccdiPurchaseTransaction/index.vue`
- `ruoyi-ui/src/api/ccdiBaseStaff.js`
- `ruoyi-ui/tests/unit/employee-asset-import-ui.test.js`
## Task 1: 新增前端 API 封装
**Files:**
- Create: `ruoyi-ui/src/api/ccdiCreditInfo.js`
- Create: `ruoyi-ui/tests/unit/credit-info-api-contract.test.js`
- [ ] **Step 1: 先写失败校验脚本**
`ruoyi-ui/tests/unit/credit-info-api-contract.test.js` 中先断言 API 文件与关键函数不存在前应失败:
```javascript
const assert = require("assert");
const fs = require("fs");
const path = require("path");
const apiPath = path.resolve(__dirname, "../../src/api/ccdiCreditInfo.js");
assert(fs.existsSync(apiPath), "未找到征信维护 API 文件 ccdiCreditInfo.js");
```
- [ ] **Step 2: 运行校验确认失败**
Run:
```bash
node ruoyi-ui/tests/unit/credit-info-api-contract.test.js
```
Expected:
- FAIL因为 `ccdiCreditInfo.js` 尚不存在。
- [ ] **Step 3: 编写最小 API 文件**
`ruoyi-ui/src/api/ccdiCreditInfo.js` 中实现:
```javascript
import request from '@/utils/request'
export function uploadCreditHtml(data) {
return request({
url: '/ccdi/creditInfo/upload',
method: 'post',
data
})
}
export function listCreditInfo(query) {
return request({
url: '/ccdi/creditInfo/list',
method: 'get',
params: query
})
}
export function getCreditInfoDetail(personId) {
return request({
url: '/ccdi/creditInfo/' + personId,
method: 'get'
})
}
export function deleteCreditInfo(personId) {
return request({
url: '/ccdi/creditInfo/' + personId,
method: 'delete'
})
}
```
- [ ] **Step 4: 补全契约断言**
脚本里至少断言以下 token
```javascript
[
"export function uploadCreditHtml(data)",
"export function listCreditInfo(query)",
"export function getCreditInfoDetail(personId)",
"export function deleteCreditInfo(personId)",
"/ccdi/creditInfo/upload",
"/ccdi/creditInfo/list",
"/ccdi/creditInfo/",
].forEach((token) => {
assert(source.includes(token), `征信维护 API 缺少关键契约: ${token}`);
});
```
- [ ] **Step 5: 运行校验确认通过**
Run:
```bash
node ruoyi-ui/tests/unit/credit-info-api-contract.test.js
```
Expected:
- PASS
- [ ] **Step 6: 提交 API 封装**
```bash
git add ruoyi-ui/src/api/ccdiCreditInfo.js ruoyi-ui/tests/unit/credit-info-api-contract.test.js
git commit -m "新增征信维护前端接口封装"
```
## Task 2: 搭建征信维护页面骨架
**Files:**
- Create: `ruoyi-ui/src/views/ccdiCreditInfo/index.vue`
- Create: `ruoyi-ui/tests/unit/credit-info-page-layout.test.js`
- [ ] **Step 1: 先写页面结构失败校验**
`credit-info-page-layout.test.js` 中断言页面必须出现:
```javascript
[
"征信维护",
"批量上传征信HTML",
"最近征信查询日期",
"负债笔数",
"负债总额",
"民事案件笔数",
"强制执行笔数",
"行政处罚笔数",
"详情",
"删除",
"@/api/ccdiCreditInfo",
].forEach((token) => {
assert(source.includes(token), `征信维护页面缺少关键结构: ${token}`);
});
```
- [ ] **Step 2: 运行校验确认失败**
Run:
```bash
node ruoyi-ui/tests/unit/credit-info-page-layout.test.js
```
Expected:
- FAIL因为页面文件尚不存在。
- [ ] **Step 3: 编写最小页面骨架**
页面至少包含:
```vue
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="姓名">
<el-input v-model="queryParams.name" placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="柜员号">
<el-input v-model="queryParams.staffId" placeholder="请输入柜员号" />
</el-form-item>
<el-form-item label="身份证号">
<el-input v-model="queryParams.idCard" placeholder="请输入身份证号" />
</el-form-item>
<el-form-item label="是否已维护">
<el-select v-model="queryParams.maintained" clearable>
<el-option label="已维护" value="1" />
<el-option label="未维护" value="0" />
</el-select>
</el-form-item>
</el-form>
<el-table :data="creditInfoList" v-loading="loading">
<el-table-column label="姓名" prop="name" />
<el-table-column label="柜员号" prop="staffId" />
<el-table-column label="身份证号" prop="idCard" />
<el-table-column label="最近征信查询日期" prop="queryDate" />
</el-table>
```
- [ ] **Step 4: 补齐查询与列表基础方法**
至少实现:
```javascript
data() {
return {
loading: false,
showSearch: true,
total: 0,
creditInfoList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
name: undefined,
staffId: undefined,
idCard: undefined,
maintained: undefined,
},
}
},
methods: {
getList() {},
handleQuery() {},
resetQuery() {},
}
```
- [ ] **Step 5: 运行校验确认通过**
Run:
```bash
node ruoyi-ui/tests/unit/credit-info-page-layout.test.js
```
Expected:
- PASS
- [ ] **Step 6: 提交页面骨架**
```bash
git add ruoyi-ui/src/views/ccdiCreditInfo/index.vue ruoyi-ui/tests/unit/credit-info-page-layout.test.js
git commit -m "新增征信维护页面骨架"
```
## Task 3: 实现批量上传弹窗与结果展示
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiCreditInfo/index.vue`
- Create: `ruoyi-ui/tests/unit/credit-info-upload-ui.test.js`
- [ ] **Step 1: 先写上传交互失败校验**
`credit-info-upload-ui.test.js` 中断言页面必须包含:
```javascript
[
"uploadDialogVisible",
"uploadFileList",
"批量上传征信HTML",
"仅支持 .html / .htm 文件",
"上传结果",
"failureList",
"successCount",
"failureCount",
"handleUploadSubmit",
"beforeUpload",
"uploadCreditHtml",
].forEach((token) => {
assert(source.includes(token), `征信上传交互缺少关键结构: ${token}`);
});
```
- [ ] **Step 2: 运行校验确认失败**
Run:
```bash
node ruoyi-ui/tests/unit/credit-info-upload-ui.test.js
```
Expected:
- FAIL因为上传弹窗和状态尚未实现。
- [ ] **Step 3: 加入上传弹窗与文件校验**
最小结构:
```vue
<el-dialog title="批量上传征信HTML" :visible.sync="uploadDialogVisible" width="600px">
<el-upload
ref="upload"
action=""
:auto-upload="false"
:file-list="uploadFileList"
:before-upload="beforeUpload"
:on-change="handleFileChange"
:on-remove="handleFileRemove"
multiple>
<el-button type="primary" size="small">选择文件</el-button>
<div slot="tip" class="el-upload__tip">仅支持 .html / .htm 文件可一次选择多个文件</div>
</el-upload>
</el-dialog>
```
文件校验:
```javascript
beforeUpload(file) {
const fileName = file.name.toLowerCase()
const passed = fileName.endsWith('.html') || fileName.endsWith('.htm')
if (!passed) {
this.$modal.msgError('仅支持上传 .html 或 .htm 文件')
}
return passed
}
```
- [ ] **Step 4: 展示上传结果汇总**
上传完成后,将接口返回赋值到:
```javascript
this.uploadResult = {
totalCount: data.totalCount,
successCount: data.successCount,
failureCount: data.failureCount,
failures: data.failures || [],
}
```
并在弹窗或结果卡片中展示:
- 总文件数
- 成功数
- 失败数
- 失败文件名 / 身份证号 / 原因
- [ ] **Step 5: 运行校验确认通过**
Run:
```bash
node ruoyi-ui/tests/unit/credit-info-upload-ui.test.js
```
Expected:
- PASS
- [ ] **Step 6: 提交上传交互**
```bash
git add ruoyi-ui/src/views/ccdiCreditInfo/index.vue ruoyi-ui/tests/unit/credit-info-upload-ui.test.js
git commit -m "新增征信维护上传交互"
```
## Task 4: 实现详情弹窗与删除交互
**Files:**
- Modify: `ruoyi-ui/src/views/ccdiCreditInfo/index.vue`
- Create: `ruoyi-ui/tests/unit/credit-info-detail-ui.test.js`
- [ ] **Step 1: 先写详情与删除失败校验**
`credit-info-detail-ui.test.js` 中断言页面包含:
```javascript
[
"detailDialogVisible",
"detailForm",
"负债信息",
"负面信息",
"civilCnt",
"enforceCnt",
"admCnt",
"handleDetail",
"handleDelete",
"deleteCreditInfo",
"确认删除该员工当前已维护的征信信息吗?",
].forEach((token) => {
assert(source.includes(token), `详情或删除交互缺少关键结构: ${token}`);
});
```
- [ ] **Step 2: 运行校验确认失败**
Run:
```bash
node ruoyi-ui/tests/unit/credit-info-detail-ui.test.js
```
Expected:
- FAIL因为详情弹窗和删除逻辑尚未实现。
- [ ] **Step 3: 编写详情弹窗**
详情区至少展示:
```vue
<el-dialog title="征信详情" :visible.sync="detailDialogVisible" width="900px">
<div class="section-header">征信摘要</div>
<el-row>
<el-col :span="8">征信查询日期{{ detailForm.queryDate }}</el-col>
<el-col :span="8">负债笔数{{ detailForm.debtCount }}</el-col>
<el-col :span="8">负债总额{{ detailForm.debtTotalAmount }}</el-col>
</el-row>
<div class="section-header">负债信息</div>
<el-table :data="detailForm.debts || []">
<el-table-column label="负债大类" prop="debtMainType" />
<el-table-column label="负债小类" prop="debtSubType" />
<el-table-column label="债权人类型" prop="creditorType" />
<el-table-column label="负债名称" prop="debtName" />
<el-table-column label="负债本金余额" prop="principalBalance" />
<el-table-column label="负债总额" prop="debtTotalAmount" />
<el-table-column label="负债状态" prop="debtStatus" />
</el-table>
</el-dialog>
```
- [ ] **Step 4: 编写删除交互**
删除方法最小实现:
```javascript
handleDelete(row) {
const personId = row.idCard
this.$modal.confirm('确认删除该员工当前已维护的征信信息吗?').then(() => {
return deleteCreditInfo(personId)
}).then(() => {
this.$modal.msgSuccess('删除成功')
this.getList()
})
}
```
- [ ] **Step 5: 运行校验确认通过**
Run:
```bash
node ruoyi-ui/tests/unit/credit-info-detail-ui.test.js
```
Expected:
- PASS
- [ ] **Step 6: 提交详情与删除**
```bash
git add ruoyi-ui/src/views/ccdiCreditInfo/index.vue ruoyi-ui/tests/unit/credit-info-detail-ui.test.js
git commit -m "新增征信维护详情与删除交互"
```
## Task 5: 前端回归验证与实施记录
**Files:**
- Create: `docs/reports/implementation/2026-03-23-credit-info-maintenance-frontend-implementation.md`
- [ ] **Step 1: 跑源码契约测试**
Run:
```bash
node ruoyi-ui/tests/unit/credit-info-api-contract.test.js
node ruoyi-ui/tests/unit/credit-info-page-layout.test.js
node ruoyi-ui/tests/unit/credit-info-upload-ui.test.js
node ruoyi-ui/tests/unit/credit-info-detail-ui.test.js
```
Expected:
- 四个脚本全部 PASS。
- [ ] **Step 2: 执行前端构建**
Run:
```bash
cd ruoyi-ui
npm run build:prod
```
Expected:
- PASS构建产物生成成功。
- [ ] **Step 3: 页面联调检查**
人工检查以下行为:
- 菜单进入 `征信维护` 页面正常
- 上传多个 HTML 后结果汇总正确
- 列表摘要字段与后端返回一致
- 详情弹窗能显示负债表与负面信息
- 删除后列表数据即时刷新
- [ ] **Step 4: 记录实施结果**
在实施记录中至少写明:
- 实际修改文件
- 前端构建命令与结果
- 页面联调截图或关键行为说明
- 若本地启动了前端 dev server记录已关闭
- [ ] **Step 5: 提交实施记录**
```bash
git add docs/reports/implementation/2026-03-23-credit-info-maintenance-frontend-implementation.md
git commit -m "补充征信维护前端实施记录"
```
## Review Notes
- 菜单由后端 `sys_menu` 下发,前端不需要手改 `router/index.js`
- 页面只负责征信维护,不要顺手把入口加回员工维护页。
- 仓库协作约定禁止开启 subagent执行本计划时直接使用 `superpowers:executing-plans`