Commit e4fbc11dc453e86097270a2131bd1314186f3cb0
1 parent
cb5cfd31
仿钉钉流程设计- 前端重构调整, 新增多人审批方式
Showing
4 changed files
with
105 additions
and
8 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmApproveMethodEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.enums.definition; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.ArrayUtil; | |
| 4 | +import lombok.AllArgsConstructor; | |
| 5 | +import lombok.Getter; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * BPM 审批方式的枚举 | |
| 9 | + * | |
| 10 | + * @author jason | |
| 11 | + */ | |
| 12 | +@Getter | |
| 13 | +@AllArgsConstructor | |
| 14 | +public enum BpmApproveMethodEnum { | |
| 15 | + | |
| 16 | + SINGLE_PERSON_APPROVE(1, "单人审批"), | |
| 17 | + ALL_APPROVE(2, "多人会签(需所有审批人同意)"), | |
| 18 | + ANY_OF_APPROVE(3, "多人或签(一名审批人同意即可)"), | |
| 19 | + SEQUENTIAL_APPROVE(4, "依次审批"); | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 审批方式 | |
| 23 | + */ | |
| 24 | + private final Integer method; | |
| 25 | + /** | |
| 26 | + * 名字 | |
| 27 | + */ | |
| 28 | + private final String name; | |
| 29 | + | |
| 30 | + public static BpmApproveMethodEnum valueOf(Integer method) { | |
| 31 | + return ArrayUtil.firstMatch(item -> item.getMethod().equals(method), values()); | |
| 32 | + } | |
| 33 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/simple/BpmSimpleModelNodeVO.java
| ... | ... | @@ -28,6 +28,9 @@ public class BpmSimpleModelNodeVO { |
| 28 | 28 | @Schema(description = "模型节点名称", example = "领导审批") |
| 29 | 29 | private String name; |
| 30 | 30 | |
| 31 | + @Schema(description = "节点展示内容", example = "指定成员: 芋道源码") | |
| 32 | + private String showText; | |
| 33 | + | |
| 31 | 34 | @Schema(description = "孩子节点") |
| 32 | 35 | private BpmSimpleModelNodeVO childNode; |
| 33 | 36 | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/SimpleModelConstants.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
| ... | ... | @@ -7,8 +7,10 @@ import cn.hutool.core.map.MapUtil; |
| 7 | 7 | import cn.hutool.core.util.ArrayUtil; |
| 8 | 8 | import cn.hutool.core.util.StrUtil; |
| 9 | 9 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.simple.BpmSimpleModelNodeVO; |
| 10 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmApproveMethodEnum; | |
| 10 | 11 | import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType; |
| 11 | 12 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; |
| 13 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants; | |
| 12 | 14 | import org.flowable.bpmn.BpmnAutoLayout; |
| 13 | 15 | import org.flowable.bpmn.model.Process; |
| 14 | 16 | import org.flowable.bpmn.model.*; |
| ... | ... | @@ -16,6 +18,7 @@ import org.flowable.bpmn.model.*; |
| 16 | 18 | import java.util.List; |
| 17 | 19 | import java.util.Map; |
| 18 | 20 | |
| 21 | +import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.END_EVENT; | |
| 19 | 22 | import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.FORM_FIELD_PERMISSION_ELEMENT; |
| 20 | 23 | import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_NAMESPACE; |
| 21 | 24 | import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_PREFIX; |
| ... | ... | @@ -30,6 +33,16 @@ public class SimpleModelUtils { |
| 30 | 33 | public static final String BPMN_SIMPLE_COPY_EXECUTION_SCRIPT = "#{bpmSimpleNodeService.copy(execution)}"; |
| 31 | 34 | |
| 32 | 35 | /** |
| 36 | + * 所有审批人同意的表达式 | |
| 37 | + */ | |
| 38 | + public static final String ALL_APPROVE_COMPLETE_EXPRESSION = "${ nrOfCompletedInstances >= 0 }"; | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 任一一名审批人同意的表达式 | |
| 42 | + */ | |
| 43 | + public static final String ANY_OF_APPROVE_COMPLETE_EXPRESSION = "${ nrOfCompletedInstances >= nrOfInstances }"; | |
| 44 | + | |
| 45 | + /** | |
| 33 | 46 | * 仿钉钉流程设计模型数据结构(json) 转换成 Bpmn Model (待完善) |
| 34 | 47 | * |
| 35 | 48 | * @param processId 流程标识 |
| ... | ... | @@ -47,10 +60,15 @@ public class SimpleModelUtils { |
| 47 | 60 | // 前端模型数据结构。 有 start event 节点. 没有 end event 节点。 |
| 48 | 61 | // 从 SimpleModel 构建 FlowNode 并添加到 Main Process |
| 49 | 62 | buildAndAddBpmnFlowNode(simpleModelNode, mainProcess); |
| 50 | - // 单独构建 end event 节点 | |
| 51 | - buildAndAddBpmnEndEvent(mainProcess); | |
| 63 | + // 找到 end event | |
| 64 | + EndEvent endEvent = (EndEvent) CollUtil.findOne(mainProcess.getFlowElements(), item -> item instanceof EndEvent); | |
| 65 | + if (endEvent == null) { | |
| 66 | + // 暂时为了兼容 单独构建 end event 节点 | |
| 67 | + endEvent = buildAndAddBpmnEndEvent(mainProcess); | |
| 68 | + } | |
| 69 | + | |
| 52 | 70 | // 构建并添加节点之间的连线 Sequence Flow |
| 53 | - buildAndAddBpmnSequenceFlow(mainProcess, simpleModelNode, BpmnModelConstants.END_EVENT_ID); | |
| 71 | + buildAndAddBpmnSequenceFlow(mainProcess, simpleModelNode, endEvent.getId()); | |
| 54 | 72 | // 自动布局 |
| 55 | 73 | new BpmnAutoLayout(bpmnModel).execute(); |
| 56 | 74 | return bpmnModel; |
| ... | ... | @@ -58,7 +76,7 @@ public class SimpleModelUtils { |
| 58 | 76 | |
| 59 | 77 | private static void buildAndAddBpmnSequenceFlow(Process mainProcess, BpmSimpleModelNodeVO node, String targetId) { |
| 60 | 78 | // 节点为 null 退出 |
| 61 | - if (node == null || node.getId() == null) { | |
| 79 | + if (node == null || node.getId() == null || END_EVENT.getType().equals(node.getType())) { | |
| 62 | 80 | return; |
| 63 | 81 | } |
| 64 | 82 | BpmSimpleModelNodeVO childNode = node.getChildNode(); |
| ... | ... | @@ -169,6 +187,11 @@ public class SimpleModelUtils { |
| 169 | 187 | mainProcess.addFlowElement(inclusiveGateway); |
| 170 | 188 | break; |
| 171 | 189 | } |
| 190 | + case END_EVENT: { | |
| 191 | + EndEvent endEvent = buildBpmnEndEvent(simpleModelNode); | |
| 192 | + mainProcess.addFlowElement(endEvent); | |
| 193 | + break; | |
| 194 | + } | |
| 172 | 195 | default: { |
| 173 | 196 | // TODO 其它节点类型的实现 |
| 174 | 197 | } |
| ... | ... | @@ -242,32 +265,59 @@ public class SimpleModelUtils { |
| 242 | 265 | return inclusiveGateway; |
| 243 | 266 | } |
| 244 | 267 | |
| 245 | - private static void buildAndAddBpmnEndEvent(Process mainProcess) { | |
| 268 | + private static EndEvent buildAndAddBpmnEndEvent(Process mainProcess) { | |
| 246 | 269 | EndEvent endEvent = new EndEvent(); |
| 247 | 270 | endEvent.setId(BpmnModelConstants.END_EVENT_ID); |
| 248 | 271 | endEvent.setName("结束"); |
| 249 | 272 | mainProcess.addFlowElement(endEvent); |
| 273 | + return endEvent; | |
| 250 | 274 | } |
| 251 | 275 | |
| 252 | 276 | private static UserTask buildBpmnUserTask(BpmSimpleModelNodeVO node) { |
| 253 | 277 | UserTask userTask = new UserTask(); |
| 254 | 278 | userTask.setId(node.getId()); |
| 255 | 279 | userTask.setName(node.getName()); |
| 256 | - // TODO 暂时测试,后面去掉 | |
| 257 | - userTask.setFormKey("24"); | |
| 258 | 280 | // 添加候选人元素 |
| 259 | 281 | addCandidateElements(node, userTask); |
| 260 | 282 | // 添加表单字段权限属性元素 |
| 261 | 283 | addFormFieldsPermission(node, userTask); |
| 284 | + // 处理多实例 | |
| 285 | + processMultiInstanceLoopCharacteristics(node, userTask); | |
| 262 | 286 | return userTask; |
| 263 | 287 | } |
| 264 | 288 | |
| 289 | + private static void processMultiInstanceLoopCharacteristics(BpmSimpleModelNodeVO node, UserTask userTask) { | |
| 290 | + Integer approveMethod = MapUtil.getInt(node.getAttributes(), SimpleModelConstants.APPROVE_METHOD_ATTRIBUTE); | |
| 291 | + BpmApproveMethodEnum bpmApproveMethodEnum = BpmApproveMethodEnum.valueOf(approveMethod); | |
| 292 | + if (bpmApproveMethodEnum == null || bpmApproveMethodEnum == BpmApproveMethodEnum.SINGLE_PERSON_APPROVE) { | |
| 293 | + return; | |
| 294 | + } | |
| 295 | + MultiInstanceLoopCharacteristics multiInstanceCharacteristics = new MultiInstanceLoopCharacteristics(); | |
| 296 | + // 设置 collectionVariable。本系统用不到。会在 仅仅为了校验。 | |
| 297 | + multiInstanceCharacteristics.setInputDataItem("${coll_userList}"); | |
| 298 | + if (bpmApproveMethodEnum == BpmApproveMethodEnum.ALL_APPROVE) { | |
| 299 | + multiInstanceCharacteristics.setCompletionCondition(ALL_APPROVE_COMPLETE_EXPRESSION); | |
| 300 | + multiInstanceCharacteristics.setSequential(false); | |
| 301 | + } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.ANY_OF_APPROVE) { | |
| 302 | + multiInstanceCharacteristics.setCompletionCondition(ANY_OF_APPROVE_COMPLETE_EXPRESSION); | |
| 303 | + multiInstanceCharacteristics.setSequential(false); | |
| 304 | + userTask.setLoopCharacteristics(multiInstanceCharacteristics); | |
| 305 | + } else if (bpmApproveMethodEnum == BpmApproveMethodEnum.SEQUENTIAL_APPROVE) { | |
| 306 | + multiInstanceCharacteristics.setCompletionCondition(ALL_APPROVE_COMPLETE_EXPRESSION); | |
| 307 | + multiInstanceCharacteristics.setSequential(true); | |
| 308 | + multiInstanceCharacteristics.setLoopCardinality("1"); | |
| 309 | + userTask.setLoopCharacteristics(multiInstanceCharacteristics); | |
| 310 | + } | |
| 311 | + userTask.setLoopCharacteristics(multiInstanceCharacteristics); | |
| 312 | + } | |
| 313 | + | |
| 265 | 314 | /** |
| 266 | 315 | * 给节点添加表单字段权限元素 |
| 267 | 316 | */ |
| 268 | 317 | private static void addFormFieldsPermission(BpmSimpleModelNodeVO node, FlowElement flowElement) { |
| 269 | 318 | List<Map<String, String>> fieldsPermissions = MapUtil.get(node.getAttributes(), |
| 270 | - FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() {}); | |
| 319 | + FORM_FIELD_PERMISSION_ELEMENT, new TypeReference<>() { | |
| 320 | + }); | |
| 271 | 321 | if (CollUtil.isNotEmpty(fieldsPermissions)) { |
| 272 | 322 | fieldsPermissions.forEach(item -> addExtensionElement(flowElement, FORM_FIELD_PERMISSION_ELEMENT, item)); |
| 273 | 323 | } |
| ... | ... | @@ -307,4 +357,11 @@ public class SimpleModelUtils { |
| 307 | 357 | startEvent.setName(node.getName()); |
| 308 | 358 | return startEvent; |
| 309 | 359 | } |
| 360 | + | |
| 361 | + private static EndEvent buildBpmnEndEvent(BpmSimpleModelNodeVO node) { | |
| 362 | + EndEvent endEvent = new EndEvent(); | |
| 363 | + endEvent.setId(node.getId()); | |
| 364 | + endEvent.setName(node.getName()); | |
| 365 | + return endEvent; | |
| 366 | + } | |
| 310 | 367 | } | ... | ... |