fix(bpm):修复流程预测时由于流程未开始或流程未真正抵达执行节点,无法获取execution导致的Expression流程表达式执行报错问题
This commit is contained in:
parent
bb236af631
commit
52b72cffb3
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
import org.flowable.engine.delegate.DelegateExecution;
|
import org.flowable.engine.delegate.DelegateExecution;
|
||||||
|
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
|
||||||
import org.flowable.engine.runtime.ProcessInstance;
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
@ -41,11 +42,34 @@ public class BpmTaskAssignLeaderExpression {
|
||||||
* @param level 指定级别
|
* @param level 指定级别
|
||||||
* @return 指定级别的领导
|
* @return 指定级别的领导
|
||||||
*/
|
*/
|
||||||
public Set<Long> calculateUsers(DelegateExecution execution, int level) {
|
public Set<Long> calculateUsers(ExecutionEntityImpl execution, Long level) {
|
||||||
Assert.isTrue(level > 0, "level 必须大于 0");
|
|
||||||
// 获得发起人
|
// 获得发起人
|
||||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
||||||
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
return calculateUsers(NumberUtils.parseLong(processInstance.getStartUserId()), level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算审批的候选人
|
||||||
|
*
|
||||||
|
* @param processInstanceId 流程实例id
|
||||||
|
* @param level 指定级别
|
||||||
|
* @return 指定级别的领导
|
||||||
|
*/
|
||||||
|
public Set<Long> calculateUsers(String processInstanceId, Long level) {
|
||||||
|
ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
|
||||||
|
return calculateUsers(NumberUtils.parseLong(processInstance.getStartUserId()), level);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算审批的候选人
|
||||||
|
*
|
||||||
|
* @param startUserId 发起人
|
||||||
|
* @param level 指定级别
|
||||||
|
* @return 指定级别的领导
|
||||||
|
*/
|
||||||
|
public Set<Long> calculateUsers(Long startUserId, Long level) {
|
||||||
|
Assert.isTrue(level > 0, "level 必须大于 0");
|
||||||
// 获得对应 leve 的部门
|
// 获得对应 leve 的部门
|
||||||
DeptRespDTO dept = null;
|
DeptRespDTO dept = null;
|
||||||
for (int i = 0; i < level; i++) {
|
for (int i = 0; i < level; i++) {
|
||||||
|
|
|
@ -33,4 +33,26 @@ public class BpmTaskAssignStartUserExpression {
|
||||||
return SetUtils.asSet(startUserId);
|
return SetUtils.asSet(startUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算审批的候选人
|
||||||
|
*
|
||||||
|
* @param startUserId 发起人id
|
||||||
|
* @return 发起人
|
||||||
|
*/
|
||||||
|
public Set<Long> calculateUsers(Long startUserId) {
|
||||||
|
return SetUtils.asSet(startUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算审批的候选人
|
||||||
|
*
|
||||||
|
* @param processInstanceId 流程实例id
|
||||||
|
* @return 发起人
|
||||||
|
*/
|
||||||
|
public Set<Long> calculateUsers(String processInstanceId) {
|
||||||
|
ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
|
||||||
|
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
||||||
|
return SetUtils.asSet(startUserId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,4 +96,8 @@ public class BpmnVariableConstants {
|
||||||
*/
|
*/
|
||||||
public static final String TASK_SIGN_PIC_URL = "TASK_SIGN_PIC_URL";
|
public static final String TASK_SIGN_PIC_URL = "TASK_SIGN_PIC_URL";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流程实例的变量 - 流程实例id
|
||||||
|
*/
|
||||||
|
public static final String PROCESS_INSTANCE_ID = "PROCESS_INSTANCE_ID";
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
|
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormFieldVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormFieldVO;
|
||||||
|
@ -30,6 +31,8 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||||
|
@ -355,6 +358,33 @@ public class FlowableUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object getExpressionValue(Map<String, Object> variable, String expressionString) {
|
public static Object getExpressionValue(Map<String, Object> variable, String expressionString) {
|
||||||
|
// 替换方法参数中的 execution 为流程实例id或userId,因为流程预测时获取不到execution对象
|
||||||
|
// 例如将 calculateUsers(execution, 1) 替换为 calculateUsers('xxx-xxx-xxx-xxx', 1)
|
||||||
|
Pattern pattern = Pattern.compile("\\(([^)]*)\\)");
|
||||||
|
Matcher matcher = pattern.matcher(expressionString);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (matcher.find()) {
|
||||||
|
// 获取方法参数列表
|
||||||
|
String args = matcher.group(1);
|
||||||
|
// 用逗号分隔参数并逐个替换精确匹配 execution 的部分
|
||||||
|
String[] params = args.split(",");
|
||||||
|
for (int i = 0; i < params.length; i++) {
|
||||||
|
if ("execution".equals(params[i].trim())) {
|
||||||
|
// 流程已开始
|
||||||
|
if(ObjectUtil.isNotEmpty(variable.get(BpmnVariableConstants.PROCESS_INSTANCE_ID))) {
|
||||||
|
String processInstanceId = variable.get(BpmnVariableConstants.PROCESS_INSTANCE_ID).toString();
|
||||||
|
params[i] = "'" + processInstanceId + "'";
|
||||||
|
} else {
|
||||||
|
//流程未开始
|
||||||
|
params[i] = Objects.requireNonNull(SecurityFrameworkUtils.getLoginUserId()).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String newArgs = String.join(", ", params);
|
||||||
|
matcher.appendReplacement(sb, "(" + newArgs + ")");
|
||||||
|
}
|
||||||
|
matcher.appendTail(sb);
|
||||||
|
expressionString = sb.toString();
|
||||||
VariableContainer variableContainer = new MapDelegateVariableContainer(variable, VariableContainer.empty());
|
VariableContainer variableContainer = new MapDelegateVariableContainer(variable, VariableContainer.empty());
|
||||||
return getExpressionValue(variableContainer, expressionString);
|
return getExpressionValue(variableContainer, expressionString);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.flowable.bpmn.constants.BpmnXMLConstants;
|
import org.flowable.bpmn.constants.BpmnXMLConstants;
|
||||||
import org.flowable.bpmn.model.*;
|
import org.flowable.bpmn.model.*;
|
||||||
import org.flowable.engine.HistoryService;
|
import org.flowable.engine.HistoryService;
|
||||||
|
@ -766,9 +767,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||||
.businessKey(businessKey)
|
.businessKey(businessKey)
|
||||||
.variables(variables);
|
.variables(variables);
|
||||||
// 3.1 创建流程 ID
|
// 3.1 创建流程 ID
|
||||||
|
String processInstanceId = null;
|
||||||
BpmModelMetaInfoVO.ProcessIdRule processIdRule = processDefinitionInfo.getProcessIdRule();
|
BpmModelMetaInfoVO.ProcessIdRule processIdRule = processDefinitionInfo.getProcessIdRule();
|
||||||
if (processIdRule != null && Boolean.TRUE.equals(processIdRule.getEnable())) {
|
if (processIdRule != null && Boolean.TRUE.equals(processIdRule.getEnable())) {
|
||||||
processInstanceBuilder.predefineProcessInstanceId(processIdRedisDAO.generate(processIdRule));
|
processInstanceId = processIdRedisDAO.generate(processIdRule);
|
||||||
|
processInstanceBuilder.predefineProcessInstanceId(processInstanceId);
|
||||||
}
|
}
|
||||||
// 3.2 流程名称
|
// 3.2 流程名称
|
||||||
BpmModelMetaInfoVO.TitleSetting titleSetting = processDefinitionInfo.getTitleSetting();
|
BpmModelMetaInfoVO.TitleSetting titleSetting = processDefinitionInfo.getTitleSetting();
|
||||||
|
@ -784,6 +787,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||||
}
|
}
|
||||||
// 3.3 发起流程实例
|
// 3.3 发起流程实例
|
||||||
ProcessInstance instance = processInstanceBuilder.start();
|
ProcessInstance instance = processInstanceBuilder.start();
|
||||||
|
// 将流程实例id保存到流程变量里,用于无法获取execution时获取流程实例id
|
||||||
|
processInstanceId = StringUtils.defaultIfBlank(processInstanceId, instance.getId());
|
||||||
|
runtimeService.setVariable(instance.getProcessInstanceId(),BpmnVariableConstants.PROCESS_INSTANCE_ID,processInstanceId);
|
||||||
return instance.getId();
|
return instance.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue