Merge remote-tracking branch 'yudao/feature/bpm' into feature/bpm-n

This commit is contained in:
Lesan 2025-01-08 10:26:01 +08:00
commit 735ec9e3ac
4 changed files with 57 additions and 40 deletions

View File

@ -6,7 +6,7 @@ import lombok.Getter;
import java.util.Arrays; import java.util.Arrays;
// TODO @芋艿枚举值的类名在考虑下 // TODO @lesanBpmListenerParamTypeEnum
/** /**
* BPM 任务监听器键值对类型 * BPM 任务监听器键值对类型
* *

View File

@ -36,24 +36,6 @@ public class BpmSimpleModelNodeVO {
@Schema(description = "子节点") @Schema(description = "子节点")
private BpmSimpleModelNodeVO childNode; // 补充说明在该模型下子节点有且仅有一个不会有多个 private BpmSimpleModelNodeVO childNode; // 补充说明在该模型下子节点有且仅有一个不会有多个
@Schema(description = "条件节点")
private List<BpmSimpleModelNodeVO> conditionNodes; // 补充说明有且仅有条件并行包容等分支会使用
// TODO @jasonconditionTypeconditionExpressiondefaultFlowconditionGroups 搞成一个 condition 属性会好点么
@Schema(description = "条件类型", example = "1")
@InEnum(BpmSimpleModeConditionType.class)
private Integer conditionType; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
@Schema(description = "条件表达式", example = "${day>3}")
private String conditionExpression; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
@Schema(description = "是否默认条件", example = "true")
private Boolean defaultFlow; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
/**
* 条件组
*/
private ConditionGroups conditionGroups; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
@Schema(description = "候选人策略", example = "30") @Schema(description = "候选人策略", example = "30")
@InEnum(BpmTaskCandidateStrategyEnum.class) @InEnum(BpmTaskCandidateStrategyEnum.class)
private Integer candidateStrategy; // 用于审批抄送节点 private Integer candidateStrategy; // 用于审批抄送节点
@ -110,6 +92,37 @@ public class BpmSimpleModelNodeVO {
*/ */
private ListenerHandler taskCompleteListener; private ListenerHandler taskCompleteListener;
@Schema(description = "延迟器设置", example = "{}")
private DelaySetting delaySetting;
@Schema(description = "条件节点")
private List<BpmSimpleModelNodeVO> conditionNodes; // 补充说明有且仅有条件并行包容分支会使用
// TODO @jasonconditionTypeconditionExpressiondefaultFlowconditionGroups 搞成一个 condition 属性会好点么
@Schema(description = "条件类型", example = "1")
@InEnum(BpmSimpleModeConditionType.class)
private Integer conditionType; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
@Schema(description = "条件表达式", example = "${day>3}")
private String conditionExpression; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
@Schema(description = "是否默认条件", example = "true")
private Boolean defaultFlow; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
/**
* 条件组
*/
private ConditionGroups conditionGroups; // 仅用于条件节点 BpmSimpleModelNodeType.CONDITION_NODE
// TODO @lesanroute 改成 router 会不会好点因为触发器延迟器都带了类似 r
// TODO @lesanrouteGroups
@Schema(description = "路由分支组", example = "[]")
private List<RouteCondition> routeGroup;
// TODO @lesan貌似没用
@Schema(description = "默认分支 ID", example = "Flow_xxx")
private String defaultFlowId; // 仅用于路由分支节点 BpmSimpleModelNodeType.ROUTE_BRANCH_NODE
@Schema(description = "任务监听器") @Schema(description = "任务监听器")
@Valid @Valid
@Data @Data
@ -130,17 +143,18 @@ public class BpmSimpleModelNodeVO {
// TODO @芋艿这里后续要不要复用 // TODO @芋艿这里后续要不要复用
// TODO @lesanListenerParam 更合适哈首先它是参数配置然后形式是键值对
@Schema(description = "任务监听器键值对") @Schema(description = "任务监听器键值对")
@Data @Data
public static class ListenerMap { public static class ListenerMap {
@Schema(description = "", example = "xxx")
private String key;
@Schema(description = "值类型", example = "1") @Schema(description = "值类型", example = "1")
@InEnum(BpmListenerMapType.class) @InEnum(BpmListenerMapType.class)
private Integer type; private Integer type;
@Schema(description = "", example = "xxx")
private String key;
@Schema(description = "", example = "xxx") @Schema(description = "", example = "xxx")
private String value; private String value;
@ -261,9 +275,6 @@ public class BpmSimpleModelNodeVO {
} }
@Schema(description = "延迟器设置", example = "{}")
private DelaySetting delaySetting;
@Schema(description = "延迟器") @Schema(description = "延迟器")
@Data @Data
@Valid @Valid
@ -280,22 +291,16 @@ public class BpmSimpleModelNodeVO {
} }
@Schema(description = "路由分支组", example = "[]")
private List<RouteCondition> routeGroups;
@Schema(description = "默认分支id", example = "Flow_xxx")
private String defaultFlowId; // 仅用于路由分支节点 BpmSimpleModelNodeType.ROUTE_BRANCH_NODE
@Schema(description = "路由分支") @Schema(description = "路由分支")
@Data @Data
@Valid @Valid
public static class RouteCondition { public static class RouteCondition {
@Schema(description = "节点 Id", example = "Activity_xxx") @Schema(description = "节点 Id", example = "Activity_xxx") // 跳转到该节点
@NotEmpty(message = "节点 Id 不能为空") @NotEmpty(message = "节点 Id 不能为空")
private String nodeId; private String nodeId;
// TODO @lesantypeexpressiongroups可以晚点改在和 conditionTypeconditionExpressiondefaultFlowconditionGroups 讨论 // TODO @lesantypeexpressiongroups
@Schema(description = "条件类型", example = "1") @Schema(description = "条件类型", example = "1")
@InEnum(BpmSimpleModeConditionType.class) @InEnum(BpmSimpleModeConditionType.class)
@NotNull(message = "条件类型不能为空") @NotNull(message = "条件类型不能为空")

View File

@ -439,28 +439,32 @@ public class SimpleModelUtils {
} }
// 设置监听器 // 设置监听器
addUserTaskListener(node, userTask); addUserTaskListener(node, userTask);
// 设置Simple设计器节点配置 // 设置 Simple 设计器节点配置
// TODO @lesan只设置到 flowableListener 里面整个 node 太大了因为很多都保存过啦
addSimpleConfigInfo(userTask, node); addSimpleConfigInfo(userTask, node);
return userTask; return userTask;
} }
private void addUserTaskListener(BpmSimpleModelNodeVO node, UserTask userTask) { private void addUserTaskListener(BpmSimpleModelNodeVO node, UserTask userTask) {
List<FlowableListener> flowableListeners = new ArrayList<>(3); List<FlowableListener> flowableListeners = new ArrayList<>(3);
if (node.getTaskCreateListener().getEnable()) { if (node.getTaskCreateListener() != null
&& Boolean.TRUE.equals(node.getTaskCreateListener().getEnable())) {
FlowableListener flowableListener = new FlowableListener(); FlowableListener flowableListener = new FlowableListener();
flowableListener.setEvent(TaskListener.EVENTNAME_CREATE); flowableListener.setEvent(TaskListener.EVENTNAME_CREATE);
flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
flowableListener.setImplementation(DELEGATE_EXPRESSION); flowableListener.setImplementation(DELEGATE_EXPRESSION);
flowableListeners.add(flowableListener); flowableListeners.add(flowableListener);
} }
if (node.getTaskAssignListener().getEnable()) { if (node.getTaskAssignListener() != null
&& Boolean.TRUE.equals(node.getTaskAssignListener().getEnable())) {
FlowableListener flowableListener = new FlowableListener(); FlowableListener flowableListener = new FlowableListener();
flowableListener.setEvent(TaskListener.EVENTNAME_ASSIGNMENT); flowableListener.setEvent(TaskListener.EVENTNAME_ASSIGNMENT);
flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
flowableListener.setImplementation(DELEGATE_EXPRESSION); flowableListener.setImplementation(DELEGATE_EXPRESSION);
flowableListeners.add(flowableListener); flowableListeners.add(flowableListener);
} }
if (node.getTaskCompleteListener().getEnable()) { if (node.getTaskCompleteListener() != null
&& Boolean.TRUE.equals(node.getTaskCompleteListener().getEnable())) {
FlowableListener flowableListener = new FlowableListener(); FlowableListener flowableListener = new FlowableListener();
flowableListener.setEvent(TaskListener.EVENTNAME_COMPLETE); flowableListener.setEvent(TaskListener.EVENTNAME_COMPLETE);
flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); flowableListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.bpm.service.task.listener; package cn.iocoder.yudao.module.bpm.service.task.listener;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
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;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmListenerMapType; import cn.iocoder.yudao.module.bpm.enums.definition.BpmListenerMapType;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
@ -24,6 +25,7 @@ import org.springframework.web.client.RestTemplate;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseSimpleConfigInfo; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseSimpleConfigInfo;
/** /**
@ -62,18 +64,23 @@ public class BpmUserTaskListener implements TaskListener {
parseListenerMap(listenerHandler.getHeader(), processVariables, headers); parseListenerMap(listenerHandler.getHeader(), processVariables, headers);
parseListenerMap(listenerHandler.getBody(), processVariables, body); parseListenerMap(listenerHandler.getBody(), processVariables, body);
// 2.1 请求头默认参数 // 2.1 请求头默认参数
headers.add("tenant-id", delegateTask.getTenantId()); if (StrUtil.isNotEmpty(delegateTask.getTenantId())) {
headers.add(HEADER_TENANT_ID, delegateTask.getTenantId());
}
// 2.2 请求体默认参数 // 2.2 请求体默认参数
// TODO @芋艿哪些默认参数后续再调研下
body.add("processInstanceId", delegateTask.getProcessInstanceId()); body.add("processInstanceId", delegateTask.getProcessInstanceId());
body.add("assignee", delegateTask.getAssignee()); body.add("assignee", delegateTask.getAssignee());
body.add("taskDefinitionKey", delegateTask.getTaskDefinitionKey()); body.add("taskDefinitionKey", delegateTask.getTaskDefinitionKey());
body.add("taskId", delegateTask.getId()); body.add("taskId", delegateTask.getId());
// 3. 异步发起请求 // 3. 异步发起请求
// TODO @芋艿确认要同步还是异步
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(listenerHandler.getPath(), HttpMethod.POST, ResponseEntity<String> responseEntity = restTemplate.exchange(listenerHandler.getPath(), HttpMethod.POST,
requestEntity, String.class); requestEntity, String.class);
log.info("[BpmUserTaskListener][的响应结果({})]", responseEntity); // TODO @lesan日志打印可以更全哈例如说请求参数对应的 task id哪个 listener
log.info("[notify][的响应结果({})]", responseEntity);
// 4. 是否需要后续操作TODO 芋艿待定 // 4. 是否需要后续操作TODO 芋艿待定
} }
@ -92,12 +99,13 @@ public class BpmUserTaskListener implements TaskListener {
}); });
} }
// TODO @lesan改成 jdk8 写法哈主要考虑好兼容
private BpmSimpleModelNodeVO.ListenerHandler getListenerHandlerByEvent(String eventName, BpmSimpleModelNodeVO node) { private BpmSimpleModelNodeVO.ListenerHandler getListenerHandlerByEvent(String eventName, BpmSimpleModelNodeVO node) {
return switch (eventName) { return switch (eventName) {
case TaskListener.EVENTNAME_CREATE -> node.getTaskCreateListener(); case TaskListener.EVENTNAME_CREATE -> node.getTaskCreateListener();
case TaskListener.EVENTNAME_ASSIGNMENT -> node.getTaskAssignListener(); case TaskListener.EVENTNAME_ASSIGNMENT -> node.getTaskAssignListener();
case TaskListener.EVENTNAME_COMPLETE -> node.getTaskCompleteListener(); case TaskListener.EVENTNAME_COMPLETE -> node.getTaskCompleteListener();
default -> null; default -> null; // TODO @lesan这个抛出异常可控一点
}; };
} }