diff --git a/specs/002-rev005-invoice-flow/frontend-finance-design.md b/specs/002-rev005-invoice-flow/frontend-finance-design.md new file mode 100644 index 0000000..ebba5bc --- /dev/null +++ b/specs/002-rev005-invoice-flow/frontend-finance-design.md @@ -0,0 +1,866 @@ +# REV-005 财务后台发票管理前端设计 + +**Feature**: `002-rev005-invoice-flow` +**Date**: 2026-05-12 +**Audience**: 财务经办、财务主管、客服协同、系统管理员 +**Purpose**: 在既有 REV-005 发票业务流正式工件基础上,补充面向财务人员的前端页面、菜单层级、字段组织、状态模型与跳转关系设计,作为 `water-frontend` 页面实现的直接输入。 + +--- + +## 1. 设计目标 + +本设计聚焦 `SYS-002 > REV-005 发票管理` 后台前端,服务对象为财务人员,遵循以下目标: + +1. 采用现有仓库已验证的前端页面模板,不引入新的页面组织范式。 +2. 以财务批量处理为主、单笔处理为辅,保证高频操作路径最短。 +3. 以缴费记录作为发票开具主数据源,以客户汇总作为大客户辅助视图,账单维度仅作为特殊补充能力。 +4. 将红冲、作废、异常从普通查询中独立出来,形成可追踪、可授权、可审计的任务池页面。 +5. 让财务人员进入页面后优先看到金额、状态、号码与失败原因,降低筛选和定位成本。 + +--- + +## 2. 设计范围 + +本轮仅覆盖 `REV-005` 财务后台前端,不扩展到: + +- `CS-004` 客户侧电子发票服务 +- `WECHAT-004` 微网厅电子发票服务 +- `SYS-008` 发票服务子系统自身后台 +- 发票物理打印页面 +- 复杂自由拆票规则配置页面 + +本设计作为 `REV-005` 前端实现补充,不替代既有 `spec.md`、`plan.md`、`tasks.md`、`contracts/` 与 `data-model.md` 的正式业务口径。 + +--- + +## 3. 用户与职责边界 + +### 3.1 目标用户 + +- **财务经办**:待开票记录筛选、批量开票、查看结果 +- **财务主管**:红冲、作废、大额合并开票、异常处理 +- **客服协同**:只读查询、查看发票状态、查看开票信息 +- **系统管理员**:全量权限、配置联调与问题核查 + +### 3.2 高风险动作 + +以下动作必须单独授权,不能仅因拥有列表查看权限而自动获得: + +- 客户汇总合并开票 +- 红冲处理 +- 作废处理 +- 异常改派 +- 账单维度补充开票 +- 大额批量开票 +- 人工强制重试 + +--- + +## 4. 页面模板选型 + +### 4.1 主模板 + +采用 `water-frontend` 既有 **标准列表查询页** 模板,参考: + +- `src/views/infra/config/index.vue` +- `src/views/settings/config/invoiceTaxRate/index.vue` + +适用于以下页面: + +- 发票开具 +- 发票查询 +- 红冲处理 +- 作废处理 +- 异常处理 + +### 4.2 辅模板 + +- **详情展示页**:发票详情页 +- **弹窗表单页**:开票信息维护、批量开票确认、红冲原因、作废原因、异常日志 + +### 4.3 不采用的模式 + +本轮不采用新的“首页工作台”或“多栏组合工作台”模式,避免偏离现有模板体系。 + +--- + +## 5. 菜单层级设计 + +### 5.1 菜单树 + +- **一级菜单**:营收业务 +- **二级菜单**:发票管理 +- **三级菜单**: + 1. 发票开具 + 2. 发票查询 + 3. 红冲处理 + 4. 作废处理 + 5. 异常处理 + +### 5.2 菜单命名原则 + +- 名称面向财务人员理解,不使用技术化名称。 +- 菜单名称直接对应主要任务,不采用“管理中心”“作业平台”等泛化命名。 +- 红冲、作废、异常分别独立,不与“发票查询”混合。 + +--- + +## 6. 总体交互原则 + +1. 财务主入口固定为 **发票开具**。 +2. 发票开具默认展示 **缴费记录视图**,并在页内切换到 **客户汇总视图**。 +3. 发票查询作为历史结果与后续处理入口页。 +4. 红冲、作废、异常均按“任务池”组织,优先突出待处理量和失败原因。 +5. 所有高风险动作都需要二次确认。 +6. 所有列表页均支持批量操作、导出与列配置。 + +--- + +## 7. 数据源口径 + +### 7.1 主数据源:缴费记录待开票 + +适用于: + +- 居民用户电子普票 +- 中小客户单笔开票 +- 后台财务批量开票 +- 特殊开账缴费后的开票 + +页面表现: + +- 发票开具页默认视图 +- 一笔缴费记录是一个待开票对象 +- 支持同一客户多笔缴费记录批量开票 + +### 7.2 辅助数据源:客户汇总待开票 + +适用于: + +- 大客户 +- 政企客户 +- 需要合并开票的集团户 +- 专票场景 + +页面表现: + +- 仅在发票开具页内切换视图 +- 先看客户聚合,再展开客户下的待开票缴费记录 + +### 7.3 备用数据源:账单维度待开票 + +仅用于极特殊场景,不作为常规菜单或默认视图: + +- 预付费特殊口径 +- 协议先票后款 +- 历史遗留修复 + +页面表现: + +- 不提供独立菜单 +- 仅通过特殊权限入口进入 + +--- + +## 8. 页面设计 + +## 8.1 发票开具页 + +### 页面定位 + +财务主作业页,用于待开票记录筛选、批量开票、单笔开票、查看开票信息。 + +### 页面结构 + +1. **查询区** + - 缴费日期范围 + - 缴费单号 + - 客户编号 + - 客户名称 + - 用户类型 + - 开票状态 + - 发票类型 + - 营业网点 / 水司 + - 收费渠道 + - 是否大客户 + - 特殊开账标识 + +2. **统计条区** + - 待开票笔数 + - 待开票金额 + - 今日新增待开票 + - 大客户待开票金额 + +3. **工具栏区** + - 查询 + - 重置 + - 批量开票 + - 批量校验 + - 导出 + - 切换视图(缴费记录 / 客户汇总) + +4. **表格区** + - 默认:缴费记录待开票表 + - 切换:客户汇总待开票表 + +### 缴费记录视图字段 + +- 选择框 +- 缴费日期 +- 缴费单号 +- 客户编号 +- 客户名称 +- 户号 +- 水表号 +- 账期 +- 缴费金额 +- 可开票金额 +- 费用类型 +- 发票类型 +- 开票抬头 +- 税号 +- 开票状态 +- 特殊开账标识 +- 收费渠道 +- 收费员 +- 操作 + +### 客户汇总视图字段 + +- 选择框 +- 客户编号 +- 客户名称 +- 客户类型 +- 税号 +- 未开票笔数 +- 未开票金额 +- 默认发票类型 +- 默认开票信息完整度 +- 最近开票日期 +- 操作(展开明细 / 合并开票) + +### 行内动作 + +- 查看明细 +- 查看开票信息 +- 单笔开票 + +### 批量动作 + +- 批量开票 +- 批量校验 +- 批量导出 + +### 页面内视图切换要求 + +- 默认进入缴费记录视图 +- 切换至客户汇总视图时,保留已输入的共用筛选条件 +- 客户汇总视图下的开票动作仍落到缴费记录级别明细校验 + +--- + +## 8.2 发票查询页 + +### 页面定位 + +历史发票归档、结果核验与后续处理入口页。 + +### 页面结构 + +1. **查询区** + - 开票日期范围 + - 发票号码 + - 发票代码 + - 客户名称 + - 客户编号 + - 发票类型 + - 发票状态 + - 推送状态 + - 红冲状态 + - 作废状态 + - 开票人 + +2. **工具栏区** + - 查询 + - 重置 + - 导出 + - 批量下载 + - 批量重推送 + - 批量打印(后续可选) + +3. **表格区** + - 发票主记录列表 + +### 表格字段 + +- 发票号码 +- 发票代码 +- 客户名称 +- 税号 +- 开票日期 +- 发票金额 +- 关联缴费笔数 +- 发票状态 +- 推送状态 +- 下载状态 +- 红冲状态 +- 作废状态 +- 开票人 +- 操作 + +### 行内动作 + +- 详情 +- 下载 +- 重推送 +- 发起红冲 +- 发起作废 + +--- + +## 8.3 红冲处理页 + +### 页面定位 + +红字发票任务池,用于对已开具发票进行冲销处理。 + +### 页面结构 + +1. **查询区** + - 红冲申请日期 + - 原发票号码 + - 客户名称 + - 红冲状态 + - 退款状态 + - 申请人 + +2. **工具栏区** + - 查询 + - 重置 + - 批量提交红冲 + - 批量重试 + - 导出 + +3. **表格区** + - 待红冲 / 红冲中 / 红冲成功 / 红冲失败 + +### 表格字段 + +- 原发票号码 +- 原发票代码 +- 客户名称 +- 红冲申请时间 +- 红冲原因 +- 关联退款金额 +- 红冲状态 +- 失败原因 +- 申请人 +- 审核人 +- 操作 + +### 行内动作 + +- 查看原发票 +- 查看退款关联 +- 提交红冲 +- 重试 +- 查看失败原因 + +--- + +## 8.4 作废处理页 + +### 页面定位 + +作废任务池,用于对满足条件的发票进行作废。 + +### 页面结构 + +1. **查询区** + - 作废申请日期 + - 发票号码 + - 客户名称 + - 作废状态 + - 申请人 + +2. **工具栏区** + - 查询 + - 重置 + - 批量作废 + - 批量重试 + - 导出 + +3. **表格区** + - 待作废 / 作废中 / 作废成功 / 作废失败 + +### 表格字段 + +- 发票号码 +- 客户名称 +- 作废申请时间 +- 作废原因 +- 发票金额 +- 作废状态 +- 失败原因 +- 申请人 +- 操作 + +### 行内动作 + +- 查看发票详情 +- 提交作废 +- 重试 +- 查看失败原因 + +--- + +## 8.5 异常处理页 + +### 页面定位 + +集中处理开票失败、回执异常、推送异常、下载异常与对账异常的任务池页面。 + +### 页面结构 + +1. **查询区** + - 异常日期 + - 异常类型 + - 业务单号 + - 客户名称 + - 当前状态 + - 是否已重试 + - 异常节点 + +2. **工具栏区** + - 查询 + - 重置 + - 批量重试 + - 批量改派 + - 导出 + +3. **表格区** + - 开票失败 + - 回执异常 + - 下载异常 + - 推送异常 + - 对账异常 + +### 表格字段 + +- 异常类型 +- 业务单号 +- 客户名称 +- 发票号码 +- 金额 +- 异常节点 +- 异常原因 +- 重试次数 +- 最新处理时间 +- 当前状态 +- 操作 + +### 行内动作 + +- 查看详情 +- 重试 +- 查看日志 +- 改派处理 +- 标记人工处理完成 + +--- + +## 8.6 发票详情页 + +### 页面定位 + +作为独立只读详情页,承载完整发票业务轨迹,不使用普通小弹窗替代。 + +### 页面结构 + +1. 基本信息区 +2. 关联缴费记录区 +3. 开票与推送轨迹区 +4. 红冲 / 作废 / 异常日志区 + +### 推荐字段分组 + +#### 基本信息 +- 发票代码 +- 发票号码 +- 发票类型 +- 发票金额 +- 开票日期 +- 发票状态 +- 开票人 + +#### 开票对象 +- 客户编号 +- 客户名称 +- 发票抬头 +- 纳税人识别号 +- 地址电话 +- 开户行 +- 银行账号 +- 邮箱 +- 手机号 + +#### 关联业务 +- 关联缴费笔数 +- 关联缴费单号列表 +- 账期范围 +- 费用类型 +- 特殊开账标识 + +#### 处理轨迹 +- 推送状态 +- 下载状态 +- 红冲状态 +- 作废状态 +- 外部回执号 +- 最近处理时间 +- 失败原因 +- 重试次数 + +--- + +## 9. 弹窗设计边界 + +### 9.1 开票信息弹窗 + +用于查看 / 维护: + +- 发票抬头 +- 税号 +- 地址电话 +- 开户行 +- 银行账号 +- 邮箱 +- 手机号 +- 发票类型 + +### 9.2 批量开票确认弹窗 + +用于确认: + +- 本次勾选笔数 +- 本次开票总金额 +- 发票类型 +- 抬头归属 +- 校验通过/失败摘要 + +### 9.3 红冲原因弹窗 + +用于录入: + +- 红冲原因 +- 退款说明 +- 备注 +- 附件说明(后续可扩展) + +### 9.4 作废原因弹窗 + +用于录入: + +- 作废原因 +- 备注 + +### 9.5 异常日志弹窗 + +用于快速查看: + +- 异常节点 +- 原始错误信息 +- 外部回执 +- 重试记录 +- 最新处理结果 + +--- + +## 10. 页面跳转关系 + +### 10.1 主链路:批量开票 + +`发票开具页` +→ 勾选缴费记录 +→ `批量开票确认弹窗` +→ 提交开票 +→ 成功后可跳转 `发票查询页` + +### 10.2 大客户链路:客户汇总合并开票 + +`发票开具页` +→ 切换到客户汇总视图 +→ 选择客户 +→ 展开明细 / 进入客户待开票记录 +→ `批量开票确认弹窗` +→ 提交开票 +→ `发票查询页` + +### 10.3 后处理链路:红冲 / 作废 + +`发票查询页` +→ 发起红冲 / 发起作废 +→ 跳转 `红冲处理页` / `作废处理页` +→ 原票详情查看 / 填原因 / 提交处理 +→ 结果回写 `发票查询页` + +### 10.4 补救链路:异常处理 + +`异常处理页` +→ 查看失败原因 +→ 重试 / 改派 / 人工处理 +→ 回到对应业务页复核 + +--- + +## 11. 权限模型建议 + +### 11.1 菜单权限 + +- 发票开具 +- 发票查询 +- 红冲处理 +- 作废处理 +- 异常处理 + +### 11.2 按钮权限 + +#### 发票开具页 +- 查询 +- 导出 +- 查看明细 +- 查看开票信息 +- 单笔开票 +- 批量开票 +- 批量校验 + +#### 发票查询页 +- 查询 +- 导出 +- 详情 +- 下载 +- 重推送 +- 发起红冲 +- 发起作废 + +#### 红冲处理页 +- 查询 +- 导出 +- 提交红冲 +- 批量红冲 +- 重试 +- 查看失败原因 + +#### 作废处理页 +- 查询 +- 导出 +- 提交作废 +- 批量作废 +- 重试 + +#### 异常处理页 +- 查询 +- 导出 +- 重试 +- 改派 +- 查看日志 +- 标记人工完成 + +### 11.3 特殊动作权限 + +以下权限建议独立控制: + +- 客户汇总合并开票 +- 红冲 +- 作废 +- 异常改派 +- 账单维度补充开票 +- 大额批量开票 +- 人工强制重试 + +--- + +## 12. 状态模型建议 + +## 12.1 开票状态(发票开具页主状态) + +- 待开票 +- 校验失败 +- 开票中 +- 开票成功 +- 开票失败 + +## 12.2 发票生命周期状态(发票查询页主展示) + +- 已开具 +- 已推送 +- 部分推送失败 +- 红冲中 +- 已红冲 +- 作废中 +- 已作废 +- 状态异常 + +## 12.3 异常类型(异常处理页) + +- 开票失败 +- 回执异常 +- 推送异常 +- 下载异常 +- 红冲失败 +- 作废失败 +- 对账异常 + +## 12.4 展示原则 + +- 开票状态、推送状态、红冲状态、作废状态分别展示,不合并成单一总状态。 +- 列表页状态标签必须能直接支持财务筛选,不要求用户进入详情后再判断。 + +--- + +## 13. 字段优先级建议 + +### 13.1 A 级(默认必须可见) + +- 客户名称 +- 缴费单号 / 发票号码 +- 金额 +- 状态 +- 发票类型 +- 日期 +- 失败原因 / 异常状态 +- 操作 + +### 13.2 B 级(默认展示,可折叠) + +- 客户编号 +- 税号 +- 收费渠道 +- 营业网点 +- 特殊开账标识 +- 开票人 +- 推送状态 + +### 13.3 C 级(列配置按需打开) + +- 水表号 +- 户号 +- 账期 +- 商品税收分类编码 +- 下载状态 +- 最近重试时间 +- 外部回执号 +- 供应商名称 + +--- + +## 14. 字段语义分组建议 + +### 14.1 业务来源组 +- 缴费单号 +- 账单号 +- 客户编号 +- 客户名称 +- 户号 +- 水表号 +- 账期 +- 特殊开账标识 +- 收费渠道 +- 营业网点 + +### 14.2 开票主体组 +- 发票抬头 +- 纳税人识别号 +- 地址电话 +- 开户行 +- 银行账号 +- 邮箱 +- 手机号 +- 发票类型 + +### 14.3 金额税务组 +- 缴费金额 +- 可开票金额 +- 发票金额 +- 税率 +- 税额 +- 不含税金额 +- 商品税收分类编码 +- 费用类型 + +### 14.4 状态轨迹组 +- 开票状态 +- 推送状态 +- 下载状态 +- 红冲状态 +- 作废状态 +- 异常类型 +- 失败原因 +- 最近处理时间 +- 重试次数 + +### 14.5 审计留痕组 +- 开票人 +- 开票时间 +- 申请人 +- 审核人 +- 操作时间 +- 外部发票号码 +- 外部回执号 +- 处理备注 + +--- + +## 15. 财务视角下的最终方案 + +`REV-005` 前端采用“**标准列表入口 + 五个三级菜单页**”的财务后台模型: + +- `发票开具`:主作业页,默认缴费记录视图,可切客户汇总视图 +- `发票查询`:历史结果页与后处理入口页 +- `红冲处理`:红字发票任务池 +- `作废处理`:作废任务池 +- `异常处理`:失败和异常集中处理池 + +整体原则如下: + +1. 批量处理优先于单笔处理。 +2. 缴费记录优先于客户汇总,客户汇总优先于账单补充。 +3. 高风险动作单独授权。 +4. 状态拆分展示,避免财务误判。 +5. 详情页承载全量轨迹,弹窗只承接局部动作。 + +--- + +## 16. 与既有正式工件的关系 + +本文件补充的是 **前端财务页面与导航设计**,应与以下正式工件一起使用: + +- `specs/002-rev005-invoice-flow/spec.md` +- `specs/002-rev005-invoice-flow/plan.md` +- `specs/002-rev005-invoice-flow/tasks.md` +- `specs/002-rev005-invoice-flow/data-model.md` +- `specs/002-rev005-invoice-flow/contracts/if-rev-008-invoice-application.md` +- `specs/002-rev005-invoice-flow/contracts/if-rev-009-invoice-query.md` + +若后续进入 `water-frontend` 实现阶段,本文件可直接作为: + +- 路由与菜单拆分输入 +- 页面目录结构输入 +- 查询区与列表字段输入 +- 权限点拆分输入 +- 页面模板选型输入 + +--- + +## 17. 未纳入本轮的事项 + +以下内容明确不在本轮设计范围内: + +- 客户侧电子发票入口页面设计 +- 微信端电子发票入口页面设计 +- 供应商税控配置页面 +- 发票打印模板设计 +- 发票审批流页面 +- 发票统计分析看板 + +后续若扩展 `CS-004`、`WECHAT-004` 或 `SYS-008`,应分别建立独立设计补充,不在本文件中混合扩展。 diff --git a/specs/009-openguass-to-pg16-migration/spec.md b/specs/009-openguass-to-pg16-migration/spec.md new file mode 100644 index 0000000..24f514f --- /dev/null +++ b/specs/009-openguass-to-pg16-migration/spec.md @@ -0,0 +1,125 @@ +# Feature Specification: [FEATURE NAME] + +**Feature Branch**: `[###-feature-name]` +**Created**: [DATE] +**Status**: Draft +**Input**: User description: "$ARGUMENTS" + +## Document Scope & Sources *(mandatory)* + +- **Target documents**: [List the exact files intended to be updated] +- **Primary source of truth**: [List the authoritative main docs] +- **Reference sources**: [List allowed Archive/guides/supporting docs] +- **Scope decision**: [State whether this request is in scope, needs confirmation, or is out of scope] + +## Repository Scope *(mandatory)* + +- **Target repos**: + - `water-docs`: [Required / Not Required] + - `water-backend`: [Required / Not Required] + - `water-frontend`: [Required / Not Required] +- **Expected delivery type**: [Document closure / Code evidence alignment / Backend implementation / Frontend implementation / Mixed] +- **Out of scope for this round**: [List anything explicitly excluded] + +## Code Baseline *(mandatory for brownfield work)* + +- **Backend baseline**: [commit SHA / branch / N/A] +- **Frontend baseline**: [commit SHA / branch / N/A] +- **Baseline capture rule**: [How the implementation evidence will be tied back to a specific code version] + +## Evidence Scope *(mandatory)* + +- **Document evidence required**: [Which formal docs or specs must be updated] +- **Backend evidence required**: [Controllers / services / tests / compile / N/A] +- **Frontend evidence required**: [Pages / routes / build / smoke / N/A] +- **Verification artifacts required**: [baseline.md / docs-validation.md / backend-validation.md / frontend-validation.md / final-verdict.md] + +## User Scenarios & Testing *(mandatory)* + + + +### User Story 1 - [Brief Title] (Priority: P1) + +[Describe the primary independently reviewable outcome in plain language] + +**Why this priority**: [Explain the value and why it has this priority level] + +**Independent Test**: [Describe how this can be reviewed independently] + +**Acceptance Scenarios**: + +1. **Given** [initial state], **When** [action], **Then** [expected outcome] +2. **Given** [initial state], **When** [action], **Then** [expected outcome] + +--- + +### User Story 2 - [Brief Title] (Priority: P2) + +[Describe this user journey in plain language] + +**Why this priority**: [Explain the value and why it has this priority level] + +**Independent Test**: [Describe how this can be tested independently] + +**Acceptance Scenarios**: + +1. **Given** [initial state], **When** [action], **Then** [expected outcome] + +--- + +### User Story 3 - [Brief Title] (Priority: P3) + +[Describe this user journey in plain language] + +**Why this priority**: [Explain the value and why it has this priority level] + +**Independent Test**: [Describe how this can be tested independently] + +**Acceptance Scenarios**: + +1. **Given** [initial state], **When** [action], **Then** [expected outcome] + +--- + +### Edge Cases + +- What happens when the formal document conclusion and the current code evidence do not align? +- What happens when a requested change is only supported by Archive history but not by current main docs? +- How does the workflow handle broken relative links, unstable anchors, or Mermaid syntax regressions introduced by edits? +- What happens when the backend and frontend are on different commits and the feature must still produce a single verdict? + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: Specification MUST identify the exact target documents that will be changed. +- **FR-002**: Specification MUST identify the main source-of-truth documents that govern the change. +- **FR-003**: Specification MUST identify which repositories are in scope and which are explicitly out of scope for the round. +- **FR-004**: Specification MUST record backend/frontend code baselines or explicitly mark them N/A. +- **FR-005**: System MUST preserve the single-source-of-truth model and MUST NOT assume creation of new parallel formal documents unless explicitly approved. +- **FR-006**: Specification MUST list the validation actions needed after the change, including file validation and any required link or Mermaid checks. +- **FR-007**: Specification MUST state whether management ledgers need updates in `01_Project_Progress.md` and `03_Task_Checklist.md`. +- **FR-008**: Specification MUST capture cross-document consistency impacts when terminology, numbering, diagrams, references, or interface contracts may change. +- **FR-009**: Specification MUST define what evidence artifacts are required before the feature can be marked complete. + +### Key Entities *(include if feature involves data)* + +- **Target Document**: A Markdown file that will be modified as part of the request. +- **Source of Truth Document**: A main document or governance document that constrains allowed conclusions. +- **Reference Source**: Archive or guide material used only for verification, traceability, or scope judgment. +- **Code Baseline**: A backend or frontend commit reference used to anchor brownfield implementation evidence. +- **Evidence Artifact**: A document under `specs/` or `evidence/` that records validation, code proof, or the final verdict. +- **Ledger Update**: A required change to project progress or task checklist records after important modifications. + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: Every target document and in-scope repository is explicitly named before implementation begins. +- **SC-002**: Every completed change can be traced to at least one source-of-truth or approved reference source. +- **SC-003**: Required validation and evidence actions are explicitly listed and can be executed without ambiguity. +- **SC-004**: Reviewers can determine from the spec alone whether ledger updates, code-baseline capture, and cross-document sync are required. +- **SC-005**: The feature can produce a final verdict without relying on unstated assumptions about backend or frontend implementation status. diff --git a/specs/012-xlsx-export-unification/spec.md b/specs/012-xlsx-export-unification/spec.md new file mode 100644 index 0000000..d758e44 --- /dev/null +++ b/specs/012-xlsx-export-unification/spec.md @@ -0,0 +1,164 @@ +# Feature Specification: Excel 导出 xlsx 统一化与前端 CSV 替换 + +**Feature Branch**: `012-xlsx-export-unification` +**Created**: 2026-05-15 +**Status**: Draft +**Input**: User description: "前端也是 两个分任务一起工作" / "按这个方案做" + +## Document Scope & Sources *(mandatory)* + +- **Target repositories**: + - `../water-backend/` + - `../water-frontend/` +- **Primary source of truth**: + - `../water-backend/sw-framework/sw-spring-boot-starter-excel/src/main/java/cn/com/emsoft/sw/framework/excel/core/util/ExcelUtils.java` + - `../water-frontend/src/views/operatingCharges/redReversalRecord/index.vue` + - `../water-frontend/src/views/collection/bankCollection/index.vue` + - `../water-frontend/src/views/collection/bankCollection/detail.vue` + - `../water-frontend/src/views/collection/bankWithholding/index.vue` + - `../water-frontend/src/views/collection/realTimeBilling/index.vue` + - `../water-frontend/src/utils/download.ts` +- **Reference sources**: + - `../water-backend/AGENTS.md` + - `../water-frontend/AGENTS.md` + - `../water-docs/AGENTS.md` +- **Code baselines**: + - backend SHA: `82b2a4bb2` + - frontend SHA: `156fe74e` +- **Scope decision**: In scope。本次工作聚焦两个并行子任务:一是后端统一 Excel 下载为标准 `.xlsx` 响应;二是前端将已确认的 5 个本地 CSV 导出页面改为调用后端真实导出接口。除为打通这 5 个页面所必需的最小接口补齐外,不扩展到其他页面重构或下载体系重写。 + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - 后端统一 xlsx 下载口径 (Priority: P1) + +作为系统维护人员,我希望后端公共 Excel 导出能力统一返回标准 `.xlsx` 文件及对应响应头,这样 Excel 客户端和浏览器不会再遇到“扩展名与文件格式不一致”的识别风险。 + +**Why this priority**: 公共 `ExcelUtils` 是后端导出统一入口,优先统一这里可以一次性消除全站 Excel 导出头信息不规范的问题。 + +**Independent Test**: 任选一个现有后端导出接口下载文件,审阅者无需阅读实现即可确认响应头与文件名后缀均为 `.xlsx` 语义,且文件可被 Excel 正常打开。 + +**Acceptance Scenarios**: + +1. **Given** 某个使用 `ExcelUtils.write(...)` 的导出接口,**When** 用户触发下载,**Then** 响应 `Content-Type` 为 xlsx 对应值,文件名以后缀 `.xlsx` 下载。 +2. **Given** 系统中其他依赖 `ExcelUtils.write(...)` 的导出接口,**When** 它们继续使用公共导出工具,**Then** 无需各自复制下载头逻辑即可继承统一的 xlsx 行为。 + +--- + +### User Story 2 - 前端页面不再本地拼 CSV (Priority: P1) + +作为业务用户,我希望“红冲记录、银行托收、托收明细、银行代扣、实时收费”这些页面的导出直接下载后端生成的 Excel 文件,而不是前端本地把当前列表拼成 CSV。 + +**Why this priority**: 这些页面当前导出逻辑与系统其他 Excel 导出路径不一致,且只导出前端内存数据,存在格式、口径和分页数据缺失风险。 + +**Independent Test**: 审阅者在这 5 个页面逐一点击导出,无需查看代码即可确认浏览器下载的是后端返回的 Excel 文件,而不是前端即时生成的 `.csv` 文件。 + +**Acceptance Scenarios**: + +1. **Given** 用户在红冲记录页点击导出,**When** 请求发往后端导出接口,**Then** 浏览器下载后端生成的 Excel 文件,不再生成 `.csv` Blob。 +2. **Given** 用户在银行托收、托收明细、银行代扣、实时收费页面点击导出,**When** 各页面调用对应后端接口,**Then** 下载文件由后端生成,文件内容以查询条件为准,而不是仅以当前页 `list.value` 为准。 + +--- + +### User Story 3 - 前后端并行可交付 (Priority: P2) + +作为项目执行人员,我希望本次改动能拆成后端 lane 与前端 lane 并行推进,并通过 worktree/分支隔离,便于先完成后端统一能力,再接线前端页面并做联调验证。 + +**Why this priority**: 本次涉及两个代码仓,若不提前明确并行边界与依赖顺序,容易造成前端等待后端、或后端改动无法快速联调。 + +**Independent Test**: 审阅者只查看规格与后续计划,即可明确 backend lane、frontend lane 各自修改范围、依赖顺序与最小验证要求。 + +**Acceptance Scenarios**: + +1. **Given** 需要同时修改 `water-backend` 和 `water-frontend`,**When** 实施按计划推进,**Then** 两个 lane 的修改边界清晰,且能在同一 feature 闭环下联调。 +2. **Given** 某个前端页面缺少现成导出接口,**When** 盘点后确认缺口,**Then** 仅补齐该页面所需最小后端导出接口,不扩大到无关页面。 + +--- + +### Edge Cases + +- 若后端 `ExcelUtils` 已统一为 `.xlsx`,但某些 controller 仍手工写死 `.xls` 文件名,则实施时必须一并盘点并修正受影响接口,避免公共工具与业务文件名口径冲突。 +- 若某个前端页面尚无对应后端导出接口,则前端不能继续保留本地 CSV 兜底;必须在计划中明确“先补接口,再接前端”。 +- 若前端查询条件包含日期区间、分页或详情上下文,导出请求必须复用页面实际查询条件,而不是重新拼装一套口径不一致的参数。 +- 若后端返回流式文件下载,前端下载封装必须按文件流处理,不得再次包装为本地 CSV Blob。 +- 若文件名包含中文、空格或特殊字符,后端响应头与前端下载链路必须保持统一编码策略,避免下载后文件名乱码。 + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: 后端公共导出工具 MUST 将 Excel 下载响应头统一为 `.xlsx` 语义,包括标准 xlsx `Content-Type`。 +- **FR-002**: 后端公共导出工具 MUST 保证下载文件名以后缀 `.xlsx` 返回,避免继续暴露 `.xls` 与实际文件格式不一致的问题。 +- **FR-003**: 本次前端 MUST 替换以下页面的本地 CSV 导出实现: + - `src/views/operatingCharges/redReversalRecord/index.vue` + - `src/views/collection/bankCollection/index.vue` + - `src/views/collection/bankCollection/detail.vue` + - `src/views/collection/bankWithholding/index.vue` + - `src/views/collection/realTimeBilling/index.vue` +- **FR-004**: 以上 5 个页面 MUST 通过后端真实导出接口下载文件,不得继续使用 `headers.join(',')`、`new Blob(... text/csv ...)`、`.csv` 文件名等本地 CSV 方案。 +- **FR-005**: 前端导出请求 MUST 复用页面当前查询条件或上下文参数,确保导出数据口径与页面筛选条件一致。 +- **FR-006**: 实施前 MUST 盘点上述 5 个页面各自是否已有后端导出接口;若缺失,则仅补齐该页面所需最小后端导出接口。 +- **FR-007**: 若某页面已有后端导出接口,前端 MUST 优先复用现有接口,不得新增平行接口。 +- **FR-008**: 前端共享下载逻辑 MAY 继续复用现有下载工具,但最终下载对象 MUST 是后端返回的文件流,而不是前端自行生成的 CSV Blob。 +- **FR-009**: 本次实施 MUST 采用前后端并行子任务组织:backend lane 聚焦公共导出工具与必要接口补齐,frontend lane 聚焦 5 个页面接线与移除 CSV 逻辑。 +- **FR-010**: 本次实施 MUST 在 worktree/分支隔离下完成,避免直接在 `develop` 上混改。 +- **FR-011**: 后端下载文件名与响应头中可编码的文件名部分 MUST 做统一编码处理,避免中文文件名在浏览器或跨端下载场景中出现乱码。 +- **FR-012**: 验证 MUST 至少覆盖后端最小编译/导出验证、前端最小构建或类型验证,以及 5 个页面的关键导出 smoke。 +- **FR-013**: 本次工作 MUST 保持最小闭环,不顺带重构无关下载工具、无关页面或导出权限体系。 + +### Key Entities *(include if feature involves data)* + +- **公共 Excel 导出工具**: 后端 `ExcelUtils.write(...)`,是后端导出响应头与输出流写入的统一入口。 +- **页面导出实现**: 前端页面中 `handleExport` 一类导出逻辑,负责把页面查询条件映射到后端导出接口。 +- **导出接口**: 后端提供的下载型 HTTP 接口,负责根据查询条件生成 Excel 文件流。 +- **导出查询条件**: 页面当前筛选条件、详情页上下文参数或批次号等,用于保证导出口径一致。 +- **CSV 本地导出逻辑**: 前端通过数组拼接、`Blob(text/csv)` 和 `.csv` 文件名直接下载的旧方案,需被移除。 + +## Assumptions + +- `EasyExcel.write(...)` 当前写出的实际文件格式可按 `.xlsx` 标准响应来承载,本次无需替换 Excel 写入库。 +- 这 5 个页面当前仍处于本地假数据 / 本地 CSV 导出阶段,属于前端临时实现,需要切换到正式后端接口模式。 +- 可能并非 5 个页面都已具备现成后端导出接口,因此计划阶段需要先完成接口盘点,再决定哪些接口复用、哪些最小补齐。 +- 本次以 `develop` 为基线派生独立 worktree/分支进行实现,最终通过正常合并流程进入 `develop`。 + +## Clarifications + +### Session 2026-05-15 + +- Q: 发现多个前端页面使用本地 CSV 导出时,期望改成哪种方式? → A: 改成调用后端真实 Excel 导出接口。 +- Q: 后端同步修改应做到哪个层级? → A: 统一修改公共 `ExcelUtils` 为 `.xlsx`。 +- Q: 前端与后端是顺序推进还是并行分任务推进? → A: 采用前后端两个分任务一起工作。 +- Q: 执行组织方式希望怎样落地? → A: 先建立 worktree,并以分任务方式并行推进前后端修改。 + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: 任一使用 `ExcelUtils.write(...)` 的后端导出接口下载后,文件后缀为 `.xlsx`,响应头为 xlsx 标准 MIME。 +- **SC-002**: 上述 5 个前端页面代码中不再出现 `text/csv`、`.csv` 下载文件名、手工 `csvContent` 拼接逻辑。 +- **SC-003**: 5 个页面点击导出时,网络面板可观察到真实后端导出请求,而不是仅在浏览器端生成 Blob 后本地下载。 +- **SC-004**: 若存在缺失导出接口,计划与实现结果中可明确指出哪些页面复用了现有接口、哪些页面补齐了最小后端接口。 +- **SC-005**: 前后端两个 lane 的修改范围可分别审查,且在同一 feature 闭环下完成联调验证。 +- **SC-006**: 含中文的导出文件名在浏览器下载后不出现乱码。 + +## Proposed Execution Lanes + +### Backend lane + +- 基于 `develop` 派生独立 worktree/分支。 +- 修改公共 `ExcelUtils`,统一 `.xlsx` 响应。 +- 盘点 5 个页面所需后端导出接口,复用已有接口并补齐必要缺口。 +- 完成最小编译与导出接口验证。 + +### Frontend lane + +- 基于 `develop` 派生独立 worktree/分支,或在同一 feature 下使用单独前端 worktree。 +- 删除 5 个页面的本地 CSV 导出逻辑。 +- 新增/调整对应 API 调用,改为下载后端返回文件流。 +- 完成最小构建/类型检查与关键页面导出 smoke。 + +## Out of Scope + +- 其余未列入的前端页面导出改造。 +- 对全站下载工具、权限系统或路由结构做额外重构。 +- 新增与 `.xlsx` 统一无关的报表格式、模板样式或导出内容字段调整。 +- 绕过分支审查流程直接修改 `develop` 的高风险操作。 \ No newline at end of file