2026-08-06-oa-approval-instance-draft-design.md 6.1 KB

OA 发起审批草稿箱 Design

项 内容
日期 2026-08-06
状态 已定稿(UI 以 docs/demos/oa-approval-draft-box-demo.html 为准)
范围 发起审批「暂存草稿」+ 侧栏「草稿箱」列表(再编辑 / 保存 / 提交 / 删除)

背景

现状「发起审批」弹窗仅有「取消」「提交」,填到一半关闭即丢失。客户要求可暂存草稿,并在「发起审批」下方增加「草稿箱」菜单集中管理。

现有 oa_app_version.status=draft 仅为模板设计草稿,与本需求的发起人填写草稿无关,不得混用。

目标与非目标

目标

  • 发起弹窗可「暂存草稿」,不进入审批流、不产生待办。
  • 侧栏「草稿箱」列出当前用户草稿;支持编辑、再次保存、提交审批、删除与批量删除。
  • 草稿仅本人可见(租户内 + 发起人 = 当前用户)。

非目标

  • 不与「我发起的」实例混排;草稿不是 oa_instance。
  • 不做跨用户共享草稿、不做审批人代填。
  • 不做自动定时暂存(仅显式点击「暂存草稿 / 保存草稿」)。
  • 不改造小程序端(本期仅 web-admin)。

方案对比与结论

方案 做法 优点 缺点
A(推荐) 独立表 oa_instance_draft 与引擎解耦;「我发起的」无需过滤 draft;语义清晰 多一张表与一套 CRUD
B oa_instance.status=draft 少表 引擎/列表/关联审批处处要排除;误发起风险高
C 仅浏览器 localStorage 无后端 换设备丢失;无法做菜单级权限与审计

选定 A。 提交时调用现有 start_instance,成功后软删对应草稿。

数据模型

表名:oa_instance_draft

字段 说明
id VARCHAR(64) PK,UUID
app_id 审批应用 ID
app_version_id 暂存时锁定的已发布版本(提交时优先用最新已发布版,见下)
title 可选标题(可由应用名或表单字段推导,可空)
form_data_json 表单数据 JSON
initiator_select_json 发起人自选 {nodeId:[userId,...]}
initiator_dept_id 发起部门(与发起接口一致)
owner_user_id 草稿所属人(= 创建人)
公共字段 tenant_no … del_flag(遵循 database-conventions)

约束与行为:

  • 同一用户对同一 app_id 允许多条草稿(与 Demo 列表一致)。
  • 列表默认 create_time DESC 不适用时,用 update_time DESC(最近保存优先)。
  • 删除:软删 del_flag=1。
  • 暂存不做完整必填校验;提交走与正式发起相同的校验。

版本策略

  • 暂存:写入当时「最新已发布」app_version_id。
  • 编辑打开:用该草稿的 app_id 取当前最新已发布模板渲染;form_data / initiator_select 按 field 名回填(字段已删则忽略多余键)。
  • 若应用已无已发布版本:编辑/提交时提示「该审批单已下架或未发布」,禁止提交,允许删除草稿。

API(/api/admin/oa-approval)

方法 路径 说明
GET /drafts 当前用户草稿分页;query:keyword(流程名)、groupId、updateTimeFrom/updateTimeTo、page/pageSize
GET /drafts/{id} 草稿详情(含 formData、initiatorSelect、app 基础信息)
POST /drafts 新建草稿(appId + formData + initiatorSelect + initiatorDeptId + title?)
PUT /drafts/{id} 更新草稿(仅 owner)
DELETE /drafts/{id} 软删单条
POST /drafts/batch-delete body: { ids: string[] } 批量软删
POST /drafts/{id}/submit 校验 + start_instance;成功后软删草稿;返回实例信息

权限:均需登录管理端用户;读写仅限 owner_user_id == 当前用户 且同 tenant_no。菜单码:oa:drafts(列表/读写统一挂此码,与 oa:start 同级授权习惯)。

前端

菜单与路由

  • 侧栏顺序:… → 发起审批 → 草稿箱 → 待办中心 → …
  • 路由:/#/system-manage/oa-approval/drafts,组件 web-admin/src/views/oa-approval/drafts/index.vue
  • 前端路由模块 sqxp.ts 与库表 sys_menu(SQL 脚本)同步增加菜单项。

发起页 start/index.vue

  • 弹窗底栏:取消 | 暂存草稿 | 提交(主色仅「提交」)。
  • 「暂存草稿」:调用 POST/PUT drafts;成功提示「已存入草稿箱」并关弹窗(或保持打开——关弹窗,与 Demo 心智一致)。
  • 若路由带 draftId(从草稿箱「编辑」跳入):打开对应模板并回填,暂存走 PUT。

草稿箱页(对齐「我发起的」列表模式)

列:序号、流程名称、模板版本、最近保存、状态(Tag「草稿」warning)、操作(编辑 / 提交审批 / 删除)。

  • 编辑:router.push 到发起页并带 draftId(或本页弹窗复用发起表单——推荐跳转发页 + query,少复制逻辑;若发起页已是弹窗模式,则在草稿箱页复用同一套 dialog 逻辑亦可。实现择一:草稿箱页内嵌与 start 相同的发起弹窗,避免整页跳转丢上下文)。
  • 提交审批:调用 POST /drafts/{id}/submit;若校验失败,打开编辑弹窗并展示错误。
  • 删除 / 批量删除:二次确认后调用删除接口。

筛选:流程名称、保存时间范围、模板分组(与 Demo 一致)。

错误处理

  • 非 owner / 已删:404 或 403,文案「草稿不存在或无权访问」。
  • 提交时应用不可用:400 + 明确文案。
  • 批量删除:跳过无权 id,返回成功数(或全部失败则报错)——采用 全部校验通过再删,任一无权则整批失败。

测试要点

  • 暂存后草稿箱可见;他人不可见。
  • 更新草稿只改本人记录。
  • 提交成功产生 oa_instance 且草稿软删;「我发起的」出现新实例。
  • 暂存不产生 oa_task。
  • 无发布版本时禁止提交。

UI 权威

docs/demos/oa-approval-draft-box-demo.html;视觉遵循 Fresh Mint / docs/web-admin-ui-spec-fresh-mint.md。