diff --git a/docs/superpowers/specs/2026-09-05-reimburse-apply-attachments-design.md b/docs/superpowers/specs/2026-09-05-reimburse-apply-attachments-design.md new file mode 100644 index 000000000..285045677 --- /dev/null +++ b/docs/superpowers/specs/2026-09-05-reimburse-apply-attachments-design.md @@ -0,0 +1,178 @@ +# 报销申请「申请附件」(可选补充材料)— 设计文档 + +> **日期**: 2026-09-05 +> **状态**: 已确认待实现 +> **仓库**: shanxia2.0(`web-admin/` + `bx-mobile/`;后端基本不动) +> **入口**: Web `#/bx/reimburse/apply`;H5 `ReimburseApplyPage` +> **实现路径**: 方案 1 — 复用现有 `bx_attachment` / `reimburse_apply` 与现有上传组件 + +## 背景与问题 + +报销申请已支持从**发票夹**选择发票附件(`invoiceLinks`)。业务还需要上传**非发票类补充材料**(行程单、说明截图、合同等)。 + +现状: + +| 能力 | 状态 | +|------|------| +| 后端 `biz_type=reimburse_apply` | 已有 | +| Web `BxAttachmentUpload`(图/视频/PDF/Office/压缩包) | 已有(付款发放等页在用) | +| 详情/审批/付款查看申请附件 | 已有(Web 多处文案为「历史附件」) | +| 小程序报销申请上传 | 已有(本需求**不改**) | +| **Web 申请表单上传入口** | **缺失** | +| **bx-mobile 申请页上传入口** | **缺失**(详情/审批已可查看) | + +## 已确认决策 + +| # | 决策 | 说明 | +|---|------|------| +| D1 | 用途 A | 补充材料,与发票夹分开;**可选、非必填** | +| D2 | 端范围 | **Web 管理端 + bx-mobile**;不含小程序 | +| D3 | 可编辑 | 与主表单编辑权限一致(现有:`draft` / `rejected` 可编辑) | +| D4 | 文件类型 B | 与现有报销附件组件一致(图片、视频、PDF、Office、压缩包等) | +| D5 | 实现方案 1 | 复用 `bx_attachment` + `reimburse_apply`,两端补齐上传/绑定入口 | +| D6 | 文案 | 统一为「申请附件」;Web 详情等处「历史附件」改为「申请附件」 | + +--- + +## 1. 目标与范围 + +### 目标 + +1. 用户在报销申请(新建/编辑)中可上传可选申请附件。 +2. Web 与 bx-mobile 均可上传、预览/下载、删除(可编辑态);查看态可只读浏览。 +3. 与「关联发票 / 发票夹」数据与 UI 完全独立。 +4. 无附件不阻断保存与提交。 + +### 范围内 + +- `web-admin`:`views/bx/reimburse/apply/index.vue` 新增/编辑弹窗上传区;详情文案;相关查看页「历史附件」→「申请附件」 +- `bx-mobile`:`ReimburseApplyPage.vue` 上传区 + 保存绑定;详情/审批已有展示则保持并对齐文案 +- 调用已有 `attachmentApi.upload` / `bindBiz` / `listByBiz` / `delete` + +### 范围外(明确不做) + +- 小程序(`miniprogram`) +- 新库表、报销主表新字段 +- 发票夹改造、发票与附件合并 +- 强制必填 +- `biz_id=0` 孤儿附件清理任务 +- 扩大列表「发票 / 附件」计数语义改造(除非实现时发现明显错误再修) + +--- + +## 2. 数据模型 + +- 表:现有 `bx_attachment` +- `biz_type = reimburse_apply` +- `biz_id = 报销申请单 id` +- 后端接口与权限校验已支持该 `biz_type`(见 `AttachmentService` / `attachment_biz` 映射);**本需求不改 schema、不改核心服务逻辑**(除非联调发现绑定/作用域缺口再最小修补)。 + +### 绑定时序 + +``` +新建: + 用户选文件 → upload(bizType=reimburse_apply, bizId=0) + → create/update 报销单成功得到 id + → bindBiz(attachmentIds, reimburse_apply, id) + +编辑(已有 id): + 打开 → listByBiz(reimburse_apply, id) 回填 + 新上传可直接带真实 bizId(或仍 upload 后 bindNew 仅绑 _existing=false 的) + 删除 → attachmentApi.delete(软删) +``` + +与备用金申请(`AdvanceApplyPage` + `useAttachment.bindNew`)同一套路。 + +--- + +## 3. Web 管理端 + +### 3.1 新增/编辑弹窗 + +- 位置:在「关联发票(可选)」与「备注说明」之间。 +- 区块标题:`申请附件(可选)`。 +- 组件:`BxAttachmentUpload` + - `bizType="reimburse_apply"` + - 新建:`bizId` 暂为 `0`(或等价空) + - 编辑:`bizId = editingId` + - hint 可用组件默认文案。 +- `v-model` 持有当前附件列表;打开编辑时 `loadBxAttachments('reimburse_apply', id)`。 +- 保存/提交前:若 `hasUploading()` → `ElMessage.warning('附件上传中,请稍候')` 并中断。 +- 新建保存成功后:对当前未绑定附件 id 调用 `attachmentApi.bindBiz`。 +- 无附件:不调用 bind,不报错。 + +### 3.2 查看态与文案 + +- 申请详情弹窗:`历史附件` → `申请附件`;无数据不展示区块(保持现状)。 +- 同步修改仍使用「历史附件」文案的 BX 查看页(如审批、综合查看、待办/我的/全部等),统一为「申请附件」,避免与 H5/付款页「申请附件」不一致。 + +### 3.3 可编辑边界 + +- 仅现有可打开编辑弹窗的状态可改附件(`canEdit`: `draft` | `rejected`)。 +- 只读详情不可上传/删除。 + +--- + +## 4. bx-mobile + +### 4.1 申请页 `ReimburseApplyPage.vue` + +- 位置:在「关联发票」卡片与备注之间,新增「申请附件(可选)」区块。 +- 对齐 `AdvanceApplyPage`: + - `useAttachment()` + - `van-uploader` + 缩略图网格(含上传中遮罩、删除) + - 保存成功后 `attachment.bindNew('reimburse_apply', id)` + - 编辑加载 `attachment.loadList('reimburse_apply', id)` + - 上传中禁止提交,toast「附件上传中,请稍候」 +- **accept**:在备用金文档类型基础上增加 `video/*` 及常见视频扩展名,与 Web `BxAttachmentUpload` 对齐(决策 D4)。 +- 数量上限:与备用金一致,**最多 10 个**。 +- 文案明确为申请附件/补充材料,避免与发票夹混淆。 + +### 4.2 查看态 + +- `ReimburseDetailPage` / `ReimburseApprovePage` 已有「申请附件」与 `loadAttachments('reimburse_apply', …)`,保持;联调确认上传后可见即可。 + +### 4.3 可编辑边界 + +- 与现有 H5 进入编辑页条件一致;只读详情不可改。 + +--- + +## 5. 异常与边界 + +| 场景 | 行为 | +|------|------| +| 单文件上传失败 | 提示错误,移除该占位项;其它附件与表单字段保留 | +| 上传中保存/提交 | 拦截并提示稍候 | +| 删除 | 二次确认后软删;失败保留列表并提示 | +| 新建后 bind 失败 | 单据已创建;提示绑定失败;用户可再进编辑重试;**不**自动回滚整单 | +| 取消未保存 | 允许留下 `biz_id=0` 孤儿(与备用金一致,本需求不治理) | +| 无附件 | 允许保存、提交 | + +--- + +## 6. 验收标准 + +1. Web 新增/编辑可上传、预览、下载、删除申请附件;与发票夹选择互不影响。 +2. 无附件可保存、可提交。 +3. 保存后详情/审批/付款等相关查看能看到「申请附件」。 +4. bx-mobile 申请页具备同等上传/编辑能力;详情/审批可查看。 +5. 仅可编辑状态可改;其它状态只读。 +6. 文件类型与现有报销附件组件一致(含视频等)。 +7. Web 相关页不再出现「历史附件」指代申请附件的文案(已改为「申请附件」)。 + +--- + +## 7. 主要改动文件(预期) + +| 端 | 文件 | +|----|------| +| Web | `web-admin/src/views/bx/reimburse/apply/index.vue` | +| Web | 含「历史附件」的 bx 查看/审批等页面(文案统一) | +| H5 | `bx-mobile/src/views/reimburse/ReimburseApplyPage.vue` | +| 后端 | 原则上无;仅联调缺口时最小修补 | + +参考实现: + +- Web:`BxAttachmentUpload.vue`;付款发放 `payment/index.vue` +- H5:`AdvanceApplyPage.vue` + `hooks/useAttachment.ts`