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>
129 lines
4.6 KiB
Markdown
129 lines
4.6 KiB
Markdown
# OA 发起审批草稿箱 Implementation Plan
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** 发起审批可暂存草稿,并新增「草稿箱」菜单支持再编辑、保存、提交与删除。
|
||
|
||
**Architecture:** 独立表 `oa_instance_draft` 存发起人填写草稿;提交时复用 `oa_engine.start_instance`,成功后软删草稿。前端在发起弹窗加「暂存草稿」,新建 `drafts/index.vue` 列表页。
|
||
|
||
**Tech Stack:** FastAPI + SQLAlchemy + MySQL;Vue 3 + Element Plus;Fresh Mint UI。
|
||
|
||
**Spec:** `docs/superpowers/specs/2026-08-06-oa-approval-instance-draft-design.md`
|
||
**UI Demo:** `docs/demos/oa-approval-draft-box-demo.html`
|
||
|
||
---
|
||
|
||
## File map
|
||
|
||
| 文件 | 职责 |
|
||
|------|------|
|
||
| `docs/sql/oa_instance_draft.sql` | 建表 + `sys_menu` 草稿箱 |
|
||
| `backend/app/models/models.py` | `OaInstanceDraft` |
|
||
| `backend/app/crud/oa_instance_draft.py` | 草稿 CRUD |
|
||
| `backend/app/api/oa_approval.py` | drafts 路由 |
|
||
| `backend/tests/test_oa_instance_draft.py` | 权限/序列化/提交后软删等单测 |
|
||
| `web-admin/src/api/oaApproval.ts` | drafts API |
|
||
| `web-admin/src/router/modules/sqxp.ts` | 路由「草稿箱」 |
|
||
| `web-admin/src/views/oa-approval/drafts/index.vue` | 草稿箱页 |
|
||
| `web-admin/src/views/oa-approval/start/index.vue` | 暂存按钮 + draftId 回填 |
|
||
| `待同步到生产的sql脚本` | 追加本 SQL 引用说明(若团队习惯) |
|
||
|
||
---
|
||
|
||
### Task 1: SQL 建表与菜单
|
||
|
||
**Files:**
|
||
- Create: `docs/sql/oa_instance_draft.sql`
|
||
|
||
- [x] **Step 1: 编写 SQL**
|
||
- [x] **Step 2: 本地执行 SQL(若有 DB)** — 脚本已写入 `docs/sql/oa_instance_draft.sql`,需在目标库手动执行
|
||
- [x] **Step 3: Commit** — 待用户要求再提交
|
||
|
||
---
|
||
|
||
### Task 2: SQLAlchemy 模型
|
||
|
||
**Files:**
|
||
- Modify: `backend/app/models/models.py`(紧挨 `OaInstance` 之前或之后)
|
||
|
||
- [ ] **Step 1: 增加 `OaInstanceDraft`**
|
||
- [ ] **Step 2: Commit** `feat(backend): add OaInstanceDraft model.`
|
||
|
||
---
|
||
|
||
### Task 3: CRUD + API(TDD)
|
||
|
||
**Files:**
|
||
- Create: `backend/app/crud/oa_instance_draft.py`
|
||
- Modify: `backend/app/api/oa_approval.py`
|
||
- Create: `backend/tests/test_oa_instance_draft.py`
|
||
|
||
- [ ] **Step 1: 写失败/单元测试**(`_row_to_dict` 字段、owner 校验逻辑可用纯函数;提交后 `del_flag` 行为可用 mock Session)
|
||
|
||
- [ ] **Step 2: 实现 CRUD**
|
||
- `list_drafts`, `get_draft`, `create_draft`, `update_draft`, `soft_delete`, `batch_soft_delete`
|
||
- list join `OaApp` 取 `appName`、version_no;仅 `owner_user_id`
|
||
|
||
- [ ] **Step 3: 挂路由**
|
||
- GET/POST `/drafts`
|
||
- GET/PUT/DELETE `/drafts/{id}`
|
||
- POST `/drafts/batch-delete`
|
||
- POST `/drafts/{id}/submit` → `start_instance` + soft delete
|
||
|
||
- [ ] **Step 4: pytest 通过**
|
||
- [ ] **Step 5: Commit** `feat(backend): OA instance draft CRUD and submit API.`
|
||
|
||
---
|
||
|
||
### Task 4: 前端 API + 路由
|
||
|
||
**Files:**
|
||
- Modify: `web-admin/src/api/oaApproval.ts`
|
||
- Modify: `web-admin/src/router/modules/sqxp.ts`(发起审批与待办之间插入 drafts)
|
||
- Modify: `web-admin/src/types/api.d.ts`(若有 OA 类型需补)
|
||
|
||
- [ ] **Step 1: API 封装**
|
||
- [ ] **Step 2: 路由 meta.title=`草稿箱`, menuCode=`oa:drafts`**
|
||
- [ ] **Step 3: Commit**
|
||
|
||
---
|
||
|
||
### Task 5: 草稿箱页面
|
||
|
||
**Files:**
|
||
- Create: `web-admin/src/views/oa-approval/drafts/index.vue`
|
||
|
||
- [ ] **Step 1: 按 Demo +「我发起的」模式做列表**(筛选、表格、分页、操作列 min-width≥260、状态 Tag)
|
||
- [ ] **Step 2: 编辑打开弹窗(可内嵌复用 start 逻辑或跳转 `start?draftId=`)——**采用 `start?draftId=`** 减少重复
|
||
- [ ] **Step 3: 提交/删除/批量删除接线**
|
||
- [ ] **Step 4: Commit**
|
||
|
||
---
|
||
|
||
### Task 6: 发起页暂存与回填
|
||
|
||
**Files:**
|
||
- Modify: `web-admin/src/views/oa-approval/start/index.vue`
|
||
|
||
- [ ] **Step 1: footer 增加「暂存草稿」**(取消 / 暂存 / 提交;主色仅提交)
|
||
- [ ] **Step 2: `route.query.draftId` 加载详情并回填;保存走 PUT**
|
||
- [ ] **Step 3: 暂存成功提示并关弹窗**
|
||
- [ ] **Step 4: Commit**
|
||
|
||
---
|
||
|
||
### Task 7: 收尾
|
||
|
||
- [ ] **Step 1:** `./scripts/update-graph.sh all`(或 backend+frontend)
|
||
- [ ] **Step 2:** 自测清单对照 spec「测试要点」
|
||
- [ ] **Step 3:** 确认 `App.vue` panelTitleBarTextRules 含「草稿箱」(若需要竖条)
|
||
|
||
---
|
||
|
||
## 验收
|
||
|
||
1. 发起弹窗可暂存,草稿箱可见。
|
||
2. 编辑回填 → 再保存 → 提交后出现在「我发起的」,草稿消失。
|
||
3. 他人账号看不到该草稿。
|
||
4. 暂存不产生待办任务。
|