From 0eeb2a144b75e304397da8e98854e5f158b1f7ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 4 Aug 2025 10:40:10 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=8A=9E?= =?UTF-8?q?=E7=90=86=E4=BA=BA=E6=9D=83=E9=99=90=E8=AE=BE=E7=BD=AE=E5=88=97?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/domain/vo/RemoteTaskAssigneeVo.java | 5 +- .../common/excel/core/ExcelDownHandler.java | 3 +- .../dubbo/RemoteTaskAssigneeServiceImpl.java | 2 +- .../common/enums/TaskAssigneeEnum.java | 26 +++++ .../service/impl/FlwSpelServiceImpl.java | 2 +- .../impl/FlwTaskAssigneeServiceImpl.java | 99 ++++++++++++------- 6 files changed, 98 insertions(+), 39 deletions(-) diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/vo/RemoteTaskAssigneeVo.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/vo/RemoteTaskAssigneeVo.java index 34976853c..aba8bde92 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/vo/RemoteTaskAssigneeVo.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/vo/RemoteTaskAssigneeVo.java @@ -1,6 +1,5 @@ package org.dromara.system.api.domain.vo; -import cn.hutool.core.convert.Convert; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -56,14 +55,14 @@ public class RemoteTaskAssigneeVo implements Serializable { Function storageId, Function handlerCode, Function handlerName, - Function groupName, + Function groupName, Function createTimeMapper) { return sourceList.stream() .map(item -> new TaskHandler( storageId.apply(item), handlerCode.apply(item), handlerName.apply(item), - groupName != null ? Convert.toStr(groupName.apply(item)) : null, + groupName.apply(item), createTimeMapper.apply(item) )).collect(Collectors.toList()); } diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java index f3b641545..81a3da449 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java @@ -1,6 +1,7 @@ package org.dromara.common.excel.core; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.EnumUtil; import cn.hutool.core.util.ObjectUtil; @@ -115,7 +116,7 @@ public class ExcelDownHandler implements SheetWriteHandler { // 否则如果指定了@ExcelEnumFormat,则使用枚举的逻辑 ExcelEnumFormat format = field.getDeclaredAnnotation(ExcelEnumFormat.class); List values = EnumUtil.getFieldValues(format.enumClass(), format.textField()); - options = StreamUtils.toList(values, String::valueOf); + options = StreamUtils.toList(values, Convert::toStr); } if (ObjectUtil.isNotEmpty(options)) { // 仅当下拉可选项不为空时执行 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteTaskAssigneeServiceImpl.java index 2824dcd16..eec27e842 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteTaskAssigneeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteTaskAssigneeServiceImpl.java @@ -61,7 +61,7 @@ public class RemoteTaskAssigneeServiceImpl implements RemoteTaskAssigneeService TableDataInfo page = roleService.selectPageRoleList(bo, pageQuery); // 使用封装的字段映射方法进行转换 List handlers = RemoteTaskAssigneeVo.convertToHandlerList(page.getRows(), - item -> Convert.toStr(item.getRoleId()), SysRoleVo::getRoleKey, SysRoleVo::getRoleName, null, SysRoleVo::getCreateTime); + item -> Convert.toStr(item.getRoleId()), SysRoleVo::getRoleKey, SysRoleVo::getRoleName, item -> "", SysRoleVo::getCreateTime); return new RemoteTaskAssigneeVo(page.getTotal(), handlers); } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java index c604f97e7..fff268837 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java @@ -3,6 +3,7 @@ package org.dromara.workflow.common.enums; import lombok.AllArgsConstructor; import lombok.Getter; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StringUtils; import java.util.Arrays; import java.util.List; @@ -110,5 +111,30 @@ public enum TaskAssigneeEnum { .map(TaskAssigneeEnum::getCode) .collect(Collectors.toList()); } + + /** + * 判断当前办理人类型是否需要调用部门服务(deptService) + * + * @return 如果类型是 USER、DEPT 或 POST,则返回 true;否则返回 false + */ + public boolean needsDeptService() { + return this == USER || this == DEPT || this == POST; + } + + /** + * 判断给定字符串是否符合 SPEL 表达式格式(以 $ 或 # 开头) + * + * @param value 待判断字符串 + * @return 是否为 SPEL 表达式 + */ + public static boolean isSpelExpression(String value) { + if (value == null) { + return false; + } + // $前缀表示默认办理人变量策略 + // #前缀表示spel办理人变量策略 + return StringUtils.startsWith(value, "$") || StringUtils.startsWith(value, "#"); + } + } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwSpelServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwSpelServiceImpl.java index 2a45f8eb5..d103cc513 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwSpelServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwSpelServiceImpl.java @@ -162,7 +162,7 @@ public class FlwSpelServiceImpl implements IFlwSpelService { TableDataInfo page = this.queryPageList(bo, pageQuery); // 使用封装的字段映射方法进行转换 List handlers = RemoteTaskAssigneeVo.convertToHandlerList(page.getRows(), - FlowSpelVo::getViewSpel, c -> "", FlowSpelVo::getRemark, null, FlowSpelVo::getCreateTime); + FlowSpelVo::getViewSpel, item -> "", FlowSpelVo::getRemark, item -> "", FlowSpelVo::getCreateTime); return new RemoteTaskAssigneeVo(page.getTotal(), handlers); } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java index cebdec5ce..e74ca985c 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java @@ -4,12 +4,14 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Pair; +import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.DubboReference; import org.dromara.common.core.enums.FormatsType; import org.dromara.common.core.utils.DateUtils; +import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.system.api.*; import org.dromara.system.api.domain.bo.RemoteTaskAssigneeBo; @@ -29,6 +31,7 @@ import org.dromara.workflow.service.IFlwTaskAssigneeService; import org.springframework.stereotype.Service; import java.util.*; +import java.util.stream.Collectors; /** * 流程设计器-获取办理人权限设置列表 @@ -53,6 +56,7 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand private RemoteRoleService remoteRoleService; @DubboReference private RemotePostService remotePostService; + private final IFlwSpelService spelService; /** @@ -97,10 +101,10 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand return Collections.emptyList(); } // 解析并归类 ID,同时记录原始顺序和对应解析结果 - Map> typeIdMap = new EnumMap<>(TaskAssigneeEnum.class); - Map> parsedMap = new LinkedHashMap<>(); + Map> typeIdMap = new EnumMap<>(TaskAssigneeEnum.class); + Map> parsedMap = new LinkedHashMap<>(); for (String storageId : storageIds) { - Pair parsed = this.parseStorageId(storageId); + Pair parsed = this.parseStorageId(storageId); parsedMap.put(storageId, parsed); if (parsed != null) { typeIdMap.computeIfAbsent(parsed.getKey(), k -> new ArrayList<>()).add(parsed.getValue()); @@ -108,14 +112,13 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand } // 查询所有类型对应的 ID 名称映射 - Map> nameMap = new EnumMap<>(TaskAssigneeEnum.class); + Map> nameMap = new EnumMap<>(TaskAssigneeEnum.class); typeIdMap.forEach((type, ids) -> nameMap.put(type, this.getNamesByType(type, ids))); - // 组装返回结果,保持原始顺序 return parsedMap.entrySet().stream() .map(entry -> { String storageId = entry.getKey(); - Pair parsed = entry.getValue(); + Pair parsed = entry.getValue(); String handlerName = (parsed == null) ? null : nameMap.getOrDefault(parsed.getKey(), Collections.emptyMap()) .get(parsed.getValue()); @@ -140,12 +143,29 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand * 根据任务办理类型获取部门数据 */ private List fetchDeptData(TaskAssigneeEnum type) { - if (type == TaskAssigneeEnum.USER || type == TaskAssigneeEnum.DEPT || type == TaskAssigneeEnum.POST) { + if (type.needsDeptService()) { return remoteDeptService.selectDeptsByList(); } return new ArrayList<>(); } + /** + * 获取权限分组名称 + * + * @param type 任务分配人枚举 + * @param groupName 权限分组 + * @return 权限分组名称 + */ + private String getGroupName(TaskAssigneeEnum type, String groupName) { + if (StringUtils.isEmpty(groupName)) { + return DEFAULT_GROUP_NAME; + } + if (type.needsDeptService()) { + return remoteDeptService.selectDeptNameByIds(groupName); + } + return DEFAULT_GROUP_NAME; + } + /** * 构建部门树状结构 */ @@ -164,10 +184,7 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand .setStorageId(assignee -> type.getCode() + assignee.getStorageId()) .setHandlerCode(assignee -> StringUtils.blankToDefault(assignee.getHandlerCode(), "无")) .setHandlerName(assignee -> StringUtils.blankToDefault(assignee.getHandlerName(), "无")) - .setGroupName(assignee -> StringUtils.defaultIfBlank( - Optional.ofNullable(assignee.getGroupName()) - .map(remoteDeptService::selectDeptNameByIds) - .orElse(DEFAULT_GROUP_NAME), DEFAULT_GROUP_NAME)) + .setGroupName(assignee -> this.getGroupName(type, assignee.getGroupName())) .setCreateTime(assignee -> DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, assignee.getCreateTime())); } @@ -184,9 +201,9 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand if (StringUtils.isEmpty(storageIds)) { return List.of(); } - Map> typeIdMap = new EnumMap<>(TaskAssigneeEnum.class); + Map> typeIdMap = new EnumMap<>(TaskAssigneeEnum.class); for (String storageId : storageIds.split(StringUtils.SEPARATOR)) { - Pair parsed = this.parseStorageId(storageId); + Pair parsed = this.parseStorageId(storageId); if (parsed != null) { typeIdMap.computeIfAbsent(parsed.getKey(), k -> new ArrayList<>()).add(parsed.getValue()); } @@ -207,13 +224,17 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand * 如果类型为部门(DEPT),则通过部门ID列表查询; * 如果类型为岗位(POST)或无法识别的类型,则返回空列表 */ - private List getUsersByType(TaskAssigneeEnum type, List ids) { + private List getUsersByType(TaskAssigneeEnum type, List ids) { + if (type == TaskAssigneeEnum.SPEL) { + return new ArrayList<>(); + } + List longIds = StreamUtils.toList(ids, Convert::toLong); return switch (type) { - case USER -> remoteUserService.selectListByIds(ids); - case ROLE -> remoteUserService.selectUsersByRoleIds(ids); - case DEPT -> remoteUserService.selectUsersByDeptIds(ids); - case POST -> remoteUserService.selectUsersByPostIds(ids); - case SPEL -> new ArrayList<>(); + case USER -> remoteUserService.selectListByIds(longIds); + case ROLE -> remoteUserService.selectUsersByRoleIds(longIds); + case DEPT -> remoteUserService.selectUsersByDeptIds(longIds); + case POST -> remoteUserService.selectUsersByPostIds(longIds); + default -> new ArrayList<>(); }; } @@ -224,14 +245,28 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand * @param ids ID 列表(如用户ID、角色ID等) * @return 返回 Map,其中 key 为 ID,value 为对应的名称 */ - private Map getNamesByType(TaskAssigneeEnum type, List ids) { - return switch (type) { - case USER -> remoteUserService.selectUserNamesByIds(ids); - case ROLE -> remoteRoleService.selectRoleNamesByIds(ids); - case DEPT -> remoteDeptService.selectDeptNamesByIds(ids); - case POST -> remotePostService.selectPostNamesByIds(ids); - case SPEL -> new HashMap<>(); + private Map getNamesByType(TaskAssigneeEnum type, List ids) { + if (type == TaskAssigneeEnum.SPEL) { + return spelService.selectRemarksBySpels(ids); + } + + List longIds = StreamUtils.toList(ids, Convert::toLong); + Map rawMap = switch (type) { + case USER -> remoteUserService.selectUserNamesByIds(longIds); + case ROLE -> remoteRoleService.selectRoleNamesByIds(longIds); + case DEPT -> remoteDeptService.selectDeptNamesByIds(longIds); + case POST -> remotePostService.selectPostNamesByIds(longIds); + default -> Collections.emptyMap(); }; + if (MapUtil.isEmpty(rawMap)) { + return Collections.emptyMap(); + } + return rawMap.entrySet() + .stream() + .collect(Collectors.toMap( + e -> Convert.toStr(e.getKey()), + Map.Entry::getValue + )); } /** @@ -240,22 +275,20 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand * @param storageId 例如 "user:123" 或 "456" * @return Pair(TaskAssigneeEnum, Long),如果格式非法返回 null */ - private Pair parseStorageId(String storageId) { + private Pair parseStorageId(String storageId) { if (StringUtils.isBlank(storageId)) { return null; } - // 跳过以 $ 或 # 开头的字符串 - if (StringUtils.startsWith(storageId, "$") || StringUtils.startsWith(storageId, "#")) { - log.debug("跳过 storageId 解析,检测到内置变量表达式:{}", storageId); - return null; + if (TaskAssigneeEnum.isSpelExpression(storageId)) { + return Pair.of(TaskAssigneeEnum.SPEL, storageId); } try { String[] parts = storageId.split(StrUtil.COLON, 2); if (parts.length < 2) { - return Pair.of(TaskAssigneeEnum.USER, Convert.toLong(parts[0])); + return Pair.of(TaskAssigneeEnum.USER, parts[0]); } else { TaskAssigneeEnum type = TaskAssigneeEnum.fromCode(parts[0] + StrUtil.COLON); - return Pair.of(type, Convert.toLong(parts[1])); + return Pair.of(type, parts[1]); } } catch (Exception e) { log.warn("解析 storageId 失败,格式非法:{},错误信息:{}", storageId, e.getMessage());