164 lines
11 KiB
Markdown
164 lines
11 KiB
Markdown
# 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` 的高风险操作。 |