Ver Fonte

//构型-故障信息基础数据

wyj0522 há 18 horas atrás
pai
commit
0aecd5a866
12 ficheiros alterados com 482 adições e 48 exclusões
  1. 11 0
      eco-common/com-core/src/main/java/org/eco/vip/core/utils/MapUtils.java
  2. 13 3
      eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/controller/configuration/FaultController.java
  3. 6 4
      eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/controller/construct/ConstructController.java
  4. 5 4
      eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/domain/configuration/pojo/FaultBO.java
  5. 48 0
      eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/domain/configuration/pojo/MonitorTableVO.java
  6. 2 0
      eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/domain/construct/pojo/ConstructVO.java
  7. 18 8
      eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/config/FaultServiceImpl.java
  8. 8 0
      eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/config/IFaultService.java
  9. 186 0
      eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/config/calculateServiceImpl.java
  10. 71 27
      eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/construct/ConstructImpl.java
  11. 4 2
      eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/construct/IConstruct.java
  12. 110 0
      eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/construct/test.java

+ 11 - 0
eco-common/com-core/src/main/java/org/eco/vip/core/utils/MapUtils.java

@@ -0,0 +1,11 @@
+package org.eco.vip.core.utils;
+
+import cn.hutool.core.map.MapUtil;
+
+/**
+ * @Author: wyj
+ * @CreateTime: 2025-08-11
+ * @Belongpackage org.eco.vip.core.utils
+ */
+public class MapUtils extends MapUtil {
+}

+ 13 - 3
eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/controller/configuration/FaultController.java

@@ -42,9 +42,9 @@ public class FaultController extends BaseController {
      * @param faultBO
      * @return
      */
-    @GetMapping("/page")
+    @PostMapping("/page")
     @SaCheckPermission("system:fault:page")
-    public CommonResult<PageResult<FaultVO>> page(FaultBO faultBO) {
+    public CommonResult<PageResult<FaultVO>> page(@RequestBody FaultBO faultBO) {
         return success(iFaultService.selectPage(faultBO));
     }
 
@@ -53,7 +53,7 @@ public class FaultController extends BaseController {
      * @param faultBO
      * @return
      */
-    @GetMapping("/list")
+    @PostMapping("/list")
     public CommonResult<List<FaultVO>> list(@RequestBody @Valid FaultBO faultBO) {
         return success(iFaultService.selectList(faultBO));
     }
@@ -90,4 +90,14 @@ public class FaultController extends BaseController {
         iFaultService.getExtraStatistics();
         return CommonResult.success();
     }
+
+    /**
+     * 计算数据
+     * @param boList
+     * @return
+     */
+    @PostMapping("/calculate")
+    public CommonResult<List<FaultVO>> calculate(List<FaultBO> boList){
+        return iFaultService.calculate(boList);
+    }
 }

+ 6 - 4
eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/controller/construct/ConstructController.java

@@ -25,6 +25,8 @@ import org.springframework.web.multipart.MultipartFile;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import static org.eco.vip.core.pojo.CommonResult.fail;
 import static org.eco.vip.core.pojo.CommonResult.success;
@@ -70,12 +72,12 @@ public class ConstructController extends BaseController {
 
     /**
      * 查询部件详情信息
-     * @param id
+     * @param ids
      * @return
      */
-    @GetMapping("/selectOne")
-    public CommonResult<List<ConstructVO>> selectOne(String id) {
-        return success(iConstruct.selectOne(id));
+    @PostMapping("/selectOne")
+    public CommonResult<Map<String, List<String>>> selectOne(@RequestBody @Valid @NotEmpty(message = "集合不能为空") List<String> ids) {
+        return success(iConstruct.selectOne(ids));
     }
 
     /**

+ 5 - 4
eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/domain/configuration/pojo/FaultBO.java

@@ -10,6 +10,7 @@ import org.eco.vip.orm.domain.BaseBO;
 import org.eco.vip.reliability.ser.domain.configuration.FaultPO;
 
 import java.util.Date;
+import java.util.List;
 
 /**
  * @Author: wyj
@@ -355,12 +356,12 @@ public class FaultBO extends BaseBO {
 
     private String upTime;
 
-    private String model;
+    private List<String> model;
 
-    private String system;
+    private List<String> system;
 
-    private String aircraftSystem;
+    private List<String> aircraftSystem;
 
-    private String component;
+    private List<String> component;
 
 }

+ 48 - 0
eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/domain/configuration/pojo/MonitorTableVO.java

@@ -0,0 +1,48 @@
+package org.eco.vip.reliability.ser.domain.configuration.pojo;
+
+import lombok.Data;
+
+/**
+ * @Author: wyj
+ * @CreateTime: 2025-08-07
+ * @Belongpackage org.eco.vip.reliability.ser.domain.configuration.pojo
+ */
+@Data
+public class MonitorTableVO {
+    /**
+     * 序号
+     */
+    private Integer serialNumber;
+    /**
+     * 监控项目名称(飞机、系统、部件)
+     */
+    private String monitorItem;
+    /**
+     *  n-2月故障率
+     */
+    private Double n2MonthRate;
+    /**
+     * n-1月故障率
+     */
+    private Double n1MonthRate;
+    /**
+     * n月故障率
+     */
+    private Double nMonthRate;
+    /**
+     * 近三个月平均值
+     */
+    private Double average;
+    /**
+     * k值
+     */
+    private Double k;
+    /**
+     * 警戒值(UCL)
+     */
+    private Double ucl;
+    /**
+     * 警告状态(如:正常、警告)
+     */
+    private String warningStatus;
+}

+ 2 - 0
eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/domain/construct/pojo/ConstructVO.java

@@ -83,10 +83,12 @@ public class ConstructVO extends BaseEntity {
     /**
      * 父节点
      */
+
     private ConstructVO parent;
     /**
      * 树结构子节点
      */
+
     private List<ConstructVO> children;
 
 }

Diff do ficheiro suprimidas por serem muito extensas
+ 18 - 8
eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/config/FaultServiceImpl.java


+ 8 - 0
eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/config/IFaultService.java

@@ -1,5 +1,6 @@
 package org.eco.vip.reliability.ser.service.config;
 
+import org.eco.vip.core.pojo.CommonResult;
 import org.eco.vip.core.pojo.PageResult;
 import org.eco.vip.orm.service.IBaseService;
 import org.eco.vip.reliability.ser.domain.configuration.FaultPO;
@@ -51,4 +52,11 @@ public interface IFaultService extends IBaseService<FaultPO> {
      * @return
      */
     boolean update(FaultBO faultBO);
+
+    /**
+     * 计算数据
+     * @param boList
+     * @return
+     */
+    CommonResult<List<FaultVO>> calculate(List<FaultBO> boList);
 }

+ 186 - 0
eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/config/calculateServiceImpl.java

@@ -0,0 +1,186 @@
+package org.eco.vip.reliability.ser.service.config;
+
+import org.eco.vip.reliability.ser.domain.configuration.FaultPO;
+import org.eco.vip.reliability.ser.domain.configuration.pojo.MonitorTableVO;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+/**
+ * @Author: wyj
+ * @CreateTime: 2025-08-07
+ * @Belongpackage org.eco.vip.reliability.ser.service.config
+ */
+@Service
+public class calculateServiceImpl {
+
+    /**
+     * 生成故障监控表格数据(飞机/系统/部件的故障率统计)
+     * @param faultList 故障数据列表(实体类集合)
+     * @return 监控表格数据列表
+     */
+    public List<MonitorTableVO> generateFaultMonitorTable(List<FaultPO> faultList) {
+        // 1. 校验输入
+        if (faultList == null || faultList.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        // 2. 确定时间范围(n月、n-1月、n-2月)
+        Map<String, String> monthRange = getMonthRange();
+        String nMonth = monthRange.get("nMonth");
+        String n1Month = monthRange.get("n1Month");
+        String n2Month = monthRange.get("n2Month");
+
+        // 3. 按监控项目和月份统计故障数量
+        Map<String, Map<String, Long>> itemMonthCount =inCount(faultList, n2Month, n1Month, nMonth);
+
+        // 4. 获取各月飞行时间(实际应从团级数据库查询,此处为示例)
+        Map<String, Double> flightTimeMap = getMonthlyFlightTime(n2Month, n1Month, nMonth);
+
+        // 5. 计算表格数据
+        return buildMonitorTable(itemMonthCount, flightTimeMap, n2Month, n1Month, nMonth);
+    }
+
+    /**
+     * 获取n月、n-1月、n-2月的年月字符串(格式:yyyy-MM)
+     */
+    private Map<String, String> getMonthRange() {
+        LocalDate now = LocalDate.now();
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
+        return new HashMap<String, String>() {{
+            put("nMonth", now.format(formatter));
+            put("n1Month", now.minusMonths(1).format(formatter));
+            put("n2Month", now.minusMonths(2).format(formatter));
+        }};
+    }
+
+    /**
+     * 统计各监控项目在指定月份的故障数量
+     */
+    private Map<String, Map<String, Long>> inCount(List<FaultPO> faultList, String n2Month, String n1Month, String nMonth) {
+        // 初始化三个监控项目的月份计数
+        Map<String, Map<String, Long>> itemMonthCount = new HashMap<>();
+        List<String> monitorItems = Arrays.asList("飞机", "系统", "部件");
+        monitorItems.forEach(item -> {
+            itemMonthCount.put(item, new HashMap<String, Long>() {{
+                put(n2Month, 0L);
+                put(n1Month, 0L);
+                put(nMonth, 0L);
+            }});
+        });
+
+        // 遍历故障数据统计数量
+        for (FaultPO fault : faultList) {
+            // 转换故障日期为年月格式
+            String dataMonth = convertDateToMonth(fault.getStatisticsDate());
+            if (dataMonth == null) continue; // 跳过日期无效的数据
+
+            // 1. 统计"飞机"维度(所有故障均计入)
+            if (Arrays.asList(n2Month, n1Month, nMonth).contains(dataMonth)) {
+                itemMonthCount.get("飞机").put(dataMonth,
+                        itemMonthCount.get("飞机").get(dataMonth) + 1);
+            }
+
+            // 2. 统计"系统"维度(仅包含有系统信息的故障)
+            if (hasText(fault.getSystems()) && Arrays.asList(n2Month, n1Month, nMonth).contains(dataMonth)) {
+                itemMonthCount.get("系统").put(dataMonth,
+                        itemMonthCount.get("系统").get(dataMonth) + 1);
+            }
+
+            // 3. 统计"部件"维度(仅包含有机件信息的故障)
+            if ((hasText(fault.getMachineType()) || hasText(fault.getMachineName()))
+                    && Arrays.asList(n2Month, n1Month, nMonth).contains(dataMonth)) {
+                itemMonthCount.get("部件").put(dataMonth,
+                        itemMonthCount.get("部件").get(dataMonth) + 1);
+            }
+        }
+        return itemMonthCount;
+    }
+
+    /**
+     * 获取各月飞行时间(实际应对接团级数据库,此处为模拟)
+     */
+    private Map<String, Double> getMonthlyFlightTime(String... months) {
+        // 模拟从团级数据库查询每月飞行时间(单位:小时)
+        Map<String, Double> flightTimeMap = new HashMap<>();
+        for (String month : months) {
+            // 实际逻辑:调用接口查询该月的飞行时间总和
+            flightTimeMap.put(month, 1500.0); // 示例值
+        }
+        return flightTimeMap;
+    }
+
+    /**
+     * 构建监控表格数据(计算故障率、平均值、UCL等)
+     */
+    private List<MonitorTableVO> buildMonitorTable(
+            Map<String, Map<String, Long>> itemMonthCount,
+            Map<String, Double> flightTimeMap,
+            String n2Month, String n1Month, String nMonth) {
+
+        List<MonitorTableVO> result = new ArrayList<>();
+        int serialNumber = 1;
+
+        // 遍历三个监控项目
+        for (String item : Arrays.asList("飞机", "系统", "部件")) {
+            MonitorTableVO vo = new MonitorTableVO();
+            vo.setSerialNumber(serialNumber++);
+            vo.setMonitorItem(item);
+
+            // 获取该项目三个月的故障数量
+            Long n2Count = itemMonthCount.get(item).get(n2Month);
+            Long n1Count = itemMonthCount.get(item).get(n1Month);
+            Long nCount = itemMonthCount.get(item).get(nMonth);
+
+            // 获取三个月的飞行时间
+            double n2Flight = flightTimeMap.getOrDefault(n2Month, 0.0);
+            double n1Flight = flightTimeMap.getOrDefault(n1Month, 0.0);
+            double nFlight = flightTimeMap.getOrDefault(nMonth, 0.0);
+
+            // 计算各月故障率(故障数/飞行时间,避免除0)
+            vo.setN2MonthRate(calculateRate(n2Count, n2Flight));
+            vo.setN1MonthRate(calculateRate(n1Count, n1Flight));
+            vo.setNMonthRate(calculateRate(nCount, nFlight));
+
+            // 计算近三个月平均值
+            vo.setAverage(calculateAverage(vo.getN2MonthRate(), vo.getN1MonthRate(), vo.getNMonthRate()));
+            // 设置k值(实际应从配置获取,此处为示例)
+            vo.setK(2.0);
+            // 计算UCL警戒值(平均值 + k*标准差)
+            double std = calculateStd(vo.getN2MonthRate(), vo.getN1MonthRate(), vo.getNMonthRate());
+            vo.setUcl(vo.getAverage() + vo.getK() * std);
+            // 确定警告状态(当前月故障率 > UCL则警告)
+            vo.setWarningStatus(vo.getNMonthRate() > vo.getUcl() ? "警告" : "正常");
+            result.add(vo);
+        }
+        return result;
+    }
+
+    private double calculateRate(Long count, double flightTime) {
+        return flightTime == 0 ? 0 : count / flightTime;
+    }
+
+    private double calculateAverage(double... values) {
+        return Arrays.stream(values).average().orElse(0);
+    }
+
+    private double calculateStd(double a, double b, double c) {
+        double avg = calculateAverage(a, b, c);
+        double sumPow = Math.pow(a - avg, 2) + Math.pow(b - avg, 2) + Math.pow(c - avg, 2);
+        return Math.sqrt(sumPow / 3);
+    }
+
+    private String convertDateToMonth(Date date) {
+        if (date == null) return null;
+        LocalDate localDate = LocalDate.ofInstant(date.toInstant(), ZoneId.systemDefault());
+        return localDate.format(DateTimeFormatter.ofPattern("yyyy-MM"));
+    }
+
+    private boolean hasText(String str) {
+        return str != null && !str.trim().isEmpty();
+    }
+
+}

+ 71 - 27
eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/construct/ConstructImpl.java

@@ -2,8 +2,10 @@ package org.eco.vip.reliability.ser.service.construct;
 
 import cn.hutool.core.lang.tree.Tree;
 import cn.hutool.core.lang.tree.TreeNode;
+import cn.hutool.core.map.MapUtil;
 import com.mybatisflex.core.paginate.Page;
 import com.mybatisflex.core.query.QueryWrapper;
+import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import org.eco.vip.core.pojo.PageResult;
 import org.eco.vip.core.utils.*;
@@ -13,6 +15,7 @@ import org.eco.vip.reliability.ser.domain.construct.ConstructPO;
 import org.eco.vip.reliability.ser.domain.construct.pojo.ConstructBO;
 import org.eco.vip.reliability.ser.domain.construct.pojo.ConstructVO;
 import org.eco.vip.reliability.ser.mapper.ConstructMapper;
+import org.eco.vip.reliability.ser.service.config.IFaultService;
 import org.springframework.stereotype.Service;
 
 import java.util.*;
@@ -30,6 +33,8 @@ import static org.eco.vip.reliability.ser.domain.construct.table.ConstructPOTabl
 @Slf4j
 public class ConstructImpl extends BaseService<ConstructMapper, ConstructPO> implements IConstruct {
 
+    @Resource
+    private IFaultService iFaultService;
 
     private QueryWrapper buidQueryWapper(ConstructBO bo) {
         return buildBaseQueryWrapper().and(CONSTRUCT_PO.ID.eq(bo.getId()))
@@ -38,38 +43,77 @@ public class ConstructImpl extends BaseService<ConstructMapper, ConstructPO> imp
 
     }
 
-    /**
-     * 查询凡所有父节点信息
-     * @param id
-     * @return
-     */
-    @Override
-    public List<ConstructVO> selectOne(String id) {
-        ArrayList<ConstructVO> treeList = new ArrayList<>();
-        String parentId = id;
-        while (true){
-            ConstructVO constructVO = selectTreeNode(parentId);
-            if(ObjUtils.isEmpty(constructVO)){
-                break;
-            }
-            String parent = constructVO.getParentId();
-            if (parent == null) {
-                break;
+    private static ConstructVO findNodeInTreeList(List<ConstructVO> treeList, String id) {
+        if (CollUtils.isEmpty(treeList) || id == null) {
+            return null;
+        }
+        for (ConstructVO node : treeList) {
+            if (id.equals(node.getId().toString())) {
+                return node;
             }
-            ConstructVO treeNode = selectTreeNode(parent);
-            if(ObjUtils.isEmpty(treeNode)){
-                break;
+            if (ObjUtils.isNotEmpty(node.getChildren())) {
+                ConstructVO found = findNodeInTreeList(node.getChildren(), id);
+                if (found != null) {
+                    return found;
+                }
             }
-            treeList.add(treeNode);
-            parentId = parent;
         }
-        return treeList;
+        return null;
+    }
+    public static List<Map<String, Object>> findNodeAndParents(List<ConstructVO> tree, String targetId) {
+        List<Map<String, Object>> result = CollUtils.newArrayList();
+        if (CollUtils.isEmpty(tree) || targetId == null) {
+            return result;
+        }
+        ConstructVO targetNode = findNodeInTreeList(tree, targetId);
+        if (targetNode == null) {
+            return result;
+        }
+        collectParents(targetNode, result);
+        Collections.reverse(result);
+        return result;
     }
 
-    public ConstructVO selectTreeNode(String id){
-        QueryWrapper where = query().where(CONSTRUCT_PO.ID.eq(id));
-        ConstructVO oneAs = this.getOneAs(where, ConstructVO.class);
-        return oneAs;
+    private static void collectParents(ConstructVO node, List<Map<String, Object>> result) {
+        if (node == null) {
+            return;
+        }
+        Map<String, Object> nodeMap = MapUtil.newHashMap();
+        nodeMap.put("id", node.getId());
+        nodeMap.put("name", node.getConfigName());
+        nodeMap.put("type", node.getConfigType());
+        result.add(nodeMap);
+        collectParents(node.getParent(), result);
+    }
+    /**
+     * 查询选择节点信息,构建查询条件
+     * @param ids
+     * @return
+     */
+    @Override
+    public Map<String, List<String>> selectOne(List<String> ids) {
+        ConstructBO bo = new ConstructBO();
+        QueryWrapper wrapper = buidQueryWapper(bo);
+        List<ConstructVO> constructVOS = mapper.selectListWithRelationsByQueryAs(wrapper, ConstructVO.class);
+        Set<Map<String, Object>> uniqueResult = new LinkedHashSet<>();
+        ids.forEach(id -> {
+            List<Map<String, Object>> result = findNodeAndParents(constructVOS, id);
+            uniqueResult.addAll(result);
+        });
+        return uniqueResult.stream()
+                .collect(Collectors.groupingBy(
+                        node -> node.get("type").toString(),
+                        Collectors.mapping(
+                                node -> node.get("name").toString(),
+                                Collectors.collectingAndThen(
+                                        Collectors.toList(),
+                                        list -> {
+                                            Collections.sort(list); // 按字典序排序
+                                            return list;
+                                        }
+                                )
+                        )
+                ));
     }
 
     /**

+ 4 - 2
eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/construct/IConstruct.java

@@ -10,6 +10,8 @@ import org.eco.vip.reliability.ser.domain.construct.pojo.ConstructVO;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * wyj
@@ -86,8 +88,8 @@ public interface IConstruct extends IBaseService<ConstructPO> {
     /**
      * 查询部件详情信息
      *
-     * @param id
+     * @param ids
      * @return
      */
-    List<ConstructVO> selectOne(String id);
+    Map<String, List<String>> selectOne(List<String> ids);
 }

+ 110 - 0
eco-reliability/reliability-service/src/main/java/org/eco/vip/reliability/ser/service/construct/test.java

@@ -0,0 +1,110 @@
+package org.eco.vip.reliability.ser.service.construct;
+
+import cn.hutool.core.lang.tree.Tree;
+import cn.hutool.core.lang.tree.TreeNode;
+import cn.hutool.core.map.MapUtil;
+import org.eco.vip.core.utils.CollUtils;
+import org.eco.vip.core.utils.MapUtils;
+import org.eco.vip.core.utils.ObjUtils;
+import org.eco.vip.core.utils.TreeUtils;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: wyj
+ * @CreateTime: 2025-08-11
+ * @Belongpackage org.eco.vip.reliability.ser.service.construct
+ */
+public class test {
+
+
+    public static void main(String[] args) {
+        // 1. 构建树节点数据
+        List<TreeNode<String>> nodeList = CollUtils.newArrayList();
+        nodeList.add(new TreeNode<>("1", "0", "J20", null).setExtra(MapUtils.of("type", "model")));
+        nodeList.add(new TreeNode<>("2", "1", "系统1", null).setExtra(MapUtils.of("type", "sys")));
+        nodeList.add(new TreeNode<>("3", "1", "系统2", null).setExtra(MapUtils.of("type", "sys")));
+        nodeList.add(new TreeNode<>("4", "2", "子系统1", null).setExtra(MapUtils.of("type", "s_sys")));
+        nodeList.add(new TreeNode<>("5", "3", "子系统2", null).setExtra(MapUtils.of("type", "s_sys")));
+        nodeList.add(new TreeNode<>("6", "4", "部件", null).setExtra(MapUtils.of("type", "cop")));
+        nodeList.add(new TreeNode<>("7", "5", "部件2", null).setExtra(MapUtils.of("type", "cop")));
+        // 2. 构建树
+        List<Tree<String>> tree = TreeUtils.build(nodeList, "0");
+        // 3. 查找指定节点及其所有父节点(扁平结构)
+        List<String> ids = CollUtils.newArrayList("2", "7", "6");
+        // 保持插入顺序
+        Set<Map<String, Object>> uniqueResult = new LinkedHashSet<>();
+        ids.forEach(id -> {
+            List<Map<String, Object>> result = findNodeAndParents(tree, id);
+            uniqueResult.addAll(result);
+        });
+        // 4. 输出结果
+        uniqueResult.forEach(System.out::println);
+
+        // 4. 按 type 分组,并按 name 排序
+        Map<String, List<String>> groupedByType = uniqueResult.stream()
+                .collect(Collectors.groupingBy(
+                        node -> node.get("type").toString(),
+                        Collectors.mapping(
+                                node -> node.get("name").toString(),
+                                Collectors.collectingAndThen(
+                                        Collectors.toList(),
+                                        list -> {
+                                            Collections.sort(list); // 按字典序排序
+                                            return list;
+                                        }
+                                )
+                        )
+                ));
+
+        // 5. 输出分组结果
+        groupedByType.forEach((type, names) -> {
+            System.out.println(type + ": " + names);
+        });
+    }
+    public static List<Map<String, Object>> findNodeAndParents(List<Tree<String>> tree, String targetId) {
+        // 查找目标节点
+        Tree<String> targetNode = findNodeInTreeList(tree, targetId);
+        if (targetNode == null) {
+            return CollUtils.newArrayList();
+        }
+        // 收集所有父节点(包括自己)
+        List<Map<String, Object>> result = CollUtils.newArrayList();
+        collectParents(targetNode, result);
+        return result;
+    }
+
+    private static Tree<String> findNodeInTreeList(List<Tree<String>> treeList, String id) {
+        for (Tree<String> tree : treeList) {
+            if (tree.getId().equals(id)) {
+                return tree;
+            }
+            if(ObjUtils.isNotEmpty(tree.getChildren())){
+                Tree<String> found = findNodeInTreeList(tree.getChildren(), id);
+                if (found != null) {
+                    return found;
+                }
+            }
+        }
+        return null;
+    }
+
+    private static void collectParents(Tree<String> node, List<Map<String, Object>> result) {
+        // 如果当前节点是 id = '0',则跳过(不添加到结果)
+        if ("0".equals(node.getId())) {
+            return;
+        }
+        // 添加当前节点
+        Map<String, Object> nodeMap = MapUtil.newHashMap();
+        nodeMap.put("id", node.getId());
+        nodeMap.put("name", node.getName());
+        nodeMap.put("type", node.get("type"));
+        result.add(nodeMap);
+
+        // 递归添加父节点
+        if (node.getParent() != null) {
+            collectParents(node.getParent(), result);
+        }
+    }
+}

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff