diff --git a/common/common-flow/src/main/java/apelet/common/flow/listener/AutoSkipTaskListener.java b/common/common-flow/src/main/java/apelet/common/flow/listener/AutoSkipTaskListener.java index 5a7ae0e..d903b63 100644 --- a/common/common-flow/src/main/java/apelet/common/flow/listener/AutoSkipTaskListener.java +++ b/common/common-flow/src/main/java/apelet/common/flow/listener/AutoSkipTaskListener.java @@ -135,16 +135,7 @@ public class AutoSkipTaskListener implements TaskListener { } else { FlowTaskExt flowTaskExt = flowTaskExtService .getByProcessDefinitionIdAndTaskId(t.getProcessDefinitionId(), userTask.getId()); - List candidateUsernames; - if (StrUtil.isBlank(flowTaskExt.getCandidateUsernames())) { - candidateUsernames = Collections.emptyList(); - } else if (!StrUtil.equals(flowTaskExt.getCandidateUsernames(), "${" + FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR + "}")) { - candidateUsernames = StrUtil.split(flowTaskExt.getCandidateUsernames(), ","); - } else { - String value = flowApiService - .getExecutionVariableStringWithSafe(t.getExecutionId(), FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR); - candidateUsernames = value == null ? null : StrUtil.split(value, ","); - } + List candidateUsernames = flowApiService.getCandidateUsernamesByExecution(flowTaskExt, t.getExecutionId()); if (candidateUsernames != null && candidateUsernames.size() == 1) { assignedUser = candidateUsernames.get(0); } diff --git a/common/common-flow/src/main/java/apelet/common/flow/listener/MultiInstanceAssigneeListener.java b/common/common-flow/src/main/java/apelet/common/flow/listener/MultiInstanceAssigneeListener.java index f89de9c..7152293 100644 --- a/common/common-flow/src/main/java/apelet/common/flow/listener/MultiInstanceAssigneeListener.java +++ b/common/common-flow/src/main/java/apelet/common/flow/listener/MultiInstanceAssigneeListener.java @@ -2,6 +2,7 @@ package apelet.common.flow.listener; import apelet.common.core.util.ApplicationContextHolder; import apelet.common.flow.model.FlowTaskExt; +import apelet.common.flow.service.FlowApiService; import apelet.common.flow.service.FlowTaskExtService; import apelet.common.flow.util.BaseFlowIdentityExtHelper; import apelet.common.flow.util.FlowCustomExtFactory; @@ -30,6 +31,8 @@ public class MultiInstanceAssigneeListener implements ExecutionListener { private final transient FlowCustomExtFactory flowCustomExtFactory = ApplicationContextHolder.getBean(FlowCustomExtFactory.class); + private final transient FlowApiService flowApiService = ApplicationContextHolder.getBean(FlowApiService.class); + @Override public void notify(DelegateExecution execution) { @@ -44,7 +47,10 @@ public class MultiInstanceAssigneeListener implements ExecutionListener { } List candidateUsernames = new ArrayList<>(); if (StrUtil.isNotBlank(flowTaskExt.getCandidateUsernames())) { - candidateUsernames.addAll(StrUtil.split(flowTaskExt.getCandidateUsernames(), ",")); + List configuredUsernames = flowApiService.getCandidateUsernamesByExecution(flowTaskExt, execution.getId()); + if (CollUtil.isNotEmpty(configuredUsernames)) { + candidateUsernames.addAll(configuredUsernames); + } } else { BaseFlowIdentityExtHelper extHelper = flowCustomExtFactory.getFlowIdentityExtHelper(); if (extHelper == null) { diff --git a/common/common-flow/src/main/java/apelet/common/flow/service/FlowApiService.java b/common/common-flow/src/main/java/apelet/common/flow/service/FlowApiService.java index a5bd813..340cb47 100644 --- a/common/common-flow/src/main/java/apelet/common/flow/service/FlowApiService.java +++ b/common/common-flow/src/main/java/apelet/common/flow/service/FlowApiService.java @@ -570,6 +570,16 @@ public interface FlowApiService { List getCandidateUsernames(FlowTaskExt flowTaskExt, String taskId); /** + * 根据执行实例Id,获取当前任务在流程图中配置候选用户组数据。 + * 配置值支持逗号分隔的登录名,以及${appointedAssignee}、${projectBean.getCommonReportManager(execution)}形式的EL表达式。 + * + * @param flowTaskExt 流程任务扩展对象。 + * @param executionId 执行实例Id。 + * @return 候选用户组数据。 + */ + List getCandidateUsernamesByExecution(FlowTaskExt flowTaskExt, String executionId); + + /** * 获取当前任务在流程图中配置到的部门岗位Id集合和岗位Id集合。 * * @param flowTaskExt 流程任务扩展对象。 diff --git a/common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowApiServiceImpl.java b/common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowApiServiceImpl.java index 8f780d2..822d43b 100644 --- a/common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowApiServiceImpl.java +++ b/common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowApiServiceImpl.java @@ -41,6 +41,7 @@ import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.converter.BpmnXMLConverter; import org.flowable.bpmn.model.*; import org.flowable.bpmn.model.Process; +import org.flowable.common.engine.api.delegate.Expression; import org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl; import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext; import org.flowable.common.engine.impl.identity.Authentication; @@ -52,7 +53,10 @@ import org.flowable.engine.delegate.TaskListener; import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.history.HistoricProcessInstanceQuery; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.impl.persistence.entity.ExecutionEntity; import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl; +import org.flowable.engine.impl.util.CommandContextUtil; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ChangeActivityStateBuilder; import org.flowable.engine.runtime.Execution; @@ -1526,14 +1530,78 @@ public class FlowApiServiceImpl implements FlowApiService { @Override public List getCandidateUsernames(FlowTaskExt flowTaskExt, String taskId) { - if (StrUtil.isBlank(flowTaskExt.getCandidateUsernames())) { + String configured = flowTaskExt.getCandidateUsernames(); + if (StrUtil.isBlank(configured)) { return Collections.emptyList(); } - if (!StrUtil.equals(flowTaskExt.getCandidateUsernames(), "${" + FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR + "}")) { - return StrUtil.split(flowTaskExt.getCandidateUsernames(), ","); + if (StrUtil.equals(configured, "${" + FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR + "}")) { + String value = getTaskVariableStringWithSafe(taskId, FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR); + return value == null ? null : StrUtil.splitTrim(value, ","); } - Object candidateUsernames = getTaskVariableStringWithSafe(taskId, FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR); - return candidateUsernames == null ? null : StrUtil.split(candidateUsernames.toString(), ","); + if (!configured.startsWith("${")) { + return StrUtil.splitTrim(configured, ","); + } + Task task = this.getTaskById(taskId); + return task == null ? Collections.emptyList() : this.getCandidateUsernamesByExecution(flowTaskExt, task.getExecutionId()); + } + + @Override + public List getCandidateUsernamesByExecution(FlowTaskExt flowTaskExt, String executionId) { + String configured = flowTaskExt.getCandidateUsernames(); + if (StrUtil.isBlank(configured)) { + return Collections.emptyList(); + } + if (StrUtil.equals(configured, "${" + FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR + "}")) { + String value = getExecutionVariableStringWithSafe(executionId, FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR); + return value == null ? null : StrUtil.splitTrim(value, ","); + } + if (!configured.startsWith("${")) { + return StrUtil.splitTrim(configured, ","); + } + // 形如${projectBean.getCommonReportManager(execution)}的EL表达式,交给引擎的表达式管理器求值。 + return this.parseCandidateUsernames(this.getExpressionValue(configured, executionId)); + } + + private List parseCandidateUsernames(Object value) { + if (value == null) { + return Collections.emptyList(); + } + if (value instanceof Collection) { + List candidateUsernames = new LinkedList<>(); + for (Object element : (Collection) value) { + if (element != null && StrUtil.isNotBlank(element.toString())) { + candidateUsernames.add(element.toString()); + } + } + return candidateUsernames; + } + if (StrUtil.isBlank(value.toString())) { + return Collections.emptyList(); + } + return StrUtil.splitTrim(value.toString(), ","); + } + + private Object getExpressionValue(String expressionStr, String executionId) { + ProcessEngineConfigurationImpl engineConfiguration = CommandContextUtil.getProcessEngineConfiguration(); + if (engineConfiguration != null) { + return this.evaluateExpression(engineConfiguration, expressionStr, executionId); + } + // 待办详情等HTTP接口场景没有活动的命令上下文,交由引擎开启一次后再求值,保证execution关键字可正常绑定。 + return managementService.executeCommand(commandContext -> this.evaluateExpression( + CommandContextUtil.getProcessEngineConfiguration(commandContext), expressionStr, executionId)); + } + + private Object evaluateExpression( + ProcessEngineConfigurationImpl engineConfiguration, String expressionStr, String executionId) { + ExecutionEntity execution = CommandContextUtil.getExecutionEntityManager().findById(executionId); + if (execution == null) { + log.error("Failed to getExpressionValue expression [{}], executionId [{}], execution not found.", + expressionStr, executionId); + return null; + } + // 与引擎UserTaskActivityBehavior.handleAssignments的求值方式保持一致,execution关键字可正常绑定到当前执行流对象。 + Expression expression = engineConfiguration.getExpressionManager().createExpression(expressionStr); + return expression.getValue(execution); } @Override diff --git a/common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowTaskExtServiceImpl.java b/common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowTaskExtServiceImpl.java index e2f5689..ac176e4 100644 --- a/common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowTaskExtServiceImpl.java +++ b/common/common-flow/src/main/java/apelet/common/flow/service/impl/FlowTaskExtServiceImpl.java @@ -219,17 +219,7 @@ public class FlowTaskExtServiceImpl extends BaseService imp default: break; } - List candidateUsernames; - if (StrUtil.isBlank(flowTaskExt.getCandidateUsernames())) { - candidateUsernames = Collections.emptyList(); - } else { - if (!StrUtil.equals(flowTaskExt.getCandidateUsernames(), " + FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR + ")) { - candidateUsernames = StrUtil.split(flowTaskExt.getCandidateUsernames(), ","); - } else { - Object v = flowApiService.getExecutionVariableStringWithSafe(executionId, FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR); - candidateUsernames = v == null ? null : StrUtil.split(v.toString(), ","); - } - } + List candidateUsernames = flowApiService.getCandidateUsernamesByExecution(flowTaskExt, executionId); if (CollUtil.isNotEmpty(candidateUsernames)) { usernameSet.addAll(candidateUsernames); }