From 808ce9c25ad20fd3170ec1b7389c7198a64badfb Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Fri, 1 Aug 2025 17:57:08 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E5=8A=9E=E7=90=86?= =?UTF-8?q?=E4=BA=BA=E6=9D=83=E9=99=90=E8=AE=BE=E7=BD=AE=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/domain/dto/TaskAssigneeDTO.java | 5 +- .../common/core/utils/StreamUtils.java | 1 - .../common/excel/core/ExcelDownHandler.java | 3 +- .../impl/SysTaskAssigneeServiceImpl.java | 8 +- .../common/enums/TaskAssigneeEnum.java | 26 +++++ .../service/impl/FlwSpelServiceImpl.java | 6 +- .../impl/FlwTaskAssigneeServiceImpl.java | 107 +++++++++++------- 7 files changed, 104 insertions(+), 52 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java index f532f4a3d..78fb40ec9 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java @@ -1,6 +1,5 @@ package org.dromara.common.core.domain.dto; -import cn.hutool.core.convert.Convert; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -56,14 +55,14 @@ public class TaskAssigneeDTO 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-core/src/main/java/org/dromara/common/core/utils/StreamUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StreamUtils.java index 1342deb71..f9e53a508 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StreamUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StreamUtils.java @@ -7,7 +7,6 @@ import lombok.NoArgsConstructor; import java.util.*; import java.util.function.BiFunction; -import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; 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/service/impl/SysTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java index 21f5ef949..7b31f7b1f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java @@ -59,7 +59,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { TableDataInfo page = roleService.selectPageRoleList(bo, pageQuery); // 使用封装的字段映射方法进行转换 List handlers = TaskAssigneeDTO.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 TaskAssigneeDTO(page.getTotal(), handlers); } @@ -83,7 +83,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { TableDataInfo page = postService.selectPagePostList(bo, pageQuery); // 使用封装的字段映射方法进行转换 List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRows(), - p -> Convert.toStr(p.getPostId()), SysPostVo::getPostCategory, SysPostVo::getPostName, SysPostVo::getDeptId, SysPostVo::getCreateTime); + item -> Convert.toStr(item.getPostId()), SysPostVo::getPostCategory, SysPostVo::getPostName, item -> Convert.toStr(item.getDeptId()), SysPostVo::getCreateTime); return new TaskAssigneeDTO(page.getTotal(), handlers); } @@ -107,7 +107,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { TableDataInfo page = deptService.selectPageDeptList(bo, pageQuery); // 使用封装的字段映射方法进行转换 List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRows(), - d -> Convert.toStr(d.getDeptId()), SysDeptVo::getDeptCategory, SysDeptVo::getDeptName, SysDeptVo::getParentId, SysDeptVo::getCreateTime); + item -> Convert.toStr(item.getDeptId()), SysDeptVo::getDeptCategory, SysDeptVo::getDeptName, item -> Convert.toStr(item.getParentId()), SysDeptVo::getCreateTime); return new TaskAssigneeDTO(page.getTotal(), handlers); } @@ -131,7 +131,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { TableDataInfo page = userService.selectPageUserList(bo, pageQuery); // 使用封装的字段映射方法进行转换 List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRows(), - u -> Convert.toStr(u.getUserId()), SysUserVo::getUserName, SysUserVo::getNickName, SysUserVo::getDeptId, SysUserVo::getCreateTime); + item -> Convert.toStr(item.getUserId()), SysUserVo::getUserName, SysUserVo::getNickName, item -> Convert.toStr(item.getDeptId()), SysUserVo::getCreateTime); return new TaskAssigneeDTO(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 be9567a5d..e06b31448 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 = TaskAssigneeDTO.convertToHandlerList(page.getRows(), - FlowSpelVo::getViewSpel, c -> "", FlowSpelVo::getRemark, null, FlowSpelVo::getCreateTime); + FlowSpelVo::getViewSpel, item -> "", FlowSpelVo::getRemark, item -> "", FlowSpelVo::getCreateTime); return new TaskAssigneeDTO(page.getTotal(), handlers); } @@ -182,7 +182,9 @@ public class FlwSpelServiceImpl implements IFlwSpelService { .select(FlowSpel::getViewSpel, FlowSpel::getRemark) .in(FlowSpel::getViewSpel, viewSpels) ); - return StreamUtils.toMap(list, FlowSpel::getViewSpel, FlowSpel::getRemark); + return StreamUtils.toMap(list, FlowSpel::getViewSpel, x -> + StringUtils.isEmpty(x.getRemark()) ? "" : x.getRemark() + ); } } 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 88abb69b8..9e9c091ad 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,6 +4,7 @@ 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; @@ -14,6 +15,7 @@ import org.dromara.common.core.domain.model.TaskAssigneeBody; import org.dromara.common.core.enums.FormatsType; import org.dromara.common.core.service.*; import org.dromara.common.core.utils.DateUtils; +import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.warm.flow.ui.dto.HandlerFunDto; import org.dromara.warm.flow.ui.dto.HandlerQuery; @@ -28,6 +30,7 @@ import org.dromara.workflow.service.IFlwTaskAssigneeService; import org.springframework.stereotype.Service; import java.util.*; +import java.util.stream.Collectors; /** * 流程设计器-获取办理人权限设置列表 @@ -90,31 +93,25 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand return Collections.emptyList(); } // 解析并归类 ID,同时记录原始顺序和对应解析结果 - Map> typeIdMap = new EnumMap<>(TaskAssigneeEnum.class); - Map> parsedMap = new LinkedHashMap<>(); - List spelList = new ArrayList<>(); + 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()); - } else if (StringUtils.startsWith(storageId, "$") || StringUtils.startsWith(storageId, "#")) { - // $前缀表示默认办理人变量策略 - // #前缀表示spel办理人变量策略 - spelList.add(storageId); } } // 查询所有类型对应的 ID 名称映射 - Map> nameMap = new EnumMap<>(TaskAssigneeEnum.class); + Map> nameMap = new EnumMap<>(TaskAssigneeEnum.class); typeIdMap.forEach((type, ids) -> nameMap.put(type, this.getNamesByType(type, ids))); - Map spelMap = spelService.selectRemarksBySpels(spelList); // 组装返回结果,保持原始顺序 return parsedMap.entrySet().stream() .map(entry -> { String storageId = entry.getKey(); - Pair parsed = entry.getValue(); - String handlerName = (parsed == null) ? spelMap.get(storageId) + Pair parsed = entry.getValue(); + String handlerName = (parsed == null) ? null : nameMap.getOrDefault(parsed.getKey(), Collections.emptyMap()) .get(parsed.getValue()); return new HandlerFeedBackVo(storageId, handlerName); @@ -138,12 +135,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 deptService.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 deptService.selectDeptNameByIds(groupName); + } + return DEFAULT_GROUP_NAME; + } + /** * 构建部门树状结构 */ @@ -162,10 +176,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(deptService::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())); } @@ -182,9 +193,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()); } @@ -205,13 +216,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 -> userService.selectListByIds(ids); - case ROLE -> userService.selectUsersByRoleIds(ids); - case DEPT -> userService.selectUsersByDeptIds(ids); - case POST -> userService.selectUsersByPostIds(ids); - case SPEL -> new ArrayList<>(); + case USER -> userService.selectListByIds(longIds); + case ROLE -> userService.selectUsersByRoleIds(longIds); + case DEPT -> userService.selectUsersByDeptIds(longIds); + case POST -> userService.selectUsersByPostIds(longIds); + default -> new ArrayList<>(); }; } @@ -222,14 +237,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 -> userService.selectUserNamesByIds(ids); - case ROLE -> roleService.selectRoleNamesByIds(ids); - case DEPT -> deptService.selectDeptNamesByIds(ids); - case POST -> postService.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 -> userService.selectUserNamesByIds(longIds); + case ROLE -> roleService.selectRoleNamesByIds(longIds); + case DEPT -> deptService.selectDeptNamesByIds(longIds); + case POST -> postService.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 + )); } /** @@ -238,24 +267,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, "#")) { - // $前缀表示默认办理人变量策略 - // #前缀表示spel办理人变量策略 - 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());