Commit b504d9841e37c23cfed48640d641d47529fb4314

Authored by jason
1 parent 210b4e54

仿钉钉流程设计-后端实现30%

yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
@@ -75,4 +75,6 @@ public interface ErrorCodeConstants { @@ -75,4 +75,6 @@ public interface ErrorCodeConstants {
75 // ========== BPM 流程表达式 1-009-014-000 ========== 75 // ========== BPM 流程表达式 1-009-014-000 ==========
76 ErrorCode PROCESS_EXPRESSION_NOT_EXISTS = new ErrorCode(1_009_014_000, "流程表达式不存在"); 76 ErrorCode PROCESS_EXPRESSION_NOT_EXISTS = new ErrorCode(1_009_014_000, "流程表达式不存在");
77 77
  78 + // ========== BPM 仿钉钉流程设计器 1-009-015-000 ==========
  79 + ErrorCode CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT = new ErrorCode(1_009_015_000, "该流程模型不支持仿钉钉设计流程");
78 } 80 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmSimpleModelController.java
1 package cn.iocoder.yudao.module.bpm.controller.admin.definition; 1 package cn.iocoder.yudao.module.bpm.controller.admin.definition;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelNodeVO;
4 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelSaveReqVO; 5 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelSaveReqVO;
5 import cn.iocoder.yudao.module.bpm.service.definition.BpmSimpleModelService; 6 import cn.iocoder.yudao.module.bpm.service.definition.BpmSimpleModelService;
6 import io.swagger.v3.oas.annotations.Operation; 7 import io.swagger.v3.oas.annotations.Operation;
  8 +import io.swagger.v3.oas.annotations.Parameter;
7 import io.swagger.v3.oas.annotations.tags.Tag; 9 import io.swagger.v3.oas.annotations.tags.Tag;
8 import jakarta.annotation.Resource; 10 import jakarta.annotation.Resource;
9 import jakarta.validation.Valid; 11 import jakarta.validation.Valid;
10 import org.springframework.security.access.prepost.PreAuthorize; 12 import org.springframework.security.access.prepost.PreAuthorize;
11 -import org.springframework.web.bind.annotation.PostMapping;  
12 -import org.springframework.web.bind.annotation.RequestBody;  
13 -import org.springframework.web.bind.annotation.RequestMapping;  
14 -import org.springframework.web.bind.annotation.RestController; 13 +import org.springframework.web.bind.annotation.*;
15 14
16 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 15 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
17 16
@@ -28,4 +27,12 @@ public class BpmSimpleModelController { @@ -28,4 +27,12 @@ public class BpmSimpleModelController {
28 public CommonResult<Boolean> saveSimpleModel(@Valid @RequestBody BpmSimpleModelSaveReqVO reqVO) { 27 public CommonResult<Boolean> saveSimpleModel(@Valid @RequestBody BpmSimpleModelSaveReqVO reqVO) {
29 return success(bpmSimpleModelService.saveSimpleModel(reqVO)); 28 return success(bpmSimpleModelService.saveSimpleModel(reqVO));
30 } 29 }
  30 +
  31 + @GetMapping("/get")
  32 + @Operation(summary = "获得仿钉钉流程设计模型")
  33 + @Parameter(name = "modelId", description = "流程模型编号", required = true, example = "a2c5eee0-eb6c-11ee-abf4-0c37967c420a")
  34 + public CommonResult<BpmSimpleModelNodeVO> getSimpleModel(@RequestParam("modelId") String modelId){
  35 + return success(bpmSimpleModelService.getSimpleModel(modelId));
  36 + }
  37 +
31 } 38 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums; 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums;
2 2
  3 +import com.google.common.collect.ImmutableSet;
  4 +import org.flowable.bpmn.model.*;
  5 +
  6 +import java.util.Set;
  7 +
3 /** 8 /**
4 * BPMN XML 常量信息 9 * BPMN XML 常量信息
5 * 10 *
@@ -24,13 +29,13 @@ public interface BpmnModelConstants { @@ -24,13 +29,13 @@ public interface BpmnModelConstants {
24 String USER_TASK_CANDIDATE_PARAM = "candidateParam"; 29 String USER_TASK_CANDIDATE_PARAM = "candidateParam";
25 30
26 /** 31 /**
27 - * BPMN Start Event 节点 Id, 用于后端生成 Start Event 节点 32 + * BPMN End Event 节点 Id, 用于后端生成 End Event 节点
28 */ 33 */
29 - String START_EVENT_ID = "StartEvent_1"; 34 + String END_EVENT_ID = "EndEvent_1";
30 35
31 /** 36 /**
32 - * BPMN End Event 节点 Id, 用于后端生成 End Event 节点 37 + * 支持转仿钉钉设计模型的 Bpmn 节点
33 */ 38 */
34 - String END_EVENT_ID = "EndEvent_1"; 39 + Set<Class<? extends FlowNode>> SUPPORT_CONVERT_SIMPLE_FlOW_NODES = ImmutableSet.of(UserTask.class, EndEvent.class);
35 40
36 } 41 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.util; @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
5 -import cn.hutool.core.lang.TypeReference;  
6 import cn.hutool.core.map.MapUtil; 5 import cn.hutool.core.map.MapUtil;
7 import cn.hutool.core.util.ArrayUtil; 6 import cn.hutool.core.util.ArrayUtil;
8 import cn.hutool.core.util.StrUtil; 7 import cn.hutool.core.util.StrUtil;
@@ -338,31 +337,26 @@ public class BpmnModelUtils { @@ -338,31 +337,26 @@ public class BpmnModelUtils {
338 337
339 /** 338 /**
340 * 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善) 339 * 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善)
341 - * @param processId 流程标识  
342 - * @param processName 流程名称 340 + *
  341 + * @param processId 流程标识
  342 + * @param processName 流程名称
343 * @param simpleModelNode 仿钉钉流程设计模型数据结构 343 * @param simpleModelNode 仿钉钉流程设计模型数据结构
344 * @return Bpmn Model 344 * @return Bpmn Model
345 */ 345 */
346 - public static BpmnModel convertSimpleModelToBpmnModel(String processId, String processName,BpmSimpleModelNodeVO simpleModelNode) { 346 + public static BpmnModel convertSimpleModelToBpmnModel(String processId, String processName, BpmSimpleModelNodeVO simpleModelNode) {
347 BpmnModel bpmnModel = new BpmnModel(); 347 BpmnModel bpmnModel = new BpmnModel();
348 Process mainProcess = new Process(); 348 Process mainProcess = new Process();
349 mainProcess.setId(processId); 349 mainProcess.setId(processId);
350 mainProcess.setName(processName); 350 mainProcess.setName(processName);
351 mainProcess.setExecutable(Boolean.TRUE); 351 mainProcess.setExecutable(Boolean.TRUE);
352 bpmnModel.addProcess(mainProcess); 352 bpmnModel.addProcess(mainProcess);
353 - // 目前前端传进来的节点。 没有 start event 节点 和 end event 节点。  
354 - // 在最前面加上 start event node  
355 - BpmSimpleModelNodeVO startEventNode = new BpmSimpleModelNodeVO();  
356 - startEventNode.setId(BpmnModelConstants.START_EVENT_ID);  
357 - startEventNode.setName("开始");  
358 - startEventNode.setType(BpmSimpleModelNodeType.START_NODE.getType());  
359 - startEventNode.setChildNode(simpleModelNode); 353 + // 前端模型数据结构。 有 start event 节点. 没有 end event 节点。
360 // 添加 FlowNode 354 // 添加 FlowNode
361 - addBpmnFlowNode(mainProcess, startEventNode); 355 + addBpmnFlowNode(mainProcess, simpleModelNode);
362 // 单独添加 end event 节点 356 // 单独添加 end event 节点
363 addBpmnEndEventNode(mainProcess); 357 addBpmnEndEventNode(mainProcess);
364 // 添加节点之间的连线 Sequence Flow 358 // 添加节点之间的连线 Sequence Flow
365 - addBpmnSequenceFlow(mainProcess, startEventNode); 359 + addBpmnSequenceFlow(mainProcess, simpleModelNode);
366 // 自动布局 360 // 自动布局
367 new BpmnAutoLayout(bpmnModel).execute(); 361 new BpmnAutoLayout(bpmnModel).execute();
368 362
@@ -371,24 +365,24 @@ public class BpmnModelUtils { @@ -371,24 +365,24 @@ public class BpmnModelUtils {
371 365
372 private static void addBpmnSequenceFlow(Process mainProcess, BpmSimpleModelNodeVO node) { 366 private static void addBpmnSequenceFlow(Process mainProcess, BpmSimpleModelNodeVO node) {
373 // 节点为 null 退出 367 // 节点为 null 退出
374 - if (node == null) { 368 + if (node == null || node.getId() == null) {
375 return; 369 return;
376 } 370 }
377 BpmSimpleModelNodeVO childNode = node.getChildNode(); 371 BpmSimpleModelNodeVO childNode = node.getChildNode();
378 // 如果后续节点为 null. 添加与结束节点的连线 372 // 如果后续节点为 null. 添加与结束节点的连线
379 - if (childNode == null) {  
380 - addBpmnSequenceFlowElement(mainProcess, node.getId(),BpmnModelConstants.END_EVENT_ID, null); 373 + if (childNode == null || childNode.getId() == null) {
  374 + addBpmnSequenceFlowElement(mainProcess, node.getId(), BpmnModelConstants.END_EVENT_ID, null);
381 return; 375 return;
382 } 376 }
383 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType()); 377 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(node.getType());
384 Assert.notNull(nodeType, "模型节点类型不支持"); 378 Assert.notNull(nodeType, "模型节点类型不支持");
385 - switch(nodeType){  
386 - case START_NODE :  
387 - case START_USER_NODE :  
388 - case APPROVE_USER_NODE : 379 + switch (nodeType) {
  380 + case START_NODE:
  381 + case START_USER_NODE:
  382 + case APPROVE_USER_NODE:
389 addBpmnSequenceFlowElement(mainProcess, node.getId(), childNode.getId(), null); 383 addBpmnSequenceFlowElement(mainProcess, node.getId(), childNode.getId(), null);
390 break; 384 break;
391 - default : { 385 + default: {
392 // TODO 其它节点类型的实现 386 // TODO 其它节点类型的实现
393 } 387 }
394 } 388 }
@@ -396,7 +390,7 @@ public class BpmnModelUtils { @@ -396,7 +390,7 @@ public class BpmnModelUtils {
396 addBpmnSequenceFlow(mainProcess, childNode); 390 addBpmnSequenceFlow(mainProcess, childNode);
397 } 391 }
398 392
399 - private static void addBpmnSequenceFlowElement(Process mainProcess, String sourceId, String targetId, String conditionExpression) { 393 + private static void addBpmnSequenceFlowElement(Process mainProcess, String sourceId, String targetId, String conditionExpression) {
400 SequenceFlow sequenceFlow = new SequenceFlow(sourceId, targetId); 394 SequenceFlow sequenceFlow = new SequenceFlow(sourceId, targetId);
401 if (StrUtil.isNotEmpty(conditionExpression)) { 395 if (StrUtil.isNotEmpty(conditionExpression)) {
402 sequenceFlow.setConditionExpression(conditionExpression); 396 sequenceFlow.setConditionExpression(conditionExpression);
@@ -407,20 +401,20 @@ public class BpmnModelUtils { @@ -407,20 +401,20 @@ public class BpmnModelUtils {
407 401
408 private static void addBpmnFlowNode(Process mainProcess, BpmSimpleModelNodeVO simpleModelNode) { 402 private static void addBpmnFlowNode(Process mainProcess, BpmSimpleModelNodeVO simpleModelNode) {
409 // 节点为 null 退出 403 // 节点为 null 退出
410 - if (simpleModelNode == null) { 404 + if (simpleModelNode == null || simpleModelNode.getId() == null) {
411 return; 405 return;
412 } 406 }
413 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType()); 407 BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(simpleModelNode.getType());
414 Assert.notNull(nodeType, "模型节点类型不支持"); 408 Assert.notNull(nodeType, "模型节点类型不支持");
415 - switch(nodeType){  
416 - case START_NODE : 409 + switch (nodeType) {
  410 + case START_NODE:
417 addBpmnStartEventNode(mainProcess, simpleModelNode); 411 addBpmnStartEventNode(mainProcess, simpleModelNode);
418 break; 412 break;
419 - case START_USER_NODE :  
420 - case APPROVE_USER_NODE : 413 + case START_USER_NODE:
  414 + case APPROVE_USER_NODE:
421 addBpmnUserTaskEventNode(mainProcess, simpleModelNode); 415 addBpmnUserTaskEventNode(mainProcess, simpleModelNode);
422 break; 416 break;
423 - default : { 417 + default: {
424 // TODO 其它节点类型的实现 418 // TODO 其它节点类型的实现
425 } 419 }
426 } 420 }
@@ -454,17 +448,16 @@ public class BpmnModelUtils { @@ -454,17 +448,16 @@ public class BpmnModelUtils {
454 UserTask userTask = new UserTask(); 448 UserTask userTask = new UserTask();
455 userTask.setId(node.getId()); 449 userTask.setId(node.getId());
456 userTask.setName(node.getName()); 450 userTask.setName(node.getName());
457 - Integer candidateStrategy = MapUtil.getInt(node.getAttributes(),BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY);  
458 - List<Integer> candidateParam = MapUtil.get(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_PARAM, new TypeReference<>() {}); 451 + Integer candidateStrategy = MapUtil.getInt(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY);
459 // 添加自定义属性 452 // 添加自定义属性
460 addExtensionAttribute(userTask, BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY, 453 addExtensionAttribute(userTask, BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY,
461 candidateStrategy == null ? null : String.valueOf(candidateStrategy)); 454 candidateStrategy == null ? null : String.valueOf(candidateStrategy));
462 addExtensionAttribute(userTask, BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM, 455 addExtensionAttribute(userTask, BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM,
463 - CollUtil.join(candidateParam, ",")); 456 + MapUtil.getStr(node.getAttributes(), BpmnModelConstants.USER_TASK_CANDIDATE_PARAM));
464 mainProcess.addFlowElement(userTask); 457 mainProcess.addFlowElement(userTask);
465 } 458 }
466 459
467 - private static void addExtensionAttribute(FlowElement element, String namespace, String name, String value) { 460 + private static void addExtensionAttribute(FlowElement element, String namespace, String name, String value) {
468 if (value == null) { 461 if (value == null) {
469 return; 462 return;
470 } 463 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmSimpleModelService.java
1 package cn.iocoder.yudao.module.bpm.service.definition; 1 package cn.iocoder.yudao.module.bpm.service.definition;
2 2
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelNodeVO;
3 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelSaveReqVO; 4 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelSaveReqVO;
4 import jakarta.validation.Valid; 5 import jakarta.validation.Valid;
5 6
@@ -15,4 +16,11 @@ public interface BpmSimpleModelService { @@ -15,4 +16,11 @@ public interface BpmSimpleModelService {
15 * @param reqVO 请求信息 16 * @param reqVO 请求信息
16 */ 17 */
17 Boolean saveSimpleModel(@Valid BpmSimpleModelSaveReqVO reqVO); 18 Boolean saveSimpleModel(@Valid BpmSimpleModelSaveReqVO reqVO);
  19 +
  20 + /**
  21 + * 获取仿钉钉流程设计模型结构
  22 + * @param modelId 流程模型编号
  23 + * @return 仿钉钉流程设计模型结构
  24 + */
  25 + BpmSimpleModelNodeVO getSimpleModel(String modelId);
18 } 26 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmSimpleModelServiceImpl.java
1 package cn.iocoder.yudao.module.bpm.service.definition; 1 package cn.iocoder.yudao.module.bpm.service.definition;
2 2
3 -import cn.hutool.core.util.ArrayUtil; 3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.lang.Assert;
  5 +import cn.hutool.core.map.MapUtil;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelNodeVO;
4 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelSaveReqVO; 7 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelSaveReqVO;
  8 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType;
  9 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
5 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; 10 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
6 import jakarta.annotation.Resource; 11 import jakarta.annotation.Resource;
7 -import org.flowable.bpmn.model.BpmnModel; 12 +import org.flowable.bpmn.model.*;
8 import org.flowable.engine.repository.Model; 13 import org.flowable.engine.repository.Model;
9 import org.springframework.stereotype.Service; 14 import org.springframework.stereotype.Service;
10 import org.springframework.validation.annotation.Validated; 15 import org.springframework.validation.annotation.Validated;
11 16
  17 +import java.util.List;
  18 +import java.util.Map;
  19 +
12 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  21 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT;
13 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.MODEL_NOT_EXISTS; 22 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.MODEL_NOT_EXISTS;
  23 +import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.START_NODE;
  24 +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_CANDIDATE_PARAM;
  25 +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY;
14 26
15 /** 27 /**
16 * 仿钉钉流程设计 Service 实现类 28 * 仿钉钉流程设计 Service 实现类
@@ -29,16 +41,124 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService { @@ -29,16 +41,124 @@ public class BpmSimpleModelServiceImpl implements BpmSimpleModelService {
29 if (model == null) { 41 if (model == null) {
30 throw exception(MODEL_NOT_EXISTS); 42 throw exception(MODEL_NOT_EXISTS);
31 } 43 }
32 - byte[] bpmnBytes = bpmModelService.getModelBpmnXML(reqVO.getModelId()); 44 +// byte[] bpmnBytes = bpmModelService.getModelBpmnXML(reqVO.getModelId());
  45 +// if (ArrayUtil.isEmpty(bpmnBytes)) {
  46 +// // BPMN XML 不存在。新增
  47 +// BpmnModel bpmnModel = BpmnModelUtils.convertSimpleModelToBpmnModel(model.getKey(), model.getName(), reqVO.getSimpleModelBody());
  48 +// bpmModelService.saveModelBpmnXml(model.getId(), BpmnModelUtils.getBpmnXml(bpmnModel));
  49 +// return Boolean.TRUE;
  50 +// } else {
  51 +// // TODO BPMN XML 已经存在。如何修改 ??
  52 +// return Boolean.FALSE;
  53 +// }
  54 + // 暂时直接修改
  55 + BpmnModel bpmnModel = BpmnModelUtils.convertSimpleModelToBpmnModel(model.getKey(), model.getName(), reqVO.getSimpleModelBody());
  56 + bpmModelService.saveModelBpmnXml(model.getId(), BpmnModelUtils.getBpmnXml(bpmnModel));
  57 + return Boolean.TRUE;
  58 + }
  59 +
  60 + @Override
  61 + public BpmSimpleModelNodeVO getSimpleModel(String modelId) {
  62 + Model model = bpmModelService.getModel(modelId);
  63 + if (model == null) {
  64 + throw exception(MODEL_NOT_EXISTS);
  65 + }
  66 + byte[] bpmnBytes = bpmModelService.getModelBpmnXML(modelId);
  67 + BpmnModel bpmnModel = BpmnModelUtils.getBpmnModel(bpmnBytes);
  68 + return convertBpmnModelToSimpleModel(bpmnModel);
  69 +
  70 + }
  71 +
  72 + /**
  73 + * Bpmn Model 转换成 仿钉钉流程设计模型数据结构(json) 待完善
  74 + *
  75 + * @param bpmnModel Bpmn Model
  76 + * @return 仿钉钉流程设计模型数据结构
  77 + */
  78 + private BpmSimpleModelNodeVO convertBpmnModelToSimpleModel(BpmnModel bpmnModel) {
  79 + if (bpmnModel == null) {
  80 + return null;
  81 + }
  82 + StartEvent startEvent = BpmnModelUtils.getStartEvent(bpmnModel);
  83 + if (startEvent == null) {
  84 + return null;
  85 + }
  86 + BpmSimpleModelNodeVO rootNode = new BpmSimpleModelNodeVO();
  87 + rootNode.setType(START_NODE.getType());
  88 + rootNode.setId(startEvent.getId());
  89 + rootNode.setName(startEvent.getName());
  90 + recursiveBuildSimpleModelNode(startEvent, rootNode);
  91 + return rootNode;
  92 +
  93 + }
33 94
34 - if (ArrayUtil.isEmpty(bpmnBytes)) {  
35 - // BPMN XML 不存在。新增  
36 - BpmnModel bpmnModel = BpmnModelUtils.convertSimpleModelToBpmnModel(model.getKey(), model.getName(), reqVO.getSimpleModelBody());  
37 - bpmModelService.saveModelBpmnXml(model.getId(),BpmnModelUtils.getBpmnXml(bpmnModel));  
38 - return Boolean.TRUE;  
39 - } else {  
40 - // TODO BPMN XML 已经存在。如何修改 ??  
41 - return Boolean.FALSE; 95 + private void recursiveBuildSimpleModelNode(FlowNode currentFlowNode, BpmSimpleModelNodeVO currentSimpleModeNode) {
  96 + BpmSimpleModelNodeType nodeType = BpmSimpleModelNodeType.valueOf(currentSimpleModeNode.getType());
  97 + Assert.notNull(nodeType, "节点类型不支持");
  98 + // 校验节点是否支持转仿钉钉的流程模型
  99 + List<SequenceFlow> outgoingFlows = validateCanConvertSimpleNode(nodeType, currentFlowNode);
  100 + if (CollUtil.isEmpty(outgoingFlows) || outgoingFlows.get(0).getTargetFlowElement() == null) {
  101 + return;
  102 + }
  103 + FlowElement targetElement = outgoingFlows.get(0).getTargetFlowElement();
  104 + // 如果是 EndEvent 直接退出
  105 + if (targetElement instanceof EndEvent) {
  106 + return;
  107 + }
  108 + if (targetElement instanceof UserTask) {
  109 + BpmSimpleModelNodeVO childNode = convertUserTaskToSimpleModelNode((UserTask) targetElement);
  110 + currentSimpleModeNode.setChildNode(childNode);
  111 + recursiveBuildSimpleModelNode((FlowNode) targetElement, childNode);
  112 + }
  113 + // TODO 其它节点类型待实现
  114 + }
  115 +
  116 +
  117 + private BpmSimpleModelNodeVO convertUserTaskToSimpleModelNode(UserTask userTask) {
  118 + BpmSimpleModelNodeVO simpleModelNodeVO = new BpmSimpleModelNodeVO();
  119 + simpleModelNodeVO.setType(BpmSimpleModelNodeType.APPROVE_USER_NODE.getType());
  120 + simpleModelNodeVO.setName(userTask.getName());
  121 + simpleModelNodeVO.setId(userTask.getId());
  122 + Map<String, Object> attributes = MapUtil.newHashMap();
  123 + // TODO 暂时是普通审批,需要加会签
  124 + attributes.put("approveMethod", 1);
  125 + attributes.computeIfAbsent(USER_TASK_CANDIDATE_STRATEGY, (key) -> BpmnModelUtils.parseCandidateStrategy(userTask));
  126 + attributes.computeIfAbsent(USER_TASK_CANDIDATE_PARAM, (key) -> BpmnModelUtils.parseCandidateParam(userTask));
  127 + simpleModelNodeVO.setAttributes(attributes);
  128 + return simpleModelNodeVO;
  129 + }
  130 +
  131 + private List<SequenceFlow> validateCanConvertSimpleNode(BpmSimpleModelNodeType nodeType, FlowNode currentFlowNode) {
  132 + switch (nodeType) {
  133 + case START_NODE:
  134 + case APPROVE_USER_NODE: {
  135 + List<SequenceFlow> outgoingFlows = currentFlowNode.getOutgoingFlows();
  136 + if (CollUtil.isNotEmpty(outgoingFlows) && outgoingFlows.size() > 1) {
  137 + throw exception(CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT);
  138 + }
  139 + validIsSupportFlowNode(outgoingFlows.get(0).getTargetFlowElement());
  140 + return outgoingFlows;
  141 + }
  142 + default: {
  143 + // TODO 其它节点类型待实现
  144 + throw exception(CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT);
  145 + }
  146 + }
  147 + }
  148 +
  149 + private void validIsSupportFlowNode(FlowElement targetElement) {
  150 + if (targetElement == null) {
  151 + return;
  152 + }
  153 + boolean isSupport = false;
  154 + for (Class<? extends FlowNode> item : BpmnModelConstants.SUPPORT_CONVERT_SIMPLE_FlOW_NODES) {
  155 + if (item.isInstance(targetElement)) {
  156 + isSupport = true;
  157 + break;
  158 + }
  159 + }
  160 + if (!isSupport) {
  161 + throw exception(CONVERT_TO_SIMPLE_MODEL_NOT_SUPPORT);
42 } 162 }
43 } 163 }
44 } 164 }