Add approval instance drafts with menu badges, dual-track user/role read model and role bound names, form-designer outline docs, and bare-metal test deploy scripts. Ignore local test-server credential file. Co-authored-by: Cursor <cursoragent@cursor.com>
124 lines
6.1 KiB
Markdown
124 lines
6.1 KiB
Markdown
# 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`。
|