Commit 1784aab186bbbba85c7be2bcb5064283a75501b3

Authored by jason
2 parents 610f39de 31c2e81d

Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm

Showing 12 changed files with 101 additions and 84 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
... ... @@ -54,6 +54,7 @@ public interface ErrorCodeConstants {
54 54 ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人");
55 55 ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在");
56 56 ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
  57 + ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!");
57 58  
58 59 // ========== 动态表单模块 1-009-010-000 ==========
59 60 ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在");
... ...
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeType.java
... ... @@ -33,7 +33,7 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable {
33 33 CONDITION_BRANCH_NODE(51, "条件分支", "exclusiveGateway"),
34 34 PARALLEL_BRANCH_NODE(52, "并行分支", "parallelGateway"),
35 35 INCLUSIVE_BRANCH_NODE(53, "包容分支", "inclusiveGateway"),
36   - ROUTE_BRANCH_NODE(54, "路由分支", "exclusiveGateway")
  36 + ROUTER_BRANCH_NODE(54, "路由分支", "exclusiveGateway")
37 37 ;
38 38  
39 39 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BpmSimpleModelNodeType::getType).toArray();
... ... @@ -51,7 +51,7 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable {
51 51 return Objects.equals(CONDITION_BRANCH_NODE.getType(), type)
52 52 || Objects.equals(PARALLEL_BRANCH_NODE.getType(), type)
53 53 || Objects.equals(INCLUSIVE_BRANCH_NODE.getType(), type)
54   - || Objects.equals(ROUTE_BRANCH_NODE.getType(), type);
  54 + || Objects.equals(ROUTER_BRANCH_NODE.getType(), type);
55 55 }
56 56  
57 57 public static BpmSimpleModelNodeType valueOf(Integer type) {
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
... ... @@ -117,11 +117,10 @@ public class BpmSimpleModelNodeVO {
117 117 private ConditionGroups conditionGroups; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
118 118  
119 119 @Schema(description = "路由分支组", example = "[]")
120   - private List<RouteCondition> routerGroups;
  120 + private List<RouterCondition> routerGroups;
121 121  
122   - // TODO @lesan:这个目前前端是随机生成的。可以后端来随机么?
123   - @Schema(description = "默认分支 ID", example = "Flow_xxx")
124   - private String defaultFlowId; // 仅用于路由分支节点 BpmSimpleModelNodeType.ROUTE_BRANCH_NODE
  122 + @Schema(description = "默认分支 ID", example = "Flow_xxx", hidden = true) // 由后端生成,所以 hidden = true
  123 + private String defaultFlowId; // 仅用于路由分支节点 BpmSimpleModelNodeType.ROUTER_BRANCH_NODE
125 124  
126 125 @Schema(description = "任务监听器")
127 126 @Valid
... ... @@ -290,11 +289,10 @@ public class BpmSimpleModelNodeVO {
290 289  
291 290 }
292 291  
293   - // TODO @lesan:还有相关的也要改下哈。route 到 router
294 292 @Schema(description = "路由分支")
295 293 @Data
296 294 @Valid
297   - public static class RouteCondition {
  295 + public static class RouterCondition {
298 296  
299 297 @Schema(description = "节点 Id", example = "Activity_xxx") // 跳转到该节点
300 298 @NotEmpty(message = "节点 Id 不能为空")
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java
... ... @@ -101,6 +101,10 @@ public class BpmApprovalDetailRespVO {
101 101 @Schema(description = "审批意见", example = "同意")
102 102 private String reason;
103 103  
  104 + // TODO @lesan:改成 signPicUrl 会好点
  105 + @Schema(description = "签名", example = "https://www.iocoder.cn/sign.png")
  106 + private String sign;
  107 +
104 108 }
105 109  
106 110 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskApproveReqVO.java
... ... @@ -18,6 +18,10 @@ public class BpmTaskApproveReqVO {
18 18 @NotEmpty(message = "审批意见不能为空")
19 19 private String reason;
20 20  
  21 + // TODO @lesan:改成 signPicUrl 会好点
  22 + @Schema(description = "签名", example = "https://www.iocoder.cn/sign.png")
  23 + private String sign;
  24 +
21 25 @Schema(description = "变量实例(动态表单)", requiredMode = Schema.RequiredMode.REQUIRED)
22 26 private Map<String, Object> variables;
23 27  
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java
... ... @@ -186,7 +186,8 @@ public interface BpmProcessInstanceConvert {
186 186 return null;
187 187 }
188 188 return BeanUtils.toBean(task, BpmApprovalDetailRespVO.ActivityNodeTask.class)
189   - .setStatus(FlowableUtils.getTaskStatus(task)).setReason(FlowableUtils.getTaskReason(task));
  189 + .setStatus(FlowableUtils.getTaskStatus(task)).setReason(FlowableUtils.getTaskReason(task))
  190 + .setSign(FlowableUtils.getTaskSign(task));
190 191 }
191 192  
192 193 default Set<Long> parseUserIds(HistoricProcessInstance processInstance,
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java
... ... @@ -59,4 +59,7 @@ public class BpmnVariableConstants {
59 59 */
60 60 public static final String TASK_VARIABLE_REASON = "TASK_REASON";
61 61  
  62 + // TODO @lesan:TASK_SIGN_PIC_URL 。。。虽然长一点,嘿嘿
  63 + public static final String TASK_VARIABLE_SIGN = "TASK_SIGN";
  64 +
62 65 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
... ... @@ -2,9 +2,11 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.convert.Convert;
  5 +import cn.hutool.core.lang.Assert;
5 6 import cn.hutool.core.map.MapUtil;
6 7 import cn.hutool.core.util.*;
7 8 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  9 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
8 10 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
9 11 import cn.iocoder.yudao.framework.common.util.string.StrUtils;
10 12 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
... ... @@ -21,6 +23,7 @@ import org.flowable.bpmn.model.Process;
21 23 import org.flowable.bpmn.model.*;
22 24 import org.flowable.common.engine.api.FlowableException;
23 25 import org.flowable.common.engine.impl.util.io.BytesStreamSource;
  26 +import org.flowable.engine.impl.el.FixedValue;
24 27  
25 28 import java.util.*;
26 29  
... ... @@ -346,12 +349,8 @@ public class BpmnModelUtils {
346 349 }
347 350  
348 351 public static void addSignEnable(Boolean signEnable, FlowElement userTask) {
349   - // TODO @lesan:是不是改成表达式会好点 addExtensionElement(userTask, SIGN_ENABLE, ObjUtil.isNotNull(signEnable) ? )
350   - if (ObjUtil.isNotNull(signEnable)) {
351   - addExtensionElement(userTask, SIGN_ENABLE, signEnable.toString());
352   - } else {
353   - addExtensionElement(userTask, SIGN_ENABLE, "false");
354   - }
  352 + addExtensionElement(userTask, SIGN_ENABLE,
  353 + ObjUtil.isNotNull(signEnable) ? signEnable.toString() : Boolean.FALSE.toString());
355 354 }
356 355  
357 356 public static Boolean parseSignEnable(BpmnModel bpmnModel, String flowElementId) {
... ... @@ -366,6 +365,19 @@ public class BpmnModelUtils {
366 365 return Convert.toBool(extensionElements.get(0).getElementText(), false);
367 366 }
368 367  
  368 + public static void addListenerConfig(FlowableListener flowableListener, BpmSimpleModelNodeVO.ListenerHandler handler) {
  369 + FieldExtension fieldExtension = new FieldExtension();
  370 + fieldExtension.setFieldName("listenerConfig");
  371 + fieldExtension.setStringValue(JsonUtils.toJsonString(handler));
  372 + flowableListener.getFieldExtensions().add(fieldExtension);
  373 + }
  374 +
  375 + public static BpmSimpleModelNodeVO.ListenerHandler parseListenerConfig(FixedValue fixedValue) {
  376 + String expressionText = fixedValue.getExpressionText();
  377 + Assert.notNull(expressionText, "监听器扩展字段({})不能为空", expressionText);
  378 + return JsonUtils.parseObject(expressionText, BpmSimpleModelNodeVO.ListenerHandler.class);
  379 + }
  380 +
369 381 // ========== BPM 简单查找相关的方法 ==========
370 382  
371 383 /**
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java
... ... @@ -213,6 +213,11 @@ public class FlowableUtils {
213 213 return (String) task.getTaskLocalVariables().get(BpmnVariableConstants.TASK_VARIABLE_REASON);
214 214 }
215 215  
  216 + // TODO @lesan:这个方法名,也改咧
  217 + public static String getTaskSign(TaskInfo task) {
  218 + return (String) task.getTaskLocalVariables().get(BpmnVariableConstants.TASK_VARIABLE_SIGN);
  219 + }
  220 +
216 221 /**
217 222 * 获得任务的表单
218 223 *
... ...
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.*;
... ... @@ -188,7 +187,7 @@ public class SimpleModelUtils {
188 187 // 分支终点节点 ID
189 188 String branchEndNodeId = null;
190 189 if (nodeType == BpmSimpleModelNodeType.CONDITION_BRANCH_NODE
191   - || nodeType == BpmSimpleModelNodeType.ROUTE_BRANCH_NODE) { // 条件分支或路由分支
  190 + || nodeType == BpmSimpleModelNodeType.ROUTER_BRANCH_NODE) { // 条件分支或路由分支
192 191 // 分两种情况 1. 分支节点有孩子节点为孩子节点 Id 2. 分支节点孩子为无效节点时 (分支嵌套且为分支最后一个节点) 为分支终点节点 ID
193 192 branchEndNodeId = isValidNode(childNode) ? childNode.getId() : targetNodeId;
194 193 } else if (nodeType == BpmSimpleModelNodeType.PARALLEL_BRANCH_NODE
... ... @@ -199,10 +198,10 @@ public class SimpleModelUtils {
199 198 Assert.notEmpty(branchEndNodeId, "分支终点节点 Id 不能为空");
200 199  
201 200 // 3. 遍历分支节点
202   - if (nodeType == BpmSimpleModelNodeType.ROUTE_BRANCH_NODE) {
  201 + if (nodeType == BpmSimpleModelNodeType.ROUTER_BRANCH_NODE) {
203 202 // 路由分支遍历
204   - for (BpmSimpleModelNodeVO.RouteCondition route : node.getRouterGroups()) {
205   - SequenceFlow sequenceFlow = RouteBranchNodeConvert.buildSequenceFlow(node.getId(), route);
  203 + for (BpmSimpleModelNodeVO.RouterCondition router : node.getRouterGroups()) {
  204 + SequenceFlow sequenceFlow = RouteBranchNodeConvert.buildSequenceFlow(node.getId(), router);
206 205 process.addFlowElement(sequenceFlow);
207 206 }
208 207 } else {
... ... @@ -233,7 +232,7 @@ public class SimpleModelUtils {
233 232 SequenceFlow sequenceFlow = buildBpmnSequenceFlow(branchEndNodeId, nextNodeId);
234 233 process.addFlowElement(sequenceFlow);
235 234 // 4.2 如果是路由分支,需要连接后续节点为默认路由
236   - } else if (nodeType == BpmSimpleModelNodeType.ROUTE_BRANCH_NODE) {
  235 + } else if (nodeType == BpmSimpleModelNodeType.ROUTER_BRANCH_NODE) {
237 236 SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), branchEndNodeId, node.getDefaultFlowId(),
238 237 null, null);
239 238 process.addFlowElement(sequenceFlow);
... ... @@ -453,10 +452,7 @@ public class SimpleModelUtils {
453 452 flowableListener.setEvent(TaskListener.EVENTNAME_CREATE);
454 453 flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
455 454 flowableListener.setImplementation(DELEGATE_EXPRESSION);
456   - FieldExtension fieldExtension = new FieldExtension();
457   - fieldExtension.setFieldName("listenerConfig");
458   - fieldExtension.setStringValue(JsonUtils.toJsonString(node.getTaskCreateListener()));
459   - flowableListener.getFieldExtensions().add(fieldExtension);
  455 + addListenerConfig(flowableListener, node.getTaskCreateListener());
460 456 flowableListeners.add(flowableListener);
461 457 }
462 458 if (node.getTaskAssignListener() != null
... ... @@ -465,11 +461,7 @@ public class SimpleModelUtils {
465 461 flowableListener.setEvent(TaskListener.EVENTNAME_ASSIGNMENT);
466 462 flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
467 463 flowableListener.setImplementation(DELEGATE_EXPRESSION);
468   - // TODO @lesan:可以在 BpmnModelUtils 搞个方法,类似 public static Integer parseCandidateStrategy。这样,就收敛啦!
469   - FieldExtension fieldExtension = new FieldExtension();
470   - fieldExtension.setFieldName("listenerConfig");
471   - fieldExtension.setStringValue(JsonUtils.toJsonString(node.getTaskAssignListener()));
472   - flowableListener.getFieldExtensions().add(fieldExtension);
  464 + addListenerConfig(flowableListener, node.getTaskAssignListener());
473 465 flowableListeners.add(flowableListener);
474 466 }
475 467 if (node.getTaskCompleteListener() != null
... ... @@ -478,10 +470,7 @@ public class SimpleModelUtils {
478 470 flowableListener.setEvent(TaskListener.EVENTNAME_COMPLETE);
479 471 flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
480 472 flowableListener.setImplementation(DELEGATE_EXPRESSION);
481   - FieldExtension fieldExtension = new FieldExtension();
482   - fieldExtension.setFieldName("listenerConfig");
483   - fieldExtension.setStringValue(JsonUtils.toJsonString(node.getTaskCompleteListener()));
484   - flowableListener.getFieldExtensions().add(fieldExtension);
  473 + addListenerConfig(flowableListener, node.getTaskCompleteListener());
485 474 flowableListeners.add(flowableListener);
486 475 }
487 476 if (CollUtil.isNotEmpty(flowableListeners)) {
... ... @@ -646,9 +635,9 @@ public class SimpleModelUtils {
646 635 node.getConditionGroups());
647 636 }
648 637  
649   - public static String buildConditionExpression(BpmSimpleModelNodeVO.RouteCondition route) {
650   - return buildConditionExpression(route.getConditionType(), route.getConditionExpression(),
651   - route.getConditionGroups());
  638 + public static String buildConditionExpression(BpmSimpleModelNodeVO.RouterCondition router) {
  639 + return buildConditionExpression(router.getConditionType(), router.getConditionExpression(),
  640 + router.getConditionGroups());
652 641 }
653 642  
654 643 public static String buildConditionExpression(Integer conditionType, String conditionExpression,
... ... @@ -728,18 +717,19 @@ public class SimpleModelUtils {
728 717 exclusiveGateway.setId(node.getId());
729 718  
730 719 // 设置默认的序列流(条件)
  720 + node.setDefaultFlowId("Flow_" + IdUtil.fastUUID());
731 721 exclusiveGateway.setDefaultFlow(node.getDefaultFlowId());
732 722 return exclusiveGateway;
733 723 }
734 724  
735 725 @Override
736 726 public BpmSimpleModelNodeType getType() {
737   - return BpmSimpleModelNodeType.ROUTE_BRANCH_NODE;
  727 + return BpmSimpleModelNodeType.ROUTER_BRANCH_NODE;
738 728 }
739 729  
740   - public static SequenceFlow buildSequenceFlow(String nodeId, BpmSimpleModelNodeVO.RouteCondition route) {
741   - String conditionExpression = ConditionNodeConvert.buildConditionExpression(route);
742   - return buildBpmnSequenceFlow(nodeId, route.getNodeId(), null, null, conditionExpression);
  730 + public static SequenceFlow buildSequenceFlow(String nodeId, BpmSimpleModelNodeVO.RouterCondition router) {
  731 + String conditionExpression = ConditionNodeConvert.buildConditionExpression(router);
  732 + return buildBpmnSequenceFlow(nodeId, router.getNodeId(), null, null, conditionExpression);
743 733 }
744 734  
745 735 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
... ... @@ -482,6 +482,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
482 482 if (instance == null) {
483 483 throw exception(PROCESS_INSTANCE_NOT_EXISTS);
484 484 }
  485 + // 1.3 校验签名
  486 + BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
  487 + Boolean signEnable = parseSignEnable(bpmnModel, task.getTaskDefinitionKey());
  488 + if (signEnable && StrUtil.isEmpty(reqVO.getSign())) {
  489 + throw exception(TASK_SIGNATURE_NOT_EXISTS);
  490 + }
485 491  
486 492 // 情况一:被委派的任务,不调用 complete 去完成任务
487 493 if (DelegationState.PENDING.equals(task.getDelegationState())) {
... ... @@ -496,8 +502,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
496 502 }
497 503  
498 504 // 情况三:审批普通的任务。大多数情况下,都是这样
499   - // 2.1 更新 task 状态、原因
  505 + // 2.1 更新 task 状态、原因、签字
500 506 updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.APPROVE.getStatus(), reqVO.getReason());
  507 + if (signEnable) {
  508 + taskService.setVariableLocal(task.getId(), BpmnVariableConstants.TASK_VARIABLE_SIGN, reqVO.getSign());
  509 + }
501 510 // 2.2 添加评论
502 511 taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(),
503 512 BpmCommentTypeEnum.APPROVE.formatComment(reqVO.getReason()));
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java
1 1 package cn.iocoder.yudao.module.bpm.service.task.listener;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4   -import cn.hutool.core.lang.Assert;
5 4 import cn.hutool.core.util.StrUtil;
6   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
7 5 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
8 6 import cn.iocoder.yudao.module.bpm.enums.definition.BpmListenerParamTypeEnum;
9   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
10   -import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
11 7 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
12 8 import jakarta.annotation.Resource;
  9 +import lombok.Setter;
13 10 import lombok.extern.slf4j.Slf4j;
14   -import org.flowable.bpmn.model.BpmnModel;
15   -import org.flowable.bpmn.model.FieldExtension;
16   -import org.flowable.bpmn.model.FlowableListener;
17   -import org.flowable.bpmn.model.UserTask;
18 11 import org.flowable.engine.delegate.TaskListener;
19 12 import org.flowable.engine.history.HistoricProcessInstance;
  13 +import org.flowable.engine.impl.el.FixedValue;
20 14 import org.flowable.task.service.delegate.DelegateTask;
  15 +import org.springframework.context.annotation.Scope;
21 16 import org.springframework.http.HttpEntity;
22 17 import org.springframework.http.HttpMethod;
23 18 import org.springframework.http.ResponseEntity;
24 19 import org.springframework.stereotype.Component;
25 20 import org.springframework.util.LinkedMultiValueMap;
26 21 import org.springframework.util.MultiValueMap;
  22 +import org.springframework.web.client.RestClientException;
27 23 import org.springframework.web.client.RestTemplate;
28 24  
29 25 import java.util.List;
30 26 import java.util.Map;
31 27  
32 28 import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
  29 +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseListenerConfig;
33 30  
34 31 /**
35 32 * BPM 用户任务通用监听器
... ... @@ -38,34 +35,32 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_
38 35 */
39 36 @Component
40 37 @Slf4j
  38 +@Scope("prototype")
41 39 public class BpmUserTaskListener implements TaskListener {
42 40  
43 41 public static final String DELEGATE_EXPRESSION = "${bpmUserTaskListener}";
44 42  
45 43 @Resource
46   - private BpmModelService modelService;
47   -
48   - @Resource
49 44 private BpmProcessInstanceService processInstanceService;
50 45  
51 46 @Resource
52 47 private RestTemplate restTemplate;
53 48  
  49 + @Setter
  50 + private FixedValue listenerConfig;
  51 +
54 52 @Override
55 53 public void notify(DelegateTask delegateTask) {
56 54 // 1. 获取所需基础信息
57 55 HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(delegateTask.getProcessInstanceId());
58   - BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(delegateTask.getProcessDefinitionId());
59   - UserTask userTask = (UserTask) BpmnModelUtils.getFlowElementById(bpmnModel, delegateTask.getTaskDefinitionKey());
60   - BpmSimpleModelNodeVO.ListenerHandler listenerHandler = getListenerHandlerByEvent(delegateTask.getEventName(),
61   - userTask.getTaskListeners());
  56 + BpmSimpleModelNodeVO.ListenerHandler listenerHandler = parseListenerConfig(listenerConfig);
62 57  
63 58 // 2. 获取请求头和请求体
64 59 Map<String, Object> processVariables = processInstance.getProcessVariables();
65 60 MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
66 61 MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
67   - parseListenerMap(listenerHandler.getHeader(), processVariables, headers);
68   - parseListenerMap(listenerHandler.getBody(), processVariables, body);
  62 + parseListenerParam(listenerHandler.getHeader(), processVariables, headers);
  63 + parseListenerParam(listenerHandler.getBody(), processVariables, body);
69 64 // 2.1 请求头默认参数
70 65 if (StrUtil.isNotEmpty(delegateTask.getTenantId())) {
71 66 headers.add(HEADER_TENANT_ID, delegateTask.getTenantId());
... ... @@ -80,21 +75,29 @@ public class BpmUserTaskListener implements TaskListener {
80 75 // 3. 异步发起请求
81 76 // TODO @芋艿:确认要同步,还是异步
82 77 HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
83   - // TODO @lesan:可能需要 try catch 哇? RestClientException
84   - ResponseEntity<String> responseEntity = restTemplate.exchange(listenerHandler.getPath(), HttpMethod.POST,
85   - requestEntity, String.class);
86   - log.info("[notify][监听器:{},事件类型:{},请求头:{},请求体:{},响应结果:{}]",
87   - DELEGATE_EXPRESSION,
88   - delegateTask.getEventName(),
89   - headers,
90   - body,
91   - responseEntity);
  78 + try {
  79 + ResponseEntity<String> responseEntity = restTemplate.exchange(listenerHandler.getPath(), HttpMethod.POST,
  80 + requestEntity, String.class);
  81 + log.info("[notify][监听器:{},事件类型:{},请求头:{},请求体:{},响应结果:{}]",
  82 + DELEGATE_EXPRESSION,
  83 + delegateTask.getEventName(),
  84 + headers,
  85 + body,
  86 + responseEntity);
  87 + } catch (RestClientException e) {
  88 + log.error("[error][监听器:{},事件类型:{},请求头:{},请求体:{},请求出错:{}]",
  89 + DELEGATE_EXPRESSION,
  90 + delegateTask.getEventName(),
  91 + headers,
  92 + body,
  93 + e.getMessage());
  94 + }
92 95 // 4. 是否需要后续操作?TODO 芋艿:待定!
93 96 }
94 97  
95   - private void parseListenerMap(List<BpmSimpleModelNodeVO.ListenerHandler.ListenerParam> list,
96   - Map<String, Object> processVariables,
97   - MultiValueMap<String, String> to) {
  98 + private void parseListenerParam(List<BpmSimpleModelNodeVO.ListenerHandler.ListenerParam> list,
  99 + Map<String, Object> processVariables,
  100 + MultiValueMap<String, String> to) {
98 101 if (CollUtil.isEmpty(list)) {
99 102 return;
100 103 }
... ... @@ -107,17 +110,4 @@ public class BpmUserTaskListener implements TaskListener {
107 110 });
108 111 }
109 112  
110   - private BpmSimpleModelNodeVO.ListenerHandler getListenerHandlerByEvent(String eventName, List<FlowableListener> node) {
111   - FlowableListener flowableListener = node.stream()
112   - .filter(item -> item.getEvent().equals(eventName))
113   - .findFirst().orElse(null);
114   - Assert.notNull(flowableListener, "监听器({})不能为空", flowableListener);
115   - // TODO @lesan:BpmnModelUtils 提供一个 BpmSimpleModelNodeVO.ListenerHandler 解析方法,尽量收敛掉。
116   - FieldExtension fieldExtension = flowableListener.getFieldExtensions().stream()
117   - .filter(item -> item.getFieldName().equals("listenerConfig"))
118   - .findFirst().orElse(null);
119   - Assert.notNull(fieldExtension, "监听器扩展字段({})不能为空", fieldExtension);
120   - return JsonUtils.parseObject(fieldExtension.getStringValue(), BpmSimpleModelNodeVO.ListenerHandler.class);
121   - }
122   -
123 113 }
124 114 \ No newline at end of file
... ...