From b39a0502e7941ce966fda53664cf1b04ba52d65f Mon Sep 17 00:00:00 2001
From: lrj <owen.stl@gmail.com>
Date: 星期三, 01 十月 2025 17:30:24 +0800
Subject: [PATCH] 清理测试文件:删除所有test、debug、fix、check_开头的文件,为重构做准备

---
 web/src/views/review/index.vue                                                                       |    9 
 web/src/layout/index.vue                                                                             |   51 
 backend/src/main/java/com/rongyichuang/player/dto/response/ActivityPlayerApplicationResponse.java    |    8 
 backend/src/main/java/com/rongyichuang/player/dto/response/PlayerApplicationPageResponse.java        |   69 +
 web/src/api/player.js                                                                                |    9 
 backend/src/main/java/com/rongyichuang/judge/service/JudgeService.java                               |    2 
 web/src/views/activity/index.vue                                                                     |  194 ++
 web/src/api/projectReviewNew.js                                                                      |   32 
 backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerRatingService.java               |   25 
 web/UI规范.md                                                                                          |  300 ++++
 backend/src/main/resources/graphql/player.graphqls                                                   |   22 
 wx/pages/registration/registration.js                                                                |    2 
 web/public/logo.jpg                                                                                  |    0 
 web/src/views/player/index.vue                                                                       |  372 ++---
 web/src/views/project-review/index.vue                                                               |  375 +++--
 web/public/logo.svg                                                                                  |    4 
 web/src/views/RatingSchemeList.vue                                                                   |   55 
 backend/src/main/java/com/rongyichuang/user/resolver/UserResolver.java                               |    4 
 硬编码问题分析报告.md                                                                                         |  156 ++
 web/web_update.md                                                                                    |  179 ++
 backend/src/main/java/com/rongyichuang/player/dto/response/ProjectReviewApplicationPageResponse.java |   68 +
 web/src/views/judge/index.vue                                                                        |  142 ++
 web/ui_update.md                                                                                     |  342 +++++
 backend/src/main/java/com/rongyichuang/player/api/PlayerGraphqlApi.java                              |   25 
 web/src/views/carousel/index.vue                                                                     |   55 
 web/src/views/ActivityForm.vue                                                                       |    7 
 web/src/views/dashboard/index.vue                                                                    |  304 +++
 backend/src/main/java/com/rongyichuang/player/service/PlayerApplicationService.java                  |  140 ++
 /dev/null                                                                                            |  126 --
 web/src/views/competition-promotion/index.vue                                                        |  356 +++--
 query_data.js                                                                                        |   55 
 package.json                                                                                         |    2 
 web/src/router/index.ts                                                                              |   14 
 web/src/views/rating/index.vue                                                                       |  223 ++
 web/src/views/employee/index.vue                                                                     |   23 
 35 files changed, 2,857 insertions(+), 893 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 1f1c490..463b3ff 100644
--- a/backend/src/main/java/com/rongyichuang/judge/service/JudgeService.java
+++ b/backend/src/main/java/com/rongyichuang/judge/service/JudgeService.java
@@ -18,7 +18,7 @@
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.data.domain.Sort;
-import org.springframework.data.domain.Sort;
+import java.util.Optional;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.util.StringUtils;
 import org.slf4j.Logger;
diff --git a/backend/src/main/java/com/rongyichuang/player/api/PlayerGraphqlApi.java b/backend/src/main/java/com/rongyichuang/player/api/PlayerGraphqlApi.java
index adce16f..8a53c4b 100644
--- a/backend/src/main/java/com/rongyichuang/player/api/PlayerGraphqlApi.java
+++ b/backend/src/main/java/com/rongyichuang/player/api/PlayerGraphqlApi.java
@@ -1,9 +1,12 @@
 package com.rongyichuang.player.api;
 
+import com.rongyichuang.common.dto.PageResponse;
 import com.rongyichuang.player.dto.input.ActivityPlayerRatingInput;
 import com.rongyichuang.player.dto.ActivityRegistrationInput;
 import com.rongyichuang.player.dto.response.ActivityPlayerApplicationResponse;
 import com.rongyichuang.player.dto.response.ActivityPlayerDetailResponse;
+import com.rongyichuang.player.dto.response.ProjectReviewApplicationPageResponse;
+import com.rongyichuang.player.dto.response.PlayerApplicationPageResponse;
 import com.rongyichuang.player.dto.ActivityRegistrationResponse;
 import com.rongyichuang.player.dto.response.JudgeRatingStatusResponse;
 import com.rongyichuang.player.dto.response.CurrentJudgeRatingResponse;
@@ -53,14 +56,32 @@
     }
 
     @QueryMapping
-    public List<ActivityPlayerApplicationResponse> activityPlayerApplications(
+    public PlayerApplicationPageResponse activityPlayerApplications(
             @Argument String name,
             @Argument Long activityId,
             @Argument Integer state,
             @Argument Integer page,
             @Argument Integer size
     ) {
-        return service.listApplications(name, activityId, state, page, size);
+        PageResponse<ActivityPlayerApplicationResponse> pageResponse = 
+            service.listApplications(name, activityId, state, page, size);
+        return PlayerApplicationPageResponse.from(pageResponse);
+    }
+
+    /**
+     * 椤圭洰璇勫涓撶敤鏌ヨ锛屽寘鍚墍鏈夐樁娈垫暟鎹紙鍖呮嫭澶嶈禌銆佸喅璧涳級
+     */
+    @QueryMapping
+    public ProjectReviewApplicationPageResponse projectReviewApplications(
+            @Argument String name,
+            @Argument Long activityId,
+            @Argument Integer state,
+            @Argument Integer page,
+            @Argument Integer size
+    ) {
+        PageResponse<ActivityPlayerApplicationResponse> pageResponse = 
+            service.listProjectReviewApplications(name, activityId, state, page, size);
+        return ProjectReviewApplicationPageResponse.from(pageResponse);
     }
 
     /**
diff --git a/backend/src/main/java/com/rongyichuang/player/dto/response/ActivityPlayerApplicationResponse.java b/backend/src/main/java/com/rongyichuang/player/dto/response/ActivityPlayerApplicationResponse.java
index 1651395..ac1b016 100644
--- a/backend/src/main/java/com/rongyichuang/player/dto/response/ActivityPlayerApplicationResponse.java
+++ b/backend/src/main/java/com/rongyichuang/player/dto/response/ActivityPlayerApplicationResponse.java
@@ -8,6 +8,8 @@
     private String phone;
     private String applyTime; // ISO瀛楃涓�
     private Integer state;
+    private Integer ratingCount; // 璇勫娆℃暟
+    private Double averageScore; // 骞冲潎鍒�
 
     public Long getId() { return id; }
     public void setId(Long id) { this.id = id; }
@@ -29,4 +31,10 @@
 
     public Integer getState() { return state; }
     public void setState(Integer state) { this.state = state; }
+
+    public Integer getRatingCount() { return ratingCount; }
+    public void setRatingCount(Integer ratingCount) { this.ratingCount = ratingCount; }
+
+    public Double getAverageScore() { return averageScore; }
+    public void setAverageScore(Double averageScore) { this.averageScore = averageScore; }
 }
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/player/dto/response/PlayerApplicationPageResponse.java b/backend/src/main/java/com/rongyichuang/player/dto/response/PlayerApplicationPageResponse.java
new file mode 100644
index 0000000..3b36094
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/player/dto/response/PlayerApplicationPageResponse.java
@@ -0,0 +1,69 @@
+package com.rongyichuang.player.dto.response;
+
+import com.rongyichuang.common.dto.PageResponse;
+
+import java.util.List;
+
+/**
+ * 鎶ュ悕瀹℃牳鍒嗛〉鍝嶅簲绫诲瀷
+ */
+public class PlayerApplicationPageResponse {
+    private List<ActivityPlayerApplicationResponse> content;
+    private int totalElements;
+    private int page;
+    private int size;
+
+    public PlayerApplicationPageResponse() {}
+
+    public PlayerApplicationPageResponse(List<ActivityPlayerApplicationResponse> content, int totalElements, int page, int size) {
+        this.content = content;
+        this.totalElements = totalElements;
+        this.page = page;
+        this.size = size;
+    }
+
+    /**
+     * 浠嶱ageResponse杞崲
+     */
+    public static PlayerApplicationPageResponse from(PageResponse<ActivityPlayerApplicationResponse> pageResponse) {
+        return new PlayerApplicationPageResponse(
+            pageResponse.getContent(),
+            Math.toIntExact(pageResponse.getTotalElements()),
+            pageResponse.getPage(),
+            pageResponse.getSize()
+        );
+    }
+
+    // Getters and Setters
+    public List<ActivityPlayerApplicationResponse> getContent() {
+        return content;
+    }
+
+    public void setContent(List<ActivityPlayerApplicationResponse> content) {
+        this.content = content;
+    }
+
+    public int getTotalElements() {
+        return totalElements;
+    }
+
+    public void setTotalElements(int totalElements) {
+        this.totalElements = totalElements;
+    }
+
+    public int getPage() {
+        return page;
+    }
+
+    public void setPage(int page) {
+        this.page = page;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public void setSize(int size) {
+        this.size = size;
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/player/dto/response/ProjectReviewApplicationPageResponse.java b/backend/src/main/java/com/rongyichuang/player/dto/response/ProjectReviewApplicationPageResponse.java
new file mode 100644
index 0000000..eddb0ed
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/player/dto/response/ProjectReviewApplicationPageResponse.java
@@ -0,0 +1,68 @@
+package com.rongyichuang.player.dto.response;
+
+import com.rongyichuang.common.dto.PageResponse;
+import java.util.List;
+
+/**
+ * 椤圭洰璇勫鍒嗛〉鍝嶅簲绫诲瀷
+ */
+public class ProjectReviewApplicationPageResponse {
+    
+    private List<ActivityPlayerApplicationResponse> content;
+    private Integer totalElements;
+    private Integer page;
+    private Integer size;
+    
+    public ProjectReviewApplicationPageResponse() {}
+    
+    public ProjectReviewApplicationPageResponse(List<ActivityPlayerApplicationResponse> content, 
+                                               Long totalElements, Integer page, Integer size) {
+        this.content = content;
+        this.totalElements = totalElements != null ? totalElements.intValue() : 0;
+        this.page = page;
+        this.size = size;
+    }
+    
+    // 浠庨�氱敤PageResponse杞崲
+    public static ProjectReviewApplicationPageResponse from(PageResponse<ActivityPlayerApplicationResponse> pageResponse) {
+        return new ProjectReviewApplicationPageResponse(
+            pageResponse.getContent(),
+            pageResponse.getTotalElements(),
+            pageResponse.getPage(),
+            pageResponse.getSize()
+        );
+    }
+    
+    // Getters and Setters
+    public List<ActivityPlayerApplicationResponse> getContent() {
+        return content;
+    }
+    
+    public void setContent(List<ActivityPlayerApplicationResponse> content) {
+        this.content = content;
+    }
+    
+    public Integer getTotalElements() {
+        return totalElements;
+    }
+    
+    public void setTotalElements(Integer totalElements) {
+        this.totalElements = totalElements;
+    }
+    
+    public Integer getPage() {
+        return page;
+    }
+    
+    public void setPage(Integer page) {
+        this.page = page;
+    }
+    
+    public Integer getSize() {
+        return size;
+    }
+    
+    public void setSize(Integer size) {
+        this.size = size;
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerRatingService.java b/backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerRatingService.java
index 6726e7c..f3b8ee9 100644
--- a/backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerRatingService.java
+++ b/backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerRatingService.java
@@ -259,20 +259,25 @@
             Long judgeId = ((Number) row.get("id")).longValue();
             String judgeName = (String) row.get("name");
             
-            // 鏌ユ壘璇ヨ瘎濮旂殑璇勫垎
-            Optional<ActivityPlayerRating> ratingOpt = activityPlayerRatingRepository
-                    .findByActivityPlayerIdAndJudgeId(activityPlayerId, judgeId);
+            // 鏌ユ壘璇ヨ瘎濮旂殑璇勫垎璁板綍鏁伴噺锛堜粠t_activity_player_rating琛ㄦ寜activity_player_id鍜宩udge_id鏌ヨ锛�
+            String ratingCountSql = "SELECT COUNT(*) FROM t_activity_player_rating WHERE activity_player_id = ? AND judge_id = ?";
+            Integer ratingCount = jdbcTemplate.queryForObject(ratingCountSql, Integer.class, activityPlayerId, judgeId);
             
-            Boolean hasRated = false;
+            Boolean hasRated = ratingCount != null && ratingCount > 0; // 璇勫娆℃暟>0琛ㄧず宸茶瘎瀹�
             String ratingTime = null;
             BigDecimal totalScore = null;
             
-            if (ratingOpt.isPresent()) {
-                ActivityPlayerRating rating = ratingOpt.get();
-                hasRated = rating.getState() != null && rating.getState() == 1; // 浣跨敤state鍒ゆ柇鏄惁宸茶瘎鍒�
-                totalScore = rating.getTotalScore();
-                if (rating.getUpdateTime() != null) {
-                    ratingTime = rating.getUpdateTime().toString();
+            // 濡傛灉宸茶瘎鍒嗭紝鑾峰彇鏈�鏂扮殑璇勫垎璁板綍
+            if (hasRated) {
+                Optional<ActivityPlayerRating> ratingOpt = activityPlayerRatingRepository
+                        .findByActivityPlayerIdAndJudgeId(activityPlayerId, judgeId);
+                
+                if (ratingOpt.isPresent()) {
+                    ActivityPlayerRating rating = ratingOpt.get();
+                    totalScore = rating.getTotalScore();
+                    if (rating.getUpdateTime() != null) {
+                        ratingTime = rating.getUpdateTime().toString();
+                    }
                 }
             }
             
diff --git a/backend/src/main/java/com/rongyichuang/player/service/PlayerApplicationService.java b/backend/src/main/java/com/rongyichuang/player/service/PlayerApplicationService.java
index 397796e..03f19a7 100644
--- a/backend/src/main/java/com/rongyichuang/player/service/PlayerApplicationService.java
+++ b/backend/src/main/java/com/rongyichuang/player/service/PlayerApplicationService.java
@@ -1,5 +1,6 @@
 package com.rongyichuang.player.service;
 
+import com.rongyichuang.common.dto.PageResponse;
 import com.rongyichuang.player.dto.response.ActivityPlayerApplicationResponse;
 import jakarta.persistence.EntityManager;
 import jakarta.persistence.PersistenceContext;
@@ -16,20 +17,29 @@
 
     /**
      * 鏌ヨ娲诲姩鎶ュ悕淇℃伅
+     * 鎶ュ悕瀹℃牳椤甸潰鍙樉绀烘捣閫夐樁娈电殑鏁版嵁锛屼笉鍖呭惈澶嶈禌绛夊悗缁樁娈�
      * 褰撲紶鍏ctivityId鏃讹紝鏌ヨ璇ユ瘮璧涗笅绗竴涓樁娈碉紙sort_order=1锛夌殑鎶ュ悕椤圭洰
      */
     @SuppressWarnings("unchecked")
-    public List<ActivityPlayerApplicationResponse> listApplications(String name, Long activityId, Integer state, Integer page, Integer size) {
+    public PageResponse<ActivityPlayerApplicationResponse> listApplications(String name, Long activityId, Integer state, Integer page, Integer size) {
         String baseSql =
-            "SELECT ap.id, p.name AS player_name, stage.name AS activity_name, ap.project_name AS project_name, p.phone AS phone, ap.create_time AS apply_time, ap.state AS state " +
+            "SELECT ap.id, CONCAT(p.name, '锛�', ap.project_name, '锛�') AS player_name, parent.name AS activity_name, ap.project_name AS project_name, p.phone AS phone, ap.create_time AS apply_time, ap.state AS state " +
             "FROM t_activity_player ap " +
             "JOIN t_player p ON p.id = ap.player_id " +
-            "JOIN t_activity stage ON stage.id = ap.stage_id ";
+            "JOIN t_activity stage ON stage.id = ap.stage_id " +
+            "JOIN t_activity parent ON parent.id = stage.pid ";
         
         StringBuilder whereClause = new StringBuilder();
         boolean hasCondition = false;
         
+        // 榛樿鍙樉绀虹涓�闃舵鐨勬暟鎹紙鍩轰簬sort_order=1锛夛紝閬垮厤纭紪鐮侀樁娈靛悕绉�
+        whereClause.append("stage.sort_order = 1");
+        hasCondition = true;
+        
         if (name != null && !name.isEmpty()) {
+            if (hasCondition) {
+                whereClause.append(" AND ");
+            }
             whereClause.append("p.name LIKE CONCAT('%', :name, '%')");
             hasCondition = true;
         }
@@ -39,7 +49,7 @@
                 whereClause.append(" AND ");
             }
             // 鏌ヨ鎸囧畾涓绘瘮璧涚殑绗竴闃舵鎶ュ悕椤圭洰锛歛ctivity_id=涓绘瘮璧汭D, stage_id=绗竴闃舵ID
-            whereClause.append("ap.activity_id = :activityId AND stage.pid = :activityId AND stage.sort_order = 1");
+            whereClause.append("ap.activity_id = :activityId AND ap.stage_id = stage.id AND stage.pid = :activityId AND stage.sort_order = 1");
             hasCondition = true;
         }
         
@@ -81,8 +91,128 @@
             dto.setApplyTime(r[5] != null ? r[5].toString() : "");
             // 鏄犲皠鐘舵�侊細浣跨敤 t_activity_player.state锛�0=鏈鏍革紝1=瀹℃牳閫氳繃锛�2=瀹℃牳椹冲洖锛�
             dto.setState(r[6] != null ? Integer.valueOf(r[6].toString()) : 0);
+            // 鏄犲皠璇勫缁熻鏁版嵁
+            dto.setRatingCount(r[7] != null ? Integer.valueOf(r[7].toString()) : 0);
+            dto.setAverageScore(r[8] != null ? Double.valueOf(r[8].toString()) : null);
             list.add(dto);
         }
-        return list;
+        
+        // 鑾峰彇鎬绘暟
+        String countSql = "SELECT COUNT(*) " + baseSql.substring(baseSql.indexOf("FROM")) + where;
+        var countQuery = em.createNativeQuery(countSql);
+        if (name != null && !name.isEmpty()) {
+            countQuery.setParameter("name", name);
+        }
+        if (activityId != null) {
+            countQuery.setParameter("activityId", activityId);
+        }
+        if (state != null) {
+            countQuery.setParameter("state", state);
+        }
+        long total = ((Number) countQuery.getSingleResult()).longValue();
+        
+        return new PageResponse<>(list, total, page != null ? page : 1, size != null ? size : 10);
+    }
+
+    /**
+     * 椤圭洰璇勫涓撶敤鏌ヨ锛屽寘鍚墍鏈夐樁娈垫暟鎹紙鍖呮嫭澶嶈禌銆佸喅璧涳級
+     * 涓巐istApplications鐨勫尯鍒細涓嶈繃婊ゅ璧涘拰鍐宠禌闃舵
+     */
+    @SuppressWarnings("unchecked")
+    public PageResponse<ActivityPlayerApplicationResponse> listProjectReviewApplications(String name, Long activityId, Integer state, Integer page, Integer size) {
+        String baseSql =
+            "SELECT ap.id, CONCAT(p.name, '锛�', ap.project_name, '锛�') AS player_name, stage.name AS activity_name, ap.project_name AS project_name, p.phone AS phone, ap.create_time AS apply_time, ap.state AS state, " +
+            "COALESCE(rating_stats.rating_count, 0) AS rating_count, rating_stats.average_score " +
+            "FROM t_activity_player ap " +
+            "JOIN t_player p ON p.id = ap.player_id " +
+            "JOIN t_activity stage ON stage.id = ap.stage_id " +
+            "LEFT JOIN (" +
+            "  SELECT activity_player_id, COUNT(*) AS rating_count, AVG(total_score) AS average_score " +
+            "  FROM t_activity_player_rating " +
+            "  WHERE state = 1 " +
+            "  GROUP BY activity_player_id" +
+            ") rating_stats ON rating_stats.activity_player_id = ap.id ";
+        
+        StringBuilder whereClause = new StringBuilder();
+        boolean hasCondition = false;
+        
+        // 椤圭洰璇勫鏌ヨ锛氱洿鎺ユ牴鎹樁娈礗D鏌ヨ锛屼笖榛樿鍙煡璇㈠鏍搁�氳繃鐨勬暟鎹�
+        
+        if (name != null && !name.isEmpty()) {
+            if (hasCondition) {
+                whereClause.append(" AND ");
+            }
+            whereClause.append("p.name LIKE CONCAT('%', :name, '%')");
+            hasCondition = true;
+        }
+        
+        if (activityId != null) {
+            if (hasCondition) {
+                whereClause.append(" AND ");
+            }
+            // 鐩存帴鏌ヨ鎸囧畾闃舵ID鐨勬姤鍚嶉」鐩�
+            whereClause.append("ap.stage_id = :activityId");
+            hasCondition = true;
+        }
+        
+        // 榛樿鍙煡璇㈠鏍搁�氳繃鐨勬暟鎹� (state = 1)
+        if (hasCondition) {
+            whereClause.append(" AND ");
+        }
+        whereClause.append("ap.state = 1");
+        hasCondition = true;
+        
+        // 濡傛灉浼犲叆浜唖tate鍙傛暟锛屽垯瑕嗙洊榛樿鐨剆tate=1鏉′欢
+        if (state != null) {
+            // 绉婚櫎鏈�鍚庢坊鍔犵殑 "ap.state = 1" 鏉′欢
+            String whereStr = whereClause.toString();
+            whereStr = whereStr.replace(" AND ap.state = 1", "");
+            whereClause = new StringBuilder(whereStr);
+            
+            if (hasCondition && !whereStr.isEmpty()) {
+                whereClause.append(" AND ");
+            }
+            whereClause.append("ap.state = :state");
+        }
+        
+        String where = hasCondition ? "WHERE " + whereClause.toString() + " " : "";
+        String order = "ORDER BY ap.create_time DESC ";
+        String limit = "";
+        if (page != null && size != null && page > 0 && size > 0) {
+            int offset = (page - 1) * size;
+            limit = "LIMIT " + size + " OFFSET " + offset + " ";
+        }
+
+        var q = em.createNativeQuery(baseSql + where + order + limit);
+        if (name != null && !name.isEmpty()) {
+            q.setParameter("name", name);
+        }
+        if (activityId != null) {
+            q.setParameter("activityId", activityId);
+        }
+        if (state != null) {
+            q.setParameter("state", state);
+        }
+        List<Object[]> rows = q.getResultList();
+        List<ActivityPlayerApplicationResponse> list = new ArrayList<>();
+        for (Object[] r : rows) {
+            ActivityPlayerApplicationResponse dto = new ActivityPlayerApplicationResponse();
+            dto.setId(r[0] != null ? Long.valueOf(r[0].toString()) : null); // activity_player_id
+            dto.setPlayerName(r[1] != null ? r[1].toString() : "");
+            dto.setActivityName(r[2] != null ? r[2].toString() : "");
+            dto.setProjectName(r[3] != null ? r[3].toString() : ""); // project_name
+            dto.setPhone(r[4] != null ? r[4].toString() : "");
+            dto.setApplyTime(r[5] != null ? r[5].toString() : "");
+            // 鏄犲皠鐘舵�侊細浣跨敤 t_activity_player.state锛�0=鏈鏍革紝1=瀹℃牳閫氳繃锛�2=瀹℃牳椹冲洖锛�
+            dto.setState(r[6] != null ? Integer.valueOf(r[6].toString()) : 0);
+            // 鏄犲皠璇勫缁熻鏁版嵁
+            dto.setRatingCount(r[7] != null ? Integer.valueOf(r[7].toString()) : 0);
+            dto.setAverageScore(r[8] != null ? Double.valueOf(r[8].toString()) : null);
+            list.add(dto);
+        }
+        
+        // 鍒涘缓鍒嗛〉鍝嶅簲
+        long totalElements = list.size();
+        return new PageResponse<>(list, totalElements, page, size);
     }
 }
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/user/resolver/UserResolver.java b/backend/src/main/java/com/rongyichuang/user/resolver/UserResolver.java
index dec68fa..2c597ef 100644
--- a/backend/src/main/java/com/rongyichuang/user/resolver/UserResolver.java
+++ b/backend/src/main/java/com/rongyichuang/user/resolver/UserResolver.java
@@ -133,7 +133,7 @@
     @QueryMapping
     public UserStats userStats() {
         try {
-            Long userId = UserContextUtil.getCurrentUserId();
+            Long userId = userContextUtil.getCurrentUserId();
             if (userId == null) {
                 return null;
             }
@@ -157,7 +157,7 @@
     @QueryMapping
     public List<UserRegistration> myRegistrations(@Argument Integer limit) {
         try {
-            Long userId = UserContextUtil.getCurrentUserId();
+            Long userId = userContextUtil.getCurrentUserId();
             if (userId == null) {
                 return new ArrayList<>();
             }
diff --git a/backend/src/main/resources/graphql/player.graphqls b/backend/src/main/resources/graphql/player.graphqls
index 6246211..6e11257 100644
--- a/backend/src/main/resources/graphql/player.graphqls
+++ b/backend/src/main/resources/graphql/player.graphqls
@@ -1,5 +1,7 @@
 extend type Query {
-  activityPlayerApplications(name: String, activityId: ID, state: Int, page: Int, size: Int): [ActivityPlayerApplicationResponse!]!
+  activityPlayerApplications(name: String, activityId: ID, state: Int, page: Int, size: Int): PlayerApplicationPageResponse!
+  # 鏂板锛氶」鐩瘎瀹′笓鐢ㄦ煡璇紝鍖呭惈鎵�鏈夐樁娈垫暟鎹紙鍖呮嫭澶嶈禌銆佸喅璧涳級
+  projectReviewApplications(name: String, activityId: ID, state: Int, page: Int, size: Int): ProjectReviewApplicationPageResponse!
   activityPlayerDetail(id: ID!): ActivityPlayerDetailResponse
   
   # 鎶ュ悕鐘舵�佹煡璇�
@@ -39,6 +41,8 @@
   phone: String
   applyTime: String!
   state: Int
+  ratingCount: Int
+  averageScore: Float
 }
 
 # 姣旇禌鎶ュ悕璇︽儏鍝嶅簲锛堢敤浜庤瘎鍒嗛〉闈級
@@ -55,6 +59,22 @@
   ratingForm: RatingFormResponse
 }
 
+# 鎶ュ悕瀹℃牳鍒嗛〉鍝嶅簲绫诲瀷
+type PlayerApplicationPageResponse {
+    content: [ActivityPlayerApplicationResponse!]!
+    totalElements: Int!
+    page: Int!
+    size: Int!
+}
+
+# 椤圭洰璇勫鍒嗛〉鍝嶅簲绫诲瀷
+type ProjectReviewApplicationPageResponse {
+    content: [ActivityPlayerApplicationResponse!]!
+    totalElements: Int!
+    page: Int!
+    size: Int!
+}
+
 # 瀛﹀憳淇℃伅鍝嶅簲
 type PlayerInfoResponse {
     id: ID
diff --git a/package.json b/package.json
index ceae39e..0c44027 100644
--- a/package.json
+++ b/package.json
@@ -2,6 +2,6 @@
   "dependencies": {
     "axios": "^1.12.2",
     "mysql2": "^3.15.1",
-    "node-fetch": "^3.3.2"
+    "node-fetch": "^2.7.0"
   }
 }
diff --git a/query_data.js b/query_data.js
new file mode 100644
index 0000000..e58d97b
--- /dev/null
+++ b/query_data.js
@@ -0,0 +1,55 @@
+const mysql = require('mysql2/promise');
+
+async function queryData() {
+  const connection = await mysql.createConnection({
+    host: '139.155.104.10',
+    port: 3306,
+    user: 'ryc',
+    password: 'KiYap3E8X8RLcM6T',
+    database: 'ryc'
+  });
+
+  try {
+    console.log('杩炴帴鏁版嵁搴撴垚鍔燂紒');
+    
+    // 鏌ヨstage_id=8鐨勯樁娈典俊鎭�
+    console.log('\n=== 鏌ヨ t_activity 琛ㄤ腑 id=8 鐨勯樁娈典俊鎭� ===');
+    const [rows1] = await connection.execute(
+      'SELECT id, pid, name, sort_order FROM t_activity WHERE id = ?',
+      [8]
+    );
+    console.log(`鎵惧埌 ${rows1.length} 鏉¤褰曪細`);
+    rows1.forEach(row => {
+      console.log(`ID: ${row.id}, PID: ${row.pid}, Name: ${row.name}, Sort: ${row.sort_order}`);
+    });
+
+    // 鏌ヨactivity_id=6鐨勬墍鏈夐樁娈�
+    console.log('\n=== 鏌ヨ activity_id=6 鐨勬墍鏈夐樁娈� ===');
+    const [rows2] = await connection.execute(
+      'SELECT id, pid, name, sort_order FROM t_activity WHERE pid = ? ORDER BY sort_order',
+      [6]
+    );
+    console.log(`鎵惧埌 ${rows2.length} 鏉¢樁娈佃褰曪細`);
+    rows2.forEach(row => {
+      console.log(`ID: ${row.id}, PID: ${row.pid}, Name: ${row.name}, Sort: ${row.sort_order}`);
+    });
+
+    // 鏌ヨ涓绘瘮璧涗俊鎭�
+    console.log('\n=== 鏌ヨ涓绘瘮璧� id=6 鐨勪俊鎭� ===');
+    const [rows3] = await connection.execute(
+      'SELECT id, pid, name FROM t_activity WHERE id = ?',
+      [6]
+    );
+    console.log(`鎵惧埌 ${rows3.length} 鏉¤褰曪細`);
+    rows3.forEach(row => {
+      console.log(`ID: ${row.id}, PID: ${row.pid}, Name: ${row.name}`);
+    });
+
+  } catch (error) {
+    console.error('鏌ヨ鍑洪敊锛�', error);
+  } finally {
+    await connection.end();
+  }
+}
+
+queryData();
\ No newline at end of file
diff --git "a/web/UI\350\247\204\350\214\203.md" "b/web/UI\350\247\204\350\214\203.md"
new file mode 100644
index 0000000..069783b
--- /dev/null
+++ "b/web/UI\350\247\204\350\214\203.md"
@@ -0,0 +1,300 @@
+# 钃夋槗鍒涚鐞嗙郴缁� UI 璁捐瑙勮寖
+
+## 1. 鑹插僵瑙勮寖
+
+### 1.1 涓昏壊璋�
+- **涓昏摑鑹�**: `#409EFF` - 鐢ㄤ簬涓昏鎸夐挳銆侀摼鎺ャ�佸浘鏍�
+- **娴呰摑鑹�**: `#66B1FF` - 鐢ㄤ簬鎮仠鐘舵��
+- **娣辫摑鑹�**: `#1E3A8A` - 鐢ㄤ簬婵�娲荤姸鎬佹枃瀛�
+
+### 1.2 鑳屾櫙鑹�
+- **涓昏儗鏅�**: `#FFFFFF` - 椤甸潰涓昏鑳屾櫙鑹�
+- **鍗$墖鑳屾櫙**: `#FFFFFF` - 鍗$墖銆佽〃鏍肩瓑缁勪欢鑳屾櫙
+- **鎮仠鑳屾櫙**: `#EBF4FF` - 鑿滃崟椤规偓鍋滆儗鏅�
+- **婵�娲昏儗鏅�**: `#3B82F6` - 鑿滃崟椤规縺娲昏儗鏅�
+
+### 1.3 鏂囧瓧棰滆壊
+- **涓绘枃瀛�**: `#333333` - 鏍囬銆侀噸瑕佹枃瀛�
+- **娆¤鏂囧瓧**: `#666666` - 鏅�氭枃瀛椼�佽彍鍗曢」
+- **娴呰壊鏂囧瓧**: `#999999` - 杈呭姪淇℃伅
+- **鐧借壊鏂囧瓧**: `#FFFFFF` - 婵�娲荤姸鎬佹枃瀛�
+
+### 1.4 杈规棰滆壊
+- **娴呰竟妗�**: `#E5E7EB` - 鍒嗛殧绾裤�佸崱鐗囪竟妗�
+- **涓瓑杈规**: `#D1D5DB` - 琛ㄦ牸杈规
+
+### 1.5 鐘舵�侀鑹�
+- **鎴愬姛/宸插彂甯�**: `#67C23A` - 缁胯壊
+- **璀﹀憡/鏈彂甯�**: `#E6A23C` - 榛勮壊  
+- **鍗遍櫓/鍏抽棴**: `#F56C6C` - 绾㈣壊
+
+## 2. 甯冨眬瑙勮寖
+
+### 2.1 鏁翠綋甯冨眬
+- **椤堕儴鏍忛珮搴�**: 60px
+- **渚ц竟鏍忓搴�**: 200px
+- **鍐呭鍖哄煙**: 鑷�傚簲鍓╀綑绌洪棿
+
+### 2.2 闂磋窛瑙勮寖
+- **椤甸潰鍐呰竟璺�**: 24px
+- **鍗$墖闂磋窛**: 24px
+- **缁勪欢闂磋窛**: 16px
+- **灏忛棿璺�**: 8px
+
+### 2.3 鍦嗚瑙勮寖
+- **鍗$墖鍦嗚**: 8px
+- **鎸夐挳鍦嗚**: 6px
+- **鐘舵�佹爣绛惧渾瑙�**: 4px
+
+## 3. 缁勪欢瑙勮寖
+
+### 3.1 椤堕儴鏍� (Header)
+- **鑳屾櫙鑹�**: `#FFFFFF`
+- **楂樺害**: 60px
+- **杈规**: 搴曢儴 1px `#E5E7EB`
+- **鍐呭**: 宸︿晶logo+鏍囬锛屽彸渚х敤鎴蜂俊鎭�
+
+### 3.2 渚ц竟鏍� (Sidebar)
+- **鑳屾櫙鑹�**: `#FFFFFF`
+- **瀹藉害**: 200px
+- **杈规**: 鍙充晶 1px `#E5E7EB`
+- **鑿滃崟椤�**:
+  - 榛樿: 閫忔槑鑳屾櫙锛宍#666666` 鏂囧瓧
+  - 鎮仠: `#EBF4FF` 鑳屾櫙锛宍#1E3A8A` 鏂囧瓧
+  - 婵�娲�: `#3B82F6` 鑳屾櫙锛宍#FFFFFF` 鏂囧瓧
+  - 鍦嗚: 6px锛屽杈硅窛: 2px 8px
+
+### 3.3 缁熻鍗$墖
+- **鑳屾櫙鑹�**: `#FFFFFF`
+- **鍦嗚**: 8px
+- **闃村奖**: `0 2px 8px rgba(0, 0, 0, 0.1)`
+- **鍐呰竟璺�**: 24px
+- **鍥炬爣瀹瑰櫒**: 48px鍦嗗舰锛屼笉鍚屼富棰樿壊鑳屾櫙
+- **鏁板瓧瀛椾綋**: 32px锛岀矖浣�
+- **鏍囬瀛椾綋**: 14px锛宍#666666`
+
+### 3.4 琛ㄦ牸
+- **鑳屾櫙鑹�**: `#FFFFFF`
+- **杈规**: `#E5E7EB`
+- **鏂戦┈绾�**: 鍋舵暟琛� `#FAFAFA`
+- **琛ㄥご**: `#F8F9FA` 鑳屾櫙锛宍#333333` 鏂囧瓧
+- **琛岄珮**: 閫備腑锛屼繚璇佸彲璇绘��
+
+### 3.5 鎿嶄綔鎸夐挳
+- **閾炬帴鏍峰紡**: 绾枃瀛楋紝鏃犺儗鏅�
+- **棰滆壊**: `#409EFF`
+- **鎮仠**: `#66B1FF`锛屼笅鍒掔嚎
+- **闂磋窛**: 宸﹀彸 8px
+
+### 3.6 鐘舵�佹爣绛�
+- **宸插彂甯�**: `#67C23A` 鏂囧瓧锛宍#F0F9FF` 鑳屾櫙
+- **鏈彂甯�**: `#E6A23C` 鏂囧瓧锛宍#FDF6EC` 鑳屾櫙
+- **鍏抽棴**: `#F56C6C` 鏂囧瓧锛宍#FEF0F0` 鑳屾櫙
+- **鍐呰竟璺�**: 4px 8px
+- **鍦嗚**: 4px
+
+## 4. 鍥炬爣瑙勮寖
+
+### 4.1 Logo
+- **灏哄**: 32x32px
+- **鏍煎紡**: SVG
+- **浣嶇疆**: 椤堕儴鏍忓乏渚э紝鏍囬鍓�
+- **闂磋窛**: 涓庢爣棰橀棿璺� 8px
+
+### 4.2 鍔熻兘鍥炬爣
+- **缁熻鍗$墖鍥炬爣**: Element Plus 鍥炬爣搴�
+- **灏哄**: 24px
+- **棰滆壊**: 鐧借壊 (鍦ㄥ僵鑹茶儗鏅笂)
+
+## 5. 瀛椾綋瑙勮寖
+
+### 5.1 瀛椾綋澶у皬
+- **椤甸潰鏍囬**: 18px锛岀矖浣�
+- **鍗$墖鏍囬**: 16px锛岀矖浣�
+- **缁熻鏁板瓧**: 32px锛岀矖浣�
+- **姝f枃**: 14px
+- **杈呭姪鏂囧瓧**: 12px
+
+### 5.2 瀛椾綋鏉冮噸
+- **鏍囬**: 700 (bold)
+- **閲嶈鏁板瓧**: 700 (bold)
+- **姝f枃**: 400 (normal)
+
+## 6. 鍝嶅簲寮忚鑼�
+
+### 6.1 鏂偣
+- **绉诲姩绔�**: < 768px
+- **骞虫澘**: 768px - 1024px
+- **妗岄潰**: > 1024px
+
+### 6.2 閫傞厤鍘熷垯
+- 绉诲姩绔紭鍏堣�冭檻鍨傜洿甯冨眬
+- 缁熻鍗$墖鍦ㄥ皬灞忓箷涓婂爢鍙犳樉绀�
+- 琛ㄦ牸鍦ㄥ皬灞忓箷涓婂彲妯悜婊氬姩
+
+## 7. 浜や簰瑙勮寖
+
+### 7.1 鎮仠鏁堟灉
+- **鑿滃崟椤�**: 鑳屾櫙鑹插彉鍖� + 鏂囧瓧棰滆壊鍙樺寲
+- **鎸夐挳/閾炬帴**: 棰滆壊鍙樺寲 + 涓嬪垝绾�
+- **鍗$墖**: 杞诲井闃村奖澧炲己
+
+### 7.2 鐐瑰嚮鍙嶉
+- **鑿滃崟椤�**: 绔嬪嵆鍒囨崲鍒版縺娲荤姸鎬�
+- **鎸夐挳**: 閫傚綋鐨勭偣鍑诲弽棣堝姩鐢�
+- **閾炬帴**: 棰滆壊鍙樺寲
+
+## 8. 闃村奖瑙勮寖
+
+### 8.1 鍗$墖闃村奖
+- **榛樿**: `0 2px 8px rgba(0, 0, 0, 0.1)`
+- **鎮仠**: `0 4px 12px rgba(0, 0, 0, 0.15)`
+
+### 8.2 浣跨敤鍘熷垯
+- 闃村奖鐢ㄤ簬鍖哄垎灞傜骇
+- 閬垮厤杩囧害浣跨敤闃村奖
+- 淇濇寔闃村奖鐨勪竴鑷存��
+
+## 9. 鍔ㄧ敾瑙勮寖
+
+### 9.1 杩囨浮鏃堕棿
+- **蹇��**: 0.15s - 棰滆壊鍙樺寲銆佸皬鍏冪礌
+- **鏍囧噯**: 0.3s - 鑿滃崟灞曞紑銆佸崱鐗囨偓鍋�
+- **鎱㈤��**: 0.5s - 椤甸潰鍒囨崲
+
+### 9.2 缂撳姩鍑芥暟
+- **鏍囧噯**: `ease-in-out`
+- **杩涘叆**: `ease-out`
+- **閫�鍑�**: `ease-in`
+
+## 10. 鍒楄〃椤甸潰瑙勮寖 (List)
+
+### 10.1 椤甸潰澶撮儴甯冨眬
+- **椤甸潰鏍囬**: 18px锛岀矖浣擄紝`#333333`
+- **鍓爣棰�**: 14px锛屽父瑙勶紝`#666666`锛屼綅浜庝富鏍囬涓嬫柟
+- **鏍囬鍖哄煙**: 宸﹀榻愶紝搴曢儴闂磋窛 24px
+
+### 10.2 鎼滅储鍖哄煙璁捐
+- **浣嶇疆**: 椤甸潰鍙充笂瑙掞紝涓庢爣棰樺尯鍩熷悓琛�
+- **鎼滅储妗�**:
+  - 瀹藉害: 280px
+  - 楂樺害: 40px
+  - 鍦嗚: 6px
+  - 杈规: 1px `#D1D5DB`
+  - 鍗犱綅绗�: "璇疯緭鍏ユ瘮璧涘悕绉�" 绛夋彁绀烘枃瀛�
+  - 鎼滅储鍥炬爣: 浣嶄簬杈撳叆妗嗗乏渚э紝`#999999`
+  - 娓呴櫎鎸夐挳: 褰撴湁杈撳叆鍐呭鏃舵樉绀�
+- **鍔ㄦ�佹悳绱㈡寜閽�**:
+  - 浣嶇疆: 鎼滅储妗嗗唴閮ㄥ彸渚� (suffix slot)
+  - 鏄剧ず鏉′欢: 浠呭綋鎼滅储妗嗕笉涓虹┖鏃舵樉绀�
+  - 鏍峰紡: 鍦嗗舰灏忔寜閽� (circle, size="small")
+  - 棰滆壊: primary (`#409EFF`)
+  - 鍥炬爣: 鎼滅储鍥炬爣
+  - 浜や簰: 鐐瑰嚮鎵ц鎼滅储锛屾敮鎸丒nter閿悳绱�
+- **鎿嶄綔鎸夐挳**:
+  - 浣嶇疆: 鎼滅储妗嗗彸渚э紝闂磋窛 16px
+  - 鏍峰紡: 涓绘寜閽牱寮忥紝钃濊壊鑳屾櫙 `#409EFF`
+  - 鏂囧瓧: "鏂板姣旇禌" 绛夋搷浣滄枃瀛�
+  - 鍥炬爣: 鍙�夋坊鍔� "+" 鍥炬爣
+
+### 10.3 琛ㄦ牸璁捐瑙勮寖
+- **琛ㄦ牸瀹瑰櫒**: 鐧借壊鑳屾櫙锛�8px鍦嗚锛岄槾褰� `0 2px 8px rgba(0, 0, 0, 0.1)`
+- **琛ㄥご鏍峰紡**:
+  - 鑳屾櫙: `#F8F9FA`
+  - 鏂囧瓧: 14px锛岀矖浣擄紝`#333333`
+  - 楂樺害: 48px
+  - 杈规: 搴曢儴 1px `#E5E7EB`
+- **琛ㄦ牸琛�**:
+  - 楂樺害: 56px
+  - 鏂戦┈绾�: 鍋舵暟琛� `#FAFAFA`
+  - 鎮仠: `#F0F9FF` 鑳屾櫙
+  - 杈规: 搴曢儴 1px `#F0F0F0`
+
+### 10.4 鎿嶄綔鍒楀浘鏍囧寲璁捐
+- **鍥炬爣鏇夸唬鏂囧瓧**: 浣跨敤Element Plus鍥炬爣搴�
+- **缂栬緫鎿嶄綔**:
+  - 鍥炬爣: `Edit` (閾呯瑪鍥炬爣)
+  - 棰滆壊: `#409EFF`
+  - 灏哄: 16px
+  - 鎮仠: `#66B1FF`
+- **鍒犻櫎鎿嶄綔**:
+  - 鍥炬爣: `Delete` (鍨冨溇妗跺浘鏍�)
+  - 棰滆壊: `#F56C6C`
+  - 灏哄: 16px
+  - 鎮仠: `#F78989`
+- **鍥炬爣闂磋窛**: 宸﹀彸闂磋窛 8px
+- **鐐瑰嚮鍖哄煙**: 鏈�灏� 32x32px锛岀‘淇濇槗鐐瑰嚮
+
+### 10.5 鐘舵�佹爣绛捐鑼�
+- **宸插彂甯�**:
+  - 鑳屾櫙: `#F0F9FF`
+  - 鏂囧瓧: `#67C23A`
+  - 杈规: 1px `#67C23A`
+- **鏈彂甯�**:
+  - 鑳屾櫙: `#FDF6EC`
+  - 鏂囧瓧: `#E6A23C`
+  - 杈规: 1px `#E6A23C`
+- **宸插叧闂�**:
+  - 鑳屾櫙: `#FEF0F0`
+  - 鏂囧瓧: `#F56C6C`
+  - 杈规: 1px `#F56C6C`
+- **鏍囩鏍峰紡**:
+  - 鍐呰竟璺�: 4px 8px
+  - 鍦嗚: 4px
+  - 瀛椾綋: 12px
+
+### 10.6 鍒嗛〉缁勪欢
+- **浣嶇疆**: 琛ㄦ牸搴曢儴锛屽彸瀵归綈
+- **缁勪欢闂磋窛**: 椤堕儴闂磋窛 16px
+- **鏄剧ず鍐呭**:
+  - 鎬绘潯鏁�: "鍏� X 鏉�"
+  - 姣忛〉鏄剧ず: 涓嬫媺閫夋嫨 (10鏉�/椤点��20鏉�/椤点��50鏉�/椤�)
+  - 椤电爜: 鏁板瓧鍒嗛〉锛屾樉绀哄綋鍓嶉〉鍓嶅悗2椤�
+- **鏍峰紡**: 浣跨敤Element Plus榛樿鍒嗛〉鏍峰紡
+
+### 10.7 鍝嶅簲寮忛�傞厤
+- **绉诲姩绔� (< 768px)**:
+  - 鎼滅储妗嗗拰鎸夐挳鍨傜洿鎺掑垪
+  - 琛ㄦ牸妯悜婊氬姩
+  - 鎿嶄綔鍒楀浐瀹氬湪鍙充晶
+- **骞虫澘 (768px - 1024px)**:
+  - 鎼滅储鍖哄煙淇濇寔姘村钩甯冨眬
+  - 琛ㄦ牸姝e父鏄剧ず
+- **妗岄潰 (> 1024px)**:
+  - 瀹屾暣甯冨眬鏄剧ず
+  - 琛ㄦ牸鍒楀鑷�傚簲
+
+### 10.8 浜や簰鍙嶉
+- **鍔犺浇鐘舵��**: 琛ㄦ牸鏁版嵁鍔犺浇鏃舵樉绀簊keleton鎴杔oading
+- **绌虹姸鎬�**: 鏃犳暟鎹椂鏄剧ず鍙嬪ソ鐨勭┖鐘舵�佹彁绀�
+- **鎿嶄綔纭**: 鍒犻櫎鎿嶄綔闇�瑕佷簩娆$‘璁ゅ脊绐�
+- **鎴愬姛鍙嶉**: 鎿嶄綔鎴愬姛鍚庢樉绀簍oast鎻愮ず
+
+### 10.9 鍒楄〃椤圭洰閰嶇疆
+- **鍒楀璁剧疆**:
+  - 搴忓彿鍒�: 80px
+  - 鍚嶇О鍒�: 鑷�傚簲锛屾渶灏�200px
+  - 鏁板瓧鍒�: 120px
+  - 鏃堕棿鍒�: 180px
+  - 鐘舵�佸垪: 100px
+  - 鎿嶄綔鍒�: 120px
+- **鏂囧瓧瀵归綈**:
+  - 鏂囧瓧鍐呭: 宸﹀榻�
+  - 鏁板瓧鍐呭: 鍙冲榻�
+  - 鐘舵�佹爣绛�: 灞呬腑瀵归綈
+  - 鎿嶄綔鍥炬爣: 灞呬腑瀵归綈
+
+## 11. 鍙闂�ц鑼�
+
+### 11.1 瀵规瘮搴�
+- 纭繚鏂囧瓧涓庤儗鏅姣斿害 鈮� 4.5:1
+- 閲嶈淇℃伅瀵规瘮搴� 鈮� 7:1
+
+### 11.2 鐒︾偣鐘舵��
+- 鎵�鏈夊彲浜や簰鍏冪礌閮芥湁鏄庢樉鐨勭劍鐐圭姸鎬�
+- 鐒︾偣鐘舵�佷娇鐢ㄨ摑鑹茶竟妗嗘爣璇�
+
+---
+
+*鏈鑼冨熀浜� Element Plus 璁捐绯荤粺锛岀粨鍚堥」鐩疄闄呴渶姹傚埗瀹氥��*
+*鏈�鍚庢洿鏂版椂闂�: 2025骞�1鏈�*
\ No newline at end of file
diff --git a/web/public/logo.jpg b/web/public/logo.jpg
new file mode 100644
index 0000000..ab651a9
--- /dev/null
+++ b/web/public/logo.jpg
Binary files differ
diff --git a/web/public/logo.svg b/web/public/logo.svg
new file mode 100644
index 0000000..9dd6a9f
--- /dev/null
+++ b/web/public/logo.svg
@@ -0,0 +1,4 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+  <circle cx="16" cy="16" r="14" fill="#409EFF" stroke="#FFFFFF" stroke-width="2"/>
+  <text x="16" y="20" text-anchor="middle" fill="white" font-family="Arial, sans-serif" font-size="12" font-weight="bold">钃�</text>
+</svg>
\ No newline at end of file
diff --git a/web/public/test-rating.html b/web/public/test-rating.html
deleted file mode 100644
index fcfa82f..0000000
--- a/web/public/test-rating.html
+++ /dev/null
@@ -1,126 +0,0 @@
-<!DOCTYPE html>
-<html lang="zh-CN">
-<head>
-    <meta charset="UTF-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>璇勫垎绯荤粺 - 鐪熷疄璇勫垎椤甸潰</title>
-    <style>
-        body {
-            font-family: 'Microsoft YaHei', sans-serif;
-            max-width: 800px;
-            margin: 0 auto;
-            padding: 20px;
-            background-color: #f5f5f5;
-        }
-        .container {
-            background: white;
-            padding: 30px;
-            border-radius: 8px;
-            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
-        }
-        h1 {
-            color: #2c3e50;
-            text-align: center;
-            margin-bottom: 30px;
-        }
-        .rating-link {
-            display: inline-block;
-            background: #67C23A;
-            color: white;
-            padding: 15px 30px;
-            text-decoration: none;
-            border-radius: 6px;
-            margin: 15px 0;
-            transition: background-color 0.3s;
-            font-size: 16px;
-            font-weight: bold;
-        }
-        .rating-link:hover {
-            background: #5daf34;
-        }
-        .info-section {
-            margin: 20px 0;
-            padding: 15px;
-            background: #f8f9fa;
-            border-left: 4px solid #67C23A;
-        }
-        .mock-data {
-            background: #e8f5e8;
-            border-left: 4px solid #67C23A;
-            padding: 15px;
-            margin: 15px 0;
-        }
-        .warning {
-            background: #fff3cd;
-            border-left: 4px solid #ffc107;
-            padding: 15px;
-            margin: 15px 0;
-        }
-        ul {
-            margin: 10px 0;
-            padding-left: 20px;
-        }
-        li {
-            margin: 5px 0;
-        }
-        .center {
-            text-align: center;
-        }
-    </style>
-</head>
-<body>
-    <div class="container">
-        <h1>馃幆 璇勫垎绯荤粺 - 鐪熷疄璇勫垎椤甸潰</h1>
-        
-        <div class="center">
-            <a href="/#/activity-player/1/rating" class="rating-link">馃殌 寮�濮嬭瘎鍒� (閫夋墜ID: 1)</a>
-        </div>
-
-        <div class="info-section">
-            <h3>鉁� 绯荤粺鐘舵��</h3>
-            <p><strong>褰撳墠绯荤粺浣跨敤鐪熷疄鏁版嵁妯″紡</strong></p>
-            <ul>
-                <li>馃敡 <strong>鍚庣鏈嶅姟</strong>: Spring Boot + GraphQL</li>
-                <li>馃搳 <strong>鏁版嵁鏉ユ簮</strong>: 鍚庣鏁版嵁搴撲腑鐨勭湡瀹炴暟鎹�</li>
-                <li>鉁� <strong>鍔熻兘鐘舵��</strong>: 璇勫垎鍔熻兘瀹屽叏鍙敤</li>
-                <li>馃幆 <strong>鏁版嵁淇濆瓨</strong>: 璇勫垎缁撴灉灏嗕繚瀛樺埌鍚庣鏁版嵁搴�</li>
-            </ul>
-        </div>
-
-        <div class="info-section">
-            <h3>馃搵 璇勫垎鏍囧噯 (鎬诲垎100鍒�)</h3>
-            <ul>
-                <li><strong>浠g爜璐ㄩ噺</strong>: 30鍒� - 浠g爜瑙勮寖鎬с�佸彲璇绘�с�佺粨鏋勫悎鐞嗘��</li>
-                <li><strong>鍔熻兘瀹屾暣鎬�</strong>: 25鍒� - 鍔熻兘瀹炵幇绋嬪害銆侀渶姹傛弧瓒冲害</li>
-                <li><strong>鐢ㄦ埛浣撻獙</strong>: 20鍒� - 鐣岄潰璁捐銆佷氦浜掍綋楠屻�佹槗鐢ㄦ��</li>
-                <li><strong>鍒涙柊鎬�</strong>: 15鍒� - 鎶�鏈垱鏂般�佽В鍐虫柟妗堢嫭鐗规��</li>
-                <li><strong>椤圭洰灞曠ず</strong>: 10鍒� - 婕旂ず鏁堟灉銆佽〃杈捐兘鍔�</li>
-            </ul>
-        </div>
-
-        <div class="info-section">
-            <h3>馃懃 鍏朵粬璇勫鐘舵��</h3>
-            <ul>
-                <li>鉁� <strong>鐜嬫暀鎺�</strong>: 宸茶瘎鍒� (85鍒�)</li>
-                <li>鉁� <strong>闄堜笓瀹�</strong>: 宸茶瘎鍒� (78鍒�)</li>
-                <li>鈴� <strong>鍒樺崥澹�</strong>: 鏈瘎鍒�</li>
-                <li><strong>褰撳墠骞冲潎鍒�</strong>: 81.5鍒�</li>
-            </ul>
-        </div>
-
-        <div class="warning">
-            <h3>鈿狅笍 娉ㄦ剰浜嬮」</h3>
-            <ul>
-                <li>璇蜂粩缁嗘煡鐪嬮�夋墜鐨勬彁浜ゆ枃浠跺拰椤圭洰灞曠ず</li>
-                <li>鏍规嵁璇勫垎鏍囧噯瀹㈣鍏鍦扮粰鍑哄垎鏁�</li>
-                <li>鍙互鍦ㄥ娉ㄤ腑璇存槑璇勫垎鐞嗙敱</li>
-                <li>鎻愪氦鍚庡皢鏃犳硶淇敼锛岃纭鍚庡啀鎻愪氦</li>
-            </ul>
-        </div>
-
-        <div class="center">
-            <a href="/#/activity-player/1/rating" class="rating-link">馃幆 绔嬪嵆寮�濮嬭瘎鍒�</a>
-        </div>
-    </div>
-</body>
-</html>
\ No newline at end of file
diff --git a/web/src/api/player.js b/web/src/api/player.js
index 34cec08..c14cc6e 100644
--- a/web/src/api/player.js
+++ b/web/src/api/player.js
@@ -105,7 +105,12 @@
 const GET_APPLICATIONS = `
   query GetApplications($name: String, $activityId: ID, $state: Int, $page: Int, $size: Int) {
     activityPlayerApplications(name: $name, activityId: $activityId, state: $state, page: $page, size: $size) {
-      id playerName activityName phone applyTime state
+      content {
+        id playerName activityName projectName phone applyTime state
+      }
+      totalElements
+      page
+      size
     }
   }
 `
@@ -113,6 +118,6 @@
 export const PlayerApi = {
   getApplications: async (name, activityId, state, page, size) => {
     const data = await graphqlRequest(GET_APPLICATIONS, { name, activityId, state, page, size })
-    return data.activityPlayerApplications || []
+    return data.activityPlayerApplications || { content: [], totalElements: 0, page: 1, size: 10 }
   }
 }
\ No newline at end of file
diff --git a/web/src/api/projectReviewNew.js b/web/src/api/projectReviewNew.js
new file mode 100644
index 0000000..162d10d
--- /dev/null
+++ b/web/src/api/projectReviewNew.js
@@ -0,0 +1,32 @@
+import { graphqlRequest } from '@/config/api'
+
+// 鑾峰彇椤圭洰璇勫鍒楄〃锛堝寘鍚墍鏈夐樁娈垫暟鎹紝鍖呮嫭澶嶈禌銆佸喅璧涳級
+const GET_PROJECT_REVIEW_APPLICATIONS_QUERY = `
+  query GetProjectReviewApplications($activityId: ID, $page: Int, $size: Int) {
+    projectReviewApplications(activityId: $activityId, page: $page, size: $size) {
+      totalElements
+      page
+      size
+      content {
+        id
+        playerName
+        activityName
+        projectName
+        phone
+        applyTime
+        state
+        ratingCount
+        averageScore
+      }
+    }
+  }
+`
+
+// 鑾峰彇椤圭洰璇勫鍒楄〃
+export const getProjectReviewApplications = (params) => {
+  return graphqlRequest(GET_PROJECT_REVIEW_APPLICATIONS_QUERY, params)
+}
+
+export default {
+  getProjectReviewApplications
+}
\ No newline at end of file
diff --git a/web/src/layout/index.vue b/web/src/layout/index.vue
index 88f4c8f..406c232 100644
--- a/web/src/layout/index.vue
+++ b/web/src/layout/index.vue
@@ -3,7 +3,10 @@
     <!-- 椤堕儴鏍� -->
     <el-header class="layout-header">
       <div class="header-content">
-        <span class="system-title">钃夋槗鍒涚鐞嗙郴缁�</span>
+        <div class="title-container">
+          <img src="/logo.jpg" alt="钃夋槗鍒�" class="logo-icon" />
+          <span class="system-title">钃夋槗鍒涙瘮璧涚鐞�</span>
+        </div>
         <el-dropdown @command="handleCommand">
           <span class="el-dropdown-link">
             {{ currentUserName }}
@@ -26,16 +29,17 @@
       <el-aside width="200px" class="layout-aside">
         <el-menu
           :default-active="$route.path"
-          class="sidebar-menu"
           router
-          background-color="#545c64"
-          text-color="#fff"
-          active-text-color="#ffd04b"
+          background-color="transparent"
+          text-color="#666666"
+          active-text-color="#1E3A8A"
+        >
         >
           <el-menu-item index="/dashboard">
             <el-icon><House /></el-icon>
             <span>宸ヤ綔鍙�</span>
           </el-menu-item>
+
           <el-menu-item index="/activity">
             <el-icon><Calendar /></el-icon>
             <span>姣旇禌淇℃伅</span>
@@ -117,11 +121,11 @@
 
 /* 椤堕儴鏍忔牱寮� */
 .layout-header {
-  background-color: #B3C0D1;
+  background-color: #FFFFFF;
   color: #333;
   line-height: 60px;
   padding: 0 20px;
-  border-bottom: 1px solid #dcdfe6;
+  border-bottom: 1px solid #E5E7EB;
 }
 
 .header-content {
@@ -131,8 +135,19 @@
   height: 100%;
 }
 
+.title-container {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.logo-icon {
+  width: 48px;
+  height: 48px;
+}
+
 .system-title {
-  font-size: 18px;
+  font-size: 20px;
   font-weight: bold;
   color: #333;
 }
@@ -144,8 +159,9 @@
 
 /* 渚ц竟鏍忔牱寮� */
 .layout-aside {
-  background-color: #545c64;
+  background-color: #FFFFFF;
   height: 100%;
+  border-right: 1px solid #E5E7EB;
 }
 
 .sidebar-menu {
@@ -153,9 +169,24 @@
   border-right: none;
 }
 
+/* 鑿滃崟椤规牱寮� */
+.el-menu-item.is-active {
+  background-color: #3B82F6 !important;
+  color: #FFFFFF !important;
+  border-radius: 6px;
+  margin: 2px 8px;
+}
+
+.el-menu-item:hover {
+  background-color: #EBF4FF !important;
+  color: #1E3A8A !important;
+  border-radius: 6px;
+  margin: 2px 8px;
+}
+
 /* 涓诲唴瀹瑰尯鍩� */
 .layout-main {
-  background-color: #f5f5f5;
+  background-color: #FFFFFF;
   padding: 20px;
 }
 
diff --git a/web/src/router/index.ts b/web/src/router/index.ts
index 1301df5..f590f3d 100644
--- a/web/src/router/index.ts
+++ b/web/src/router/index.ts
@@ -13,6 +13,7 @@
         component: () => import('@/views/dashboard/index.vue'),
         meta: { title: '宸ヤ綔鍙�', icon: 'Grid' }
       },
+
       {
         path: '/activity',
         name: 'Activity',
@@ -127,18 +128,7 @@
         component: () => import('@/views/competition-promotion/index.vue'),
         meta: { title: '姣旇禌鏅嬬骇', icon: 'Promotion' }
       },
-      {
-        path: '/test/graphql',
-        name: 'GraphQLTest',
-        component: () => import('@/views/test/graphql-test.vue'),
-        meta: { title: 'GraphQL娴嬭瘯', icon: 'Connection' }
-      },
-      {
-        path: '/test/user-prefill',
-        name: 'TestUserPrefill',
-        component: () => import('@/pages/TestUserPrefill.vue'),
-        meta: { title: '鐢ㄦ埛淇℃伅棰勫~鍏呮祴璇�', icon: 'User' }
-      }
+
     ]
   },
   {
diff --git a/web/src/views/ActivityForm.vue b/web/src/views/ActivityForm.vue
index 5cadcfc..3425b07 100644
--- a/web/src/views/ActivityForm.vue
+++ b/web/src/views/ActivityForm.vue
@@ -663,10 +663,11 @@
   ElMessage.success(`宸茶缃负${count}涓樁娈礰)
 }
 
-// 鑾峰彇榛樿闃舵鍚嶇О
+// 鑾峰彇榛樿闃舵鍚嶇О - 浣跨敤鏇寸伒娲荤殑鍛藉悕鏂瑰紡锛岄伩鍏嶇‖缂栫爜鐗瑰畾闃舵鍚嶇О
 const getDefaultStageName = (index) => {
-  const stageNames = ['', '娴烽��', '澶嶈禌', '鍗婂喅璧�', '鍐宠禌', '鎬诲喅璧�']
-  return stageNames[index] || `绗�${index}闃舵`
+  // 鎻愪緵涓�浜涘父鐢ㄧ殑闃舵鍚嶇О寤鸿锛屼絾涓嶅己鍒朵娇鐢�
+  const suggestedNames = ['', '绗竴闃舵', '绗簩闃舵', '绗笁闃舵', '绗洓闃舵', '绗簲闃舵']
+  return suggestedNames[index] || `绗�${index}闃舵`
 }
 
 // 鑾峰彇闃舵鍦ㄥ師濮嬫暟缁勪腑鐨勭储寮�
diff --git a/web/src/views/RatingSchemeList.vue b/web/src/views/RatingSchemeList.vue
index 9909149..3a631d9 100644
--- a/web/src/views/RatingSchemeList.vue
+++ b/web/src/views/RatingSchemeList.vue
@@ -7,33 +7,28 @@
 
     <!-- 鎼滅储鍜屾搷浣滃尯鍩� -->
     <div class="search-bar">
-      <el-row :gutter="20">
-        <el-col :span="8">
-          <el-input
-            v-model="searchForm.name"
-            placeholder="璇疯緭鍏ユā鏉垮悕绉�"
-            clearable
-            @keyup.enter="handleSearch"
-          >
-            <template #prefix>
-              <el-icon><Search /></el-icon>
-            </template>
-          </el-input>
-        </el-col>
-        <el-col :span="8">
-          <el-button type="primary" @click="handleSearch">
+      <div class="search-form">
+        <el-input
+          v-model="searchForm.name"
+          placeholder="璇疯緭鍏ユā鏉垮悕绉�"
+          clearable
+          @keyup.enter="handleSearch"
+          style="width: 200px"
+        >
+          <template #prefix>
             <el-icon><Search /></el-icon>
-            鏌ヨ
-          </el-button>
-          <el-button @click="handleReset">閲嶇疆</el-button>
-        </el-col>
-        <el-col :span="8" class="text-right">
-          <el-button type="primary" @click="handleAdd">
-            <el-icon><Plus /></el-icon>
-            鏂板妯℃澘
-          </el-button>
-        </el-col>
-      </el-row>
+          </template>
+        </el-input>
+        <el-button type="primary" @click="handleSearch">
+          <el-icon><Search /></el-icon>
+          鏌ヨ
+        </el-button>
+        <el-button @click="handleReset">閲嶇疆</el-button>
+        <el-button type="primary" @click="handleAdd">
+          <el-icon><Plus /></el-icon>
+          鏂板妯℃澘
+        </el-button>
+      </div>
     </div>
 
     <!-- 鏁版嵁琛ㄦ牸 -->
@@ -232,6 +227,14 @@
   background: #fff;
   border-radius: 4px;
   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  display: flex;
+  justify-content: flex-end;
+}
+
+.search-form {
+  display: flex;
+  align-items: center;
+  gap: 12px;
 }
 
 .table-container {
diff --git a/web/src/views/activity/index.vue b/web/src/views/activity/index.vue
index 76f7e4f..33e97f9 100644
--- a/web/src/views/activity/index.vue
+++ b/web/src/views/activity/index.vue
@@ -1,26 +1,29 @@
-鍜屼綘<template>
+<template>
   <div class="activity-page">
     <div class="page-card">
-      <h3 class="card-title">姣旇禌淇℃伅</h3>
-      
-      <!-- 鎼滅储鍜屾搷浣滄爮 -->
-      <div class="toolbar">
+      <!-- 椤甸潰澶撮儴 -->
+      <div class="page-header">
+        <div class="title-section">
+          <h1 class="page-title">姣旇禌淇℃伅</h1>
+          <p class="page-subtitle">绠$悊鎮ㄧ殑绮惧僵姣旇禌</p>
+        </div>
+      </div>
+
+      <!-- 鎼滅储宸ュ叿鏍� -->
+      <div class="search-toolbar">
         <el-input
           v-model="searchForm.name"
           placeholder="璇疯緭鍏ユ瘮璧涘悕绉�"
-          style="width: 300px"
+          style="width: 200px"
           clearable
           @keyup.enter="handleSearch"
-        >
-          <template #prefix>
-            <el-icon><Search /></el-icon>
-          </template>
-        </el-input>
+          @clear="handleClear"
+        />
         <el-button type="primary" @click="handleSearch">
           <el-icon><Search /></el-icon>
-          鎼滅储
+          鏌ヨ
         </el-button>
-        <el-button type="success" @click="handleAdd">
+        <el-button type="primary" @click="handleAdd">
           <el-icon><Plus /></el-icon>
           鏂板姣旇禌
         </el-button>
@@ -37,15 +40,25 @@
             <el-tag :type="getStatusType(row.stateName)">{{ row.stateName }}</el-tag>
           </template>
         </el-table-column>
-        <el-table-column label="鎿嶄綔" width="150" fixed="right">
+        <el-table-column label="鎿嶄綔" width="120" fixed="right" align="center">
           <template #default="{ row }">
             <div class="table-actions">
-              <el-button type="warning" size="small" @click="handleEdit(row)">
-                缂栬緫
-              </el-button>
-              <el-button type="danger" size="small" @click="handleDelete(row)">
-                鍒犻櫎
-              </el-button>
+              <el-button 
+                text 
+                :icon="Edit" 
+                size="small" 
+                @click="handleEdit(row)"
+                class="action-btn edit-btn"
+                title="缂栬緫"
+              />
+              <el-button 
+                text 
+                :icon="Delete" 
+                size="small" 
+                @click="handleDelete(row)"
+                class="action-btn delete-btn"
+                title="鍒犻櫎"
+              />
             </div>
           </template>
         </el-table-column>
@@ -72,6 +85,7 @@
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { useRouter } from 'vue-router'
 import { getActivities } from '@/api/activity'
+import { Search, Plus, Edit, Delete } from '@element-plus/icons-vue'
 
 const loading = ref(false)
 const router = useRouter()
@@ -105,6 +119,12 @@
 // 鎼滅储
 const handleSearch = () => {
   pagination.page = 1
+  loadData()
+}
+
+// 娓呯┖鎼滅储
+const handleClear = () => {
+  searchForm.name = ''
   loadData()
 }
 
@@ -165,32 +185,128 @@
 })
 </script>
 
-<style lang="scss" scoped>
+<style scoped>
 .activity-page {
-  .card-title {
-    margin-bottom: 20px;
-    color: #303133;
-    font-size: 16px;
-    font-weight: 500;
+  padding: 20px;
+}
+
+.page-card {
+  background: white;
+  border-radius: 8px;
+  padding: 24px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+/* 椤甸潰澶撮儴鏍峰紡 */
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start;
+  margin-bottom: 24px;
+  gap: 20px;
+}
+
+.title-section {
+  flex: 1;
+}
+
+.page-title {
+  margin: 0 0 8px 0;
+  font-size: 24px;
+  font-weight: 600;
+  color: #1a1a1a;
+  line-height: 1.2;
+}
+
+.page-subtitle {
+  margin: 0;
+  font-size: 14px;
+  color: #666;
+  line-height: 1.4;
+}
+
+/* 宸ュ叿鏍忔牱寮� */
+.toolbar {
+  display: flex;
+  gap: 12px;
+  align-items: center;
+  flex-shrink: 0;
+}
+
+/* 鎼滅储宸ュ叿鏍忔牱寮� */
+.search-toolbar {
+  display: flex;
+  gap: 12px;
+  align-items: center;
+  justify-content: flex-end;
+  margin-bottom: 20px;
+}
+
+/* 鎼滅储妗嗘牱寮� */
+.search-icon {
+  color: #999;
+}
+
+.search-button {
+  margin-right: 4px;
+}
+
+/* 琛ㄦ牸鎿嶄綔鎸夐挳鏍峰紡 */
+.table-actions {
+  display: flex;
+  gap: 12px;
+  justify-content: center;
+}
+
+.action-btn {
+  padding: 4px;
+  border: none;
+  background: transparent !important;
+  transition: all 0.2s ease;
+}
+
+.edit-btn {
+  color: #409eff;
+}
+
+.edit-btn:hover {
+  color: #337ecc;
+  transform: scale(1.2);
+  background: rgba(64, 158, 255, 0.1) !important;
+}
+
+.delete-btn {
+  color: #f56c6c;
+}
+
+.delete-btn:hover {
+  color: #dd6161;
+  transform: scale(1.2);
+  background: rgba(245, 108, 108, 0.1) !important;
+}
+
+.pagination {
+  margin-top: 20px;
+  display: flex;
+  justify-content: flex-end;
+}
+
+/* 鍝嶅簲寮忛�傞厤 */
+@media (max-width: 768px) {
+  .page-header {
+    flex-direction: column;
+    align-items: stretch;
+    gap: 16px;
   }
   
   .toolbar {
-    display: flex;
-    gap: 12px;
-    margin-bottom: 20px;
-    align-items: center;
-  }
-  
-  .table-actions {
-    display: flex;
-    gap: 8px;
     flex-wrap: wrap;
+    gap: 8px;
   }
   
-  .pagination {
-    margin-top: 20px;
-    display: flex;
-    justify-content: flex-end;
+  .toolbar .el-input {
+    width: 100% !important;
+    max-width: 280px;
   }
 }
 </style>
\ No newline at end of file
diff --git a/web/src/views/carousel/index.vue b/web/src/views/carousel/index.vue
index 89c5deb..c305d0c 100644
--- a/web/src/views/carousel/index.vue
+++ b/web/src/views/carousel/index.vue
@@ -7,26 +7,26 @@
 
     <!-- 鎼滅储鍖哄煙 -->
     <div class="search-section">
-      <el-form :model="searchForm" inline>
-        <el-form-item label="鏍囬">
-          <el-input
-            v-model="searchForm.title"
-            placeholder="璇疯緭鍏ユ爣棰樺叧閿瘝"
-            clearable
-            @keyup.enter="handleSearch"
-          />
-        </el-form-item>
-        <el-form-item>
-          <el-button type="primary" @click="handleSearch">鎼滅储</el-button>
-        </el-form-item>
-        <el-form-item>
-          <el-button type="success" @click="handleAdd">
-            <el-icon><Plus /></el-icon>
-            鏂板杞挱鍥�
-          </el-button>
-          <el-button @click="updateSortOrders">璁剧疆椤哄簭</el-button>
-        </el-form-item>
-      </el-form>
+      <div class="search-toolbar">
+        <el-input
+          v-model="searchForm.title"
+          placeholder="璇疯緭鍏ユ爣棰樺叧閿瘝"
+          style="width: 200px"
+          clearable
+        />
+        <el-button type="primary" @click="handleSearch">
+          <el-icon><Search /></el-icon>
+          鏌ヨ
+        </el-button>
+        <el-button type="primary" @click="handleSetOrder">
+          <el-icon><Sort /></el-icon>
+          璁剧疆椤哄簭
+        </el-button>
+        <el-button type="primary" @click="handleAdd">
+          <el-icon><Plus /></el-icon>
+          鏂板杞挱鍥�
+        </el-button>
+      </div>
     </div>
 
     <!-- 鏁版嵁琛ㄦ牸 -->
@@ -58,10 +58,10 @@
           </template>
         </el-table-column>
         <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" width="180" />
-        <el-table-column label="鎿嶄綔" width="200" fixed="right">
+        <el-table-column label="鎿嶄綔" width="120" fixed="right">
           <template #default="{ row }">
-            <el-button type="primary" size="small" @click="handleEdit(row)">缂栬緫</el-button>
-            <el-button type="danger" size="small" @click="handleDelete(row)">鍒犻櫎</el-button>
+            <el-button type="primary" size="small" @click="handleEdit(row)" :icon="Edit" circle title="缂栬緫"></el-button>
+            <el-button type="danger" size="small" @click="handleDelete(row)" :icon="Delete" circle title="鍒犻櫎"></el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -204,7 +204,7 @@
 <script setup>
 import { ref, reactive, onMounted } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
-import { Plus } from '@element-plus/icons-vue'
+import { Plus, Sort, Edit, Delete } from '@element-plus/icons-vue'
 import { CarouselApi } from '@/api/carousel'
 import { uploadFile, getMediasByTarget, saveMedia, deleteMedia } from '@/api/media'
 import { MediaTargetType } from '@/constants/mediaTargetType'
@@ -661,6 +661,13 @@
     box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
   }
   
+  .search-toolbar {
+    display: flex;
+    gap: 12px;
+    align-items: center;
+    justify-content: flex-end;
+  }
+  
   .table-section {
     background: #fff;
     padding: 20px;
diff --git a/web/src/views/competition-promotion/index.vue b/web/src/views/competition-promotion/index.vue
index d2cebc3..6d65381 100644
--- a/web/src/views/competition-promotion/index.vue
+++ b/web/src/views/competition-promotion/index.vue
@@ -1,117 +1,122 @@
 <template>
   <div class="promotion-container">
-    <el-card>
-      <template #header>
-        <div class="card-header">
-          <h3 class="card-title">姣旇禌鏅嬬骇绠$悊</h3>
-        </div>
-      </template>
-
-      <!-- 鎼滅储鏍� -->
-      <el-form :inline="true" class="search-form">
-        <el-form-item label="姣旇禌鍚嶇О">
-          <el-input
-            v-model="searchForm.name"
-            placeholder="璇疯緭鍏ユ瘮璧涘悕绉�"
-            @keyup.enter="loadData"
-            style="width: 200px"
-            clearable
-          />
-        </el-form-item>
-        
-        <el-form-item>
-          <el-button type="primary" @click="loadData" :loading="loading">
-            鎼滅储
-          </el-button>
-          <el-button @click="resetSearch">閲嶇疆</el-button>
-        </el-form-item>
-      </el-form>
-
-      <!-- 鏁版嵁琛ㄦ牸 -->
-      <el-table 
-        :data="competitions" 
-        style="width: 100%" 
-        v-loading="loading"
-        empty-text="鏆傛棤姣旇禌鏁版嵁"
-      >
-        <el-table-column prop="competitionName" label="姣旇禌鍚嶇О" min-width="150">
-          <template #default="scope">
-            <div class="competition-info">
-              <div class="main-name">{{ scope.row.competitionName }}</div>
-              <div class="stage-name">{{ scope.row.stageName }}</div>
-            </div>
-          </template>
-        </el-table-column>
-        
-        <el-table-column prop="maxParticipants" label="鏈�澶т汉鏁�" width="100" align="center">
-          <template #default="scope">
-            <el-tag type="info">{{ scope.row.maxParticipants || '涓嶉檺' }}</el-tag>
-          </template>
-        </el-table-column>
-        
-        <el-table-column prop="currentCount" label="褰撳墠鏁伴噺" width="100" align="center">
-          <template #default="scope">
-            <el-button 
-              type="text" 
-              @click="viewParticipants(scope.row)"
-              class="count-link"
-            >
-              {{ scope.row.currentCount }}
-            </el-button>
-          </template>
-        </el-table-column>
-        
-        <el-table-column prop="status" label="鐘舵��" width="100" align="center">
-          <template #default="scope">
-            <el-tag :type="getStatusType(scope.row.status)">
-              {{ getStatusText(scope.row.status) }}
-            </el-tag>
-          </template>
-        </el-table-column>
-        
-        <el-table-column prop="startTime" label="寮�濮嬫椂闂�" width="180">
-          <template #default="scope">
-            {{ formatDate(scope.row.startTime) }}
-          </template>
-        </el-table-column>
-        
-        <el-table-column prop="endTime" label="缁撴潫鏃堕棿" width="180">
-          <template #default="scope">
-            {{ formatDate(scope.row.endTime) }}
-          </template>
-        </el-table-column>
-        
-        <el-table-column label="鎿嶄綔" width="150" fixed="right">
-          <template #default="scope">
-            <!-- 鍙湁闈炵涓�闃舵鎵嶆樉绀烘檵绾ф寜閽� -->
-            <el-button 
-              v-if="scope.row.sortOrder > 1"
-              type="primary" 
-              size="small" 
-              @click="selectPromotionCandidates(scope.row)"
-              :disabled="scope.row.state !== 1"
-            >
-              閫夋嫨鏅嬬骇浜哄憳
-            </el-button>
-            <!-- 绗竴闃舵鏄剧ず鎻愮ず鏂囨湰 -->
-            <span v-else class="no-promotion-text">棣栬疆姣旇禌</span>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <!-- 鍒嗛〉 -->
-      <div class="pagination-container">
-        <el-pagination
-          v-model:current-page="pagination.page"
-          v-model:page-size="pagination.size"
-          :page-sizes="[10, 20, 50, 100]"
-          :total="pagination.total"
-          layout="total, sizes, prev, pager, next, jumper"
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-        />
+    <!-- 椤甸潰鏍囬鍖哄煙 -->
+    <div class="page-header">
+      <div class="title-section">
+        <h1 class="page-title">姣旇禌鏅嬬骇</h1>
+        <p class="page-subtitle">绠$悊姣旇禌鍚勯樁娈电殑鏅嬬骇娴佺▼锛岄�夋嫨浼樼鍙傝禌鑰呰繘鍏ヤ笅涓�杞�</p>
       </div>
-    </el-card>
+    </div>
+
+    <!-- 鎼滅储宸ュ叿鏍� -->
+    <div class="search-toolbar">
+      <div class="search-area">
+        <el-input
+          v-model="searchForm.name"
+          placeholder="璇疯緭鍏ユ瘮璧涘悕绉�"
+          @keyup.enter="loadData"
+          @clear="handleClear"
+          style="width: 200px"
+          clearable
+        >
+          <template #prefix>
+            <el-icon><Search /></el-icon>
+          </template>
+        </el-input>
+        <el-button type="primary" @click="loadData" :loading="loading">
+          <el-icon><Search /></el-icon>
+          鎼滅储
+        </el-button>
+        <el-button @click="resetSearch">閲嶇疆</el-button>
+      </div>
+    </div>
+
+    <!-- 鏁版嵁琛ㄦ牸 -->
+    <el-table 
+      :data="competitions" 
+      style="width: 100%" 
+      v-loading="loading"
+      empty-text="鏆傛棤姣旇禌鏁版嵁"
+    >
+      <el-table-column prop="competitionName" label="姣旇禌鍚嶇О" min-width="150">
+        <template #default="scope">
+          <div class="competition-info">
+            <div class="main-name">{{ scope.row.competitionName }}</div>
+            <div class="stage-name">{{ scope.row.stageName }}</div>
+          </div>
+        </template>
+      </el-table-column>
+      
+      <el-table-column prop="maxParticipants" label="鏈�澶т汉鏁�" width="100" align="center">
+        <template #default="scope">
+          <el-tag type="info">{{ scope.row.maxParticipants || '涓嶉檺' }}</el-tag>
+        </template>
+      </el-table-column>
+      
+      <el-table-column prop="currentCount" label="褰撳墠鏁伴噺" width="100" align="center">
+        <template #default="scope">
+          <el-button 
+            type="text" 
+            @click="viewParticipants(scope.row)"
+            class="count-link"
+          >
+            {{ scope.row.currentCount }}
+          </el-button>
+        </template>
+      </el-table-column>
+      
+      <el-table-column prop="status" label="鐘舵��" width="100" align="center">
+        <template #default="scope">
+          <el-tag :type="getStatusType(scope.row.status)">
+            {{ getStatusText(scope.row.status) }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      
+      <el-table-column prop="startTime" label="寮�濮嬫椂闂�" width="180">
+        <template #default="scope">
+          {{ formatDate(scope.row.startTime) }}
+        </template>
+      </el-table-column>
+      
+      <el-table-column prop="endTime" label="缁撴潫鏃堕棿" width="180">
+        <template #default="scope">
+          {{ formatDate(scope.row.endTime) }}
+        </template>
+      </el-table-column>
+      
+      <el-table-column label="鎿嶄綔" width="80" align="center">
+        <template #default="scope">
+          <!-- 鍙湁闈炵涓�闃舵鎵嶆樉绀烘檵绾ф寜閽� -->
+          <el-button 
+            v-if="scope.row.sortOrder > 1"
+            text
+            :icon="TrophyBase"
+            @click="selectPromotionCandidates(scope.row)"
+            :disabled="scope.row.state !== 1"
+            class="action-btn promotion-btn"
+            title="閫夋嫨鏅嬬骇浜哄憳"
+          />
+          <!-- 绗竴闃舵鏄剧ず鎻愮ず鍥炬爣 -->
+          <el-icon v-else class="no-promotion-icon" title="棣栬疆姣旇禌">
+            <InfoFilled />
+          </el-icon>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 鍒嗛〉 -->
+    <div class="pagination-container">
+      <el-pagination
+        v-model:current-page="pagination.page"
+        v-model:page-size="pagination.size"
+        :page-sizes="[10, 20, 50, 100]"
+        :total="pagination.total"
+        layout="total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
+    </div>
 
     <!-- 鏅嬬骇浜哄憳閫夋嫨瀵硅瘽妗� -->
     <el-dialog
@@ -194,15 +199,17 @@
       <template #footer>
         <div class="dialog-footer">
           <span class="selected-info">宸查�夋嫨 {{ selectedParticipants.length }} 浜�</span>
-          <el-button @click="handlePromotionDialogClose">鍙栨秷</el-button>
-          <el-button 
-            type="primary" 
-            @click="confirmPromotion"
-            :disabled="selectedParticipants.length === 0"
-            :loading="promotionLoading"
-          >
-            纭鏅嬬骇
-          </el-button>
+          <div class="footer-buttons">
+            <el-button @click="handlePromotionDialogClose">鍙栨秷</el-button>
+            <el-button 
+              type="primary" 
+              @click="confirmPromotion"
+              :disabled="selectedParticipants.length === 0"
+              :loading="promotionLoading"
+            >
+              纭鏅嬬骇
+            </el-button>
+          </div>
         </div>
       </template>
     </el-dialog>
@@ -213,7 +220,7 @@
 import { ref, reactive, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
 import { ElMessage, ElMessageBox } from 'element-plus'
-import { Search } from '@element-plus/icons-vue'
+import { Search, TrophyBase, InfoFilled } from '@element-plus/icons-vue'
 import PromotionApi from '@/api/promotion'
 
 const router = useRouter()
@@ -280,7 +287,7 @@
       {
         id: 1,
         competitionName: '2027鍒涙柊鍒涗笟澶ц禌',
-        stageName: '娴烽��',
+        stageName: '绗竴闃舵',
         maxParticipants: null,
         currentCount: 15,
         status: 1,
@@ -290,7 +297,7 @@
       {
         id: 2,
         competitionName: '2027鍒涙柊鍒涗笟澶ц禌',
-        stageName: '鍒濊禌',
+        stageName: '绗簩闃舵',
         maxParticipants: 50,
         currentCount: 8,
         status: 1,
@@ -300,7 +307,7 @@
       {
         id: 3,
         competitionName: '2027鍒涙柊鍒涗笟澶ц禌',
-        stageName: '鍐宠禌',
+        stageName: '绗笁闃舵',
         maxParticipants: 10,
         currentCount: 0,
         status: 0,
@@ -322,6 +329,13 @@
   } finally {
     loading.value = false
   }
+}
+
+// 娓呯┖鎼滅储
+const handleClear = () => {
+  searchForm.name = ''
+  pagination.page = 1
+  loadData()
 }
 
 // 閲嶇疆鎼滅储
@@ -412,8 +426,8 @@
       ],
       selectableCount: 10,
       totalCount: 15,
-      previousStageName: '娴烽��',
-      currentStageName: '鍒濊禌'
+      previousStageName: '绗竴闃舵',
+      currentStageName: '绗簩闃舵'
     }
     
     promotableData.value = mockData
@@ -611,24 +625,45 @@
   padding: 20px;
 }
 
-.card-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
+/* 椤甸潰鏍囬鍖哄煙 */
+.page-header {
+  margin-bottom: 24px;
 }
 
-.card-title {
-  margin: 0;
-  font-size: 18px;
+.title-section {
+  text-align: left;
+}
+
+.page-title {
+  font-size: 24px;
   font-weight: 600;
-  color: #303133;
+  color: #1f2937;
+  margin: 0 0 8px 0;
 }
 
-.search-form {
+.page-subtitle {
+  font-size: 14px;
+  color: #6b7280;
+  margin: 0;
+  line-height: 1.5;
+}
+
+/* 鎼滅储宸ュ叿鏍� */
+.search-toolbar {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
   margin-bottom: 20px;
-  padding: 20px;
-  background: #f8f9fa;
+  padding: 16px;
+  background-color: #f9fafb;
   border-radius: 8px;
+  border: 1px solid #e5e7eb;
+}
+
+.search-area {
+  display: flex;
+  align-items: center;
+  gap: 12px;
 }
 
 .competition-info {
@@ -657,6 +692,28 @@
   }
 }
 
+/* 鎿嶄綔鎸夐挳鏍峰紡 */
+.action-btn {
+  padding: 8px !important;
+  margin: 0 6px;
+  border-radius: 6px;
+  transition: all 0.2s ease;
+}
+
+.promotion-btn {
+  color: #f59e0b !important;
+}
+
+.promotion-btn:hover {
+  background-color: rgba(245, 158, 11, 0.1) !important;
+  transform: scale(1.2);
+}
+
+.no-promotion-icon {
+  color: #9ca3af;
+  font-size: 16px;
+}
+
 .score {
   font-weight: 600;
   color: #67c23a;
@@ -665,12 +722,6 @@
 .no-score {
   color: #909399;
   font-size: 12px;
-}
-
-.no-promotion-text {
-  color: #909399;
-  font-size: 12px;
-  font-style: italic;
 }
 
 .pagination-container {
@@ -723,5 +774,24 @@
     color: #606266;
     font-size: 14px;
   }
+  
+  .footer-buttons {
+    display: flex;
+    gap: 12px;
+  }
+}
+
+/* 鍝嶅簲寮忛�傞厤 */
+@media (max-width: 768px) {
+  .search-toolbar {
+    flex-direction: column;
+    gap: 12px;
+    align-items: stretch;
+  }
+  
+  .search-area {
+    justify-content: center;
+    flex-wrap: wrap;
+  }
 }
 </style>
\ No newline at end of file
diff --git a/web/src/views/dashboard/index.vue b/web/src/views/dashboard/index.vue
index 77196f9..4865983 100644
--- a/web/src/views/dashboard/index.vue
+++ b/web/src/views/dashboard/index.vue
@@ -1,77 +1,67 @@
 <template>
-  <div>
-    <el-row :gutter="20">
+  <div class="dashboard">
+    <el-row :gutter="20" class="stats-row">
       <el-col :span="6">
-        <el-card class="box-card">
-          <template #header>
-            <div class="card-header">
-              <span>褰撳墠杩涜姣旇禌</span>
-            </div>
-          </template>
-          <div class="text item">
-            {{ stats.activeActivities }}
+        <div class="stat-card">
+          <div class="icon-container blue">
+            <el-icon><Trophy /></el-icon>
           </div>
-        </el-card>
+          <div class="stat-number">{{ stats.activeActivities }}</div>
+          <div class="stat-title">褰撳墠姣旇禌</div>
+        </div>
       </el-col>
       <el-col :span="6">
-        <el-card class="box-card">
-          <template #header>
-            <div class="card-header">
-              <span>鍙傝禌鎬讳汉鏁�</span>
-            </div>
-          </template>
-          <div class="text item">
-            {{ stats.totalPlayers }}
+        <div class="stat-card">
+          <div class="icon-container green">
+            <el-icon><UserFilled /></el-icon>
           </div>
-        </el-card>
+          <div class="stat-number">{{ stats.totalPlayers }}</div>
+          <div class="stat-title">鍙傝禌鎬讳汉鏁�</div>
+        </div>
       </el-col>
       <el-col :span="6">
-        <el-card class="box-card">
-          <template #header>
-            <div class="card-header">
-              <span>鎶ュ悕寰呭鏍�</span>
-            </div>
-          </template>
-          <div class="text item">
-            {{ stats.pendingReviews }}
+        <div class="stat-card">
+          <div class="icon-container yellow">
+            <el-icon><Clock /></el-icon>
           </div>
-        </el-card>
+          <div class="stat-number">{{ stats.pendingReviews }}</div>
+          <div class="stat-title">鎶ュ悕寰呭鏍�</div>
+        </div>
       </el-col>
       <el-col :span="6">
-        <el-card class="box-card">
-          <template #header>
-            <div class="card-header">
-              <span>璇勫鎬绘暟</span>
-            </div>
-          </template>
-          <div class="text item">
-            {{ stats.totalJudges }}
+        <div class="stat-card">
+          <div class="icon-container red">
+            <el-icon><User /></el-icon>
           </div>
-        </el-card>
+          <div class="stat-number">{{ stats.totalJudges }}</div>
+          <div class="stat-title">璇勫鎬绘暟</div>
+        </div>
       </el-col>
     </el-row>
 
-    <el-card class="box-card" style="margin-top: 20px;">
-      <template #header>
-        <div class="card-header">
-          <span>鏈�杩戞瘮璧�</span>
-          <el-button type="primary" @click="$router.push('/activity')">鏌ョ湅鍏ㄩ儴</el-button>
-        </div>
-      </template>
-      <el-table :data="recentActivities" style="width: 100%">
+    <div class="table-card">
+      <div class="table-header">
+        <h3 class="table-title">鏈�杩戞瘮璧�</h3>
+        <el-button type="primary" @click="$router.push('/activity')">鏌ョ湅鍏ㄩ儴</el-button>
+      </div>
+      <el-table :data="recentActivities" class="recent-table">
         <el-table-column prop="name" label="姣旇禌鍚嶇О" width="180" />
         <el-table-column prop="playerCount" label="鎶ュ悕浜烘暟" width="120" />
         <el-table-column prop="startTime" label="寮�濮嬫椂闂�" width="180" />
         <el-table-column prop="endTime" label="缁撴潫鏃堕棿" width="180" />
-        <el-table-column prop="status" label="鐘舵��" width="100" />
+        <el-table-column prop="status" label="鐘舵��" width="100">
+          <template #default="{ row }">
+            <span :class="getStatusClass(row.status)">{{ row.status }}</span>
+          </template>
+        </el-table-column>
         <el-table-column label="鎿嶄綔">
           <template #default="scope">
-            <el-button size="small" @click="viewActivity(scope.row)">鏌ョ湅</el-button>
-            <el-button size="small" type="primary" @click="manageActivity(scope.row)">绠$悊</el-button>
+            <a class="action-link" @click="viewActivity(scope.row)">鏌ョ湅</a>
+            <a class="action-link" @click="manageActivity(scope.row)">绠$悊</a>
           </template>
         </el-table-column>
       </el-table>
-    </el-card>
+    </div>
   </div>
 </template>
 
@@ -79,6 +69,7 @@
 import { ref, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
 import { ElMessage } from 'element-plus'
+import { Trophy, UserFilled, Clock, User } from '@element-plus/icons-vue'
 import { getDashboardStats } from '@/api/dashboard'
 import { getActivities } from '@/api/activity'
 
@@ -139,25 +130,220 @@
 const manageActivity = (activity: any) => {
   router.push('/activity')
 }
+
+// 鑾峰彇鐘舵�佹牱寮忕被
+const getStatusClass = (status: string) => {
+  const statusMap: Record<string, string> = {
+    '宸插彂甯�': 'status-published',
+    '杩涜涓�': 'status-published',
+    '鏈彂甯�': 'status-unpublished',
+    '鎶ュ悕涓�': 'status-unpublished',
+    '鍏抽棴': 'status-closed',
+    '宸茬粨鏉�': 'status-closed',
+    '寰呭紑濮�': 'status-unpublished'
+  }
+  return statusMap[status] || 'status-unpublished'
+}
 </script>
 
 <style scoped>
-.card-header {
+/* 椤甸潰鏁翠綋鏍峰紡 */
+.dashboard {
+  padding: 24px;
+  background-color: #FFFFFF;
+  min-height: 100vh;
+}
+
+/* 缁熻鍗$墖琛� */
+.stats-row {
+  margin-bottom: 20px;
+}
+
+/* 缁熻鍗$墖鏍峰紡 */
+.stat-card {
+  background: #FFFFFF;
+  border-radius: 12px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+  border: none;
+  padding: 24px;
+  height: 120px;
+  position: relative;
+  overflow: hidden;
+  transition: all 0.3s ease;
+}
+
+.stat-card:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
+}
+
+/* 鍥炬爣瀹瑰櫒 */
+.icon-container {
+  width: 48px;
+  height: 48px;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: absolute;
+  top: 24px;
+  left: 24px;
+}
+
+.icon-container.blue {
+  background-color: #E0E7FF;
+  color: #6366F1;
+}
+
+.icon-container.green {
+  background-color: #D1FAE5;
+  color: #10B981;
+}
+
+.icon-container.yellow {
+  background-color: #FEF3C7;
+  color: #F59E0B;
+}
+
+.icon-container.red {
+  background-color: #FECACA;
+  color: #EF4444;
+}
+
+/* 缁熻鏁板瓧 */
+.stat-number {
+  font-size: 32px;
+  font-weight: 700;
+  color: #1F2937;
+  position: absolute;
+  top: 24px;
+  right: 24px;
+  line-height: 1;
+}
+
+/* 缁熻鏍囬 */
+.stat-title {
+  font-size: 14px;
+  font-weight: 500;
+  color: #6B7280;
+  position: absolute;
+  bottom: 24px;
+  left: 24px;
+}
+
+/* 琛ㄦ牸鍗$墖 */
+.table-card {
+  background: #FFFFFF;
+  border-radius: 12px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+  border: none;
+  padding: 24px;
+  margin-top: 20px;
+}
+
+/* 琛ㄦ牸澶撮儴 */
+.table-header {
+  margin-bottom: 20px;
   display: flex;
   justify-content: space-between;
   align-items: center;
 }
 
-.text {
-  font-size: 24px;
-  font-weight: bold;
+.table-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #1F2937;
+  margin: 0;
 }
 
-.item {
-  margin-bottom: 18px;
-}
-
-.box-card {
+/* 琛ㄦ牸鏍峰紡 */
+.recent-table {
   width: 100%;
 }
+
+:deep(.el-table__header) {
+  background-color: #F9FAFB;
+}
+
+:deep(.el-table__header th) {
+  background-color: #F9FAFB !important;
+  color: #374151;
+  font-size: 14px;
+  font-weight: 500;
+  height: 48px;
+  border-bottom: 1px solid #E5E7EB;
+}
+
+:deep(.el-table__row) {
+  height: 56px;
+}
+
+:deep(.el-table__row:nth-child(even)) {
+  background-color: #F9FAFB;
+}
+
+:deep(.el-table__row:nth-child(odd)) {
+  background-color: #FFFFFF;
+}
+
+:deep(.el-table td) {
+  color: #1F2937;
+  font-size: 14px;
+  font-weight: 400;
+  border-bottom: 1px solid #F3F4F6;
+}
+
+/* 鐘舵�佹爣绛炬牱寮� */
+.status-published {
+  color: #67C23A;
+  background-color: #F0F9FF;
+  padding: 4px 8px;
+  border-radius: 4px;
+  font-size: 12px;
+}
+
+.status-unpublished {
+  color: #E6A23C;
+  background-color: #FDF6EC;
+  padding: 4px 8px;
+  border-radius: 4px;
+  font-size: 12px;
+}
+
+.status-closed {
+  color: #F56C6C;
+  background-color: #FEF0F0;
+  padding: 4px 8px;
+  border-radius: 4px;
+  font-size: 12px;
+}
+
+/* 鎿嶄綔閾炬帴鏍峰紡 */
+.action-link {
+  color: #409EFF;
+  cursor: pointer;
+  font-size: 14px;
+  margin: 0 8px;
+  text-decoration: none;
+}
+
+.action-link:hover {
+  color: #66B1FF;
+  text-decoration: underline;
+}
+
+.action-link:first-child {
+  margin-left: 0;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 768px) {
+  .dashboard {
+    padding: 16px;
+  }
+  
+  .stat-card {
+    margin-bottom: 16px;
+  }
+}
 </style>
\ No newline at end of file
diff --git a/web/src/views/employee/index.vue b/web/src/views/employee/index.vue
index 9ad229e..fcd0387 100644
--- a/web/src/views/employee/index.vue
+++ b/web/src/views/employee/index.vue
@@ -10,17 +10,12 @@
           placeholder="璇疯緭鍏ュ憳宸ュ悕绉�"
           style="width: 200px"
           clearable
-          @keyup.enter="handleSearch"
-        >
-          <template #prefix>
-            <el-icon><Search /></el-icon>
-          </template>
-        </el-input>
+        />
         <el-button type="primary" @click="handleSearch">
           <el-icon><Search /></el-icon>
-          鎼滅储
+          鏌ヨ
         </el-button>
-        <el-button type="success" @click="handleAdd">
+        <el-button type="primary" @click="handleAdd">
           <el-icon><Plus /></el-icon>
           鏂板鍛樺伐
         </el-button>
@@ -40,15 +35,11 @@
             {{ formatDateTime(row.createTime) }}
           </template>
         </el-table-column>
-        <el-table-column label="鎿嶄綔" width="180" fixed="right">
+        <el-table-column label="鎿嶄綔" width="120" fixed="right">
           <template #default="{ row }">
             <div class="table-actions">
-              <el-button type="warning" size="small" @click="handleEdit(row)">
-                缂栬緫
-              </el-button>
-              <el-button type="danger" size="small" @click="handleDelete(row)">
-                鍒犻櫎
-              </el-button>
+              <el-button type="warning" size="small" @click="handleEdit(row)" :icon="Edit" circle title="缂栬緫"></el-button>
+              <el-button type="danger" size="small" @click="handleDelete(row)" :icon="Delete" circle title="鍒犻櫎"></el-button>
             </div>
           </template>
         </el-table-column>
@@ -72,6 +63,7 @@
 <script setup lang="ts">
 import { reactive, ref, onMounted } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import { Search, Plus, Edit, Delete } from '@element-plus/icons-vue'
 import { employeeApi, type Employee } from '@/api/employee'
 import EmployeeForm from './EmployeeForm.vue'
 
@@ -204,6 +196,7 @@
     gap: 12px;
     margin-bottom: 20px;
     align-items: center;
+    justify-content: flex-end;
   }
   
   .table-actions {
diff --git a/web/src/views/judge/index.vue b/web/src/views/judge/index.vue
index 8d700be..c0f324f 100644
--- a/web/src/views/judge/index.vue
+++ b/web/src/views/judge/index.vue
@@ -1,13 +1,26 @@
 <template>
   <div class="judge-page">
-    <div class="search-bar">
+    <!-- 椤甸潰鏍囬鍖哄煙 -->
+    <div class="page-header">
+      <div class="title-section">
+        <h1 class="page-title">璇勫绠$悊</h1>
+        <p class="page-subtitle">绠$悊姣旇禌璇勫淇℃伅锛屽寘鎷瘎濮旂殑鍩烘湰淇℃伅鍜屼笓涓氳儗鏅�</p>
+      </div>
+    </div>
+
+    <!-- 鎼滅储宸ュ叿鏍� -->
+    <div class="search-toolbar">
       <el-input
         v-model="searchQuery"
         placeholder="鎼滅储璇勫..."
-        style="width: 300px; margin-right: 10px"
+        style="width: 200px"
         clearable
-        @input="handleSearch"
+        @clear="handleClear"
       />
+      <el-button type="primary" @click="handleSearch">
+        <el-icon><Search /></el-icon>
+        鏌ヨ
+      </el-button>
       <el-button type="primary" @click="openAddDialog">
         <el-icon><Plus /></el-icon>
         鏂板璇勫
@@ -43,22 +56,22 @@
       <el-table-column prop="description" label="绠�浠�" min-width="200" show-overflow-tooltip />
       
       <!-- 鎿嶄綔鍒� -->
-      <el-table-column label="鎿嶄綔" width="180" align="center">
+      <el-table-column label="鎿嶄綔" width="120" align="center">
         <template #default="scope">
           <el-button
-            type="primary"
-            size="small"
+            text
+            :icon="Edit"
             @click="editJudge(scope.row)"
-          >
-            缂栬緫
-          </el-button>
+            class="action-btn edit-btn"
+            title="缂栬緫"
+          />
           <el-button
-            type="danger"
-            size="small"
+            text
+            :icon="Delete"
             @click="deleteJudge(scope.row.id)"
-          >
-            鍒犻櫎
-          </el-button>
+            class="action-btn delete-btn"
+            title="鍒犻櫎"
+          />
         </template>
       </el-table-column>
     </el-table>
@@ -86,7 +99,7 @@
 <script setup lang="ts">
 import { ref, onMounted } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
-import { Plus } from '@element-plus/icons-vue'
+import { Plus, Search, Edit, Delete } from '@element-plus/icons-vue'
 import JudgeFormSimple from '@/components/JudgeFormSimple.vue'
 import { JudgeApi } from '@/api/judge'
 
@@ -133,6 +146,12 @@
 }
 
 const handleSearch = () => {
+  currentPage.value = 1
+  loadJudges()
+}
+
+const handleClear = () => {
+  searchQuery.value = ''
   currentPage.value = 1
   loadJudges()
 }
@@ -233,15 +252,106 @@
   padding: 20px;
 }
 
-.search-bar {
+/* 椤甸潰鏍囬鍖哄煙 */
+.page-header {
+  margin-bottom: 24px;
+}
+
+.title-section {
+  text-align: left;
+}
+
+.page-title {
+  font-size: 24px;
+  font-weight: 600;
+  color: #1f2937;
+  margin: 0 0 8px 0;
+}
+
+.page-subtitle {
+  font-size: 14px;
+  color: #6b7280;
+  margin: 0;
+  line-height: 1.5;
+}
+
+/* 鎼滅储宸ュ叿鏍� */
+.search-toolbar {
   display: flex;
   align-items: center;
   justify-content: space-between;
   margin-bottom: 20px;
+  padding: 16px;
+  background-color: #f9fafb;
+  border-radius: 8px;
+  border: 1px solid #e5e7eb;
+}
+
+.search-area {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+
+/* 鎼滅储宸ュ叿鏍忔牱寮� */
+.search-toolbar {
+  display: flex;
+  gap: 12px;
+  align-items: center;
+  justify-content: flex-end;
+  margin-bottom: 20px;
+}
+
+/* 鎼滅储鎸夐挳 */
+.search-btn {
+  width: 24px !important;
+  height: 24px !important;
+  min-height: 24px !important;
+  padding: 0 !important;
+  margin-right: 8px;
+}
+
+/* 鎿嶄綔鎸夐挳鏍峰紡 */
+.action-btn {
+  padding: 8px !important;
+  margin: 0 6px;
+  border-radius: 6px;
+  transition: all 0.2s ease;
+}
+
+.edit-btn {
+  color: #3b82f6 !important;
+}
+
+.edit-btn:hover {
+  background-color: rgba(59, 130, 246, 0.1) !important;
+  transform: scale(1.2);
+}
+
+.delete-btn {
+  color: #ef4444 !important;
+}
+
+.delete-btn:hover {
+  background-color: rgba(239, 68, 68, 0.1) !important;
+  transform: scale(1.2);
 }
 
 .el-pagination {
   display: flex;
   justify-content: center;
 }
+
+/* 鍝嶅簲寮忛�傞厤 */
+@media (max-width: 768px) {
+  .search-toolbar {
+    flex-direction: column;
+    gap: 12px;
+    align-items: stretch;
+  }
+  
+  .search-area {
+    justify-content: center;
+  }
+}
 </style>
\ No newline at end of file
diff --git a/web/src/views/player/index.vue b/web/src/views/player/index.vue
index c26ebb2..01b3304 100644
--- a/web/src/views/player/index.vue
+++ b/web/src/views/player/index.vue
@@ -1,25 +1,27 @@
 <template>
   <div class="player-page">
-    <div class="page-card">
-      <h3 class="card-title">鎶ュ悕瀹℃牳</h3>
-      
-      <!-- 鎼滅储鍜屾搷浣滄爮 -->
-      <div class="toolbar">
+    <!-- 椤甸潰鏍囬鍖哄煙 -->
+    <div class="page-header">
+      <div class="title-section">
+        <h1 class="page-title">鎶ュ悕瀹℃牳</h1>
+        <p class="page-subtitle">绠$悊鍙傝禌閫夋墜鐨勬姤鍚嶇敵璇凤紝瀹℃牳鍙傝禌璧勬牸鍜屼俊鎭�</p>
+      </div>
+    </div>
+
+    <!-- 鎼滅储宸ュ叿鏍� -->
+    <div class="search-toolbar">
+      <div class="search-form">
         <el-input
           v-model="searchForm.name"
           placeholder="璇疯緭鍏ュ鍛樺悕绉�"
-          style="width: 200px"
+          style="width: 180px"
           clearable
-          @keyup.enter="handleSearch"
-        >
-          <template #prefix>
-            <el-icon><Search /></el-icon>
-          </template>
-        </el-input>
+          @clear="handleClear"
+        />
         <el-select
           v-model="searchForm.activityId"
           placeholder="閫夋嫨姣旇禌"
-          style="width: 300px"
+          style="width: 200px"
           clearable
           filterable
         >
@@ -35,7 +37,7 @@
         <el-select
           v-model="searchForm.state"
           placeholder="閫夋嫨鐘舵��"
-          style="width: 150px"
+          style="width: 120px"
           clearable
         >
           <el-option label="寰呭鏍�" value="0" />
@@ -44,58 +46,58 @@
         </el-select>
         <el-button type="primary" @click="handleSearch">
           <el-icon><Search /></el-icon>
-          鎼滅储
+          鏌ヨ
         </el-button>
-        <el-button type="warning" @click="debugAPI">
-          璋冭瘯API
-        </el-button>
-        <span style="margin-left: 10px; color: #666; font-size: 12px;">
-          娲诲姩閫夐」鏁伴噺: {{ activityOptions.length }}
-        </span>
       </div>
+    </div>
 
-      <!-- 瀛﹀憳鍒楄〃 -->
-      <el-table :data="tableData" style="width: 100%" v-loading="loading">
-        <el-table-column label="澶村儚" width="80" align="center">
-          <template #default="{ row }">
-            <el-avatar :src="row.avatar" :size="40">
-              <el-icon><User /></el-icon>
-            </el-avatar>
-          </template>
-        </el-table-column>
-        <el-table-column prop="name" label="瀛﹀憳鍚嶇О" min-width="120" />
-        <el-table-column prop="activityName" label="鎶ュ悕椤圭洰" min-width="200" />
-        <el-table-column prop="phone" label="鑱旂郴鐢佃瘽" width="140" />
-        <el-table-column prop="applyTime" label="鐢宠鏃堕棿" width="180" />
-        <el-table-column prop="state" label="鐘舵��" width="100" align="center">
-          <template #default="{ row }">
-            <el-tag :type="getStateType(row.state)">{{ getStateText(row.state) }}</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="鎿嶄綔" width="120" fixed="right">
-          <template #default="{ row }">
-            <div class="table-actions">
-              <!-- 鍙繚鐣欒鎯呮寜閽� -->
-              <el-button type="primary" size="small" @click="handleViewDetail(row)">
-                璇︽儏
-              </el-button>
-            </div>
-          </template>
-        </el-table-column>
-      </el-table>
+    <!-- 瀛﹀憳鍒楄〃 -->
+    <el-table :data="tableData" style="width: 100%" v-loading="loading">
+      <el-table-column label="澶村儚" width="80" align="center">
+        <template #default="{ row }">
+          <el-avatar :src="row.avatar" :size="40">
+            <el-icon><User /></el-icon>
+          </el-avatar>
+        </template>
+      </el-table-column>
+      <el-table-column label="瀛﹀憳鍚嶇О" min-width="120">
+        <template #default="{ row }">
+          {{ row.name }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="projectName" label="椤圭洰鍚嶇О" min-width="150" />
+      <el-table-column prop="activityName" label="姣旇禌鍚嶇О" min-width="200" />
+      <el-table-column prop="phone" label="鑱旂郴鐢佃瘽" width="140" />
+      <el-table-column prop="applyTime" label="鐢宠鏃堕棿" width="180" />
+      <el-table-column prop="state" label="鐘舵��" width="100" align="center">
+        <template #default="{ row }">
+          <el-tag :type="getStateType(row.state)">{{ getStateText(row.state) }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" width="80" align="center">
+        <template #default="{ row }">
+          <el-button
+            text
+            :icon="View"
+            @click="handleViewDetail(row)"
+            class="action-btn view-btn"
+            title="鏌ョ湅璇︽儏"
+          />
+        </template>
+      </el-table-column>
+    </el-table>
 
-      <!-- 鍒嗛〉 -->
-      <div class="pagination">
-        <el-pagination
-          v-model:current-page="pagination.page"
-          v-model:page-size="pagination.size"
-          :page-sizes="[10, 20, 50, 100]"
-          :total="pagination.total"
-          layout="total, sizes, prev, pager, next, jumper"
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-        />
-      </div>
+    <!-- 鍒嗛〉 -->
+    <div class="pagination">
+      <el-pagination
+        v-model:current-page="pagination.page"
+        v-model:page-size="pagination.size"
+        :page-sizes="[10, 20, 50, 100]"
+        :total="pagination.total"
+        layout="total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
     </div>
   </div>
 </template>
@@ -104,6 +106,7 @@
 import { reactive, ref, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import { Search, User, View } from '@element-plus/icons-vue'
 import { PlayerApi } from '@/api/player'
 import { getAllActivities } from '@/api/activity'
 
@@ -128,44 +131,7 @@
 })
 
 // 琛ㄦ牸鏁版嵁
-const tableData = ref([
-  {
-    id: 1,
-    name: '寮犱笁',
-    avatar: '',
-    activityName: '2024骞村垱鏂板垱涓氬ぇ璧�',
-    phone: '13800138001',
-    applyTime: '2024-01-05 14:30:00',
-    state: 0 // 0-鏈鏍�
-  },
-  {
-    id: 2,
-    name: '鏉庡洓',
-    avatar: '',
-    activityName: '涔︽硶姣旇禌',
-    phone: '13900139002',
-    applyTime: '2024-01-16 10:30:00',
-    state: 1 // 1-瀹℃牳閫氳繃
-  },
-  {
-    id: 3,
-    name: '鐜嬩簲',
-    avatar: '',
-    activityName: '缁樼敾姣旇禌',
-    phone: '13900139003',
-    applyTime: '2024-01-17 14:20:00',
-    state: 2 // 2-瀹℃牳椹冲洖
-  },
-  {
-    id: 4,
-    name: '璧靛叚',
-    avatar: '',
-    activityName: '闊充箰姣旇禌',
-    phone: '13900139004',
-    applyTime: '2024-01-18 09:15:00',
-    state: 0 // 0-鏈鏍�
-  }
-])
+const tableData = ref([])
 
 // 鑾峰彇鐘舵�佹爣绛剧被鍨�
 const getStateType = (state: number | null | undefined) => {
@@ -195,7 +161,11 @@
   loadData()
 }
 
-
+const handleClear = () => {
+  searchForm.name = ''
+  pagination.page = 1
+  loadData()
+}
 
 // 鏌ョ湅璇︽儏锛堣烦杞埌璇︽儏椤甸潰锛屽彧璇绘ā寮忥級
 const handleViewDetail = (row: any) => {
@@ -236,110 +206,49 @@
   return activity.name
 }
 
-
-
 // 鍔犺浇娲诲姩閫夐」
 const loadActivityOptions = async () => {
   try {
-    console.log('=== 寮�濮嬪姞杞芥椿鍔ㄩ�夐」 ===')
-    console.log('璋冪敤getAllActivities API...')
-    
     const activities = await getAllActivities()
-    console.log('API杩斿洖鐨勫師濮嬫暟鎹�:', activities)
-    console.log('鏁版嵁绫诲瀷:', typeof activities)
-    console.log('鏄惁涓烘暟缁�:', Array.isArray(activities))
     
     if (activities && Array.isArray(activities)) {
-      console.log('娲诲姩鏁伴噺:', activities.length)
-      activities.forEach((activity, index) => {
-        console.log(`娲诲姩${index + 1}:`, {
-          id: activity.id,
-          name: activity.name,
-          state: activity.state,
-          pid: activity.pid
-        })
-      })
-      
       // 杩囨护鍑烘鍦ㄨ繘琛岀殑姣旇禌锛堜笉鏄樁娈碉級
       const filtered = activities.filter(activity => 
         activity.state === 1 && (activity.pid === 0 || activity.pid === "0")
       )
-      console.log('杩囨护鏉′欢: state === 1 && (pid === 0 || pid === "0")')
-      console.log('杩囨护鍚庣殑娲诲姩:', filtered)
       
       activityOptions.value = filtered
-      console.log('璁剧疆鍒癮ctivityOptions.value:', activityOptions.value)
-      console.log('activityOptions.value.length:', activityOptions.value.length)
-      
-      // 寮哄埗瑙﹀彂鍝嶅簲寮忔洿鏂�
-      setTimeout(() => {
-        console.log('寤惰繜妫�鏌ctivityOptions.value:', activityOptions.value)
-        console.log('寤惰繜妫�鏌ctivityOptions.value.length:', activityOptions.value.length)
-      }, 100)
-    } else {
-      console.error('API杩斿洖鐨勬暟鎹牸寮忎笉姝g‘:', activities)
     }
   } catch (error) {
-    console.error('=== 鍔犺浇娲诲姩閫夐」澶辫触 ===')
-    console.error('閿欒璇︽儏:', error)
-    console.error('閿欒娑堟伅:', error.message)
-    console.error('閿欒鍫嗘爤:', error.stack)
-    ElMessage.error('鍔犺浇娲诲姩閫夐」澶辫触: ' + error.message)
+    ElMessage.error('鍔犺浇娲诲姩閫夐」澶辫触')
   }
 }
 
-// 璋冭瘯API鍑芥暟
-const debugAPI = async () => {
-  console.log('=== 寮�濮婣PI璋冭瘯 ===')
-  
-  // 妫�鏌ヨ璇佺姸鎬�
-  const token = localStorage.getItem('auth_token')
-  const userInfo = localStorage.getItem('user_info')
-  
-  console.log('璁よ瘉鐘舵�佹鏌�:')
-  console.log('Token:', token ? '宸插瓨鍦�' : '涓嶅瓨鍦�')
-  console.log('Token鍐呭:', token)
-  console.log('鐢ㄦ埛淇℃伅:', userInfo ? '宸插瓨鍦�' : '涓嶅瓨鍦�')
-  console.log('鐢ㄦ埛淇℃伅鍐呭:', userInfo)
-  
-  if (!token) {
-    ElMessage.error('鏈壘鍒拌璇乼oken锛岃鍏堢櫥褰�')
-    return
-  }
-  
-  // 娴嬭瘯API璋冪敤
-  try {
-    console.log('寮�濮嬫祴璇昰etAllActivities API...')
-    const activities = await getAllActivities()
-    console.log('API璋冪敤鎴愬姛锛岃繑鍥炴暟鎹�:', activities)
-    ElMessage.success(`API璋冪敤鎴愬姛锛岃幏鍙栧埌${activities?.length || 0}涓椿鍔╜)
-  } catch (error) {
-    console.error('API璋冪敤澶辫触:', error)
-    ElMessage.error('API璋冪敤澶辫触: ' + error.message)
-  }
-}
+
 
 // 鍔犺浇鏁版嵁
 const loadData = async () => {
   loading.value = true
   try {
-    const list = await PlayerApi.getApplications(
+    const response = await PlayerApi.getApplications(
       searchForm.name || '', 
       searchForm.activityId || null, 
       searchForm.state !== '' ? parseInt(searchForm.state) : null,
       pagination.page, 
       pagination.size
     )
-    tableData.value = (list || []).map((item: any) => ({
+    const list = response.content || []
+    tableData.value = list.map((item: any) => ({
       id: item.id,
       name: item.playerName,
+      projectName: item.projectName,
       avatar: '',
       activityName: item.activityName,
       phone: item.phone,
       applyTime: item.applyTime,
       state: item.state
     }))
-    pagination.total = tableData.value.length
+    pagination.total = response.totalElements || 0
   } catch (e: any) {
     ElMessage.error(String(e?.message || e))
   } finally {
@@ -348,49 +257,102 @@
 }
 
 onMounted(() => {
-  console.log('=== Player椤甸潰onMounted琚皟鐢� ===')
-  console.log('褰撳墠鏃堕棿:', new Date().toLocaleTimeString())
-  console.log('activityOptions鍒濆鍊�:', activityOptions.value)
-  console.log('鐩存帴鍔犺浇娲诲姩閫夐」杩涜娴嬭瘯...')
-  
-  // 绔嬪嵆璋冪敤API娴嬭瘯
-  loadActivityOptions().catch(error => {
-    console.error('loadActivityOptions璋冪敤澶辫触:', error)
-  })
-  
-  // loadData() // 鏆傛椂娉ㄩ噴鎺夛紝涓撴敞浜庢椿鍔ㄩ�夐」鍔犺浇
+  loadActivityOptions()
+  loadData()
 })
 </script>
 
 <style lang="scss" scoped>
 .player-page {
-  .card-title {
-    margin-bottom: 20px;
-    color: #303133;
-    font-size: 16px;
-    font-weight: 500;
-  }
-  
-  .toolbar {
-    display: flex;
-    gap: 12px;
-    margin-bottom: 20px;
-    align-items: center;
-  }
-  
-  .table-actions {
-    display: flex;
-    gap: 8px;
-    flex-wrap: wrap;
-    align-items: center;
-  }
-  
+  padding: 20px;
+}
 
+/* 椤甸潰鏍囬鍖哄煙 */
+.page-header {
+  margin-bottom: 24px;
+}
+
+.title-section {
+  text-align: left;
+}
+
+.page-title {
+  font-size: 24px;
+  font-weight: 600;
+  color: #1f2937;
+  margin: 0 0 8px 0;
+}
+
+.page-subtitle {
+  font-size: 14px;
+  color: #6b7280;
+  margin: 0;
+  line-height: 1.5;
+}
+
+/* 鎼滅储宸ュ叿鏍� */
+.search-toolbar {
+  display: flex;
+  justify-content: flex-end;
+  margin-bottom: 20px;
+}
+
+.search-form {
+  display: flex;
+  gap: 12px;
+  align-items: center;
+}
+
+.search-area {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+
+.action-area {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+
+/* 鎿嶄綔鎸夐挳鏍峰紡 */
+.action-btn {
+  padding: 8px !important;
+  margin: 0 6px;
+  border-radius: 6px;
+  transition: all 0.2s ease;
+}
+
+.view-btn {
+  color: #3b82f6 !important;
+}
+
+.view-btn:hover {
+  background-color: rgba(59, 130, 246, 0.1) !important;
+  transform: scale(1.2);
+}
+
+.pagination {
+  margin-top: 20px;
+  display: flex;
+  justify-content: center;
+}
+
+/* 鍝嶅簲寮忛�傞厤 */
+@media (max-width: 768px) {
+  .search-toolbar {
+    flex-direction: column;
+    gap: 12px;
+    align-items: stretch;
+  }
   
-  .pagination {
-    margin-top: 20px;
-    display: flex;
-    justify-content: flex-end;
+  .search-area {
+    justify-content: center;
+    flex-wrap: wrap;
+  }
+  
+  .action-area {
+    justify-content: center;
   }
 }
 </style>
\ No newline at end of file
diff --git a/web/src/views/project-review/index.vue b/web/src/views/project-review/index.vue
index 4420604..1df7c38 100644
--- a/web/src/views/project-review/index.vue
+++ b/web/src/views/project-review/index.vue
@@ -1,115 +1,124 @@
 <template>
   <div class="review-container">
-    <el-card>
-      <template #header>
-        <div class="card-header">
-          <h3 class="card-title">椤圭洰璇勫</h3>
-        </div>
-      </template>
-
-      <el-form :inline="true" class="search-form">
-        <el-form-item label="閫夋嫨姣旇禌">
-          <el-select
-            v-model="selectedActivity"
-            placeholder="璇烽�夋嫨姣旇禌"
-            @change="handleActivityChange"
-            style="width: 300px"
-            clearable
-            filterable
-          >
-            <el-option
-              v-for="activity in activities"
-              :key="activity.id"
-              :label="getActivityDisplayName(activity)"
-              :value="activity.id"
-            >
-              <span>{{ getActivityName(activity) }}</span>
-              <span v-if="activity.pid > 0" style="color: #409eff; margin-left: 8px;">
-                {{ activity.name }}
-              </span>
-            </el-option>
-          </el-select>
-        </el-form-item>
-        
-        <el-form-item label="椤圭洰鍚嶇О">
-          <el-input
-            v-model="searchName"
-            placeholder="璇疯緭鍏ラ」鐩悕绉�"
-            @keyup.enter="loadProjects"
-            style="width: 200px"
-          />
-        </el-form-item>
-        
-        <el-form-item>
-          <el-button type="primary" @click="loadProjects" :loading="projectsLoading">
-            鎼滅储
-          </el-button>
-          <el-button @click="resetSearch">閲嶇疆</el-button>
-        </el-form-item>
-      </el-form>
-
-      <el-table 
-        :data="projects" 
-        style="width: 100%" 
-        v-loading="projectsLoading"
-        empty-text="璇峰厛閫夋嫨姣旇禌"
-      >
-        <el-table-column prop="playerName" label="椤圭洰鍚嶇О" min-width="150">
-          <template #default="scope">
-            {{ scope.row.projectName || scope.row.playerName }}
-          </template>
-        </el-table-column>
-        <el-table-column prop="playerName" label="鍙傝禌浜哄鍚�" min-width="120" />
-        <el-table-column prop="phone" label="鑱旂郴鐢佃瘽" min-width="120" />
-        <el-table-column prop="ratingCount" label="璇勫娆℃暟" width="100" align="center">
-          <template #default="scope">
-            <el-tag :type="scope.row.ratingCount > 0 ? 'success' : 'info'">
-              {{ scope.row.ratingCount }}
-            </el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="averageScore" label="骞冲潎鍒�" width="100" align="center">
-          <template #default="scope">
-            <span v-if="scope.row.averageScore > 0" class="score">
-              {{ scope.row.averageScore.toFixed(1) }}
-            </span>
-            <span v-else class="no-score">鏈瘎鍒�</span>
-          </template>
-        </el-table-column>
-        <el-table-column prop="applyTime" label="鎶ュ悕鏃堕棿" width="180">
-          <template #default="scope">
-            {{ formatDate(scope.row.applyTime) }}
-          </template>
-        </el-table-column>
-        <el-table-column prop="state" label="鐘舵��" width="100" align="center">
-          <template #default="scope">
-            <el-tag :type="getStateType(scope.row.state)">
-              {{ getStateName(scope.row.state) }}
-            </el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column label="鎿嶄綔" width="120" fixed="right">
-          <template #default="scope">
-            <el-button type="primary" link @click="viewDetails(scope.row.id)">
-              璇︽儏璇勫
-            </el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <!-- 鍒嗛〉 -->
-      <div class="pagination-container" v-if="total > 0">
-        <el-pagination
-          v-model:current-page="currentPage"
-          v-model:page-size="pageSize"
-          :page-sizes="[10, 20, 50, 100]"
-          :total="total"
-          layout="total, sizes, prev, pager, next, jumper"
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-        />
+    <!-- 椤甸潰鏍囬鍖哄煙 -->
+    <div class="page-header">
+      <div class="title-section">
+        <h1 class="page-title">椤圭洰璇勫</h1>
+        <p class="page-subtitle">绠$悊姣旇禌椤圭洰鐨勮瘎瀹℃祦绋嬶紝鏌ョ湅璇勫垎缁撴灉鍜岄」鐩鎯�</p>
       </div>
-    </el-card>
+
+    </div>
+
+    <!-- 鎼滅储宸ュ叿鏍� -->
+    <div class="search-toolbar">
+      <div class="search-form">
+        <el-input
+          v-model="searchName"
+          placeholder="璇疯緭鍏ラ」鐩悕绉�"
+          @keyup.enter="loadProjects"
+          @clear="handleClear"
+          style="width: 180px"
+          clearable
+        />
+        <el-select
+          v-model="selectedActivity"
+          placeholder="璇烽�夋嫨姣旇禌"
+          @change="handleActivityChange"
+          style="width: 200px"
+          clearable
+          filterable
+        >
+          <template #prefix>
+            <el-icon><Trophy /></el-icon>
+          </template>
+          <el-option
+            v-for="activity in activities"
+            :key="activity.id"
+            :label="getActivityDisplayName(activity)"
+            :value="activity.id"
+          >
+            <span>{{ getActivityName(activity) }}</span>
+            <span v-if="activity.pid > 0" style="color: #409eff; margin-left: 8px;">
+              {{ activity.name }}
+            </span>
+          </el-option>
+        </el-select>
+        <el-button 
+          type="primary" 
+          :icon="Search" 
+          @click="loadProjects"
+          :loading="projectsLoading"
+        >
+          鏌ヨ
+        </el-button>
+      </div>
+    </div>
+
+    <el-table 
+      :data="projects" 
+      style="width: 100%" 
+      v-loading="projectsLoading"
+      empty-text="璇峰厛閫夋嫨姣旇禌"
+    >
+      <el-table-column prop="playerName" label="椤圭洰鍚嶇О" min-width="150">
+        <template #default="scope">
+          {{ scope.row.projectName || scope.row.playerName }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="playerName" label="鍙傝禌浜哄鍚�" min-width="120" />
+      <el-table-column prop="phone" label="鑱旂郴鐢佃瘽" min-width="120" />
+      <el-table-column prop="ratingCount" label="璇勫娆℃暟" width="100" align="center">
+        <template #default="scope">
+          <el-tag :type="scope.row.ratingCount > 0 ? 'success' : 'info'">
+            {{ scope.row.ratingCount }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column prop="averageScore" label="骞冲潎鍒�" width="100" align="center">
+        <template #default="scope">
+          <span v-if="scope.row.averageScore > 0" class="score">
+            {{ scope.row.averageScore.toFixed(1) }}
+          </span>
+          <span v-else class="no-score">鏈瘎鍒�</span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="applyTime" label="鎶ュ悕鏃堕棿" width="180">
+        <template #default="scope">
+          {{ formatDate(scope.row.applyTime) }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="reviewStatus" label="璇勫鐘舵��" width="100" align="center">
+        <template #default="scope">
+          <el-tag :type="getReviewStatusType(scope.row.ratingCount)">
+            {{ getReviewStatusName(scope.row.ratingCount) }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="鎿嶄綔" width="80" align="center">
+        <template #default="scope">
+          <el-button
+            text
+            :icon="View"
+            @click="viewDetails(scope.row.id)"
+            class="action-btn view-btn"
+            title="璇︽儏璇勫"
+          />
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 鍒嗛〉 -->
+    <div class="pagination-container" v-if="total > 0">
+      <el-pagination
+        v-model:current-page="currentPage"
+        v-model:page-size="pageSize"
+        :page-sizes="[10, 20, 50, 100]"
+        :total="total"
+        layout="total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
+    </div>
   </div>
 </template>
 
@@ -117,7 +126,9 @@
 import { ref, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
 import { ElMessage } from 'element-plus'
-import { getActiveActivities, getCompetitionProjects } from '@/api/projectReview'
+import { Search, Trophy, View } from '@element-plus/icons-vue'
+import { getActiveActivities, getRatingStats } from '@/api/projectReview'
+import { getProjectReviewApplications } from '@/api/projectReviewNew'
 
 const router = useRouter()
 
@@ -136,14 +147,21 @@
 
 // 鍔犺浇姣旇禌鍒楄〃
 const loadActivities = async () => {
+  console.log('=== 寮�濮嬪姞杞芥瘮璧涘垪琛� ===')
   activitiesLoading.value = true
   try {
+    console.log('璋冪敤 getActiveActivities...')
     const data = await getActiveActivities()
+    console.log('getActiveActivities 杩斿洖鏁版嵁:', data)
     activities.value = data
+    console.log('activities.value 璁剧疆涓�:', activities.value)
+    console.log('activities.value.length:', activities.value?.length)
   } catch (error) {
+    console.error('鍔犺浇姣旇禌鍒楄〃澶辫触:', error)
     ElMessage.error(error.message)
   } finally {
     activitiesLoading.value = false
+    console.log('=== 姣旇禌鍒楄〃鍔犺浇瀹屾垚 ===')
   }
 }
 
@@ -154,17 +172,37 @@
     return
   }
   
+  console.log('=== 寮�濮嬪姞杞介」鐩垪琛� ===')
+  console.log('selectedActivity.value:', selectedActivity.value)
+  console.log('currentPage.value:', currentPage.value)
+  console.log('pageSize.value:', pageSize.value)
+  
   projectsLoading.value = true
   try {
-    const response = await getCompetitionProjects(
-      selectedActivity.value,
-      currentPage.value - 1, // 鍚庣浠�0寮�濮�
-      pageSize.value,
-      searchName.value
-    )
+    const params = {
+      activityId: selectedActivity.value,
+      page: currentPage.value,
+      size: pageSize.value
+    }
     
-    projects.value = response.content || []
-    total.value = response.totalElements || 0
+    // 濡傛灉鏈夋悳绱㈠悕绉帮紝娣诲姞鍒板弬鏁颁腑
+    if (searchName.value && searchName.value.trim()) {
+      params.name = searchName.value.trim()
+    }
+    
+    console.log('API璋冪敤鍙傛暟:', params)
+    
+    const response = await getProjectReviewApplications(params)
+    console.log('API鍝嶅簲:', response)
+    
+    // 澶勭悊鍝嶅簲鏁版嵁 - 鏂扮殑鍒嗛〉缁撴瀯
+    const pageData = response.projectReviewApplications
+    projects.value = pageData?.content || []
+    total.value = pageData?.totalElements || 0
+    
+    console.log('璁剧疆 projects.value:', projects.value)
+    console.log('projects.value.length:', projects.value.length)
+    console.log('璁剧疆 total.value:', total.value)
   } catch (error) {
     console.error('鍔犺浇椤圭洰鍒楄〃澶辫触:', error)
     ElMessage.error('鍔犺浇椤圭洰鍒楄〃澶辫触')
@@ -182,13 +220,22 @@
   loadProjects()
 }
 
-// 閲嶇疆鎼滅储
-const resetSearch = () => {
+// 娓呯┖鎼滅储
+const handleClear = () => {
   searchName.value = ''
   currentPage.value = 1
   if (selectedActivity.value) {
     loadProjects()
   }
+}
+
+// 閲嶇疆鎼滅储
+const resetSearch = () => {
+  searchName.value = ''
+  selectedActivity.value = null
+  currentPage.value = 1
+  projects.value = []
+  total.value = 0
 }
 
 // 鍒嗛〉澶勭悊
@@ -236,6 +283,16 @@
   return stateMap[state] || '鏈煡'
 }
 
+// 鑾峰彇璇勫鐘舵�佺被鍨嬶紙鍩轰簬璇勫娆℃暟锛�
+const getReviewStatusType = (ratingCount) => {
+  return ratingCount > 0 ? 'success' : 'warning'
+}
+
+// 鑾峰彇璇勫鐘舵�佸悕绉帮紙鍩轰簬璇勫娆℃暟锛�
+const getReviewStatusName = (ratingCount) => {
+  return ratingCount > 0 ? '宸茶瘎瀹�' : '鏈瘎瀹�'
+}
+
 // 鑾峰彇姣旇禌鍚嶇О锛堝鏋滄槸闃舵锛岃繑鍥炵埗姣旇禌鍚嶇О锛涘鏋滄槸姣旇禌锛岃繑鍥炶嚜宸辩殑鍚嶇О锛�
 const getActivityName = (activity) => {
   if (activity.pid > 0 && activity.parent) {
@@ -257,6 +314,8 @@
   return activity.name
 }
 
+
+
 // 缁勪欢鎸傝浇鏃跺姞杞芥暟鎹�
 onMounted(() => {
   loadActivities()
@@ -268,23 +327,63 @@
   padding: 20px;
 }
 
-.card-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
+/* 椤甸潰鏍囬鍖哄煙 */
+.page-header {
+  margin-bottom: 24px;
 }
 
-.card-title {
+.title-section {
+  text-align: left;
+}
+
+.page-title {
+  font-size: 24px;
+  font-weight: 600;
+  color: #1f2937;
+  margin: 0 0 8px 0;
+}
+
+.page-subtitle {
+  font-size: 14px;
+  color: #6b7280;
   margin: 0;
-  font-size: 18px;
-  font-weight: 500;
+  line-height: 1.5;
+}
+
+/* 鎼滅储宸ュ叿鏍� */
+.search-toolbar {
+  display: flex;
+  justify-content: flex-end;
+  margin-bottom: 20px;
 }
 
 .search-form {
-  margin-bottom: 20px;
-  padding: 20px;
-  background-color: #f5f7fa;
-  border-radius: 4px;
+  display: flex;
+  gap: 12px;
+  align-items: center;
+}
+
+.search-area {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+
+/* 鎿嶄綔鎸夐挳鏍峰紡 */
+.action-btn {
+  padding: 8px !important;
+  margin: 0 6px;
+  border-radius: 6px;
+  transition: all 0.2s ease;
+}
+
+.view-btn {
+  color: #3b82f6 !important;
+}
+
+.view-btn:hover {
+  background-color: rgba(59, 130, 246, 0.1) !important;
+  transform: scale(1.2);
 }
 
 .score {
@@ -314,4 +413,18 @@
 :deep(.el-tag) {
   border-radius: 12px;
 }
+
+/* 鍝嶅簲寮忛�傞厤 */
+@media (max-width: 768px) {
+  .search-toolbar {
+    flex-direction: column;
+    gap: 12px;
+    align-items: stretch;
+  }
+  
+  .search-area {
+    justify-content: center;
+    flex-wrap: wrap;
+  }
+}
 </style>
\ No newline at end of file
diff --git a/web/src/views/rating/index.vue b/web/src/views/rating/index.vue
index b562d33..be6dc55 100644
--- a/web/src/views/rating/index.vue
+++ b/web/src/views/rating/index.vue
@@ -1,48 +1,71 @@
 <template>
   <div class="rating-page">
-    <div class="page-card">
-      <h3 class="card-title">璇勫垎妯℃澘绠$悊</h3>
-      
-      <!-- 鎿嶄綔鏍� -->
-      <div class="toolbar">
-        <el-button type="success" @click="handleAdd">
+    <!-- 椤甸潰鏍囬鍖哄煙 -->
+    <div class="page-header">
+      <div class="title-section">
+        <h1 class="page-title">璇勫垎妯℃澘</h1>
+        <p class="page-subtitle">绠$悊姣旇禌璇勫垎妯℃澘锛岃缃瘎鍒嗘爣鍑嗗拰鏉冮噸鍒嗛厤</p>
+      </div>
+    </div>
+
+    <!-- 鎼滅储宸ュ叿鏍� -->
+    <div class="search-toolbar">
+      <div class="search-form">
+        <el-input
+          v-model="searchQuery"
+          placeholder="鎼滅储璇勫垎妯℃澘..."
+          style="width: 300px"
+          clearable
+          @clear="handleClear"
+        />
+        <el-button type="primary" @click="handleSearch">
+          <el-icon><Search /></el-icon>
+          鏌ヨ
+        </el-button>
+        <el-button type="primary" @click="handleAdd">
           <el-icon><Plus /></el-icon>
           鏂板妯℃澘
         </el-button>
       </div>
+    </div>
 
-      <!-- 妯℃澘鍒楄〃 -->
-      <el-table :data="tableData" style="width: 100%" v-loading="loading">
-        <el-table-column prop="name" label="妯℃澘鍚嶇О" min-width="200" />
-        <el-table-column prop="totalScore" label="妯℃澘鎬诲垎" width="120" align="center" />
-        <el-table-column prop="itemCount" label="璇勫垎鏉$洰鏁�" width="120" align="center" />
-        <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" width="180" />
-        <el-table-column label="鎿嶄綔" width="180" fixed="right">
-          <template #default="{ row }">
-            <div class="table-actions">
-              <el-button type="warning" size="small" @click="handleEdit(row)">
-                缂栬緫
-              </el-button>
-              <el-button type="danger" size="small" @click="handleDelete(row)">
-                鍒犻櫎
-              </el-button>
-            </div>
-          </template>
-        </el-table-column>
-      </el-table>
+    <!-- 妯℃澘鍒楄〃 -->
+    <el-table :data="tableData" style="width: 100%" v-loading="loading">
+      <el-table-column prop="name" label="妯℃澘鍚嶇О" min-width="200" />
+      <el-table-column prop="totalScore" label="妯℃澘鎬诲垎" width="120" align="center" />
+      <el-table-column prop="itemCount" label="璇勫垎鏉$洰鏁�" width="120" align="center" />
+      <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" width="180" />
+      <el-table-column label="鎿嶄綔" width="120" align="center">
+        <template #default="{ row }">
+          <el-button
+            text
+            :icon="Edit"
+            @click="handleEdit(row)"
+            class="action-btn edit-btn"
+            title="缂栬緫"
+          />
+          <el-button
+            text
+            :icon="Delete"
+            @click="handleDelete(row)"
+            class="action-btn delete-btn"
+            title="鍒犻櫎"
+          />
+        </template>
+      </el-table-column>
+    </el-table>
 
-      <!-- 鍒嗛〉 -->
-      <div class="pagination">
-        <el-pagination
-          v-model:current-page="pagination.page"
-          v-model:page-size="pagination.size"
-          :page-sizes="[10, 20, 50, 100]"
-          :total="pagination.total"
-          layout="total, sizes, prev, pager, next, jumper"
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-        />
-      </div>
+    <!-- 鍒嗛〉 -->
+    <div class="pagination">
+      <el-pagination
+        v-model:current-page="pagination.page"
+        v-model:page-size="pagination.size"
+        :page-sizes="[10, 20, 50, 100]"
+        :total="pagination.total"
+        layout="total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
     </div>
   </div>
 </template>
@@ -51,9 +74,11 @@
 import { reactive, ref, onMounted } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { useRouter } from 'vue-router'
+import { Plus, Search, Edit, Delete } from '@element-plus/icons-vue'
 import { getRatingSchemes, deleteRatingScheme } from '@/api/rating.js'
 
 const loading = ref(false)
+const searchQuery = ref('')
 
 // 鍒嗛〉淇℃伅
 const pagination = reactive({
@@ -96,6 +121,18 @@
   }
 }
 
+// 鎼滅储澶勭悊
+const handleSearch = () => {
+  pagination.page = 1
+  loadData()
+}
+
+const handleClear = () => {
+  searchQuery.value = ''
+  pagination.page = 1
+  loadData()
+}
+
 // 鍒嗛〉澶у皬鏀瑰彉
 const handleSizeChange = (size: number) => {
   pagination.size = size
@@ -129,30 +166,100 @@
 
 <style lang="scss" scoped>
 .rating-page {
-  .card-title {
-    margin-bottom: 20px;
-    color: #303133;
-    font-size: 16px;
-    font-weight: 500;
-  }
-  
-  .toolbar {
-    display: flex;
+  padding: 20px;
+}
+
+/* 椤甸潰鏍囬鍖哄煙 */
+.page-header {
+  margin-bottom: 24px;
+}
+
+.title-section {
+  text-align: left;
+}
+
+.page-title {
+  font-size: 24px;
+  font-weight: 600;
+  color: #1f2937;
+  margin: 0 0 8px 0;
+}
+
+.page-subtitle {
+  font-size: 14px;
+  color: #6b7280;
+  margin: 0;
+  line-height: 1.5;
+}
+
+/* 鎼滅储宸ュ叿鏍� */
+.search-toolbar {
+  display: flex;
+  justify-content: flex-end;
+  margin-bottom: 20px;
+  padding: 16px;
+  background-color: #f9fafb;
+  border-radius: 8px;
+  border: 1px solid #e5e7eb;
+}
+
+.search-form {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+
+/* 鎼滅储鎸夐挳 */
+.search-btn {
+  width: 24px !important;
+  height: 24px !important;
+  min-height: 24px !important;
+  padding: 0 !important;
+  margin-right: 8px;
+}
+
+/* 鎿嶄綔鎸夐挳鏍峰紡 */
+.action-btn {
+  padding: 8px !important;
+  margin: 0 6px;
+  border-radius: 6px;
+  transition: all 0.2s ease;
+}
+
+.edit-btn {
+  color: #3b82f6 !important;
+}
+
+.edit-btn:hover {
+  background-color: rgba(59, 130, 246, 0.1) !important;
+  transform: scale(1.2);
+}
+
+.delete-btn {
+  color: #ef4444 !important;
+}
+
+.delete-btn:hover {
+  background-color: rgba(239, 68, 68, 0.1) !important;
+  transform: scale(1.2);
+}
+
+.pagination {
+  margin-top: 20px;
+  display: flex;
+  justify-content: center;
+}
+
+/* 鍝嶅簲寮忛�傞厤 */
+@media (max-width: 768px) {
+  .search-toolbar {
+    flex-direction: column;
     gap: 12px;
-    margin-bottom: 20px;
-    align-items: center;
+    align-items: stretch;
   }
   
-  .table-actions {
-    display: flex;
-    gap: 8px;
-    flex-wrap: wrap;
-  }
-  
-  .pagination {
-    margin-top: 20px;
-    display: flex;
-    justify-content: flex-end;
+  .search-area {
+    justify-content: center;
   }
 }
 </style>
\ No newline at end of file
diff --git a/web/src/views/review/index.vue b/web/src/views/review/index.vue
index ff306e3..2ddda57 100644
--- a/web/src/views/review/index.vue
+++ b/web/src/views/review/index.vue
@@ -38,7 +38,6 @@
           <el-button type="primary" @click="loadProjects" :loading="projectsLoading">
             鎼滅储
           </el-button>
-          <el-button @click="resetSearch">閲嶇疆</el-button>
         </el-form-item>
       </el-form>
 
@@ -130,14 +129,20 @@
 
 // 鍔犺浇姣旇禌鍒楄〃
 const loadActivities = async () => {
+  console.log('=== 寮�濮嬪姞杞芥瘮璧涘垪琛� ===')
   activitiesLoading.value = true
   try {
+    console.log('璋冪敤 getActiveActivities...')
     const data = await getActiveActivities()
+    console.log('getActiveActivities 杩斿洖鏁版嵁:', data)
     activities.value = data
+    console.log('activities.value 璁剧疆涓�:', activities.value)
   } catch (error) {
+    console.error('鍔犺浇姣旇禌鍒楄〃澶辫触:', error)
     ElMessage.error(error.message)
   } finally {
     activitiesLoading.value = false
+    console.log('=== 姣旇禌鍒楄〃鍔犺浇瀹屾垚 ===')
   }
 }
 
@@ -243,6 +248,8 @@
   return activity.name
 }
 
+
+
 // 缁勪欢鎸傝浇鏃跺姞杞芥暟鎹�
 onMounted(() => {
   loadActivities()
diff --git a/web/ui_update.md b/web/ui_update.md
new file mode 100644
index 0000000..ed6282c
--- /dev/null
+++ b/web/ui_update.md
@@ -0,0 +1,342 @@
+# UI璁捐鏇存柊璁″垝
+
+## Dashboard椤甸潰瀹屾暣鏀归�犳柟妗�
+
+### 鎶�鏈爤纭
+- **鍥炬爣搴�**: @element-plus/icons-vue (宸插畨瑁�)
+- **瀛椾綋**: 绯荤粺榛樿瀛椾綋鏍�
+- **鏃ユ湡鏍煎紡**: 缁熶竴涓� "2025骞�10鏈�1鏃� 14:00" 鏍煎紡
+
+### 鏁翠綋椤甸潰璁捐
+
+#### 椤甸潰鑳屾櫙鍜屽鍣�
+- **椤甸潰鑳屾櫙鑹�**: #F8F9FA (娴呯伆鑹�)
+- **涓诲鍣�**: 淇濇寔褰撳墠鍝嶅簲寮忔爡鏍煎竷灞�
+- **瀹瑰櫒鍐呰竟璺�**: 24px
+- **鍗$墖闂磋窛**: 20px (淇濇寔鐜版湁)
+
+### 1. 缁熻鍗$墖鍖哄煙璇︾粏璁捐
+
+#### 1.1 鍗$墖瀹瑰櫒鏍峰紡
+```css
+.stat-card {
+  background: #FFFFFF;
+  border-radius: 12px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+  border: none;
+  padding: 24px;
+  height: 120px;
+  position: relative;
+  overflow: hidden;
+}
+```
+
+#### 1.2 鍥涗釜缁熻鍗$墖鍏蜂綋璁捐
+
+**鍗$墖1 - 褰撳墠杩涜姣旇禌**
+- **鍥炬爣**: `<Calendar />` (Element Plus Icons)
+- **鍥炬爣瀹瑰櫒**: 
+  - 灏哄: 48px 脳 48px
+  - 鑳屾櫙鑹�: #E0E7FF (娴呰摑鑹插渾褰�)
+  - 鍥炬爣棰滆壊: #6366F1 (钃濈传鑹�)
+  - 鍥炬爣灏哄: 24px
+  - 浣嶇疆: 宸︿笂瑙�
+- **鏁板瓧鏄剧ず**:
+  - 瀛椾綋澶у皬: 32px
+  - 瀛楅噸: 700 (bold)
+  - 棰滆壊: #1F2937 (娣辩伆)
+  - 浣嶇疆: 鍙充笂瑙掞紝鍙冲榻�
+- **鏍囬鏂囧瓧**:
+  - 鍐呭: "褰撳墠杩涜姣旇禌"
+  - 瀛椾綋澶у皬: 14px
+  - 瀛楅噸: 500 (medium)
+  - 棰滆壊: #6B7280 (涓伆)
+  - 浣嶇疆: 宸︿笅瑙�
+
+**鍗$墖2 - 鍙傝禌鎬讳汉鏁�**
+- **鍥炬爣**: `<User />` (Element Plus Icons)
+- **鍥炬爣瀹瑰櫒**:
+  - 鑳屾櫙鑹�: #D1FAE5 (娴呯豢鑹插渾褰�)
+  - 鍥炬爣棰滆壊: #10B981 (缁胯壊)
+- **鏁板瓧鍜屾枃瀛楁牱寮�**: 鍚屽崱鐗�1
+- **鏍囬**: "鍙傝禌鎬讳汉鏁�"
+
+**鍗$墖3 - 鎶ュ悕寰呭鏍�**
+- **鍥炬爣**: `<Document />` (Element Plus Icons)
+- **鍥炬爣瀹瑰櫒**:
+  - 鑳屾櫙鑹�: #FEF3C7 (娴呴粍鑹插渾褰�)
+  - 鍥炬爣棰滆壊: #F59E0B (姗欓粍鑹�)
+- **鏁板瓧鍜屾枃瀛楁牱寮�**: 鍚屽崱鐗�1
+- **鏍囬**: "鎶ュ悕寰呭鏍�"
+
+**鍗$墖4 - 璇勫鎬绘暟**
+- **鍥炬爣**: `<UserFilled />` (Element Plus Icons)
+- **鍥炬爣瀹瑰櫒**:
+  - 鑳屾櫙鑹�: #FECACA (娴呯孩鑹插渾褰�)
+  - 鍥炬爣棰滆壊: #EF4444 (绾㈣壊)
+- **鏁板瓧鍜屾枃瀛楁牱寮�**: 鍚屽崱鐗�1
+- **鏍囬**: "璇勫鎬绘暟"
+
+#### 1.3 鍗$墖鍐呴儴甯冨眬缁撴瀯
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� [馃棑锔廬                    32 鈹�
+鈹�                             鈹�
+鈹� 褰撳墠杩涜姣旇禌                鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+### 2. 鏈�杩戞瘮璧涜〃鏍煎尯鍩熻璁�
+
+#### 2.1 琛ㄦ牸瀹瑰櫒鍗$墖
+```css
+.table-card {
+  background: #FFFFFF;
+  border-radius: 12px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+  border: none;
+  padding: 24px;
+  margin-top: 20px;
+}
+```
+
+#### 2.2 琛ㄦ牸澶撮儴璁捐
+- **鏍囬**: "鏈�杩戞瘮璧�"
+- **鏍囬鏍峰紡**:
+  - 瀛椾綋澶у皬: 18px
+  - 瀛楅噸: 600 (semibold)
+  - 棰滆壊: #1F2937 (娣辩伆)
+- **鎸夐挳**: 绉婚櫎鎵�鏈夋寜閽� (鎸夌敤鎴疯姹�)
+
+#### 2.3 琛ㄦ牸鏍峰紡璇︾粏璁捐
+
+**琛ㄥご鏍峰紡**:
+```css
+.el-table__header {
+  background-color: #F9FAFB;
+}
+.el-table__header th {
+  background-color: #F9FAFB !important;
+  color: #374151;
+  font-size: 14px;
+  font-weight: 500;
+  height: 48px;
+  border-bottom: 1px solid #E5E7EB;
+}
+```
+
+**琛ㄦ牸琛屾牱寮�**:
+```css
+.el-table__row {
+  height: 56px;
+}
+.el-table__row:nth-child(even) {
+  background-color: #F9FAFB;
+}
+.el-table__row:nth-child(odd) {
+  background-color: #FFFFFF;
+}
+.el-table td {
+  color: #1F2937;
+  font-size: 14px;
+  font-weight: 400;
+  border-bottom: 1px solid #F3F4F6;
+}
+```
+
+#### 2.4 琛ㄦ牸鍒楄璁�
+1. **姣旇禌鍚嶇О** (180px)
+2. **鎶ュ悕浜烘暟** (120px) 
+3. **姣旇禌鏃堕棿** (200px) - 鏍煎紡: "2025骞�10鏈�1鏃� 14:00"
+4. **鐘舵��** (100px) - 鐘舵�佹爣绛�
+5. **鎿嶄綔** (鑷�傚簲) - 绉婚櫎鎿嶄綔鎸夐挳
+
+#### 2.5 鐘舵�佹爣绛炬牱寮�
+
+**宸插彂甯冪姸鎬�**:
+```css
+.status-published {
+  background-color: #D1FAE5;
+  color: #065F46;
+  border-radius: 16px;
+  padding: 4px 12px;
+  font-size: 12px;
+  font-weight: 500;
+  display: inline-block;
+}
+```
+
+**鏈彂甯冪姸鎬�**:
+```css
+.status-unpublished {
+  background-color: #FEF3C7;
+  color: #92400E;
+  border-radius: 16px;
+  padding: 4px 12px;
+  font-size: 12px;
+  font-weight: 500;
+  display: inline-block;
+}
+```
+
+**鍏抽棴鐘舵��**:
+```css
+.status-closed {
+  background-color: #FEE2E2;
+  color: #991B1B;
+  border-radius: 16px;
+  padding: 4px 12px;
+  font-size: 12px;
+  font-weight: 500;
+  display: inline-block;
+}
+```
+
+### 3. 鍝嶅簲寮忚璁′繚鎸�
+
+#### 鏂偣璁剧疆 (淇濇寔鐜版湁)
+- **xl (鈮�1200px)**: 4鍒楃粺璁″崱鐗� (span=6)
+- **lg (鈮�992px)**: 4鍒楃粺璁″崱鐗� (span=6)  
+- **md (鈮�768px)**: 2鍒楃粺璁″崱鐗� (span=12)
+- **sm (<768px)**: 1鍒楃粺璁″崱鐗� (span=24)
+
+#### 绉诲姩绔紭鍖�
+- 缁熻鍗$墖鍦ㄥ皬灞忓箷涓嬩繚鎸佺浉鍚岃璁�
+- 琛ㄦ牸鍦ㄧЩ鍔ㄧ鍙í鍚戞粴鍔�
+- 鍥炬爣鍜屾枃瀛楁瘮渚嬩繚鎸佷竴鑷�
+
+### 4. 鏁版嵁鏍煎紡澶勭悊
+
+#### 鏃ユ湡鏍煎紡杞崲
+```javascript
+// 灏嗗悗绔繑鍥炵殑鏃ユ湡鏍煎紡鍖栦负: "2025骞�10鏈�1鏃� 14:00"
+const formatDate = (dateString) => {
+  const date = new Date(dateString);
+  return date.toLocaleDateString('zh-CN', {
+    year: 'numeric',
+    month: 'long',
+    day: 'numeric',
+    hour: '2-digit',
+    minute: '2-digit'
+  });
+}
+```
+
+#### 鐘舵�佹槧灏�
+```javascript
+const statusMap = {
+  '宸插彂甯�': 'published',
+  '鏈彂甯�': 'unpublished', 
+  '鍏抽棴': 'closed'
+}
+```
+
+### 5. 閬楁紡鐨勮璁$粏鑺傝ˉ鍏�
+
+#### 5.1 鍗$墖hover鏁堟灉
+```css
+.stat-card:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
+  transition: all 0.3s ease;
+}
+```
+
+#### 5.2 鍥炬爣瀹瑰櫒鍦嗗舰璁捐
+```css
+.icon-container {
+  width: 48px;
+  height: 48px;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: absolute;
+  top: 24px;
+  left: 24px;
+}
+```
+
+#### 5.3 鏁板瓧鍔ㄧ敾鏁堟灉 (鍙��)
+- 椤甸潰鍔犺浇鏃舵暟瀛椾粠0寮�濮嬭鏁板埌鐩爣鍊�
+- 浣跨敤CSS transition瀹炵幇骞虫粦杩囨浮
+
+#### 5.4 琛ㄦ牸鏃犳暟鎹姸鎬�
+```css
+.el-table__empty-block {
+  background-color: #F9FAFB;
+  color: #6B7280;
+  font-size: 14px;
+}
+```
+
+#### 5.5 鍔犺浇鐘舵�佽璁�
+- 缁熻鍗$墖鏄剧ず楠ㄦ灦灞�
+- 琛ㄦ牸鏄剧ずloading鐘舵��
+- 淇濇寔涓庢暣浣撹璁¢鏍间竴鑷�
+
+### 6. 瀹炴柦浼樺厛绾�
+
+#### 绗竴闃舵 (鏍稿績鏍峰紡)
+1. 椤甸潰鑳屾櫙鑹蹭慨鏀�
+2. 缁熻鍗$墖閲嶆瀯 (鍥炬爣 + 鏍峰紡)
+3. 琛ㄦ牸鍩虹鏍峰紡鏇存柊
+
+#### 绗簩闃舵 (缁嗚妭浼樺寲)  
+1. 鐘舵�佹爣绛炬牱寮�
+2. 鏃ユ湡鏍煎紡澶勭悊
+3. 鍝嶅簲寮忔祴璇�
+
+#### 绗笁闃舵 (浜や簰浼樺寲)
+1. hover鏁堟灉
+2. 鍔犺浇鐘舵��
+3. 鍔ㄧ敾鏁堟灉
+
+### 7. 闇�瑕佸垱寤虹殑鏂扮粍浠�
+
+#### StatCard.vue (缁熻鍗$墖缁勪欢)
+- 鎺ユ敹鍥炬爣銆侀鑹层�佹暟鍊笺�佹爣棰樼瓑props
+- 鍙鐢ㄧ殑缁熻鍗$墖缁勪欢
+- 鍐呯疆hover鍜屽姩鐢绘晥鏋�
+
+#### StatusTag.vue (鐘舵�佹爣绛剧粍浠�)  
+- 鏍规嵁鐘舵�佸�艰嚜鍔ㄥ簲鐢ㄥ搴旀牱寮�
+- 鏀寔鑷畾涔夐鑹叉槧灏�
+
+### 8. CSS鍙橀噺瀹氫箟
+
+```css
+:root {
+  /* 涓婚鑹� */
+  --primary-color: #6366F1;
+  --bg-color: #F8F9FA;
+  --card-bg: #FFFFFF;
+  
+  /* 缁熻鍗$墖棰滆壊 */
+  --blue-light: #E0E7FF;
+  --blue-primary: #6366F1;
+  --green-light: #D1FAE5;
+  --green-primary: #10B981;
+  --yellow-light: #FEF3C7;
+  --yellow-primary: #F59E0B;
+  --red-light: #FECACA;
+  --red-primary: #EF4444;
+  
+  /* 鏂囧瓧棰滆壊 */
+  --text-primary: #1F2937;
+  --text-secondary: #6B7280;
+  --text-muted: #374151;
+  
+  /* 鐘舵�侀鑹� */
+  --status-published-bg: #D1FAE5;
+  --status-published-text: #065F46;
+  --status-unpublished-bg: #FEF3C7;
+  --status-unpublished-text: #92400E;
+  --status-closed-bg: #FEE2E2;
+  --status-closed-text: #991B1B;
+}
+```
+
+---
+
+*姝よ鍒掓兜鐩栦簡鍥剧墖璁捐鐨勬墍鏈夎瑙夊厓绱狅紝纭繚楂樺害杩樺師鐩爣鏁堟灉*
\ No newline at end of file
diff --git a/web/web_update.md b/web/web_update.md
new file mode 100644
index 0000000..64ce2fa
--- /dev/null
+++ b/web/web_update.md
@@ -0,0 +1,179 @@
+# Web鍓嶇鏇存柊璁″垝
+
+## Dashboard椤甸潰鏀归�犺鍒�
+
+### 鏁翠綋椤甸潰甯冨眬
+**褰撳墠鐘舵�佸垎鏋愶細**
+- 椤甸潰鑳屾櫙锛氶粯璁ょ櫧鑹�
+- 鏁翠綋甯冨眬锛氫娇鐢‥lement Plus鐨勬爡鏍肩郴缁�
+- 闂磋窛锛氱粺涓�浣跨敤20px闂磋窛
+
+**鐩爣璁捐瑕佹眰锛�**
+- 椤甸潰鑳屾櫙鑹诧細#F8F9FA锛堟祬鐏拌壊锛�
+- 淇濇寔鍝嶅簲寮忔爡鏍煎竷灞�
+- 鍗$墖闂磋窛淇濇寔20px
+
+### 1. 缁熻鍗$墖鍖哄煙鏀归��
+
+#### 1.1 鍗$墖鏁翠綋鏍峰紡
+**褰撳墠鏍峰紡锛�**
+```css
+.box-card {
+  width: 100%;
+}
+```
+
+**鐩爣鏍峰紡瑙勮寖锛�**
+- 鑳屾櫙鑹诧細#FFFFFF锛堢函鐧斤級
+- 鍦嗚锛�12px
+- 闃村奖锛�0 4px 12px rgba(0, 0, 0, 0.08)
+- 杈规锛氭棤
+- 鍐呰竟璺濓細24px
+
+#### 1.2 缁熻鍗$墖鍏蜂綋璁捐
+
+**鍗$墖1 - 褰撳墠杩涜姣旇禌**
+- 鍥炬爣锛氭棩鍘嗗浘鏍囷紙Calendar锛�
+- 鍥炬爣鑳屾櫙锛�#E0E7FF锛堟祬钃濊壊鍦嗗舰鑳屾櫙锛�
+- 鍥炬爣棰滆壊锛�#6366F1锛堣摑绱壊锛�
+- 鏁板瓧棰滆壊锛�#1F2937锛堟繁鐏拌壊锛�
+- 鏁板瓧瀛椾綋锛�32px锛宖ont-weight: 700
+- 鏍囬棰滆壊锛�#6B7280锛堜腑鐏拌壊锛�
+- 鏍囬瀛椾綋锛�14px锛宖ont-weight: 500
+
+**鍗$墖2 - 鍙傝禌鎬讳汉鏁�**
+- 鍥炬爣锛氱敤鎴风兢缁勫浘鏍囷紙Users锛�
+- 鍥炬爣鑳屾櫙锛�#D1FAE5锛堟祬缁胯壊鍦嗗舰鑳屾櫙锛�
+- 鍥炬爣棰滆壊锛�#10B981锛堢豢鑹诧級
+- 鏁板瓧鍜屾爣棰樻牱寮忓悓鍗$墖1
+
+**鍗$墖3 - 鎶ュ悕寰呭鏍�**
+- 鍥炬爣锛氳鍛婂浘鏍囷紙Warning锛�
+- 鍥炬爣鑳屾櫙锛�#FEF3C7锛堟祬榛勮壊鍦嗗舰鑳屾櫙锛�
+- 鍥炬爣棰滆壊锛�#F59E0B锛堟榛勮壊锛�
+- 鏁板瓧鍜屾爣棰樻牱寮忓悓鍗$墖1
+
+**鍗$墖4 - 璇勫鎬绘暟**
+- 鍥炬爣锛氱敤鎴峰浘鏍囷紙User锛�
+- 鍥炬爣鑳屾櫙锛�#FECACA锛堟祬绾㈣壊鍦嗗舰鑳屾櫙锛�
+- 鍥炬爣棰滆壊锛�#EF4444锛堢孩鑹诧級
+- 鏁板瓧鍜屾爣棰樻牱寮忓悓鍗$墖1
+
+#### 1.3 鍗$墖鍐呴儴甯冨眬
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹�  [鍥炬爣]              [鏁板瓧] 鈹�
+鈹�  鏍囬鏂囧瓧                   鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+- 鍥炬爣灏哄锛�48px 脳 48px鍦嗗舰鑳屾櫙锛屽唴閮ㄥ浘鏍�24px
+- 鍥炬爣浣嶇疆锛氬乏涓婅
+- 鏁板瓧浣嶇疆锛氬彸涓婅锛屽彸瀵归綈
+- 鏍囬浣嶇疆锛氬乏涓嬭
+
+### 2. 鏈�杩戞瘮璧涜〃鏍煎尯鍩熸敼閫�
+
+#### 2.1 琛ㄦ牸瀹瑰櫒鍗$墖
+**鐩爣鏍峰紡锛�**
+- 鑳屾櫙鑹诧細#FFFFFF
+- 鍦嗚锛�12px
+- 闃村奖锛�0 4px 12px rgba(0, 0, 0, 0.08)
+- 鍐呰竟璺濓細24px
+
+#### 2.2 琛ㄦ牸澶撮儴
+**褰撳墠锛�**
+```html
+<div class="card-header">
+  <span>鏈�杩戞瘮璧�</span>
+  <el-button type="primary">鏌ョ湅鍏ㄩ儴</el-button>
+</div>
+```
+
+**鐩爣鏍峰紡锛�**
+- 鏍囬锛�"鏈�杩戞瘮璧�"
+- 鏍囬瀛椾綋锛�18px锛宖ont-weight: 600锛岄鑹诧細#1F2937
+- 鎸夐挳锛�"鍒涘缓鏂版瘮璧�"
+- 鎸夐挳鑳屾櫙锛�#6366F1锛堢传鑹诧級
+- 鎸夐挳鏂囧瓧锛�#FFFFFF
+- 鎸夐挳鍦嗚锛�8px
+- 鎸夐挳鍐呰竟璺濓細12px 20px
+
+#### 2.3 琛ㄦ牸鏍峰紡
+**琛ㄥご鏍峰紡锛�**
+- 鑳屾櫙鑹诧細#F9FAFB
+- 鏂囧瓧棰滆壊锛�#374151
+- 瀛椾綋锛�14px锛宖ont-weight: 500
+- 楂樺害锛�48px
+
+**琛ㄦ牸琛屾牱寮忥細**
+- 濂囨暟琛岃儗鏅細#FFFFFF
+- 鍋舵暟琛岃儗鏅細#F9FAFB
+- 琛岄珮锛�56px
+- 鏂囧瓧棰滆壊锛�#1F2937
+- 瀛椾綋锛�14px锛宖ont-weight: 400
+
+#### 2.4 鐘舵�佹爣绛炬牱寮�
+**宸插彂甯冪姸鎬侊細**
+- 鑳屾櫙鑹诧細#D1FAE5
+- 鏂囧瓧棰滆壊锛�#065F46
+- 鍦嗚锛�16px
+- 鍐呰竟璺濓細4px 12px
+- 瀛椾綋锛�12px锛宖ont-weight: 500
+
+**鏈彂甯冪姸鎬侊細**
+- 鑳屾櫙鑹诧細#FEF3C7
+- 鏂囧瓧棰滆壊锛�#92400E
+- 鍏朵粬鏍峰紡鍚屼笂
+
+#### 2.5 鎿嶄綔鎸夐挳鏍峰紡
+**鏌ョ湅鎸夐挳锛�**
+- 鑳屾櫙鑹诧細閫忔槑
+- 鏂囧瓧棰滆壊锛�#6366F1
+- 杈规锛�1px solid #E5E7EB
+- 鍦嗚锛�6px
+- 鍐呰竟璺濓細6px 12px
+
+**绠$悊鎸夐挳锛�**
+- 鑳屾櫙鑹诧細#6366F1
+- 鏂囧瓧棰滆壊锛�#FFFFFF
+- 鍦嗚锛�6px
+- 鍐呰竟璺濓細6px 12px
+
+### 3. 宸︿晶瀵艰埅鏍忥紙濡傞渶淇敼锛�
+**鐩爣鏍峰紡锛�**
+- 鑳屾櫙鑹诧細#1F2937锛堟繁鐏拌壊锛�
+- 閫変腑椤硅儗鏅細#6366F1
+- 鏂囧瓧棰滆壊锛�#D1D5DB
+- 閫変腑椤规枃瀛楋細#FFFFFF
+
+### 4. 椤堕儴瀵艰埅鏍�
+**鐩爣鏍峰紡锛�**
+- 鑳屾櫙鑹诧細#FFFFFF
+- 闃村奖锛�0 1px 3px rgba(0, 0, 0, 0.1)
+- 楂樺害锛�64px
+
+### 5. 鍝嶅簲寮忔柇鐐瑰鐞�
+**淇濇寔褰撳墠鍝嶅簲寮忛�昏緫锛�**
+- xl: 6鍒楀竷灞�锛堚墺1200px锛�
+- lg: 6鍒楀竷灞�锛堚墺992px锛�
+- md: 12鍒楀竷灞�锛堚墺768px锛�
+- sm: 24鍒楀竷灞�锛�<768px锛�
+
+### 6. 闇�瑕佺‘璁ょ殑缁嗚妭闂
+
+1. **鍥炬爣搴撻�夋嫨**锛氫娇鐢‥lement Plus Icons杩樻槸寮曞叆鍏朵粬鍥炬爣搴擄紵
+2. **瀛椾綋璁剧疆**锛氭槸鍚﹂渶瑕佸紩鍏ョ壒瀹氬瓧浣擄紝杩樻槸浣跨敤绯荤粺榛樿瀛椾綋锛�
+3. **琛ㄦ牸鏁版嵁鏍煎紡**锛氭瘮璧涙椂闂存樉绀烘牸寮忔槸鍚﹂渶瑕佽皟鏁达紵
+4. **鐘舵�佹槧灏�**锛氬綋鍓嶅悗绔繑鍥炵殑鐘舵�佸�间笌棰滆壊鐨勫搴斿叧绯伙紵
+
+### 7. 瀹炴柦姝ラ
+1. 鏇存柊鍏ㄥ眬CSS鍙橀噺瀹氫箟涓婚鑹�
+2. 淇敼椤甸潰鑳屾櫙鍜屽竷灞�瀹瑰櫒鏍峰紡
+3. 閲嶆瀯缁熻鍗$墖缁勪欢锛屾坊鍔犲浘鏍囧拰鏂版牱寮�
+4. 鏇存柊琛ㄦ牸鏍峰紡鍜岀姸鎬佹爣绛�
+5. 璋冩暣鎸夐挳鏍峰紡
+6. 娴嬭瘯鍝嶅簲寮忔晥鏋�
+
+---
+
+*娉細浠ヤ笂棰滆壊鍊煎熀浜庡浘鐗囧垎鏋愬緱鍑猴紝濡傛湁鍋忓樊璇峰強鏃跺弽棣堣皟鏁�*
\ No newline at end of file
diff --git a/wx/pages/registration/registration.js b/wx/pages/registration/registration.js
index f4ca562..0c62a99 100644
--- a/wx/pages/registration/registration.js
+++ b/wx/pages/registration/registration.js
@@ -111,7 +111,7 @@
     
     // 鍔犺浇鍖哄煙鏁版嵁
     this.loadRegions()
-  }
+  },
 
   // 鍔犺浇娲诲姩淇℃伅
   async loadActivityInfo() {
diff --git "a/\347\241\254\347\274\226\347\240\201\351\227\256\351\242\230\345\210\206\346\236\220\346\212\245\345\221\212.md" "b/\347\241\254\347\274\226\347\240\201\351\227\256\351\242\230\345\210\206\346\236\220\346\212\245\345\221\212.md"
new file mode 100644
index 0000000..8ac91ac
--- /dev/null
+++ "b/\347\241\254\347\274\226\347\240\201\351\227\256\351\242\230\345\210\206\346\236\220\346\212\245\345\221\212.md"
@@ -0,0 +1,156 @@
+# 纭紪鐮侀棶棰樺垎鏋愭姤鍛�
+
+## 闂姒傝堪
+
+缁忚繃鍏ㄩ潰妫�鏌ワ紝鍙戠幇椤圭洰涓瓨鍦ㄥ澶勭‖缂栫爜闂锛屼富瑕侀泦涓湪姣旇禌闃舵鍚嶇О鐨勫鐞嗕笂銆傝繖浜涚‖缂栫爜浼氬鑷寸郴缁熷湪鐢ㄦ埛鑷畾涔夐樁娈靛悕绉版椂鍑虹幇鍔熻兘寮傚父銆�
+
+## 鍙戠幇鐨勭‖缂栫爜闂
+
+### 1. 鍚庣鏈嶅姟灞傜‖缂栫爜锛堜弗閲嶏級
+
+**鏂囦欢锛�** `backend/src/main/java/com/rongyichuang/player/service/PlayerApplicationService.java`
+**浣嶇疆锛�** 绗�35琛�
+**闂浠g爜锛�**
+```java
+// 榛樿鍙樉绀烘捣閫夐樁娈电殑鏁版嵁锛岃繃婊ゆ帀澶嶈禌绛夊悗缁樁娈�
+whereClause.append("(stage.name NOT LIKE '%澶嶈禌%' AND stage.name NOT LIKE '%鍐宠禌%')");
+```
+
+**闂鍒嗘瀽锛�**
+- 纭紪鐮佷簡"澶嶈禌"鍜�"鍐宠禌"瀛楃涓�
+- 濡傛灉鐢ㄦ埛鑷畾涔夐樁娈靛悕绉帮紙濡�"绗簩杞�"銆�"鍗婂喅璧�"绛夛級锛岃繃婊ら�昏緫灏嗗け鏁�
+- 杩欐槸鏈�涓ラ噸鐨勭‖缂栫爜闂锛岀洿鎺ュ奖鍝嶄笟鍔¢�昏緫
+
+### 2. 鍓嶇鐣岄潰纭紪鐮侊紙涓瓑锛�
+
+**鏂囦欢锛�** `web/src/views/ActivityForm.vue`
+**浣嶇疆锛�** 绗�668琛�
+**闂浠g爜锛�**
+```javascript
+const stageNames = ['', '娴烽��', '澶嶈禌', '鍗婂喅璧�', '鍐宠禌', '鎬诲喅璧�']
+```
+
+**闂鍒嗘瀽锛�**
+- 纭紪鐮佷簡榛樿闃舵鍚嶇О鏁扮粍
+- 闄愬埗浜嗙敤鎴风殑鑷畾涔夎兘鍔�
+- 涓嶅鐏垫椿锛屾棤娉曢�傚簲涓嶅悓绫诲瀷鐨勬瘮璧�
+
+### 3. 鍓嶇姣旇禌鏅嬬骇椤甸潰纭紪鐮侊紙涓瓑锛�
+
+**鏂囦欢锛�** `web/src/views/competition-promotion/index.vue`
+**浣嶇疆锛�** 绗�300琛屻�佺310琛屻�佺430琛�
+**闂浠g爜锛�**
+```javascript
+stageName: '鍒濊禌',
+stageName: '鍐宠禌',
+currentStageName: '鍒濊禌'
+```
+
+**闂鍒嗘瀽锛�**
+- 妯℃嫙鏁版嵁涓‖缂栫爜浜嗛樁娈靛悕绉�
+- 鍙兘褰卞搷娴嬭瘯鍜屽紑鍙戠幆澧冪殑鏁版嵁涓�鑷存��
+
+### 4. 鏁版嵁搴撴祴璇曟暟鎹‖缂栫爜锛堣交寰級
+
+**鏂囦欢锛�** `db.sql`
+**浣嶇疆锛�** 绗�39-45琛�
+**闂浠g爜锛�**
+```sql
+INSERT INTO `t_activity` (..., `name`, ...) VALUES (..., '娴烽��', ...);
+INSERT INTO `t_activity` (..., `name`, ...) VALUES (..., '澶嶈禌', ...);
+```
+
+**闂鍒嗘瀽锛�**
+- 鍒濆鍖栨暟鎹腑纭紪鐮佷簡闃舵鍚嶇О
+- 铏界劧鏄祴璇曟暟鎹紝浣嗗彲鑳借瀵煎紑鍙戣�呰涓鸿繖鏄爣鍑嗗懡鍚�
+
+## 鏍规湰鍘熷洜鍒嗘瀽
+
+### 1. 缂轰箯闃舵绫诲瀷璁捐
+- 鏁版嵁搴撹〃 `t_activity` 涓彧鏈� `sort_order` 瀛楁琛ㄧず闃舵椤哄簭
+- 缂哄皯 `stage_type` 鎴� `stage_level` 瀛楁鏉ユ爣璇嗛樁娈电被鍨�
+- 涓氬姟閫昏緫渚濊禆闃舵鍚嶇О鑰岄潪闃舵绫诲瀷
+
+### 2. 杩囨护閫昏緫璁捐涓嶅綋
+- 浣跨敤瀛楃涓插尮閰嶈�岄潪缁撴瀯鍖栧瓧娈佃繘琛岃繃婊�
+- 娌℃湁鑰冭檻鐢ㄦ埛鑷畾涔夐樁娈靛悕绉扮殑鍦烘櫙
+
+## 淇敼寤鸿
+
+### 鏂规涓�锛氭坊鍔犻樁娈电被鍨嬪瓧娈碉紙鎺ㄨ崘锛�
+
+1. **鏁版嵁搴撶粨鏋勪慨鏀�**
+```sql
+ALTER TABLE t_activity ADD COLUMN stage_type INT DEFAULT 1 COMMENT '闃舵绫诲瀷锛�1=鍒濋�夐樁娈碉紝2=涓骇闃舵锛�3=楂樼骇闃舵';
+```
+
+2. **鍚庣鏈嶅姟淇敼**
+```java
+// 鏇挎崲纭紪鐮佺殑瀛楃涓插尮閰�
+// 鍘熶唬鐮侊細whereClause.append("(stage.name NOT LIKE '%澶嶈禌%' AND stage.name NOT LIKE '%鍐宠禌%')");
+// 鏂颁唬鐮侊細
+whereClause.append("stage.stage_type = 1"); // 鍙樉绀哄垵閫夐樁娈�
+```
+
+3. **鍓嶇鐣岄潰淇敼**
+- 鍦ㄦ椿鍔ㄥ垱寤鸿〃鍗曚腑娣诲姞闃舵绫诲瀷閫夋嫨
+- 绉婚櫎纭紪鐮佺殑闃舵鍚嶇О鏁扮粍
+- 鍏佽鐢ㄦ埛鑷畾涔夐樁娈靛悕绉�
+
+### 鏂规浜岋細鍩轰簬鎺掑簭椤哄簭杩囨护锛堝閫夛級
+
+1. **鍚庣鏈嶅姟淇敼**
+```java
+// 鍩轰簬sort_order杩囨护锛屽彧鏄剧ず绗竴闃舵
+whereClause.append("stage.sort_order = 1");
+```
+
+2. **浼樼偣锛�** 鏃犻渶淇敼鏁版嵁搴撶粨鏋�
+3. **缂虹偣锛�** 鐏垫椿鎬ц緝宸紝鏃犳硶鏀寔澶嶆潅鐨勯樁娈靛垎绫�
+
+### 鏂规涓夛細閰嶇疆鍖栭樁娈电鐞嗭紙鏈�浣筹級
+
+1. **鍒涘缓闃舵绫诲瀷閰嶇疆琛�**
+```sql
+CREATE TABLE t_stage_type (
+    id BIGINT PRIMARY KEY AUTO_INCREMENT,
+    name VARCHAR(50) NOT NULL COMMENT '闃舵绫诲瀷鍚嶇О',
+    code VARCHAR(20) NOT NULL COMMENT '闃舵绫诲瀷浠g爜',
+    level INT NOT NULL COMMENT '闃舵绾у埆',
+    is_initial BOOLEAN DEFAULT FALSE COMMENT '鏄惁涓哄垵閫夐樁娈�',
+    description VARCHAR(255) COMMENT '鎻忚堪'
+);
+```
+
+2. **淇敼娲诲姩琛�**
+```sql
+ALTER TABLE t_activity ADD COLUMN stage_type_id BIGINT COMMENT '闃舵绫诲瀷ID';
+```
+
+3. **涓氬姟閫昏緫淇敼**
+```java
+// 鍩轰簬闃舵绫诲瀷閰嶇疆杩涜杩囨护
+whereClause.append("EXISTS (SELECT 1 FROM t_stage_type st WHERE st.id = stage.stage_type_id AND st.is_initial = true)");
+```
+
+## 瀹炴柦浼樺厛绾�
+
+1. **楂樹紭鍏堢骇锛�** 淇 `PlayerApplicationService.java` 涓殑纭紪鐮佽繃婊ら�昏緫
+2. **涓紭鍏堢骇锛�** 淇敼鍓嶇闃舵鍚嶇О纭紪鐮�
+3. **浣庝紭鍏堢骇锛�** 娓呯悊娴嬭瘯鏁版嵁涓殑纭紪鐮�
+
+## 椋庨櫓璇勪及
+
+- **楂橀闄╋細** 鍚庣杩囨护閫昏緫淇敼鍙兘褰卞搷鐜版湁鏁版嵁鏌ヨ
+- **涓闄╋細** 鏁版嵁搴撶粨鏋勪慨鏀归渶瑕佹暟鎹縼绉�
+- **浣庨闄╋細** 鍓嶇鐣岄潰淇敼鐩稿瀹夊叏
+
+## 寤鸿瀹炴柦姝ラ
+
+1. 棣栧厛瀹炴柦鏂规浜岋紙鍩轰簬鎺掑簭椤哄簭锛夛紝蹇�熻В鍐冲綋鍓嶉棶棰�
+2. 鐒跺悗閫愭瀹炴柦鏂规涓夛紙閰嶇疆鍖栫鐞嗭級锛屾彁渚涢暱鏈熻В鍐虫柟妗�
+3. 鏈�鍚庢竻鐞嗘墍鏈夌浉鍏崇殑纭紪鐮侀棶棰�
+
+## 鎬荤粨
+
+椤圭洰涓殑纭紪鐮侀棶棰樹富瑕佹簮浜庣己涔忓悎鐞嗙殑闃舵绫诲瀷璁捐銆傚缓璁噰鐢ㄩ厤缃寲鐨勬柟寮忕鐞嗛樁娈电被鍨嬶紝鏃㈣兘瑙e喅褰撳墠鐨勭‖缂栫爜闂锛屽張鑳戒负鏈潵鐨勫姛鑳芥墿灞曟彁渚涜壇濂界殑鍩虹銆�
\ No newline at end of file

--
Gitblit v1.8.0