工作流引擎设计文档
工作流引擎设计文档
1. 架构总览
工作流引擎采用"定义—实例—任务—记录"四层数据模型,流转逻辑集中在 WfEngineService。
┌──────────────────────────────────────────────────────────────────┐
│ WfEngineService │
│ 公共入口: Start / Approve / Reject / Resubmit / Withdraw / │
│ Transfer / AddSign / Delegate / RemoveSign / Urge │
│ AdminTerminate / AdminSuspend / AdminResume / │
│ AdminReassign / AdminJump │
│ 私有辅助: RunInTx / Load* / PrepareStartFlow / ... │
│ 内部引擎: ArriveNode / AdvanceToNext / ResolveNextNode │
│ 审批人解析: ResolveApprovers / ResolveByUserIds / NotifyUserIds │
└──────────────────────────────────────────────────────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
WfFlowDefinition WfFlowInstance WfFlowTask WfFlowRecord
(静态结构) (一次申请) (待办/抄送) (操作轨迹)
│ │ │
▼ ▼ ▼
WfFlowNode WfFlowNode(运行时) WfNodeLink(连线/分支)
WfNodeLink
核心设计约定
- 连线(wf_node_link)是流程串联的唯一事实来源,
NodeOrder仅作展示排序与数据缺失兜底。前端须为每条边(含直线)生成一条WfNodeLink;直线ConditionJson留空。 - 审批人统一以 userId 落库:定义态存稳定标识(userId / 角色Id / 部门Id / 表单字段 key),运行态全部解析为
SysUser.UserId,显示名以快照(ApproverNames/AssigneeNickName/ApplyNickName)冗余存储,运行时不反查用户表。 - 所有公共流转方法均走事务(
RunInTx→UseTran),异常统一包装为CustomException。
2. 数据模型
2.1 流程定义 wf_flow_definition
| 字段 | 类型 | 说明 |
|---|---|---|
| FlowId | long (PK) | 主键,自增。每个版本一个独立 FlowId |
| FlowCode | string(64) | 流程编码,同流程多版本共享;严格唯一(新增独立流程必须走新编码) |
| Version | int | 版本号,同 FlowCode 下自增;历史版本冻结保留 |
| FlowName | string(100) | 流程名称 |
| Status | int | 0=停用 1=启用 |
| IsDraft | int | 0=已发布(正式版) 1=草稿(不可发起) |
| IsDelete | int | 软删除标记 0/1 |
| FormItems | text(JSON) | 表单字段定义数组 |
| DesignJson | text(JSON) | LogicFlow 完整设计数据(节点/连线/画布) |
唯一现行版本 = 同 FlowCode 下
Status=1 && IsDraft=0。IsCurrent为查询时计算的展示字段,非持久化列。
2.2 流程节点 wf_flow_node
| 字段 | 类型 | 说明 |
|---|---|---|
| NodeId | long (PK) | 主键 |
| FlowId | long | 所属流程 |
| NodeName | string(100) | 节点名称 |
| NodeType | int | 节点类型(见 §3) |
| ApproverType | int | 审批人类型(见 §4) |
| ApproverId | string(500) | 审批人标识(userId/角色Id/部门Id/表单字段 key,逗号分隔) |
| ApproverNames | string(500) | 审批人 userName 快照(选人时与 ApproverId 同步写入) |
| NodeOrder | int | 顺序(展示/兜底排序) |
| SignType | int | 0=或签 1=会签 2=Sequential 依次审批(顺序会签) 3=Percent 比例会签(达到 PassRatio 比例即通过) |
| PassRatio | decimal? | 比例会签通过比例(SignType=3 时生效,0~1,如 0.5=50%),默认 1(=100%,等同会签) |
| ConditionField | string(100) | 节点条件:表单字段 key |
| ConditionOp | int | 节点条件运算符(见 §5) |
| ConditionValue | string(100) | 节点条件比较值 |
| ParallelGroup | int | 并行分组号 >0 表示参与并行分支 |
| EnterWebhookId | long? | 节点进入事件 Webhook 端点(→ wf_webhook.Id) |
| LeaveWebhookId | long? | 节点离开事件 Webhook 端点 |
| EmptyApproverStrategy | int | 审批人解析为空时的兜底策略:0=自动通过 1=指定默认审批人 |
| DefaultApproverId | long? | 兜底策略=1 时指定的默认审批人 userId |
| DefaultApproverName | string | 兜底默认审批人姓名快照 |
| TimeoutHours | int | 节点超时时长(小时);0=不启用超时(默认) |
| TimeoutAction | int | 超时动作 WfTimeoutAction:0=不处理 1=自动通过 2=自动驳回 3=转交指定人 |
| TimeoutTransferUserId | long? | 超时动作=3 时的转交目标用户;为空则退化为自动通过 |
2.3 流程实例 wf_flow_instance
| 字段 | 类型 | 说明 |
|---|---|---|
| InstanceId | long (PK) | 主键 |
| FlowId | long | 绑定的流程定义(含版本,冻结各自 FormItems) |
| FlowName | string(100) | 流程名快照 |
| ApplyUser / ApplyUserId / ApplyNickName | — | 申请人登录名 / Id / 昵称快照 |
| Title | string(200) | 申请标题 |
| Status | int | 0=审批中 1=通过 2=驳回 3=撤回 |
| CurrentNodeId | long? | 当前节点 |
| FormContent | text(JSON) | 表单内容(字段→值,值全为字符串) |
| Attachment | string(1000) | 附件路径(逗号分隔) |
2.4 审批任务 wf_flow_task
| 字段 | 类型 | 说明 |
|---|---|---|
| TaskId | long (PK) | 主键 |
| InstanceId / NodeId | long | 关联实例 / 节点 |
| Assignee / AssigneeId / AssigneeNickName | — | 审批人登录名 / Id / 昵称 |
| Status | int | 0=待审(Pending) 1=已审(Done) 2=跳过(Skipped) 3=排队中(Waiting,依次审批未轮到) |
| Action | int? | 实际动作(1=通过 2=驳回) |
| TaskType | int | 0=审批 1=抄送(区分待办与抄送知会) |
| IsRead | bool | 待办已读标记 |
| DelegateId / DelegateName | long? / string | 委托代审:任务仍归属 Assignee,仅记录代审人;代审人凭 DelegateId 可见并代审 |
| Opinion / HandleTime | — | 审批意见 / 处理时间 |
2.5 审批记录 wf_flow_record
| 字段 | 类型 | 说明 |
|---|---|---|
| RecordId | long (PK) | 主键 |
| InstanceId / NodeId / TaskId | long? | 关联实例/节点/任务 |
| Operator / OperatorId / OperatorNickName | — | 操作人(登录名/Id/昵称) |
| Action | int | 0=提交 1=通过 2=驳回 3=转办 4=撤回 5=加签 6=重提 7=抄送 |
| Opinion | string(500) | 意见 |
| IsRead | bool | 抄送已读标记 |
| AiSummary | text? | AI 自动生成的审批摘要(仅 Action=0 系统生成记录落此字段;人工记录为空) |
2.6 节点连线 wf_node_link
流程串联唯一事实来源。
| 字段 | 类型 | 说明 |
|---|---|---|
| Id | long (PK) | 主键 |
| FlowId | long | 所属流程 |
| SourceNodeId | long | 源节点 |
| TargetNodeId | long | 目标节点 |
| ConditionJson | text(JSON) | 分支条件,空=默认分支 |
| Sort | int | 同一源节点出边评估顺序(小优先) |
2.7 其他表
wf_flow_comment:审批评论/批注(独立动作,不推进流程)wf_form_template:可复用表单模板(与流程定义为拷贝语义)wf_webhook:Webhook 端点配置(Name/Url/Enabled/Secret),节点经WfFlowNode.EnterWebhookId/LeaveWebhookId引用wf_webhook_delivery:Webhook 投递 Outbox 记录(EventId/Payload/RetryCount/Status,失败超限转 Dead 死信)
3. 节点类型(WfNodeType)
| 值 | 名称 | 引擎行为 |
|---|---|---|
| 0 | Start 开始 | 隐式,不在 dto.Nodes |
| 1 | Audit 审批 | 生成待办,IsNodeComplete 判定完成 |
| 2 | Cc 抄送 | 生成抄送任务+记录,不阻塞,立即流转 |
| 3 | End 结束 | 隐式终点,允许无出边 |
| 4 | Condition 条件网关 | 自身不生成任务,到达后按出边 ConditionJson 选一路继续 |
| 7 | ParallelFork 并行分叉 | 真实节点,到达后 fork 全部出边目标,各自独立推进 |
| 8 | ParallelJoin 并行汇聚 | 真实节点,所有入边分支(真实业务节点审批/抄送)完成才继续 |
条件网关约束:
ParallelGroup必须=0(不进并行分组);须 ≥2 条有效出边且至少 1 条带条件,否则ValidateLinks抛错。条件网关可作流程首节点(顶部透传)。 并行网关:采用双真实节点(7 分叉 + 8 汇聚)+CurrentNodeIds活动节点集模型。fork 时对每个成员AddActiveNodeId再SyncActiveNodeId;join 前整组IsNodeComplete才汇聚。
4. 审批人解析(WfApproverType)
ResolveApprovers(WfFlowNode, formValues) 统一返回 (UserId, UserName, NickName):
| 值 | 类型 | ApproverId 含义 | 解析方式 |
|---|---|---|---|
| 0 | User 指定用户 | userId 逗号分隔 | 直接查 SysUser.UserId |
| 1 | Role 角色 | 角色Id 逗号分隔 | JOIN SysUserRole 取角色下用户 |
| 2 | Dept 部门 | 部门Id 逗号分隔 | 取该部门下 Status=0 用户 |
| 3 | Field 表单字段 | 表单字段 key,值为 userId 逗号串 | 从 FormContent 读 userId 查用户 |
| 4 | DeptLeader 部门负责人 | 部门Id 逗号分隔 | 解析该部门 LeaderIds 对应 SysUser |
| 5 | ApplyLeader 发起人主管 | approverId 恒空 | 运行时取发起人 SysUser.LeaderId |
空审批人兜底策略(WfFlowNode.EmptyApproverStrategy):当上述来源最终解析为空时:
0自动通过:节点 AutoSkip,留痕WfAction.AutoSkip=8,reason="审批人为空,节点自动跳过"。1指定默认审批人:DefaultApproverId/DefaultApproverName姓名快照兜底。
⚠️ 表单里的
user类型字段(如"同行人")存 nickName 串,仅供展示,不可配置为 Field 节点审批人(引擎 Field 分支只认 userId)。
5. 条件与比较(WfConditionOp)
节点条件(ConditionField/Op/Value)与连线条件(WfLinkCondition)共用 CompareValue 比较语义:
| Op 值 | 运算符 | 说明 |
|---|---|---|
| 0 | None | 无条件(节点必经) |
| 1 | Lt 小于 | 两端可解析为 double 则数值比较,否则 Ordinal 字符串 |
| 2 | Le 小于等于 | 同上 |
| 3 | Gt 大于 | 同上 |
| 4 | Ge 大于等于 | 同上 |
| 5 | Eq 等于 | 始终按字符串 OrdinalIgnoreCase 比较 |
| 6 | Ne 不等于 | 始终按字符串 OrdinalIgnoreCase 比较 |
连线条件 JSON 结构(WfLinkCondition,字段 lowercase):
{ "field": "amount", "op": 3, "value": "10000" }
保守原则:字段/运算符/值任一缺失或解析失败 → 条件视为不满足。
多条件组合(AND / OR):一条连线可配置多个条件项,通过 LogicType 指定组合方式:
0= AND(与):所有条件项都满足才算满足;1= OR(或):任一条件项满足即满足。
项结构(WfLinkCondition 数组,Conditions 字段)示例:
{
"logicType": 0,
"conditions": [
{ "field": "amount", "op": 3, "value": "10000" },
{ "field": "category", "op": 5, "value": "差旅" }
]
}
旧版单条件结构(ConditionField/Op/Value + ConditionJson)仍兼容;新设计器统一走多条件数组。
5.1 表单字段权限(WfFieldPermission)
按节点配置表单字段的可见 / 可编辑范围,实现"不同审批人只看/改自己关心的字段",典型场景:财务节点只看金额、HR 节点可编辑入职信息。
| 字段 | 类型 | 说明 |
|---|---|---|
| FlowId | long | 关联流程定义 |
| NodeId | long | 关联节点(节点级生效,作用于该节点任务详情页) |
| PermissionType | int | 1=可见字段(白名单)/ 2=可编辑字段(白名单)/ 3=隐藏字段(黑名单) |
| FieldKeys | text | 受控字段名列表(逗号分隔,对应 FormItems.field) |
- 解析规则(优先级从高到低):隐藏(黑名单) 优先 → 可编辑白名单 → 不可见字段直接不渲染;若未配置任何权限,则全部字段默认可见 + 只读(发起节点默认可编辑)。
- 前端在节点任务详情渲染时调用
WfFlowInstanceService.GetFieldPermission(nodeId)取该节点权限,按规则过滤FormItems后展示。
5.1 动作枚举(WfAction,用于 wf_flow_record.Action)
| 值 | 动作 | 说明 |
|---|---|---|
| 0 | Submit 提交 | 发起申请 |
| 1 | Approve 通过 | 审批通过 |
| 2 | Reject 驳回 | 驳回至发起人 |
| 3 | Transfer 转办 | 节点不变换人 |
| 4 | Withdraw 撤回 | 申请人撤回 |
| 5 | AddSign 加签 | 追加审批人 |
| 6 | Resubmit 重新提交 | 驳回后重提 |
| 7 | Cc 抄送 | 抄送知会 |
| 8 | AutoSkip 自动跳过 | 审批人为空自动放行(reason 记录原因) |
| 9 | RemoveSign 减签 | 移除加签/会签待审批人 |
| 10 | Delegate 委托代审 | 任务仍归属原审批人,代审人凭 DelegateId 代审 |
| 11 | Suspend 挂起 | 管理员挂起 |
| 12 | Resume 恢复 | 管理员恢复 |
| 13 | Terminate 终止 | 管理员终止/作废 |
| 14 | Reassign 改派 | 管理员改派未完成任务 |
| 15 | Jump 跳转 | 管理员跳转节点 |
| 16 | Urge 催办 | 申请人催办(24h 同实例限一次) |
6. 流转引擎核心逻辑
6.1 公共入口
| 方法 | 说明 | 权限 |
|---|---|---|
Start(instance) | 发起申请,落库实例+记录,到达首节点 | workflow:instance:start |
Approve(taskId, opinion, operatorId) | 通过(或签一人即通过,会签需全通过,比例会签达 PassRatio 比例即通过,依次审批轮转下一位) | workflow:task:approve |
Reject(taskId, opinion, operatorId) | 驳回,实例置 Rejected | workflow:task:reject |
Resubmit(instanceId, formContent, attachment, title, userId) | 驳回后重提,回首节点 | workflow:instance:start |
Withdraw(instanceId, operatorId) | 撤回(仅申请人、当前节点未审批时) | workflow:instance:withdraw |
Transfer(taskId, targetUserId, opinion, operatorId) | 转办(节点不变) | workflow:task:transfer |
AddSign(taskId, userIds, opinion, operatorId) | 加签(追加审批人) | workflow:task:addsign |
Delegate(taskId, targetUserId, opinion, operatorId) | 委托代审(任务仍归属原审批人,仅记 DelegateId/Name) | workflow:task:delegate |
RemoveSign(taskId, targetUserId, opinion, operatorId) | 减签(移除当前节点某加签/会签待审批人,操作人须为该节点审批人之一) | workflow:task:removesign |
Urge(instanceId, operatorId) | 催办(仅申请人、仅审批中实例,24h 同实例限一次) | workflow:task:urge |
AdminTerminate(instanceId, operatorId) | 管理员终止/作废 | workflow:instance:terminate |
AdminSuspend(instanceId, operatorId) | 管理员挂起 | workflow:instance:suspend |
AdminResume(instanceId, operatorId) | 管理员恢复 | workflow:instance:resume |
AdminReassign(instanceId, nodeId, targetUserId, operatorId) | 管理员改派(未完成任务改派目标用户) | workflow:instance:reassign |
AdminJump(instanceId, targetNodeId, operatorId) | 管理员跳转节点(跳并行组内成员仅激活该节点 singleNodeOnly,其余分支置 Skipped,不卡死) | workflow:instance:jump |
身份约定:所有
operatorId/targetUserId/userIds均为 userId(稳定外键),不再使用 userName。 鉴权改为按 userId 比对:待办校验task.AssigneeId == operatorId,撤回/重提校验instance.ApplyUserId == operatorId。 通知、审批记录统一以 userId 落库(OperatorId/AssigneeId),显示名由ResolvedApprover携带的UserName/NickName快照呈现。
6.2 流转流程(ArriveNode / AdvanceToNext)
ArriveNode(node)
├─ Condition 网关 → ResolveNextNode 按出边条件选一路 → 递归
├─ 节点条件不满足(EvalCondition false) → 顺延下一节点
├─ ParallelGroup>0 → fork 组内所有节点(包容网关) → 等待 AdvanceToNext 汇聚
├─ Cc 抄送 → 生成抄送任务+记录 → 继续下一节点
└─ Audit 审批 → 生成待办并等待
AdvanceToNext(completedNode)
├─ 并行分组未全部完成(IsNodeComplete) → 等待
├─ 下一节点为空 → 实例置 Approved
└─ 存在下一节点 → ArriveNode(next)
6.3 下一节点解析(ResolveNextNode)
- 当前节点有出边(
linksBySource命中SourceNodeId):- 按
Sort升序遍历出边; - 命中条件分支(
EvalLinkCondition为 true)走该边; - 无任一命中且有默认分支(
ConditionJson空)走默认; - 仍无则流程结束(置 Approved)。
- 按
- 无出边:fallback 到
NodeOrder升序取下一审批/抄送节点(防卡死兜底)。
6.4 节点完成判定(IsNodeComplete)
- 抄送节点:无待办即完成(
Status=Skipped视为完成)。 - 审批节点(或签 Or):任一
Done即完成。 - 审批节点(会签 And):全部
Done才完成。 - 审批节点(依次审批 Sequential):当前处理人
Done即轮转下一位Waiting;全部轮转完毕才完成;任一驳回则整节点驳回。 - 审批节点(比例会签 Percent):全部审批人同时激活,通过人数达到
PassRatio比例(如 0.6=60%)即完成推进;未达比例前未审者继续等待。 - 节点完成后自动把同节点其余
Pending任务置Skipped,避免重复流转。
6.5 超时自动处理(Job_WfTimeoutAutoProcess)
- 配置:审批节点设
TimeoutHours>0时,引擎在生成待办时计算WfFlowTask.DeadlineTime = ArriveTime + TimeoutHours。 - 扫描:独立定时任务
Job_WfTimeoutAutoProcess(默认每 5 分钟、按租户展开)扫描Status=Pending且DeadlineTime < now的待办。 - 动作(
WfTimeoutAction):None(0)跳过 /AutoApprove(1)自动通过 /AutoReject(2)自动驳回 /Transfer(3)转交TimeoutTransferUserId(为空退化为自动通过)。 - 效果:执行后写审批记录(带超时语义)+ 通知,无需人工鉴权,不阻断主流程。
6.5 审批人完成后的跳过逻辑
或签场景下,某审批人通过后,同节点其余 Pending 任务被置为 Skipped,避免重复流转。
7. 版本与副本管理
WfFlowDefinitionService 提供:
| 操作 | 接口 | 行为 |
|---|---|---|
| 复制 Copy | POST workflow/definition/copy/{flowId} | 生成停用副本,编码 {code}_copy/_copy2,名称加 _副本 |
| 另存为新版本 | POST workflow/definition/saveAsNewVersion/{flowId} | FlowCode 不变,Version+1,草稿态 |
| 版本历史 | GET workflow/definition/versions?flowCode= | 按 Version 升序,标记 IsCurrent |
| 设为现行 | POST workflow/definition/setCurrent/{flowId} | 启用+发布目标,停用同 FlowCode 其他版本 |
| 发布草稿 | POST workflow/definition/publish/{flowId} | IsDraft 0→1 |
| 版本回滚 | POST workflow/definition/rollback/{flowId} | 历史版本复制为新的最高版本(草稿态) |
版本对比(按节点对齐比较类型 / 审批人 / 签类型 / 并行组,标色展示新增 / 移除 / 修改)为前端本地能力,后端不提供独立 diff 接口,前端基于两个版本的
GetInfo结果在内存中比对渲染。
新增/编辑时连带写节点与连线:InsertNodes 返回「客户端 NodeId → 新 NodeId」映射,InsertLinks 据此重映射 SourceNodeId/TargetNodeId。编辑采用「先删旧连线+旧节点,再按映射重建」。
⚠️ 前端临时 NodeId 必须用唯一负数(如自减),绝不能用 0(多节点互相覆盖导致连线重映射错乱)。有效出边判定口径允许负数临时 id(
!=0 && !=彼此)。
8. 已读功能
- 待办已读:
POST workflow/task/read(body{ ids }逗号串),限定当前用户防越权。 - 抄送已读:
POST workflow/record/read,同样限定当前用户。 - 未读角标:
GET workflow/task/unread、GET workflow/record/unread(数据面板红点)。 - 存量抄送记录回填:旧数据
Action=0且Opinion='抄送'需执行UPDATE wf_flow_record SET action=7 WHERE opinion='抄送'。
9. 表初始化与多租户
- 租户级表初始化器:
WorkflowTenantInitializer,InitCore注册 8 张表(definition/instance/node/task/record/comment/formTemplate/nodeLink)。 - 使用
DbMigrationService.EnsureEntitySchema:表不存在则建,已存在则补列(不删列/不改类型,幂等)。
10. API 接口清单
所有接口前缀 workflow,分组 workflow。JSON 默认 camelCase 序列化。
10.1 流程定义 workflow/definition
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | list | definition:list | 列表 |
| GET | {flowId} | common | 详情(含 Nodes/NodeLinks) |
| GET | nodes/{flowId} | definition:list | 节点列表 |
| POST | `` | definition:add | 新增(FlowCode 严格唯一) |
| PUT | `` | definition:edit | 修改 |
| POST | delete/{ids} | definition:delete | 删除(存在进行中实例则禁止) |
| POST | copy/{flowId} | definition:add | 复制 |
| POST | saveAsNewVersion/{flowId} | definition:add | 另存新版本 |
| GET | versions?flowCode= | definition:list | 版本历史 |
| POST | setCurrent/{flowId} | definition:edit | 设为现行 |
| POST | publish/{flowId} | definition:edit | 发布草稿 |
| POST | rollback/{flowId} | definition:edit | 版本回滚 |
10.2 流程实例 workflow/instance
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| POST | start | instance:start | 发起 |
| GET | my | instance:list | 我发起的 |
| GET | {instanceId} | common | 详情(含 Tasks/Records) |
| POST | withdraw/{instanceId} | instance:withdraw | 撤回 |
| POST | resubmit/{instanceId} | instance:start | 驳回后重提 |
| GET | dashboard | — | 数据面板统计 |
| GET | efficiency | — | 流程效率统计 |
| POST | terminate/{instanceId} | instance:terminate | 管理员终止/作废 |
| POST | suspend/{instanceId} | instance:suspend | 管理员挂起 |
| POST | resume/{instanceId} | instance:resume | 管理员恢复 |
| POST | reassign/{instanceId} | instance:reassign | 管理员改派 |
| POST | jump/{instanceId} | instance:jump | 管理员跳转节点 |
10.3 审批任务 workflow/task
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | todo | common | 待我审批 |
| GET | done | common | 已办 |
| POST | approve | task:approve | 通过 |
| POST | reject | task:reject | 驳回 |
| POST | transfer | task:transfer | 转办 |
| POST | addsign | task:addsign | 加签 |
| POST | delegate | task:delegate | 委托代审(任务仍归属原审批人) |
| POST | removesign | task:removesign | 减签 |
| POST | urge | task:urge | 催办(24h 同实例限一次) |
| POST | read | common | 标记已读 |
| GET | unread | common | 未读数量 |
| POST | batchApprove | task:approve | 批量通过 |
10.4 审批记录 workflow/record
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | list | common | 记录列表 |
| GET | cc | common | 抄送给我 |
| POST | read | common | 标记已读 |
| GET | unread | common | 未读数量 |
10.5 评论与表单模板
workflow/comment:list(common)、add(comment:add)workflow/formTemplate:list(common)、{formId}(common)、POST(template:add)、PUT(template:edit)、delete/{ids}(template:delete)
10.6 AI 能力 workflow/ai
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| POST | generate | definition:ai | 自然语言生成流程草稿(节点/连线/表单字段),仅返回不落库 |
| POST | approval-suggest | task:ai | 提交前审批意见话术建议(不落库,可编辑);支持 ?regenerate=true 忽略历史缓存重新生成 |
| POST | approval-summary | — | 审批动作后引擎后台自动调用,把「动作+节点+意见+表单」压成一句话摘要写入一条 Action=0 系统记录的 AiSummary 字段(落痕),无独立前端入口 |
| POST | instance-summary/{instanceId} | instance:ai-summary | 汇总整条实例审批链路为连贯摘要;支持 ?regenerate=true 以全量记录重新汇总(忽略局部摘要) |
| POST | flow-analyze | definition:ai-analyze | 流程优化体检(节点/连线/条件/审批人/并行汇聚的合规性检查) |
| POST | match-fill | instance:ai-fill | 自然语言发起申请:匹配最合适流程并预填表单字段 |
| POST | risk-check/{taskId} | task:ai-risk | 审批风险研判:基于节点+表单+路径给出风险等级/说明/处置建议,仅展示不影响流转 |
提示词(prompts)统一由后端
PromptLoader从磁盘AiOptions.PromptDir目录读取(留空取程序基目录Prompts/),文件缺失时对应能力调用返回友好提示而非报错。当前Prompts/下含approval-suggest.md、risk-check.md、flow-generate.md。
10.7 Webhook 配置 workflow/webhook
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | list | common | 配置列表(设计器下拉选择端点也走此接口) |
| POST | `` | webhook:add | 新增端点(Name/Url/Enabled/Secret) |
| PUT | `` | webhook:edit | 修改端点 |
| POST | delete/{ids} | webhook:delete | 删除端点 |
10.8 移动端菜单 workflow/menu
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | `` | common | 返回 uni-app 工作流工作台菜单(与移动端 RouterVo 同结构),按当前用户权限过滤;作为 App 工作台独立、唯一的菜单源(不与通用菜单合并) |
11. 权限与菜单种子
WorkflowSeedService.EnsureMenuSeedData() 幂等种子化菜单与按钮权限,并默认授予所有角色(普通审批角色访问接口的前提)。
两个一级目录(M 类型)
- 流程管理(
wf-set):流程定义、表单模板、流程定义设计(隐藏子页) - 流程中心(
workflow):数据面板、我的流程、待我审批、已办任务、审批记录、抄送给我、发起申请/重新提交/流程审批(隐藏跳转入口)
12. Webhook 出站(事件回调)
12.1 端点配置
- 表
wf_webhook(WfWebhook):Name/Url/Enabled/Secret。CRUD 经WfWebhookController(workflow/webhook)。 - 节点通过
WfFlowNode.EnterWebhookId/LeaveWebhookId引用对应端点;节点进入/离开时触发回调。
12.2 Outbox 事务发件箱
- 节点到达/离开时,在流转事务体内写一条
wf_webhook_delivery(Status=Pending,与业务变更原子落库)。 - 投递失败不阻断主流程——主业务已提交,回调异步保证。
12.3 投递与重试
- 独立定时任务
Job_WfWebhookRetry(默认每 2 分钟,经Job_Dispatcher按租户展开)调用WfEngineService.RetryWebhookDeliveries()。 - 流程:捞取
Pending/ 可重试记录 → 乐观锁 claim(避免多实例重复发送)→POST端点(SendWebhook,受保护 virtual 方法便于单测注入)→ 成功置Sent。 - 重试上限:未超限回
Pending等待下次重试;超限转Dead(死信)不再自动重试。 wf_webhook_delivery记录EventId/Payload/RetryCount/Status,便于排查。
12.4 并发安全
AdvanceToNext入口在事务内重新查库取活动节点集,若刚被完成的源节点completedNode已不在活动集(说明它已被另一并发事务移出并 fork 了后续待办),则跳过本次推进,避免或签多待办并发时重复 fork 子节点。必须用事务内查库得到的实例,而非外层传入的内存副本(读不到已提交的并发修改)。
