Files
ccdi/docs/design/2026-03-16-project-upload-file-delete-design.md

338 lines
9.4 KiB
Markdown

# 项目上传文件列表删除功能设计
## 背景
当前项目详情页“上传数据”中的“上传文件列表”仅展示文件信息和状态,不支持针对单条文件记录执行业务操作。
现有系统已经具备以下基础能力:
- `ccdi_file_upload_record` 已保存每条上传记录的 `id``lsfxProjectId``logId``fileStatus``errorMessage`
- `ccdi_bank_statement` 已按 `projectId + batchId(logId)` 关联每次上传入库的流水数据
- 流水分析平台客户端 `LsfxAnalysisClient` 已封装删除文件接口 `deleteFiles`
当前缺失的是:
- 解析失败文件缺少“查看错误原因”入口
- 解析成功文件缺少“删除”入口
- 删除后缺少保留历史记录并展示“已删除”状态的机制
## 目标
- 在项目详情-上传数据-上传文件列表中新增“操作”列
- 当文件状态为 `parsed_failed` 时,支持查看错误原因
- 当文件状态为 `parsed_success` 时,支持删除文件
- 删除时增加二次确认,明确会同步删除平台文件与本地流水
- 删除成功后调用流水分析平台删除接口
- 删除成功后删除本地银行流水表中对应文件的全部流水
- 删除成功后保留上传记录,并将状态更新为 `deleted`
- 删除后的列表状态显示为“已删除”
## 非目标
- 不删除 `ccdi_file_upload_record` 历史记录
- 不新增独立删除标记字段,如 `deleted_flag``deleted_time`
- 不调整现有批量上传、轮询解析、本行信息拉取等主流程
- 不改造流水明细查询页面的筛选交互
## 现状分析
### 前端现状
上传文件列表页面位于:
- `ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue`
当前列表字段包括:
- 文件名
- 文件大小
- 状态
- 主体名称
- 主体账号
- 上传时间
- 上传人
当前前端已经具备:
- 查询列表:`getFileUploadList`
- 查询统计:`getFileUploadStatistics`
- 查看列表中的 `fileStatus`
- 弹窗提示能力 `this.$alert`
- 二次确认能力 `this.$confirm`
当前前端未具备:
- 操作列渲染
- 按记录 ID 删除文件的 API
- `deleted` 状态映射
### 后端现状
后端上传记录相关接口位于:
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiFileUploadController.java`
当前已提供:
- `GET /ccdi/file-upload/list`
- `GET /ccdi/file-upload/statistics/{projectId}`
- `GET /ccdi/file-upload/detail/{id}`
服务层位于:
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java`
当前已具备:
- 按状态统计上传记录
- 根据 `logId` 拉取并入库银行流水
- 失败时记录 `errorMessage`
- 通过 `CcdiBankStatementMapper.deleteByProjectIdAndBatchId(projectId, logId)` 清理本地流水
流水分析平台客户端位于:
- `ccdi-lsfx/src/main/java/com/ruoyi/lsfx/client/LsfxAnalysisClient.java`
当前已具备:
- `deleteFiles(DeleteFilesRequest)` 删除平台文件
### 状态现状
当前 `file_status` 已存在以下状态:
- `uploading`
- `parsing`
- `parsed_success`
- `parsed_failed`
当前缺少删除后的业务状态,因此无法在保留记录的前提下表达“已删除”。
## 方案对比
### 方案一:基于现有状态字段增加 `deleted`
-`file_status` 中新增 `deleted`
- 删除成功后仅更新记录状态,不删除记录
- 前后端统一基于状态判断操作按钮与文案
优点:
- 最符合“保留并显示为已删除”的需求
- 复用现有查询、展示、统计结构
- 改动范围集中,数据库结构无需新增字段
缺点:
- 需要同步扩展状态映射和统计逻辑
### 方案二:新增独立删除标记字段
- 保留原有 `file_status`
- 额外增加 `deletedFlag``deletedTime`
优点:
- 删除状态与解析状态语义分离
缺点:
- 查询、展示、统计逻辑更复杂
- 需要新增数据库字段和 Mapper 映射
- 当前需求下属于过度设计
### 方案三:物理删除上传记录
优点:
- 实现最直接
缺点:
- 与“继续保留并显示为已删除”冲突
- 无法追溯文件历史和删除操作结果
## 最终方案
采用方案一:在 `ccdi_file_upload_record.file_status` 中新增 `deleted` 状态,基于现有上传记录做软删除保留。
## 详细设计
### 状态模型
上传记录状态统一定义为:
- `uploading`:上传中
- `parsing`:解析中
- `parsed_success`:解析成功
- `parsed_failed`:解析失败
- `deleted`:已删除
状态驱动前端操作规则:
- `parsed_failed`:显示“查看错误原因”
- `parsed_success`:显示“删除”
- `deleted`:不显示按钮
- `uploading``parsing`:不显示按钮
### 删除链路
删除流程按以下顺序执行:
1. 前端点击“删除”
2. 前端展示二次确认弹窗
3. 用户确认后调用“按上传记录 ID 删除文件”接口
4. 后端校验记录存在、归属当前项目、状态为 `parsed_success`、且包含 `lsfxProjectId``logId`
5. 后端调用流水分析平台 `deleteFiles`
6. 平台删除成功后,后端删除本地 `ccdi_bank_statement``projectId + batchId(logId)` 的全部流水
7. 本地流水删除成功后,后端将 `ccdi_file_upload_record.file_status` 更新为 `deleted`
8. 前端收到成功响应后刷新列表与统计
### 一致性原则
删除必须遵守“先平台、后本地、再改状态”:
- 平台删除失败:不删本地流水,不更新记录状态
- 本地流水删除失败:不更新记录状态为 `deleted`
- 状态更新失败:整体按失败返回,避免界面和数据不一致
### 后端接口设计
新增接口建议:
- `DELETE /ccdi/file-upload/{id}`
接口语义:
- 按上传记录 ID 删除对应文件
- 仅允许删除 `parsed_success` 状态记录
返回规则:
- 成功:`AjaxResult.success("删除成功")`
- 失败:`AjaxResult.error("具体失败原因")`
### 后端服务设计
服务层新增删除方法,职责包括:
- 查询上传记录
- 校验项目归属与状态
- 组装 `DeleteFilesRequest`
- 调用 `LsfxAnalysisClient.deleteFiles`
- 删除本地银行流水
- 更新上传记录状态为 `deleted`
建议保持数据库层面不新增表结构,仅扩展状态值和相关逻辑。
### 前端交互设计
上传文件列表新增“操作”列。
操作规则:
- `parsed_failed`:点击“查看错误原因”,弹出错误信息弹窗
- `parsed_success`:点击“删除”,弹出确认框
- `deleted`:显示状态“已删除”,无操作按钮
删除确认文案建议:
`删除后将同步删除流水分析平台中的文件,并清除本系统中该文件对应的所有银行流水数据,是否继续?`
删除成功后:
- 提示“删除成功”
- 刷新列表
- 刷新统计
### 统计设计
当前统计 VO 仅统计:
- `uploading`
- `parsing`
- `parsedSuccess`
- `parsedFailed`
- `total`
本次建议扩展:
- `deleted`
这样前端统计口径可以完整覆盖全部状态,也便于后续展示已删除数量。
如果短期内页面不展示该数字,也建议后端先统一支持,避免状态被统计遗漏。
## 影响范围
### 后端
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiFileUploadController.java`
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiFileUploadService.java`
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java`
- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiFileUploadStatisticsVO.java`
- `ccdi-project/src/main/resources/mapper/ccdi/project/CcdiFileUploadRecordMapper.xml`
### 前端
- `ruoyi-ui/src/api/ccdiProjectUpload.js`
- `ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue`
## 风险与边界
需要重点拦截以下删除场景:
- 记录不存在
- 记录不属于当前项目
- 记录状态不是 `parsed_success`
- 记录已经是 `deleted`
- 记录缺少 `lsfxProjectId`
- 记录缺少 `logId`
需要注意以下业务影响:
- 软删除后,流水明细查询将不再能查到该文件对应流水
- 上传记录会继续保留,便于审计和追溯
- 如果平台删除成功但本地状态更新失败,需要明确作为失败返回并记录日志
## 测试方案
### 后端单元测试
- 删除成功时:平台删除成功、本地流水删除成功、记录状态更新为 `deleted`
- 平台删除失败时:本地流水不删除、记录状态不变
- 本地流水删除失败时:记录状态不变
-`parsed_success` 状态删除时返回失败
- `deleted` 状态重复删除时返回失败
- 缺少 `logId``lsfxProjectId` 时返回失败
### 控制器测试
- 删除接口成功返回正确消息
- Service 抛出异常时返回错误消息
### 前端测试
- `parsed_failed` 状态显示“查看错误原因”
- `parsed_success` 状态显示“删除”
- `deleted` 状态显示“已删除”且不显示操作按钮
- 删除前弹出二次确认
- 删除成功后刷新列表和统计
- 错误原因弹窗能正确显示 `errorMessage`
## 验收标准
- 上传文件列表新增“操作”列
- 解析失败文件可以查看错误原因
- 解析成功文件可以二次确认后删除
- 删除成功后已调用流水分析平台删除接口
- 删除成功后本地银行流水数据被清理
- 删除成功后上传记录仍保留,状态显示为“已删除”
- 已删除记录不再出现删除按钮
---
**设计日期:** 2026-03-16
**设计人员:** Codex
**审核状态:** 已确认