Files
ccdi/docs/plans/2026-03-11-project-detail-pull-bank-info-frontend-implementation.md

9.9 KiB
Raw Blame History

Project Detail Pull Bank Info Frontend Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Build the “拉取本行信息” modal on the project detail upload page, including ID-card Excel auto-parse and backfill, date-range submission, and reuse of the existing upload-record polling refresh flow.

Architecture: Keep the implementation inside the existing UploadData.vue page and ccdiProjectUpload.js API module instead of introducing a new page or a new API file. Replace the current confirm-only placeholder with a real dialog, call a dedicated parse endpoint as soon as the user chooses an Excel file, merge the returned身份证集合 back into the textarea, then submit the final list and reuse the existing statistics, record list, and polling behavior.

Tech Stack: Vue 2.6, Element UI 2.15, Axios request wrapper, existing polling/list refresh logic, npm run build:prod


Task 1: Add API contracts and make the build fail first

Files:

  • Modify: ruoyi-ui/src/api/ccdiProjectUpload.js
  • Modify: ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue

Step 1: Write the failing verification

先在 UploadData.vue 中把原来的简单确认流程替换成新的 API 引用,但暂时不创建 API 方法:

import {
  getImportStatus,
  getNameListOptions,
  getUploadStatus,
  pullBankInfo,
  parseIdCardFile,
  updateNameListSelection,
  uploadFile,
  batchUploadFiles,
  getFileUploadList,
  getFileUploadStatistics,
} from "@/api/ccdiProjectUpload";

并把 handleFetchBankInfo 改成只打开弹窗:

handleFetchBankInfo() {
  this.pullBankInfoDialogVisible = true;
}

Step 2: Run build to verify it fails

Run: cd ruoyi-ui; npm run build:prod

Expected: FAIL because parseIdCardFile does not exist in ccdiProjectUpload.js, and the new dialog state has not been defined.

Step 3: Write minimal implementation

ccdiProjectUpload.js 中补两个接口:

export function parseIdCardFile(file) {
  const formData = new FormData();
  formData.append("file", file);
  return request({
    url: "/ccdi/file-upload/parse-id-card-file",
    method: "post",
    data: formData,
    headers: {
      "Content-Type": "multipart/form-data"
    }
  });
}
export function pullBankInfo(data) {
  return request({
    url: "/ccdi/file-upload/pull-bank-info",
    method: "post",
    data
  });
}

注意:把原来 pullBankInfo(projectId) 的签名改成 JSON 提交,不再走 /ccdi/project/{projectId}/pull-bank-info 占位接口。

Step 4: Run build to verify it still only fails on missing dialog state

Run: cd ruoyi-ui; npm run build:prod

Expected: FAIL only because UploadData.vue 还没有新增弹窗数据和模板绑定。

Step 5: Commit

git add ruoyi-ui/src/api/ccdiProjectUpload.js ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
git commit -m "补充拉取本行信息前端接口契约"

Task 2: Build the modal shell and page state

Files:

  • Modify: ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue

Step 1: Write the failing verification

在模板里新增弹窗骨架,但先不实现方法:

  • el-dialog 标题:拉取本行信息
  • el-input type="textarea" 用于证件号码输入
  • el-upload 用于身份证文件上传
  • el-date-picker type="daterange" 用于时间跨度
  • 底部按钮:取消确认拉取

使用以下数据字段:

pullBankInfoDialogVisible: false,
pullBankInfoLoading: false,
parsingIdCardFile: false,
idCardFileList: [],
pullBankInfoForm: {
  idCardText: "",
  dateRange: []
}

Step 2: Run build to verify it fails

Run: cd ruoyi-ui; npm run build:prod

Expected: FAIL because the template references pullBankInfoDialogVisible, pullBankInfoForm, and upload handlers that are not implemented yet.

Step 3: Write minimal implementation

data() 中补齐新状态,并实现基础弹窗方法:

openPullBankInfoDialog() {
  this.pullBankInfoDialogVisible = true;
}
resetPullBankInfoForm() {
  this.pullBankInfoForm = {
    idCardText: "",
    dateRange: []
  };
  this.idCardFileList = [];
  this.parsingIdCardFile = false;
  this.pullBankInfoLoading = false;
}

同时调整 handleFetchBankInfo() 改为:

handleFetchBankInfo() {
  this.resetPullBankInfoForm();
  this.openPullBankInfoDialog();
}

Step 4: Run build to verify it passes

Run: cd ruoyi-ui; npm run build:prod

Expected: PASS

Step 5: Commit

git add ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
git commit -m "搭建拉取本行信息弹窗骨架"

Task 3: Implement instant Excel parsing and textarea backfill

Files:

  • Modify: ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue

Step 1: Write the failing verification

把文件上传控件接到实际事件,但先不写实现:

<el-upload
  action="#"
  :auto-upload="false"
  :limit="1"
  :file-list="idCardFileList"
  :on-change="handleIdCardFileChange"
  :on-remove="handleIdCardFileRemove">
</el-upload>

并在文件列表下面显示解析提示:

<div v-if="parsingIdCardFile">正在解析身份证文件...</div>

Step 2: Run build to verify it fails

Run: cd ruoyi-ui; npm run build:prod

Expected: FAIL because handleIdCardFileChange and handleIdCardFileRemove do not exist yet.

Step 3: Write minimal implementation

实现 4 个前端辅助方法:

  1. parseIdCardText(text)
parseIdCardText(text) {
  return Array.from(new Set(
    (text || "")
      .split(/[\n,]+/)
      .map(item => item.trim())
      .filter(Boolean)
  ));
}
  1. mergeIdCards(currentText, parsedIdCards)
mergeIdCards(currentText, parsedIdCards) {
  const merged = [
    ...this.parseIdCardText(currentText),
    ...(parsedIdCards || [])
  ];
  return Array.from(new Set(merged)).join(", ");
}
  1. handleIdCardFileChange(file, fileList)
  • 只保留一个文件
  • 校验扩展名为 .xls / .xlsx
  • 设置 parsingIdCardFile = true
  • 调用 parseIdCardFile(file.raw)
  • 成功后把返回的 idCards 合并回填到 pullBankInfoForm.idCardText
  • 失败后提示错误并清空文件列表
  1. handleIdCardFileRemove()
  • 清空 idCardFileList

解析成功后的关键回填逻辑:

this.pullBankInfoForm.idCardText = this.mergeIdCards(
  this.pullBankInfoForm.idCardText,
  res.data.idCards || []
);

Step 4: Run build to verify it passes

Run: cd ruoyi-ui; npm run build:prod

Expected: PASS

Step 5: Commit

git add ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
git commit -m "实现身份证文件自动解析与输入框回填"

Task 4: Submit the final pull request and reuse the existing polling refresh flow

Files:

  • Modify: ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue

Step 1: Write the failing verification

先把“确认拉取”按钮接到真正的方法名,但先不写逻辑:

<el-button type="primary" :loading="pullBankInfoLoading" @click="handleConfirmPullBankInfo">
  确认拉取
</el-button>

Step 2: Run build to verify it fails

Run: cd ruoyi-ui; npm run build:prod

Expected: FAIL because handleConfirmPullBankInfo does not exist yet.

Step 3: Write minimal implementation

实现提交前的最终整理与校验:

  1. buildFinalIdCardList()
buildFinalIdCardList() {
  return this.parseIdCardText(this.pullBankInfoForm.idCardText);
}
  1. handleConfirmPullBankInfo()
  • 校验证件号码非空
  • 校验 dateRange 长度为 2
  • 组装请求体:
const [startDate, endDate] = this.pullBankInfoForm.dateRange || [];
const payload = {
  projectId: this.projectId,
  idCards: this.buildFinalIdCardList(),
  startDate,
  endDate
};
  • 调用 pullBankInfo(payload)
  • 成功后:
    • 关闭弹窗
    • 提示“拉取任务已提交”
    • await Promise.all([this.loadStatistics(), this.loadFileList()])
    • 若有 uploading / parsing 记录则执行 this.startPolling()

失败后:

  • 保留弹窗内容
  • 显示后端错误信息

Step 4: Run build to verify it passes

Run: cd ruoyi-ui; npm run build:prod

Expected: PASS

Step 5: Commit

git add ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
git commit -m "接通拉取本行信息提交流程与列表刷新"

Task 5: Final verification and manual smoke-check

Files:

  • Modify if needed after failures: ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
  • Modify if needed after failures: ruoyi-ui/src/api/ccdiProjectUpload.js

Step 1: Run production build

Run: cd ruoyi-ui; npm run build:prod

Expected: BUILD SUCCESS

Step 2: Manual smoke in the browser

手工验证以下场景:

  1. 打开项目详情页 上传数据
  2. 点击“拉取本行信息”,确认弹窗打开
  3. 手工输入两个身份证,确认文本框保留原值
  4. 上传身份证 Excel确认自动解析并把去重后的身份证回填到文本框
  5. 不选日期时点击“确认拉取”,确认拦截
  6. 选择日期后提交,确认弹窗关闭、提示提交成功
  7. 确认上传记录列表新增记录并进入 上传中 / 解析中
  8. 确认已有轮询逻辑能自动刷新状态

Step 3: Fix the smallest UI or data-binding issue

优先排查:

  • 日期控件 value-format 是否返回 yyyy-MM-dd
  • 文件移除后是否错误保留旧文件列表
  • 文本框合并去重后是否出现多余逗号或空白
  • 提交成功后是否忘记重置弹窗状态

Step 4: Run final build again

Run: cd ruoyi-ui; npm run build:prod

Expected: BUILD SUCCESS

Step 5: Commit

git add ruoyi-ui/src/api/ccdiProjectUpload.js ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
git commit -m "完成拉取本行信息前端弹窗与自动解析"