Commit a23b0480f159eaad446b7b93b182b565f8c455de

Authored by jason
1 parent 362b872a

【功能新增】 新增修改流程表单数据触发器

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 +}
... ...