Преглед изворни кода

【代码评审】BPM:review simple 表单的转化

YunaiV пре 1 година
родитељ
комит
1ae06b89e4

+ 4 - 3
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java

@@ -15,9 +15,9 @@ import lombok.Getter;
 public enum BpmApproveMethodEnum {
 
     SINGLE_PERSON_APPROVE(1, "单人审批"),
-    ALL_APPROVE(2, "多人会签(需所有审批人同意)"),
-    ANY_OF_APPROVE(3, "多人或签(一名审批人同意即可)"),
-    SEQUENTIAL_APPROVE(4, "依次审批");
+    ALL_APPROVE(2, "多人会签(需所有审批人同意)"), // 会签
+    ANY_OF_APPROVE(3, "多人或签(一名审批人同意即可)"), // 或签
+    SEQUENTIAL_APPROVE(4, "依次审批"); // 依次审批
 
     /**
      * 审批方式
@@ -31,4 +31,5 @@ public enum BpmApproveMethodEnum {
     public static BpmApproveMethodEnum valueOf(Integer method) {
         return ArrayUtil.firstMatch(item -> item.getMethod().equals(method), values());
     }
+
 }

+ 53 - 20
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java

@@ -49,6 +49,8 @@ public class SimpleModelUtils {
      */
     public static final String ANY_OF_APPROVE_COMPLETE_EXPRESSION = "${ nrOfCompletedInstances > 0 }";
 
+    // TODO @jason:建议方法名,改成 buildBpmnModel
+    // TODO @yunai:注释需要完善下;
     /**
      * 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善)
      *
@@ -59,28 +61,31 @@ public class SimpleModelUtils {
      */
     public static BpmnModel convertSimpleModelToBpmnModel(String processId, String processName, BpmSimpleModelNodeVO simpleModelNode) {
         BpmnModel bpmnModel = new BpmnModel();
+        bpmnModel.setTargetNamespace(BPMN2_NAMESPACE); // TODO @jason:待定:是不是搞个自定义的 namespace;
+        // TODO 芋艿:后续在 review
         // 不加这个 解析 Message 会报 NPE 异常
-        bpmnModel.setTargetNamespace(BPMN2_NAMESPACE);
         Message rejectPostProcessMsg = new Message();
         rejectPostProcessMsg.setName(REJECT_POST_PROCESS_MESSAGE_NAME);
         bpmnModel.addMessage(rejectPostProcessMsg);
 
-        Process mainProcess = new Process();
-        mainProcess.setId(processId);
-        mainProcess.setName(processName);
-        mainProcess.setExecutable(Boolean.TRUE);
-        bpmnModel.addProcess(mainProcess);
-        // 前端模型数据结构。
+        Process process = new Process();
+        process.setId(processId);
+        process.setName(processName);
+        process.setExecutable(Boolean.TRUE); // TODO @jason:这个是必须设置的么?
+        bpmnModel.addProcess(process);
+
+        // 前端模型数据结构
         // 从 SimpleModel 构建 FlowNode 并添加到 Main Process
-        buildAndAddBpmnFlowNode(simpleModelNode, mainProcess);
+        buildAndAddBpmnFlowNode(simpleModelNode, process);
         // 找到 end event
-        EndEvent endEvent = (EndEvent) CollUtil.findOne(mainProcess.getFlowElements(), item -> item instanceof EndEvent);
+        EndEvent endEvent = (EndEvent) CollUtil.findOne(process.getFlowElements(), item -> item instanceof EndEvent);
         if (endEvent == null) {
             // TODO 暂时为了兼容 单独构建 end event 节点. 后面去掉
-            endEvent = buildAndAddBpmnEndEvent(mainProcess);
+            endEvent = buildAndAddBpmnEndEvent(process);
         }
+
         // 构建并添加节点之间的连线 Sequence Flow
-        buildAndAddBpmnSequenceFlow(mainProcess, simpleModelNode, endEvent.getId());
+        buildAndAddBpmnSequenceFlow(process, simpleModelNode, endEvent.getId());
         // 自动布局
         new BpmnAutoLayout(bpmnModel).execute();
         return bpmnModel;
@@ -197,20 +202,27 @@ public class SimpleModelUtils {
         return sequenceFlow;
     }
 
+    // TODO @jason:要不改成 recursionNode 递归节点,然后把 build 名字让出来,专门用于构建各种 Node
+    // TODO @jason:simpleModelNode 改成 node,mainProcess 改成 process;更符合递归的感觉哈,处理当前节点
     private static void buildAndAddBpmnFlowNode(BpmSimpleModelNodeVO simpleModelNode, Process mainProcess) {
         // 节点为 null 退出
+        // TODO @jason:是不是写个 isValidNode 方法:判断是否为有效节点;
         if (simpleModelNode == null || simpleModelNode.getId() == null) {
             return;
         }
         BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType());
         Assert.notNull(nodeType, "模型节点类型不支持");
+        // TODO @jason:要不抽个 buildNode 方法,然后返回一个 List<FlowElement>,之后这个方法 addFlowElement;原因是,让当前这个方法,有主干逻辑;不然现在太长了;
         switch (nodeType) {
             case START_EVENT: {
+                // TODO @jason:每个 nodeType,buildXXX 方法要不更明确,并且去掉 Bpmn;
                 StartEvent startEvent = buildBpmnStartEvent(simpleModelNode);
                 mainProcess.addFlowElement(startEvent);
                 break;
             }
             case USER_TASK: {
+                // TODO @jason:这个,搞成一个 buildUserTask,然后把下面这 2 种节点,搞在一起实现类;这样 buildNode 里面可以更简洁;
+                // TODO @jason:这里还有个想法,是不是可以所有的都叫 buildXXXNode,然后里面有一些是 bpmn 相关的构建,叫做 buildBpmnUserTask,用于区分;
                 // 获取用户任务的配置
                 SimpleModelUserTaskConfig userTaskConfig = BeanUtil.toBean(simpleModelNode.getAttributes(), SimpleModelUserTaskConfig.class);
                 UserTask userTask = buildBpmnUserTask(simpleModelNode, userTaskConfig);
@@ -259,18 +271,23 @@ public class SimpleModelUtils {
         }
 
         // 如果不是网关类型的接口, 并且chileNode为空退出
+        // TODO @jason:建议这个判断去掉,可以更简洁一点;因为往下走;如果不成功,本身也就会结束哈;主要是,这里多了一个这样的判断,增加了理解成本;
         if (!BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType()) && simpleModelNode.getChildNode() == null) {
             return;
         }
 
-        // 如果是网关类型接口. 递归添加条件节点
-        if (BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType()) && ArrayUtil.isNotEmpty(simpleModelNode.getConditionNodes())) {
+        // 如果是“条件”节点,则递归处理条件
+        if (BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType())
+                && ArrayUtil.isNotEmpty(simpleModelNode.getConditionNodes())) {
+            // TODO @jason:可以搞成 stream 写成一行哈;
             for (BpmSimpleModelNodeVO node : simpleModelNode.getConditionNodes()) {
                 buildAndAddBpmnFlowNode(node.getChildNode(), mainProcess);
             }
         }
 
+        // 如果有“子”节点,则递归处理子节点
         // chileNode不为空,递归添加子节点
+        // TODO @jason:这个,是不是不写判断,直接继续调用;因为本身 buildAndAddBpmnFlowNode 就会最开始判断了哈,就不重复判断了;
         if (simpleModelNode.getChildNode() != null) {
             buildAndAddBpmnFlowNode(simpleModelNode.getChildNode(), mainProcess);
         }
@@ -301,30 +318,33 @@ public class SimpleModelUtils {
     private static ParallelGateway buildBpmnParallelGateway(BpmSimpleModelNodeVO node) {
         ParallelGateway parallelGateway = new ParallelGateway();
         parallelGateway.setId(node.getId());
+        // TODO @jason:setName
+
+        // TODO @芋艿 + jason:合并网关;是不是要有条件啥的。微信讨论
         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
+        // TODO @jason:建议用 delegateExpression;原因是,直接走 bpmSimpleNodeService.copy(execution) 的话,万一后续抄送改实现,可能比较麻烦。最好是搞个独立的 bean,然后它去调用抄 bpmSimpleNodeService;
+        serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
+        serviceTask.setImplementation(BPMN_SIMPLE_COPY_EXECUTION_SCRIPT);
+
         // 添加抄送候选人元素
         addCandidateElements(MapUtil.getInt(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY),
                 MapUtil.getStr(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_PARAM),
                 serviceTask);
+
         // 添加表单字段权限属性元素
+        // TODO @芋艿:这块关注下哈;
         List<Map<String, String>> fieldsPermissions = MapUtil.get(node.getAttributes(),
-                FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() {
-                });
+                FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() {});
         addFormFieldsPermission(fieldsPermissions, serviceTask);
         return serviceTask;
     }
 
-
     /**
      * 给节点添加候选人元素
      */
@@ -350,6 +370,9 @@ public class SimpleModelUtils {
     private static InclusiveGateway buildBpmnInclusiveGateway(BpmSimpleModelNodeVO node, Boolean isFork) {
         InclusiveGateway inclusiveGateway = new InclusiveGateway();
         inclusiveGateway.setId(node.getId());
+        // TODO @jason:这里是不是 setName 哈;
+
+        // TODO @芋艿 + jason:是不是搞个合并网关;这里微信讨论下,有点奇怪;
         if (isFork) {
             Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空");
             // 网关的最后一个条件为 网关的 default sequence flow
@@ -375,6 +398,9 @@ public class SimpleModelUtils {
             userTask.setDueDate(userTaskConfig.getTimeoutHandler().getTimeDuration());
         }
 
+        // TODO 芋艿 + jason:要不要基于服务任务,实现或签下的审批不通过?或者说,按比例审批
+
+        // TODO @jason:addCandidateElements、processMultiInstanceLoopCharacteristics 建议一起搞哈?
         // 添加候选人元素
         addCandidateElements(userTaskConfig.getCandidateStrategy(), userTaskConfig.getCandidateParam(), userTask);
         // 添加表单字段权限属性元素
@@ -455,10 +481,14 @@ public class SimpleModelUtils {
         element.addExtensionElement(extensionElement);
     }
 
+    // ========== 各种 build 节点的方法 ==========
+
     private static StartEvent buildBpmnStartEvent(BpmSimpleModelNodeVO node) {
         StartEvent startEvent = new StartEvent();
         startEvent.setId(node.getId());
         startEvent.setName(node.getName());
+
+        // TODO 芋艿 + jason:要不要在开启节点后面,加一个“发起人”任务节点,然后自动审批通过
         return startEvent;
     }
 
@@ -466,6 +496,9 @@ public class SimpleModelUtils {
         EndEvent endEvent = new EndEvent();
         endEvent.setId(node.getId());
         endEvent.setName(node.getName());
+
+        // TODO @芋艿 + jason:要不要加一个终止定义?
         return endEvent;
     }
+
 }