Files
shanxia2.0/docs/superpowers/specs/2026-09-05-reimburse-apply-attachments-design.md
T

7.3 KiB
Raw Blame History

报销申请「申请附件」(可选补充材料)— 设计文档

日期: 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