diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTriggerTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTriggerTypeEnum.java index 66f34e6559..95c278492a 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTriggerTypeEnum.java +++ b/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 { - HTTP_REQUEST(1, "发起 HTTP 请求"); + HTTP_REQUEST(1, "发起 HTTP 请求"), + UPDATE_NORMAL_FORM(2, "更新流程表单"); + /** * 触发器执行动作类型 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java index b5a5ac11c6..c7dd31125a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java +++ b/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;得看看有没别的业务需要,抽象统一 /** * 请求返回处理设置,用于修改流程表单值 - * + *

* key:表示要修改的流程表单字段名(name) * value:接口返回的字段名 */ @Schema(description = "请求返回处理设置", example = "[]") private List> 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 updateFormFields; + } } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java index eae4eb988b..3f22c7c259 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java +++ b/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 attributes) { if (attributes == null) { return; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 97c5f8a707..561db886d2 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/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 strConditionGroups = CollectionUtils.convertList(conditionGroups.getConditions(), item -> { + if (CollUtil.isEmpty(item.getRules())) { + return ""; } - List strConditionGroups = CollectionUtils.convertList(conditionGroups.getConditions(), item -> { - if (CollUtil.isEmpty(item.getRules())) { - return ""; - } - // 构造规则表达式 - List 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 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 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 variables, BpmSimpleModelNodeVO conditionNode) { - return BpmnModelUtils.evalConditionExpress(variables, ConditionNodeConvert.buildConditionExpression(conditionNode)); + public static boolean evalConditionExpress(Map 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 params, diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmUpdateNormalFormTrigger.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmUpdateNormalFormTrigger.java new file mode 100644 index 0000000000..2a1298e9ea --- /dev/null +++ b/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 processVariables = processInstance.getProcessVariables(); + String expression = SimpleModelUtils.buildConditionExpression(setting.getConditionType(), setting.getConditionExpression(), + setting.getConditionGroups()); + + // 3.满足条件,更新流程表单 + if(BpmnModelUtils.evalConditionExpress(processVariables, expression)) { + processInstanceService.updateProcessInstanceVariables(processInstanceId, setting.getUpdateFormFields()); + } + } +}