ソースを参照

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

jason 6 ヶ月 前
コミット
a23b0480f1

+ 3 - 1
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;
 @AllArgsConstructor
 public enum BpmTriggerTypeEnum implements ArrayValuable<Integer> {
 
-    HTTP_REQUEST(1, "发起 HTTP 请求");
+    HTTP_REQUEST(1, "发起 HTTP 请求"),
+    UPDATE_NORMAL_FORM(2, "更新流程表单");
+
 
     /**
      * 触发器执行动作类型

+ 25 - 2
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 {
         @Valid
         private HttpRequestTriggerSetting httpRequestSetting;
 
+        /**
+         * 更新流程表单触发器设置
+         */
+        private UpdateNormalFormTriggerSetting updateNormalFormSetting;
+
         @Schema(description = "http 请求触发器设置", example = "{}")
         @Data
         public static class HttpRequestTriggerSetting {
@@ -365,14 +370,32 @@ public class BpmSimpleModelNodeVO {
             // TODO @json:可能未来看情况,搞个 HttpResponseParam;得看看有没别的业务需要,抽象统一
             /**
              * 请求返回处理设置,用于修改流程表单值
-             *
+             * <p>
              * key:表示要修改的流程表单字段名(name)
              * value:接口返回的字段名
              */
             @Schema(description = "请求返回处理设置", example = "[]")
             private List<KeyValue<String, String>> response;
-
         }
 
+        @Schema(description = "更新流程表单触发器设置", example = "{}")
+        @Data
+        public static class UpdateNormalFormTriggerSetting {
+
+            @Schema(description = "条件类型", example = "1")
+            @InEnum(BpmSimpleModeConditionTypeEnum.class)
+            @NotNull(message = "条件类型不能为空")
+            private Integer conditionType;
+
+            @Schema(description = "条件表达式", example = "${day>3}")
+            private String conditionExpression;
+
+            @Schema(description = "条件组", example = "{}")
+            private ConditionGroups conditionGroups;
+
+            @Schema(description = "更新的表单字段", example = "userName")
+            @NotEmpty(message = "更新的表单字段不能为空")
+            private Map<String, Object> updateFormFields;
+        }
     }
 }

+ 7 - 0
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 {
         addExtensionElement(element, name, String.valueOf(value));
     }
 
+    public static void addExtensionElementJson(FlowElement element, String name, Object value) {
+        if (value == null) {
+            return;
+        }
+        addExtensionElement(element, name, JsonUtils.toJsonString(value));
+    }
+
     public static void addExtensionElement(FlowElement element, String name, Map<String, String> attributes) {
         if (attributes == null) {
             return;

+ 49 - 50
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;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.*;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups;
 import cn.iocoder.yudao.module.bpm.enums.definition.*;
@@ -626,54 +625,52 @@ public class SimpleModelUtils {
 
         public static SequenceFlow buildSequenceFlow(String sourceId, String targetId,
                                                      BpmSimpleModelNodeVO node) {
-            String conditionExpression = buildConditionExpression(node);
+            String conditionExpression = buildConditionExpression(node.getConditionSetting());
             return buildBpmnSequenceFlow(sourceId, targetId, node.getId(), node.getName(), conditionExpression);
         }
 
-        /**
-         * 构造条件表达式
-         *
-         * @param node 条件节点
-         */
-        public static String buildConditionExpression(BpmSimpleModelNodeVO node) {
-            return buildConditionExpression(node.getConditionSetting().getConditionType(), node.getConditionSetting().getConditionExpression(),
-                    node.getConditionSetting().getConditionGroups());
-        }
 
-        public static String buildConditionExpression(BpmSimpleModelNodeVO.RouterSetting router) {
-            return buildConditionExpression(router.getConditionType(), router.getConditionExpression(),
-                    router.getConditionGroups());
-        }
+    }
 
-        public static String buildConditionExpression(Integer conditionType, String conditionExpression,
-                                                      ConditionGroups conditionGroups) {
-            BpmSimpleModeConditionTypeEnum conditionTypeEnum = BpmSimpleModeConditionTypeEnum.valueOf(conditionType);
-            if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.EXPRESSION) {
-                return conditionExpression;
+    /**
+     * 构造条件表达式
+     */
+    public static String buildConditionExpression(BpmSimpleModelNodeVO.ConditionSetting conditionSetting) {
+        return buildConditionExpression(conditionSetting.getConditionType(), conditionSetting.getConditionExpression(),
+                conditionSetting.getConditionGroups());
+    }
+
+    public static String buildConditionExpression(BpmSimpleModelNodeVO.RouterSetting routerSetting) {
+        return buildConditionExpression(routerSetting.getConditionType(), routerSetting.getConditionExpression(),
+                routerSetting.getConditionGroups());
+    }
+
+    public static String buildConditionExpression(Integer conditionType, String conditionExpression, ConditionGroups conditionGroups) {
+        BpmSimpleModeConditionTypeEnum conditionTypeEnum = BpmSimpleModeConditionTypeEnum.valueOf(conditionType);
+        if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.EXPRESSION) {
+            return conditionExpression;
+        }
+        if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.RULE) {
+            if (conditionGroups == null || CollUtil.isEmpty(conditionGroups.getConditions())) {
+                return null;
             }
-            if (conditionTypeEnum == BpmSimpleModeConditionTypeEnum.RULE) {
-                if (conditionGroups == null || CollUtil.isEmpty(conditionGroups.getConditions())) {
-                    return null;
+            List<String> strConditionGroups = CollectionUtils.convertList(conditionGroups.getConditions(), item -> {
+                if (CollUtil.isEmpty(item.getRules())) {
+                    return "";
                 }
-                List<String> strConditionGroups = CollectionUtils.convertList(conditionGroups.getConditions(), item -> {
-                    if (CollUtil.isEmpty(item.getRules())) {
-                        return "";
-                    }
-                    // 构造规则表达式
-                    List<String> list = CollectionUtils.convertList(item.getRules(), (rule) -> {
-                        String rightSide = NumberUtil.isNumber(rule.getRightSide()) ? rule.getRightSide()
-                                : "\"" + rule.getRightSide() + "\""; // 如果非数值类型加引号
-                        return String.format(" %s %s var:convertByType(%s,%s)", rule.getLeftSide(), rule.getOpCode(), rule.getLeftSide(), rightSide);
-                    });
-                    // 构造条件组的表达式
-                    Boolean and = item.getAnd();
-                    return "(" + CollUtil.join(list, and ? " && " : " || ") + ")";
+                // 构造规则表达式
+                List<String> list = CollectionUtils.convertList(item.getRules(), (rule) -> {
+                    String rightSide = NumberUtil.isNumber(rule.getRightSide()) ? rule.getRightSide()
+                            : "\"" + rule.getRightSide() + "\""; // 如果非数值类型加引号
+                    return String.format(" %s %s var:convertByType(%s,%s)", rule.getLeftSide(), rule.getOpCode(), rule.getLeftSide(), rightSide);
                 });
-                return String.format("${%s}", CollUtil.join(strConditionGroups, conditionGroups.getAnd() ? " && " : " || "));
-            }
-            return null;
+                // 构造条件组的表达式
+                Boolean and = item.getAnd();
+                return "(" + CollUtil.join(list, and ? " && " : " || ") + ")";
+            });
+            return String.format("${%s}", CollUtil.join(strConditionGroups, conditionGroups.getAnd() ? " && " : " || "));
         }
-
+        return null;
     }
 
     public static class DelayTimerNodeConvert implements NodeConvert {
@@ -727,9 +724,10 @@ public class SimpleModelUtils {
             if (node.getTriggerSetting() != null) {
                 addExtensionElement(serviceTask, TRIGGER_TYPE, node.getTriggerSetting().getType());
                 if (node.getTriggerSetting().getHttpRequestSetting() != null) {
-                    // TODO @jason:加个 addExtensionElementJson 方法,方便设置 JSON 类型的属性
-                    addExtensionElement(serviceTask, TRIGGER_PARAM,
-                            JsonUtils.toJsonString(node.getTriggerSetting().getHttpRequestSetting()));
+                    addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getHttpRequestSetting());
+                }
+                if (node.getTriggerSetting().getUpdateNormalFormSetting() != null) {
+                    addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getUpdateNormalFormSetting());
                 }
             }
             return serviceTask;
@@ -760,7 +758,7 @@ public class SimpleModelUtils {
         }
 
         public static SequenceFlow buildSequenceFlow(String nodeId, BpmSimpleModelNodeVO.RouterSetting router) {
-            String conditionExpression = ConditionNodeConvert.buildConditionExpression(router);
+            String conditionExpression = SimpleModelUtils.buildConditionExpression(router);
             return buildBpmnSequenceFlow(nodeId, router.getNodeId(), null, null, conditionExpression);
         }
 
@@ -804,7 +802,7 @@ public class SimpleModelUtils {
             // 查找满足条件的 BpmSimpleModelNodeVO 节点
             BpmSimpleModelNodeVO matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(),
                     conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())
-                            && evalConditionExpress(variables, conditionNode));
+                            && evalConditionExpress(variables, conditionNode.getConditionSetting()));
             if (matchConditionNode == null) {
                 matchConditionNode = CollUtil.findOne(currentNode.getConditionNodes(),
                         conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()));
@@ -819,7 +817,7 @@ public class SimpleModelUtils {
             // 查找满足条件的 BpmSimpleModelNodeVO 节点
             Collection<BpmSimpleModelNodeVO> matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(),
                     conditionNode -> !BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow())
-                            && evalConditionExpress(variables, conditionNode));
+                            && evalConditionExpress(variables, conditionNode.getConditionSetting()));
             if (CollUtil.isEmpty(matchConditionNodes)) {
                 matchConditionNodes = CollUtil.filterNew(currentNode.getConditionNodes(),
                         conditionNode -> BooleanUtil.isTrue(conditionNode.getConditionSetting().getDefaultFlow()));
@@ -841,16 +839,17 @@ public class SimpleModelUtils {
         simulateNextNode(currentNode.getChildNode(), variables, resultNodes);
     }
 
-    public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO conditionNode) {
-        return BpmnModelUtils.evalConditionExpress(variables, ConditionNodeConvert.buildConditionExpression(conditionNode));
+    public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) {
+        return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting));
     }
 
     // TODO @芋艿:【高】要不要优化下,抽个 HttpUtils
+
     /**
      * 添加 HTTP 请求参数。请求头或者请求体
      *
-     * @param params HTTP 请求参数
-     * @param paramSettings HTTP 请求参数设置
+     * @param params           HTTP 请求参数
+     * @param paramSettings    HTTP 请求参数设置
      * @param processVariables 流程变量
      */
     public static void addHttpRequestParam(MultiValueMap<String, String> params,

+ 53 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmUpdateNormalFormTrigger.java

@@ -0,0 +1,53 @@
+package cn.iocoder.yudao.module.bpm.service.task.trigger;
+
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.UpdateNormalFormTriggerSetting;
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+
+/**
+ * BPM 更新流程表单触发器
+ *
+ * @author jason
+ */
+@Component
+@Slf4j
+public class BpmUpdateNormalFormTrigger implements BpmTrigger {
+
+    @Resource
+    private BpmProcessInstanceService processInstanceService;
+
+    @Override
+    public BpmTriggerTypeEnum getType() {
+        return BpmTriggerTypeEnum.UPDATE_NORMAL_FORM;
+    }
+
+    @Override
+    public void execute(String processInstanceId, String param) {
+        // 1. 解析更新流程表单配置
+        UpdateNormalFormTriggerSetting setting = JsonUtils.parseObject(param, UpdateNormalFormTriggerSetting.class);
+        if (setting == null) {
+            log.error("[execute][流程({}) 更新流程表单触发器配置为空]", processInstanceId);
+            return;
+        }
+        // 2.获取流程变量
+        ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
+        Map<String, Object> processVariables = processInstance.getProcessVariables();
+        String expression = SimpleModelUtils.buildConditionExpression(setting.getConditionType(), setting.getConditionExpression(),
+                setting.getConditionGroups());
+
+        // 3.满足条件,更新流程表单
+        if(BpmnModelUtils.evalConditionExpress(processVariables, expression)) {
+            processInstanceService.updateProcessInstanceVariables(processInstanceId, setting.getUpdateFormFields());
+        }
+    }
+}