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 fce908a..26f11b9 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 @@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSONObject; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; +import org.jeecg.common.exception.JeecgBootException; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.runtime.Execution; @@ -276,6 +277,28 @@ public class FlowNodeExpression { return sysbase.getUserByRoleIdLocalApi(roleId); } + /** + * Get required usernames for a Flowable multi-instance task. + * An empty collection would otherwise make Flowable skip the task, so fail fast instead. + * Example: ${flowNodeExpression.getRequiredUsersListByRole('roleIdValue')} + * + * @param roleId system role id + * @return non-empty username list + */ + public List getRequiredUsersListByRole(String roleId) { + if (StringUtils.isBlank(roleId)) { + throw new JeecgBootException("流程角色ID不能为空"); + } + + List usernames = ISysBaseAPI.getUsernamesByRoleIdLocalApi(roleId); + log.info("流程多实例按角色取人,roleId={}, usernames={}, count={}", roleId, usernames, + usernames == null ? 0 : usernames.size()); + if (CollectionUtils.isEmpty(usernames)) { + throw new JeecgBootException("角色[" + roleId + "]未配置有效用户,流程无法继续"); + } + return usernames; + } + /** * Get subprocess variable. * Example: ${flowNodeExpression.getSonProcessVariable(execution, 'subApproveUser')} diff --git a/jeecg-module-system/jeecg-system-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/fallback/SysBaseAPIFallback.java b/jeecg-module-system/jeecg-system-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/fallback/SysBaseAPIFallback.java index 7b8a3d3..9336d11 100644 --- a/jeecg-module-system/jeecg-system-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/fallback/SysBaseAPIFallback.java +++ b/jeecg-module-system/jeecg-system-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/fallback/SysBaseAPIFallback.java @@ -10,6 +10,7 @@ import org.jeecg.common.constant.enums.EmailTemplateEnum; import org.jeecg.common.system.api.ISysBaseAPI; import org.jeecg.common.system.vo.*; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @@ -24,6 +25,12 @@ public class SysBaseAPIFallback implements ISysBaseAPI { @Setter private Throwable cause; + @Override + public List getUsernamesByRoleIdLocalApi(String roleId) { + log.error("Query usernames by role failed, roleId={}", roleId, cause); + return Collections.emptyList(); + } + @Override public void sendSysAnnouncement(MessageDTO message) { log.error("发送消息失败 {}", cause); diff --git a/jeecg-module-system/jeecg-system-api/jeecg-system-local-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java b/jeecg-module-system/jeecg-system-api/jeecg-system-local-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java index 632c7c4..8a994ba 100644 --- a/jeecg-module-system/jeecg-system-api/jeecg-system-local-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java +++ b/jeecg-module-system/jeecg-system-api/jeecg-system-local-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java @@ -575,4 +575,13 @@ public interface ISysBaseAPI extends CommonAPI { List getUsersListByDeptIdAndRoleIdLocalApi(String deptId, String roleId); List getUserByRoleIdLocalApi(String roleId); - } + + /** + * Query active usernames by role for Flowable multi-instance tasks. + * This method intentionally uses an independent query path so existing role queries remain unchanged. + * + * @param roleId system role id + * @return active username list + */ + List getUsernamesByRoleIdLocalApi(String roleId); +} diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysUserMapper.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysUserMapper.java index 4a359dc..dfe3411 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysUserMapper.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysUserMapper.java @@ -251,4 +251,13 @@ public interface SysUserMapper extends BaseMapper { * @return */ List getUserByRoleId(String roleId); + + /** + * Query active usernames by role through a dedicated statement. + * It must not reuse the overloaded getUserByRoleId statement used by the user management page. + * + * @param roleId role id + * @return username list + */ + List getUsernamesByRoleId(@Param("roleId") String roleId); } diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml index 4efa813..248441f 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml @@ -59,6 +59,17 @@ + + +