Appearance
规范 04 · 引擎核心操作
方法语义契约。引擎一次执行旅程的时序与设计动机见 设计原理 03 · 执行引擎。
启动流程
text
startProcessInstanceById(defineId, operator, args) → ProcessInstance语义:
- 加载流程定义,解析为 ProcessModel
- 创建 ProcessInstance(state=10)
- 保存实例到仓库
- 执行 start 节点 → 遍历输出边 → 创建第一个任务(发起申请节点,actor=发起人)
- 任务的 actor 根据 assignee / assignmentHandler 解析
- 保存任务和参与者记录
startAndExecute 契约(调用方约定,引擎不内置):
text
startAndExecute(defineId, operator, args) → ProcessInstance- 调用
startProcessInstanceById - 获取所有进行中任务,逐个自动完成(submitType=0 APPLY)
- 流程由此推进到第一个真正的审批节点
引擎不自动执行第一个任务——这是调用方的职责(mldong 框架模式), 四版 demo 的
/wf/processInstance/startAndExecute端点均遵循此契约。
完成任务
text
executeProcessTask(taskId, operator, args) → ProcessInstance语义:
- 加载任务 → 校验权限(actor 包含 operator;
flow.admin/flow.auto恒放行,见下) - 任务状态 10→20,记录操作人和完成时间
- 执行当前节点 → 遍历输出边 → 创建下一批任务
- 若下一节点为 end → 实例状态 10→20(完成)
- 若下一节点为 task → 创建新任务(解析 actor)
- 若下一节点为 decision → 评估表达式 → 选择分支
- 若下一节点为 fork → 并行创建多条路径的任务
- 保存变更
系统代执行(flow.auto / flow.admin)
v1.0.1(集成反馈④):对齐 mldong 框架 boot2/boot3 语义。
- 权限放行:
operator = "flow.auto"(自动执行,发起即提交)或"flow.admin"(超级管理员)时,任务权限校验直接通过,无需在参与者列表内(忽略大小写)。 - 变量注入跳过:
flow.auto/flow.admin不是真实用户——引擎执行时不调用 UserProvider 注入u_*变量,流程变量保持既有值。需要u_*反映实际执行人时, 由调用方(如startAndExecute)在 args 中显式携带。 - 发起即提交(startAndExecute):启动流程后,调用方获取 doing 任务,以
flow.auto逐个自动完成(submitType=APPLY),把流程推进到第一个真正的审批节点——apply 节点 参与者为发起人(applicant),由flow.auto代执行,语义等价于发起人亲自提交。
驳回
text
executeAndJumpToEnd(taskId, operator, args) → ProcessInstance语义:
- 校验权限
- 任务状态 10→20
- 实例状态 10→45(已拒绝)
- 废弃其他进行中的任务(状态 →99)
退回发起人(mldong 框架契约):业务上"驳回后让发起人改单重提"不使用
executeAndJumpToEnd(那是拒绝,实例直接 45),而是submitType=6(ROLLBACK_TO_OPERATOR)调executeAndJumpToFirstTaskNode——第一个任务节点重执行且参与者强制为发起人, 发起人收到新待办,实例保持 10 进行中。四版 demo 的/wf/processTask/execute遵循此行为 (submitType 全枚举见 设计原理 06 §3-4)。
跳转
text
executeAndJumpTask(taskId, operator, args, targetTaskName) → ProcessInstance语义:
- 校验权限
- 任务状态 10→20
- 在已完成的节点中找到 targetTaskName,重新执行其输出边
- 废弃当前未完成的任务
会签
会签在普通任务基础上增加:
- 并行会签:为每个 actor 创建独立任务,全部完成才驱动下一步
- 串行会签:一次只创建一个任务,完成后创建下一个 actor 的任务
- 按比例会签:完成率达到阈值即驱动下一步
会签的 actor 存储在流程变量中:{COUNTERSIGN_PREFIX}_{taskName}_operatorList
三种模式的引擎实现细节见 设计原理 03 §6。
流程变量约定
引擎自动注入以下变量(前缀 u_ 表示用户信息):
| 变量名 | 来源 | 说明 |
|---|---|---|
u_userId | IUserProvider | 当前操作人 ID |
u_realName | IUserProvider | 当前操作人姓名 |
u_deptId | IUserProvider | 部门 ID |
u_deptName | IUserProvider | 部门名称 |
u_postId | IUserProvider | 岗位 ID |
u_postName | IUserProvider | 岗位名称 |
autoGenTitle | 引擎自动生成 | ${realName}的${displayName}-${时间} |
BUSINESS_NO | 业务方传入 | 业务流水号 |
submitType | 操作时传入 | 全枚举 0=发起 1=同意 2=拒绝 3=退回上一步 4=跳转 5=重新提交 6=退回发起人 20=会签拒绝(见 设计原理 06 §3-4) |
聚合根方法清单(跨语言契约)
四版实现遵循统一 DDD 结构:聚合根封装业务规则,引擎只做编排。 设计论证见 设计原理 02 · 领域模型。
ProcessInstance(聚合根)
| 行为 | 说明 |
|---|---|
create | 工厂——创建流程实例(state=10) |
completeTask(task, operator, vars) | 完成任务(子实体状态转换 + 实例变量合并) |
abandonTask(task) | 废弃单个任务 |
abandonAllDoing() | 废弃所有进行中任务 |
finish() | 流程完成(state 10→20) |
reject() | 驳回(state 10→45) |
addVariable(vars) | 追加流程变量 |
createTask(...) | 创建任务(子实体工厂) |
getDoingTasks() / getDoneTasks() | 查询 |
isAllTasksFinished() | join 合并判断 |
ProcessTask(子实体)
| 行为 | 说明 |
|---|---|
finish(operator, vars) | 完成任务(10→20,记录操作人/完成时间) |
abandon() | 废弃(10→99) |
isAllowed(operator) | 参与者权限判断 |
isDoing() / isFinished() | 状态判断 |
各语言实现位置
| 语言 | 聚合根 | 引擎(薄编排) |
|---|---|---|
| Java | domain/ProcessInstance.java + domain/ProcessTask.java | core/JeeflowEngineImpl.java |
| Go | model/instance.go | engine/engine_impl.go |
| Node.js | src/model.ts(class) | src/engine.ts |
| Python | jeeflow/model.py(dataclass + 方法) | jeeflow/engine.py |
引擎保留:流程遍历(executeNode)、决策求值、参与者解析、仓储调用。 任务状态转换/创建等业务规则一律收敛到聚合根。