liyong
6 天以前 f5ee8e7afb178179c1d1d078cf42fe33dc7607f9
src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
@@ -291,8 +291,15 @@
                                            ProductionOrderBom orderBom,
                                            List<ProductionBomStructure> structureList,
                                            Long rootProductModelId) {
        // 重新查询BOM结构,按子节点优先排序
        List<ProductionBomStructure> routingStructureList = this.list(
                Wrappers.<ProductionBomStructure>lambdaQuery()
                        .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId())
                        .orderByDesc(ProductionBomStructure::getParentId)
                        .orderByAsc(ProductionBomStructure::getId));
        ProductionOrderRouting orderRouting = getOrCreateOrderRoutingSnapshot(productionOrderId, productionOrder, orderBom, rootProductModelId);
        List<ProductionOrderRoutingOperation> desiredOperationList = buildDesiredRoutingOperationList(structureList, rootProductModelId);
        List<ProductionOrderRoutingOperation> desiredOperationList = buildDesiredRoutingOperationList(routingStructureList, rootProductModelId);
        List<ProductionOrderRoutingOperation> existingOperationList = productionOrderRoutingOperationMapper.selectList(
                Wrappers.<ProductionOrderRoutingOperation>lambdaQuery()
                        .eq(ProductionOrderRoutingOperation::getOrderRoutingId, orderRouting.getId())
@@ -310,7 +317,7 @@
            if (matchedOperation == null) {
                matchedOperation = insertRoutingOperationSnapshot(orderRouting.getId(), productionOrderId, desiredOperation);
            } else {
                updateRoutingOperationSnapshotIfNecessary(desiredOperation, orderRouting.getId(), productionOrderId, matchedOperation);
                updateRoutingOperationSnapshotIfNecessary(matchedOperation, orderRouting.getId(), productionOrderId, desiredOperation);
            }
            finalOperationList.add(matchedOperation);
        }
@@ -381,14 +388,14 @@
        Map<Long, ProductionBomStructure> structureById = structureList.stream()
                .filter(item -> item != null && item.getId() != null)
                .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left));
        // 构建父-子映射关系
        Map<Long, List<ProductionBomStructure>> treeMap = buildParentChildMap(structureList);
        // 使用后序遍历构建操作列表(先子后父,确保工艺路线顺序正确)
        Map<String, ProductionBomStructure> uniqueOperationMap = new LinkedHashMap<>();
        for (ProductionBomStructure bomStructure : structureList) {
            if (bomStructure == null || bomStructure.getTechnologyOperationId() == null) {
                continue;
            }
            Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(bomStructure, structureById), rootProductModelId);
            uniqueOperationMap.putIfAbsent(buildBomOperationDedupKey(bomStructure, outputProductModelId), bomStructure);
        }
        buildOperationListPostOrder(null, treeMap, uniqueOperationMap, structureById, rootProductModelId);
        List<ProductionOrderRoutingOperation> desiredOperationList = new ArrayList<>();
        int dragSort = 1;
        for (ProductionBomStructure bomStructure : uniqueOperationMap.values()) {
@@ -405,6 +412,52 @@
            desiredOperationList.add(routingOperation);
        }
        return desiredOperationList;
    }
    private Map<Long, List<ProductionBomStructure>> buildParentChildMap(List<ProductionBomStructure> structureList) {
        Map<Long, List<ProductionBomStructure>> treeMap = new LinkedHashMap<>();
        Map<Long, Integer> childCountMap = new HashMap<>();
        // 第一遍:统计每个节点的子节点数量,同时构建初始映射
        for (ProductionBomStructure structure : structureList) {
            if (structure == null) continue;
            Long parentId = structure.getParentId();
            childCountMap.merge(parentId, 1, Integer::sum);  // 统计每个父节点有多少个子节点
            treeMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(structure);
        }
        // 第二遍:对每个父节点下的子节点按子节点数量倒序排序(有子节点的优先)
        for (Map.Entry<Long, List<ProductionBomStructure>> entry : treeMap.entrySet()) {
            List<ProductionBomStructure> children = entry.getValue();
            children.sort((a, b) -> {
                int countA = childCountMap.getOrDefault(a.getId(), 0);
                int countB = childCountMap.getOrDefault(b.getId(), 0);
                return Integer.compare(countB, countA);  // 子节点多的排前面
            });
        }
        return treeMap;
    }
    private void buildOperationListPostOrder(Long parentId,
                                             Map<Long, List<ProductionBomStructure>> treeMap,
                                             Map<String, ProductionBomStructure> uniqueOperationMap,
                                             Map<Long, ProductionBomStructure> structureById,
                                             Long rootProductModelId) {
        List<ProductionBomStructure> children = treeMap.get(parentId);
        if (children == null || children.isEmpty()) {
            return;
        }
        for (ProductionBomStructure child : children) {
            // 先递归处理子节点
            buildOperationListPostOrder(child.getId(), treeMap, uniqueOperationMap, structureById, rootProductModelId);
            // 再处理当前节点
            if (child.getTechnologyOperationId() != null) {
                Long outputProductModelId = resolveOutputProductModelId(resolveOperationOutputNode(child, structureById), rootProductModelId);
                uniqueOperationMap.putIfAbsent(buildBomOperationDedupKey(child, outputProductModelId), child);
            }
        }
    }
    private Map<String, Deque<ProductionOrderRoutingOperation>> buildExistingRoutingOperationBucketMap(List<ProductionOrderRoutingOperation> existingOperationList) {
@@ -482,6 +535,12 @@
        if (!Objects.equals(currentOperation.getIsProduction(), desiredOperation.getIsProduction())) {
            update.setIsProduction(desiredOperation.getIsProduction());
            currentOperation.setIsProduction(desiredOperation.getIsProduction());
            changed = true;
        }
        // 更新 dragSort 字段,确保工艺路线顺序正确
        if (!Objects.equals(currentOperation.getDragSort(), desiredOperation.getDragSort())) {
            update.setDragSort(desiredOperation.getDragSort());
            currentOperation.setDragSort(desiredOperation.getDragSort());
            changed = true;
        }
        if (!Objects.equals(currentOperation.getType(), desiredOperation.getType())) {
@@ -744,8 +803,8 @@
            return;
        }
        for (ProductionBomStructureDto node : source) {
            flattenTree(node.getChildren(), result);  // 先递归添加子节点
            result.add(node);
            flattenTree(node.getChildren(), result);
        }
    }