Files
ccdi/docs/plans/2026-03-10-project-detail-transaction-query-design.md

372 lines
9.3 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.
# 项目详情流水明细查询设计
## 概述
本次设计面向项目详情页中的“流水明细查询”菜单,按原型图实现“查询 + 筛选 + 导出”能力,不包含旧需求中的“加入分析”“二次分析”等扩展功能。
页面默认查询当前项目下全部已入库流水,数据源仅使用本地表 `ccdi_bank_statement`,不再依赖上传记录的“查看流水”跳转。上传数据页同步移除上传记录表的操作列,后续不再从上传记录进入流水明细页。
## 已确认范围
- 页面入口保留在项目详情页的 `detail` 菜单
- 默认查询范围为当前 `projectId` 下全部流水
- 上传页移除“查看流水”入口
- “导出流水”需要实现真实功能
- 导出范围为当前页面筛选后的全部结果
- 本次只做“查询 + 筛选 + 导出”
- 摘要筛选仅使用 `userMemo`
- 筛选栏中的多选项需要基于整个项目维度单独查询
- 进入页面时即并行加载列表数据和项目级多选项
## 方案对比
### 方案一:本地库专用查询模块
-`ccdi-project` 模块新增银行流水查询 Controller、Service、Mapper 查询方法
- 页面直接查询本地 `ccdi_bank_statement`
- 导出使用本地查询条件复用
优点:
- 与现有“上传后落本地库”架构一致
- 查询与导出结果稳定,可复现
- 后续可继续扩展更多项目级分析能力
缺点:
- 需要补充 DTO、VO、Mapper SQL、导出模型
### 方案二:大而全聚合接口
- 用一个接口同时返回列表、多选项、统计信息
优点:
- 前端调用少
缺点:
- 接口职责混杂
- 后续增加筛选维度时维护成本高
- 导出仍需要单独处理
### 方案三:直接回源 LSFX 接口
- 页面查询与导出实时调用流水分析平台接口
优点:
- 本地查询层改动少
缺点:
- 与现有本地入库方案冲突
- 项目级全量查询稳定性差
- 页面与导出口径难统一
## 选型
采用方案一:本地库专用查询模块。
该方案与当前 `ccdi_bank_statement``CcdiFileUploadServiceImpl` 的入库逻辑一致,最符合“项目维度统一查询 + 当前筛选导出”的实现要求。
## 页面结构
页面仍由 `ruoyi-ui/src/views/ccdiProject/detail.vue` 动态加载 `DetailQuery.vue`
`DetailQuery.vue` 从占位组件升级为正式页面,整体布局分为左右两栏:
- 左侧:固定筛选栏
- 右侧:结果区域
右侧结果区域包含:
- 标题“流水明细查询”
- 顶部页签:`全部` / `流入` / `流出`
- 导出按钮:`导出流水`
- 列表表格
- 分页器
列表中的操作位保留只读详情能力,用于打开详情抽屉或弹窗查看单条流水完整字段。
## 筛选项设计
左侧筛选栏按原型提供以下条件:
1. 交易时间
- 对应字段:`trxDate`
- 支持起止范围查询
- 后端兼容 `yyyy-MM-dd HH:mm:ss``yyyy-MM-dd`
2. 对方名称 + 空值
- 对应字段:`customerAccountName`
- 输入框为模糊匹配
- 勾选空值时匹配 `null`、空串、全空白字符串
3. 摘要 + 空值
- 对应字段:`userMemo`
- 输入框为模糊匹配
- 勾选空值时匹配 `null`、空串、全空白字符串
4. 本方主体
- 对应字段:`leAccountName`
- 多选
5. 本方银行
- 对应字段:`bank`
- 多选
6. 本方账户
- 对应字段:`leAccountNo`
- 多选
7. 交易金额
- 使用绝对值范围筛选
- 统一适配 `全部 / 流入 / 流出` 三个页签
8. 对方账户 + 空值
- 对应字段:`customerAccountNo`
- 输入框为模糊匹配
9. 交易类型 + 空值
- 对应字段:`cashType`
- 输入框为模糊匹配
## 多选项加载规则
本方主体、本方银行、本方账户三类多选项不从当前列表结果派生,而是通过单独接口按整个项目维度去重查询。
进入页面时前端并行加载:
- 列表接口:默认查询当前项目全部流水
- 多选项接口:返回整个项目维度的全部主体、银行、账户选项
多选项接口返回值:
- `ourSubjectOptions`
- `ourBankOptions`
- `ourAccountOptions`
前端多选框内部搜索仅在已加载的项目级选项上做本地过滤,不再触发额外远程请求。
## 列表列设计
表格列与原型语义对齐:
1. 交易时间
- 字段:`trxDate`
2. 本行账户/主体
- 主行:`leAccountNo`
- 副行:`leAccountName`
3. 对方名称/账户
- 主行:`customerAccountName`
- 副行:`customerAccountNo`
4. 摘要/交易类型
- 主行:`userMemo`
- 副行:`cashType`
5. 交易金额
- 流入显示 `+amountCr`
- 流出显示 `-amountDr`
- 页面展示统一输出计算后的 `displayAmount`
6. 操作
- 只读详情
## 页签与排序规则
### 页签规则
- `全部`:不过滤金额方向
- `流入`:仅查询 `amount_cr > 0`
- `流出`:仅查询 `amount_dr > 0`
### 排序规则
支持两个排序字段:
- 交易时间
- 交易金额
排序方向支持:
- 升序
- 降序
交易金额排序按绝对值排序,和金额范围筛选保持一致。
排序字段必须由后端白名单控制,禁止前端任意传值直接拼接 SQL。
## 后端接口设计
建议新增专用 Controller`CcdiBankStatementController`
### 1. 列表分页查询
- 路径:`GET /ccdi/project/bank-statement/list`
- 入参:`CcdiBankStatementQueryDTO`
- 返回:`TableDataInfo`
入参字段包括:
- `projectId`
- `tabType`
- `transactionStartTime`
- `transactionEndTime`
- `counterpartyName`
- `counterpartyNameEmpty`
- `userMemo`
- `userMemoEmpty`
- `ourSubjects`
- `ourBanks`
- `ourAccounts`
- `amountMin`
- `amountMax`
- `counterpartyAccount`
- `counterpartyAccountEmpty`
- `transactionType`
- `transactionTypeEmpty`
- `orderBy`
- `orderDirection`
### 2. 多选项查询
- 路径:`GET /ccdi/project/bank-statement/options`
- 入参:`projectId`
- 返回:`CcdiBankStatementFilterOptionsVO`
### 3. 单条详情
- 路径:`GET /ccdi/project/bank-statement/detail/{bankStatementId}`
- 返回:`CcdiBankStatementDetailVO`
### 4. 导出
- 路径:`POST /ccdi/project/bank-statement/export`
- 入参:复用 `CcdiBankStatementQueryDTO`
- 返回Excel 文件流
## 服务层设计
建议新增:
- `ICcdiBankStatementService`
- `CcdiBankStatementServiceImpl`
职责拆分:
- 列表查询参数校验与标准化
- 排序字段白名单处理
- 时间范围解析与兼容
- 多选项去重查询
- 单条详情查询
- 导出列表查询与导出模型组装
## Mapper 设计
保留现有 `CcdiBankStatementMapper`,在接口和 XML 中新增查询方法,不新增独立 Mapper。
建议补充的方法:
- `selectStatementPage`
- `selectStatementListForExport`
- `selectFilterOptions`
- `selectStatementDetailById`
SQL 规则:
- 基于 `project_id` 做主过滤
- 使用动态 SQL 处理输入框、空值、多选数组
- 用统一表达式计算排序时间字段
- 用统一表达式计算展示金额与金额排序值
## 前端设计
建议新增 API 文件:
- `ruoyi-ui/src/api/ccdiProjectBankStatement.js`
建议改造文件:
- `ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue`
- `ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue`
页面初始化流程:
1. 读取 `projectId`
2. 并行调用:
- `list`
- `options`
3. 渲染左侧筛选和右侧列表
交互规则:
- 查询、页签切换、排序切换、分页切换时重置到第一页并刷新列表
- 重置时恢复默认筛选并回到 `全部`
- 导出时使用当前筛选条件导出全部结果
## 导出规则
- 导出范围:当前页面筛选后的全部结果
- 不受当前分页限制
- 导出文件名:`项目名称_流水明细_时间戳.xlsx`
- 导出列与页面列表保持一致:
- 交易时间
- 本方账户
- 本方主体
- 对方名称
- 对方账户
- 摘要
- 交易类型
- 交易金额
- 当前筛选结果为空时,不生成空文件,直接提示“当前条件下无可导出数据”
## 异常处理
- 多选项接口失败:列表仍可查询,筛选项置空并提示可刷新重试
- 列表接口失败:显示错误态并保留当前筛选值
- 详情接口失败:仅阻断详情展示,不影响主页面
- 导出失败:保留筛选条件并提示失败原因
- 项目下无流水数据:显示空态,导出按钮禁用
## 验收标准
### 功能验收
- 进入页面时并行加载列表与项目级多选项
- 默认展示当前项目下全部流水
- 三个页签切换结果正确
- 所有筛选项单独与组合查询均正确
- 空值筛选逻辑正确
- 交易时间兼容两种时间格式
- 金额范围按绝对值筛选正确
- 排序仅支持交易时间与交易金额
- 导出结果与页面筛选口径一致
- 上传页操作列已移除,不再支持查看流水跳转
### 技术验收
- 后端遵循项目 DTO / VO 分层规范
- Controller 使用 Swagger 注释
- 简单查询由 MyBatis Plus + XML 动态 SQL 实现
- 前端 API 独立封装到 `src/api`
- 页面在桌面端和移动端均可正常展示
## 风险与约束
1. `TRX_DATE` 为字符串字段
- 需要在 SQL 或服务层统一解析,保证筛选与排序稳定
2. 历史数据可能存在空字符串与空白字符串混用
- 空值筛选必须统一兼容
3. 项目维度多选项可能数量较大
- 首版先按项目维度一次性加载
- 若实际数据量过大,再考虑远程搜索优化
4. 当前页面不引入旧需求中的二次分析能力
- 后续若扩展,需要新增业务表与关联逻辑