diff --git a/backend/src/main/java/com/designhub/service/AnalyticsService.java b/backend/src/main/java/com/designhub/service/AnalyticsService.java index 727b77f..28cd61f 100644 --- a/backend/src/main/java/com/designhub/service/AnalyticsService.java +++ b/backend/src/main/java/com/designhub/service/AnalyticsService.java @@ -2866,6 +2866,7 @@ public class AnalyticsService { /** * 构建任务类型分析数据(一级、二级、三级分类) + * 任务通常只关联三级类型,需要向上聚合到二级和一级 * @param tasks 任务列表 * @return 按层级分组的任务类型分析数据,key为层级(1/2/3) */ @@ -2886,30 +2887,19 @@ public class AnalyticsService { Map typeNameMap = allTypes.stream() .collect(Collectors.toMap(DemandType::getId, t -> t.getName() != null ? t.getName() : "未知", (a, b) -> a)); - // 收集所有任务中涉及的任务类型ID - Set allTaskTypeIds = new HashSet<>(); - for (Task task : tasks) { - // 单个任务类型ID - if (task.getTaskTypeId() != null) { - allTaskTypeIds.add(task.getTaskTypeId()); - } - // 多个任务类型ID(逗号分隔) - if (task.getTaskTypeIds() != null && !task.getTaskTypeIds().trim().isEmpty()) { - String[] ids = task.getTaskTypeIds().split(","); - for (String id : ids) { - try { - allTaskTypeIds.add(Long.parseLong(id.trim())); - } catch (NumberFormatException e) { - // 忽略无效ID - } - } - } + // 计算每个类型的层级 + Map typeLevelMap = new HashMap<>(); + for (DemandType type : allTypes) { + int level = calculateTypeLevel(type.getId(), typeMap); + typeLevelMap.put(type.getId(), level); } - log.info("涉及的任务类型ID数量: {}", allTaskTypeIds.size()); + // 按各层级类型ID分组统计任务(向上聚合) + // key: 类型ID, value: 任务列表 + Map> tasksByLevel1TypeId = new HashMap<>(); + Map> tasksByLevel2TypeId = new HashMap<>(); + Map> tasksByLevel3TypeId = new HashMap<>(); - // 按任务类型ID分组统计任务 - Map> tasksByTypeId = new HashMap<>(); for (Task task : tasks) { Set typeIds = new HashSet<>(); if (task.getTaskTypeId() != null) { @@ -2925,17 +2915,50 @@ public class AnalyticsService { } } } + for (Long typeId : typeIds) { - tasksByTypeId.computeIfAbsent(typeId, k -> new ArrayList<>()).add(task); + DemandType type = typeMap.get(typeId); + if (type == null) { + continue; + } + + int level = typeLevelMap.getOrDefault(typeId, 1); + + // 根据当前类型的层级,向上聚合到各级 + if (level == 3) { + // 三级类型:直接加入三级统计 + tasksByLevel3TypeId.computeIfAbsent(typeId, k -> new ArrayList<>()).add(task); + + // 向上聚合到二级 + Long level2Id = type.getParentId(); + if (level2Id != null) { + tasksByLevel2TypeId.computeIfAbsent(level2Id, k -> new ArrayList<>()).add(task); + + // 向上聚合到一级 + DemandType level2Type = typeMap.get(level2Id); + if (level2Type != null && level2Type.getParentId() != null) { + Long level1Id = level2Type.getParentId(); + tasksByLevel1TypeId.computeIfAbsent(level1Id, k -> new ArrayList<>()).add(task); + } + } + } else if (level == 2) { + // 二级类型:加入二级统计 + tasksByLevel2TypeId.computeIfAbsent(typeId, k -> new ArrayList<>()).add(task); + + // 向上聚合到一级 + Long level1Id = type.getParentId(); + if (level1Id != null) { + tasksByLevel1TypeId.computeIfAbsent(level1Id, k -> new ArrayList<>()).add(task); + } + } else if (level == 1) { + // 一级类型:直接加入一级统计 + tasksByLevel1TypeId.computeIfAbsent(typeId, k -> new ArrayList<>()).add(task); + } } } - // 计算每个类型的层级 - Map typeLevelMap = new HashMap<>(); - for (DemandType type : allTypes) { - int level = calculateTypeLevel(type.getId(), typeMap); - typeLevelMap.put(type.getId(), level); - } + log.info("各层级涉及的类型数量: 一级={}, 二级={}, 三级={}", + tasksByLevel1TypeId.size(), tasksByLevel2TypeId.size(), tasksByLevel3TypeId.size()); // 构建各层级的分析数据 Map> result = new HashMap<>(); @@ -2943,25 +2966,43 @@ public class AnalyticsService { result.put(2, new ArrayList<>()); result.put(3, new ArrayList<>()); - for (Long typeId : allTaskTypeIds) { + // 构建一级分析数据 + for (Map.Entry> entry : tasksByLevel1TypeId.entrySet()) { + Long typeId = entry.getKey(); + List typeTasks = entry.getValue(); DemandType type = typeMap.get(typeId); - if (type == null) { - continue; + if (type != null && !typeTasks.isEmpty()) { + DimensionAnalysisVO.TaskTypeAnalysis analysis = buildSingleTaskTypeAnalysis( + type, typeTasks, 1, typeMap, typeNameMap + ); + result.get(1).add(analysis); } - - List typeTasks = tasksByTypeId.getOrDefault(typeId, new ArrayList<>()); - if (typeTasks.isEmpty()) { - continue; + } + + // 构建二级分析数据 + for (Map.Entry> entry : tasksByLevel2TypeId.entrySet()) { + Long typeId = entry.getKey(); + List typeTasks = entry.getValue(); + DemandType type = typeMap.get(typeId); + if (type != null && !typeTasks.isEmpty()) { + DimensionAnalysisVO.TaskTypeAnalysis analysis = buildSingleTaskTypeAnalysis( + type, typeTasks, 2, typeMap, typeNameMap + ); + result.get(2).add(analysis); + } + } + + // 构建三级分析数据 + for (Map.Entry> entry : tasksByLevel3TypeId.entrySet()) { + Long typeId = entry.getKey(); + List typeTasks = entry.getValue(); + DemandType type = typeMap.get(typeId); + if (type != null && !typeTasks.isEmpty()) { + DimensionAnalysisVO.TaskTypeAnalysis analysis = buildSingleTaskTypeAnalysis( + type, typeTasks, 3, typeMap, typeNameMap + ); + result.get(3).add(analysis); } - - int level = typeLevelMap.getOrDefault(typeId, 1); - - // 构建分析数据 - DimensionAnalysisVO.TaskTypeAnalysis analysis = buildSingleTaskTypeAnalysis( - type, typeTasks, level, typeMap, typeNameMap - ); - - result.get(level).add(analysis); } // 对各层级按任务数量降序排序