Commit a23b0480f159eaad446b7b93b182b565f8c455de
1 parent
362b872a
【功能新增】 新增修改流程表单数据触发器
Showing
5 changed files
with
137 additions
and
53 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTriggerTypeEnum.java
| ... | ... | @@ -16,7 +16,9 @@ import java.util.Arrays; |
| 16 | 16 | @AllArgsConstructor |
| 17 | 17 | public enum BpmTriggerTypeEnum implements ArrayValuable<Integer> { |
| 18 | 18 | |
| 19 | - HTTP_REQUEST(1, "发起 HTTP 请求"); | |
| 19 | + HTTP_REQUEST(1, "发起 HTTP 请求"), | |
| 20 | + UPDATE_NORMAL_FORM(2, "更新流程表单"); | |
| 21 | + | |
| 20 | 22 | |
| 21 | 23 | /** |
| 22 | 24 | * 触发器执行动作类型 | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
| ... | ... | @@ -345,6 +345,11 @@ public class BpmSimpleModelNodeVO { |
| 345 | 345 | @Valid |
| 346 | 346 | private HttpRequestTriggerSetting httpRequestSetting; |
| 347 | 347 | |
| 348 | + /** | |
| 349 | + * 更新流程表单触发器设置 | |
| 350 | + */ | |
| 351 | + private UpdateNormalFormTriggerSetting updateNormalFormSetting; | |
| 352 | + | |
| 348 | 353 | @Schema(description = "http 请求触发器设置", example = "{}") |
| 349 | 354 | @Data |
| 350 | 355 | public static class HttpRequestTriggerSetting { |
| ... | ... | @@ -365,14 +370,32 @@ public class BpmSimpleModelNodeVO { |
| 365 | 370 | // TODO @json:可能未来看情况,搞个 HttpResponseParam;得看看有没别的业务需要,抽象统一 |
| 366 | 371 | /** |
| 367 | 372 | * 请求返回处理设置,用于修改流程表单值 |
| 368 | - * | |
| 373 | + * <p> | |
| 369 | 374 | * key:表示要修改的流程表单字段名(name) |
| 370 | 375 | * value:接口返回的字段名 |
| 371 | 376 | */ |
| 372 | 377 | @Schema(description = "请求返回处理设置", example = "[]") |
| 373 | 378 | private List<KeyValue<String, String>> response; |
| 374 | - | |
| 375 | 379 | } |
| 376 | 380 | |
| 381 | + @Schema(description = "更新流程表单触发器设置", example = "{}") | |
| 382 | + @Data | |
| 383 | + public static class UpdateNormalFormTriggerSetting { | |
| 384 | + | |
| 385 | + @Schema(description = "条件类型", example = "1") | |
| 386 | + @InEnum(BpmSimpleModeConditionTypeEnum.class) | |
| 387 | + @NotNull(message = "条件类型不能为空") | |
| 388 | + private Integer conditionType; | |
| 389 | + | |
| 390 | + @Schema(description = "条件表达式", example = "${day>3}") | |
| 391 | + private String conditionExpression; | |
| 392 | + | |
| 393 | + @Schema(description = "条件组", example = "{}") | |
| 394 | + private ConditionGroups conditionGroups; | |
| 395 | + | |
| 396 | + @Schema(description = "更新的表单字段", example = "userName") | |
| 397 | + @NotEmpty(message = "更新的表单字段不能为空") | |
| 398 | + private Map<String, Object> updateFormFields; | |
| 399 | + } | |
| 377 | 400 | } |
| 378 | 401 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
| ... | ... | @@ -64,6 +64,13 @@ public class BpmnModelUtils { |
| 64 | 64 | addExtensionElement(element, name, String.valueOf(value)); |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | + public static void addExtensionElementJson(FlowElement element, String name, Object value) { | |
| 68 | + if (value == null) { | |
| 69 | + return; | |
| 70 | + } | |
| 71 | + addExtensionElement(element, name, JsonUtils.toJsonString(value)); | |
| 72 | + } | |
| 73 | + | |
| 67 | 74 | public static void addExtensionElement(FlowElement element, String name, Map<String, String> attributes) { |
| 68 | 75 | if (attributes == null) { |
| 69 | 76 | return; | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
| ... | ... | @@ -5,7 +5,6 @@ import cn.hutool.core.lang.Assert; |
| 5 | 5 | import cn.hutool.core.map.MapUtil; |
| 6 | 6 | import cn.hutool.core.util.*; |
| 7 | 7 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 8 | -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | |
| 9 | 8 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; |
| 10 | 9 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups; |
| 11 | 10 | import cn.iocoder.yudao.module.bpm.enums.definition.*; |
| ... | ... | @@ -626,54 +625,52 @@ public class SimpleModelUtils { |
| 626 | 625 | |
| 627 | 626 | public static SequenceFlow buildSequenceFlow(String sourceId, String targetId, |
| 628 | 627 | BpmSimpleModelNodeVO node) { |
| 629 | - String conditionExpression = buildConditionExpression(node); | |
| 628 | + String conditionExpression = buildConditionExpression(node.getConditionSetting()); | |
| 630 | 629 | return buildBpmnSequenceFlow(sourceId, targetId, node.getId(), node.getName(), conditionExpression); |
| 631 | 630 | } |
| 632 | 631 | |
| 633 | - /** | |
| 634 | - * 构造条件表达式 | |
| 635 | - * | |
| 636 | - * @param node 条件节点 | |
| 637 | - */ | |
| 638 | - public static String buildConditionExpression(BpmSimpleModelNodeVO node) { | |
| 639 | - return buildConditionExpression(node.getConditionSetting().getConditionType(), node.getConditionSetting().getConditionExpression(), | |
| 640 | - node.getConditionSetting().getConditionGroups()); | |
| 641 | - } | |
| 642 | 632 | |
| 643 | - public static String buildConditionExpression(BpmSimpleModelNodeVO.RouterSetting router) { | |
| 644 | - return buildConditionExpression(router.getConditionType(), router.getConditionExpression(), | |
| 645 | - router.getConditionGroups()); | |
| 646 | - } | |
| 633 | + } | |
| 647 | 634 | |
| 648 | - public static String buildConditionExpression(Integer conditionType, String conditionExpression, | |
| 649 | - ConditionGroups conditionGroups) { | |
| 650 | - BpmSimpleModeConditionTypeEnum conditionTypeEnum = BpmSimpleModeConditionTypeEnum.valueOf(conditionType); | |
| 651 | - if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.EXPRESSION) { | |
| 652 | - return conditionExpression; | |
| 635 | + /** | |
| 636 | + * 构造条件表达式 | |
| 637 | + */ | |
| 638 | + public static String buildConditionExpression(BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { | |
| 639 | + return buildConditionExpression(conditionSetting.getConditionType(), conditionSetting.getConditionExpression(), | |
| 640 | + conditionSetting.getConditionGroups()); | |
| 641 | + } | |
| 642 | + | |
| 643 | + public static String buildConditionExpression(BpmSimpleModelNodeVO.RouterSetting routerSetting) { | |
| 644 | + return buildConditionExpression(routerSetting.getConditionType(), routerSetting.getConditionExpression(), | |
| 645 | + routerSetting.getConditionGroups()); | |
| 646 | + } | |
| 647 | + | |
| 648 | + public static String buildConditionExpression(Integer conditionType, String conditionExpression, ConditionGroups conditionGroups) { | |
| 649 | + BpmSimpleModeConditionTypeEnum conditionTypeEnum = BpmSimpleModeConditionTypeEnum.valueOf(conditionType); | |
| 650 | + if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.EXPRESSION) { | |
| 651 | + return conditionExpression; | |
| 652 | + } | |
| 653 | + if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.RULE) { | |
| 654 | + if (conditionGroups == null || CollUtil.isEmpty(conditionGroups.getConditions())) { | |
| 655 | + return null; | |
| 653 | 656 | } |
| 654 | - if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.RULE) { | |
| 655 | - if (conditionGroups == null || CollUtil.isEmpty(conditionGroups.getConditions())) { | |
| 656 | - return null; | |
| 657 | + List<String> strConditionGroups = CollectionUtils.convertList(conditionGroups.getConditions(), item -> { | |
| 658 | + if (CollUtil.isEmpty(item.getRules())) { | |
| 659 | + return ""; | |
| 657 | 660 | } |
| 658 | - List<String> strConditionGroups = CollectionUtils.convertList(conditionGroups.getConditions(), item -> { | |
| 659 | - if (CollUtil.isEmpty(item.getRules())) { | |
| 660 | - return ""; | |
| 661 | - } | |
| 662 | - // 构造规则表达式 | |
| 663 | - List<String> list = CollectionUtils.convertList(item.getRules(), (rule) -> { | |
| 664 | - String rightSide = NumberUtil.isNumber(rule.getRightSide()) ? rule.getRightSide() | |
| 665 | - : "\"" + rule.getRightSide() + "\""; // 如果非数值类型加引号 | |
| 666 | - return String.format(" %s %s var:convertByType(%s,%s)", rule.getLeftSide(), rule.getOpCode(), rule.getLeftSide(), rightSide); | |
| 667 | - }); | |
| 668 | - // 构造条件组的表达式 | |
| 669 | - Boolean and = item.getAnd(); | |
| 670 | - return "(" + CollUtil.join(list, and ? " && " : " || ") + ")"; | |
| 661 | + // 构造规则表达式 | |
| 662 | + List<String> list = CollectionUtils.convertList(item.getRules(), (rule) -> { | |
| 663 | + String rightSide = NumberUtil.isNumber(rule.getRightSide()) ? rule.getRightSide() | |
| 664 | + : "\"" + rule.getRightSide() + "\""; // 如果非数值类型加引号 | |
| 665 | + return String.format(" %s %s var:convertByType(%s,%s)", rule.getLeftSide(), rule.getOpCode(), rule.getLeftSide(), rightSide); | |
| 671 | 666 | }); |
| 672 | - return String.format("${%s}", CollUtil.join(strConditionGroups, conditionGroups.getAnd() ? " && " : " || ")); | |
| 673 | - } | |
| 674 | - return null; | |
| 667 | + // 构造条件组的表达式 | |
| 668 | + Boolean and = item.getAnd(); | |
| 669 | + return "(" + CollUtil.join(list, and ? " && " : " || ") + ")"; | |
| 670 | + }); | |
| 671 | + return String.format("${%s}", CollUtil.join(strConditionGroups, conditionGroups.getAnd() ? " && " : " || ")); | |
| 675 | 672 | } |
| 676 | - | |
| 673 | + return null; | |
| 677 | 674 | } |
| 678 | 675 | |
| 679 | 676 | public static class DelayTimerNodeConvert implements NodeConvert { |
| ... | ... | @@ -727,9 +724,10 @@ public class SimpleModelUtils { |
| 727 | 724 | if (node.getTriggerSetting() != null) { |
| 728 | 725 | addExtensionElement(serviceTask, TRIGGER_TYPE, node.getTriggerSetting().getType()); |
| 729 | 726 | if (node.getTriggerSetting().getHttpRequestSetting() != null) { |
| 730 | - // TODO @jason:加个 addExtensionElementJson 方法,方便设置 JSON 类型的属性 | |
| 731 | - addExtensionElement(serviceTask, TRIGGER_PARAM, | |
| 732 | - JsonUtils.toJsonString(node.getTriggerSetting().getHttpRequestSetting())); | |
| 727 | + addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getHttpRequestSetting()); | |
| 728 | + } | |
| 729 | + if (node.getTriggerSetting().getUpdateNormalFormSetting() != null) { | |
| 730 | + addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getUpdateNormalFormSetting()); | |
| 733 | 731 | } |
| 734 | 732 | } |
| 735 | 733 | return serviceTask; |
| ... | ... | @@ -760,7 +758,7 @@ public class SimpleModelUtils { |
| 760 | 758 | } |
| 761 | 759 | |
| 762 | 760 | public static SequenceFlow buildSequenceFlow(String nodeId, BpmSimpleModelNodeVO.RouterSetting router) { |
| 763 | - String conditionExpression = ConditionNodeConvert.buildConditionExpression(router); | |
| 761 | + String conditionExpression = SimpleModelUtils.buildConditionExpression(router); | |
| 764 | 762 | return buildBpmnSequenceFlow(nodeId, router.getNodeId(), null, null, conditionExpression); |
| 765 | 763 | } |
| 766 | 764 | |
| ... | ... | @@ -804,7 +802,7 @@ public class SimpleModelUtils { |
| 804 | 802 | // 查找满足条件的 BpmSimpleModelNodeVO 节点 |
| 805 | 803 | BpmSimpleModelNodeVO matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(), |
| 806 | 804 | conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()) |
| 807 | - && evalConditionExpress(variables, conditionNode)); | |
| 805 | + && evalConditionExpress(variables, conditionNode.getConditionSetting())); | |
| 808 | 806 | if (matchConditionNode == null) { |
| 809 | 807 | matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(), |
| 810 | 808 | conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())); |
| ... | ... | @@ -819,7 +817,7 @@ public class SimpleModelUtils { |
| 819 | 817 | // 查找满足条件的 BpmSimpleModelNodeVO 节点 |
| 820 | 818 | Collection<BpmSimpleModelNodeVO> matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(), |
| 821 | 819 | conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()) |
| 822 | - && evalConditionExpress(variables, conditionNode)); | |
| 820 | + && evalConditionExpress(variables, conditionNode.getConditionSetting())); | |
| 823 | 821 | if (CollUtil.isEmpty(matchConditionNodes)) { |
| 824 | 822 | matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(), |
| 825 | 823 | conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())); |
| ... | ... | @@ -841,16 +839,17 @@ public class SimpleModelUtils { |
| 841 | 839 | simulateNextNode(currentNode.getChildNode(), variables, resultNodes); |
| 842 | 840 | } |
| 843 | 841 | |
| 844 | - public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO conditionNode) { | |
| 845 | - return BpmnModelUtils.evalConditionExpress(variables, ConditionNodeConvert.buildConditionExpression(conditionNode)); | |
| 842 | + public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { | |
| 843 | + return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting)); | |
| 846 | 844 | } |
| 847 | 845 | |
| 848 | 846 | // TODO @芋艿:【高】要不要优化下,抽个 HttpUtils |
| 847 | + | |
| 849 | 848 | /** |
| 850 | 849 | * 添加 HTTP 请求参数。请求头或者请求体 |
| 851 | 850 | * |
| 852 | - * @param params HTTP 请求参数 | |
| 853 | - * @param paramSettings HTTP 请求参数设置 | |
| 851 | + * @param params HTTP 请求参数 | |
| 852 | + * @param paramSettings HTTP 请求参数设置 | |
| 854 | 853 | * @param processVariables 流程变量 |
| 855 | 854 | */ |
| 856 | 855 | public static void addHttpRequestParam(MultiValueMap<String, String> params, | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmUpdateNormalFormTrigger.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.task.trigger; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | |
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.UpdateNormalFormTriggerSetting; | |
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum; | |
| 6 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; | |
| 7 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils; | |
| 8 | +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | |
| 9 | +import jakarta.annotation.Resource; | |
| 10 | +import lombok.extern.slf4j.Slf4j; | |
| 11 | +import org.flowable.engine.runtime.ProcessInstance; | |
| 12 | +import org.springframework.stereotype.Component; | |
| 13 | + | |
| 14 | +import java.util.Map; | |
| 15 | + | |
| 16 | + | |
| 17 | +/** | |
| 18 | + * BPM 更新流程表单触发器 | |
| 19 | + * | |
| 20 | + * @author jason | |
| 21 | + */ | |
| 22 | +@Component | |
| 23 | +@Slf4j | |
| 24 | +public class BpmUpdateNormalFormTrigger implements BpmTrigger { | |
| 25 | + | |
| 26 | + @Resource | |
| 27 | + private BpmProcessInstanceService processInstanceService; | |
| 28 | + | |
| 29 | + @Override | |
| 30 | + public BpmTriggerTypeEnum getType() { | |
| 31 | + return BpmTriggerTypeEnum.UPDATE_NORMAL_FORM; | |
| 32 | + } | |
| 33 | + | |
| 34 | + @Override | |
| 35 | + public void execute(String processInstanceId, String param) { | |
| 36 | + // 1. 解析更新流程表单配置 | |
| 37 | + UpdateNormalFormTriggerSetting setting = JsonUtils.parseObject(param, UpdateNormalFormTriggerSetting.class); | |
| 38 | + if (setting == null) { | |
| 39 | + log.error("[execute][流程({}) 更新流程表单触发器配置为空]", processInstanceId); | |
| 40 | + return; | |
| 41 | + } | |
| 42 | + // 2.获取流程变量 | |
| 43 | + ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId); | |
| 44 | + Map<String, Object> processVariables = processInstance.getProcessVariables(); | |
| 45 | + String expression = SimpleModelUtils.buildConditionExpression(setting.getConditionType(), setting.getConditionExpression(), | |
| 46 | + setting.getConditionGroups()); | |
| 47 | + | |
| 48 | + // 3.满足条件,更新流程表单 | |
| 49 | + if(BpmnModelUtils.evalConditionExpress(processVariables, expression)) { | |
| 50 | + processInstanceService.updateProcessInstanceVariables(processInstanceId, setting.getUpdateFormFields()); | |
| 51 | + } | |
| 52 | + } | |
| 53 | +} | ... | ... |