Commit b504d9841e37c23cfed48640d641d47529fb4314
1 parent
210b4e54
仿钉钉流程设计-后端实现30%
Showing
6 changed files
with
186 additions
and
51 deletions
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 | } |