From 6a3cfa9ea60ae56b1d7fb02e7f9e4165a8dc09b0 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Thu, 12 Mar 2026 13:41:40 +0800 Subject: [PATCH] Add file size update after upload --- .../impl/CcdiFileUploadServiceImpl.java | 3 + .../impl/CcdiFileUploadServiceImplTest.java | 56 +++++---- ...-info-date-limit-backend-implementation.md | 35 ++++++ ...-03-12-pull-bank-info-date-limit-design.md | 45 +++++++ ...info-date-limit-frontend-implementation.md | 111 ++++++++++++++++++ .../components/detail/UploadData.vue | 43 +++++++ ...oad-data-pull-bank-info-date-limit.test.js | 26 ++++ 7 files changed, 294 insertions(+), 25 deletions(-) create mode 100644 docs/plans/2026-03-12-pull-bank-info-date-limit-backend-implementation.md create mode 100644 docs/plans/2026-03-12-pull-bank-info-date-limit-design.md create mode 100644 docs/plans/2026-03-12-pull-bank-info-date-limit-frontend-implementation.md create mode 100644 ruoyi-ui/tests/unit/upload-data-pull-bank-info-date-limit.test.js diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java index 7305685..cbea371 100644 --- a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java @@ -656,6 +656,9 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService { if (StringUtils.hasText(fileName)) { record.setFileName(fileName); } + if (logItem.getFileSize() != null) { + record.setFileSize(logItem.getFileSize()); + } log.info("【文件上传】文件状态: status={}, uploadStatusDesc={}", status, uploadStatusDesc); boolean parseSuccess = status != null && status == -5 diff --git a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImplTest.java b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImplTest.java index 54e4b69..a2186c2 100644 --- a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImplTest.java +++ b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImplTest.java @@ -223,31 +223,37 @@ class CcdiFileUploadServiceImplTest { verify(bankStatementMapper).deleteByProjectIdAndBatchId(PROJECT_ID, LOG_ID); } -// @Test -// void processPullBankInfoAsync_shouldUpdateFileNameFromStatusResponse() { -// when(lsfxClient.fetchInnerFlow(any())).thenReturn(buildFetchInnerFlowResponse(LOG_ID)); -// when(lsfxClient.checkParseStatus(LSFX_PROJECT_ID, String.valueOf(LOG_ID))) -// .thenReturn(buildCheckParseStatusResponse(false)); -// when(lsfxClient.getFileUploadStatus(any())).thenReturn(buildParsedSuccessStatusResponse("XX身份证.xlsx")); -// when(lsfxClient.getBankStatement(any(GetBankStatementRequest.class))) -// .thenReturn(buildEmptyBankStatementResponse()); -// -// CcdiFileUploadRecord record = buildRecord(); -// service.processPullBankInfoAsync( -// PROJECT_ID, -// LSFX_PROJECT_ID, -// record, -// "110101199001018888", -// "2026-03-01", -// "2026-03-10", -// 9527L -// ); -// -// verify(recordMapper, org.mockito.Mockito.atLeastOnce()).updateById(org.mockito.ArgumentMatchers.argThat(item -> -// "XX身份证.xlsx".equals(item.getFileName()))); -// verify(recordMapper, org.mockito.Mockito.atLeastOnce()).updateById(org.mockito.ArgumentMatchers.argThat(item -> -// "parsed_success".equals(item.getFileStatus()))); -// } + @Test + void processPullBankInfoAsync_shouldUpdateFileSizeFromStatusResponse() { + GetFileUploadStatusResponse statusResponse = buildParsedSuccessStatusResponse("XX身份证.xlsx"); + statusResponse.getData().getLogs().get(0).setFileSize(2048L); + + when(lsfxClient.fetchInnerFlow(any())).thenReturn(buildFetchInnerFlowResponse(LOG_ID)); + when(lsfxClient.checkParseStatus(LSFX_PROJECT_ID, String.valueOf(LOG_ID))) + .thenReturn(buildCheckParseStatusResponse(false)); + when(lsfxClient.getFileUploadStatus(any())).thenReturn(statusResponse); + when(lsfxClient.getBankStatement(any(GetBankStatementRequest.class))) + .thenReturn(buildEmptyBankStatementResponse()); + + CcdiFileUploadRecord record = buildRecord(); + record.setFileSize(0L); + + service.processPullBankInfoAsync( + PROJECT_ID, + LSFX_PROJECT_ID, + record, + "110101199001018888", + "2026-03-01", + "2026-03-10" + ); + + verify(recordMapper, org.mockito.Mockito.atLeastOnce()).updateById( + org.mockito.ArgumentMatchers.argThat(item -> + Long.valueOf(2048L).equals(item.getFileSize()) + && "XX身份证.xlsx".equals(item.getFileName()) + && "parsed_success".equals(item.getFileStatus())) + ); + } // @Test // void processPullBankInfoAsync_shouldMarkParsedFailedWhenFetchInnerFlowThrows() { diff --git a/docs/plans/2026-03-12-pull-bank-info-date-limit-backend-implementation.md b/docs/plans/2026-03-12-pull-bank-info-date-limit-backend-implementation.md new file mode 100644 index 0000000..3848da7 --- /dev/null +++ b/docs/plans/2026-03-12-pull-bank-info-date-limit-backend-implementation.md @@ -0,0 +1,35 @@ +# Pull Bank Info Date Limit Backend Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Confirm the new date restriction is fully handled in the frontend and does not require backend changes. + +**Architecture:** The allowed date window is enforced in the Vue dialog before the request is submitted. The backend request contract remains `projectId`, `idCards`, `startDate`, and `endDate`, so this plan records a no-op backend implementation boundary and the verification needed to avoid accidental API changes. + +**Tech Stack:** Java 21, Spring Boot 3, Maven, existing `ccdi-project` upload APIs + +--- + +### Task 1: Verify backend impact is zero + +**Files:** +- Review: `docs/plans/2026-03-12-pull-bank-info-date-limit-design.md` +- Review: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/` +- Review: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/` + +**Step 1: Confirm bug scope** + +Check that the requirement only changes frontend date selection and frontend submit validation. + +**Step 2: Verify request contract stays unchanged** + +Confirm the request still submits the same fields: + +- `projectId` +- `idCards` +- `startDate` +- `endDate` + +**Step 3: Keep backend code unchanged** + +Do not modify controller, service, mapper, DTO, or test classes for this task. diff --git a/docs/plans/2026-03-12-pull-bank-info-date-limit-design.md b/docs/plans/2026-03-12-pull-bank-info-date-limit-design.md new file mode 100644 index 0000000..f19cfc0 --- /dev/null +++ b/docs/plans/2026-03-12-pull-bank-info-date-limit-design.md @@ -0,0 +1,45 @@ +# 拉取本行信息日期范围限制设计 + +## 背景 +项目详情页“上传数据”中的“拉取本行信息”弹窗当前允许选择今天及未来日期,这与业务规则不符。用户只能拉取截止到当前日期前一天的数据。 + +## 目标 +- 日期范围组件中禁用今天及未来日期 +- 提交时兜底校验,阻止异常方式带入今天或未来日期 +- 保持现有接口、文件解析和弹窗结构不变 + +## 非目标 +- 不调整后端接口 +- 不修改现有日期范围字段格式 +- 不改变“至少输入一个身份证号”和“必须完整选择时间跨度”的现有校验 + +## 方案对比 + +### 方案一:仅在日期面板禁选 +- 优点:改动最小,交互直观 +- 缺点:若后续通过脚本赋值或异常回填带入无效日期,提交时缺少保护 + +### 方案二:仅在提交时校验 +- 优点:实现简单 +- 缺点:用户仍然可以在面板中选到无效日期,体验较差 + +### 方案三:日期面板禁选 + 提交兜底校验 +- 优点:同时覆盖交互层和数据层,最稳妥 +- 缺点:多一小段前端校验逻辑 + +## 最终方案 +采用方案三。 + +在前端日期范围选择器上增加 `picker-options.disabledDate`,将本地当前日期零点及之后的日期全部禁用。以 `2026-03-12` 为例,最晚只能选择到 `2026-03-11`。 + +在提交逻辑中新增“最大可选日期”为昨天的兜底校验。如果开始日期或结束日期晚于昨天,则阻止提交并提示“时间跨度最晚只能选择到昨天”。 + +## 影响范围 +- 前端组件:`ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue` +- 前端测试:`ruoyi-ui/tests/unit/` +- 后端:无代码改动,仅保留接口契约不变 + +## 验收标准 +- 日期面板无法选择今天和未来日期 +- 通过异常赋值带入今天或未来日期时,提交会被拦截 +- 原有弹窗交互和上传相关逻辑无回归 diff --git a/docs/plans/2026-03-12-pull-bank-info-date-limit-frontend-implementation.md b/docs/plans/2026-03-12-pull-bank-info-date-limit-frontend-implementation.md new file mode 100644 index 0000000..cf6c629 --- /dev/null +++ b/docs/plans/2026-03-12-pull-bank-info-date-limit-frontend-implementation.md @@ -0,0 +1,111 @@ +# Pull Bank Info Date Limit Frontend Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Restrict the pull-bank-info date range so users can only select dates up to yesterday and block invalid submissions. + +**Architecture:** Keep the existing dialog and request flow in `UploadData.vue`. Add one focused source-level regression test that asserts the date picker has an explicit restriction hook, then implement a shared “yesterday” boundary for both Element UI `disabledDate` behavior and submit-time validation. + +**Tech Stack:** Vue 2, Element UI 2, scoped SFC logic, Node-based source assertions in `ruoyi-ui/tests/unit` + +--- + +### Task 1: Add a regression test for the date restriction hook + +**Files:** +- Create: `ruoyi-ui/tests/unit/upload-data-pull-bank-info-date-limit.test.js` +- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue` + +**Step 1: Write the failing test** + +Create a source-based test that verifies the pull-bank-info date picker: + +- uses `picker-options` +- binds to a dedicated `pullBankInfoDatePickerOptions` +- the script contains a helper for calculating the latest allowed date + +**Step 2: Run test to verify it fails** + +Run: + +```bash +node ruoyi-ui/tests/unit/upload-data-pull-bank-info-date-limit.test.js +``` + +Expected: FAIL because the current component does not define the new date limit hook yet. + +### Task 2: Implement date picker restrictions + +**Files:** +- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue` +- Test: `ruoyi-ui/tests/unit/upload-data-pull-bank-info-date-limit.test.js` + +**Step 1: Add the date picker option** + +Bind the pull-bank-info date range picker to `pullBankInfoDatePickerOptions`. + +**Step 2: Add the latest allowed date helper** + +Add a method or computed-backed helper that returns yesterday based on the browser local date. + +**Step 3: Disable today and future dates** + +Implement `disabledDate` so dates greater than or equal to today 00:00 are disabled. + +**Step 4: Run the new test** + +Run: + +```bash +node ruoyi-ui/tests/unit/upload-data-pull-bank-info-date-limit.test.js +``` + +Expected: PASS + +### Task 3: Add submit-time fallback validation + +**Files:** +- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue` +- Test: `ruoyi-ui/tests/unit/upload-data-pull-bank-info-date-limit.test.js` + +**Step 1: Reuse the same date boundary in submit logic** + +Before calling `pullBankInfo(payload)`, verify both selected dates are not later than yesterday. + +**Step 2: Show a clear warning** + +If validation fails, warn the user with a concise message such as `时间跨度最晚只能选择到昨天`. + +**Step 3: Keep existing validations intact** + +Retain the current empty-ID-card and incomplete-date-range checks. + +### Task 4: Run regression verification + +**Files:** +- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue` + +**Step 1: Run focused tests** + +Run: + +```bash +node ruoyi-ui/tests/unit/upload-data-pull-bank-info-date-limit.test.js +node ruoyi-ui/tests/unit/upload-data-pull-bank-info-dialog-layout.test.js +node ruoyi-ui/tests/unit/upload-data-batch-upload.test.js +node ruoyi-ui/tests/unit/upload-data-file-list-settings.test.js +``` + +Expected: all tests pass. + +**Step 2: Run build verification** + +Run: + +```bash +npm run build:prod +``` + +Workdir: `ruoyi-ui` + +Expected: build succeeds without introducing Vue template or script errors. diff --git a/ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue b/ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue index a703a0d..5abd134 100644 --- a/ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue +++ b/ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue @@ -270,6 +270,7 @@ v-model="pullBankInfoForm.dateRange" type="daterange" value-format="yyyy-MM-dd" + :picker-options="pullBankInfoDatePickerOptions" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" @@ -502,6 +503,13 @@ export default { pollingInterval: 5000, }; }, + computed: { + pullBankInfoDatePickerOptions() { + return { + disabledDate: (time) => this.isPullBankInfoDateDisabled(time), + }; + }, + }, created() { // 加载初始数据 // this.loadInitialData(); @@ -860,6 +868,36 @@ export default { this.idCardFileList = []; this.parsingIdCardFile = false; }, + getPullBankInfoTodayStart() { + const today = new Date(); + today.setHours(0, 0, 0, 0); + return today; + }, + getPullBankInfoMaxSelectableDate() { + const yesterday = this.getPullBankInfoTodayStart(); + yesterday.setDate(yesterday.getDate() - 1); + return yesterday; + }, + parsePullBankInfoDate(dateValue) { + if (!dateValue) return null; + const [year, month, day] = String(dateValue) + .split("-") + .map((item) => Number(item)); + if (![year, month, day].every(Number.isFinite)) { + return null; + } + return new Date(year, month - 1, day); + }, + isPullBankInfoDateDisabled(time) { + return time.getTime() >= this.getPullBankInfoTodayStart().getTime(); + }, + hasInvalidPullBankInfoDateRange(dateRange) { + const maxSelectableDate = this.getPullBankInfoMaxSelectableDate(); + return (dateRange || []).some((dateValue) => { + const date = this.parsePullBankInfoDate(dateValue); + return !date || date.getTime() > maxSelectableDate.getTime(); + }); + }, buildFinalIdCardList() { return this.parseIdCardText(this.pullBankInfoForm.idCardText); }, @@ -877,6 +915,11 @@ export default { return; } + if (this.hasInvalidPullBankInfoDateRange([startDate, endDate])) { + this.$message.warning("时间跨度最晚只能选择到昨天"); + return; + } + this.pullBankInfoLoading = true; try { diff --git a/ruoyi-ui/tests/unit/upload-data-pull-bank-info-date-limit.test.js b/ruoyi-ui/tests/unit/upload-data-pull-bank-info-date-limit.test.js new file mode 100644 index 0000000..adc6d86 --- /dev/null +++ b/ruoyi-ui/tests/unit/upload-data-pull-bank-info-date-limit.test.js @@ -0,0 +1,26 @@ +const assert = require("assert"); +const fs = require("fs"); +const path = require("path"); + +const componentPath = path.resolve( + __dirname, + "../../src/views/ccdiProject/components/detail/UploadData.vue" +); +const source = fs.readFileSync(componentPath, "utf8"); + +assert( + /:picker-options="pullBankInfoDatePickerOptions"/.test(source), + "拉取本行信息日期范围应绑定专用的 picker-options" +); + +assert( + /pullBankInfoDatePickerOptions/.test(source), + "组件脚本中应定义拉取本行信息日期范围的专用配置" +); + +assert( + /getPullBankInfoMaxSelectableDate/.test(source), + "组件脚本中应提供“最晚可选日期”为昨天的统一 helper" +); + +console.log("upload-data-pull-bank-info-date-limit test passed");