【审核人员看清楚再审核,我是把自己公司的案例分析一下, 这哪是广告???】
Camunda是Activiti最大的贡献者之一(除Alfresco以外),同时也是它一个主 要的执行咨询合作伙伴。camunda表示Activiti可能太拘束于Alfresco对以文档为中心的工作流的需求(这个也是BPMN约束使然),而忽视了Activiti起步时 的更为普遍的BPM平台。camunda宣布他们正从Activiti 分裂出一个新的开源工程,那就是camunda BPM
官网
下载
Camunda文档中文站
http://camunda-cn.shaochenfeng.com/
学习路线知识点
https://www.processon.com/view/link/622da3ba1e085307a23dc108#map
由于公司业务限制,没有用到表单引擎和BPMN.js
模型是后端调用Camunda api(BpmnModelInstance、BpmnDiagram)自动生成的(老板嫌弃BPMN.js画的BPMN图丑),表单引擎比较复杂都是单独写,没用到在线表单生成
目前已实现功能点(国内常见的操作都能实现):发起,审批通过,驳回,转交他人审批,退回历史节点,前置加签/后置加签,撤回,重新发起,作废,转阅,催办
后面有部分代码,我也业务代码删除了,童鞋们可以参考一下,有疑问可以私信我。
效果图:
流程定义添加
用户发起:
审批:
后续相关代码实现
// 工作流引擎camunda-bpm依赖
implementation "org.camunda.bpm.springboot:camunda-bpm-spring-boot-starter:7.16.0"
implementation "org.camunda.bpm.springboot:camunda-bpm-spring-boot-starter-webapp:7.16.0"
implementation "org.camunda.bpm:camunda-engine-plugin-spin:7.16.0"
implementation "org.camunda.spin:camunda-spin-dataformat-all:1.16.0"
Camunda工具类
package com.oa.business.flow.utils.camunda;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.galileotime.oa.business.flow.utils.camunda.constant.CamundaEnum;
import com.galileotime.oa.business.flow.utils.camunda.pojo.ProcessPOJO;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.model.bpmn.Bpmn;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.camunda.bpm.model.bpmn.instance.Process;
import org.camunda.bpm.model.bpmn.instance.*;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnDiagram;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnEdge;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnPlane;
import org.camunda.bpm.model.bpmn.instance.bpmndi.BpmnShape;
import org.camunda.bpm.model.bpmn.instance.camunda.CamundaExecutionListener;
import org.camunda.bpm.model.bpmn.instance.camunda.CamundaTaskListener;
import org.camunda.bpm.model.bpmn.instance.dc.Bounds;
import org.camunda.bpm.model.bpmn.instance.di.Waypoint;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
/**
* @author HeZeMin
* @className CamundaUtils
* @description Camunda工作流引擎工具类
* @date 2022/4/8 15:50
*/
@Slf4j
@Component
public class CamundaModelUtils {
/**
*
* @Description 创建流程定义
* @Return: void
* @Author HeZeMin
* @Date 2022年04月08日 15:54
*/
public String createExecutableProcess(HashMap<String, Object> param, Long userId) {
ProcessPOJO processPOJO = new ProcessPOJO();
BeanUtil.copyProperties(param.get("process"), processPOJO);
log.info(JSONUtil.toJsonStr(param));
//1、创建一个空的 BPMN 模型实例
BpmnModelInstance modelInstance = Bpmn.createEmptyModel();
//2、创建BPMN定义元素,设置目标名称空间,并将其添加到新创建的模型实例中
Definitions definitions = modelInstance.newInstance(Definitions.class);
definitions.setTargetNamespace("http://camunda.org/examples");
modelInstance.setDefinitions(definitions);
// di-对于图,需要创建一个图和一个平面元素。平面被设置在一个图对象中,图被添加为子元素
BpmnDiagram bpmnDiagram = modelInstance.newInstance(BpmnDiagram.class);
BpmnPlane plane = modelInstance.newInstance(BpmnPlane.class);
bpmnDiagram.setBpmnPlane(plane);
definitions.addChildElement(bpmnDiagram);
//3、创建流程
String procDefKey = CamundaEnum.PROCESS.getName() + this.id();
Process process = createElement(definitions, procDefKey, Process.class);
process.setName(processPOJO.getProcessName());
process.setExecutable(true);//可执行的流程
// di-平面元素添加process
plane.setBpmnElement(process);
//---业务代码处理start
//保存流程定义
//保存流程发起人用户
//保存流程发起人角色
//---业务代码处理end
//4、创建开始事件
StartEvent startEvent = this.createElement(process, CamundaEnum.EVENT.getName() + this.id(), StartEvent.class);
startEvent.setCamundaInitiator("initiator");//发起人
this.drawBpmnShape(modelInstance, plane, startEvent.getId());// di-平面元素添加节点
//5、创建申请人节点
UserTask userTask = this.createElement(process, CamundaEnum.ACTIVITY.getName() + this.id(), UserTask.class);
userTask.setName("发起人");
userTask.setCamundaAssignee("${initiator}");
// di-平面元素添加节点
this.drawBpmnShape(modelInstance, plane, userTask.getId());
// 开始事件连线到申请人节点
SequenceFlow sequenceFlow = this.createSequenceFlow(process, startEvent, userTask);
// di-平面元素添加连线
this.drawBpmnEdge(modelInstance, plane, sequenceFlow.getId());
//6、创建结束事件
EndEvent endEvent = this.createElement(process, CamundaEnum.EVENT.getName() + this.id(), EndEvent.class);
// 结束监听器
ExtensionElements extensionElements = this.createElement(endEvent, "", ExtensionElements.class);
CamundaExecutionListener start = this.createElement(extensionElements, "", CamundaExecutionListener.class);
start.setCamundaDelegateExpression("#{EndEventListener}");
start.setCamundaEvent("start");//start||end
CamundaExecutionListener end = this.createElement(extensionElements, "", CamundaExecutionListener.class);
end.setCamundaDelegateExpression("#{EndEventListener}");
end.setCamundaEvent("end");//start||end
endEvent.setExtensionElements(extensionElements);
this.drawBpmnShape(modelInstance, plane, endEvent.getId());// di-平面元素添加节点
//7、处理节点数据-[递归算法]
this.iterate(modelInstance, plane, process, userTask, endEvent, null, JSONUtil.toJsonStr(param.get("processModeel")), userId);
//8、验证模型
Bpmn.validateModel(modelInstance);
//9、转换为xml字符串
String xmlString = Bpmn.convertToString(modelInstance);
log.info(xmlString);
return xmlString;
}
/**
*
* @Description 修改流程定义
* @Return: void
* @Author HeZeMin
* @Date 2022年04月08日 15:54
*/
public String updateExecutableProcess(HashMap<String, Object> param, Long userId) {
ProcessPOJO processPOJO = new ProcessPOJO();
BeanUtil.copyProperties(param.get("process"), processPOJO);
log.info(JSONUtil.toJsonStr(param));
//1、创建一个空的 BPMN 模型实例
BpmnModelInstance modelInstance = Bpmn.createEmptyModel();
//2、创建BPMN定义元素,设置目标名称空间,并将其添加到新创建的模型实例中
Definitions definitions = modelInstance.newInstance(Definitions.class);
definitions.setTargetNamespace("http://camunda.org/examples");
modelInstance.setDefinitions(definitions);
// di-对于图,需要创建一个图和一个平面元素。平面被设置在一个图对象中,图被添加为子元素
BpmnDiagram bpmnDiagram = modelInstance.newInstance(BpmnDiagram.class);
BpmnPlane plane = modelInstance.newInstance(BpmnPlane.class);
bpmnDiagram.setBpmnPlane(plane);
definitions.addChildElement(bpmnDiagram);
//3、创建流程
String procDefKey = processPOJO.getProcDefKey();
Process process = createElement(definitions, procDefKey, Process.class);
process.setName(processPOJO.getProcessName());
process.setExecutable(true);//可执行的流程
// di-平面元素添加process
plane.setBpmnElement(process);
//---业务代码处理start
//修改流程定义
//流程发起人用户全部逻辑删除
//流程发起人角色全部逻辑删除
//保存流程发起人用户
//保存流程发起人角色
//流程节点定义规则全部逻辑删除
//流程节点定义用户规则全部逻辑删除
//流程网关定义规则全部逻辑删除
//流程网关定义条件规则全部逻辑删除
//---业务代码处理end
//4、创建开始事件
StartEvent startEvent = this.createElement(process, CamundaEnum.EVENT.getName() + this.id(), StartEvent.class);
startEvent.setCamundaInitiator("initiator");//发起人
this.drawBpmnShape(modelInstance, plane, startEvent.getId());// di-平面元素添加节点
//5、创建申请人节点
UserTask userTask = this.createElement(process, CamundaEnum.ACTIVITY.getName() + this.id(), UserTask.class);
userTask.setName("发起人");
userTask.setCamundaAssignee("${initiator}");
// di-平面元素添加节点
this.drawBpmnShape(modelInstance, plane, userTask.getId());
// 开始事件连线到申请人节点
SequenceFlow sequenceFlow = this.createSequenceFlow(process, startEvent, userTask);
// di-平面元素添加连线
this.drawBpmnEdge(modelInstance, plane, sequenceFlow.getId());
//6、创建结束事件
EndEvent endEvent = this.createElement(process, CamundaEnum.EVENT.getName() + this.id(), EndEvent.class);
// 结束监听器
ExtensionElements extensionElements = this.createElement(endEvent, "", ExtensionElements.class);
CamundaExecutionListener start = this.createElement(extensionElements, "", CamundaExecutionListener.class);
start.setCamundaDelegateExpression("#{EndEventListener}");
start.setCamundaEvent("start");//start||end
CamundaExecutionListener end = this.createElement(extensionElements, "", CamundaExecutionListener.class);
end.setCamundaDelegateExpression("#{EndEventListener}");
end.setCamundaEvent("end");//start||end
endEvent.setExtensionElements(extensionElements);
this.drawBpmnShape(modelInstance, plane, endEvent.getId());// di-平面元素添加节点
//7、处理节点数据-递归
this.iterate(modelInstance, plane, process, userTask, endEvent, null, JSONUtil.toJsonStr(param.get("processModeel")), userId);
//8、验证模型
Bpmn.validateModel(modelInstance);
//9、转换为xml字符串
String xmlString = Bpmn.convertToString(modelInstance);
log.info(xmlString);
return xmlString;
}
/**
*迭代器
* @Description 迭代器
* @Param process: 流程DOM对象
* @Param previouEvent: 上一节点DOM对象
* @Param endEvent: 结束事件DOM对象
* @Param conditionMap: 网关条件
* @Param jsonStr: 参数json串
* @Return: void
* @Author HeZeMin
* @Date 2022年04月12日 10:35
*/
public void iterate(BpmnModelInstance modelInstance, BpmnPlane plane, Process process, FlowNode previouEvent, FlowNode endEvent, HashMap<String, String> conditionMap, String jsonStr, Long userId) {
JSONObject jsonObject = JSONUtil.parseObj(jsonStr);
process.getId();
if (ObjectUtil.isNotNull(jsonObject) && jsonObject.size() > 0) {
Integer nodeType = jsonObject.get("nodeType", Integer.class);
if (1 == nodeType || 2 == nodeType) {// 1=审批人,2=执行人
Integer auditType = jsonObject.get("auditType", Integer.class);
Integer auditMethod = jsonObject.get("auditMethod", Integer.class);
Integer isAdminAudit = jsonObject.get("isAdminAudit", Integer.class);
String dataType = jsonObject.get("dataType", String.class);
String nodeName = jsonObject.get("nodeName", String.class);
String dataValue = jsonObject.get("dataValue", String.class);
// 创建用户任务节点
String id = CamundaEnum.ACTIVITY.getName() + this.id();
if (2 == nodeType) {// 执行人额外增加一个属性标识,不然不知道是执行人还是审批人
id = CamundaEnum.ACTIVITY.getName() + "executor_" + this.id();// 执行人标识
}
UserTask userTask = this.createElement(process, id, UserTask.class);
if (2 == nodeType) {
userTask.setName(StrUtil.isBlank(nodeName) ? "执行人" : nodeName);
} else {
userTask.setName(StrUtil.isBlank(nodeName) ? "审批人" : nodeName);
}
userTask.setCamundaAssignee("${assignee}");
// 创建多人签实例
MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = this.createElement(userTask, "", MultiInstanceLoopCharacteristics.class);
//审批人集合参数
multiInstanceLoopCharacteristics.setCamundaCollection("assigneeList_" + id);
//迭代集合
multiInstanceLoopCharacteristics.setCamundaElementVariable("assignee");
//完成条件 已完成数等于实例数
CompletionCondition completionCondition = this.createElement(multiInstanceLoopCharacteristics, "", CompletionCondition.class);
if (0 == auditMethod || 1 == auditMethod) {// 或签
completionCondition.setTextContent("${nrOfCompletedInstances == 1}");
} else if (2 == auditMethod) {// 会签
completionCondition.setTextContent("${nrOfActiveInstances == nrOfInstances}");
} else {
completionCondition.setTextContent("${nrOfActiveInstances == nrOfInstances}");
}
multiInstanceLoopCharacteristics.setCompletionCondition(completionCondition);
// 并行,为true时就是顺序签
if (3 == auditMethod) {
multiInstanceLoopCharacteristics.setSequential(true);
} else {
multiInstanceLoopCharacteristics.setSequential(false);
}
userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
// 站内信和提醒 监听器
ExtensionElements extensionElements = this.createElement(userTask, "", ExtensionElements.class);
CamundaTaskListener create = this.createElement(extensionElements, "", CamundaTaskListener.class);
create.setCamundaDelegateExpression("#{TaskMessageListener}");
create.setCamundaEvent("create");
CamundaTaskListener complete = this.createElement(extensionElements, "", CamundaTaskListener.class);
complete.setCamundaDelegateExpression("#{TaskMessageListener}");
complete.setCamundaEvent("complete");
userTask.setExtensionElements(extensionElements);
// di-平面元素添加节点
this.drawBpmnShape(modelInstance, plane, userTask.getId());
//--相关数据存入数据库start
//保存节点
//保存节点对应的数据
//--相关数据存入数据库end
JSONArray nextNodeDataList = (JSONArray) jsonObject.get("nextNodeData");
if (CollUtil.isNotEmpty(nextNodeDataList)) {//有下一个节点
SequenceFlow sequenceFlow = this.createSequenceFlow(process, previouEvent, userTask, conditionMap);
// di-平面元素添加连线
this.drawBpmnEdge(modelInstance, plane, sequenceFlow.getId());
this.iterate(modelInstance, plane, process, userTask, endEvent, null, JSONUtil.toJsonStr(nextNodeDataList.get(0)), userId);
} else {// 没有下一个节点了,连线结束事件
SequenceFlow sequenceFlow = this.createSequenceFlow(process, previouEvent, userTask, conditionMap);
SequenceFlow sequenceFlow1 = this.createSequenceFlow(process, userTask, endEvent);
// di-平面元素添加连线
this.drawBpmnEdge(modelInstance, plane, sequenceFlow.getId());
// di-平面元素添加连线
this.drawBpmnEdge(modelInstance, plane, sequenceFlow1.getId());
}
} else if (3 == nodeType) {// 3=抄送人
Integer auditType = jsonObject.get("auditType", Integer.class);
Integer auditMethod = jsonObject.get("auditMethod", Integer.class);
Integer isAdminAudit = jsonObject.get("isAdminAudit", Integer.class);
String dataType = jsonObject.get("dataType", String.class);
String dataValue = jsonObject.get("dataValue", String.class);
String nodeName = jsonObject.get("nodeName", String.class);
// 创建用户任务节点
String id = CamundaEnum.ACTIVITY.getName() + "copy_" + this.id();
UserTask userTask = this.createElement(process, id, UserTask.class);
userTask.setName(StrUtil.isBlank(nodeName) ? "抄送人" : nodeName);
// 抄送监听器
ExtensionElements extensionElements = this.createElement(userTask, "", ExtensionElements.class);
CamundaTaskListener create = this.createElement(extensionElements, "", CamundaTaskListener.class);
create.setCamundaDelegateExpression("#{CopyListener}");
create.setCamundaEvent("create");
CamundaTaskListener complete = this.createElement(extensionElements, "", CamundaTaskListener.class);
complete.setCamundaDelegateExpression("#{CopyListener}");
complete.setCamundaEvent("complete");
userTask.setExtensionElements(extensionElements);
// di-平面元素添加节点
this.drawBpmnShape(modelInstance, plane, userTask.getId());
//--相关数据存入数据库
//保存节点
//保存节点对应的数据
//--相关数据存入数据库
JSONArray nextNodeDataList = (JSONArray) jsonObject.get("nextNodeData");
if (CollUtil.isNotEmpty(nextNodeDataList)) {//有下一个节点
SequenceFlow sequenceFlow = this.createSequenceFlow(process, previouEvent, userTask, conditionMap);
// di-平面元素添加连线
this.drawBpmnEdge(modelInstance, plane, sequenceFlow.getId());
this.iterate(modelInstance, plane, process, userTask, endEvent, null, JSONUtil.toJsonStr(nextNodeDataList.get(0)), userId);
} else {// 没有下一个节点了,连线结束事件
SequenceFlow sequenceFlow = this.createSequenceFlow(process, previouEvent, userTask, conditionMap);
SequenceFlow sequenceFlow1 = this.createSequenceFlow(process, userTask, endEvent);
// di-平面元素添加连线
this.drawBpmnEdge(modelInstance, plane, sequenceFlow.getId());
// di-平面元素添加连线
this.drawBpmnEdge(modelInstance, plane, sequenceFlow1.getId());
}
} else if (4 == nodeType){// 4=条件分支,只有网关才会有下一节点数据和条件判断数据同时出现的情况
String nodeName = jsonObject.get("nodeName", String.class);
// 创建网关
String id = CamundaEnum.GATEWAY.getName() + this.id();
// 专属网关,直走一个条件
ExclusiveGateway gateway = this.createElement(process, id, ExclusiveGateway.class);
// 并行网关,所有条件都走
// ParallelGateway gateway = createElement(process, id, ParallelGateway.class);
SequenceFlow sequenceFlow = this.createSequenceFlow(process, previouEvent, gateway, conditionMap);
// di-平面元素添加节点
this.drawBpmnShape(modelInstance, plane, gateway.getId());
// di-平面元素添加连线
this.drawBpmnEdge(modelInstance, plane, sequenceFlow.getId());
//--相关数据存入数据库start
// 保存网关节点
//--相关数据存入数据库end
// 条件判断集合
JSONArray conditionList = (JSONArray) jsonObject.get("conditionList");
Iterator<Object> iterator = conditionList.iterator();
while (iterator.hasNext()) {
JSONObject condition = (JSONObject) iterator.next();
//--相关数据存入数据库start
// 保存网关节点条件判断
//--相关数据存入数据库end
// 网关表达式
StringBuilder textContent = new StringBuilder();
textContent.append("${");
if (StrUtil.isNotBlank(condition.get("conditionKey_", String.class))) {//两个条件
textContent.append("(");
if (StrUtil.contains("区间", condition.get("operator", String.class))) {
textContent.append(condition.get("targetValue1", String.class) + condition.get("targetValue1Operator", String.class) + condition.get("conditionKey", String.class))
.append(" && ")
.append(condition.get("conditionKey", String.class) + condition.get("targetValue2Operator", String.class) + condition.get("targetValue2", String.class));
} else if (StrUtil.contains("包含", condition.get("operator", String.class))) {
List<String> stringList = StrUtil.split(condition.get("targetValue", String.class), ",");
for (int i = 0; i < stringList.size(); i++) {
String targetValue = stringList.get(i);
if (i == 0) {
textContent.append(condition.get("conditionKey", String.class) + " == " + targetValue);
} else {
textContent.append(" || ");
textContent.append(condition.get("conditionKey", String.class) + " == " + targetValue);
}
}
} else if (StrUtil.contains("不包含", condition.get("operator", String.class))) {
List<String> stringList = StrUtil.split(condition.get("targetValue", String.class), ",");
for (int i = 0; i < stringList.size(); i++) {
String targetValue = stringList.get(i);
if (i == 0) {
textContent.append(condition.get("conditionKey", String.class) + " != " + targetValue);
} else {
textContent.append(" && ");
textContent.append(condition.get("conditionKey", String.class) + " != " + targetValue);
}
}
} else {
textContent.append(condition.get("conditionKey", String.class) + condition.get("operator", String.class) + condition.get("targetValue", String.class));
}
textContent.append(") && (");
if (StrUtil.contains("区间", condition.get("operator_", String.class))) {
textContent.append(condition.get("targetValue1_", String.class) + condition.get("targetValue1Operator_", String.class) + condition.get("conditionKey_", String.class))
.append(" && ")
.append(condition.get("conditionKey_", String.class) + condition.get("targetValue2Operator_", String.class) + condition.get("targetValue2_", String.class));
} else if (StrUtil.contains("包含", condition.get("operator_", String.class))) {
List<String> stringList = StrUtil.split(condition.get("targetValue_", String.class), ",");
for (int i = 0; i < stringList.size(); i++) {
String targetValue = stringList.get(i);
if (i == 0) {
textContent.append(condition.get("conditionKey_", String.class) + " == " + targetValue);
} else {
textContent.append(" || ");
textContent.append(condition.get("conditionKey_", String.class) + " == " + targetValue);
}
}
} else if (StrUtil.contains("不包含", condition.get("operator_", String.class))) {
List<String> stringList = StrUtil.split(condition.get("targetValue_", String.class), ",");
for (int i = 0; i < stringList.size(); i++) {
String targetValue = stringList.get(i);
if (i == 0) {
textContent.append(condition.get("conditionKey_", String.class) + " != " + targetValue);
} else {
textContent.append(" && ");
textContent.append(condition.get("conditionKey_", String.class) + " != " + targetValue);
}
}
} else {
textContent.append(condition.get("conditionKey_", String.class) + condition.get("operator_", String.class) + condition.get("targetValue_", String.class));
}
textContent.append(")");
} else {// 一个条件
if (StrUtil.contains("区间", condition.get("operator", String.class))) {
textContent.append(condition.get("targetValue1", String.class) + condition.get("targetValue1Operator", String.class) + condition.get("conditionKey", String.class))
.append(" && ")
.append(condition.get("conditionKey", String.class) + condition.get("targetValue2Operator", String.class) + condition.get("targetValue2", String.class));
} else if (StrUtil.contains("包含", condition.get("operator", String.class))) {
List<String> stringList = StrUtil.split(condition.get("targetValue", String.class), ",");
for (int i = 0; i < stringList.size(); i++) {
String targetValue = stringList.get(i);
if (i == 0) {
textContent.append(condition.get("conditionKey", String.class) + " == " + targetValue);
} else {
textContent.append(" || ");
textContent.append(condition.get("conditionKey", String.class) + " == " + targetValue);
}
}
} else if (StrUtil.contains("不包含", condition.get("operator", String.class))) {
List<String> stringList = StrUtil.split(condition.get("targetValue", String.class), ",");
for (int i = 0; i < stringList.size(); i++) {
String targetValue = stringList.get(i);
if (i == 0) {
textContent.append(condition.get("conditionKey", String.class) + " != " + targetValue);
} else {
textContent.append(" && ");
textContent.append(condition.get("conditionKey", String.class) + " != " + targetValue);
}
}
} else {
textContent.append(condition.get("conditionKey", String.class) + condition.get("operator", String.class) + condition.get("targetValue", String.class));
}
}
textContent.append("}");
JSONArray nextNodeDataList = (JSONArray) condition.get("nextNodeData");
if (CollUtil.isNotEmpty(nextNodeDataList)) {//有下一个节点
String conditionName = condition.get("conditionName", String.class);
HashMap<String, String> map = new HashMap<>();
map.put("name", StrUtil.isBlank(conditionName) ? textContent.toString() : conditionName);
map.put("type", "");
map.put("textContent", textContent.toString());
this.iterate(modelInstance, plane, process, gateway, endEvent, map, JSONUtil.toJsonStr(nextNodeDataList.get(0)), userId);
} else {
SequenceFlow sequenceFlow1 = this.createSequenceFlow(process, gateway, endEvent);
// di-平面元素添加连线
this.drawBpmnEdge(modelInstance, plane, sequenceFlow1.getId());
// 一下注释代码暂时用不到,勿删
// 网关的下一个节点,不是条件下的
// JSONArray gatewayNnextNodeDataList = (JSONArray) jsonObject.get("nextNodeData");
// if (CollUtil.isNotEmpty(gatewayNnextNodeDataList)) {//有下一个节点
// this.createSequenceFlow(process, startEvent, gateway, conditionMap);
// this.iterate(process, gateway, endEvent, null, JSONUtil.toJsonStr(gatewayNnextNodeDataList.get(0)));
// } else {// 没有下一个节点了,连线结束事件
// this.createSequenceFlow(process, gateway, endEvent, conditionMap);
// }
}
}
}
} else {
// 开始事件连线到结束事件
SequenceFlow sequenceFlow = this.createSequenceFlow(process, previouEvent, endEvent);
// di-平面元素添加连线
this.drawBpmnEdge(modelInstance, plane, sequenceFlow.getId());
}
}
/**
* Description:id生成器
* @Author HeZeMin
* @Date