Appearance
规范 02 · 流程定义格式
流程定义 = LogicFlow JSON。同一份 JSON 在所有语言实现中必须产生一致的执行结果。
顶层结构
json5
{
"name": "leave", // 流程编码(唯一)
"displayName": "请假审批", // 流程显示名称
"type": "approval", // 流程类型
"nodes": [...],
"edges": [...]
}流程级 properties
来源:mldong 框架
process-drawer-schema.ts
| 字段 | 类型 | 引擎 |
|---|---|---|
name | string | ✅ |
displayName | string | ✅ |
instanceUrl | string | 计划 |
instanceNoClass | string | 计划 |
expireTime | string | ✅ |
preInterceptors | array | ✅ Registry |
postInterceptors | array | ✅ Registry |
selectUserOnInitiate | int | ❌ 前端 |
selectUserApi | string | ❌ 前端 |
enableCcActors | int | ❌ 前端 |
enableApplyReason | int | ❌ 前端 |
enableAttachment | int | ❌ 前端 |
enableFieldPerm | int | ❌ 前端 |
节点类型总览
| type | 说明 | 必填 |
|---|---|---|
snaker:start | 开始 | - |
snaker:end | 结束(全流程只能有一个) | - |
snaker:task | 任务 | assignee 或 assignmentHandler |
snaker:decision | 条件分支 | 出边 expr |
snaker:fork | 并行分支 | - |
snaker:join | 并行合并 | - |
snaker:custom | 自定义 | customClass |
snaker:subprocess | 子流程 | subProcessKey |
发起申请节点约定(mldong 框架契约):每个流程的 start 后第一个任务节点必须是 "发起申请"节点,
assignee使用特殊值"applicant"——引擎在解析参与者时将其替换为 流程发起人(instance.operator)。引擎本身不自动执行该节点,由调用方(demo 的startAndExecute)在启动后自动完成,从而把流程推进到真正的审批节点。 契约动机见 设计原理 06 · 契约约定。
任务节点 properties
来源:mldong 框架
prop-config/task-form/*.vue
| 字段 | 类型 | 引擎 | 说明 |
|---|---|---|---|
name | string | ✅ | 节点唯一编码 → taskName |
displayName | string | ✅ | 显示名称 |
form | string | ✅ | 表单标识 → formKey |
assignee | string | ✅ | 固定参与者,逗号分隔 → actor;每个 token 优先按流程变量 key 解析(见 参与者解析) |
assignmentHandler | string | ✅ | 动态参与者类名 → Registry |
candidateUsers | string | ⚠️ | 候选人列表 → candidatePage API |
candidateGroups | string | ⚠️ | 候选组 → candidatePage API |
candidateHandler | string | ⚠️ | 动态候选人处理类 → candidatePage API |
taskType | int | ✅ | 0=主办 1=协办 |
performType | int | ✅ | 0=普通 1=会签 |
countersignType | string | ✅ | PARALLEL/SEQUENTIAL/RATIO(0.5) |
countersignCompletionCondition | string | ✅ | 会签完成条件(如 #nrOfCompletedInstances>=2) |
actionBtns | array | ❌ | 审批按钮配置 |
expireTime | string | ✅ | 期望完成时间 |
reminderTime | string | 计划 | 提醒时间 |
reminderRepeat | string | 计划 | 重复提醒间隔 |
autoExecute | int | 计划 | 自动完成 |
callback | string | 计划 | 回调处理类 |
preInterceptors | array | ✅ | 节点前置拦截器 |
postInterceptors | array | ✅ | 节点后置拦截器 |
⚠️
candidate*系列不生成 actor 记录,但引擎通过candidatePageAPI 返回候选人列表, 供前端"指定下一节点参与人"时使用。
参与者解析(assignee)
v1.0.1(集成反馈③):对齐 mldong 框架 boot2/boot3 语义——"token 即变量 key, 能替换就换,换不了就是字面量"。
解析顺序(引擎创建任务时):
tf_nextNodeOperator优先:流程变量中存在tf_nextNodeOperator(下一节点处理人, 由前端/上一步动态指定)时直接采用,不再看 assignee。值为 String 按逗号分割; 值为 Collection/数组 原样展开。- assignee 逐 token:按英文逗号分割,逐个处理:
- token =
applicant→ 流程发起人(instance.operator)——mldong 契约特殊值 - 其他 token → 先查流程变量(token 作为 key):命中 → 用变量值(值为集合则展开为多人); 未命中 → token 本身作为参与者(静态用户 ID 写法)
- 不做
${...}剥壳——${deptLeader}与 boot2/boot3 行为一致:按 key 查不到 → 字面量
- token =
- assignmentHandler 兜底:assignee 为空/解析结果为空时,按类名反射调用动态参与者处理器。
对齐说明:boot2/boot3 的 getTaskActors 语义为 args.get(token, token)——token 当 key 查流程变量,命中用值、未命中用字面量;applicant 为 jeeflow 增强(boot2/boot3 的"发起人" 靠 assignmentHandler=OperatorAssignmentHandler 实现,二者等价)。
决策节点 properties
| 字段 | 位置 | 引擎 | 说明 |
|---|---|---|---|
expr | 节点 | ✅ | 节点级决策表达式 |
decisionHandler | 节点 | ✅ | 自定义决策类名 → Registry |
expr | 出边 | ✅ | 分支条件表达式 |
text.value | 出边 | ✅ | 分支标签(钉钉模式渲染) |
其他节点 properties
| 节点 | 字段 | 引擎 | 说明 |
|---|---|---|---|
custom | customClass | ✅ | 自定义处理器类名 |
subprocess | subProcessKey | ✅ | 子流程编码 |
subprocess | subProcessName | ❌ | 前端显示 |
完整示例
json
{
"name": "leave",
"displayName": "请假审批",
"type": "approval",
"nodes": [
{ "id":"start", "type":"snaker:start", "x":100, "y":200, "properties":{}, "text":{"value":"开始"} },
{ "id":"apply", "type":"snaker:task", "x":250, "y":200,
"properties":{ "form":"apply-form", "assignee":"applicant", "taskType":0, "performType":0 },
"text":{"value":"发起申请"} },
{ "id":"t1", "type":"snaker:task", "x":400, "y":200,
"properties":{ "form":"leave-form", "assignee":"leader", "taskType":0, "performType":0 },
"text":{"value":"组长审批"} },
{ "id":"end", "type":"snaker:end", "x":550, "y":200, "properties":{}, "text":{"value":"结束"} }
],
"edges": [
{ "id":"e1", "sourceNodeId":"start", "targetNodeId":"apply", "properties":{} },
{ "id":"e2", "sourceNodeId":"apply", "targetNodeId":"t1", "properties":{} },
{ "id":"e3", "sourceNodeId":"t1", "targetNodeId":"end", "properties":{} }
]
}决策分支边必须带 text.value 分支标签(钉钉模式渲染在分支线上):
json
{ "id":"e4", "sourceNodeId":"decision1", "targetNodeId":"t2",
"properties":{"expr":"amount > 1000"}, "text":{"value":"金额>1000"} }