Files
shanxia2.0/docs/superpowers/specs/2026-09-02-pl-plan-draft-save-design.md
T
zlwuandCursor 70c9de3618 docs: add transport plan draft/save design for drafting follow status
Capture approved decisions for 暂存 button, drafting status, list tab, and saveMode API so implementation can follow a single spec.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 11:33:05 +08:00

180 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 运输计划「暂存 / 草稿中」设计
日期:2026-09-02
范围:`web-admin` 运输计划列表与新增/编辑弹窗;`backend` 计划 create-full / update 及跟进状态相关门禁
状态:已评审(待实现)
## 1. 背景与目标
业务希望在【运输计划】新增/编辑弹窗增加【暂存】:跳过合同、装送货段、产品等业务校验,以跟进状态「草稿中」落库,便于稍后补全。
正式【创建/保存】仍走全量校验;若原状态为草稿,正式保存后自动升为「待安排」。
## 2. 已确认决策
| 项 | 决策 |
|---|---|
| 列表默认可见 | 「草稿中」进入默认筛选(与待安排等同类) |
| 首个 Tab | 文案改为「待安排/草稿」;默认同时查 `pending_arrange` + `drafting` |
| 跟进状态筛选 | 保持多选;该 Tab 下不再禁用,可继续增删勾选 |
| 暂存校验 | 仅要求归属公司 + 创建日期;跳过业务校验 |
| 正式保存 | 草稿 → 自动变为待安排 |
| 【暂存】可见性 | 新建、草稿中、待安排可暂存;等通知/已安排/已完成/已取消不可 |
| 列表操作 | 草稿与待安排完全相同(安排运输、等通知等;动作内仍全量校验) |
| 实现路径 | 新增状态值 `drafting` + create/update 增加 `saveMode`(方案 1) |
## 3. 状态与数据模型
### 3.1 跟进状态枚举(6)
| value | 文案 | Tag 建议 |
|---|---|---|
| `drafting` | 草稿中 | `info` |
| `wait_notice` | 等通知 | `warning` |
| `pending_arrange` | 待安排 | `danger` |
| `arranged` | 已安排 | `success` |
| `completed` | 已完成 | `success` |
| `cancelled` | 已取消 | `info` |
- **不复用** 旧兼容值 `draft`(展示层曾映射为「待安排」)。
- **不动** `archive_status = draft`(归档暂存,另一概念)。
- `pl_plan.follow_status` 为字符串字段,**无需 DDL**;更新 schema 注释、前端选项与强制改状态白名单即可。
### 3.2 状态流转
```
新建【暂存】 ──────────────────▶ drafting
drafting / pending_arrange
【暂存】 ──────────────────▶ drafting
drafting
【创建/保存】formal ────────▶ pending_arrange
drafting / pending_arrange
【安排运输】全量校验 ───────▶ arranged
drafting / pending_arrange
【等通知】全量校验 ─────────▶ wait_notice
wait_notice / arranged / completed / cancelled
✕ 不允许【暂存】降级
```
### 3.3 与「待安排」对齐的门禁
凡业务上写死「仅 `pending_arrange`」且应对草稿开放的能力,同步允许 `drafting`:
- 前端:`canWaitNotice`、删除按钮可见性等
- 后端:`wait-notice`、`delete`、`ALLOWED_FORCE_FOLLOW_STATUSES`(纳入 `drafting`)
- 安排运输:全量校验通过后可从 `drafting` 直接进入 `arranged`
## 4. 接口与校验
### 4.1 请求约定
在现有接口 body 增加(缺省兼容现网):
```ts
saveMode?: 'draft' | 'formal' // 默认 'formal'
```
涉及:
- `POST /transport/plan/create-full`
- `PUT /transport/plan/{id}`
不新增独立草稿 URL。
### 4.2 服务端行为
| saveMode | 校验 | follow_status 写入 |
|---|---|---|
| `draft` | 仅强制 `belongsCompany`、`createDate`(缺省则服务端用当天);跳过 `validate_create_full`、装送货合同/产品等业务校验;不完整装送货结构宽松落库或按空段处理 | 固定 `drafting` |
| `formal` | 保持现有全量校验 | 新建 → `pending_arrange`;若原为 `drafting` → 升为 `pending_arrange`;其它正式状态按现有更新逻辑 |
`draft` 更新门禁:仅当当前 `follow_status ∈ {drafting, pending_arrange}`,否则 400「当前状态不可暂存」。
### 4.3 列表动作接口
| 接口 | 调整 |
|---|---|
| `wait-notice` | 源状态允许 `drafting` \| `pending_arrange` |
| `delete` | 允许 `drafting`(仍要求未安排运输、未归档) |
| `force-follow-status` | 白名单加入 `drafting` |
| 安排运输链路 | 全量校验后 → `arranged`(可自 `drafting`) |
## 5. 前端 UI
### 5.1 列表 Tab / 筛选
文件主要:`web-admin/src/utils/pl-display.ts`、`web-admin/src/views/pl/plan/index.vue`
- `PL_PLAN_LIST_TABS` 首项 label:`待安排/草稿`(`name` 仍为 `pending_arrange`)
- `plPlanListTabToFilters('pending_arrange')` → `followStatus: 'pending_arrange,drafting'`
- 切入该 Tab:`searchForm.followStatus = ['pending_arrange', 'drafting']`
- 离开该 Tab:恢复扩展后的 `PL_PLAN_DEFAULT_FOLLOW_STATUSES`(含 `drafting`,不含 `cancelled`)
- 跟进状态:`el-select` `multiple`;**去掉**该 Tab 下的 `:disabled`
- `PL_PLAN_FOLLOW_STATUS_OPTIONS` 增加「草稿中」/`drafting`
- `getPlPlanFollowStatusLabel` / `TagType` 支持 `drafting`
### 5.2 弹窗底栏(`PlPlanFormDialog`)
顺序:`取消` → **`暂存`**(条件)→ `创建|保存` → `创建并安排|保存并安排` / `调整运输`
【暂存】显示:
- 新建:显示
- 编辑:仅 `followStatus ∈ {drafting, pending_arrange}`
样式:中性描边(非 primary);与保存共用/互斥 loading。
`handleSubmit` 增加 mode:`'draft' | 'save' | 'saveAndArrange' | 'rearrange'`
- `draft`:只校验归属公司 + 创建日期;`saveMode: 'draft'`;成功「暂存成功」
- `save`:全量校验;`saveMode: 'formal'`
- 安排类:全量校验 + 现有安排链路(不传 draft)
### 5.3 错误与成功提示
| 场景 | 行为 |
|---|---|
| 暂存缺归属公司/创建日期 | 高亮两项 + Message;不跑其它校验 |
| 非法状态暂存 | 后端 400 |
| 正式保存/安排失败 | 与现网一致,状态不变 |
| 暂存成功 | 关弹窗、刷新列表 |
## 6. 主要改动面
| 层 | 路径 |
|---|---|
| 展示常量 | `web-admin/src/utils/pl-display.ts` |
| 列表页 | `web-admin/src/views/pl/plan/index.vue` |
| 表单弹窗 | `web-admin/src/components/business/pl-plan-form-dialog/index.vue` |
| API 类型 | `web-admin/src/api/pl/index.ts`(`saveMode`) |
| Schema | `backend/app/schemas/pl/plan.py` |
| 创建/更新 | `backend/app/api/pl/plan.py` |
| 校验辅助 | `backend/app/services/pl_plan_service.py`(按需拆 `validate_draft_min_fields`) |
| 强制改状态等 | 同 `plan.py` 白名单与 wait-notice / delete |
危化品证等其它列表若复用 `PL_PLAN_FOLLOW_STATUS_OPTIONS` / 默认筛选,一并带上 `drafting`(与「默认可见」决策一致)。
## 7. 验收用例
1. 新建仅填归属公司 + 创建日期 → 暂存 → 列表「草稿中」,出现在「待安排/草稿」Tab
2. 编辑草稿 → 正式保存 → 「待安排」
3. 编辑待安排 → 暂存 → 「草稿中」
4. 已安排打开编辑 → 无【暂存】
5. 「待安排/草稿」Tab 默认同时看到两类;多选可再筛
6. 草稿可点等通知/安排:失败提示校验;成功离开草稿态
7. 草稿可删除(未安排、未归档)
## 8. 非目标
- 不改归档暂存(`archive_status`)语义与「归档草稿」接口
- 不做本地未落库草稿(必须写库)
- 不为此单独做新页面/新菜单
- 不强制迁移历史数据中的旧 `draft` 跟进值(若存在,展示兼容可保留,与新 `drafting` 并存)
## 9. 风险
- create-full / update 的 draft 分支若跳过装送货校验过松,需保证 DB 可空字段与前端再次打开不崩
- 列表「与待安排相同」会扩大草稿可触发的下游动作,依赖动作内全量校验守门
- Tab `name` 仍为 `pending_arrange`,文档与代码注释需标明「含草稿」以免后续误改回单状态过滤