From 310da8ec2f87930444b62212ba513aab9e2fa878 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 23 三月 2026 08:58:36 +0800
Subject: [PATCH] yys 1.修改产品基础模块

---
 src/main/java/com/ruoyi/common/utils/OrderUtils.java |  311 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 307 insertions(+), 4 deletions(-)

diff --git a/src/main/java/com/ruoyi/common/utils/OrderUtils.java b/src/main/java/com/ruoyi/common/utils/OrderUtils.java
index 9520b75..22915df 100644
--- a/src/main/java/com/ruoyi/common/utils/OrderUtils.java
+++ b/src/main/java/com/ruoyi/common/utils/OrderUtils.java
@@ -2,6 +2,10 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.ruoyi.basic.dto.ProductModelExcelDto;
+import com.ruoyi.basic.dto.ProductModelExcelItemDto;
+import com.ruoyi.common.utils.uuid.UUID;
 import org.apache.poi.ss.formula.functions.T;
 import org.springframework.stereotype.Component;
 
@@ -10,9 +14,8 @@
 import java.time.LocalTime;
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @author :yys
@@ -51,6 +54,306 @@
         // 鎵ц鏌ヨ
         Long aLong = mapper.selectCount(queryWrapper);
         // 鎷兼帴璁㈠崟缂栧彿 preFix + 鏃堕棿锛坹yyyMMdd锛� + 璁㈠崟鏁伴噺(001)
-        return preFix + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE).replaceAll("-", "") + String.format("%03d", (aLong + 1));
+        return preFix + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE).replaceAll("-", "") + String.format("%03d", (aLong + 1)) + "-" + new Date().getTime();
     }
+
+    /**
+     * 灏嗗钩闈㈠垪琛ㄨ浆鎹负鏍戝舰缁撴瀯锛堝惈瑙勬牸鍨嬪彿鎷嗗垎鍔熻兘锛�
+     * @param flatList 瀵煎叆鐨勫钩闈㈡暟鎹垪琛�
+     * @return 鏍戝舰缁撴瀯鐨勬牴鑺傜偣鍒楄〃
+     */
+    public static List<ProductModelExcelDto> buildTree(List<ProductModelExcelDto> flatList) {
+        // 1. 鍙傛暟鏍¢獙
+        if (CollectionUtils.isEmpty(flatList)) {
+            return new ArrayList<>();
+        }
+
+        // 2. 棰勫鐞嗭細杩囨护鏃犳晥鏁版嵁 + 瑙勬牸鍨嬪彿鎷嗗垎 + 鍒濆鍖栧瓙鑺傜偣鍒楄〃
+        List<ProductModelExcelDto> validList = preprocessData(flatList);
+        if (CollectionUtils.isEmpty(validList)) {
+            return new ArrayList<>();
+        }
+
+        // 3. 鎸夊眰绾у垎缁勶紝渚夸簬閫愬眰澶勭悊
+        Map<Integer, List<ProductModelExcelDto>> levelGroupMap = groupByLevel(validList);
+
+        // 4. 鏋勫缓鑺傜偣鏄犲皠锛堝簭鍙� -> 鑺傜偣锛夛紝鎻愰珮鏌ヨ鏁堢巼
+        Map<String, ProductModelExcelDto> nodeMap = buildNodeMap(validList);
+
+        // 5. 閫愬眰鏋勫缓鐖跺瓙鍏崇郴
+        buildParentChildRelation(levelGroupMap, nodeMap);
+
+        // 6. 鑾峰彇鏍硅妭鐐癸紙灞傜骇1锛夊苟鎺掑簭
+        List<ProductModelExcelDto> rootNodes = getRootNodes(levelGroupMap);
+        sortTreeNodes(rootNodes);
+
+        return rootNodes;
+    }
+
+    /**
+     * 鏁版嵁棰勫鐞嗭細
+     * 1. 杩囨护鏃犳晥鏁版嵁
+     * 2. 瑙勬牸鍨嬪彿鎷嗗垎骞跺~鍏呭埌items闆嗗悎
+     * 3. 鍒濆鍖栧瓙鑺傜偣鍒楄〃
+     */
+    private static List<ProductModelExcelDto> preprocessData(List<ProductModelExcelDto> flatList) {
+        return flatList.stream()
+                // 杩囨护鏍稿績瀛楁鏃犳晥鐨勮妭鐐�
+                .filter(node -> isValidNode(node))
+                // 澶勭悊瑙勬牸鍨嬪彿鎷嗗垎鍜宨tems濉厖
+                .peek(node -> {
+                    // 鎷嗗垎瑙勬牸鍨嬪彿骞跺~鍏呭埌items
+                    splitModelAndFillItems(node);
+                    // 鍒濆鍖栧瓙鑺傜偣鍒楄〃锛堥伩鍏嶇┖鎸囬拡锛�
+                    if (node.getChildren() == null) {
+                        node.setChildren(new ArrayList<>());
+                    }
+                })
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 楠岃瘉鑺傜偣鏄惁鏈夋晥锛堟牳蹇冨瓧娈垫牎楠岋級
+     */
+    private static boolean isValidNode(ProductModelExcelDto node) {
+        if (node == null) {
+            return false;
+        }
+        // 搴忓彿蹇呴』鏈夋晥锛堝熀纭�鏍¢獙锛�
+        if (!isValidSequence(node.getNumber())) {
+            return false;
+        }
+        // 浜у搧鍚嶇О闈炵┖锛堜笟鍔℃牎楠岋紝鍙牴鎹疄闄呴渶姹傝皟鏁达級
+        return StringUtils.isNotBlank(node.getProductName());
+    }
+
+    /**
+     * 瑙勬牸鍨嬪彿鎷嗗垎骞跺~鍏呭埌items闆嗗悎
+     * @param node 寰呭鐞嗙殑鑺傜偣
+     */
+    private static void splitModelAndFillItems(ProductModelExcelDto node) {
+        // 1. 鑾峰彇鍘熷瑙勬牸鍨嬪彿
+        String originalModel = node.getModel();
+        List<ProductModelExcelItemDto> items = new ArrayList<>();
+
+        if (StringUtils.isNotBlank(originalModel)) {
+            // 2. 鎸�"+"鎷嗗垎瑙勬牸鍨嬪彿锛堝鏋滄湁澶氫釜锛夛紝澶勭悊姣忎釜鐗囨
+            List<String> splitModels = Arrays.stream(originalModel.split("\\+"))
+                    .map(String::trim)
+                    .filter(StringUtils::isNotBlank)
+                    .distinct()
+                    .collect(Collectors.toList());
+
+            // 3. 涓烘瘡涓鏍煎垱寤篒tem锛堝嵆浣垮彧鏈変竴涓紝涔熺敓鎴愪竴涓狪tem锛�
+            items = splitModels.stream()
+                    .map(model -> createExcelItem(node, model))
+                    .collect(Collectors.toList());
+        }
+
+        // 4. 濉厖鍒拌妭鐐圭殑items闆嗗悎锛堣鐩栧師鏈夋暟鎹級
+        node.setItems(items);
+    }
+
+    /**
+     * 鍒涘缓ProductModelExcelItemDto瀵硅薄锛堢户鎵垮師鑺傜偣鐨勫叕鍏卞睘鎬э級
+     * @param node 鍘熻妭鐐�
+     * @param model 鎷嗗垎鍚庣殑瑙勬牸鍨嬪彿
+     * @return 鏋勫缓濂界殑Item瀵硅薄
+     */
+    private static ProductModelExcelItemDto createExcelItem(ProductModelExcelDto node, String model) {
+        ProductModelExcelItemDto item = new ProductModelExcelItemDto();
+        // 1. 鎷嗗垎鍚庣殑瑙勬牸鍨嬪彿
+        item.setModel(model);
+        // 2. 缁ф壙鍘熻妭鐐圭殑鍗曚綅锛堢┖鍊煎鐞嗭級
+        item.setUnit(StringUtils.defaultIfBlank(node.getUnit(), ""));
+        // 3. 缁ф壙鍘熻妭鐐圭殑浜у搧绫诲瀷锛堢┖鍊煎鐞嗭紝榛樿0琛ㄧず鏈煡锛�
+        item.setProductType(Optional.ofNullable(node.getProductType()).orElse(0));
+        // 4. 缁ф壙鍘熻妭鐐圭殑鍥剧焊缂栧彿锛堢┖鍊煎鐞嗭級
+        item.setDrawingNumber(StringUtils.defaultIfBlank(node.getDrawingNumber(), ""));
+        return item;
+    }
+
+    /**
+     * 楠岃瘉搴忓彿鏍煎紡鏄惁鏈夋晥锛堟敮鎸�1銆�1.1銆�1.1.1绛夋牸寮忥級
+     */
+    private static boolean isValidSequence(String sequence) {
+        if (StringUtils.isBlank(sequence)) {
+            return false;
+        }
+        // 姝e垯琛ㄨ揪寮忥細鍖归厤鏁板瓧寮�澶达紝鍚庣画鍙窡.鍜屾暟瀛�
+        return sequence.trim().matches("^\\d+(\\.\\d+)*$");
+    }
+
+    /**
+     * 鎸夎妭鐐瑰眰绾у垎缁�
+     */
+    private static Map<Integer, List<ProductModelExcelDto>> groupByLevel(List<ProductModelExcelDto> validList) {
+        return validList.stream()
+                .collect(Collectors.groupingBy(
+                        node -> getNodeLevel(node.getNumber()),  // 璁$畻灞傜骇
+                        TreeMap::new,  // 鎸夊眰绾у崌搴忔帓搴�
+                        Collectors.toList()
+                ));
+    }
+
+    /**
+     * 璁$畻鑺傜偣灞傜骇锛堝簭鍙蜂腑.鐨勬暟閲� + 1锛�
+     * 渚嬶細1 -> 1绾э紝1.1 -> 2绾э紝1.1.1 -> 3绾�
+     */
+    private static int getNodeLevel(String sequence) {
+        if (StringUtils.isBlank(sequence)) {
+            return 0;
+        }
+        String trimmedSeq = sequence.trim();
+        return trimmedSeq.split("\\.").length;
+    }
+
+    /**
+     * 鏋勫缓鑺傜偣鏄犲皠琛紙搴忓彿 -> 鑺傜偣锛�
+     */
+    private static Map<String, ProductModelExcelDto> buildNodeMap(List<ProductModelExcelDto> validList) {
+        return validList.stream()
+                .collect(Collectors.toMap(
+                        node -> node.getNumber().trim(),  // 閿細搴忓彿锛堝幓绌烘牸锛�
+                        node -> node,                     // 鍊硷細鑺傜偣瀵硅薄
+                        (oldVal, newVal) -> oldVal        // 澶勭悊閲嶅搴忓彿锛氫繚鐣欑涓�涓�
+                ));
+    }
+
+    /**
+     * 鏋勫缓鐖跺瓙鑺傜偣鍏崇郴
+     */
+    private static void buildParentChildRelation(Map<Integer, List<ProductModelExcelDto>> levelGroupMap,
+                                                 Map<String, ProductModelExcelDto> nodeMap) {
+        // 浠庡眰绾�2寮�濮嬪鐞嗭紙灞傜骇1鏄牴鑺傜偣锛屾棤鐖惰妭鐐癸級
+        for (Map.Entry<Integer, List<ProductModelExcelDto>> entry : levelGroupMap.entrySet()) {
+            int currentLevel = entry.getKey();
+            if (currentLevel <= 1) {
+                continue;  // 璺宠繃鏍硅妭鐐瑰眰绾�
+            }
+
+            List<ProductModelExcelDto> currentLevelNodes = entry.getValue();
+            for (ProductModelExcelDto currentNode : currentLevelNodes) {
+                // 璁$畻鐖惰妭鐐瑰簭鍙�
+                String parentSequence = getParentSequence(currentNode.getNumber());
+                if (StringUtils.isBlank(parentSequence)) {
+                    continue;
+                }
+
+                // 鏌ユ壘鐖惰妭鐐�
+                ProductModelExcelDto parentNode = nodeMap.get(parentSequence);
+                if (parentNode != null && parentNode.getChildren() != null) {
+                    // 娣诲姞鍒扮埗鑺傜偣鐨勫瓙鑺傜偣鍒楄〃
+                    parentNode.getChildren().add(currentNode);
+                }
+            }
+        }
+    }
+
+    /**
+     * 鏍规嵁褰撳墠鑺傜偣搴忓彿鑾峰彇鐖惰妭鐐瑰簭鍙�
+     * 渚嬶細1.1.2 -> 1.1锛�1.2 -> 1锛�1 -> null
+     */
+    private static String getParentSequence(String currentSequence) {
+        if (StringUtils.isBlank(currentSequence)) {
+            return null;
+        }
+
+        String trimmedSeq = currentSequence.trim();
+        String[] seqParts = trimmedSeq.split("\\.");
+        if (seqParts.length <= 1) {
+            return null;  // 鏍硅妭鐐规棤鐖惰妭鐐�
+        }
+
+        // 鍘绘帀鏈�鍚庝竴閮ㄥ垎锛屾嫾鎺ョ埗鑺傜偣搴忓彿
+        String[] parentParts = Arrays.copyOfRange(seqParts, 0, seqParts.length - 1);
+        return String.join(".", parentParts);
+    }
+
+    /**
+     * 鑾峰彇鏍硅妭鐐瑰垪琛紙灞傜骇1鐨勮妭鐐癸級
+     */
+    private static List<ProductModelExcelDto> getRootNodes(Map<Integer, List<ProductModelExcelDto>> levelGroupMap) {
+        return levelGroupMap.getOrDefault(1, new ArrayList<>());
+    }
+
+    /**
+     * 閫掑綊鎺掑簭鎵�鏈夎妭鐐癸紙鎸夊簭鍙锋暟瀛楅『搴忥級
+     */
+    private static void sortTreeNodes(List<ProductModelExcelDto> nodeList) {
+        if (CollectionUtils.isEmpty(nodeList)) {
+            return;
+        }
+
+        // 鎺掑簭褰撳墠灞傜骇鑺傜偣
+        nodeList.sort(Comparator.comparing(
+                ProductModelExcelDto::getNumber,
+                new SequenceComparator()  // 鑷畾涔夊簭鍙锋瘮杈冨櫒
+        ));
+
+        // 閫掑綊鎺掑簭瀛愯妭鐐�
+        for (ProductModelExcelDto node : nodeList) {
+            sortTreeNodes(node.getChildren());
+        }
+    }
+
+    /**
+     * 搴忓彿姣旇緝鍣細鎸夋暟瀛楅『搴忔帓搴忥紙鏀寔1.10鍦�1.2涔嬪悗锛�
+     */
+    private static class SequenceComparator implements Comparator<String> {
+        @Override
+        public int compare(String seq1, String seq2) {
+            if (StringUtils.isBlank(seq1) && StringUtils.isBlank(seq2)) {
+                return 0;
+            }
+            if (StringUtils.isBlank(seq1)) {
+                return -1;
+            }
+            if (StringUtils.isBlank(seq2)) {
+                return 1;
+            }
+
+            // 鍒嗗壊搴忓彿涓烘暟瀛楁暟缁�
+            String[] parts1 = seq1.trim().split("\\.");
+            String[] parts2 = seq2.trim().split("\\.");
+
+            // 閫愭姣旇緝鏁板瓧
+            int minLength = Math.min(parts1.length, parts2.length);
+            for (int i = 0; i < minLength; i++) {
+                int num1 = parseSequencePart(parts1[i]);
+                int num2 = parseSequencePart(parts2[i]);
+                if (num1 != num2) {
+                    return num1 - num2;
+                }
+            }
+
+            // 闀垮害涓嶅悓鏃讹紝鐭殑鍦ㄥ墠锛堝1.1鍦�1.1.1涔嬪墠锛�
+            return parts1.length - parts2.length;
+        }
+
+        /**
+         * 瑙f瀽搴忓彿鐗囨涓烘暟瀛楋紙澶勭悊寮傚父鎯呭喌锛�
+         */
+        private int parseSequencePart(String part) {
+            try {
+                return Integer.parseInt(part.trim());
+            } catch (NumberFormatException e) {
+                return 0;  // 寮傚父鎯呭喌鎸�0澶勭悊
+            }
+        }
+    }
+
+
+    /**
+     * 浜у搧绫诲瀷鏄犲皠锛�1=鐗╂枡锛�2=浜у搧锛�0=鏈煡锛�
+     */
+    private static String mapProductType(Integer productType) {
+        return Optional.ofNullable(productType)
+                .map(type -> type == 1 ? "鐗╂枡" : (type == 2 ? "浜у搧" : "鏈煡"))
+                .orElse("鏈煡");
+    }
+
+
+
+
 }

--
Gitblit v1.9.3