Преглед на файлове

update 解析扩展属性 JSON,构建 Node 扩展属性对象,增强代码可读性

AprilWind преди 10 месеца
родител
ревизия
25de0b3530

+ 45 - 0
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/NodeExtVo.java

@@ -0,0 +1,45 @@
+package org.dromara.workflow.domain.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Node 扩展属性解析结果 VO
+ * <p>
+ * 用于封装从扩展属性 JSON 中解析出的各类信息,包括按钮权限、抄送对象和自定义参数。
+ *
+ * @author AprilWind
+ */
+@Data
+public class NodeExtVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 按钮权限列表
+     * <p>
+     * 根据扩展属性中 ButtonPermissionEnum 类型的数据生成,每个元素表示一个按钮及其是否勾选。
+     */
+    private List<ButtonPermissionVo> buttonPermissions;
+
+    /**
+     * 抄送对象 ID 集合
+     * <p>
+     * 根据扩展属性中 CopySettingEnum 类型的数据生成,存储需要抄送的对象 ID
+     */
+    private Set<String> copySettings;
+
+    /**
+     * 自定义参数 Map
+     * <p>
+     * 根据扩展属性中 VariablesEnum 类型的数据生成,存储 key=value 格式的自定义参数
+     */
+    private Map<String, String> variables;
+
+}

+ 16 - 6
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwNodeExtService.java

@@ -1,8 +1,6 @@
 package org.dromara.workflow.service;
 
-import org.dromara.workflow.domain.vo.ButtonPermissionVo;
-
-import java.util.List;
+import org.dromara.workflow.domain.vo.NodeExtVo;
 
 /**
  * 流程节点扩展属性 服务层
@@ -12,11 +10,23 @@ import java.util.List;
 public interface IFlwNodeExtService {
 
     /**
-     * 从扩展属性构建按钮权限列表:根据 ext 中记录的权限值,标记每个按钮是否勾选
+     * 解析扩展属性 JSON 并构建 Node 扩展属性对象
+     * <p>
+     * 根据传入的 JSON 字符串,将扩展属性分为三类:
+     * 1. ButtonPermissionEnum:解析为按钮权限列表,标记每个按钮是否勾选
+     * 2. CopySettingEnum:解析为抄送对象 ID 集合
+     * 3. VariablesEnum:解析为自定义参数 Map
+     *
+     * <p>示例 JSON:
+     * [
+     * {"code": "ButtonPermissionEnum", "value": "back,termination"},
+     * {"code": "CopySettingEnum", "value": "1"},
+     * {"code": "VariablesEnum", "value": "key1=value1,key2=value2"}
+     * ]
      *
      * @param ext 扩展属性 JSON 字符串
-     * @return 按钮权限 VO 列表
+     * @return NodeExtVo 对象,封装按钮权限列表、抄送对象集合和自定义参数 Map
      */
-    List<ButtonPermissionVo> buildButtonPermissionsFromExt(String ext);
+    NodeExtVo parseNodeExt(String ext);
 
 }

+ 60 - 62
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwNodeExtServiceImpl.java

@@ -1,8 +1,8 @@
 package org.dromara.workflow.service.impl;
 
 import cn.hutool.core.convert.Convert;
+import cn.hutool.core.lang.Dict;
 import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.core.domain.dto.DictTypeDTO;
@@ -17,12 +17,12 @@ import org.dromara.workflow.common.enums.CopySettingEnum;
 import org.dromara.workflow.common.enums.NodeExtEnum;
 import org.dromara.workflow.common.enums.VariablesEnum;
 import org.dromara.workflow.domain.vo.ButtonPermissionVo;
+import org.dromara.workflow.domain.vo.NodeExtVo;
 import org.dromara.workflow.service.IFlwNodeExtService;
 import org.springframework.stereotype.Service;
 
 import java.util.*;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
  * 流程设计器-节点扩展属性
@@ -187,73 +187,71 @@ public class FlwNodeExtServiceImpl implements NodeExtService, IFlwNodeExtService
     }
 
     /**
-     * 从扩展属性构建按钮权限列表:根据 ext 中记录的权限值,标记每个按钮是否勾选
+     * 解析扩展属性 JSON 并构建 Node 扩展属性对象
+     * <p>
+     * 根据传入的 JSON 字符串,将扩展属性分为三类:
+     * 1. ButtonPermissionEnum:解析为按钮权限列表,标记每个按钮是否勾选
+     * 2. CopySettingEnum:解析为抄送对象 ID 集合
+     * 3. VariablesEnum:解析为自定义参数 Map
+     *
+     * <p>示例 JSON:
+     * [
+     * {"code": "ButtonPermissionEnum", "value": "back,termination"},
+     * {"code": "CopySettingEnum", "value": "1"},
+     * {"code": "VariablesEnum", "value": "key1=value1,key2=value2"}
+     * ]
      *
      * @param ext 扩展属性 JSON 字符串
-     * @return 按钮权限 VO 列表
+     * @return NodeExtVo 对象,封装按钮权限列表、抄送对象集合和自定义参数 Map
      */
     @Override
-    public List<ButtonPermissionVo> buildButtonPermissionsFromExt(String ext) {
-        // 解析 ext 为 Map<code, Set<value>>,用于标记权限
-        Map<String, Set<String>> permissionMap = JsonUtils.parseArray(ext, ButtonPermissionVo.class)
-            .stream()
-            .collect(Collectors.toMap(
-                ButtonPermissionVo::getCode,
-                item -> StringUtils.splitList(item.getValue()).stream()
-                    .map(String::trim)
-                    .filter(StrUtil::isNotBlank)
-                    .collect(Collectors.toSet()),
-                (a, b) -> b,
-                HashMap::new
-            ));
+    public NodeExtVo parseNodeExt(String ext) {
+        NodeExtVo nodeExtVo = new NodeExtVo();
 
-        // 构建按钮权限列表,标记哪些按钮在 permissionMap 中出现(表示已勾选)
-        return buildPermissionsFromSources(permissionMap, List.of(ButtonPermissionEnum.class));
-    }
+        // 解析 JSON 为 Dict 列表
+        List<Dict> nodeExtMap = JsonUtils.parseArrayMap(ext);
 
-    /**
-     * 将权限映射与按钮权限来源(枚举类或字典类型)进行匹配,生成权限视图列表
-     * <p>
-     * 使用说明:
-     * - sources 支持传入多个来源类型,支持 NodeExtEnum 枚举类 或 字典类型字符串(dictType)
-     * - 若需要扩展更多按钮权限,只需在 sources 中新增对应的枚举类或字典类型
-     * <p>
-     * 示例:
-     * buildPermissionsFromSources(permissionMap, List.of(ButtonPermissionEnum.class, "custom_button_dict"));
-     *
-     * @param permissionMap 权限映射
-     * @param sources       枚举类或字典类型列表
-     * @return 按钮权限视图对象列表
-     */
-    @SuppressWarnings("unchecked cast")
-    private List<ButtonPermissionVo> buildPermissionsFromSources(Map<String, Set<String>> permissionMap, List<Object> sources) {
-        return sources.stream()
-            .flatMap(source -> {
-                if (source instanceof Class<?> clazz && NodeExtEnum.class.isAssignableFrom(clazz)) {
-                    Set<String> selectedSet = permissionMap.getOrDefault(clazz.getSimpleName(), Collections.emptySet());
-                    return extractDictItems(this.buildChildNode((Class<? extends NodeExtEnum>) clazz), selectedSet).stream();
-                } else if (source instanceof String dictType) {
-                    Set<String> selectedSet = permissionMap.getOrDefault(dictType, Collections.emptySet());
-                    return extractDictItems(this.buildChildNode(dictType), selectedSet).stream();
-                }
-                return Stream.empty();
-            }).toList();
-    }
+        for (Dict nodeExt : nodeExtMap) {
+            String code = nodeExt.getStr("code");
+            String value = nodeExt.getStr("value");
 
-    /**
-     * 从节点子项中提取字典项,并构建按钮权限视图对象列表
-     *
-     * @param childNode   子节点
-     * @param selectedSet 已选中的值集
-     * @return 按钮权限视图对象列表
-     */
-    private List<ButtonPermissionVo> extractDictItems(NodeExt.ChildNode childNode, Set<String> selectedSet) {
-        return Optional.ofNullable(childNode)
-            .map(NodeExt.ChildNode::getDict)
-            .orElse(List.of())
-            .stream()
-            .map(dict -> new ButtonPermissionVo(dict.getValue(), selectedSet.contains(dict.getValue())))
-            .toList();
+            if (ButtonPermissionEnum.class.getSimpleName().equals(code)) {
+                // 解析按钮权限
+                // 将 value 拆分为 Set<String>,便于精确匹配
+                Set<String> buttonSet = StringUtils.str2Set(value, StringUtils.SEPARATOR);
+
+                // 获取按钮字典配置
+                NodeExt.ChildNode childNode = buildChildNode(ButtonPermissionEnum.class);
+
+                // 构建 ButtonPermissionVo 列表
+                List<ButtonPermissionVo> buttonList = Optional.ofNullable(childNode)
+                    .map(NodeExt.ChildNode::getDict)
+                    .orElse(List.of())
+                    .stream()
+                    .map(dict -> new ButtonPermissionVo(dict.getValue(), buttonSet.contains(dict.getValue())))
+                    .toList();
+
+                nodeExtVo.setButtonPermissions(buttonList);
+
+            } else if (CopySettingEnum.class.getSimpleName().equals(code)) {
+                // 解析抄送对象 ID 集合
+                nodeExtVo.setCopySettings(StringUtils.str2Set(value, StringUtils.SEPARATOR));
+
+            } else if (VariablesEnum.class.getSimpleName().equals(code)) {
+                // 解析自定义参数
+                // 将 key=value 字符串拆分为 Map
+                Map<String, String> variables = Arrays.stream(StringUtils.split(value, StringUtils.SEPARATOR))
+                    .map(s -> StringUtils.split(s, "="))
+                    .filter(arr -> arr.length == 2)
+                    .collect(Collectors.toMap(arr -> arr[0], arr -> arr[1]));
+
+                nodeExtVo.setVariables(variables);
+            } else {
+                // 未知扩展类型,记录日志
+                log.warn("未知扩展类型:code={}, value={}", code, value);
+            }
+        }
+        return nodeExtVo;
     }
 
 }

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

@@ -48,6 +48,7 @@ import org.dromara.workflow.domain.FlowInstanceBizExt;
 import org.dromara.workflow.domain.bo.*;
 import org.dromara.workflow.domain.vo.FlowHisTaskVo;
 import org.dromara.workflow.domain.vo.FlowTaskVo;
+import org.dromara.workflow.domain.vo.NodeExtVo;
 import org.dromara.workflow.mapper.FlwCategoryMapper;
 import org.dromara.workflow.mapper.FlwInstanceBizExtMapper;
 import org.dromara.workflow.mapper.FlwTaskMapper;
@@ -597,8 +598,9 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
         if (ObjectUtil.isNull(flowNode)) {
             throw new NullPointerException("当前【" + flowTaskVo.getNodeCode() + "】节点编码不存在");
         }
+        NodeExtVo nodeExtVo = flwNodeExtService.parseNodeExt(flowNode.getExt());
         //设置按钮权限
-        flowTaskVo.setButtonList(flwNodeExtService.buildButtonPermissionsFromExt(flowNode.getExt()));
+        flowTaskVo.setButtonList(nodeExtVo.getButtonPermissions());
         flowTaskVo.setNodeRatio(flowNode.getNodeRatio());
         flowTaskVo.setApplyNode(flowNode.getNodeCode().equals(flwCommonService.applyNodeCode(task.getDefinitionId())));
         return flowTaskVo;