一句话回答:仿钉钉流程模型转换成 BPMN 2.0,本质上不是 JSON 换成 XML,而是把审批树编译成可执行流程图。 转换器需要先统一节点和分支语义,再生成 User Task、Gateway、Sequence Flow、Event、Extension Elements 与 BPMN DI;会签、或签、条件分支、抄送、超时和空审批人策略都必须有明确映射。
最稳妥的方案是保留两层模型:简化审批 DSL 服务业务人员,BPMN 2.0 服务流程引擎和技术治理。两者之间增加"规范化中间模型 + 编译器 + 映射清单",而不是让前端直接拼接 BPMN XML。
一、先给结论:这是模型编译,不是格式转换
仿钉钉设计器通常用卡片和分支树表达"发起人、审批人、条件、并行、抄送、结束"。BPMN 2.0 则使用事件、活动、网关和顺序流描述 Token 怎样移动。两者看起来都能画流程,语义却不完全相同。
一个可生产使用的转换器至少完成六件事:
- 校验简化模型,补全开始、结束、分支汇合和默认路径;
- 把树形结构规范化为有向图,并生成稳定、可追踪的节点 ID;
- 把审批节点映射为 User Task,把条件与并行映射为正确网关;
- 把审批人、表单、按钮、数据权限和操作策略写入扩展属性;
- 生成 BPMN DI 坐标与连线路径,使 XML 能被 bpmn-js 正确显示;
- 输出 BPMN XML、源节点映射、编译器版本和校验报告。
如果只把每张审批卡片替换成一个 User Task,再按照 JSON 的 nextId 连线,简单串行流程可能能跑,但一遇到多个条件同时成立、并行汇合、会签比例或空审批人,就会出现执行语义错误。
二、两种模型的语义差异在哪里
| 维度 | 仿钉钉审批模型 | BPMN 2.0 |
|---|---|---|
| 主要用户 | 业务管理员、部门负责人 | 流程架构师、开发与运维 |
| 结构 | 审批树、条件分支、并行分支 | 任意有向流程图 |
| 节点语言 | 审批人、抄送人、条件、会签 | Event、Task、Gateway、Sequence Flow |
| 人员规则 | 部门主管、角色、发起人自选 | 标准资源分配 + 引擎扩展 |
| 中国式操作 | 加签、退回、撤回、转办 | 多数属于运行时平台能力 |
| 图形信息 | 卡片位置常由前端自动排列 | BPMN DI 明确保存 Shape 与 Edge |
| 交换能力 | 平台私有 JSON | OMG 标准 XML 与扩展命名空间 |
BPMN 2.0 的优势是标准化和执行语义完整;简化模型的优势是易学、易约束。转换的目标不是消灭简化模型,而是为它建立稳定、可解释的执行出口。
下面用同一份"采购申请"业务展示两种图形。业务规则保持一致:申请提交后先由部门审批;金额达到 10,000 元时增加财务审批,否则直接进入抄送和结束。两张图表达的是同一件事,但面向的建模者和图形语言完全不同。

图 1:仿钉钉审批图采用纵向卡片、加号插入和业务化节点名称,用户主要回答"由谁审批、满足什么条件、下一步做什么"。可选节点被限制在审批人、抄送人、条件分支和并行分支等常用类型内。

图 2:专业 BPMN 图使用开始事件、用户任务、排他网关、顺序流、汇合点、泳道和结束事件表达执行语义;建模者需要明确分支怎样拆分、怎样汇合以及 Token 沿哪条路径移动。
最直观的区别是:仿钉钉图把"业务动作"做成卡片并由设计器自动维护结构;BPMN 图把"执行语义"暴露为标准元素,允许建模者自由组织拓扑。前者通过限制换取易用性,后者通过标准符号获得表达能力。转换器的工作,就是把卡片背后的业务含义展开成右图中的事件、任务、网关和连线,而不是照着卡片位置复制图形。

图 3:简化审批节点先进入中间模型,再映射为 BPMN 语义元素和平台扩展。
三、为什么要先设计中间模型
前端 JSON 往往混合了界面状态、临时 ID、组件配置和业务语义。直接以它为编译输入,会让 BPMN 转换器依赖具体页面实现。更稳妥的做法是增加一层与 UI 无关的 Approval IR。
建议中间模型至少包含:
| 对象 | 核心字段 | 作用 |
|---|---|---|
| Process | processKey、name、version、tenant、startNodeId | 定义流程边界与版本 |
| Node | id、type、name、next、properties | 表示开始、审批、抄送、条件、并行或结束 |
| Branch | id、priority、condition、target、isDefault | 表示分支次序、表达式和兜底路径 |
| AssigneeRule | resolverType、resolverId、scope、emptyPolicy | 描述人员解析规则 |
| ApprovalPolicy | mode、passRule、rejectRule、sequential | 描述或签、会签、比例与顺序 |
| FormPolicy | formKey、fieldPermissions、buttons | 描述表单版本、字段和按钮权限 |
| OperationPolicy | allowAddSign、allowReturn、allowTransfer | 描述运行时允许的操作 |
| LayoutHint | lane、order、preferredWidth | 提供布局提示,不直接保存绝对坐标 |
中间模型需要满足三个条件:
- 与 Vue 组件结构解耦,前端升级不影响编译器;
- 能表达业务语义,但不混入某个引擎的 flowable: 或 camunda: 属性;
- 每个源节点和生成的 BPMN 元素可双向追踪。
建议 ID 由源节点 ID 稳定派生,例如审批节点 N12 始终生成 UserTask_N12。不要每次导出都使用随机 ID,否则流程版本对比、实例迁移和问题定位会非常困难。
四、常见节点如何映射到 BPMN 2.0
| 简化节点 | BPMN 元素 | 关键配置 | 注意事项 |
|---|---|---|---|
| 发起人 | Start Event | initiator、启动表单扩展 | 发起人不是必须生成一个 User Task |
| 单人审批 | User Task | assignee 或人员解析扩展 | 设计时规则与运行时人员快照分开 |
| 候选人或签 | 单个 User Task | candidateUsers/candidateGroups | 任一候选人签收并完成,不等于多实例 |
| 多人会签 | Multi-instance User Task | collection、elementVariable、completionCondition | 并行或串行必须显式区分 |
| 条件分支 | Exclusive Gateway + 条件顺序流 | conditionExpression、default | 条件顺序与兜底路径必须确定 |
| 并行分支 | Parallel Gateway 拆分与汇合 | split、join | 汇合网关要等待所有实际分支 |
| 可选多分支 | Inclusive Gateway | 多个条件 + 汇合 | 汇合语义复杂,需防止错误等待 |
| 抄送 | Send Task、Service Task 或平台扩展 | recipientRule、通知模板 | 只通知与需要阅读回执的语义不同 |
| 自动处理 | Service Task / Business Rule Task | delegate、topic、decisionRef | 与业务事务、重试和幂等一起设计 |
| 子流程 | Call Activity / Sub-process | calledElement、输入输出映射 | 跨版本调用要明确绑定策略 |
| 超时 | Boundary Timer Event | duration/date/cycle | 区分中断和非中断 |
| 结束 | End Event | 结束类型、业务结果 | 驳回结束与正常结束可用不同结果扩展 |
发起人节点经常只是设计器上的入口卡片。若流程提交即启动,可以把发起人、组织和表单信息放入启动变量或扩展元素,不需要额外创建"发起人审批任务"。
抄送也不是 BPMN 标准中的 OA 概念。如果抄送只是通知,可用消息、Send Task、Service Task 或任务监听器;如果必须阅读、确认并形成待办,则应建 User Task 或平台自定义任务,不能只改图标。
五、条件分支为什么必须生成网关
在 BPMN 中,一个普通活动拥有多条带条件的出线时,可能同时选择多条满足条件的顺序流并产生并行执行。仿钉钉条件组通常表达"按优先级命中一个分支",更接近 Exclusive Gateway。
条件分支的正确编译步骤是:
- 在分支入口生成 Exclusive Gateway;
- 为每个分支生成 Sequence Flow;
- 把字段条件编译为引擎可执行的 conditionExpression;
- 按业务优先级稳定排列出线;
- 生成一个明确的 default 顺序流;
- 分支结束后生成汇合网关,再连接后续节点。
例如"金额大于 10 万走总经理,否则走部门经理",必须有默认路径。没有默认路径时,如果变量缺失或表达式均为 false,引擎通常会报错或使流程停在网关。
条件表达式不能直接拼接用户输入。转换器应把表单字段映射为受控变量,把运算符限制在白名单,并进行类型检查、空值处理和转义。字符串、数字、日期、枚举和组织字段需要不同的编译策略。
并行分支应使用 Parallel Gateway 拆分与汇合。若分支带条件且可能同时进入多条路径,可评估 Inclusive Gateway,但其汇合需要判断哪些上游分支真正被激活,测试成本明显更高。简化设计器如果无法解释这种语义,宁可限制功能,也不要偷偷降级。
六、或签、会签和依次审批怎样转换
"多人审批"至少有四种不同语义:
| 业务语义 | 推荐 BPMN 表达 | 运行时含义 |
|---|---|---|
| 多人候选,任一人办理 | 单个 User Task + Candidate | 只产生一个任务,签收后由一人负责 |
| 多人并行会签 | 并行 Multi-instance User Task | 每个人产生独立任务 |
| 多人依次审批 | 串行 Multi-instance User Task | 按人员列表逐个产生任务 |
| 固定顺序、每步规则不同 | 多个串联 User Task | 每个节点可有独立表单、按钮与超时 |
并行会签需要 collection、elementVariable 和 isSequential=false;依次审批使用 isSequential=true。通过比例可编译为 completionCondition,但要注意:nrOfCompletedInstances 只表示任务完成数量,不等于"同意数量"。审批结果应写入结构化变量,由平台计算 approvedCount、rejectedCount 和 passRule。
一票否决也不能仅靠删除剩余任务。平台需要记录谁否决、哪些任务被终止、流程怎样继续,以及消息和业务副作用如何补偿。对复杂审批策略,更推荐在扩展属性中保存 ApprovalPolicy,由任务监听器或统一审批服务执行,BPMN 负责稳定的流程骨架。
审批人规则建议在任务进入时解析,并把最终人员列表保存为不可变快照。部门主管、连续多级主管、角色、岗位、发起人自选和表单字段选人都可能随组织调整变化;只保存 resolverId 而不保存快照,会让历史审计无法解释当时为什么选择这些人。
七、哪些信息应该放进扩展属性
BPMN 2.0 允许通过 extensionElements 承载厂商或平台扩展。建议把标准流程语义与业务扩展分层:
- 标准层:Start Event、User Task、Gateway、Sequence Flow、Timer、Call Activity;
- 平台层:审批人解析、会签策略、表单版本、按钮权限、字段权限、数据范围;
- 引擎适配层:Flowable、Camunda 等引擎需要的 assignee、candidate、listener、class 或 topic 属性。
平台可以定义独立命名空间,例如 yc:assigneeRule、yc:approvalPolicy、yc:formPolicy、yc:operationPolicy。发布到不同引擎时,再由适配器生成对应的 flowable:、camunda: 或 Worker 配置。
扩展属性至少应覆盖:
- 人员规则:类型、规则 ID、作用域、是否允许自选、空结果策略;
- 审批策略:或签、并行会签、串行会签、通过比例、一票否决;
- 表单策略:formKey、formVersion、字段可见/只读/必填;
- 操作策略:同意、拒绝、加签、转办、委派、退回、撤回;
- 数据权限:本人、部门、流程参与人、自定义规则;
- 通知策略:渠道、模板、抄送人、催办和超时;
- 审计字段:源节点 ID、设计器版本、规则版本和编译器版本。
扩展元素必须有正式的 moddle 描述文件,才能被 bpmn-moddle 可靠读写。把任意 JSON 字符串塞进 documentation 虽然省事,却不利于校验、差异比较和属性面板编辑。
八、转换器应该采用怎样的编译流水线

图 4:先分析语义,再生成 BPMN 和图形信息;任何阶段失败都不应发布。
推荐把转换器拆成七个阶段:
- 解析与 Schema 校验:检查节点类型、必填属性、引用完整性和版本;
- 规范化:去除 UI 临时字段,展开默认节点,补齐 Start、End 和分支汇合;
- 语义分析:识别或签、会签、分支优先级、空审批人和回退策略;
- 控制流生成:创建 Event、Task、Gateway 和 Sequence Flow;
- 扩展生成:写入人员、表单、权限、按钮、通知和引擎适配属性;
- BPMN DI 布局:生成 Shape 坐标、Edge waypoints 和分支层级;
- 验证与导出:执行标准校验、引擎校验、业务校验并输出 XML 与映射清单。
编译器输出不应只有一个 .bpmn 文件,还应包含:
- sourceNodeId 与 bpmnElementId 的映射;
- 模型摘要、哈希、编译器版本和目标引擎 Profile;
- Warning 与 Error 列表;
- 不可逆或降级转换说明;
- 设计时人员规则与发布时规则版本;
- BPMN XML 和必要的部署资源。
这份映射清单会直接影响日志定位、任务中心展示、流程版本对比、实例迁移和线上故障排查。
九、BPMN.js 在转换中负责什么
bpmn-js 是 BPMN 2.0 的浏览器端渲染与建模工具;bpmn-moddle负责按照 BPMN 元模型读写 XML。它们可以验证模型对象、生成 XML、渲染 BPMN DI,并通过 Modeling API 创建与连接元素。
但 bpmn-js 不知道"连续多级主管""金额条件组""会签一票否决"是什么意思。业务语义编译必须由平台自己的 Compiler 完成。
实践中有两种实现方式:
1. 方式一:前端使用 Modeling API
通过 elementFactory 创建形状,使用 modeling.createShape、modeling.connect、modeling.updateProperties 维护画布,最后 saveXML。优点是生成过程可视化、天然经过 bpmn-js 规则;缺点是大量模型转换依赖浏览器状态,批量发布和后端校验不够方便。
2. 方式二:后端生成语义模型,前端负责预览
后端编译 Approval IR,使用 XML/元模型库生成 BPMN 语义与 DI,前端通过 importXML 预览并允许技术人员二次编辑。优点是可测试、可批量、可在发布流水线执行,更适合企业平台。
推荐采用"后端编译为主、bpmn-js 预览与专业编辑为辅"的方式。前端保存后仍需回到后端重新校验,不能把 importXML 成功当作可执行证明。
十、BPMN DI 怎样自动布局
BPMN XML 只有语义元素而没有 BPMNShape、BPMNEdge 时,引擎可能仍能部署,但 bpmn-js 无法得到完整图形位置。转换器必须同时生成 DI。
简化模型适合使用确定性分层布局:
- 按拓扑顺序计算节点层级,主流程从左到右排列;
- 条件和并行分支在纵向分层,汇合后回到主轴;
- User Task 使用统一尺寸,Event 与 Gateway 使用标准尺寸;
- 连线采用正交折线,先离开节点安全区再转向;
- 同一源模型每次编译得到稳定坐标,便于版本差异比较;
- 当分支过多或存在回路时,转入专业 BPMN 模式人工整理。
图形布局与执行语义应分开测试。移动一个节点只应改变 DI,不应导致流程定义语义变化;修改审批条件则必须产生可审计的语义差异。
十一、如何验证转换结果真的可执行

图 5:XML 能打开只是第一层,生产发布还要通过引擎、业务语义和回归验证。
建议建立四层验证:
1. 第一层:结构与标准验证
检查唯一 ID、sourceRef/targetRef、开始与结束、网关出入线、默认流、BPMN Schema、扩展命名空间和 BPMN DI 完整性。使用 bpmn-moddle fromXML/toXML 做往返测试,确保未知属性没有丢失。
2. 第二层:目标引擎验证
将模型部署到 Flowable、Camunda 或目标引擎的测试环境,验证表达式语法、人员扩展、多实例、定时器、监听器和异步行为。标准 BPMN 可交换,不代表所有扩展和表达式可以跨引擎直接运行。
3. 第三层:业务语义验证
用例至少覆盖:
- 条件无命中、单命中和多条件同时成立;
- 候选或签、并行会签、串行会签、比例通过和一票否决;
- 审批人为空、人员重复、组织变更和发起人自选;
- 分支并行、汇合、超时、抄送与子流程;
- 表单字段权限、按钮权限、数据范围和消息;
- 加签、退回、转办、撤回的授权与审计。
4. 第四层:版本与回归验证
比较源模型、BPMN XML 和映射清单差异,用旧版本真实数据启动或迁移实例。每个编译器版本都应有 Golden Files:固定输入产生固定 XML,只有明确变更才更新基线。
发布门禁应区分 Error、Warning 和 Info。没有默认分支、网关无法汇合、人员规则无空值策略应阻止发布;布局过宽、节点名称过长可以提示但不阻断。
十二、退回、加签、撤回为什么不能画成普通连线
很多平台为了表现"可退回",从每个审批节点画一条返回线。这样会迅速形成蜘蛛网,并把运行时操作误写成固定流程路径。
退回、加签、转办、撤回通常依赖当前实例状态、操作者权限、已完成节点、并行分支和业务副作用,不是设计时永远可走的 Sequence Flow。正确做法是:
- 在 extensionElements 中保存允许的操作策略;
- 运行时根据当前执行树计算合法目标;
- 使用引擎状态变更或实例修改 API 执行;
- 同步处理多实例计数、变量作用域、异步作业和边界事件;
- 在独立审计表记录操作者、原因、源节点、目标节点和影响范围;
- 对消息、库存、财务等外部副作用执行补偿。
只有业务上固定存在的驳回路径,才适合使用 BPMN 网关和顺序流建模。临时加签和自由退回不应污染主流程图。
十三、双模式平台怎样落地
企业流程平台可以同时保留简化审批设计器和专业 BPMN 设计器:
- 业务人员在简化设计器中配置常见审批;
- 编译器生成标准 BPMN 与平台扩展;
- 技术人员在 BPMN.js 中预览复杂结果;
- 超出简化模型能力边界时,切换为专业模式;
- 发布中心统一管理模型版本、校验、部署、回滚和审计;
- 运行时统一接入组织、表单、任务、消息和权限服务。
关键是建立兼容性标记:
| 模型状态 | 含义 | 是否可回到简化设计器 |
|---|---|---|
| simple-compatible | 只使用审批 DSL 支持的 BPMN 子集 | 可以无损往返 |
| advanced-only | 使用事件子流程、补偿等高级元素 | 只能专业模式编辑 |
| lossy | 可近似展示,但无法保留全部语义 | 禁止覆盖原模型 |
在云程低代码开发平台这类产品中,这一层编译器的价值是把用户友好的审批体验与标准化执行底座连接起来。上层业务不必理解 BPMN XML,引擎也不必理解每一种页面组件,双方通过稳定的模型契约演进。


十四、如果只记住六句话
- 仿钉钉模型转 BPMN 是编译问题,不是 JSON 转 XML。
- 先建立与 UI、引擎解耦的 Approval IR,再生成 BPMN。
- 条件分支要生成网关、条件顺序流和默认路径,不能只给任务增加多条出线。
- 或签是单任务候选,会签是多实例;任务完成数量不等于同意数量。
- 审批人、表单、按钮和数据权限属于扩展层;退回、加签、撤回属于受控运行时操作。
- XML 能被 bpmn-js 打开只是起点,发布前还要通过引擎、业务语义和版本回归验证。
最值得建设的不是一个"导出 BPMN"按钮,而是一套可测试、可审计、可升级的模型编译体系。只有这样,简化设计器才能既保持业务友好,又不会牺牲 BPMN 2.0 的执行正确性与长期可移植性。