diff --git a/docs/superpowers/specs/2026-10-16-oa-done-bank-receipt-upload-demo.html b/docs/superpowers/specs/2026-10-16-oa-done-bank-receipt-upload-demo.html new file mode 100644 index 00000000..dc630444 --- /dev/null +++ b/docs/superpowers/specs/2026-10-16-oa-done-bank-receipt-upload-demo.html @@ -0,0 +1,664 @@ + + + + + + 已办中心 · 银行回执单上传 Demo + + + +
+

已办中心

+ Demo · 点击操作列「上传回执」打开弹窗 +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
序号流程名称申请人申请时间当前节点流程状态操作
1费用报销申请张三2026-10-12 14:22—已完成 +
+ + + +
+
2付款申请单李四2026-10-10 09:05财务复核进行中 +
+ + + +
+
+
+ +
+ 交互说明: + 操作列新增「上传回执」→ 弹窗回显该审批实例已上传的银行回执单(多张)→ + 左侧上传卡片可继续追加 → 支持预览/下载/删除 → 点「确定」保存。 + 本 Demo 为前端示意,文件不会真正上传到服务器。 +
+ +
+ +
+ +
+ + + + diff --git a/docs/superpowers/specs/2026-10-16-oa-done-bank-receipt-upload-design.md b/docs/superpowers/specs/2026-10-16-oa-done-bank-receipt-upload-design.md new file mode 100644 index 00000000..cdb79cec --- /dev/null +++ b/docs/superpowers/specs/2026-10-16-oa-done-bank-receipt-upload-design.md @@ -0,0 +1,190 @@ +# OA 已办中心 · 上传银行回执单 + +**模块**: OA 审批 · 已办中心 +**日期**: 2026-10-16 +**状态**: 待实现 +**UI Demo**: `docs/superpowers/specs/2026-10-16-oa-done-bank-receipt-upload-demo.html` +**决策记录**: +- 实现方案: **方案 A**(`biz_attachment` 挂实例,不改 `oa_instance` 表) +- 入口仅 `web-admin`【已办中心】;有独立权限才显示按钮 +- 弹窗回显历史多张回执,支持追加、下载、删除;确定时整体覆盖保存 +- 全部已办行均可操作(不按流程类型过滤) + +--- + +## 1. 背景与目标 + +财务/经办人在审批办结后,需要为流程实例补传银行回执单(可多张)。入口放在【已办中心】操作列,通过弹窗管理该实例的回执附件。 + +**成功标准**: +- 拥有权限的用户在已办列表看到「上传回执」,打开弹窗可回显历史并继续上传 +- 无权限用户看不到按钮,且接口拒绝 +- 附件交互与展示对齐 web-admin 附件卡片化规范(Fresh Mint) + +--- + +## 2. 范围 + +### 2.1 在范围内 + +| 项 | 说明 | +|----|------| +| 入口 | `web-admin/src/views/oa-approval/done/index.vue` 操作列 | +| 弹窗 | 新组件(建议 `OaBankReceiptDialog.vue`) | +| 存储 | `biz_attachment`:`business_type=oa_bank_receipt`,`business_id=instance_id` | +| 上传 | 现有 `fetchUploadAttachment`,`folder=oa-bank-receipt` | +| API | `GET` / `PUT` `.../instances/{instance_id}/bank-receipts` | +| 权限 | 按钮级菜单 `perms=oa:done:bank-receipt` + SQL 种子 | + +### 2.2 非目标 + +- 小程序 / H5 已办中心 +- 审批详情页内展示回执 +- 打印 PDF 嵌入回执 +- 按流程类型隐藏按钮 +- 删除时物理删除 MinIO 对象(仅软删 `biz_attachment`) +- 修改 `oa_instance` 表结构 + +--- + +## 3. 交互 + +1. 操作列在「查看 / 打印」旁增加「上传回执」(图标 + 文案;有权限才渲染)。 +2. 点击打开弹窗(`dialog-form-layout`,无 backdrop blur): + - 只读摘要:流程名称、申请人、申请时间、已上传张数 + - 「银行回执单」附件区:上传卡片在首 + 历史附件卡片;支持拖拽;预览 / 下载 / 删除 +3. 打开时 `GET` 拉取历史;选文件后立即上传 MinIO;点「确定」时 `PUT` 整体覆盖保存。 +4. 取消 / 关闭不提交关联变更(已上传到 MinIO 但未 PUT 的孤儿文件可接受,与现有附件习惯一致)。 + +UI 布局以 Demo 为准。 + +--- + +## 4. 权限模型 + +| 角色/权限 | 「上传回执」按钮 | GET/PUT | +|-----------|------------------|---------| +| 能进已办中心、无 `oa:done:bank-receipt` | 不显示 | 403 | +| 拥有 `oa:done:bank-receipt` | 显示 | 允许(同租户实例) | +| 超级管理员 / `menuPermAll` | 显示 | 允许 | + +- 权限字符:`oa:done:bank-receipt` +- 菜单名:已办中心-上传银行回执 +- 挂载:`sys_menu` 按钮级节点(`menu_type=F`),父级为「已办中心」菜单 +- 前端:`useMenuPerm().hasMenuPerm('oa:done:bank-receipt')` 控制按钮显隐 +- 后端:`user_has_menu_perm` **强制**校验;禁止仅靠前端隐藏 + +--- + +## 5. 数据与 API + +### 5.1 存储 + +| 字段 | 值 | +|------|-----| +| `business_type` | `oa_bank_receipt` | +| `business_id` | OA 实例 `id`(`instance_id`) | +| 其它 | 沿用 `biz_attachment` 公共字段;删除 = `del_flag=1` | + +不新增业务表,不改 `oa_instance`。 + +### 5.2 端点 + +``` +GET /web/admin/oa-approval/instances/{instance_id}/bank-receipts +PUT /web/admin/oa-approval/instances/{instance_id}/bank-receipts +``` + +鉴权:管理端登录 + `oa:done:bank-receipt`;实例须存在且 `tenant_no` 与当前用户一致。 + +**GET 响应** + +```json +{ + "items": [ + { + "id": "...", + "fileName": "电子回单.pdf", + "fileUrl": "oa-bank-receipt/...", + "fileType": "application/pdf", + "fileSize": 120849, + "createTime": "2026-10-16 12:00:00" + } + ] +} +``` + +排序:`create_time ASC`(稳定回显顺序)。 + +**PUT body** + +```json +{ + "items": [ + { + "fileUrl": "oa-bank-receipt/...", + "fileName": "电子回单.pdf", + "fileType": "application/pdf", + "fileSize": 120849 + } + ] +} +``` + +语义:**整体覆盖**——以 body 中的 `fileUrl` 集合为准: +- 已有且仍在集合中:保留(可更新文件名等展示字段) +- 集合中新增:创建或绑定 `biz_attachment` 行(`business_type` / `business_id`) +- 库中已有但不在集合中:软删 + +允许 `items: []`(清空该实例全部银行回执关联)。 + +文件二进制上传仍走通用附件上传接口,本 PUT 只维护业务关联。 + +### 5.3 实例可见性 + +已办列表本身仅含当前用户办过的任务。本接口在有权限前提下,对**同租户且存在的实例**允许读写回执;不额外校验「当前用户必须是该实例办理人」(避免权限角色无法代传)。若产品后续要求收紧,可再加办理人校验。 + +--- + +## 6. 前端实现要点 + +| 文件 | 职责 | +|------|------| +| `done/index.vue` | 操作列按钮 + 打开弹窗;`hasMenuPerm` | +| `OaBankReceiptDialog.vue`(建议路径 `components/oa-approval/`) | GET 回显、卡片上传、PUT 保存 | +| `api/oaApproval.ts` | 封装 GET/PUT | +| `docs/sql/migrations/...` | 按钮菜单种子 | + +附件卡片:对齐 `ProtocolFormDialog`「协议附件」与 OpenSpec ui-conventions「附件上传卡片化布局」;单文件 ≤ 20MB;上传中禁止确定。 + +操作列 `min-width` 在现有基础上加宽,避免按钮被裁切。 + +--- + +## 7. 错误处理与边界 + +| 场景 | 行为 | +|------|------| +| 无权限 | 按钮隐藏;API 403 | +| 实例不存在 / 跨租户 | 400/404,不泄露他租户 | +| 上传中点确定 | 提示「附件上传中,请稍候」 | +| 单文件超 20MB | 前端拦截 | +| PUT 空列表 | 软删全部关联 | +| 并发保存 | 后写覆盖先写;不做乐观锁 | +| MinIO 上传失败 | 移除占位项并提示 | + +--- + +## 8. 验收 + +1. 无 `oa:done:bank-receipt`:看不到按钮;直接调 GET/PUT 被拒。 +2. 有权限:打开可见历史;追加 / 下载 / 删除后确定;再次打开与保存一致。 +3. UI 符合附件卡片规范与 Demo。 +4. 种子 SQL 可执行;角色勾选后刷新菜单权限码即可赋权,无需改代码。 + +--- + +## 9. 测试建议 + +- 后端:无权限 403;有权限 GET 空/非空;PUT 增删改覆盖;跨租户隔离。 +- 前端:权限显隐;上传中拦截;确定后列表与 GET 一致(可用组件/接口 mock)。