Ver código fonte

update 优化 办理人权限设置列表

疯狂的狮子Li 11 meses atrás
pai
commit
0eeb2a144b

+ 2 - 3
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<T, String> storageId,
         Function<T, String> handlerCode,
         Function<T, String> handlerName,
-        Function<T, Long> groupName,
+        Function<T, String> groupName,
         Function<T, Date> 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());
     }

+ 2 - 1
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<Object> values = EnumUtil.getFieldValues(format.enumClass(), format.textField());
-                options = StreamUtils.toList(values, String::valueOf);
+                options = StreamUtils.toList(values, Convert::toStr);
             }
             if (ObjectUtil.isNotEmpty(options)) {
                 // 仅当下拉可选项不为空时执行

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteTaskAssigneeServiceImpl.java

@@ -61,7 +61,7 @@ public class RemoteTaskAssigneeServiceImpl implements RemoteTaskAssigneeService
         TableDataInfo<SysRoleVo> page = roleService.selectPageRoleList(bo, pageQuery);
         // 使用封装的字段映射方法进行转换
         List<RemoteTaskAssigneeVo.TaskHandler> 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);
     }
 

+ 26 - 0
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, "#");
+    }
+
 }
 

+ 1 - 1
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwSpelServiceImpl.java

@@ -162,7 +162,7 @@ public class FlwSpelServiceImpl implements IFlwSpelService {
         TableDataInfo<FlowSpelVo> page = this.queryPageList(bo, pageQuery);
         // 使用封装的字段映射方法进行转换
         List<RemoteTaskAssigneeVo.TaskHandler> 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);
     }
 

+ 66 - 33
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<TaskAssigneeEnum, List<Long>> typeIdMap = new EnumMap<>(TaskAssigneeEnum.class);
-        Map<String, Pair<TaskAssigneeEnum, Long>> parsedMap = new LinkedHashMap<>();
+        Map<TaskAssigneeEnum, List<String>> typeIdMap = new EnumMap<>(TaskAssigneeEnum.class);
+        Map<String, Pair<TaskAssigneeEnum, String>> parsedMap = new LinkedHashMap<>();
         for (String storageId : storageIds) {
-            Pair<TaskAssigneeEnum, Long> parsed = this.parseStorageId(storageId);
+            Pair<TaskAssigneeEnum, String> 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<TaskAssigneeEnum, Map<Long, String>> nameMap = new EnumMap<>(TaskAssigneeEnum.class);
+        Map<TaskAssigneeEnum, Map<String, String>> 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<TaskAssigneeEnum, Long> parsed = entry.getValue();
+                Pair<TaskAssigneeEnum, String> 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<RemoteDeptVo> 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<TaskAssigneeEnum, List<Long>> typeIdMap = new EnumMap<>(TaskAssigneeEnum.class);
+        Map<TaskAssigneeEnum, List<String>> typeIdMap = new EnumMap<>(TaskAssigneeEnum.class);
         for (String storageId : storageIds.split(StringUtils.SEPARATOR)) {
-            Pair<TaskAssigneeEnum, Long> parsed = this.parseStorageId(storageId);
+            Pair<TaskAssigneeEnum, String> 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<RemoteUserVo> getUsersByType(TaskAssigneeEnum type, List<Long> ids) {
+    private List<RemoteUserVo> getUsersByType(TaskAssigneeEnum type, List<String> ids) {
+        if (type == TaskAssigneeEnum.SPEL) {
+            return new ArrayList<>();
+        }
+        List<Long> 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<Long, String> getNamesByType(TaskAssigneeEnum type, List<Long> 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<String, String> getNamesByType(TaskAssigneeEnum type, List<String> ids) {
+        if (type == TaskAssigneeEnum.SPEL) {
+            return spelService.selectRemarksBySpels(ids);
+        }
+
+        List<Long> longIds = StreamUtils.toList(ids, Convert::toLong);
+        Map<Long, String> 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<TaskAssigneeEnum, Long> parseStorageId(String storageId) {
+    private Pair<TaskAssigneeEnum, String> 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());