Commit 1ae06b89e4cc639a638e8745a36535c3c3bc3468

Authored by YunaiV
1 parent 95bbf749

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

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;
15 15 public enum BpmApproveMethodEnum {
16 16  
17 17 SINGLE_PERSON_APPROVE(1, "单人审批"),
18   - ALL_APPROVE(2, "多人会签(需所有审批人同意)"),
19   - ANY_OF_APPROVE(3, "多人或签(一名审批人同意即可)"),
20   - SEQUENTIAL_APPROVE(4, "依次审批");
  18 + ALL_APPROVE(2, "多人会签(需所有审批人同意)"), // 会签
  19 + ANY_OF_APPROVE(3, "多人或签(一名审批人同意即可)"), // 或签
  20 + SEQUENTIAL_APPROVE(4, "依次审批"); // 依次审批
21 21  
22 22 /**
23 23 * 审批方式
... ... @@ -31,4 +31,5 @@ public enum BpmApproveMethodEnum {
31 31 public static BpmApproveMethodEnum valueOf(Integer method) {
32 32 return ArrayUtil.firstMatch(item -> item.getMethod().equals(method), values());
33 33 }
  34 +
34 35 }
... ...
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 {
49 49 */
50 50 public static final String ANY_OF_APPROVE_COMPLETE_EXPRESSION = "${ nrOfCompletedInstances > 0 }";
51 51  
  52 + // TODO @jason:建议方法名,改成 buildBpmnModel
  53 + // TODO @yunai:注释需要完善下;
52 54 /**
53 55 * 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善)
54 56 *
... ... @@ -59,28 +61,31 @@ public class SimpleModelUtils {
59 61 */
60 62 public static BpmnModel convertSimpleModelToBpmnModel(String processId, String processName, BpmSimpleModelNodeVO simpleModelNode) {
61 63 BpmnModel bpmnModel = new BpmnModel();
  64 + bpmnModel.setTargetNamespace(BPMN2_NAMESPACE); // TODO @jason:待定:是不是搞个自定义的 namespace;
  65 + // TODO 芋艿:后续在 review
62 66 // 不加这个 解析 Message 会报 NPE 异常
63   - bpmnModel.setTargetNamespace(BPMN2_NAMESPACE);
64 67 Message rejectPostProcessMsg = new Message();
65 68 rejectPostProcessMsg.setName(REJECT_POST_PROCESS_MESSAGE_NAME);
66 69 bpmnModel.addMessage(rejectPostProcessMsg);
67 70  
68   - Process mainProcess = new Process();
69   - mainProcess.setId(processId);
70   - mainProcess.setName(processName);
71   - mainProcess.setExecutable(Boolean.TRUE);
72   - bpmnModel.addProcess(mainProcess);
73   - // 前端模型数据结构。
  71 + Process process = new Process();
  72 + process.setId(processId);
  73 + process.setName(processName);
  74 + process.setExecutable(Boolean.TRUE); // TODO @jason:这个是必须设置的么?
  75 + bpmnModel.addProcess(process);
  76 +
  77 + // 前端模型数据结构
74 78 // 从 SimpleModel 构建 FlowNode 并添加到 Main Process
75   - buildAndAddBpmnFlowNode(simpleModelNode, mainProcess);
  79 + buildAndAddBpmnFlowNode(simpleModelNode, process);
76 80 // 找到 end event
77   - EndEvent endEvent = (EndEvent) CollUtil.findOne(mainProcess.getFlowElements(), item -> item instanceof EndEvent);
  81 + EndEvent endEvent = (EndEvent) CollUtil.findOne(process.getFlowElements(), item -> item instanceof EndEvent);
78 82 if (endEvent == null) {
79 83 // TODO 暂时为了兼容 单独构建 end event 节点. 后面去掉
80   - endEvent = buildAndAddBpmnEndEvent(mainProcess);
  84 + endEvent = buildAndAddBpmnEndEvent(process);
81 85 }
  86 +
82 87 // 构建并添加节点之间的连线 Sequence Flow
83   - buildAndAddBpmnSequenceFlow(mainProcess, simpleModelNode, endEvent.getId());
  88 + buildAndAddBpmnSequenceFlow(process, simpleModelNode, endEvent.getId());
84 89 // 自动布局
85 90 new BpmnAutoLayout(bpmnModel).execute();
86 91 return bpmnModel;
... ... @@ -197,20 +202,27 @@ public class SimpleModelUtils {
197 202 return sequenceFlow;
198 203 }
199 204  
  205 + // TODO @jason:要不改成 recursionNode 递归节点,然后把 build 名字让出来,专门用于构建各种 Node
  206 + // TODO @jason:simpleModelNode 改成 node,mainProcess 改成 process;更符合递归的感觉哈,处理当前节点
200 207 private static void buildAndAddBpmnFlowNode(BpmSimpleModelNodeVO simpleModelNode, Process mainProcess) {
201 208 // 节点为 null 退出
  209 + // TODO @jason:是不是写个 isValidNode 方法:判断是否为有效节点;
202 210 if (simpleModelNode == null || simpleModelNode.getId() == null) {
203 211 return;
204 212 }
205 213 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType());
206 214 Assert.notNull(nodeType, "模型节点类型不支持");
  215 + // TODO @jason:要不抽个 buildNode 方法,然后返回一个 List<FlowElement>,之后这个方法 addFlowElement;原因是,让当前这个方法,有主干逻辑;不然现在太长了;
207 216 switch (nodeType) {
208 217 case START_EVENT: {
  218 + // TODO @jason:每个 nodeType,buildXXX 方法要不更明确,并且去掉 Bpmn;
209 219 StartEvent startEvent = buildBpmnStartEvent(simpleModelNode);
210 220 mainProcess.addFlowElement(startEvent);
211 221 break;
212 222 }
213 223 case USER_TASK: {
  224 + // TODO @jason:这个,搞成一个 buildUserTask,然后把下面这 2 种节点,搞在一起实现类;这样 buildNode 里面可以更简洁;
  225 + // TODO @jason:这里还有个想法,是不是可以所有的都叫 buildXXXNode,然后里面有一些是 bpmn 相关的构建,叫做 buildBpmnUserTask,用于区分;
214 226 // 获取用户任务的配置
215 227 SimpleModelUserTaskConfig userTaskConfig = BeanUtil.toBean(simpleModelNode.getAttributes(), SimpleModelUserTaskConfig.class);
216 228 UserTask userTask = buildBpmnUserTask(simpleModelNode, userTaskConfig);
... ... @@ -259,18 +271,23 @@ public class SimpleModelUtils {
259 271 }
260 272  
261 273 // 如果不是网关类型的接口, 并且chileNode为空退出
  274 + // TODO @jason:建议这个判断去掉,可以更简洁一点;因为往下走;如果不成功,本身也就会结束哈;主要是,这里多了一个这样的判断,增加了理解成本;
262 275 if (!BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType()) && simpleModelNode.getChildNode() == null) {
263 276 return;
264 277 }
265 278  
266   - // 如果是网关类型接口. 递归添加条件节点
267   - if (BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType()) && ArrayUtil.isNotEmpty(simpleModelNode.getConditionNodes())) {
  279 + // 如果是“条件”节点,则递归处理条件
  280 + if (BpmSimpleModelNodeType.isBranchNode(simpleModelNode.getType())
  281 + && ArrayUtil.isNotEmpty(simpleModelNode.getConditionNodes())) {
  282 + // TODO @jason:可以搞成 stream 写成一行哈;
268 283 for (BpmSimpleModelNodeVO node : simpleModelNode.getConditionNodes()) {
269 284 buildAndAddBpmnFlowNode(node.getChildNode(), mainProcess);
270 285 }
271 286 }
272 287  
  288 + // 如果有“子”节点,则递归处理子节点
273 289 // chileNode不为空,递归添加子节点
  290 + // TODO @jason:这个,是不是不写判断,直接继续调用;因为本身 buildAndAddBpmnFlowNode 就会最开始判断了哈,就不重复判断了;
274 291 if (simpleModelNode.getChildNode() != null) {
275 292 buildAndAddBpmnFlowNode(simpleModelNode.getChildNode(), mainProcess);
276 293 }
... ... @@ -301,30 +318,33 @@ public class SimpleModelUtils {
301 318 private static ParallelGateway buildBpmnParallelGateway(BpmSimpleModelNodeVO node) {
302 319 ParallelGateway parallelGateway = new ParallelGateway();
303 320 parallelGateway.setId(node.getId());
  321 + // TODO @jason:setName
  322 +
  323 + // TODO @芋艿 + jason:合并网关;是不是要有条件啥的。微信讨论
304 324 return parallelGateway;
305 325 }
306 326  
307 327 private static ServiceTask buildBpmnServiceTask(BpmSimpleModelNodeVO node) {
308 328 ServiceTask serviceTask = new ServiceTask();
309   - serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
310   - serviceTask.setImplementation(BPMN_SIMPLE_COPY_EXECUTION_SCRIPT);
311 329 serviceTask.setId(node.getId());
312 330 serviceTask.setName(node.getName());
313   - // TODO @jason:建议使用 ServiceTask,通过 executionListeners 实现;
314   - // @芋艿 ServiceTask 就可以了吧。 不需要 executionListeners
  331 + // TODO @jason:建议用 delegateExpression;原因是,直接走 bpmSimpleNodeService.copy(execution) 的话,万一后续抄送改实现,可能比较麻烦。最好是搞个独立的 bean,然后它去调用抄 bpmSimpleNodeService;
  332 + serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
  333 + serviceTask.setImplementation(BPMN_SIMPLE_COPY_EXECUTION_SCRIPT);
  334 +
315 335 // 添加抄送候选人元素
316 336 addCandidateElements(MapUtil.getInt(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY),
317 337 MapUtil.getStr(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_PARAM),
318 338 serviceTask);
  339 +
319 340 // 添加表单字段权限属性元素
  341 + // TODO @芋艿:这块关注下哈;
320 342 List<Map<String, String>> fieldsPermissions = MapUtil.get(node.getAttributes(),
321   - FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() {
322   - });
  343 + FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() {});
323 344 addFormFieldsPermission(fieldsPermissions, serviceTask);
324 345 return serviceTask;
325 346 }
326 347  
327   -
328 348 /**
329 349 * 给节点添加候选人元素
330 350 */
... ... @@ -350,6 +370,9 @@ public class SimpleModelUtils {
350 370 private static InclusiveGateway buildBpmnInclusiveGateway(BpmSimpleModelNodeVO node, Boolean isFork) {
351 371 InclusiveGateway inclusiveGateway = new InclusiveGateway();
352 372 inclusiveGateway.setId(node.getId());
  373 + // TODO @jason:这里是不是 setName 哈;
  374 +
  375 + // TODO @芋艿 + jason:是不是搞个合并网关;这里微信讨论下,有点奇怪;
353 376 if (isFork) {
354 377 Assert.notEmpty(node.getConditionNodes(), "网关节点的条件节点不能为空");
355 378 // 网关的最后一个条件为 网关的 default sequence flow
... ... @@ -375,6 +398,9 @@ public class SimpleModelUtils {
375 398 userTask.setDueDate(userTaskConfig.getTimeoutHandler().getTimeDuration());
376 399 }
377 400  
  401 + // TODO 芋艿 + jason:要不要基于服务任务,实现或签下的审批不通过?或者说,按比例审批
  402 +
  403 + // TODO @jason:addCandidateElements、processMultiInstanceLoopCharacteristics 建议一起搞哈?
378 404 // 添加候选人元素
379 405 addCandidateElements(userTaskConfig.getCandidateStrategy(), userTaskConfig.getCandidateParam(), userTask);
380 406 // 添加表单字段权限属性元素
... ... @@ -455,10 +481,14 @@ public class SimpleModelUtils {
455 481 element.addExtensionElement(extensionElement);
456 482 }
457 483  
  484 + // ========== 各种 build 节点的方法 ==========
  485 +
458 486 private static StartEvent buildBpmnStartEvent(BpmSimpleModelNodeVO node) {
459 487 StartEvent startEvent = new StartEvent();
460 488 startEvent.setId(node.getId());
461 489 startEvent.setName(node.getName());
  490 +
  491 + // TODO 芋艿 + jason:要不要在开启节点后面,加一个“发起人”任务节点,然后自动审批通过
462 492 return startEvent;
463 493 }
464 494  
... ... @@ -466,6 +496,9 @@ public class SimpleModelUtils {
466 496 EndEvent endEvent = new EndEvent();
467 497 endEvent.setId(node.getId());
468 498 endEvent.setName(node.getName());
  499 +
  500 + // TODO @芋艿 + jason:要不要加一个终止定义?
469 501 return endEvent;
470 502 }
  503 +
471 504 }
... ...