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<RegistrationTrendPoint> 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<Object[]> rawData = activityPlayerRepository.countFirstStageRegistrationsByDate(startDateTime);
|
Map<String, Long> 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<RegistrationTrendPoint> 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<RegionRegistrationStat> getRegionRegistrationStats() {
|
List<Object[]> rawData = activityPlayerRepository.countFirstStageRegistrationsByRegion();
|
List<RegionRegistrationStat> 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;
|
}
|
}
|