Files
zkxw/docs/superpowers/plans/2026-07-15-oa-return-copy-new-instance.md
T
zlwuandCursor c9711d0dce feat(oa): terminate on return and copy form to start a new instance
Align with DingTalk: returned/rejected/cancelled are terminal; progress
shows return on the approver task only; done list includes returned;
deprecate same-instance resubmit and source-instance linking.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-15 15:19:20 +08:00

3.9 KiB
Raw Blame History

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: 引擎侧修正 list_tasks/build_progress_items,废弃同实例 resubmit 与 source_instance_id 业务写入;前端统一「复制并重新发起」走 copyFromInstanceId 预填后 start。

Tech Stack: FastAPI / SQLAlchemy / Vue 3 / Element Plus;单测 backend/tests/test_oa_engine.py

Spec: docs/superpowers/specs/2026-07-15-oa-return-copy-new-instance-design.md


Task 1: 后端 — done 含 returned;progress 去重复打回节点;returned 终态收尾

Files:

  • Modify: backend/app/services/oa_engine.py (list_tasks, build_progress_items, return_task 注释)

  • Modify: backend/tests/test_oa_engine.py

  • Step 1: list_tasks 的 kind=="done" 改为 status.in_(("approved", "rejected", "returned"))

  • Step 2: build_progress_items:删除对 returns_by_round / kind=return 的追加;在终态分支增加 returned → _terminal_item("returned", "已打回", inst);轮次循环可保留字段但前端不再标「第 N 轮」(引擎仍可只投当前已有任务)

  • Step 3: 单测:

    • test_done_list_includes_returned:任务 status=returned 出现在 done
    • test_progress_return_no_duplicate_return_kind:task returned + return event 时 progress 无 kind==return,仅有 task.status=returned,且有 terminal returned
    • 删除或改写 test_resubmit_starts_new_round 为 test_resubmit_raises_deprecated
  • Step 4: pytest backend/tests/test_oa_engine.py -q 通过后 commit

Task 2: 后端 — 废弃 resubmit;start 不再写关联;详情不回显关联

Files:

  • Modify: backend/app/services/oa_engine.py (start_instance, get_instance_detail, resubmit_instance)

  • Modify: backend/app/api/oa_approval.py(resubmit 路由返回 410/业务错误或保留但引擎抛错)

  • Step 1: resubmit_instance 改为直接 raise OaEngineError("同实例再次提交已废弃,请复制表单重新发起")

  • Step 2: start_instance 不再将 source_instance_id 写入实例(参数可忽略)

  • Step 3: get_instance_detail 不再查/返回有意义的 resubmittedInstanceId 关联跳转(置空);sourceInstanceId 恒返回空字符串(兼容前端字段)

  • Step 4: 更新测试 + commit

Task 3: 前端 — 详情/列表/发起页

Files:

  • Modify: web-admin/src/views/oa-approval/instances/detail.vue

  • Modify: web-admin/src/views/oa-approval/_placeholder/RuntimeList.vue

  • Modify: web-admin/src/views/oa-approval/start/index.vue

  • Modify: web-admin/src/api/oaApproval.ts(可选保留 fetchResubmit 不再使用)

  • Step 1: 详情:returned 文案「已打回」;三种终态显示「复制并重新发起」→ start?appId=&copyFromInstanceId=;去掉同单 resubmit、原单/重提单提示、轮次标题、kind===return 标签

  • Step 2: RuntimeList:mine 在 returned|cancelled|rejected 显示同一按钮;文案「已打回」;query 用 copyFromInstanceId

  • Step 3: start:读 copyFromInstanceId 预填 formData;submit 不传 sourceInstanceId

  • Step 4: commit

Task 4: 验收勾选 + 图谱

  • 勾选 spec §7 验收项(实现完成项)
  • ./scripts/update-graph.sh backend(若改了 backend)
  • commit docs if needed

Self-review: Spec §3–§7 均有对应 Task;无 TBD;copyFromInstanceId 命名前后一致。