diff --git a/jeecg-boot-module/jeecg-module-flow/src/main/java/org/jeecg/xispeak/XiSpeakFlow.java b/jeecg-boot-module/jeecg-module-flow/src/main/java/org/jeecg/xispeak/XiSpeakFlow.java index dd147da..761b6af 100644 --- a/jeecg-boot-module/jeecg-module-flow/src/main/java/org/jeecg/xispeak/XiSpeakFlow.java +++ b/jeecg-boot-module/jeecg-module-flow/src/main/java/org/jeecg/xispeak/XiSpeakFlow.java @@ -40,6 +40,10 @@ public class XiSpeakFlow { return userList; } + public int getBgDeptLdUserIdListLength() { + return getBgDeptLdUserIdList().size(); + } + public Integer getNeedSdwApproval(Object jsonData) { XiSpeakConfig.XiSpeakProperties props = xiSpeakConfig.getXiSpeak(); if (jsonData == null || org.apache.commons.lang.StringUtils.isBlank(props.getNeedSdwApproveCode())) { @@ -71,6 +75,10 @@ public class XiSpeakFlow { return iSysBaseAPI.getUsersListByDeptIdAndRoleIdLocalApi(deptId, xiSpeakConfig.getXiSpeak().getLdRoleId()); } + public int getImplDeptLdsListLength(String deptId) { + return getImplDeptLdsList(deptId).size(); + } + public int getListSize(String jsonData){ if (org.apache.commons.lang3.StringUtils.isEmpty(jsonData)) { return 0; diff --git a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/extbpm/listener/task/SaveCurrentTaskAssigneeLocalListener.java b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/extbpm/listener/task/SaveCurrentTaskAssigneeLocalListener.java index 0b8a6f4..dfe5fb1 100644 --- a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/extbpm/listener/task/SaveCurrentTaskAssigneeLocalListener.java +++ b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/extbpm/listener/task/SaveCurrentTaskAssigneeLocalListener.java @@ -3,7 +3,9 @@ package org.jeecg.modules.extbpm.listener.task; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.flowable.engine.RuntimeService; +import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.TaskListener; +import org.flowable.engine.runtime.Execution; import org.flowable.task.service.delegate.DelegateTask; import org.jeecg.common.util.SpringContextUtils; @@ -21,24 +23,55 @@ public class SaveCurrentTaskAssigneeLocalListener implements TaskListener { runtimeService = SpringContextUtils.getBean(RuntimeService.class); } + + @Override public void notify(DelegateTask delegateTask) { - if (delegateTask == null) { - return; - } + if (delegateTask == null) return; + String assignee = delegateTask.getAssignee(); - if (StringUtils.isBlank(assignee)) { - log.warn("SaveCurrentTaskAssigneeLocalListener skipped, taskId={}, taskDefinitionKey={}, assignee is blank", - delegateTask.getId(), delegateTask.getTaskDefinitionKey()); + if (StringUtils.isBlank(assignee)) return; + + String currentExecutionId = delegateTask.getExecutionId(); + if (StringUtils.isBlank(currentExecutionId)) return; + + // 2. 先通过 runtimeService 查询当前的执行实例对象 + Execution currentExecution = runtimeService.createExecutionQuery() + .executionId(currentExecutionId) + .singleResult(); + + if (currentExecution == null) return; + + // 2. 向上寻找第一层父级 (比如:内层会签容器/子流程) + String parentId = currentExecution.getParentId(); + if (StringUtils.isBlank(parentId)) { + log.warn("无法找到父级执行实例,当前已是顶层"); return; } - if (StringUtils.isBlank(delegateTask.getExecutionId())) { - log.warn("SaveCurrentTaskAssigneeLocalListener skipped, taskId={}, taskDefinitionKey={}, executionId is blank", - delegateTask.getId(), delegateTask.getTaskDefinitionKey()); - return; + + // 3. 核心:通过 runtimeService 获取第一层父级的实体对象,从而拿到第二层的 ID + // 只有拿到实体对象,才能调用 getParentId() 继续向上爬 + Execution parentExecution = runtimeService.createExecutionQuery() + .executionId(parentId) + .singleResult(); + + if (parentExecution != null) { + // 4. 获取第二层父级 ID (大会签容器/外层作用域) + String grandParentId = parentExecution.getParentId(); + + // 5. 确定最终存储目标 + // 如果有第二层父级,则存入第二层;如果没有,则退而求其次存入第一层 + String targetId = StringUtils.isNotBlank(grandParentId) ? grandParentId : parentId; + + try { + // 6. 执行存储 + runtimeService.setVariableLocal(targetId, VARIABLE_NAME, assignee); + + log.info("变量已存入向上两层级:TargetId={}, OriginalId={}, Assignee={}", + targetId, currentExecution.getId(), assignee); + } catch (Exception e) { + log.error("设置嵌套局部变量失败", e); + } } - runtimeService.setVariableLocal(delegateTask.getExecutionId(), VARIABLE_NAME, assignee); - log.info("SaveCurrentTaskAssigneeLocalListener success, taskId={}, taskDefinitionKey={}, variableName={}, assignee={}", - delegateTask.getId(), delegateTask.getTaskDefinitionKey(), VARIABLE_NAME, assignee); } } diff --git a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/extbpm/process/common/expression/FlowNodeExpression.java b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/extbpm/process/common/expression/FlowNodeExpression.java index 7f131af..bc1642f 100644 --- a/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/extbpm/process/common/expression/FlowNodeExpression.java +++ b/jeecg-boot-platform/jeecg-boot-module-bpm-flowable/src/main/java/org/jeecg/modules/extbpm/process/common/expression/FlowNodeExpression.java @@ -304,6 +304,62 @@ public class FlowNodeExpression { return Collections.emptyList(); } +// +// /** +// * 从当前流程实例的所有执行实例中获取指定的局部变量 +// * +// * @param execution 当前执行流 +// * @param variableName 变量名 +// * @return 审批人字符串 (找到第一个即返回,未找到返回空串) +// */ +// public String getSubApproveLeader(DelegateExecution execution, String variableName) { +// if (execution == null || StringUtils.isBlank(variableName)) { +// return StringUtils.EMPTY; +// } +// +// try { +// // 1. 优先检查当前节点是否有该局部变量 +// if (execution.hasVariableLocal(variableName)) { +// return String.valueOf(execution.getVariableLocal(variableName)); +// } +// +// // 2. 遍历当前流程实例下所有的执行流 (Execution) +// // 这样可以覆盖到你之前“向上两层”或者在其他同级分支设置的 Local 变量 +// List executions = runtimeService.createExecutionQuery() +// .processInstanceId(execution.getProcessInstanceId()) +// .list(); +// +// for (Execution childExecution : executions) { +// // 跳过当前已经检查过的 +// if (execution.getId().equals(childExecution.getId())) { +// continue; +// } +// +// // 尝试获取每个执行流下的 Local 变量 +// Object localVariable = runtimeService.getVariableLocal(childExecution.getId(), variableName); +// if (localVariable != null) { +// // 找到即返回 String +// return String.valueOf(localVariable); +// } +// } +// +// // 3. 兜底逻辑:如果全流程的所有 Execution Local 都没有,则尝试获取全局变量 +// Object variable = execution.getVariable(variableName); +// if (variable != null) { +// return String.valueOf(variable); +// } +// } catch (Exception e) { +// log.warn("getSubApproveLeader failed, executionId={}, variableName={}", +// execution.getId(), variableName, e); +// } +// +// return StringUtils.EMPTY; +// } + + public int getSonProcessVariableLength(DelegateExecution execution, String variableName){ + return getSonProcessVariable(execution, variableName).size(); + } + /** * Get first subprocess variable username. * Example: ${flowNodeExpression.getSonProcessVariableString(execution, 'subApproveUser')}