package com.rongyichuang.dashboard.service; import com.rongyichuang.activity.repository.ActivityRepository; import com.rongyichuang.dashboard.dto.response.DashboardStatsResponse; import com.rongyichuang.dashboard.dto.response.RegionRegistrationStat; import com.rongyichuang.dashboard.dto.response.RegistrationTrendPoint; import com.rongyichuang.judge.repository.JudgeRepository; import com.rongyichuang.player.repository.ActivityPlayerRepository; import com.rongyichuang.player.repository.PlayerRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Dashboard 统计数据服务 */ @Service public class DashboardService { private static final int DEFAULT_TREND_DAYS = 15; private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); private static final String UNASSIGNED_REGION_NAME = "未选择区域"; @Autowired private ActivityRepository activityRepository; @Autowired private PlayerRepository playerRepository; @Autowired private ActivityPlayerRepository activityPlayerRepository; @Autowired private JudgeRepository judgeRepository; /** * 获取Dashboard统计数据 */ public DashboardStatsResponse getDashboardStats() { DashboardStatsResponse stats = new DashboardStatsResponse(); // 当前进行比赛数量(状态为1的比赛,pid=0表示主比赛) long activeActivities = activityRepository.countActiveActivities(); stats.setActiveActivities((int) activeActivities); // 参赛总人数(状态为1的参赛选手) long totalPlayers = playerRepository.countByState(1); stats.setTotalPlayers((int) totalPlayers); // 报名待审核人数(activityPlayer状态为0表示待审核) long pendingReviews = activityPlayerRepository.countByState(0); stats.setPendingReviews((int) pendingReviews); // 评委总数(状态为1的评委) long totalJudges = judgeRepository.countByState(1); stats.setTotalJudges((int) totalJudges); return stats; } /** * 获取最近报名趋势(默认最近15天,仅统计第一阶段) */ public List getRegistrationTrend(Integer days) { int queryDays = (days == null || days <= 0) ? DEFAULT_TREND_DAYS : days; LocalDate today = LocalDate.now(); LocalDate startDate = today.minusDays(queryDays - 1L); LocalDateTime startDateTime = startDate.atStartOfDay(); List rawData = activityPlayerRepository.countFirstStageRegistrationsByDate(startDateTime); Map dataMap = new HashMap<>(); for (Object[] row : rawData) { if (row == null || row.length < 2) { continue; } Object dateObj = row[0]; LocalDate date; if (dateObj instanceof java.sql.Date sqlDate) { date = sqlDate.toLocalDate(); } else if (dateObj instanceof LocalDate localDate) { date = localDate; } else { date = LocalDate.parse(dateObj.toString()); } Long count = row[1] != null ? ((Number) row[1]).longValue() : 0L; dataMap.put(date.format(DATE_FORMATTER), count); } List result = new ArrayList<>(queryDays); for (int i = 0; i < queryDays; i++) { LocalDate date = startDate.plusDays(i); String key = date.format(DATE_FORMATTER); Long count = dataMap.getOrDefault(key, 0L); result.add(new RegistrationTrendPoint(key, count)); } return result; } /** * 获取区域报名分布(仅统计第一阶段,剔除非叶子区域) */ public List getRegionRegistrationStats() { List rawData = activityPlayerRepository.countFirstStageRegistrationsByRegion(); List stats = new ArrayList<>(); for (Object[] row : rawData) { if (row == null || row.length < 4) { continue; } String regionId = null; if (row[0] != null) { Object regionIdObj = row[0]; if (regionIdObj instanceof Number number) { regionId = String.valueOf(number.longValue()); } else { regionId = regionIdObj.toString(); } } String regionName = row[1] != null ? row[1].toString() : UNASSIGNED_REGION_NAME; // leaf_flag字段在不同驱动下的类型可能差异,需要统一转换 Boolean leafFlag = null; Object leafObj = row[2]; if (leafObj instanceof Number number) { leafFlag = number.intValue() == 1; } else if (leafObj instanceof Boolean bool) { leafFlag = bool; } else if (leafObj != null) { String leafText = leafObj.toString().trim().toLowerCase(); if (!leafText.isEmpty()) { if ("1".equals(leafText) || "true".equals(leafText)) { leafFlag = true; } else if ("0".equals(leafText) || "false".equals(leafText)) { leafFlag = false; } } } Long count = row[3] != null ? ((Number) row[3]).longValue() : 0L; if (Boolean.FALSE.equals(leafFlag)) { // 非叶子区域不参与统计 continue; } if (regionName == null || regionName.isBlank()) { regionName = UNASSIGNED_REGION_NAME; } stats.add(new RegionRegistrationStat(regionId, regionName, leafFlag, count)); } return stats; } }