Commit 9e41576dc47bcf9a7d94fc61dcece8dbec966f21
1 parent
4d49952c
仿钉钉流程设计- 模型节点结构调整
Showing
7 changed files
with
122 additions
and
21 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.enums.definition; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ArrayUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 4 | 5 | import lombok.AllArgsConstructor; |
| 5 | 6 | import lombok.Getter; |
| 6 | 7 | |
| 8 | +import java.util.Arrays; | |
| 9 | + | |
| 7 | 10 | /** |
| 8 | 11 | * BPM 多人审批方式的枚举 |
| 9 | 12 | * |
| ... | ... | @@ -11,7 +14,7 @@ import lombok.Getter; |
| 11 | 14 | */ |
| 12 | 15 | @Getter |
| 13 | 16 | @AllArgsConstructor |
| 14 | -public enum BpmApproveMethodEnum { | |
| 17 | +public enum BpmApproveMethodEnum implements IntArrayValuable { | |
| 15 | 18 | |
| 16 | 19 | RANDOM_SELECT_ONE_APPROVE(1, "随机挑选一人审批"), |
| 17 | 20 | APPROVE_BY_RATIO(2, "多人会签(按通过比例)"), // 会签(按通过比例) |
| ... | ... | @@ -22,13 +25,20 @@ public enum BpmApproveMethodEnum { |
| 22 | 25 | * 审批方式 |
| 23 | 26 | */ |
| 24 | 27 | private final Integer method; |
| 28 | + | |
| 25 | 29 | /** |
| 26 | 30 | * 名字 |
| 27 | 31 | */ |
| 28 | 32 | private final String name; |
| 29 | 33 | |
| 34 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmApproveMethodEnum::getMethod).toArray(); | |
| 35 | + | |
| 30 | 36 | public static BpmApproveMethodEnum valueOf(Integer method) { |
| 31 | 37 | return ArrayUtil.firstMatch(item -> item.getMethod().equals(method), values()); |
| 32 | 38 | } |
| 33 | 39 | |
| 40 | + @Override | |
| 41 | + public int[] array() { | |
| 42 | + return ARRAYS; | |
| 43 | + } | |
| 34 | 44 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskRejectHandlerType.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.enums.definition; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ArrayUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 4 | 5 | import lombok.AllArgsConstructor; |
| 5 | 6 | import lombok.Getter; |
| 6 | 7 | |
| 8 | +import java.util.Arrays; | |
| 9 | + | |
| 7 | 10 | /** |
| 8 | 11 | * BPM 用户任务拒绝处理类型枚举 |
| 9 | 12 | * |
| ... | ... | @@ -11,7 +14,7 @@ import lombok.Getter; |
| 11 | 14 | */ |
| 12 | 15 | @Getter |
| 13 | 16 | @AllArgsConstructor |
| 14 | -public enum BpmUserTaskRejectHandlerType { | |
| 17 | +public enum BpmUserTaskRejectHandlerType implements IntArrayValuable { | |
| 15 | 18 | |
| 16 | 19 | FINISH_PROCESS(1, "终止流程"), |
| 17 | 20 | RETURN_USER_TASK(2, "驳回到指定任务节点"); |
| ... | ... | @@ -19,8 +22,14 @@ public enum BpmUserTaskRejectHandlerType { |
| 19 | 22 | private final Integer type; |
| 20 | 23 | private final String name; |
| 21 | 24 | |
| 25 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskRejectHandlerType::getType).toArray(); | |
| 26 | + | |
| 22 | 27 | public static BpmUserTaskRejectHandlerType typeOf(Integer type) { |
| 23 | 28 | return ArrayUtil.firstMatch(item -> item.getType().equals(type), values()); |
| 24 | 29 | } |
| 25 | 30 | |
| 31 | + @Override | |
| 32 | + public int[] array() { | |
| 33 | + return ARRAYS; | |
| 34 | + } | |
| 26 | 35 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskTimeoutActionEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.enums.definition; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ArrayUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 4 | 5 | import lombok.AllArgsConstructor; |
| 5 | 6 | import lombok.Getter; |
| 6 | 7 | |
| 8 | +import java.util.Arrays; | |
| 9 | + | |
| 7 | 10 | /** |
| 8 | 11 | * 用户任务超时处理执行动作枚举 |
| 9 | 12 | * |
| ... | ... | @@ -11,7 +14,7 @@ import lombok.Getter; |
| 11 | 14 | */ |
| 12 | 15 | @Getter |
| 13 | 16 | @AllArgsConstructor |
| 14 | -public enum BpmUserTaskTimeoutActionEnum { | |
| 17 | +public enum BpmUserTaskTimeoutActionEnum implements IntArrayValuable { | |
| 15 | 18 | |
| 16 | 19 | AUTO_REMINDER(1,"自动提醒"), |
| 17 | 20 | AUTO_APPROVE(2, "自动同意"), |
| ... | ... | @@ -20,7 +23,14 @@ public enum BpmUserTaskTimeoutActionEnum { |
| 20 | 23 | private final Integer action; |
| 21 | 24 | private final String name; |
| 22 | 25 | |
| 26 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmUserTaskTimeoutActionEnum::getAction).toArray(); | |
| 27 | + | |
| 23 | 28 | public static BpmUserTaskTimeoutActionEnum actionOf(Integer action) { |
| 24 | 29 | return ArrayUtil.firstMatch(item -> item.getAction().equals(action), values()); |
| 25 | 30 | } |
| 31 | + | |
| 32 | + @Override | |
| 33 | + public int[] array() { | |
| 34 | + return ARRAYS; | |
| 35 | + } | |
| 26 | 36 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.validation.InEnum; |
| 4 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmApproveMethodEnum; | |
| 4 | 5 | import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType; |
| 6 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskRejectHandlerType; | |
| 7 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutActionEnum; | |
| 8 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; | |
| 5 | 9 | import com.fasterxml.jackson.annotation.JsonIgnore; |
| 6 | 10 | import com.fasterxml.jackson.annotation.JsonInclude; |
| 7 | 11 | import io.swagger.v3.oas.annotations.media.Schema; |
| ... | ... | @@ -50,6 +54,64 @@ public class BpmSimpleModelNodeVO { |
| 50 | 54 | @JsonIgnore |
| 51 | 55 | private String attachNodeId; |
| 52 | 56 | |
| 57 | + @Schema(description = "候选人策略", example = "30") | |
| 58 | + @InEnum(BpmTaskCandidateStrategyEnum.class) | |
| 59 | + private Integer candidateStrategy; // 用于审批,抄送节点 | |
| 60 | + | |
| 61 | + @Schema(description = "候选人参数") | |
| 62 | + private String candidateParam; // 用于审批,抄送节点 | |
| 63 | + | |
| 64 | + @Schema(description = "多人审批方式", example = "1") | |
| 65 | + @InEnum(BpmApproveMethodEnum.class) // 用于审批节点 | |
| 66 | + private Integer approveMethod; | |
| 67 | + | |
| 68 | + @Schema(description = "表单权限", example = "[]") | |
| 69 | + private List<Map<String, String>> fieldsPermission; | |
| 70 | + | |
| 71 | + @Schema(description = "通过比例", example = "100") | |
| 72 | + private Integer approveRatio; // 通过比例 当多人审批方式为:多人会签(按通过比例) 需要设置 | |
| 73 | + | |
| 74 | + /** | |
| 75 | + * 审批节点拒绝处理 | |
| 76 | + */ | |
| 77 | + private RejectHandler rejectHandler; | |
| 78 | + | |
| 79 | + /** | |
| 80 | + * 审批节点超时处理 | |
| 81 | + */ | |
| 82 | + private TimeoutHandler timeoutHandler; | |
| 83 | + | |
| 84 | + @Data | |
| 85 | + @Schema(description = "审批节点拒绝处理策略") | |
| 86 | + public static class RejectHandler { | |
| 87 | + | |
| 88 | + @Schema(description = "拒绝处理类型", example = "1") | |
| 89 | + @InEnum(BpmUserTaskRejectHandlerType.class) | |
| 90 | + private Integer type; | |
| 91 | + | |
| 92 | + @Schema(description = "任务拒绝后驳回的节点 Id", example = "Activity_1") | |
| 93 | + private String returnNodeId; | |
| 94 | + } | |
| 95 | + | |
| 96 | + @Data | |
| 97 | + @Schema(description = "审批节点超时处理策略") | |
| 98 | + public static class TimeoutHandler { | |
| 99 | + | |
| 100 | + @Schema(description = "是否开启超时处理", example = "false") | |
| 101 | + private Boolean enable; | |
| 102 | + | |
| 103 | + @Schema(description = "任务超时未处理的行为", example = "1") | |
| 104 | + @InEnum(BpmUserTaskTimeoutActionEnum.class) | |
| 105 | + private Integer action; | |
| 106 | + | |
| 107 | + @Schema(description = "超时时间", example = "PT6H") | |
| 108 | + private String timeDuration; | |
| 109 | + | |
| 110 | + @Schema(description = "最大提醒次数", example = "1") | |
| 111 | + private Integer maxRemindCount; | |
| 112 | + } | |
| 113 | + | |
| 114 | + | |
| 53 | 115 | // Map<String, Integer> formPermissions; 表单权限;仅发起、审批、抄送节点会使用 |
| 54 | 116 | // Integer approveMethod; 审批方式;仅审批节点会使用 |
| 55 | 117 | // TODO @jason 后面和前端一起调整一下;下面的 ①、②、③ 是优先级 |
| ... | ... | @@ -61,4 +123,5 @@ public class BpmSimpleModelNodeVO { |
| 61 | 123 | // TODO @芋艿:⑨ 超时配置;要支持指定时间点、指定时间间隔; |
| 62 | 124 | // TODO @芋艿:条件;建议可以固化的一些选项;然后有个表达式兜底;要支持 |
| 63 | 125 | |
| 126 | + | |
| 64 | 127 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmTaskCandidateStrategyEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.framework.flowable.core.enums; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ArrayUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 4 | 5 | import lombok.AllArgsConstructor; |
| 5 | 6 | import lombok.Getter; |
| 6 | 7 | |
| 8 | +import java.util.Arrays; | |
| 9 | + | |
| 7 | 10 | /** |
| 8 | 11 | * BPM 任务的候选人策略枚举 |
| 9 | 12 | * |
| ... | ... | @@ -13,7 +16,7 @@ import lombok.Getter; |
| 13 | 16 | */ |
| 14 | 17 | @Getter |
| 15 | 18 | @AllArgsConstructor |
| 16 | -public enum BpmTaskCandidateStrategyEnum { | |
| 19 | +public enum BpmTaskCandidateStrategyEnum implements IntArrayValuable { | |
| 17 | 20 | |
| 18 | 21 | ROLE(10, "角色"), |
| 19 | 22 | DEPT_MEMBER(20, "部门的成员"), // 包括负责人 |
| ... | ... | @@ -26,6 +29,8 @@ public enum BpmTaskCandidateStrategyEnum { |
| 26 | 29 | EXPRESSION(60, "流程表达式"), // 表达式 ExpressionManager |
| 27 | 30 | ; |
| 28 | 31 | |
| 32 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmTaskCandidateStrategyEnum::getStrategy).toArray(); | |
| 33 | + | |
| 29 | 34 | /** |
| 30 | 35 | * 类型 |
| 31 | 36 | */ |
| ... | ... | @@ -39,4 +44,9 @@ public enum BpmTaskCandidateStrategyEnum { |
| 39 | 44 | return ArrayUtil.firstMatch(o -> o.getStrategy().equals(strategy), values()); |
| 40 | 45 | } |
| 41 | 46 | |
| 47 | + @Override | |
| 48 | + public int[] array() { | |
| 49 | + return ARRAYS; | |
| 50 | + } | |
| 51 | + | |
| 42 | 52 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
| ... | ... | @@ -8,13 +8,12 @@ import cn.hutool.core.map.MapUtil; |
| 8 | 8 | import cn.hutool.core.util.*; |
| 9 | 9 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 10 | 10 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; |
| 11 | +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.RejectHandler; | |
| 11 | 12 | import cn.iocoder.yudao.module.bpm.enums.definition.BpmApproveMethodEnum; |
| 12 | 13 | import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModeConditionType; |
| 13 | 14 | import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType; |
| 14 | 15 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; |
| 15 | 16 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.simplemodel.SimpleModelConditionGroups; |
| 16 | -import cn.iocoder.yudao.module.bpm.framework.flowable.core.simplemodel.SimpleModelUserTaskConfig; | |
| 17 | -import cn.iocoder.yudao.module.bpm.framework.flowable.core.simplemodel.SimpleModelUserTaskConfig.RejectHandler; | |
| 18 | 17 | import org.flowable.bpmn.BpmnAutoLayout; |
| 19 | 18 | import org.flowable.bpmn.model.Process; |
| 20 | 19 | import org.flowable.bpmn.model.*; |
| ... | ... | @@ -24,6 +23,7 @@ import java.util.List; |
| 24 | 23 | import java.util.Map; |
| 25 | 24 | import java.util.Objects; |
| 26 | 25 | |
| 26 | +import static cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TimeoutHandler; | |
| 27 | 27 | import static cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType.USER_TASK_TIMEOUT; |
| 28 | 28 | import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.*; |
| 29 | 29 | import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutActionEnum.AUTO_REMINDER; |
| ... | ... | @@ -336,18 +336,17 @@ public class SimpleModelUtils { |
| 336 | 336 | |
| 337 | 337 | private static List<FlowElement> convertApproveNode(BpmSimpleModelNodeVO node) { |
| 338 | 338 | List<FlowElement> flowElements = new ArrayList<>(); |
| 339 | - SimpleModelUserTaskConfig userTaskConfig = BeanUtil.toBean(node.getAttributes(), SimpleModelUserTaskConfig.class); | |
| 340 | - UserTask userTask = buildBpmnUserTask(node, userTaskConfig); | |
| 339 | + UserTask userTask = buildBpmnUserTask(node); | |
| 341 | 340 | flowElements.add(userTask); |
| 342 | - if (userTaskConfig.getTimeoutHandler() != null && userTaskConfig.getTimeoutHandler().getEnable()) { | |
| 341 | + if (node.getTimeoutHandler() != null && node.getTimeoutHandler().getEnable()) { | |
| 343 | 342 | // 添加用户任务的 Timer Boundary Event, 用于任务的超时处理 |
| 344 | - BoundaryEvent boundaryEvent = buildUserTaskTimerBoundaryEvent(userTask, userTaskConfig.getTimeoutHandler()); | |
| 343 | + BoundaryEvent boundaryEvent = buildUserTaskTimerBoundaryEvent(userTask, node.getTimeoutHandler()); | |
| 345 | 344 | flowElements.add(boundaryEvent); |
| 346 | 345 | } |
| 347 | 346 | return flowElements; |
| 348 | 347 | } |
| 349 | 348 | |
| 350 | - private static BoundaryEvent buildUserTaskTimerBoundaryEvent(UserTask userTask, SimpleModelUserTaskConfig.TimeoutHandler timeoutHandler) { | |
| 349 | + private static BoundaryEvent buildUserTaskTimerBoundaryEvent(UserTask userTask, TimeoutHandler timeoutHandler) { | |
| 351 | 350 | // 定时器边界事件 |
| 352 | 351 | BoundaryEvent boundaryEvent = new BoundaryEvent(); |
| 353 | 352 | boundaryEvent.setId("Event-" + IdUtil.fastUUID()); |
| ... | ... | @@ -444,26 +443,26 @@ public class SimpleModelUtils { |
| 444 | 443 | return inclusiveGateway; |
| 445 | 444 | } |
| 446 | 445 | |
| 447 | - private static UserTask buildBpmnUserTask(BpmSimpleModelNodeVO node, SimpleModelUserTaskConfig userTaskConfig) { | |
| 446 | + private static UserTask buildBpmnUserTask(BpmSimpleModelNodeVO node) { | |
| 448 | 447 | UserTask userTask = new UserTask(); |
| 449 | 448 | userTask.setId(node.getId()); |
| 450 | 449 | userTask.setName(node.getName()); |
| 451 | 450 | // 设置审批任务的截止时间 |
| 452 | - if (userTaskConfig.getTimeoutHandler() != null && userTaskConfig.getTimeoutHandler().getEnable()) { | |
| 453 | - userTask.setDueDate(userTaskConfig.getTimeoutHandler().getTimeDuration()); | |
| 451 | + if (node.getTimeoutHandler() != null && node.getTimeoutHandler().getEnable()) { | |
| 452 | + userTask.setDueDate(node.getTimeoutHandler().getTimeDuration()); | |
| 454 | 453 | } |
| 455 | 454 | |
| 456 | 455 | // TODO 芋艿 + jason:要不要基于服务任务,实现或签下的审批不通过?或者说,按比例审批 |
| 457 | 456 | |
| 458 | 457 | // TODO @jason:addCandidateElements、processMultiInstanceLoopCharacteristics 建议一起搞哈? |
| 459 | 458 | // 添加候选人元素 |
| 460 | - addCandidateElements(userTaskConfig.getCandidateStrategy(), userTaskConfig.getCandidateParam(), userTask); | |
| 459 | + addCandidateElements(node.getCandidateStrategy(), node.getCandidateParam(), userTask); | |
| 461 | 460 | // 添加表单字段权限属性元素 |
| 462 | - addFormFieldsPermission(userTaskConfig.getFieldsPermission(), userTask); | |
| 461 | + addFormFieldsPermission(node.getFieldsPermission(), userTask); | |
| 463 | 462 | // 处理多实例 |
| 464 | - processMultiInstanceLoopCharacteristics(userTaskConfig.getApproveMethod(), userTaskConfig.getApproveRatio(), userTask); | |
| 463 | + processMultiInstanceLoopCharacteristics(node.getApproveMethod(), node.getApproveRatio(), userTask); | |
| 465 | 464 | // 添加任务被拒绝的处理元素 |
| 466 | - addTaskRejectElements(userTaskConfig.getRejectHandler(), userTask); | |
| 465 | + addTaskRejectElements(node.getRejectHandler(), userTask); | |
| 467 | 466 | return userTask; |
| 468 | 467 | } |
| 469 | 468 | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| ... | ... | @@ -350,7 +350,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 350 | 350 | } |
| 351 | 351 | // 3.2.2 添加评论 |
| 352 | 352 | taskService.addComment(task.getParentTaskId(), task.getProcessInstanceId(), |
| 353 | - BpmCommentTypeEnum.REJECT.getType(), BpmCommentTypeEnum.REJECT.formatComment(REJECT_BY_ADD_SIGN_TASK_REJECT)); | |
| 353 | + BpmCommentTypeEnum.REJECT.getType(), REJECT_BY_ADD_SIGN_TASK_REJECT.getComment()); | |
| 354 | 354 | // 3.2.3 更新还在进行中的加签任务状态为取消 |
| 355 | 355 | List<Task> addSignTaskList = getTaskListByParentTaskId(task.getParentTaskId()); |
| 356 | 356 | updateTaskStatusWhenCanceled(CollectionUtils.filterList(addSignTaskList, item -> !item.getId().equals(task.getId())), |
| ... | ... | @@ -375,10 +375,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 375 | 375 | updateTaskStatusWhenCanceled(CollectionUtils.filterList(taskList, item -> !item.getId().equals(task.getId()) && !item.getId().equals(task.getParentTaskId())), |
| 376 | 376 | reqVO.getReason()); |
| 377 | 377 | // 4.2.2 终止流程 |
| 378 | - List<String> activityIds = convertList(taskList, Task::getTaskDefinitionKey); | |
| 378 | + Set<String> activityIds = convertSet(taskList, Task::getTaskDefinitionKey); | |
| 379 | 379 | EndEvent endEvent = BpmnModelUtils.getEndEvent(bpmnModel); |
| 380 | 380 | Assert.notNull(endEvent, "结束节点不能未空"); |
| 381 | - processInstanceService.updateProcessInstanceReject(instance, activityIds, endEvent.getId(), reqVO.getReason()); | |
| 381 | + processInstanceService.updateProcessInstanceReject(instance, CollUtil.newArrayList(activityIds), endEvent.getId(), reqVO.getReason()); | |
| 382 | 382 | } |
| 383 | 383 | |
| 384 | 384 | private void updateTaskStatusWhenCanceled(List<Task> taskList, String reason) { | ... | ... |