hongjli
2025-05-26 7a4a03e2c1455ba7a7c6fa60702e350faf6e25bb
管路&气柜产能负载按日统计查不到数据时不返回空
已修改3个文件
442 ■■■■■ 文件已修改
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsGasPipingRouteStatMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java 418 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/resources/mapper/core/ApsGasPipingRouteStatMapper.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
aps-modules/aps-core/src/main/java/com/aps/core/mapper/ApsGasPipingRouteStatMapper.java
@@ -130,4 +130,18 @@
     * @return 基础统计数据列表
     */
    public List<Map<String, Object>> selectBaseStatData(Map<String, Object> params);
    /**
     * 查询所有去重的工序名称
     *
     * @return 所有去重的工序名称列表
     */
    public List<String> selectDistinctProcessNames();
    /**
     * 查询所有去重的车间
     *
     * @return 所有去重的车间列表
     */
    public List<String> selectDistinctWorkshops();
}
aps-modules/aps-core/src/main/java/com/aps/core/service/impl/ApsGasPipingRouteStatServiceImpl.java
@@ -1540,160 +1540,159 @@
                plantTable.add(rowEntry);
            }
            
            // 更新结果但不直接返回,继续执行后续注意点4的处理
            result.put("plantTable", plantTable);
            result.put("timePoints", timePoints);
            result.put("rowGroupBy", rowGroupBy);
        } else {
            // 在Service层完成聚合
            // 使用组合key来实现多维度分组(动态rowGroupBy字段 + 可选的工厂/专业/车间)
            Map<String, Map<String, Object>> groupInfoMap = new HashMap<>();
            Map<String, Map<String, BigDecimal>> groupTimeDataMap = new HashMap<>();
            // 存储每个groupKey对应的processName集合
            Map<String, Set<String>> groupProcessNamesMap = new HashMap<>();
            
            return result;
        }
        // 在Service层完成聚合
        // 使用组合key来实现多维度分组(动态rowGroupBy字段 + 可选的工厂/专业/车间)
        Map<String, Map<String, Object>> groupInfoMap = new HashMap<>();
        Map<String, Map<String, BigDecimal>> groupTimeDataMap = new HashMap<>();
        // 存储每个groupKey对应的processName集合
        Map<String, Set<String>> groupProcessNamesMap = new HashMap<>();
        // 遍历原始数据,按多维度分组进行聚合
        for (Map<String, Object> data : rawData) {
            // 获取行分组字段值
            String rowGroupValue = getStringValue(data, rowGroupBy);
            if (rowGroupValue == null || rowGroupValue.trim().isEmpty()) {
                log.warn("跳过处理:{} 字段值为空", rowGroupBy);
                continue;
            }
            // 获取工序名称(用于日志和后续处理)
            String processName = getStringValue(data, "processName");
            // 处理开工日期
            Date processPlanStartDay = (Date) data.get("processPlanStartDay");
            if (processPlanStartDay == null) {
                log.warn("跳过处理:计划开工日为null, {}={}", rowGroupBy, rowGroupValue);
                continue;
            }
            // 构建分组键 - 基于row分组字段和可选的其他维度
            String plant = getStringValue(data, "plant");
            String major = getStringValue(data, "major");
            String workshop = getStringValue(data, "workshop");
            StringBuilder groupKeyBuilder = new StringBuilder(rowGroupValue);
            // 根据用户选择的分组维度添加到分组键
            if (groupByPlant && plant != null) {
                groupKeyBuilder.append("_PLANT_").append(plant);
            }
            if (groupByMajor && major != null) {
                groupKeyBuilder.append("_MAJOR_").append(major);
            }
            if (groupByWorkshop && workshop != null) {
                groupKeyBuilder.append("_WORKSHOP_").append(workshop);
            }
            String groupKey = groupKeyBuilder.toString();
            // 记录分组的基本信息(只记录一次)
            if (!groupInfoMap.containsKey(groupKey)) {
                Map<String, Object> groupInfo = new HashMap<>();
                groupInfo.put(rowGroupBy, rowGroupValue);
                groupInfo.put("plant", plant);
                groupInfo.put("major", major);
                groupInfo.put("workshop", workshop);
                groupInfo.put("processName", processName);
                groupInfoMap.put(groupKey, groupInfo);
            }
            // 收集processName
            if (processName != null && !processName.trim().isEmpty()) {
                if (!groupProcessNamesMap.containsKey(groupKey)) {
                    groupProcessNamesMap.put(groupKey, new HashSet<>());
            // 遍历原始数据,按多维度分组进行聚合
            for (Map<String, Object> data : rawData) {
                // 获取行分组字段值
                String rowGroupValue = getStringValue(data, rowGroupBy);
                if (rowGroupValue == null || rowGroupValue.trim().isEmpty()) {
                    log.warn("跳过处理:{} 字段值为空", rowGroupBy);
                    continue;
                }
                groupProcessNamesMap.get(groupKey).add(processName);
            }
            // 计算时间点Key
            String timeKey;
            LocalDate planStartLocalDate = processPlanStartDay.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            if ("day".equalsIgnoreCase(timeGranularity)) {
                // 日粒度: 2025-05-25
                timeKey = planStartLocalDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
            } else {
                // 月粒度: 2025-05
                timeKey = planStartLocalDate.getYear() + "-" + String.format("%02d", planStartLocalDate.getMonthValue());
            }
            // 获取该分组的时间点映射,如果不存在则创建
            if (!groupTimeDataMap.containsKey(groupKey)) {
                groupTimeDataMap.put(groupKey, new HashMap<>());
            }
            Map<String, BigDecimal> timeMap = groupTimeDataMap.get(groupKey);
            // 累加该分组在该时间点的工时数据
            BigDecimal processTotalTime = getBigDecimalValue(data, "processTotalTime");
            if (processTotalTime != null) {
                BigDecimal currentTotal = timeMap.getOrDefault(timeKey, BigDecimal.ZERO);
                timeMap.put(timeKey, currentTotal.add(processTotalTime));
            }
        }
        // 构建最终返回的数据结构
        for (String groupKey : groupInfoMap.keySet()) {
            Map<String, Object> rowEntry = new HashMap<>();
            Map<String, Object> rowDetail = new HashMap<>();
            // 获取该分组的基本信息
            Map<String, Object> groupInfo = groupInfoMap.get(groupKey);
            String rowGroupValue = (String) groupInfo.get(rowGroupBy);
            // 添加分组基本信息
            if (groupByPlant) {
                rowDetail.put("plant", groupInfo.get("plant"));
            }
            if (groupByMajor) {
                rowDetail.put("major", groupInfo.get("major"));
            }
            if (groupByWorkshop) {
                rowDetail.put("workshop", groupInfo.get("workshop"));
            }
            // 处理processName - 如果rowGroupBy为workshop,则将所有processName用分号连接
            if ("workshop".equals(rowGroupBy)) {
                Set<String> processNames = groupProcessNamesMap.getOrDefault(groupKey, new HashSet<>());
                if (!processNames.isEmpty()) {
                    String joinedProcessNames = String.join(";", processNames);
                    rowDetail.put("processName", joinedProcessNames);
                // 获取工序名称(用于日志和后续处理)
                String processName = getStringValue(data, "processName");
                // 处理开工日期
                Date processPlanStartDay = (Date) data.get("processPlanStartDay");
                if (processPlanStartDay == null) {
                    log.warn("跳过处理:计划开工日为null, {}={}", rowGroupBy, rowGroupValue);
                    continue;
                }
                // 构建分组键 - 基于row分组字段和可选的其他维度
                String plant = getStringValue(data, "plant");
                String major = getStringValue(data, "major");
                String workshop = getStringValue(data, "workshop");
                StringBuilder groupKeyBuilder = new StringBuilder(rowGroupValue);
                // 根据用户选择的分组维度添加到分组键
                if (groupByPlant && plant != null) {
                    groupKeyBuilder.append("_PLANT_").append(plant);
                }
                if (groupByMajor && major != null) {
                    groupKeyBuilder.append("_MAJOR_").append(major);
                }
                if (groupByWorkshop && workshop != null) {
                    groupKeyBuilder.append("_WORKSHOP_").append(workshop);
                }
                String groupKey = groupKeyBuilder.toString();
                // 记录分组的基本信息(只记录一次)
                if (!groupInfoMap.containsKey(groupKey)) {
                    Map<String, Object> groupInfo = new HashMap<>();
                    groupInfo.put(rowGroupBy, rowGroupValue);
                    groupInfo.put("plant", plant);
                    groupInfo.put("major", major);
                    groupInfo.put("workshop", workshop);
                    groupInfo.put("processName", processName);
                    groupInfoMap.put(groupKey, groupInfo);
                }
                // 收集processName
                if (processName != null && !processName.trim().isEmpty()) {
                    if (!groupProcessNamesMap.containsKey(groupKey)) {
                        groupProcessNamesMap.put(groupKey, new HashSet<>());
                    }
                    groupProcessNamesMap.get(groupKey).add(processName);
                }
                // 计算时间点Key
                String timeKey;
                LocalDate planStartLocalDate = processPlanStartDay.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                if ("day".equalsIgnoreCase(timeGranularity)) {
                    // 日粒度: 2025-05-25
                    timeKey = planStartLocalDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
                } else {
                    // 月粒度: 2025-05
                    timeKey = planStartLocalDate.getYear() + "-" + String.format("%02d", planStartLocalDate.getMonthValue());
                }
                // 获取该分组的时间点映射,如果不存在则创建
                if (!groupTimeDataMap.containsKey(groupKey)) {
                    groupTimeDataMap.put(groupKey, new HashMap<>());
                }
                Map<String, BigDecimal> timeMap = groupTimeDataMap.get(groupKey);
                // 累加该分组在该时间点的工时数据
                BigDecimal processTotalTime = getBigDecimalValue(data, "processTotalTime");
                if (processTotalTime != null) {
                    BigDecimal currentTotal = timeMap.getOrDefault(timeKey, BigDecimal.ZERO);
                    timeMap.put(timeKey, currentTotal.add(processTotalTime));
                }
            }
            // 构建最终返回的数据结构
            for (String groupKey : groupInfoMap.keySet()) {
                Map<String, Object> rowEntry = new HashMap<>();
                Map<String, Object> rowDetail = new HashMap<>();
                // 获取该分组的基本信息
                Map<String, Object> groupInfo = groupInfoMap.get(groupKey);
                String rowGroupValue = (String) groupInfo.get(rowGroupBy);
                // 添加分组基本信息
                if (groupByPlant) {
                    rowDetail.put("plant", groupInfo.get("plant"));
                }
                if (groupByMajor) {
                    rowDetail.put("major", groupInfo.get("major"));
                }
                if (groupByWorkshop) {
                    rowDetail.put("workshop", groupInfo.get("workshop"));
                }
                // 处理processName - 如果rowGroupBy为workshop,则将所有processName用分号连接
                if ("workshop".equals(rowGroupBy)) {
                    Set<String> processNames = groupProcessNamesMap.getOrDefault(groupKey, new HashSet<>());
                    if (!processNames.isEmpty()) {
                        String joinedProcessNames = String.join(";", processNames);
                        rowDetail.put("processName", joinedProcessNames);
                    } else {
                        rowDetail.put("processName", groupInfo.get("processName"));
                    }
                } else if (!"processName".equals(rowGroupBy)) {
                    // 保留工序名称信息,以便前端展示
                    rowDetail.put("processName", groupInfo.get("processName"));
                }
            } else if (!"processName".equals(rowGroupBy)) {
                // 保留工序名称信息,以便前端展示
                rowDetail.put("processName", groupInfo.get("processName"));
                // 添加时间数据
                List<Map<String, Object>> timeDataList = new ArrayList<>();
                Map<String, BigDecimal> timeMap = groupTimeDataMap.getOrDefault(groupKey, new HashMap<>());
                for (String timePoint : timePoints) {
                    Map<String, Object> pointData = new HashMap<>();
                    pointData.put("planDay", timePoint);
                    // 获取该时间点的需求工时,如果不存在则设为0
                    BigDecimal requireTimes = timeMap.getOrDefault(timePoint, BigDecimal.ZERO);
                    pointData.put("requireTimes", requireTimes);
                    // 设计工时和产能负荷稍后计算
                    pointData.put("designTimes", 0);
                    pointData.put("capacityLoad", 0);
                    timeDataList.add(pointData);
                }
                rowDetail.put("timeData", timeDataList);
                rowEntry.put(rowGroupValue, rowDetail);
                plantTable.add(rowEntry);
            }
            // 添加时间数据
            List<Map<String, Object>> timeDataList = new ArrayList<>();
            Map<String, BigDecimal> timeMap = groupTimeDataMap.getOrDefault(groupKey, new HashMap<>());
            for (String timePoint : timePoints) {
                Map<String, Object> pointData = new HashMap<>();
                pointData.put("planDay", timePoint);
                // 获取该时间点的需求工时,如果不存在则设为0
                BigDecimal requireTimes = timeMap.getOrDefault(timePoint, BigDecimal.ZERO);
                pointData.put("requireTimes", requireTimes);
                // 设计工时和产能负荷稍后计算
                pointData.put("designTimes", 0);
                pointData.put("capacityLoad", 0);
                timeDataList.add(pointData);
            }
            rowDetail.put("timeData", timeDataList);
            rowEntry.put(rowGroupValue, rowDetail);
            plantTable.add(rowEntry);
        }
        // 在返回前查询设计产能数据并计算产能负荷
@@ -1878,6 +1877,135 @@
            });
        }
        
        // 实现注意点4:当时间颗粒度为"日"时,确保没有数据的工厂也返回完整结构
        if ("day".equalsIgnoreCase(timeGranularity) && params.containsKey("plant")) {
            // 获取请求中的工厂列表
            List<String> requestedPlants = new ArrayList<>();
            Object plantParam = params.get("plant");
            if (plantParam instanceof List) {
                requestedPlants.addAll((List<String>) plantParam);
            } else if (plantParam instanceof String) {
                String plantStr = (String) plantParam;
                if (plantStr.contains(",")) {
                    requestedPlants.addAll(Arrays.asList(plantStr.split(",")));
                } else {
                    requestedPlants.add(plantStr);
                }
            }
            if (!requestedPlants.isEmpty()) {
                // 检查哪些工厂没有数据
                Set<String> plantsWithData = new HashSet<>();
                for (Map<String, Object> rowEntry : plantTable) {
                    for (String rowKey : rowEntry.keySet()) {
                        Map<String, Object> rowDetail = (Map<String, Object>) rowEntry.get(rowKey);
                        if (rowDetail.containsKey("plant")) {
                            plantsWithData.add((String) rowDetail.get("plant"));
                        }
                    }
                }
                // 找出没有数据的工厂
                List<String> plantsWithoutData = requestedPlants.stream()
                        .filter(plant -> !plantsWithData.contains(plant))
                        .collect(Collectors.toList());
                if (!plantsWithoutData.isEmpty()) {
                    // 获取所有去重的processName或workshop
                    List<String> allUniqueValues;
                    if ("processName".equals(rowGroupBy)) {
                        allUniqueValues = apsGasPipingRouteStatMapper.selectDistinctProcessNames();
                    } else if ("workshop".equals(rowGroupBy)) {
                        allUniqueValues = apsGasPipingRouteStatMapper.selectDistinctWorkshops();
                    } else {
                        // 如果rowGroupBy不是processName或workshop,跳过处理
                        return result;
                    }
                    // 为每个没有数据的工厂创建空数据结构
                    for (String plant : plantsWithoutData) {
                        for (String uniqueValue : allUniqueValues) {
                            if (uniqueValue == null || uniqueValue.trim().isEmpty()) {
                                continue;
                            }
                            // 检查是否已经存在这个值
                            boolean exists = false;
                            for (Map<String, Object> entry : plantTable) {
                                if (entry.containsKey(uniqueValue)) {
                                    Map<String, Object> detail = (Map<String, Object>) entry.get(uniqueValue);
                                    String existingPlant = detail.containsKey("plant") ? (String) detail.get("plant") : "";
                                    if (plant.equals(existingPlant)) {
                                        exists = true;
                                        break;
                                    }
                                }
                            }
                            // 如果不存在,创建新的空数据结构
                            if (!exists) {
                                Map<String, Object> rowEntry = new HashMap<>();
                                Map<String, Object> rowDetail = new HashMap<>();
                                // 设置基本信息
                                rowDetail.put("plant", plant);
                                if (groupByMajor) {
                                    rowDetail.put("major", "");
                                }
                                if (groupByWorkshop && !"workshop".equals(rowGroupBy)) {
                                    rowDetail.put("workshop", "");
                                }
                                // 处理processName - 如果rowGroupBy为workshop,需要设置空的processName
                                if ("workshop".equals(rowGroupBy)) {
                                    rowDetail.put("processName", "");
                                }
                                // 为每个时间点创建零值数据
                                List<Map<String, Object>> timeDataList = new ArrayList<>();
                                for (String timePoint : timePoints) {
                                    Map<String, Object> pointData = new HashMap<>();
                                    pointData.put("planDay", timePoint);
                                    pointData.put("requireTimes", BigDecimal.ZERO);
                                    pointData.put("designTimes", BigDecimal.ZERO);
                                    pointData.put("capacityLoad", BigDecimal.ZERO);
                                    timeDataList.add(pointData);
                                }
                                rowDetail.put("timeData", timeDataList);
                                rowEntry.put(uniqueValue, rowDetail);
                                plantTable.add(rowEntry);
                            }
                        }
                    }
                    // 重新排序结果
                    Collections.sort(plantTable, (map1, map2) -> {
                        String key1 = map1.keySet().iterator().next();
                        String key2 = map2.keySet().iterator().next();
                        // 首先按rowGroupBy排序(processName或workshop)
                        int result1 = key1.compareTo(key2);
                        if (result1 != 0) {
                            return result1;
                        }
                        // 如果rowGroupBy相同,再按plant排序
                        Map<String, Object> detail1 = (Map<String, Object>) map1.get(key1);
                        Map<String, Object> detail2 = (Map<String, Object>) map2.get(key2);
                        String plant1 = detail1.containsKey("plant") ? (String) detail1.get("plant") : "";
                        String plant2 = detail2.containsKey("plant") ? (String) detail2.get("plant") : "";
                        return plant1.compareTo(plant2);
                    });
                    // 更新结果
                    result.put("plantTable", plantTable);
                }
            }
        }
        return result;
    }
    
aps-modules/aps-core/src/main/resources/mapper/core/ApsGasPipingRouteStatMapper.xml
@@ -451,5 +451,15 @@
            </if>
        </where>
    </select>
    <!-- 查询所有去重的工序名称 -->
    <select id="selectDistinctProcessNames" resultType="java.lang.String">
        SELECT DISTINCT process_name FROM aps_gas_piping_route_stat WHERE process_name IS NOT NULL AND process_name != ''
    </select>
    <!-- 查询所有去重的车间 -->
    <select id="selectDistinctWorkshops" resultType="java.lang.String">
        SELECT DISTINCT workshop FROM aps_gas_piping_route_stat WHERE workshop IS NOT NULL AND workshop != ''
    </select>
</mapper>