From c4a9cad1c50e89365e2a58b50e259af642ed3b8c Mon Sep 17 00:00:00 2001 From: Codex Assistant <codex@example.com> Date: 星期二, 07 十月 2025 16:12:20 +0800 Subject: [PATCH] feat(review): 调整评审详情展示顺序与样式,描述支持多行,项目信息列宽40/60 fix(auth): 登录页与首页循环跳转保护;api.ts 在登录页不再重定向;401分支在登录页不跳转 fix(router): /login 放行策略优化,避免死循环;评审列表跳转到 /project-review/:id/detail fix(frontend): 补齐 utils/appConfig.ts,避免启动白屏 fix(review): 详情页提交评分缺少stageId时回退使用项目详情的stageId feat(backend): ActivityPlayerDetailResponse.playerInfo 补充 avatarUrl/avatar,服务组装时填充用户头像 chore(dev): 启动脚本注入本地JWT密钥,重启前后端 --- backend/src/main/java/com/rongyichuang/dashboard/service/DashboardService.java | 130 +++++++++++++++++++++++++++++++++++++++--- 1 files changed, 119 insertions(+), 11 deletions(-) diff --git a/backend/src/main/java/com/rongyichuang/dashboard/service/DashboardService.java b/backend/src/main/java/com/rongyichuang/dashboard/service/DashboardService.java index b97fdf0..ae96164 100644 --- a/backend/src/main/java/com/rongyichuang/dashboard/service/DashboardService.java +++ b/backend/src/main/java/com/rongyichuang/dashboard/service/DashboardService.java @@ -1,12 +1,22 @@ 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 com.rongyichuang.dashboard.dto.response.DashboardStatsResponse; 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 缁熻鏁版嵁鏈嶅姟 @@ -14,15 +24,19 @@ @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; @@ -31,23 +45,117 @@ */ public DashboardStatsResponse getDashboardStats() { DashboardStatsResponse stats = new DashboardStatsResponse(); - + // 褰撳墠杩涜姣旇禌鏁伴噺锛堢姸鎬佷负1鐨勬瘮璧涳紝pid=0琛ㄧず涓绘瘮璧涳級 long activeActivities = activityRepository.countActiveActivities(); stats.setActiveActivities((int) activeActivities); - - // 鍙傝禌鎬讳汉鏁帮紙鐘舵�佷负1鐨勯�夋墜锛� + + // 鍙傝禌鎬讳汉鏁帮紙鐘舵�佷负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; } -} \ No newline at end of file + + /** + * 鑾峰彇鏈�杩戞姤鍚嶈秼鍔匡紙榛樿鏈�杩�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; + } +} -- Gitblit v1.8.0