diff --git a/backend/src/main/java/com/designhub/controller/AnalyticsController.java b/backend/src/main/java/com/designhub/controller/AnalyticsController.java index 2200bbc..480a4bd 100644 --- a/backend/src/main/java/com/designhub/controller/AnalyticsController.java +++ b/backend/src/main/java/com/designhub/controller/AnalyticsController.java @@ -6,6 +6,7 @@ import com.designhub.util.JwtUtil; import com.designhub.vo.DeductionDetailVO; import com.designhub.vo.DemandStatisticsVO; import com.designhub.vo.DesignerPerformanceVO; +import com.designhub.vo.DimensionAnalysisVO; import com.designhub.vo.ProcessEfficiencyVO; import com.designhub.vo.WarningTaskVO; import io.swagger.v3.oas.annotations.Operation; @@ -101,5 +102,16 @@ public class AnalyticsController { return Result.success(analyticsService.getDesignerDeductionDetails(userId, month)); } + + @Operation(summary = "获取多维度分析数据(类目/品牌/部门/平台)") + @GetMapping("/dimension-analysis") + public Result getDimensionAnalysis( + @RequestParam(required = false, defaultValue = "month") String dateRange, + @RequestParam(required = false) String month + ) { + log.info("获取多维度分析数据: dateRange={}, month={}", dateRange, month); + + return Result.success(analyticsService.getDimensionAnalysis(dateRange, month)); + } } diff --git a/backend/src/main/java/com/designhub/service/AnalyticsService.java b/backend/src/main/java/com/designhub/service/AnalyticsService.java index 91cc507..92f30d9 100644 --- a/backend/src/main/java/com/designhub/service/AnalyticsService.java +++ b/backend/src/main/java/com/designhub/service/AnalyticsService.java @@ -6,6 +6,7 @@ import com.designhub.mapper.*; import com.designhub.vo.DeductionDetailVO; import com.designhub.vo.DemandStatisticsVO; import com.designhub.vo.DesignerPerformanceVO; +import com.designhub.vo.DimensionAnalysisVO; import com.designhub.vo.ProcessEfficiencyVO; import com.designhub.vo.WarningTaskVO; import lombok.RequiredArgsConstructor; @@ -41,6 +42,9 @@ public class AnalyticsService { private final DesignerTargetScoreMapper designerTargetScoreMapper; private final DemandTypeMapper demandTypeMapper; private final ProgressDeductionLogMapper progressDeductionLogMapper; + private final BrandMapper brandMapper; + private final CategoryMapper categoryMapper; + private final PlatformMapper platformMapper; private final com.designhub.util.WorkHoursCalculator workHoursCalculator; /** @@ -1838,5 +1842,416 @@ public class AnalyticsService { .progressDeductions(progressDeductions) .build(); } + + /** + * 获取多维度分析数据 + * @param dateRange 时间范围 + * @param month 指定月份 + */ + public DimensionAnalysisVO getDimensionAnalysis(String dateRange, String month) { + log.info("获取多维度分析数据: dateRange={}, month={}", dateRange, month); + + // 计算时间范围 + LocalDateTime startTime; + LocalDateTime endTime; + + if (month != null && !month.isEmpty()) { + try { + LocalDate monthDate = LocalDate.parse(month + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd")); + startTime = LocalDateTime.of(monthDate, LocalTime.MIN); + endTime = LocalDateTime.of(monthDate.with(TemporalAdjusters.lastDayOfMonth()), LocalTime.MAX); + } catch (Exception e) { + log.warn("月份格式错误: {}, 使用默认范围", month); + startTime = calculateStartTime(dateRange); + endTime = LocalDateTime.now(); + } + } else { + startTime = calculateStartTime(dateRange); + endTime = LocalDateTime.now(); + } + + // 查询时间范围内的所有任务 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .ge(startTime != null, Task::getCreateTime, startTime) + .le(Task::getCreateTime, endTime) + .ne(Task::getStatus, "draft"); // 排除草稿 + + List tasks = taskMapper.selectList(queryWrapper); + log.info("查询到任务数量: {}", tasks.size()); + + DimensionAnalysisVO result = new DimensionAnalysisVO(); + result.setCategoryAnalysis(buildCategoryAnalysis(tasks)); + result.setBrandAnalysis(buildBrandAnalysis(tasks)); + result.setReceivingDeptAnalysis(buildReceivingDeptAnalysis(tasks)); + result.setDemandDeptAnalysis(buildDemandDeptAnalysis(tasks)); + result.setPlatformAnalysis(buildPlatformAnalysis(tasks)); + + return result; + } + + /** + * 构建类目分析数据 + */ + private List buildCategoryAnalysis(List tasks) { + // 按类目ID分组 + Map> tasksByCategory = tasks.stream() + .filter(t -> t.getCategoryId() != null) + .collect(Collectors.groupingBy(Task::getCategoryId)); + + List result = new ArrayList<>(); + + // 获取所有类目 + List categories = categoryMapper.selectList(null); + Map categoryNames = categories.stream() + .collect(Collectors.toMap(Category::getId, Category::getName, (a, b) -> a)); + + for (Map.Entry> entry : tasksByCategory.entrySet()) { + Long categoryId = entry.getKey(); + List categoryTasks = entry.getValue(); + + DimensionAnalysisVO.CategoryAnalysis analysis = new DimensionAnalysisVO.CategoryAnalysis(); + analysis.setCategoryId(categoryId); + analysis.setCategoryName(categoryNames.getOrDefault(categoryId, "未知类目")); + analysis.setTotalTasks(categoryTasks.size()); + + long completedCount = categoryTasks.stream() + .filter(t -> "completed".equals(t.getStatus())) + .count(); + analysis.setCompletedTasks((int) completedCount); + + long inProgressCount = categoryTasks.stream() + .filter(t -> "in_progress".equals(t.getStatus())) + .count(); + analysis.setInProgressTasks((int) inProgressCount); + + long pendingCount = categoryTasks.stream() + .filter(t -> t.getStatus() != null && t.getStatus().contains("pending")) + .count(); + analysis.setPendingTasks((int) pendingCount); + + // 计算总积分 + BigDecimal totalScore = categoryTasks.stream() + .filter(t -> t.getScore() != null) + .map(Task::getScore) + .reduce(BigDecimal.ZERO, BigDecimal::add); + analysis.setTotalScore(totalScore); + + // 计算完成率 + if (categoryTasks.size() > 0) { + analysis.setCompletionRate(BigDecimal.valueOf(completedCount * 100.0 / categoryTasks.size()) + .setScale(2, RoundingMode.HALF_UP)); + } else { + analysis.setCompletionRate(BigDecimal.ZERO); + } + + // 计算总数量 + int totalQuantity = categoryTasks.stream() + .filter(t -> t.getQuantity() != null) + .mapToInt(Task::getQuantity) + .sum(); + analysis.setTotalQuantity(totalQuantity); + + result.add(analysis); + } + + // 按任务数量降序排序 + result.sort((a, b) -> Integer.compare(b.getTotalTasks(), a.getTotalTasks())); + + return result; + } + + /** + * 构建品牌分析数据 + */ + private List buildBrandAnalysis(List tasks) { + // 按品牌ID分组 + Map> tasksByBrand = tasks.stream() + .filter(t -> t.getBrandId() != null) + .collect(Collectors.groupingBy(Task::getBrandId)); + + List result = new ArrayList<>(); + + // 获取所有品牌 + List brands = brandMapper.selectList(null); + Map brandNames = brands.stream() + .collect(Collectors.toMap(Brand::getId, Brand::getName, (a, b) -> a)); + + for (Map.Entry> entry : tasksByBrand.entrySet()) { + Long brandId = entry.getKey(); + List brandTasks = entry.getValue(); + + DimensionAnalysisVO.BrandAnalysis analysis = new DimensionAnalysisVO.BrandAnalysis(); + analysis.setBrandId(brandId); + analysis.setBrandName(brandNames.getOrDefault(brandId, "未知品牌")); + analysis.setTotalTasks(brandTasks.size()); + + long completedCount = brandTasks.stream() + .filter(t -> "completed".equals(t.getStatus())) + .count(); + analysis.setCompletedTasks((int) completedCount); + + long inProgressCount = brandTasks.stream() + .filter(t -> "in_progress".equals(t.getStatus())) + .count(); + analysis.setInProgressTasks((int) inProgressCount); + + // 计算总积分 + BigDecimal totalScore = brandTasks.stream() + .filter(t -> t.getScore() != null) + .map(Task::getScore) + .reduce(BigDecimal.ZERO, BigDecimal::add); + analysis.setTotalScore(totalScore); + + // 计算完成率 + if (brandTasks.size() > 0) { + analysis.setCompletionRate(BigDecimal.valueOf(completedCount * 100.0 / brandTasks.size()) + .setScale(2, RoundingMode.HALF_UP)); + } else { + analysis.setCompletionRate(BigDecimal.ZERO); + } + + // 计算总数量 + int totalQuantity = brandTasks.stream() + .filter(t -> t.getQuantity() != null) + .mapToInt(Task::getQuantity) + .sum(); + analysis.setTotalQuantity(totalQuantity); + + result.add(analysis); + } + + // 按任务数量降序排序 + result.sort((a, b) -> Integer.compare(b.getTotalTasks(), a.getTotalTasks())); + + return result; + } + + /** + * 构建接单部门分析数据 + */ + private List buildReceivingDeptAnalysis(List tasks) { + // 按接单部门ID分组 + Map> tasksByDept = tasks.stream() + .filter(t -> t.getReceiverDeptId() != null) + .collect(Collectors.groupingBy(Task::getReceiverDeptId)); + + List result = new ArrayList<>(); + + // 获取所有部门 + List departments = departmentMapper.selectList(null); + Map deptNames = departments.stream() + .collect(Collectors.toMap(d -> d.getId(), d -> d.getName(), (a, b) -> a)); + + for (Map.Entry> entry : tasksByDept.entrySet()) { + Long deptId = entry.getKey(); + List deptTasks = entry.getValue(); + + DimensionAnalysisVO.ReceivingDeptAnalysis analysis = new DimensionAnalysisVO.ReceivingDeptAnalysis(); + analysis.setDeptId(deptId); + analysis.setDeptName(deptNames.getOrDefault(deptId, "未知部门")); + analysis.setTotalTasks(deptTasks.size()); + + long completedCount = deptTasks.stream() + .filter(t -> "completed".equals(t.getStatus())) + .count(); + analysis.setCompletedTasks((int) completedCount); + + long inProgressCount = deptTasks.stream() + .filter(t -> "in_progress".equals(t.getStatus())) + .count(); + analysis.setInProgressTasks((int) inProgressCount); + + long pendingCount = deptTasks.stream() + .filter(t -> t.getStatus() != null && t.getStatus().contains("pending")) + .count(); + analysis.setPendingTasks((int) pendingCount); + + // 计算总积分 + BigDecimal totalScore = deptTasks.stream() + .filter(t -> t.getScore() != null) + .map(Task::getScore) + .reduce(BigDecimal.ZERO, BigDecimal::add); + analysis.setTotalScore(totalScore); + + // 计算完成率 + if (deptTasks.size() > 0) { + analysis.setCompletionRate(BigDecimal.valueOf(completedCount * 100.0 / deptTasks.size()) + .setScale(2, RoundingMode.HALF_UP)); + } else { + analysis.setCompletionRate(BigDecimal.ZERO); + } + + // 计算总数量 + int totalQuantity = deptTasks.stream() + .filter(t -> t.getQuantity() != null) + .mapToInt(Task::getQuantity) + .sum(); + analysis.setTotalQuantity(totalQuantity); + + // 计算平均完成时长(小时) + List completedTasks = deptTasks.stream() + .filter(t -> "completed".equals(t.getStatus()) && t.getCompleteTime() != null && t.getUpdateTime() != null) + .collect(Collectors.toList()); + if (!completedTasks.isEmpty()) { + double avgHours = completedTasks.stream() + .mapToDouble(t -> { + Duration duration = Duration.between(t.getCreateTime(), t.getCompleteTime()); + return duration.toHours(); + }) + .average() + .orElse(0); + analysis.setAvgCompletionHours(BigDecimal.valueOf(avgHours).setScale(2, RoundingMode.HALF_UP)); + } else { + analysis.setAvgCompletionHours(BigDecimal.ZERO); + } + + result.add(analysis); + } + + // 按任务数量降序排序 + result.sort((a, b) -> Integer.compare(b.getTotalTasks(), a.getTotalTasks())); + + return result; + } + + /** + * 构建需求部门分析数据 + */ + private List buildDemandDeptAnalysis(List tasks) { + // 按需求部门ID分组 + Map> tasksByDept = tasks.stream() + .filter(t -> t.getPublisherDeptId() != null) + .collect(Collectors.groupingBy(Task::getPublisherDeptId)); + + List result = new ArrayList<>(); + + // 获取所有部门 + List departments = departmentMapper.selectList(null); + Map deptNames = departments.stream() + .collect(Collectors.toMap(d -> d.getId(), d -> d.getName(), (a, b) -> a)); + + for (Map.Entry> entry : tasksByDept.entrySet()) { + Long deptId = entry.getKey(); + List deptTasks = entry.getValue(); + + DimensionAnalysisVO.DemandDeptAnalysis analysis = new DimensionAnalysisVO.DemandDeptAnalysis(); + analysis.setDeptId(deptId); + analysis.setDeptName(deptNames.getOrDefault(deptId, "未知部门")); + analysis.setTotalTasks(deptTasks.size()); + + long completedCount = deptTasks.stream() + .filter(t -> "completed".equals(t.getStatus())) + .count(); + analysis.setCompletedTasks((int) completedCount); + + long inProgressCount = deptTasks.stream() + .filter(t -> "in_progress".equals(t.getStatus())) + .count(); + analysis.setInProgressTasks((int) inProgressCount); + + long pendingCount = deptTasks.stream() + .filter(t -> t.getStatus() != null && t.getStatus().contains("pending")) + .count(); + analysis.setPendingTasks((int) pendingCount); + + // 计算总积分 + BigDecimal totalScore = deptTasks.stream() + .filter(t -> t.getScore() != null) + .map(Task::getScore) + .reduce(BigDecimal.ZERO, BigDecimal::add); + analysis.setTotalScore(totalScore); + + // 计算完成率 + if (deptTasks.size() > 0) { + analysis.setCompletionRate(BigDecimal.valueOf(completedCount * 100.0 / deptTasks.size()) + .setScale(2, RoundingMode.HALF_UP)); + } else { + analysis.setCompletionRate(BigDecimal.ZERO); + } + + // 计算总数量 + int totalQuantity = deptTasks.stream() + .filter(t -> t.getQuantity() != null) + .mapToInt(Task::getQuantity) + .sum(); + analysis.setTotalQuantity(totalQuantity); + + // 需求部门不计算平均完成时长,设置为null + analysis.setAvgCompletionHours(null); + + result.add(analysis); + } + + // 按任务数量降序排序 + result.sort((a, b) -> Integer.compare(b.getTotalTasks(), a.getTotalTasks())); + + return result; + } + + /** + * 构建平台分析数据 + */ + private List buildPlatformAnalysis(List tasks) { + // 按平台ID分组 + Map> tasksByPlatform = tasks.stream() + .filter(t -> t.getPlatformId() != null) + .collect(Collectors.groupingBy(Task::getPlatformId)); + + List result = new ArrayList<>(); + + // 获取所有平台 + List platforms = platformMapper.selectList(null); + Map platformNames = platforms.stream() + .collect(Collectors.toMap(Platform::getId, Platform::getName, (a, b) -> a)); + + for (Map.Entry> entry : tasksByPlatform.entrySet()) { + Long platformId = entry.getKey(); + List platformTasks = entry.getValue(); + + DimensionAnalysisVO.PlatformAnalysis analysis = new DimensionAnalysisVO.PlatformAnalysis(); + analysis.setPlatformId(platformId); + analysis.setPlatformName(platformNames.getOrDefault(platformId, "未知平台")); + analysis.setTotalTasks(platformTasks.size()); + + long completedCount = platformTasks.stream() + .filter(t -> "completed".equals(t.getStatus())) + .count(); + analysis.setCompletedTasks((int) completedCount); + + long inProgressCount = platformTasks.stream() + .filter(t -> "in_progress".equals(t.getStatus())) + .count(); + analysis.setInProgressTasks((int) inProgressCount); + + // 计算总积分 + BigDecimal totalScore = platformTasks.stream() + .filter(t -> t.getScore() != null) + .map(Task::getScore) + .reduce(BigDecimal.ZERO, BigDecimal::add); + analysis.setTotalScore(totalScore); + + // 计算完成率 + if (platformTasks.size() > 0) { + analysis.setCompletionRate(BigDecimal.valueOf(completedCount * 100.0 / platformTasks.size()) + .setScale(2, RoundingMode.HALF_UP)); + } else { + analysis.setCompletionRate(BigDecimal.ZERO); + } + + // 计算总数量 + int totalQuantity = platformTasks.stream() + .filter(t -> t.getQuantity() != null) + .mapToInt(Task::getQuantity) + .sum(); + analysis.setTotalQuantity(totalQuantity); + + result.add(analysis); + } + + // 按任务数量降序排序 + result.sort((a, b) -> Integer.compare(b.getTotalTasks(), a.getTotalTasks())); + + return result; + } } diff --git a/backend/src/main/java/com/designhub/vo/DimensionAnalysisVO.java b/backend/src/main/java/com/designhub/vo/DimensionAnalysisVO.java new file mode 100644 index 0000000..6e4c266 --- /dev/null +++ b/backend/src/main/java/com/designhub/vo/DimensionAnalysisVO.java @@ -0,0 +1,169 @@ +package com.designhub.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 多维分析数据VO + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DimensionAnalysisVO { + + /** + * 类目维度分析 + */ + private List categoryAnalysis; + + /** + * 品牌维度分析 + */ + private List brandAnalysis; + + /** + * 接单部门维度分析 + */ + private List receivingDeptAnalysis; + + /** + * 需求部门维度分析 + */ + private List demandDeptAnalysis; + + /** + * 平台维度分析 + */ + private List platformAnalysis; + + /** + * 类目分析数据 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class CategoryAnalysis { + private Long categoryId; + private String categoryName; + private Integer totalTasks; // 总任务数 + private Integer completedTasks; // 已完成任务数 + private Integer inProgressTasks; // 进行中任务数 + private Integer pendingTasks; // 待接单任务数 + private Integer totalQuantity; // 总数量 + private BigDecimal totalScore; // 总积分 + private BigDecimal avgScore; // 平均积分 + private BigDecimal completionRate; // 完成率 + private Double onTimeRate; // 准时率 + private Double avgCompletionHours; // 平均完成时长(小时) + private Integer designerCount; // 参与设计师数量 + } + + /** + * 品牌分析数据 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class BrandAnalysis { + private Long brandId; + private String brandName; + private Integer totalTasks; // 总任务数 + private Integer completedTasks; // 已完成任务数 + private Integer inProgressTasks; // 进行中任务数 + private Integer pendingTasks; // 待接单任务数 + private Integer totalQuantity; // 总数量 + private BigDecimal totalScore; // 总积分 + private BigDecimal avgScore; // 平均积分 + private BigDecimal completionRate; // 完成率 + private Double onTimeRate; // 准时率 + private Double avgCompletionHours; // 平均完成时长(小时) + private Integer categoryCount; // 涉及类目数量 + } + + /** + * 接单部门维度分析 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class ReceivingDeptAnalysis { + private Long deptId; + private String deptName; + private Integer totalTasks; // 总接单数(主任务+子任务) + private Integer completedTasks; // 已完成任务数 + private Integer inProgressTasks; // 进行中任务数 + private Integer pendingTasks; // 待接单任务数 + private Integer totalQuantity; // 总数量 + private Integer designerCount; // 设计师数量 + private Integer activeDesignerCount; // 活跃设计师数量(有接单的设计师) + private BigDecimal totalScore; // 获得总积分 + private BigDecimal avgScore; // 平均积分 + private BigDecimal completionRate; // 完成率 + private Double onTimeRate; // 准时率 + private BigDecimal avgCompletionHours; // 平均完成时长(小时) + private BigDecimal totalDeductionScore; // 总扣分 + private BigDecimal netScore; // 净积分 + private Double workloadRate; // 工作量占比 + } + + /** + * 需求部门维度分析 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class DemandDeptAnalysis { + private Long deptId; + private String deptName; + private Integer totalTasks; // 总发布任务数 + private Integer completedTasks; // 已完成任务数 + private Integer inProgressTasks; // 进行中任务数 + private Integer pendingTasks; // 待接单任务数 + private Integer totalQuantity; // 总数量 + private Integer publisherCount; // 发布人数量 + private Integer activePublisherCount; // 活跃发布人数量 + private BigDecimal totalScore; // 消耗总积分 + private BigDecimal avgScore; // 平均积分 + private BigDecimal completionRate; // 完成率 + private Double onTimeRate; // 准时率 + private BigDecimal avgCompletionHours; // 平均完成时长(小时) + private Integer brandCount; // 涉及品牌数量 + private Integer categoryCount; // 涉及类目数量 + } + + /** + * 平台维度分析 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class PlatformAnalysis { + private Long platformId; + private String platformName; + private Integer totalTasks; // 总任务数 + private Integer completedTasks; // 已完成任务数 + private Integer inProgressTasks; // 进行中任务数 + private Integer pendingTasks; // 待接单任务数 + private Integer totalQuantity; // 总数量 + private BigDecimal totalScore; // 总积分 + private BigDecimal avgScore; // 平均积分 + private BigDecimal completionRate; // 完成率 + private Double onTimeRate; // 准时率 + private Double avgCompletionHours; // 平均完成时长(小时) + private Integer brandCount; // 涉及品牌数量 + private Integer categoryCount; // 涉及类目数量 + private Integer demandDeptCount; // 需求部门数量 + private Integer receivingDeptCount; // 接单部门数量 + } +} diff --git a/frontend/src/views/Analytics.vue b/frontend/src/views/Analytics.vue index d976531..d17498a 100644 --- a/frontend/src/views/Analytics.vue +++ b/frontend/src/views/Analytics.vue @@ -432,6 +432,141 @@ + + + +
+ + + +
+

类目分析

+ + + +
+
+ + + +
+

品牌分析

+ + + +
+
+ + + +
+

接单部门分析

+ + + +
+
+ + + +
+

需求部门分析

+ + + +
+
+ + + +
+

平台分析

+ + + +
+
+
+
+
@@ -525,13 +660,15 @@ import { getProcessEfficiency, getWarningTasks, getDesignerDeductionDetails, + getDimensionAnalysis, type DemandStatistics, type DesignerPerformance, type ProcessEfficiency, type WarningTask, type DeductionDetail, type DelayDeductionItem, - type ProgressDeductionItem + type ProgressDeductionItem, + type DimensionAnalysis } from '@/api/analytics' import { message } from 'ant-design-vue' import * as echarts from 'echarts' @@ -627,6 +764,15 @@ const processEfficiency = reactive({ const warningTasks = ref([]) const warningFilter = ref('all') +// 多维度分析数据 +const dimensionData = reactive({ + categoryAnalysis: [], + brandAnalysis: [], + receivingDeptAnalysis: [], + demandDeptAnalysis: [], + platformAnalysis: [] +}) + // 部门筛选 const selectedDeptId = ref(undefined) const departmentList = ref([]) @@ -795,6 +941,58 @@ const progressDeductionColumns = [ { title: '扣分原因', dataIndex: 'reason', key: 'reason' } ] +// 多维度分析表格列定义 +const categoryColumns = [ + { title: '类目名称', dataIndex: 'categoryName', key: 'categoryName', ellipsis: true }, + { title: '任务数', dataIndex: 'totalTasks', key: 'totalTasks', align: 'center', width: 80 }, + { title: '总数量', dataIndex: 'totalQuantity', key: 'totalQuantity', align: 'center', width: 80 }, + { title: '已完成', dataIndex: 'completedTasks', key: 'completedTasks', align: 'center', width: 80 }, + { title: '进行中', dataIndex: 'inProgressTasks', key: 'inProgressTasks', align: 'center', width: 80 }, + { title: '完成率', key: 'completionRate', align: 'center', width: 80 }, + { title: '总积分', key: 'totalScore', align: 'center', width: 80 } +] + +const brandColumns = [ + { title: '品牌名称', dataIndex: 'brandName', key: 'brandName', ellipsis: true }, + { title: '任务数', dataIndex: 'totalTasks', key: 'totalTasks', align: 'center', width: 80 }, + { title: '总数量', dataIndex: 'totalQuantity', key: 'totalQuantity', align: 'center', width: 80 }, + { title: '已完成', dataIndex: 'completedTasks', key: 'completedTasks', align: 'center', width: 80 }, + { title: '进行中', dataIndex: 'inProgressTasks', key: 'inProgressTasks', align: 'center', width: 80 }, + { title: '完成率', key: 'completionRate', align: 'center', width: 80 }, + { title: '总积分', key: 'totalScore', align: 'center', width: 80 } +] + +const receivingDeptColumns = [ + { title: '部门名称', dataIndex: 'deptName', key: 'deptName', ellipsis: true }, + { title: '任务数', dataIndex: 'totalTasks', key: 'totalTasks', align: 'center', width: 70 }, + { title: '总数量', dataIndex: 'totalQuantity', key: 'totalQuantity', align: 'center', width: 70 }, + { title: '已完成', dataIndex: 'completedTasks', key: 'completedTasks', align: 'center', width: 70 }, + { title: '进行中', dataIndex: 'inProgressTasks', key: 'inProgressTasks', align: 'center', width: 70 }, + { title: '完成率', key: 'completionRate', align: 'center', width: 70 }, + { title: '总积分', key: 'totalScore', align: 'center', width: 70 }, + { title: '平均耗时', key: 'avgCompletionHours', align: 'center', width: 90 } +] + +const demandDeptColumns = [ + { title: '部门名称', dataIndex: 'deptName', key: 'deptName', ellipsis: true }, + { title: '任务数', dataIndex: 'totalTasks', key: 'totalTasks', align: 'center', width: 80 }, + { title: '总数量', dataIndex: 'totalQuantity', key: 'totalQuantity', align: 'center', width: 80 }, + { title: '已完成', dataIndex: 'completedTasks', key: 'completedTasks', align: 'center', width: 80 }, + { title: '待处理', dataIndex: 'pendingTasks', key: 'pendingTasks', align: 'center', width: 80 }, + { title: '完成率', key: 'completionRate', align: 'center', width: 80 }, + { title: '总积分', key: 'totalScore', align: 'center', width: 80 } +] + +const platformColumns = [ + { title: '平台名称', dataIndex: 'platformName', key: 'platformName', ellipsis: true }, + { title: '任务数', dataIndex: 'totalTasks', key: 'totalTasks', align: 'center', width: 100 }, + { title: '总数量', dataIndex: 'totalQuantity', key: 'totalQuantity', align: 'center', width: 100 }, + { title: '已完成', dataIndex: 'completedTasks', key: 'completedTasks', align: 'center', width: 100 }, + { title: '进行中', dataIndex: 'inProgressTasks', key: 'inProgressTasks', align: 'center', width: 100 }, + { title: '完成率', key: 'completionRate', align: 'center', width: 100 }, + { title: '总积分', key: 'totalScore', align: 'center', width: 100 } +] + // 方法 const handleMonthChange = (value: string | null) => { selectedMonth.value = value @@ -820,11 +1018,12 @@ const loadAllData = async () => { const month = selectedMonth.value || undefined // 并行加载所有数据 - const [demandData, designerData, efficiencyData, warningsData] = await Promise.all([ + const [demandData, designerData, efficiencyData, warningsData, dimensionAnalysisData] = await Promise.all([ getDemandStatistics(dateRange.value, undefined, undefined, month), getDesignerPerformance(month, selectedDeptId.value), getProcessEfficiency(month), - getWarningTasks() + getWarningTasks(), + getDimensionAnalysis(dateRange.value, month) ]) // 更新需求统计 @@ -839,6 +1038,9 @@ const loadAllData = async () => { // 更新预警任务 warningTasks.value = warningsData + // 更新多维度分析数据 + Object.assign(dimensionData, dimensionAnalysisData) + await nextTick() // 渲染当前Tab的图表