From 955ad86db45eabb9260a6aad68a81b66e3097d03 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Tue, 7 Jan 2025 16:31:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Simple=E8=AE=BE=E8=AE=A1=E5=99=A8-?= =?UTF-8?q?=E7=9B=91=E5=90=AC=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/model/simple/BpmSimpleModelNodeVO.java | 14 +++- .../flowable/core/util/BpmnModelUtils.java | 40 +++++++++ .../flowable/core/util/SimpleModelUtils.java | 31 +++++-- .../task/listener/BpmUserTaskListener.java | 82 +++++++++++-------- 4 files changed, 121 insertions(+), 46 deletions(-) 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 382cd7c318..b6bfc803b3 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 @@ -96,20 +96,26 @@ public class BpmSimpleModelNodeVO { */ private AssignEmptyHandler assignEmptyHandler; - // TODO @lesan:建议改成 taskCreateListener; /** * 创建任务监听器 */ - private ListenerHandler createTaskListener; + private ListenerHandler taskCreateListener; + /** + * 指派任务监听器 + */ + private ListenerHandler taskAssignListener; + /** + * 完成任务监听器 + */ + private ListenerHandler taskCompleteListener; @Schema(description = "任务监听器") @Valid @Data public static class ListenerHandler { - // TODO @lesan:参数校验,需要加下 - @Schema(description = "是否开启任务监听器", example = "false") + @NotNull(message = "是否开启任务监听器不能为空") private Boolean enable; @Schema(description = "请求路径", example = "http://xxxxx") 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 01200298f9..f2f3017ec9 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 @@ -6,6 +6,7 @@ import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; @@ -56,6 +57,18 @@ public class BpmnModelUtils { element.addExtensionElement(extensionElement); } + public static void addExtensionElementJson(FlowElement element, String name, Object value) { + if (value == null) { + return; + } + ExtensionElement extensionElement = new ExtensionElement(); + extensionElement.setNamespace(FLOWABLE_EXTENSIONS_NAMESPACE); + extensionElement.setNamespacePrefix(FLOWABLE_EXTENSIONS_PREFIX); + extensionElement.setElementText(JsonUtils.toJsonString(value)); + extensionElement.setName(name); + element.addExtensionElement(extensionElement); + } + public static void addExtensionElement(FlowElement element, String name, Integer value) { if (value == null) { return; @@ -93,6 +106,33 @@ public class BpmnModelUtils { return element != null ? element.getElementText() : null; } + public static T parseExtensionElementJson(FlowElement flowElement, String elementName, Class clazz) { + if (flowElement == null) { + return null; + } + ExtensionElement element = CollUtil.getFirst(flowElement.getExtensionElements().get(elementName)); + return element != null ? JsonUtils.parseObject(element.getElementText(), clazz) : null; + } + + /** + * 给节点添加Simple设计器配置Json + * + * @param userTask 节点 + * @param node 节点对象 + */ + public static void addSimpleConfigInfo(FlowElement userTask, Object node) { + addExtensionElementJson(userTask, "config", node); + } + + /** + * 解析Simple设计器配置Json + * + * @param userTask 节点 + */ + public static BpmSimpleModelNodeVO parseSimpleConfigInfo(FlowElement userTask) { + return parseExtensionElementJson(userTask, "config", BpmSimpleModelNodeVO.class); + } + /** * 给节点添加候选人元素 * 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 6922b0a453..1c7ccc300c 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 @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.*; -import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 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; @@ -23,7 +22,6 @@ import java.util.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*; import static cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener.DELEGATE_EXPRESSION; -import static cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener.EXTENSION_SUFFIX; import static java.util.Arrays.asList; /** @@ -442,23 +440,38 @@ public class SimpleModelUtils { userTask.setDueDate(node.getTimeoutHandler().getTimeDuration()); } // 设置监听器 + addUserTaskListener(node, userTask); + // 设置Simple设计器节点配置 + addSimpleConfigInfo(userTask, node); + return userTask; + } + + private void addUserTaskListener(BpmSimpleModelNodeVO node, UserTask userTask) { List flowableListeners = new ArrayList<>(3); - if (node.getCreateTaskListener().getEnable()) { + if (node.getTaskCreateListener().getEnable()) { FlowableListener flowableListener = new FlowableListener(); flowableListener.setEvent(TaskListener.EVENTNAME_CREATE); flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); flowableListener.setImplementation(DELEGATE_EXPRESSION); - // TODO @lesan:可以加个 addExtensionElementJson() 方法; - // TODO @lesan:是不是不用带 "create" + EXTENSION_SUFFIX 这种,直接给个 "config" 就完事了! - addExtensionElement(userTask, "create" + EXTENSION_SUFFIX, - // TODO @lesan:默认使用项目里的 JsonUtils 方法 - JSONUtil.toJsonStr(node.getCreateTaskListener())); + flowableListeners.add(flowableListener); + } + if (node.getTaskAssignListener().getEnable()) { + FlowableListener flowableListener = new FlowableListener(); + flowableListener.setEvent(TaskListener.EVENTNAME_ASSIGNMENT); + flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); + flowableListener.setImplementation(DELEGATE_EXPRESSION); + flowableListeners.add(flowableListener); + } + if (node.getTaskCompleteListener().getEnable()) { + FlowableListener flowableListener = new FlowableListener(); + flowableListener.setEvent(TaskListener.EVENTNAME_COMPLETE); + flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); + flowableListener.setImplementation(DELEGATE_EXPRESSION); flowableListeners.add(flowableListener); } if (CollUtil.isNotEmpty(flowableListeners)) { userTask.setTaskListeners(flowableListeners); } - return userTask; } private void processMultiInstanceLoopCharacteristics(Integer approveMethod, Integer approveRatio, UserTask userTask) { diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java index d77b820aad..14dda44055 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.bpm.service.task.listener; -import cn.hutool.http.HttpRequest; -import cn.hutool.json.JSONUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; import cn.iocoder.yudao.module.bpm.enums.definition.BpmListenerMapType; import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; @@ -14,12 +14,18 @@ import org.flowable.bpmn.model.FlowElement; import org.flowable.engine.delegate.TaskListener; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.task.service.delegate.DelegateTask; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; -import java.util.HashMap; +import java.util.List; import java.util.Map; -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseExtensionElement; +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseSimpleConfigInfo; /** * BPM 用户任务通用监听器 @@ -32,52 +38,62 @@ public class BpmUserTaskListener implements TaskListener { public static final String DELEGATE_EXPRESSION = "${bpmUserTaskListener}"; - public static final String EXTENSION_SUFFIX = "TaskListenerMetaInfo"; - @Resource private BpmModelService modelService; @Resource private BpmProcessInstanceService processInstanceService; + @Resource + private RestTemplate restTemplate; + @Override public void notify(DelegateTask delegateTask) { // 1. 获取所需基础信息 HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(delegateTask.getProcessInstanceId()); BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(delegateTask.getProcessDefinitionId()); - FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, delegateTask.getTaskDefinitionKey()); - // TODO @lesan:可以写到 FlowableUtils 里,简化解析逻辑! - BpmSimpleModelNodeVO.ListenerHandler listenerHandler = JSONUtil.toBean( - parseExtensionElement(userTaskElement, delegateTask.getEventName() + EXTENSION_SUFFIX), - BpmSimpleModelNodeVO.ListenerHandler.class); + FlowElement userTask = BpmnModelUtils.getFlowElementById(bpmnModel, delegateTask.getTaskDefinitionKey()); + BpmSimpleModelNodeVO node = parseSimpleConfigInfo(userTask); + BpmSimpleModelNodeVO.ListenerHandler listenerHandler = getListenerHandlerByEvent(delegateTask.getEventName(), node); // 2. 获取请求头和请求体 Map processVariables = processInstance.getProcessVariables(); - Map headers = new HashMap<>(); - Map body = new HashMap<>(); - listenerHandler.getHeader().forEach(item -> { - // TODO @lesan:可以写个统一的方法,解析参数。然后非空,put 到 headers 或者 body 里! - if (item.getType().equals(BpmListenerMapType.FIXED_VALUE.getType())) { - headers.put(item.getKey(), item.getValue()); - } else if (item.getType().equals(BpmListenerMapType.FROM_FORM.getType())) { - headers.put(item.getKey(), processVariables.getOrDefault(item.getValue(), "").toString()); - } - }); - // TODO @lesan:header 里面,需要添加下 tenant-id! - listenerHandler.getBody().forEach(item -> { - if (item.getType().equals(BpmListenerMapType.FIXED_VALUE.getType())) { - body.put(item.getKey(), item.getValue()); - } else if (item.getType().equals(BpmListenerMapType.FROM_FORM.getType())) { - body.put(item.getKey(), processVariables.getOrDefault(item.getValue(), "")); - } - }); + MultiValueMap headers = new LinkedMultiValueMap<>(); + MultiValueMap body = new LinkedMultiValueMap<>(); + parseListenerMap(listenerHandler.getHeader(), processVariables, headers); + headers.add("tenant-id", delegateTask.getTenantId()); + parseListenerMap(listenerHandler.getBody(), processVariables, body); // 3. 异步发起请求 - // TODO @lesan:最好打印下日志! - HttpRequest.post(listenerHandler.getPath()) - .addHeaders(headers).form(body).executeAsync(); - + HttpEntity> requestEntity = new HttpEntity<>(body, headers); + ResponseEntity responseEntity = restTemplate.exchange(listenerHandler.getPath(), HttpMethod.POST, + requestEntity, String.class); + log.info("[BpmUserTaskListener][的响应结果({})]", responseEntity); // 4. 是否需要后续操作?TODO 芋艿:待定! } + private void parseListenerMap(List list, + Map processVariables, + MultiValueMap to) { + if (CollUtil.isEmpty(list)) { + return; + } + list.forEach(item -> { + if (item.getType().equals(BpmListenerMapType.FIXED_VALUE.getType())) { + to.add(item.getKey(), item.getValue()); + } else if (item.getType().equals(BpmListenerMapType.FROM_FORM.getType())) { + to.add(item.getKey(), processVariables.get(item.getValue()).toString()); + } + }); + } + + private BpmSimpleModelNodeVO.ListenerHandler getListenerHandlerByEvent(String eventName, BpmSimpleModelNodeVO node) { + return switch (eventName) { + case TaskListener.EVENTNAME_CREATE -> node.getTaskCreateListener(); + case TaskListener.EVENTNAME_ASSIGNMENT -> node.getTaskAssignListener(); + case TaskListener.EVENTNAME_COMPLETE -> node.getTaskCompleteListener(); + default -> null; + }; + } + } \ No newline at end of file