1. 页面概览
1.1 是什么
「工作流」是 LightFoundry 的协作与工作流编排页面(对应设计文档 TAD-10,源码 action/web/src/views/WorkflowPage.vue)。它把「审批、数据处理、通知」等环节编排成一张 DAG(有向无环图),支持创建/校验/发布/启动工作流、查看实例历史与详情、处理个人待办(通过/拒绝)、在实例上评论互动、接收站内通知。页面顶部注释块概括了五大能力:
- 工作流列表 + 创建(nodes/edges 以 JSON 编辑)+ 校验/发布/启动;
- 实例历史与详情(任务状态/审批);
- 我的待办(approve/reject/reassign);
- 评论(按 target_type+target_id 列出/发表/删除);
- 通知(列表 + 标已读)。
后端引擎采用单进程同步轮询模型(MVP):实例启动或人工任务审批后,引擎反复计算「哪些节点的所有入边来源节点已完成」,对这些节点按类型执行(auto_task 调本体 Action / script_task 执行脚本 / gateway 条件分支 / human_task 创建人工任务并通知),重复直至到达 end 或无可执行节点。也就是说,前端负责编辑与发起,真正的推进逻辑在服务端。
1.2 核心价值
| 维度 | 说明 |
| 可视化流程定义 | 以 nodes(节点)+ edges(边)JSON 声明流程,前后端统一语义 |
| 七类节点 | start / human_task / auto_task / script_task / gateway / wait / end 各司其职 |
| 条件分支 | gateway 节点按边条件(如 {{amount}} > 1000)选择唯一分支 |
| 人工审批 | human_task 创建任务并暂停实例,指定用户或角色分配,通过/拒绝驱动推进 |
| 实例可追溯 | 每个启动为一条实例记录,历史/详情/任务/输出全量可见 |
| 协作与通知 | 评论(@提及)与站内通知闭环,待办一键处理 |
1.3 一句话总结
用节点+边的 JSON 定义一条 DAG 流程,校验、发布、启动;引擎沿图推进,人工节点暂停等待审批,直到走到 end。
2. 访问入口
2.1 路由与菜单
- 路由:
/foundry/workflows
- 路由名称:
FoundryWorkflows
- 菜单位置:Foundry 左侧边栏「工作流」(
FoundryLayout.vue 菜单项,位于「应用构建」之后)
- 源码文件:
action/web/src/views/WorkflowPage.vue
- 路由注册:
action/web/src/router/index.js,meta: { title: '工作流', requiresAuth: true }
2.2 认证与权限
- 需要登录:是(路由
meta.requiresAuth = true)
- 登录方式:AIP 统一登录;
localStorage.aip_token 自动写入 Bearer Token
- 页面读取
currentUser(localStorage.aip_username 或 aip_user_id),用于识别「我的待办」与「我的评论可删除」
- 审批权限:
approve/reject 必须是被分配人(后端 checkTaskHandler 校验),否则返回 403 语义错误「任务 x 仅限被分配人 xxx 处理」
- 401 排错:token 缺失/过期被跳转
/login,重新登录即可
2.3 端口与 API 前缀
- 后端端口:18081(Foundry)
- 前端 API 客户端:
action/web/src/api/client.js,baseURL = '/api/v1',超时 30 秒
- 本页接口覆盖
/workflows、/tasks、/comments、/notifications 四组路径
3. 界面布局
页面是单屏纵向布局,从上到下依次是:页面头(标题 + 刷新待办/新建工作流)、操作提示、创建/编辑表单(折叠)、工作流列表、实例历史(选中工作流后出现)、实例详情(含评论)、我的待办、通知。
┌─────────────────────────────────────────────────────────────────────┐
│ 协作与工作流 [刷新待办] [新建工作流/收起]│
├─────────────────────────────────────────────────────────────────────┤
│ [操作结果提示 alert(可关闭)] │
│ ┌ 卡片: 创建/编辑表单(showForm 时显示)──────────────────────────┐ │
│ │ 名称* | 显示名 | 分类 / 描述 │ │
│ │ 节点(JSON 数组 textarea)+ 边(JSON 数组 textarea) │ │
│ │ [保存] [取消] │ │
│ ┌ 卡片: 工作流列表表格 ─────────────────────────────────────────┐ │
│ │ ID | 名称 | 显示名 | 分类 | 状态 | 版本 | 操作 │ │
│ │ 操作: 启动/校验/发布/编辑/实例/删除 │ │
│ ┌ 卡片: 实例历史(selectedWorkflow 时显示)──────────────────────┐ │
│ │ ID | 状态 | 触发人 | 输入 | 输出 | 开始 | 结束 | 操作(详情/取消)│ │
│ ┌ 卡片: 实例详情(instanceDetail 时显示)────────────────────────┐ │
│ │ 任务表格: 任务ID/类型/状态/分配人/意见/截止 │ │
│ │ 评论子块: 评论列表 + 发表输入框 + [发表] │ │
│ ┌ 卡片: 我的待办 ──────────────────────────────────────────────┐ │
│ │ 任务ID | 类型 | 状态 | 实例 | 意见 | 操作(意见输入+通过/拒绝) │ │
│ ┌ 卡片: 通知 ──────────────────────────────────────────────────┐ │
│ │ [全部标为已读] 通知项: 已读/未读 | 标题 | 时间 | 内容 | [标为已读]│ │
└─────────────────────────────────────────────────────────────────────┘
| 板块 | 职责 |
| 页面头 | 「刷新待办」重拉我的待办;「新建工作流/收起表单」切换编辑表单 |
| 创建/编辑表单 | 填基础信息 + 以 JSON 编辑 nodes/edges,保存创建或更新 |
| 工作流列表 | 全部工作流定义,行内启动/校验/发布/编辑/实例/删除 |
| 实例历史 | 选中工作流的运行实例,含输入/输出快照,running 可取消 |
| 实例详情 | 实例任务状态表 + 针对该实例的评论协作 |
| 我的待办 | 分配给当前用户的待处理任务,可填意见后通过/拒绝 |
| 通知 | 站内通知(任务分配/提及/完成),单条或全部标已读 |
4. 交互元素详解
4.1 页面级元素
| 元素 | 含义 | 操作效果 | 后端调用 |
| 「刷新待办」 | 手动重拉我的待办 | loadTasks() | GET /api/v1/tasks/my |
| 「新建工作流」/「收起表单」 | 展开/收起创建表单 | showCreate 预填 start→human_task→end 示例 JSON 后切换 showForm | 无 |
| 「关闭」(alert 内) | 清除提示 | 清空 alert.message | 无 |
新建表单的默认示例(nodes/edges JSON,逐字):
// nodes
[
{ "key": "s", "type": "start", "label": "开始" },
{ "key": "h", "type": "human_task", "label": "审批", "config": { "assignee_user": "" } },
{ "key": "e", "type": "end", "label": "结束" }
]
// edges
[
{ "source_node_id": "s", "target_node_id": "h" },
{ "source_node_id": "h", "target_node_id": "e" }
]
节点字段:key(创建时边引用)、type(start/human_task/auto_task/script_task/gateway/wait/end)、label、config。人工任务配置 {"assignee_user":"用户ID"} 或 {"assignee_role":"角色名"};自动任务配置 {"action":"动作名","object_type_id":1,"params":{}}。边字段:source_node_id、target_node_id(创建时引用节点 key)、condition(gateway 分支条件,如 {{amount}} > 1000,空串为默认分支)。
4.2 创建/编辑工作流表单
| 元素 | 含义 | 必填 | 编辑态 | 操作效果 | 后端调用 |
| 「名称(api_name)*」 | 工作流唯一标识 | 是 | 禁用不可改(编辑态) | 创建时提交 | name |
| 「显示名」 | 展示名,如「订单审批流」 | 否 | 可改 | - | display_name |
| 「分类」 | 审批 / 数据操作 等 | 否 | 可改 | - | category |
| 「描述」 | 流程用途说明 | 否 | 可改 | - | description |
| 「节点(JSON 数组)」textarea | nodes JSON | 是 | 可改 | 保存时 parseJson 校验必须为数组 | nodes |
| 「边(JSON 数组)」textarea | edges JSON | 是 | 可改 | 同上 | edges |
| 按钮「保存」 | 提交 | - | - | 创建 POST /workflows;编辑 PUT /workflows/:id(仅草稿可编辑) | 见左 |
| 按钮「取消」 | 收起表单 | - | - | closeForm() | 无 |
「编辑」打开表单后自动 loadDefinition(id):GET /workflows/:id,把后端返回的节点/边映射成前端可编辑 JSON(节点含 id、key、type、label、config;边含 source_node_id、target_node_id、condition)。
4.3 工作流列表表格
| 列 | 显示 |
| ID | w.id |
| 名称 | 粗体 w.name |
| 显示名 | display_name,无则 - |
| 分类 | category,无则 - |
| 状态 | 徽标(statusLabel:draft=草稿/active=已发布/paused=暂停/deprecated=停用;statusClass 着色) |
| 版本 | v{{w.version}} |
| 操作 | 「启动」「校验」「发布」(active 时禁用)「编辑」「实例」「删除」 |
| 按钮 | 操作效果 | 后端调用 |
| 「启动」 | prompt 输入 JSON(如 {"amount":2000},默认 {"amount":100})作为输入,空则 {};成功后自动打开实例详情 + 刷新待办/通知 | POST /workflows/:id/start |
| 「校验」 | 后端校验 DAG,通过提示「工作流 #id 校验通过」,失败提示「校验失败: <errors 逗号拼接>」 | POST /workflows/:id/validate |
| 「发布」 | 版本自增并置 active,提示「工作流 #id 已发布(v{version})」;active 时按钮禁用 | POST /workflows/:id/publish |
| 「编辑」 | 打开表单并加载定义 | GET /workflows/:id |
| 「实例」 | 打开实例历史面板 | GET /workflows/:id/instances |
| 「删除」 | confirm 后删除定义(实例历史保留) | DELETE /workflows/:id |
4.4 实例历史与详情
实例历史列:ID、状态(running=运行中/completed=已完成/cancelled=已取消/failed=失败)、触发人、输入(截断 JSON)、输出(截断 JSON)、开始、结束、操作(「详情」+ running 时「取消」)。
| 按钮 | 操作效果 | 后端调用 |
| 「详情」 | 打开实例详情(任务表 + 评论) | GET /workflows/:id/instances/:instanceId |
| 「取消」 | 取消运行中实例(未完成任务置 skipped) | POST /workflows/:id/instances/:instanceId/cancel |
实例详情:任务表列 任务ID/类型/状态/分配人/意见/截止;下方「评论(target: workflow_instance #id)」子块:评论列表(用户/时间/内容,自己的可「删除」)+ 输入框「发表评论(@用户名 可提及)」+「发表」按钮。
| 元素 | 操作效果 | 后端调用 |
| 「删除」(评论) | 仅 cm.user_id === currentUser 显示 | DELETE /comments/:id |
| 「发表」/回车 | 内容非空即发表 | POST /comments |
| 评论输入框 | Enter 触发发表(@keyup.enter) | - |
4.5 我的待办
| 列/元素 | 显示/操作 |
| 任务ID / 类型 / 状态 / 实例 / 意见 | 待办任务字段(实例为 workflow_instance_id) |
| 「意见」输入框 | 每行一个,审批时提交 comment |
| 「通过」按钮 | 任务状态为 assigned/pending/in_progress 时可用 | POST /tasks/:id/approve,body {comment} |
| 「拒绝」按钮 | prompt 输入原因(非空)后提交 | POST /tasks/:id/reject,body {comment} |
| 「刷新待办」/审批后 | 自动重拉待办并刷新当前实例详情 | GET /tasks/my |
4.6 通知
| 元素 | 操作效果 | 后端调用 |
| 「全部标为已读」 | 我的全部通知置已读 | POST /notifications/read-all |
| 「标为已读」 | 单条通知置已读 | POST /notifications/:id/read |
| 通知项 | 已读/未读徽标 + 标题 + 时间 + 内容 | - |
5. 后端关联
5.1 API 客户端
页面使用 action/web/src/api/client.js:baseURL '/api/v1'、超时 30 秒、请求自动带 Bearer token、401 清 token 跳登录。
5.2 端点表
| 方法 | 路径 | 请求体 | 成功响应 | 备注 |
| GET | /workflows | - | {data:[...]} | 工作流列表 |
| POST | /workflows | name/display_name/description/category/nodes/edges | 201 {data:{id}} | 创建草稿 v1 |
| GET | /workflows/:id | - | {data:{...,nodes,edges}} | 完整定义 |
| PUT | /workflows/:id | 同创建(无 name) | {data:{id}} | 仅草稿可编辑 |
| DELETE | /workflows/:id | - | {data:{deleted:true}} | 级联节点/边 |
| POST | /workflows/:id/validate | - | {data:{valid:bool,errors:[...]}} | DAG 校验 |
| POST | /workflows/:id/publish | - | {data:{id,version,status:"active"}} | 版本自增 + active |
| POST | /workflows/:id/start | 可选 {input:{...}}(空 body 也可) | {data:{instance}} | 启动实例 |
| GET | /workflows/:id/instances | - | {data:[...]} | 实例历史 |
| GET | /workflows/:id/instances/:instanceId | - | {data:{instance,tasks}} | 实例详情 |
| POST | /workflows/:id/instances/:instanceId/cancel | - | {data:{id,status:"cancelled"}} | 取消实例 |
| GET | /tasks/my | - | {data:[...]} | 我的待办 |
| GET | /tasks/:taskId | - | {data:{...}} | 任务详情 |
| POST | /tasks/:taskId/approve | {comment} | {data:{id,status:"completed"}} | 通过 |
| POST | /tasks/:taskId/reject | {comment} | {data:{id,status:"rejected"}} | 拒绝 |
| POST | /tasks/:taskId/reassign | {new_assignee_id} | {data:{id,assignee_id}} | 转交(前端无 UI,API 存在) |
| GET | /comments | query target_type+target_id(必填) | {data:[...]} | 评论列表 |
| POST | /comments | {target_type,target_id,content} | 201 {data:{id}} | 发表评论 |
| DELETE | /comments/:id | - | {data:{deleted:true}} | 删除自己的评论 |
| GET | /notifications | - | {data:[...]} | 我的通知 |
| POST | /notifications/read-all | - | {data:{marked:true}} | 全部已读 |
| POST | /notifications/:id/read | - | {data:{id,is_read:true}} | 单条已读 |
5.3 响应结构
实例详情示例(GET /workflows/:id/instances/:instanceId):
{
"data": {
"instance": {
"id": 5,
"workflow_id": 1,
"workflow_version": 2,
"status": "running",
"trigger_type": "manual",
"trigger_user": "zhangsan",
"input_data": {"amount": 2000},
"output_data": null,
"runtime_context": {"amount": 2000},
"executed_nodes": ["s"],
"started_at": "...",
"ended_at": null
},
"tasks": [
{
"id": 7,
"workflow_instance_id": 5,
"node_id": "h",
"type": "human_task",
"status": "assigned",
"assignee_id": "lisi",
"input_data": {"amount": 2000},
"comment": "",
"due_at": null
}
]
}
}
5.4 关联模块表
| 后端包/文件 | 职责 |
action/products/foundry/workflow/models.go | 七张表:workflows / workflow_nodes / workflow_edges / workflow_instances / task_instances / comments / notifications;状态常量 |
action/products/foundry/workflow/service.go | WorkflowService + engine(token 模型推进、快照/恢复) |
action/products/foundry/workflow/validate.go | ValidateDAG:节点类型/单 start/end/出边约束/环检测/可达性 |
action/products/foundry/workflow/expression.go | 条件表达式求值与 {{var}} 模板解析 |
action/products/foundry/server/workflow_handlers.go | HTTP handler + RegisterWorkflowRoutes + executorActionRunner |
action/products/foundry/writepath | 本体 Action 写路径执行器(auto_task 真实执行时注入) |
5.5 关键机制
- 节点类型(
NodeType*):start(入口,唯一)、end(终点,唯一)、human_task(人工任务,创建后暂停)、auto_task(调本体 Action,未注入 runner 时模拟执行 {"simulated":true,...})、script_task(script_type=set_var 设变量 / js 预留 / 未知类型记录不阻断)、gateway(条件分支,选首个匹配出边)、wait(MVP 立即通过)。
- 执行模型:单进程同步轮询。引擎持有
frontier(前沿队列)、completed(已执行集合)、vars(上下文变量)。advance() 循环弹出节点执行,直到 end(done=true)或遇到 human_task(done=false 暂停)或无可执行节点。单实例执行步数上限 10000(防死循环)。
- 审批推进:
approve 任务置 completed 并把 {decision:"approved",comment,handler} 写入上下文 → resumeInstance 重建引擎、恢复 runtime_context/executed_nodes 快照、从被审批节点继续推进(避免 start→human_task 之间节点重复执行,BUG-1 修复);reject 任务置 rejected、实例置 failed(拒绝即流程终止,MVP 语义)。
- Gateway 求值:对节点出边逐条
EvalCondition(如 {{amount}} > 1000),首个为 true 的边作为分支;全部不命中报「无匹配条件分支」;空条件视为默认分支。
- 变量引用:
{{var}} 支持点路径(如 {{approval.decision}}),从 vars(input + 各节点输出)解析;ResolveTemplatesDeep 在 auto_task 的 params 上做模板替换。
- 分配语义:human_task 配置
assignee_user(直接指定)或 assignee_role(查 user_roles 关联 roles,取首个用户,无用户报错);支持 due_in_hours 设截止时间。
- 通知:任务分配、评论 @提及、工作流结束自动发站内通知(best-effort)。
- 触发方式:
trigger_type 常量 manual/schedule/event;当前页面仅 manual(启动按钮);schedule/event 为预留。
6. 核心流程详解
6.1 主流程一:创建并发布工作流
- 点「新建工作流」→ 表单预填 start → human_task → end 示例 JSON。
- 填「名称(api_name)」与基础信息;编辑 nodes/edges JSON。
- 点「保存」→
POST /workflows(草稿,version=1)→ 提示「工作流已创建(id=xxx)」。
- 在列表点「校验」→ 后端
ValidateDAG 检查(唯一 start/end、类型合法、出边约束、拓扑环检测、可达 end);通过则提示「校验通过」。
- 点「发布」→ 校验后版本自增并置 active → 列表状态徽标变「已发布」。
6.2 主流程二:启动并推进实例
- 列表点「启动」→
prompt 填 JSON 输入(如 {"amount":2000})。
- 引擎从 start 沿 DAG 推进:auto_task/script_task/gateway/wait 立即执行;
- 遇 human_task:创建任务(assigned)+ 发通知,实例保持 running 暂停;
- 遇 end:实例置 completed,
output_data 写最终 vars,通知发起人。
- 被分配人登录后在「我的待办」看到任务,填意见后「通过」→ 实例继续推进;或「拒绝」→ 实例置 failed。
- 多级审批链:每个 human_task 通过后引擎从该节点继续,可再次暂停到下一个 human_task(快照恢复语义)。
- 实例详情面板可随时查看任务状态、评论;running 中的实例可「取消」(未完成任务置 skipped)。
6.3 主流程三:审批(approve/reject)语义
- 「通过」:校验必须是被分配人 → 任务 completed,输出
{decision:"approved",comment,handler} 写入上下文 → resumeInstance 恢复引擎快照继续推进 → 若推进中出现新 human_task 则再次暂停,否则 completed。
- 「拒绝」:同样校验分配人 → 任务 rejected,
output_data 记 {decision:"rejected",...} → 实例直接 failed(MVP 语义:拒绝即流程终止),output_data 记错误原因。
6.4 主流程四:评论与通知
- 打开实例详情 → 评论区以
target_type=workflow_instance&target_id=<实例ID> 拉评论。
- 输入内容(
@用户名 可提及,命中用户会收 mentioned 通知)→「发表」或回车 → POST /comments。
- 自己的评论可「删除」(
cm.user_id === currentUser 才显示删除按钮)。
- 「通知」面板:任务分配/提及/工作流完成自动生成通知,单条或「全部标为已读」。
6.5 状态机 / 任务终态语义
工作流定义: draft(草稿) ──发布──▶ active(已发布) ──▶ paused(暂停) / deprecated(停用)
实例: running(运行中) ──到达end──▶ completed(已完成)
│ ├── 人工拒绝 ──▶ failed(失败)
│ └── 用户取消 ──▶ cancelled(已取消)
任务: pending(待分配) → assigned(待处理) → in_progress(处理中)
│ ├── approve ──▶ completed(已完成)
│ └── reject ──▶ rejected(已拒绝)
└── 实例取消/流程结束未执行 ──▶ skipped(已跳过)
7. 权限与安全
- 认证:全部接口走
/api/v1 protected 组,JWT 必需。
- 审批人校验:approve/reject 后端强制「仅限被分配人处理」(
checkTaskHandler);评论删除仅限作者本人;通知标已读仅本人通知。
- 分配角色:
assignee_role 通过 user_roles/roles 关联表解析,角色下无用户时任务创建报错(防悬空任务)。
- 表达式安全:gateway 条件与
set_var 使用内置表达式求值器,非任意代码执行;auto_task 的 Action 执行走 writepath 写路径安全流水线(Mode: writepath.ModeRun),未注入 executor 时仅模拟执行。
- 写操作防护:删除工作流/删除评论/取消实例均有
confirm;「保存」「启动」等操作由 busy 禁用防重复。
- 幂等执行:auto_task 以
wf-<instanceID>-<nodeID> 作为 IdempotencyKey 调本体 Action,防重复写。
- 启动前置条件:工作流必须 active 才可启动;DAG 校验失败禁止启动(后端双重校验)。
8. 常见问题与排错
8.1 启动报「工作流未发布」
- 现象:点「启动」提示
工作流 "xxx" 未发布(当前状态 draft),无法启动。
- 原因:工作流还是草稿,未发布;
StartWorkflow 要求 status === active。
- 排查:① 先点「校验」确认 DAG 合法;② 点「发布」使其变 active;③ 若发布也失败,读后端校验错误列表(
errors 逗号拼接)逐条修正 nodes/edges JSON。
8.2 「我的待办」看不到新任务
- 现象:启动后被分配人登录,「我的待办」为空。
- 原因:① 当前登录用户不是任务的
assignee_id(配置了 assignee_user 指定他人,或 assignee_role 解析到别人);② 未点「刷新待办」(列表只在进入页面/刷新待办/启动后刷新)。
- 排查:① 在实例详情任务表中查看「分配人」列;② 用该用户重新登录;③ 点页面头「刷新待办」;④ 若
assignee_role 且角色下多用户,后端取首个用户,确认被分配人。
8.3 保存时报「nodes 格式错误」或「edges 格式错误」
- 现象:点「保存」提示
nodes 格式错误: ... / edges 格式错误: ...。
- 原因:textarea 内容不是合法 JSON 数组(漏逗号/多余逗号/花括号不配对),
parseJson 强制要求 JSON 数组。
- 排查:① 用
JSON.stringify 思路检查语法;② 编辑态从 GET /workflows/:id 回填的 JSON 直接改字段,勿手敲整体;③ 确保 nodes 数组每项含 key/type/label(config 可选),edges 数组每项含 source_node_id/target_node_id(condition 可选)。
8.4 实例卡在 running 且任务无人处理
- 现象:实例状态 running,任务 assigned 但一直没推进。
- 原因:human_task 正在等待被分配人审批,这是正常暂停态;或分配人被分配错了。
- 排查:① 确认该任务出现在某个用户的「我的待办」;② 可在实例详情「取消」实例(未完成任务置 skipped);③ 若分配角色错误导致悬空,需重新编辑定义(仅草稿可改,已发布需先确认边界)后重新启动。
8.5 审批报「任务 x 仅限被分配人 xxx 处理」
- 现象:登录用户点「通过」/「拒绝」返回 403 语义错误。
- 原因:
checkTaskHandler 强制要求处理人 = assignee_id,当前用户不是被分配人。
- 排查:① 确认是否用被分配人账号登录;② 该任务可能已被转交(reassign)或已处理;③ 需要转交时用后端
POST /tasks/:taskId/reassign(前端无 UI,可用 curl 调)。
9. 已知缺陷与边界
| 项目 | 说明 |
| 前端无图编辑器 | 节点/边以 JSON textarea 编辑,无拖拽画布(表单提示字段语义) |
| 同步轮询引擎 | 单进程同步推进,无异步任务队列/定时调度;大型流程同步阻塞 |
| schedule/event 触发 | trigger_type 常量预留 manual/schedule/event,当前页面仅 manual |
| 拒绝即终止 | reject 使实例 failed(MVP 语义),无「退回上一步/重试」能力 |
| wait 节点 | MVP 立即通过,无真实等待/延时实现 |
| script_task js | script_type=js 预留,未实现沙箱执行;set_var 是唯一真实脚本能力 |
| auto_task 模拟 | 未注入 executorActionRunner 时返回 {"simulated":true,...},非真实写 |
| 分配角色取首用户 | assignee_role 解析时按 user_id 排序取第一个,不支持轮询分配 |
| 通知无分页 | 通知/实例/评论列表均一次拉全量 |
| 发布不可撤销 | 发布后版本自增,无「回退到上一版本」UI(需重新编辑草稿再发新版本) |
注:待办无转交入口已于 2026-09-06 修复(待办行新增「转交」按钮,输入目标用户 ID 后调 POST /tasks/:id/reassign)。