mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-19 03:30:06 +08:00
仿钉钉流程设计- code review 修改。扩展属性保存在 extensionElement 尝试
This commit is contained in:
parent
1e97ca282b
commit
9456d461f9
@ -18,20 +18,17 @@ import java.util.Objects;
|
|||||||
public enum BpmSimpleModelNodeType implements IntArrayValuable {
|
public enum BpmSimpleModelNodeType implements IntArrayValuable {
|
||||||
|
|
||||||
// TODO @jaosn:-1、0、1、4、-2 是前端已经定义好的么?感觉未来可以考虑搞成和 BPMN 尽量一致的单词哈;类似 usertask 用户审批;
|
// TODO @jaosn:-1、0、1、4、-2 是前端已经定义好的么?感觉未来可以考虑搞成和 BPMN 尽量一致的单词哈;类似 usertask 用户审批;
|
||||||
// TODO @jason:_NODE 都删除掉哈;
|
START_EVENT(0, "开始节点"),
|
||||||
START_EVENT_NODE(0, "开始节点"),
|
END_EVENT(-2, "结束节点"), // TODO @jaosn:挪到 START_EVENT_NODE 后;
|
||||||
END_EVENT_NODE(-2, "结束节点"), // TODO @jaosn:挪到 START_EVENT_NODE 后;
|
|
||||||
|
|
||||||
APPROVE_USER_NODE(1, "审批人节点"), // TODO @jaosn:是不是这里从 10 开始好点;相当于说,0-9 给开始和结束;10-19 给各种节点;20-29 给各种条件;TODO @jason:改成 USER_TASK 是不是好点呀
|
USER_TASK(1, "审批人节点"), // TODO @jaosn:是不是这里从 10 开始好点;相当于说,0-9 给开始和结束;10-19 给各种节点;20-29 给各种条件; TODO 后面改改
|
||||||
// 抄送人节点、对应 BPMN 的 ScriptTask. 使用ScriptTask 原因。好像 ServiceTask 自定义属性不能写入 XML;
|
COPY_TASK(2, "抄送人节点"),
|
||||||
// TODO @jason:ServiceTask 自定义 xml,有没啥报错信息;
|
|
||||||
SCRIPT_TASK_NODE(2, "抄送人节点"), // TODO @jason:是不是改成 COPY_TASK 好一点哈;
|
|
||||||
|
|
||||||
EXCLUSIVE_GATEWAY_NODE(4, "排他网关"), // TODO @jason:是不是改成叫 条件分支?
|
EXCLUSIVE_GATEWAY(4, "排他网关"), // TODO @jason:是不是改成叫 条件分支?
|
||||||
PARALLEL_GATEWAY_FORK_NODE(5, "并行网关分叉节点"), // TODO @jason:是不是一个 并行分支 ?就可以啦?
|
PARALLEL_GATEWAY_FORK(5, "并行网关分叉节点"), // TODO @jason:是不是一个 并行分支 ?就可以啦? 后面是否去掉并行网关。只用包容网关
|
||||||
PARALLEL_GATEWAY_JOIN_NODE(6, "并行网关聚合节点"),
|
PARALLEL_GATEWAY_JOIN(6, "并行网关聚合节点"),
|
||||||
INCLUSIVE_GATEWAY_FORK_NODE(7, "包容网关分叉节点"),
|
INCLUSIVE_GATEWAY_FORK(7, "包容网关分叉节点"),
|
||||||
INCLUSIVE_GATEWAY_JOIN_NODE(8, "包容网关聚合节点"),
|
INCLUSIVE_GATEWAY_JOIN(8, "包容网关聚合节点"),
|
||||||
;
|
;
|
||||||
|
|
||||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmSimpleModelNodeType::getType).toArray();
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmSimpleModelNodeType::getType).toArray();
|
||||||
@ -39,9 +36,13 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable {
|
|||||||
private final Integer type;
|
private final Integer type;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
public static boolean isGatewayNode(Integer type) {
|
/**
|
||||||
return Objects.equals(EXCLUSIVE_GATEWAY_NODE.getType(), type) || Objects.equals(PARALLEL_GATEWAY_FORK_NODE.getType(), type)
|
* 判断是否为分支节点
|
||||||
|| Objects.equals(INCLUSIVE_GATEWAY_FORK_NODE.getType(), type) ;
|
* @param type 节点类型
|
||||||
|
*/
|
||||||
|
public static boolean isBranchNode(Integer type) {
|
||||||
|
return Objects.equals(EXCLUSIVE_GATEWAY.getType(), type) || Objects.equals(PARALLEL_GATEWAY_FORK.getType(), type)
|
||||||
|
|| Objects.equals(INCLUSIVE_GATEWAY_FORK.getType(), type) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BpmSimpleModelNodeType valueOf(Integer type) {
|
public static BpmSimpleModelNodeType valueOf(Integer type) {
|
||||||
|
@ -1,43 +1,41 @@
|
|||||||
package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
|
||||||
import cn.hutool.core.map.MapUtil;
|
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelNodeVO;
|
|
||||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType;
|
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
|
||||||
import org.flowable.bpmn.BpmnAutoLayout;
|
|
||||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||||
import org.flowable.bpmn.model.Process;
|
import org.flowable.bpmn.model.Process;
|
||||||
import org.flowable.bpmn.model.*;
|
import org.flowable.bpmn.model.*;
|
||||||
import org.flowable.common.engine.impl.scripting.ScriptingEngines;
|
|
||||||
import org.flowable.common.engine.impl.util.io.BytesStreamSource;
|
import org.flowable.common.engine.impl.util.io.BytesStreamSource;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.flowable.bpmn.constants.BpmnXMLConstants.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 流程模型转操作工具类
|
* 流程模型转操作工具类
|
||||||
*/
|
*/
|
||||||
public class BpmnModelUtils {
|
public class BpmnModelUtils {
|
||||||
|
|
||||||
public static final String BPMN_SIMPLE_COPY_EXECUTION_SCRIPT = "#{bpmSimpleNodeService.copy(execution)}";
|
|
||||||
|
|
||||||
public static Integer parseCandidateStrategy(FlowElement userTask) {
|
public static Integer parseCandidateStrategy(FlowElement userTask) {
|
||||||
return NumberUtils.parseInt(userTask.getAttributeValue(
|
Integer candidateStrategy = NumberUtils.parseInt(userTask.getAttributeValue(
|
||||||
BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY));
|
BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY));
|
||||||
|
// @芋艿 尝试从 ExtensionElement 取. 后续相关扩展是否都可以 存 extensionElement。 如表单权限。 按钮权限
|
||||||
|
if (candidateStrategy == null) {
|
||||||
|
ExtensionElement element = CollUtil.getFirst(userTask.getExtensionElements().get(BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY));
|
||||||
|
candidateStrategy = NumberUtils.parseInt(Optional.ofNullable(element).map(ExtensionElement::getElementText).orElse(null));
|
||||||
|
|
||||||
|
}
|
||||||
|
return candidateStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String parseCandidateParam(FlowElement userTask) {
|
public static String parseCandidateParam(FlowElement userTask) {
|
||||||
return userTask.getAttributeValue(
|
String candidateParam = userTask.getAttributeValue(
|
||||||
BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM);
|
BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM);
|
||||||
|
if (candidateParam == null) {
|
||||||
|
ExtensionElement element = CollUtil.getFirst(userTask.getExtensionElements().get(BpmnModelConstants.USER_TASK_CANDIDATE_PARAM));
|
||||||
|
candidateParam = Optional.ofNullable(element).map(ExtensionElement::getElementText).orElse(null);
|
||||||
|
}
|
||||||
|
return candidateParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -339,231 +337,4 @@ public class BpmnModelUtils {
|
|||||||
}
|
}
|
||||||
return userTaskList;
|
return userTaskList;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== TODO @jason:单独出一个 SimpleModelUtils;定位上,它是 BPMN 的精简模式 ==========
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善)
|
|
||||||
*
|
|
||||||
* @param processId 流程标识
|
|
||||||
* @param processName 流程名称
|
|
||||||
* @param simpleModelNode 仿钉钉流程设计模型数据结构
|
|
||||||
* @return Bpmn Model
|
|
||||||
*/
|
|
||||||
public static BpmnModel convertSimpleModelToBpmnModel(String processId, String processName, BpmSimpleModelNodeVO simpleModelNode) {
|
|
||||||
BpmnModel bpmnModel = new BpmnModel();
|
|
||||||
Process mainProcess = new Process();
|
|
||||||
mainProcess.setId(processId);
|
|
||||||
mainProcess.setName(processName);
|
|
||||||
mainProcess.setExecutable(Boolean.TRUE);
|
|
||||||
bpmnModel.addProcess(mainProcess);
|
|
||||||
// 前端模型数据结构。 有 start event 节点. 没有 end event 节点。
|
|
||||||
// 添加 FlowNode
|
|
||||||
addBpmnFlowNode(mainProcess, simpleModelNode);
|
|
||||||
// 单独添加 end event 节点
|
|
||||||
addBpmnEndEventNode(mainProcess);
|
|
||||||
// 添加节点之间的连线 Sequence Flow
|
|
||||||
addBpmnSequenceFlow(mainProcess, simpleModelNode, BpmnModelConstants.END_EVENT_ID);
|
|
||||||
// 自动布局
|
|
||||||
new BpmnAutoLayout(bpmnModel).execute();
|
|
||||||
return bpmnModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addBpmnSequenceFlow(Process mainProcess, BpmSimpleModelNodeVO node, String endId) {
|
|
||||||
// 节点为 null 退出
|
|
||||||
if (node == null || node.getId() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BpmSimpleModelNodeVO childNode = node.getChildNode();
|
|
||||||
// 如果不是网关节点、且后续节点为 null. 添加与结束节点的连线
|
|
||||||
if (!BpmSimpleModelNodeType.isGatewayNode(node.getType()) && (childNode == null || childNode.getId() == null)) {
|
|
||||||
addBpmnSequenceFlowElement(mainProcess, node.getId(), endId, null, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType());
|
|
||||||
Assert.notNull(nodeType, "模型节点类型不支持");
|
|
||||||
// TODO @jason:建议是,addXXX 都改成 buildXXX,构建出一个什么;然后返回之后,让这个方法添加到自己的结果里;
|
|
||||||
switch (nodeType) {
|
|
||||||
case START_EVENT_NODE:
|
|
||||||
case APPROVE_USER_NODE:
|
|
||||||
case SCRIPT_TASK_NODE:
|
|
||||||
case PARALLEL_GATEWAY_JOIN_NODE:
|
|
||||||
case INCLUSIVE_GATEWAY_JOIN_NODE:{
|
|
||||||
addBpmnSequenceFlowElement(mainProcess, node.getId(), childNode.getId(), null, null);
|
|
||||||
// 递归调用后续节点
|
|
||||||
addBpmnSequenceFlow(mainProcess, childNode, endId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PARALLEL_GATEWAY_FORK_NODE:
|
|
||||||
case EXCLUSIVE_GATEWAY_NODE:
|
|
||||||
case INCLUSIVE_GATEWAY_FORK_NODE:{
|
|
||||||
String gateWayEndId = (childNode == null || childNode.getId() == null) ? BpmnModelConstants.END_EVENT_ID : childNode.getId();
|
|
||||||
List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes();
|
|
||||||
Assert.notEmpty(conditionNodes, "网关节点的条件节点不能为空");
|
|
||||||
for (int i = 0; i < conditionNodes.size(); i++) {
|
|
||||||
BpmSimpleModelNodeVO item = conditionNodes.get(i);
|
|
||||||
BpmSimpleModelNodeVO nextNodeOnCondition = item.getChildNode();
|
|
||||||
if (nextNodeOnCondition != null && nextNodeOnCondition.getId() != null) {
|
|
||||||
addBpmnSequenceFlowElement(mainProcess, node.getId(), nextNodeOnCondition.getId(),
|
|
||||||
String.format("%s_SequenceFlow_%d", node.getId(), i + 1), null);
|
|
||||||
addBpmnSequenceFlow(mainProcess, nextNodeOnCondition, gateWayEndId);
|
|
||||||
} else {
|
|
||||||
addBpmnSequenceFlowElement(mainProcess, node.getId(), gateWayEndId,
|
|
||||||
String.format("%s_SequenceFlow_%d", node.getId(), i + 1), null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 递归调用后续节点
|
|
||||||
addBpmnSequenceFlow(mainProcess, childNode, endId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
// TODO 其它节点类型的实现
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addBpmnSequenceFlowElement(Process mainProcess, String sourceId, String targetId, String seqFlowId, String conditionExpression) {
|
|
||||||
SequenceFlow sequenceFlow = new SequenceFlow(sourceId, targetId);
|
|
||||||
if (StrUtil.isNotEmpty(conditionExpression)) {
|
|
||||||
sequenceFlow.setConditionExpression(conditionExpression);
|
|
||||||
}
|
|
||||||
if (StrUtil.isNotEmpty(seqFlowId)) {
|
|
||||||
sequenceFlow.setId(seqFlowId);
|
|
||||||
}
|
|
||||||
mainProcess.addFlowElement(sequenceFlow);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addBpmnFlowNode(Process mainProcess, BpmSimpleModelNodeVO simpleModelNode) {
|
|
||||||
// 节点为 null 退出
|
|
||||||
if (simpleModelNode == null || simpleModelNode.getId() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType());
|
|
||||||
Assert.notNull(nodeType, "模型节点类型不支持");
|
|
||||||
switch (nodeType) {
|
|
||||||
case START_EVENT_NODE:
|
|
||||||
addBpmnStartEventNode(mainProcess, simpleModelNode);
|
|
||||||
break;
|
|
||||||
case APPROVE_USER_NODE:
|
|
||||||
addBpmnUserTaskNode(mainProcess, simpleModelNode);
|
|
||||||
break;
|
|
||||||
case SCRIPT_TASK_NODE:
|
|
||||||
addBpmnScriptTaSskNode(mainProcess, simpleModelNode);
|
|
||||||
break;
|
|
||||||
case EXCLUSIVE_GATEWAY_NODE:
|
|
||||||
addBpmnExclusiveGatewayNode(mainProcess, simpleModelNode);
|
|
||||||
break;
|
|
||||||
case PARALLEL_GATEWAY_FORK_NODE:
|
|
||||||
case PARALLEL_GATEWAY_JOIN_NODE:
|
|
||||||
addBpmnParallelGatewayNode(mainProcess, simpleModelNode);
|
|
||||||
break;
|
|
||||||
case INCLUSIVE_GATEWAY_FORK_NODE:
|
|
||||||
addBpmnInclusiveGatewayNode(mainProcess, simpleModelNode, Boolean.TRUE);
|
|
||||||
break;
|
|
||||||
case INCLUSIVE_GATEWAY_JOIN_NODE:
|
|
||||||
addBpmnInclusiveGatewayNode(mainProcess, simpleModelNode, Boolean.FALSE);
|
|
||||||
break;
|
|
||||||
default: {
|
|
||||||
// TODO 其它节点类型的实现
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果不是网关类型的接口, 并且chileNode为空退出
|
|
||||||
if (!BpmSimpleModelNodeType.isGatewayNode(simpleModelNode.getType()) && simpleModelNode.getChildNode() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果是网关类型接口. 递归添加条件节点
|
|
||||||
if (BpmSimpleModelNodeType.isGatewayNode(simpleModelNode.getType()) && ArrayUtil.isNotEmpty(simpleModelNode.getConditionNodes())) {
|
|
||||||
for (BpmSimpleModelNodeVO node : simpleModelNode.getConditionNodes()) {
|
|
||||||
addBpmnFlowNode(mainProcess, node.getChildNode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// chileNode不为空,递归添加子节点
|
|
||||||
if (simpleModelNode.getChildNode() != null) {
|
|
||||||
addBpmnFlowNode(mainProcess, simpleModelNode.getChildNode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addBpmnParallelGatewayNode(Process mainProcess, BpmSimpleModelNodeVO node) {
|
|
||||||
ParallelGateway parallelGateway = new ParallelGateway();
|
|
||||||
parallelGateway.setId(node.getId());
|
|
||||||
mainProcess.addFlowElement(parallelGateway);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addBpmnScriptTaSskNode(Process mainProcess, BpmSimpleModelNodeVO node) {
|
|
||||||
ScriptTask scriptTask = new ScriptTask();
|
|
||||||
scriptTask.setId(node.getId());
|
|
||||||
scriptTask.setName(node.getName());
|
|
||||||
// TODO @jason:建议使用 ServiceTask,通过 executionListeners 实现;
|
|
||||||
scriptTask.setScriptFormat(ScriptingEngines.DEFAULT_SCRIPTING_LANGUAGE);
|
|
||||||
scriptTask.setScript(BPMN_SIMPLE_COPY_EXECUTION_SCRIPT);
|
|
||||||
// 添加自定义属性
|
|
||||||
// TODO @jason:可以使用 ServiceTask 搞 ExtensionAttribute 么?
|
|
||||||
addExtensionAttributes(node, scriptTask);
|
|
||||||
mainProcess.addFlowElement(scriptTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addExtensionAttributes(BpmSimpleModelNodeVO node, FlowElement flowElement) {
|
|
||||||
Integer candidateStrategy = MapUtil.getInt(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY);
|
|
||||||
addExtensionAttributes(flowElement, BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY,
|
|
||||||
candidateStrategy == null ? null : String.valueOf(candidateStrategy));
|
|
||||||
addExtensionAttributes(flowElement, BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM,
|
|
||||||
MapUtil.getStr(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_PARAM));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addBpmnExclusiveGatewayNode(Process mainProcess, BpmSimpleModelNodeVO node) {
|
|
||||||
Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空");
|
|
||||||
ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
|
|
||||||
exclusiveGateway.setId(node.getId());
|
|
||||||
// 网关的最后一个条件为 网关的 default sequence flow
|
|
||||||
exclusiveGateway.setDefaultFlow(String.format("%s_SequenceFlow_%d", node.getId(), node.getConditionNodes().size()));
|
|
||||||
mainProcess.addFlowElement(exclusiveGateway);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addBpmnInclusiveGatewayNode(Process mainProcess, BpmSimpleModelNodeVO node, Boolean isFork) {
|
|
||||||
InclusiveGateway inclusiveGateway = new InclusiveGateway();
|
|
||||||
inclusiveGateway.setId(node.getId());
|
|
||||||
if (isFork) {
|
|
||||||
Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空");
|
|
||||||
// 网关的最后一个条件为 网关的 default sequence flow
|
|
||||||
inclusiveGateway.setDefaultFlow(String.format("%s_SequenceFlow_%d", node.getId(), node.getConditionNodes().size()));
|
|
||||||
}
|
|
||||||
mainProcess.addFlowElement(inclusiveGateway);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addBpmnEndEventNode(Process mainProcess) {
|
|
||||||
EndEvent endEvent = new EndEvent();
|
|
||||||
endEvent.setId(BpmnModelConstants.END_EVENT_ID);
|
|
||||||
endEvent.setName("结束");
|
|
||||||
mainProcess.addFlowElement(endEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addBpmnUserTaskNode(Process mainProcess, BpmSimpleModelNodeVO node) {
|
|
||||||
UserTask userTask = new UserTask();
|
|
||||||
userTask.setId(node.getId());
|
|
||||||
userTask.setName(node.getName());
|
|
||||||
addExtensionAttributes(node, userTask);
|
|
||||||
mainProcess.addFlowElement(userTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addExtensionAttributes(FlowElement element, String namespace, String name, String value) {
|
|
||||||
if (value == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ExtensionAttribute extensionAttribute = new ExtensionAttribute(name, value);
|
|
||||||
extensionAttribute.setNamespace(namespace);
|
|
||||||
extensionAttribute.setNamespacePrefix(FLOWABLE_EXTENSIONS_PREFIX);
|
|
||||||
element.addAttribute(extensionAttribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addBpmnStartEventNode(Process mainProcess, BpmSimpleModelNodeVO node) {
|
|
||||||
StartEvent startEvent = new StartEvent();
|
|
||||||
startEvent.setId(node.getId());
|
|
||||||
startEvent.setName(node.getName());
|
|
||||||
mainProcess.addFlowElement(startEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,270 @@
|
|||||||
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelNodeVO;
|
||||||
|
import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
|
||||||
|
import org.flowable.bpmn.BpmnAutoLayout;
|
||||||
|
import org.flowable.bpmn.model.*;
|
||||||
|
import org.flowable.bpmn.model.Process;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_NAMESPACE;
|
||||||
|
import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_PREFIX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仿钉钉快搭模型相关的工具方法
|
||||||
|
*
|
||||||
|
* @author jason
|
||||||
|
*/
|
||||||
|
public class SimpleModelUtils {
|
||||||
|
|
||||||
|
public static final String BPMN_SIMPLE_COPY_EXECUTION_SCRIPT = "#{bpmSimpleNodeService.copy(execution)}";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善)
|
||||||
|
*
|
||||||
|
* @param processId 流程标识
|
||||||
|
* @param processName 流程名称
|
||||||
|
* @param simpleModelNode 仿钉钉流程设计模型数据结构
|
||||||
|
* @return Bpmn Model
|
||||||
|
*/
|
||||||
|
public static BpmnModel convertSimpleModelToBpmnModel(String processId, String processName, BpmSimpleModelNodeVO simpleModelNode) {
|
||||||
|
BpmnModel bpmnModel = new BpmnModel();
|
||||||
|
Process mainProcess = new Process();
|
||||||
|
mainProcess.setId(processId);
|
||||||
|
mainProcess.setName(processName);
|
||||||
|
mainProcess.setExecutable(Boolean.TRUE);
|
||||||
|
bpmnModel.addProcess(mainProcess);
|
||||||
|
// 前端模型数据结构。 有 start event 节点. 没有 end event 节点。
|
||||||
|
// 从 SimpleModel 构建 FlowNode 并添加到 Main Process
|
||||||
|
buildAndAddBpmnFlowNode(simpleModelNode, mainProcess);
|
||||||
|
// 单独构建 end event 节点
|
||||||
|
buildAndAddBpmnEndEvent(mainProcess);
|
||||||
|
// 构建并添加节点之间的连线 Sequence Flow
|
||||||
|
buildAndAddBpmnSequenceFlow(mainProcess, simpleModelNode, BpmnModelConstants.END_EVENT_ID);
|
||||||
|
// 自动布局
|
||||||
|
new BpmnAutoLayout(bpmnModel).execute();
|
||||||
|
return bpmnModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void buildAndAddBpmnSequenceFlow(Process mainProcess, BpmSimpleModelNodeVO node, String targetId) {
|
||||||
|
// 节点为 null 退出
|
||||||
|
if (node == null || node.getId() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BpmSimpleModelNodeVO childNode = node.getChildNode();
|
||||||
|
// 如果不是网关节点、且后续节点为 null. 添加与结束节点的连线
|
||||||
|
if (!BpmSimpleModelNodeType.isBranchNode(node.getType()) && (childNode == null || childNode.getId() == null)) {
|
||||||
|
SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), targetId, null, null);
|
||||||
|
mainProcess.addFlowElement(sequenceFlow);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType());
|
||||||
|
Assert.notNull(nodeType, "模型节点类型不支持");
|
||||||
|
switch (nodeType) {
|
||||||
|
case START_EVENT:
|
||||||
|
case USER_TASK:
|
||||||
|
case COPY_TASK:
|
||||||
|
case PARALLEL_GATEWAY_JOIN:
|
||||||
|
case INCLUSIVE_GATEWAY_JOIN:{
|
||||||
|
SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), childNode.getId(), null, null);
|
||||||
|
mainProcess.addFlowElement(sequenceFlow);
|
||||||
|
// 递归调用后续节点
|
||||||
|
buildAndAddBpmnSequenceFlow(mainProcess, childNode, targetId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PARALLEL_GATEWAY_FORK:
|
||||||
|
case EXCLUSIVE_GATEWAY:
|
||||||
|
case INCLUSIVE_GATEWAY_FORK:{
|
||||||
|
String sequenceFlowTargetId = (childNode == null || childNode.getId() == null) ? BpmnModelConstants.END_EVENT_ID : childNode.getId();
|
||||||
|
List<BpmSimpleModelNodeVO> conditionNodes = node.getConditionNodes();
|
||||||
|
Assert.notEmpty(conditionNodes, "网关节点的条件节点不能为空");
|
||||||
|
for (int i = 0; i < conditionNodes.size(); i++) {
|
||||||
|
BpmSimpleModelNodeVO item = conditionNodes.get(i);
|
||||||
|
BpmSimpleModelNodeVO nextNodeOnCondition = item.getChildNode();
|
||||||
|
if (nextNodeOnCondition != null && nextNodeOnCondition.getId() != null) {
|
||||||
|
SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), nextNodeOnCondition.getId(),
|
||||||
|
String.format("%s_SequenceFlow_%d", node.getId(), i + 1), null);
|
||||||
|
mainProcess.addFlowElement(sequenceFlow);
|
||||||
|
// 递归调用后续节点
|
||||||
|
buildAndAddBpmnSequenceFlow(mainProcess, nextNodeOnCondition, sequenceFlowTargetId);
|
||||||
|
} else {
|
||||||
|
SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), sequenceFlowTargetId,
|
||||||
|
String.format("%s_SequenceFlow_%d", node.getId(), i + 1), null);
|
||||||
|
mainProcess.addFlowElement(sequenceFlow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 递归调用后续节点
|
||||||
|
buildAndAddBpmnSequenceFlow(mainProcess, childNode, targetId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// TODO 其它节点类型的实现
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SequenceFlow buildBpmnSequenceFlow(String sourceId, String targetId, String seqFlowId, String conditionExpression) {
|
||||||
|
SequenceFlow sequenceFlow = new SequenceFlow(sourceId, targetId);
|
||||||
|
if (StrUtil.isNotEmpty(conditionExpression)) {
|
||||||
|
sequenceFlow.setConditionExpression(conditionExpression);
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotEmpty(seqFlowId)) {
|
||||||
|
sequenceFlow.setId(seqFlowId);
|
||||||
|
}
|
||||||
|
return sequenceFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void buildAndAddBpmnFlowNode(BpmSimpleModelNodeVO simpleModelNode, Process mainProcess) {
|
||||||
|
// 节点为 null 退出
|
||||||
|
if (simpleModelNode == null || simpleModelNode.getId() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType());
|
||||||
|
Assert.notNull(nodeType, "模型节点类型不支持");
|
||||||
|
switch (nodeType) {
|
||||||
|
case START_EVENT: {
|
||||||
|
StartEvent startEvent = buildBpmnStartEvent(simpleModelNode);
|
||||||
|
mainProcess.addFlowElement(startEvent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case USER_TASK: {
|
||||||
|
UserTask userTask = buildBpmnUserTask(simpleModelNode);
|
||||||
|
mainProcess.addFlowElement(userTask);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case COPY_TASK: {
|
||||||
|
ServiceTask serviceTask = buildBpmnServiceTask(simpleModelNode);
|
||||||
|
mainProcess.addFlowElement(serviceTask);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EXCLUSIVE_GATEWAY: {
|
||||||
|
ExclusiveGateway exclusiveGateway = buildBpmnExclusiveGateway(simpleModelNode);
|
||||||
|
mainProcess.addFlowElement(exclusiveGateway);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PARALLEL_GATEWAY_FORK:
|
||||||
|
case PARALLEL_GATEWAY_JOIN: {
|
||||||
|
ParallelGateway parallelGateway = buildBpmnParallelGateway(simpleModelNode);
|
||||||
|
mainProcess.addFlowElement(parallelGateway);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INCLUSIVE_GATEWAY_FORK: {
|
||||||
|
InclusiveGateway inclusiveGateway = buildBpmnInclusiveGateway(simpleModelNode, Boolean.TRUE);
|
||||||
|
mainProcess.addFlowElement(inclusiveGateway);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case INCLUSIVE_GATEWAY_JOIN: {
|
||||||
|
InclusiveGateway inclusiveGateway = buildBpmnInclusiveGateway(simpleModelNode, Boolean.FALSE);
|
||||||
|
mainProcess.addFlowElement(inclusiveGateway);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// TODO 其它节点类型的实现
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果不是网关类型的接口, 并且chileNode为空退出
|
||||||
|
if (!BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType()) && simpleModelNode.getChildNode() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是网关类型接口. 递归添加条件节点
|
||||||
|
if (BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType()) && ArrayUtil.isNotEmpty(simpleModelNode.getConditionNodes())) {
|
||||||
|
for (BpmSimpleModelNodeVO node : simpleModelNode.getConditionNodes()) {
|
||||||
|
buildAndAddBpmnFlowNode(node.getChildNode(), mainProcess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// chileNode不为空,递归添加子节点
|
||||||
|
if (simpleModelNode.getChildNode() != null) {
|
||||||
|
buildAndAddBpmnFlowNode(simpleModelNode.getChildNode(), mainProcess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ParallelGateway buildBpmnParallelGateway(BpmSimpleModelNodeVO node) {
|
||||||
|
ParallelGateway parallelGateway = new ParallelGateway();
|
||||||
|
parallelGateway.setId(node.getId());
|
||||||
|
return parallelGateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServiceTask buildBpmnServiceTask(BpmSimpleModelNodeVO node) {
|
||||||
|
ServiceTask serviceTask = new ServiceTask();
|
||||||
|
serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
|
||||||
|
serviceTask.setImplementation(BPMN_SIMPLE_COPY_EXECUTION_SCRIPT);
|
||||||
|
serviceTask.setId(node.getId());
|
||||||
|
serviceTask.setName(node.getName());
|
||||||
|
// TODO @jason:建议使用 ServiceTask,通过 executionListeners 实现;
|
||||||
|
// @芋艿 ServiceTask 就可以了吧。 不需要 executionListeners
|
||||||
|
addExtensionElement(node, serviceTask);
|
||||||
|
return serviceTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addExtensionElement(BpmSimpleModelNodeVO node, FlowElement flowElement) {
|
||||||
|
Integer candidateStrategy = MapUtil.getInt(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY);
|
||||||
|
addExtensionElement(flowElement, FLOWABLE_EXTENSIONS_NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY,
|
||||||
|
candidateStrategy == null ? null : String.valueOf(candidateStrategy));
|
||||||
|
addExtensionElement(flowElement, FLOWABLE_EXTENSIONS_NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM,
|
||||||
|
MapUtil.getStr(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_PARAM));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ExclusiveGateway buildBpmnExclusiveGateway(BpmSimpleModelNodeVO node) {
|
||||||
|
Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空");
|
||||||
|
ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
|
||||||
|
exclusiveGateway.setId(node.getId());
|
||||||
|
// 网关的最后一个条件为 网关的 default sequence flow
|
||||||
|
exclusiveGateway.setDefaultFlow(String.format("%s_SequenceFlow_%d", node.getId(), node.getConditionNodes().size()));
|
||||||
|
return exclusiveGateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InclusiveGateway buildBpmnInclusiveGateway(BpmSimpleModelNodeVO node, Boolean isFork) {
|
||||||
|
InclusiveGateway inclusiveGateway = new InclusiveGateway();
|
||||||
|
inclusiveGateway.setId(node.getId());
|
||||||
|
if (isFork) {
|
||||||
|
Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空");
|
||||||
|
// 网关的最后一个条件为 网关的 default sequence flow
|
||||||
|
inclusiveGateway.setDefaultFlow(String.format("%s_SequenceFlow_%d", node.getId(), node.getConditionNodes().size()));
|
||||||
|
}
|
||||||
|
return inclusiveGateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void buildAndAddBpmnEndEvent(Process mainProcess) {
|
||||||
|
EndEvent endEvent = new EndEvent();
|
||||||
|
endEvent.setId(BpmnModelConstants.END_EVENT_ID);
|
||||||
|
endEvent.setName("结束");
|
||||||
|
mainProcess.addFlowElement(endEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UserTask buildBpmnUserTask(BpmSimpleModelNodeVO node) {
|
||||||
|
UserTask userTask = new UserTask();
|
||||||
|
userTask.setId(node.getId());
|
||||||
|
userTask.setName(node.getName());
|
||||||
|
addExtensionElement(node, userTask);
|
||||||
|
return userTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addExtensionElement(FlowElement element, String namespace, String name, String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ExtensionElement extensionElement = new ExtensionElement();
|
||||||
|
extensionElement.setNamespace(namespace);
|
||||||
|
extensionElement.setNamespacePrefix(FLOWABLE_EXTENSIONS_PREFIX);
|
||||||
|
extensionElement.setElementText(value);
|
||||||
|
extensionElement.setName(name);
|
||||||
|
element.addExtensionElement(extensionElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StartEvent buildBpmnStartEvent(BpmSimpleModelNodeVO node) {
|
||||||
|
StartEvent startEvent = new StartEvent();
|
||||||
|
startEvent.setId(node.getId());
|
||||||
|
startEvent.setName(node.getName());
|
||||||
|
return startEvent;
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimp
|
|||||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType;
|
import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.flowable.bpmn.model.*;
|
import org.flowable.bpmn.model.*;
|
||||||
import org.flowable.engine.repository.Model;
|
import org.flowable.engine.repository.Model;
|
||||||
@ -22,7 +23,7 @@ import java.util.Map;
|
|||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT;
|
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT;
|
||||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.MODEL_NOT_EXISTS;
|
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.MODEL_NOT_EXISTS;
|
||||||
import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.START_EVENT_NODE;
|
import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.START_EVENT;
|
||||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_CANDIDATE_PARAM;
|
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_CANDIDATE_PARAM;
|
||||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY;
|
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY;
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService {
|
|||||||
// return Boolean.FALSE;
|
// return Boolean.FALSE;
|
||||||
// }
|
// }
|
||||||
// 1. JSON 转换成 bpmnModel
|
// 1. JSON 转换成 bpmnModel
|
||||||
BpmnModel bpmnModel = BpmnModelUtils.convertSimpleModelToBpmnModel(model.getKey(), model.getName(), reqVO.getSimpleModelBody());
|
BpmnModel bpmnModel = SimpleModelUtils.convertSimpleModelToBpmnModel(model.getKey(), model.getName(), reqVO.getSimpleModelBody());
|
||||||
// 2.1 保存 Bpmn XML
|
// 2.1 保存 Bpmn XML
|
||||||
bpmModelService.saveModelBpmnXml(model.getId(), StrUtil.utf8Bytes(BpmnModelUtils.getBpmnXml(bpmnModel)));
|
bpmModelService.saveModelBpmnXml(model.getId(), StrUtil.utf8Bytes(BpmnModelUtils.getBpmnXml(bpmnModel)));
|
||||||
// 2.2 保存 JSON 数据
|
// 2.2 保存 JSON 数据
|
||||||
@ -93,7 +94,7 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
BpmSimpleModelNodeVO rootNode = new BpmSimpleModelNodeVO();
|
BpmSimpleModelNodeVO rootNode = new BpmSimpleModelNodeVO();
|
||||||
rootNode.setType(START_EVENT_NODE.getType());
|
rootNode.setType(START_EVENT.getType());
|
||||||
rootNode.setId(startEvent.getId());
|
rootNode.setId(startEvent.getId());
|
||||||
rootNode.setName(startEvent.getName());
|
rootNode.setName(startEvent.getName());
|
||||||
recursiveBuildSimpleModelNode(startEvent, rootNode);
|
recursiveBuildSimpleModelNode(startEvent, rootNode);
|
||||||
@ -105,10 +106,10 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService {
|
|||||||
Assert.notNull(nodeType, "节点类型不支持");
|
Assert.notNull(nodeType, "节点类型不支持");
|
||||||
// 校验节点是否支持转仿钉钉的流程模型
|
// 校验节点是否支持转仿钉钉的流程模型
|
||||||
List<SequenceFlow> outgoingFlows = validateCanConvertSimpleNode(nodeType, currentFlowNode);
|
List<SequenceFlow> outgoingFlows = validateCanConvertSimpleNode(nodeType, currentFlowNode);
|
||||||
if (CollUtil.isEmpty(outgoingFlows) || outgoingFlows.get(0).getTargetFlowElement() == null) {
|
if (CollUtil.isEmpty(outgoingFlows) || CollUtil.getFirst(outgoingFlows).getTargetFlowElement() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FlowElement targetElement = outgoingFlows.get(0).getTargetFlowElement();
|
FlowElement targetElement = CollUtil.getFirst(outgoingFlows).getTargetFlowElement();
|
||||||
// 如果是 EndEvent 直接退出
|
// 如果是 EndEvent 直接退出
|
||||||
if (targetElement instanceof EndEvent) {
|
if (targetElement instanceof EndEvent) {
|
||||||
return;
|
return;
|
||||||
@ -123,7 +124,7 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService {
|
|||||||
|
|
||||||
private BpmSimpleModelNodeVO convertUserTaskToSimpleModelNode(UserTask userTask) {
|
private BpmSimpleModelNodeVO convertUserTaskToSimpleModelNode(UserTask userTask) {
|
||||||
BpmSimpleModelNodeVO simpleModelNodeVO = new BpmSimpleModelNodeVO();
|
BpmSimpleModelNodeVO simpleModelNodeVO = new BpmSimpleModelNodeVO();
|
||||||
simpleModelNodeVO.setType(BpmSimpleModelNodeType.APPROVE_USER_NODE.getType());
|
simpleModelNodeVO.setType(BpmSimpleModelNodeType.USER_TASK.getType());
|
||||||
simpleModelNodeVO.setName(userTask.getName());
|
simpleModelNodeVO.setName(userTask.getName());
|
||||||
simpleModelNodeVO.setId(userTask.getId());
|
simpleModelNodeVO.setId(userTask.getId());
|
||||||
Map<String, Object> attributes = MapUtil.newHashMap();
|
Map<String, Object> attributes = MapUtil.newHashMap();
|
||||||
@ -137,13 +138,13 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService {
|
|||||||
|
|
||||||
private List<SequenceFlow> validateCanConvertSimpleNode(BpmSimpleModelNodeType nodeType, FlowNode currentFlowNode) {
|
private List<SequenceFlow> validateCanConvertSimpleNode(BpmSimpleModelNodeType nodeType, FlowNode currentFlowNode) {
|
||||||
switch (nodeType) {
|
switch (nodeType) {
|
||||||
case START_EVENT_NODE:
|
case START_EVENT:
|
||||||
case APPROVE_USER_NODE: {
|
case USER_TASK: {
|
||||||
List<SequenceFlow> outgoingFlows = currentFlowNode.getOutgoingFlows();
|
List<SequenceFlow> outgoingFlows = currentFlowNode.getOutgoingFlows();
|
||||||
if (CollUtil.isNotEmpty(outgoingFlows) && outgoingFlows.size() > 1) {
|
if (CollUtil.isNotEmpty(outgoingFlows) && outgoingFlows.size() > 1) {
|
||||||
throw exception(CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT);
|
throw exception(CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT);
|
||||||
}
|
}
|
||||||
validIsSupportFlowNode(outgoingFlows.get(0).getTargetFlowElement());
|
validIsSupportFlowNode(CollUtil.getFirst(outgoingFlows).getTargetFlowElement());
|
||||||
return outgoingFlows;
|
return outgoingFlows;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
@ -47,7 +47,7 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy
|
|||||||
// TODO @芋艿:这里多加了一个 name;
|
// TODO @芋艿:这里多加了一个 name;
|
||||||
@Override
|
@Override
|
||||||
public void createProcessInstanceCopy(Collection<Long> userIds, String processInstanceId, String taskId, String taskName) {
|
public void createProcessInstanceCopy(Collection<Long> userIds, String processInstanceId, String taskId, String taskName) {
|
||||||
// 1.1 校验任务存在 暂时去掉这个校验. 因为任务可能仿钉钉快搭的抄送节点(ScriptTask) TODO jason:抄送节点,会没有来源的 taskId 么?
|
// 1.1 校验任务存在 暂时去掉这个校验. 因为任务可能仿钉钉快搭的抄送节点(ScriptTask) TODO jason:抄送节点,会没有来源的 taskId 么? @芋艿 是否校验一下 传递进来的 id 不为空就行
|
||||||
// Task task = taskService.getTask(taskId);
|
// Task task = taskService.getTask(taskId);
|
||||||
// if (ObjectUtil.isNull(task)) {
|
// if (ObjectUtil.isNull(task)) {
|
||||||
// throw exception(ErrorCodeConstants.TASK_NOT_EXISTS);
|
// throw exception(ErrorCodeConstants.TASK_NOT_EXISTS);
|
||||||
|
@ -9,7 +9,8 @@ import org.springframework.stereotype.Service;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仿钉钉快搭各个节点 Service TODO @jason:注释要有空行哈;
|
* 仿钉钉快搭各个节点 Service
|
||||||
|
*
|
||||||
* @author jason
|
* @author jason
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@ -21,7 +22,8 @@ public class BpmSimpleNodeService {
|
|||||||
private BpmProcessInstanceCopyService processInstanceCopyService;
|
private BpmProcessInstanceCopyService processInstanceCopyService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仿钉钉快搭抄送 TODO @jason:注释要有空行哈;
|
* 仿钉钉快搭抄送
|
||||||
|
*
|
||||||
* @param execution 执行的任务(ScriptTask)
|
* @param execution 执行的任务(ScriptTask)
|
||||||
*/
|
*/
|
||||||
public Boolean copy(DelegateExecution execution) {
|
public Boolean copy(DelegateExecution execution) {
|
||||||
|
Loading…
Reference in New Issue
Block a user