From 58d9f460b2f8c34430285115e2557d18333c5cab Mon Sep 17 00:00:00 2001
From: Codex Assistant <codex@example.com>
Date: 星期三, 08 十月 2025 14:16:55 +0800
Subject: [PATCH] feat: 修复Player实体phone字段数据冗余问题并优化小程序报名逻辑

---
 backend/src/main/java/com/rongyichuang/judge/service/JudgeService.java |   99 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 93 insertions(+), 6 deletions(-)

diff --git a/backend/src/main/java/com/rongyichuang/judge/service/JudgeService.java b/backend/src/main/java/com/rongyichuang/judge/service/JudgeService.java
index 463b3ff..dfc89f0 100644
--- a/backend/src/main/java/com/rongyichuang/judge/service/JudgeService.java
+++ b/backend/src/main/java/com/rongyichuang/judge/service/JudgeService.java
@@ -2,6 +2,7 @@
 
 import com.rongyichuang.judge.dto.request.JudgeInput;
 import com.rongyichuang.judge.dto.response.JudgeResponse;
+import com.rongyichuang.judge.dto.response.JudgeStatsResponse;
 import com.rongyichuang.judge.entity.Judge;
 import com.rongyichuang.tag.entity.Tag;
 import com.rongyichuang.judge.repository.JudgeRepository;
@@ -12,12 +13,14 @@
 import com.rongyichuang.common.service.MediaService;
 import com.rongyichuang.common.exception.BusinessException;
 import com.rongyichuang.common.enums.MediaTargetType;
+import com.rongyichuang.common.util.UserContextUtil;
 import com.rongyichuang.tag.repository.TagRepository;
 import com.rongyichuang.user.service.UserService;
 import com.rongyichuang.user.entity.User;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.data.domain.Sort;
+import org.springframework.jdbc.core.JdbcTemplate;
 import java.util.Optional;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.util.StringUtils;
@@ -39,18 +42,23 @@
     private final MediaRepository mediaRepository;
     private final MediaService mediaService;
     private final UserService userService;
+    private final JdbcTemplate jdbcTemplate;
+    private final UserContextUtil userContextUtil;
     
     @Value("${app.media-url}")
     private String mediaBaseUrl;
 
     public JudgeService(JudgeRepository judgeRepository, TagRepository tagRepository, 
                        MediaRepository mediaRepository, MediaService mediaService,
-                       UserService userService) {
+                       UserService userService, JdbcTemplate jdbcTemplate,
+                       UserContextUtil userContextUtil) {
         this.judgeRepository = judgeRepository;
         this.tagRepository = tagRepository;
         this.mediaRepository = mediaRepository;
         this.mediaService = mediaService;
         this.userService = userService;
+        this.jdbcTemplate = jdbcTemplate;
+        this.userContextUtil = userContextUtil;
     }
 
     public List<JudgeResponse> findAll() {
@@ -79,6 +87,63 @@
         return judge.orElse(null);
     }
 
+    /**
+     * 鑾峰彇褰撳墠璇勫鐨勭粺璁℃暟鎹�
+     */
+    public JudgeStatsResponse getJudgeStats() {
+        log.info("鑾峰彇璇勫缁熻鏁版嵁");
+        
+        Long currentJudgeId = userContextUtil.getCurrentJudgeId();
+        if (currentJudgeId == null) {
+            throw new RuntimeException("褰撳墠鐢ㄦ埛涓嶆槸璇勫锛屾棤娉曟煡璇㈣瘎瀹$粺璁�");
+        }
+        
+        // 鏌ヨ鎴戞湭璇勫鐨勬暟閲�
+        String unReviewedSql = "SELECT COUNT(*) FROM t_activity_player ap " +
+                              "WHERE EXISTS (" +
+                              "  SELECT 1 FROM t_activity_judge aj " +
+                              "  WHERE ap.activity_id = aj.activity_id " +
+                              "  AND ap.stage_id = aj.stage_id " +
+                              "  AND aj.judge_id = ? " +
+                              ") " +
+                              "AND NOT EXISTS (" +
+                              "  SELECT 1 FROM t_activity_player_rating apr " +
+                              "  WHERE ap.id = apr.activity_player_id " +
+                              "  AND apr.judge_id = ? " +
+                              "  AND apr.state = 1 " +
+                              ") " +
+                              "AND ap.state = 1";
+        Integer unReviewedCount = jdbcTemplate.queryForObject(unReviewedSql, Integer.class, currentJudgeId, currentJudgeId);
+
+        // 鏌ヨ鎴戝凡璇勫鐨勬暟閲�
+        String reviewedSql = "SELECT COUNT(*) FROM t_activity_player ap " +
+                            "WHERE EXISTS (" +
+                            "  SELECT 1 FROM t_activity_judge aj " +
+                            "  WHERE ap.activity_id = aj.activity_id " +
+                            "  AND ap.stage_id = aj.stage_id " +
+                            "  AND aj.judge_id = ? " +
+                            ") " +
+                            "AND EXISTS (" +
+                            "  SELECT 1 FROM t_activity_player_rating apr " +
+                            "  WHERE ap.id = apr.activity_player_id " +
+                            "  AND apr.judge_id = ? " +
+                            "  AND apr.state = 1 " +
+                            ") " +
+                            "AND ap.state = 1";
+        Integer reviewedCount = jdbcTemplate.queryForObject(reviewedSql, Integer.class, currentJudgeId, currentJudgeId);
+
+        // 璁$畻鎬绘暟
+        Integer totalCount = (unReviewedCount != null ? unReviewedCount : 0) + (reviewedCount != null ? reviewedCount : 0);
+
+        log.info("璇勫缁熻鏁版嵁 - 寰呰瘎瀹�: {}, 宸茶瘎瀹�: {}, 鎬绘暟: {}", unReviewedCount, reviewedCount, totalCount);
+
+        return new JudgeStatsResponse(
+            unReviewedCount != null ? unReviewedCount : 0,
+            reviewedCount != null ? reviewedCount : 0,
+            totalCount
+        );
+    }
+
     @Transactional
     public JudgeResponse save(JudgeInput input) {
         Judge judge;
@@ -94,18 +159,28 @@
         }
 
         if (input.getId() != null) {
+            // 鏇存柊鐜版湁璇勫
             judge = judgeRepository.findById(input.getId())
                     .orElseThrow(() -> new BusinessException("璇勫涓嶅瓨鍦�"));
+            
+            // 妫�鏌ョ敤鎴稩D鏄惁琚叾浠栬瘎濮斾娇鐢�
+            Optional<Judge> existingJudgeByUserId = judgeRepository.findByUserId(user.getId());
+            if (existingJudgeByUserId.isPresent() && !existingJudgeByUserId.get().getId().equals(input.getId())) {
+                throw new BusinessException("璇ユ墜鏈哄彿宸茶鍏朵粬璇勫浣跨敤");
+            }
         } else {
+            // 鏂板璇勫
             judge = new Judge();
-            // 鏂板璇勫鏃舵鏌ユ墜鏈哄彿鏄惁宸插瓨鍦�
-            if (judgeRepository.existsByPhone(input.getPhone())) {
-                throw new BusinessException("PHONE_EXISTS", "鎵嬫満鍙风爜宸插瓨鍦紝璇蜂娇鐢ㄥ叾浠栨墜鏈哄彿鐮�");
+            
+            // 妫�鏌ヨ鐢ㄦ埛鏄惁宸叉槸璇勫
+            Optional<Judge> existingJudge = judgeRepository.findByUserId(user.getId());
+            if (existingJudge.isPresent()) {
+                throw new BusinessException("璇ユ墜鏈哄彿宸茶鍏朵粬璇勫浣跨敤");
             }
         }
 
         judge.setName(input.getName());
-        judge.setPhone(input.getPhone());
+        judge.setPhone(null); // 搴熷純judge.phone瀛楁锛岃缃负null
         judge.setGender(input.getGender());
         judge.setDescription(input.getDescription());
         judge.setTitle(input.getTitle());
@@ -139,7 +214,19 @@
         JudgeResponse response = new JudgeResponse();
         response.setId(judge.getId());
         response.setName(judge.getName());
-        response.setPhone(judge.getPhone());
+        
+        // 閫氳繃鍏宠仈鐨剈ser鑾峰彇phone
+        if (judge.getUserId() != null) {
+            Optional<User> userOpt = userService.findById(judge.getUserId());
+            if (userOpt.isPresent()) {
+                response.setPhone(userOpt.get().getPhone());
+            } else {
+                response.setPhone(null);
+            }
+        } else {
+            response.setPhone(null);
+        }
+        
         response.setGender(judge.getGender());
         response.setDescription(judge.getDescription());
         response.setTitle(judge.getTitle());

--
Gitblit v1.8.0