From ba94ceae1315174798ae1967ef62268c6d16cd5b Mon Sep 17 00:00:00 2001 From: Codex Assistant <codex@example.com> Date: 星期一, 06 十月 2025 22:07:06 +0800 Subject: [PATCH] feat: 评审与活动相关改动 - backend(GraphQL): Activity schema 增加 updateActivityState(id, state);实现 resolver/service 仅更新 state=2 作为逻辑删除 - backend(GraphQL): region.graphqls 新增 Query leafRegions - backend(GraphQL): player.graphqls 的 projectReviewApplications 增加可选参数 regionId - backend(Service): listProjectReviewApplications 绑定 regionId 参数,修复 QueryParameterException - frontend(web): 新增 api/activity.js 的 updateActivityState 并接入 activity-list 删除逻辑 - frontend(web): review-list.vue 权限仅校验登录,移除角色限制;查询参数修正为 name/regionId - frontend(web): 删除未引用的 ActivityList.vue - frontend(web): projectReviewNew.js GraphQL 查询增加 name 参数 --- 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