diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java new file mode 100644 index 000000000..d9ba36449 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.bpm.enums.definition; + +import cn.hutool.core.util.ArrayUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * BPM 审批方式的枚举 + * + * @author jason + */ +@Getter +@AllArgsConstructor +public enum BpmApproveMethodEnum { + + SINGLE_PERSON_APPROVE(1, "单人审批"), + ALL_APPROVE(2, "多人会签(需所有审批人同意)"), + ANY_OF_APPROVE(3, "多人或签(一名审批人同意即可)"), + SEQUENTIAL_APPROVE(4, "依次审批"); + + /** + * 审批方式 + */ + private final Integer method; + /** + * 名字 + */ + private final String name; + + public static BpmApproveMethodEnum valueOf(Integer method) { + return ArrayUtil.firstMatch(item -> item.getMethod().equals(method), values()); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/simple/BpmSimpleModelNodeVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/simple/BpmSimpleModelNodeVO.java index 09db4764c..4a9e653e5 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/simple/BpmSimpleModelNodeVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/simple/BpmSimpleModelNodeVO.java @@ -28,6 +28,9 @@ public class BpmSimpleModelNodeVO { @Schema(description = "模型节点名称", example = "领导审批") private String name; + @Schema(description = "节点展示内容", example = "指定成员: 芋道源码") + private String showText; + @Schema(description = "孩子节点") private BpmSimpleModelNodeVO childNode; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/SimpleModelConstants.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/SimpleModelConstants.java index d02f9a4f1..6892bed14 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/SimpleModelConstants.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/SimpleModelConstants.java @@ -7,4 +7,8 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums; */ public interface SimpleModelConstants { + /** + * 审批方式属性 + */ + String APPROVE_METHOD_ATTRIBUTE = "approveMethod"; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 26b709120..2e44d5286 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -7,8 +7,10 @@ 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.BpmApproveMethodEnum; 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.SimpleModelConstants; import org.flowable.bpmn.BpmnAutoLayout; import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.*; @@ -16,6 +18,7 @@ import org.flowable.bpmn.model.*; import java.util.List; import java.util.Map; +import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.END_EVENT; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.FORM_FIELD_PERMISSION_ELEMENT; import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_NAMESPACE; import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_PREFIX; @@ -29,6 +32,16 @@ public class SimpleModelUtils { public static final String BPMN_SIMPLE_COPY_EXECUTION_SCRIPT = "#{bpmSimpleNodeService.copy(execution)}"; + /** + * 所有审批人同意的表达式 + */ + public static final String ALL_APPROVE_COMPLETE_EXPRESSION = "${ nrOfCompletedInstances >= 0 }"; + + /** + * 任一一名审批人同意的表达式 + */ + public static final String ANY_OF_APPROVE_COMPLETE_EXPRESSION = "${ nrOfCompletedInstances >= nrOfInstances }"; + /** * 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善) * @@ -47,10 +60,15 @@ public class SimpleModelUtils { // 前端模型数据结构。 有 start event 节点. 没有 end event 节点。 // 从 SimpleModel 构建 FlowNode 并添加到 Main Process buildAndAddBpmnFlowNode(simpleModelNode, mainProcess); - // 单独构建 end event 节点 - buildAndAddBpmnEndEvent(mainProcess); + // 找到 end event + EndEvent endEvent = (EndEvent) CollUtil.findOne(mainProcess.getFlowElements(), item -> item instanceof EndEvent); + if (endEvent == null) { + // 暂时为了兼容 单独构建 end event 节点 + endEvent = buildAndAddBpmnEndEvent(mainProcess); + } + // 构建并添加节点之间的连线 Sequence Flow - buildAndAddBpmnSequenceFlow(mainProcess, simpleModelNode, BpmnModelConstants.END_EVENT_ID); + buildAndAddBpmnSequenceFlow(mainProcess, simpleModelNode, endEvent.getId()); // 自动布局 new BpmnAutoLayout(bpmnModel).execute(); return bpmnModel; @@ -58,7 +76,7 @@ public class SimpleModelUtils { private static void buildAndAddBpmnSequenceFlow(Process mainProcess, BpmSimpleModelNodeVO node, String targetId) { // 节点为 null 退出 - if (node == null || node.getId() == null) { + if (node == null || node.getId() == null || END_EVENT.getType().equals(node.getType())) { return; } BpmSimpleModelNodeVO childNode = node.getChildNode(); @@ -169,6 +187,11 @@ public class SimpleModelUtils { mainProcess.addFlowElement(inclusiveGateway); break; } + case END_EVENT: { + EndEvent endEvent = buildBpmnEndEvent(simpleModelNode); + mainProcess.addFlowElement(endEvent); + break; + } default: { // TODO 其它节点类型的实现 } @@ -242,32 +265,59 @@ public class SimpleModelUtils { return inclusiveGateway; } - private static void buildAndAddBpmnEndEvent(Process mainProcess) { + private static EndEvent buildAndAddBpmnEndEvent(Process mainProcess) { EndEvent endEvent = new EndEvent(); endEvent.setId(BpmnModelConstants.END_EVENT_ID); endEvent.setName("结束"); mainProcess.addFlowElement(endEvent); + return endEvent; } private static UserTask buildBpmnUserTask(BpmSimpleModelNodeVO node) { UserTask userTask = new UserTask(); userTask.setId(node.getId()); userTask.setName(node.getName()); - // TODO 暂时测试,后面去掉 - userTask.setFormKey("24"); // 添加候选人元素 addCandidateElements(node, userTask); // 添加表单字段权限属性元素 addFormFieldsPermission(node, userTask); + // 处理多实例 + processMultiInstanceLoopCharacteristics(node, userTask); return userTask; } + private static void processMultiInstanceLoopCharacteristics(BpmSimpleModelNodeVO node, UserTask userTask) { + Integer approveMethod = MapUtil.getInt(node.getAttributes(), SimpleModelConstants.APPROVE_METHOD_ATTRIBUTE); + BpmApproveMethodEnum bpmApproveMethodEnum = BpmApproveMethodEnum.valueOf(approveMethod); + if (bpmApproveMethodEnum == null || bpmApproveMethodEnum == BpmApproveMethodEnum.SINGLE_PERSON_APPROVE) { + return; + } + MultiInstanceLoopCharacteristics multiInstanceCharacteristics = new MultiInstanceLoopCharacteristics(); + // 设置 collectionVariable。本系统用不到。会在 仅仅为了校验。 + multiInstanceCharacteristics.setInputDataItem("${coll_userList}"); + if (bpmApproveMethodEnum == BpmApproveMethodEnum.ALL_APPROVE) { + multiInstanceCharacteristics.setCompletionCondition(ALL_APPROVE_COMPLETE_EXPRESSION); + multiInstanceCharacteristics.setSequential(false); + } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.ANY_OF_APPROVE) { + multiInstanceCharacteristics.setCompletionCondition(ANY_OF_APPROVE_COMPLETE_EXPRESSION); + multiInstanceCharacteristics.setSequential(false); + userTask.setLoopCharacteristics(multiInstanceCharacteristics); + } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.SEQUENTIAL_APPROVE) { + multiInstanceCharacteristics.setCompletionCondition(ALL_APPROVE_COMPLETE_EXPRESSION); + multiInstanceCharacteristics.setSequential(true); + multiInstanceCharacteristics.setLoopCardinality("1"); + userTask.setLoopCharacteristics(multiInstanceCharacteristics); + } + userTask.setLoopCharacteristics(multiInstanceCharacteristics); + } + /** * 给节点添加表单字段权限元素 */ private static void addFormFieldsPermission(BpmSimpleModelNodeVO node, FlowElement flowElement) { List> fieldsPermissions = MapUtil.get(node.getAttributes(), - FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() {}); + FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() { + }); if (CollUtil.isNotEmpty(fieldsPermissions)) { fieldsPermissions.forEach(item -> addExtensionElement(flowElement, FORM_FIELD_PERMISSION_ELEMENT, item)); } @@ -307,4 +357,11 @@ public class SimpleModelUtils { startEvent.setName(node.getName()); return startEvent; } + + private static EndEvent buildBpmnEndEvent(BpmSimpleModelNodeVO node) { + EndEvent endEvent = new EndEvent(); + endEvent.setId(node.getId()); + endEvent.setName(node.getName()); + return endEvent; + } }