Appearance
用户指南 02 · 流程定义
流程定义 = LogicFlow JSON。本文给出完整字段参考和编写规范。
1. 顶层结构
json5
{
"name": "leave", // 流程编码(唯一)
"displayName": "请假审批", // 流程显示名称
"type": "approval", // 流程类型
"nodes": [...], // 节点列表
"edges": [...] // 边列表
}2. 节点编写规范
2.1 流程骨架(必守 3 条)
1. 只有一个 start(snaker:start)
2. 只有一个 end(snaker:end)——分支必须汇合到同一个结束节点
3. start 后第一个任务节点必须是"发起申请"节点:
assignee = "applicant"(引擎解析为发起人)2.2 节点类型
| type | 必填 properties | 说明 |
|---|---|---|
snaker:start | - | 开始 |
snaker:end | - | 结束 |
snaker:task | assignee 或 assignmentHandler | 任务节点 |
snaker:decision | 出边 expr | 条件分支 |
snaker:fork | - | 并行分支 |
snaker:join | - | 并行合并 |
snaker:custom | customClass | 自定义节点 |
snaker:subprocess | subProcessKey | 子流程 |
2.3 任务节点字段参考(完整)
| 字段 | 必填 | 说明 |
|---|---|---|
id | ✅ | 节点编码(唯一)→ 任务名 |
displayName(text.value) | ✅ | 显示名称 |
assignee | 二选一 | 固定参与者,逗号分隔多人;"applicant" = 发起人 |
assignmentHandler | 二选一 | 动态参与者注册名 |
form | - | 表单标识 → formKey |
taskType | - | 0=主办 1=协办 |
performType | - | 0=普通 1=会签 |
countersignType | 会签时 | PARALLEL / SEQUENTIAL / RATIO |
expireTime | - | 期望完成时间 |
preInterceptors / postInterceptors | - | 节点拦截器注册名 |
2.4 决策节点
节点 properties:
expr: "amount > 1000" # 节点级默认表达式(可选)
decisionHandler: "xxx" # 自定义决策器注册名(可选)
出边 properties:
expr: "amount > 1000" # 分支条件(决策节点出边必填)
出边 text.value:
"金额>1000" # 分支标签(钉钉模式渲染在线上)决策路由规则:引擎按出边顺序求值,第一个 expr 为真的边获胜;无 expr 的出边作为默认分支。
2.5 会签节点
json
{
"id": "countersign",
"type": "snaker:task",
"properties": {
"assignee": "userA,userB,userC",
"performType": 1,
"countersignType": "PARALLEL"
},
"text": { "value": "会签审批" }
}| 模式 | 行为 |
|---|---|
PARALLEL | 每个参与者一个任务,全部完成才推进 |
SEQUENTIAL | 一次一个任务,完成后下一个参与者 |
RATIO | 阈值完成即推进(完成条件表达式:计划中) |
3. 边
json5
{
"id": "e1",
"sourceNodeId": "start", // 起点节点 id
"targetNodeId": "apply", // 终点节点 id
"properties": { "expr": "amount > 1000" }, // 决策分支条件
"text": { "value": "金额>1000" } // 分支标签(决策/fork 边建议必填)
}建议:decision 出边、fork 出边都写 text.value 标签——钉钉模式渲染在分支线上,没有标签线上是空的。
4. 完整示例(标准骨架)
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": "leader", "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": "leader", "properties": {} },
{ "id": "e3", "sourceNodeId": "leader", "targetNodeId": "end", "properties": {} }
]
}5. 决策表达式
表达式求值走 ExpressionEvaluator SPI,demo 内置了简单数值比较:
amount > 1000
amount <= 1000
u_deptId == 'D01' # 变量前缀 u_ 为引擎注入的用户信息
finalAmount >= 5000生产接入时按需选型(Java 用 SpEL、Python 用 simpleeval 等),引擎不内置。
6. 常见错误
| 错误 | 现象 | 修复 |
|---|---|---|
| 多个 end 节点 | 分支各自结束 | 汇合到同一个 end |
| 申请节点缺 assignee | 启动后无任务 | 加 "assignee": "applicant" |
| 决策出边缺 expr | 走默认分支(第一个无 expr 边) | 每条出边补 expr |
| 决策/fork 边缺 text | 线上无标签 | 补 text.value |
| 节点 id 重复 | 任务名冲突 | 保证 id 全流程唯一 |
7. 用设计器画流程图
jeeflow-ui 已集成钉钉版流程设计器(mldong-flow-designer-plus):
- 预览:流程下拉选定义 → 点"👁 预览" → 只读模式查看
- 实例详情:点"详情" → 流程图 + 高亮(历史节点绿色、进行中橙色)
- 设计器输出的 JSON 结构与本文档一致,可直接存入
wf_process_define.content