From 4fa9591629721797386fc11836e3a9deb69cd58c Mon Sep 17 00:00:00 2001
From: lrj <owen.stl@gmail.com>
Date: 星期三, 24 九月 2025 17:00:37 +0800
Subject: [PATCH] 修改评分逻辑,支持多个评委

---
 backend/src/main/java/com/rongyichuang/employee/entity/Employee.java                               |  152 +
 backend/src/main/java/com/rongyichuang/judge/dto/request/JudgeInput.java                           |   36 
 backend/src/main/java/com/rongyichuang/role/entity/Role.java                                       |  150 +
 DatabaseSchemaExporter.java                                                                        |  110 
 add_description_column.sql                                                                         |    7 
 web/src/api/player.js                                                                              |    8 
 backend/src/main/java/com/rongyichuang/player/dto/response/CurrentJudgeRatingResponse.java         |  110 
 backend/src/main/java/com/rongyichuang/judge/service/JudgeService.java                             |   67 
 backend/src/main/java/com/rongyichuang/role/api/RoleGraphqlApi.java                                |   68 
 backend/src/main/java/com/rongyichuang/common/enums/MediaTargetType.java                           |   92 
 backend/src/main/java/com/rongyichuang/config/GraphQLConfig.java                                   |   27 
 backend/src/main/java/com/rongyichuang/config/DatabaseMigration.java                               |   38 
 backend/src/main/java/com/rongyichuang/judge/dto/response/JudgeResponse.java                       |   36 
 backend/src/main/java/com/rongyichuang/role/repository/RoleRepository.java                         |   35 
 test_employee_api_fix.ps1                                                                          |   43 
 backend/db_actual.sql                                                                              |  398 +++
 backend/src/main/java/com/rongyichuang/judge/repository/JudgeRepository.java                       |   12 
 backend/src/main/java/com/rongyichuang/player/dto/response/PlayerInfoResponse.java                 |    2 
 backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerRatingService.java             |  291 ++
 backend/src/main/resources/graphql/employee.graphqls                                               |   47 
 web/src/components/RatingForm.vue                                                                  |  170 +
 backend/src/main/java/com/rongyichuang/tag/entity/Tag.java                                         |    2 
 project.md                                                                                         |  117 
 backend/src/main/java/DatabaseSchemaExporter.java                                                  |  110 
 backend/src/main/java/com/rongyichuang/activity/repository/ActivityRepository.java                 |    3 
 backend/src/test/java/com/rongyichuang/judge/JudgeTableSchemaTest.java                             |   55 
 backend/src/main/java/com/rongyichuang/employee/repository/EmployeeRepository.java                 |   52 
 backend/src/test/java/com/rongyichuang/TableStructureTest.java                                     |  151 +
 backend/src/main/java/com/rongyichuang/carousel/service/CarouselService.java                       |    9 
 backend/src/main/java/com/rongyichuang/common/api/MediaGraphqlApi.java                             |   13 
 backend/src/test/java/com/rongyichuang/tools/RatingTemplateFixer.java                              |   94 
 backend/src/main/resources/logback-spring.xml                                                      |   55 
 web/src/views/carousel/index.vue                                                                   |    3 
 backend/src/main/java/com/rongyichuang/player/service/PlayerApplicationService.java                |   30 
 backend/src/main/java/com/rongyichuang/activity/resolver/ActivityResolver.java                     |    4 
 backend/src/main/java/com/rongyichuang/employee/dto/response/EmployeeResponse.java                 |   86 
 test_employee_management.ps1                                                                       |   65 
 backend/src/main/java/com/rongyichuang/tag/api/TagGraphqlApi.java                                  |    8 
 web/src/api/activityPlayer.js                                                                      |  119 
 backend/src/main/java/com/rongyichuang/activity/entity/ActivityPlayerRatingItem.java               |  184 +
 web/src/components/JudgeFormSimple.vue                                                             |    5 
 backend/src/main/java/com/rongyichuang/tag/dto/response/TagResponse.java                           |    2 
 web/src/views/activity-player/rating.vue                                                           |  121 
 .gitignore                                                                                         |    2 
 backend/src/main/java/com/rongyichuang/activity/repository/ActivityPlayerRatingRepository.java     |   69 
 web/src/constants/mediaTargetType.ts                                                               |   26 
 web/src/api/activity.js                                                                            |    5 
 backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerDetailService.java             |   17 
 backend/src/test/java/com/rongyichuang/tools/RatingTemplateVerifier.java                           |   59 
 backend/src/main/resources/graphql/role.graphqls                                                   |   51 
 update_employee_table.ps1                                                                          |   18 
 backend/src/main/java/com/rongyichuang/activity/entity/ActivityPlayerRating.java                   |  156 +
 backend/src/main/java/com/rongyichuang/role/service/RoleService.java                               |   98 
 web/package.json                                                                                   |    1 
 backend/src/main/resources/graphql/player.graphqls                                                 |   43 
 backend/src/main/resources/graphql/schema.graphqls                                                 |    3 
 backend/src/test/java/com/rongyichuang/tools/RatingTemplateInserter.java                           |   99 
 web/src/api/mockData.js                                                                            |  125 +
 insert_rating_template.sql                                                                         |   30 
 backend/src/main/java/com/rongyichuang/employee/resolver/EmployeeResolver.java                     |   65 
 backend/src/main/java/com/rongyichuang/activity/repository/ActivityPlayerRatingItemRepository.java |   51 
 web/src/views/employee/EmployeeForm.vue                                                            |  267 ++
 web/src/views/player/index.vue                                                                     |  126 
 backend/src/main/java/com/rongyichuang/employee/service/EmployeeService.java                       |  185 +
 backend/src/main/java/com/rongyichuang/common/api/MediaTestController.java                         |    4 
 backend/src/main/java/com/rongyichuang/employee/dto/request/EmployeeInput.java                     |   65 
 backend/src/main/resources/db/migration/V2__add_judge_fields.sql                                   |    7 
 web/public/test-rating.html                                                                        |  126 +
 web/src/views/carousel/CarouselForm.vue                                                            |    5 
 backend/src/main/java/com/rongyichuang/role/dto/response/RoleResponse.java                         |   79 
 backend/src/test/java/com/rongyichuang/judge/JudgeAvatarTest.java                                  |   52 
 backend/src/test/java/com/rongyichuang/tools/DataInsertTest.java                                   |    4 
 db_actual.sql                                                                                      |  376 +++
 backend/src/main/java/com/rongyichuang/tools/DatabaseSchemaExporter.java                           |  114 
 backend/src/main/java/com/rongyichuang/activity/service/ActivityService.java                       |   62 
 backend/src/main/java/com/rongyichuang/player/api/PlayerGraphqlApi.java                            |   58 
 web/src/api/role.ts                                                                                |  244 ++
 backend/src/main/java/com/rongyichuang/judge/entity/Judge.java                                     |   54 
 backend/src/main/java/com/rongyichuang/player/dto/response/CurrentJudgeInfoResponse.java           |   53 
 backend/src/main/java/com/rongyichuang/player/dto/response/JudgeRatingStatusResponse.java          |   66 
 web/src/views/ActivityForm.vue                                                                     |    5 
 web/src/api/employee.ts                                                                            |  210 +
 backend/src/main/java/com/rongyichuang/tag/service/DataInitService.java                            |    6 
 backend/src/test/java/com/rongyichuang/tools/StageIdFixTest.java                                   |    2 
 backend/src/main/java/com/rongyichuang/tag/repository/TagRepository.java                           |    4 
 backend/src/main/java/com/rongyichuang/tools/MockDataInserter.java                                 |    4 
 db.sql                                                                                             |  552 ++--
 backend/src/main/java/com/rongyichuang/common/util/UserContextUtil.java                            |  133 +
 backend/src/test/java/com/rongyichuang/region/RegionTableTest.java                                 |    4 
 web/src/views/employee/index.vue                                                                   |  179 
 90 files changed, 6,633 insertions(+), 518 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7d9fe17..ef228d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,8 @@
 
 # 鎺掗櫎 Maven 鏋勫缓鐩綍锛坱arget锛�
 target/
+# 鎺掗櫎UI鐩綍
+UI/
 
 # 鍙�夛細濡傛灉鏈夊叾浠栨瀯寤哄伐鍏风殑杈撳嚭鐩綍锛屼篃鍙互涓�骞舵帓闄�
 # 渚嬪 Gradle 鐨勬瀯寤虹洰褰�
diff --git a/DatabaseSchemaExporter.java b/DatabaseSchemaExporter.java
new file mode 100644
index 0000000..7f3d150
--- /dev/null
+++ b/DatabaseSchemaExporter.java
@@ -0,0 +1,110 @@
+import java.io.FileWriter;
+import java.io.IOException;
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 鐙珛鐨勬暟鎹簱琛ㄧ粨鏋勫鍑哄伐鍏�
+ */
+public class DatabaseSchemaExporter {
+
+    private static final String URL = "jdbc:mysql://139.155.104.10:3306/ryc?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
+    private static final String USERNAME = "ryc";
+    private static final String PASSWORD = "KiYap3E8X8RLcM6T";
+    private static final String DATABASE_NAME = "ryc";
+
+    public static void main(String[] args) {
+        new DatabaseSchemaExporter().exportDatabaseSchema();
+    }
+
+    public void exportDatabaseSchema() {
+        System.out.println("馃攧 寮�濮嬪鍑烘暟鎹簱琛ㄧ粨鏋�...");
+        
+        try {
+            // 鍔犺浇MySQL椹卞姩
+            Class.forName("com.mysql.cj.jdbc.Driver");
+            
+            try (Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD)) {
+                StringBuilder sqlBuilder = new StringBuilder();
+                sqlBuilder.append("-- Database schema dump for ryc\n");
+                sqlBuilder.append("-- Generated at: ").append(new java.util.Date()).append("\n\n");
+
+                // 鑾峰彇鎵�鏈夎〃鍚�
+                List<String> tableNames = getAllTableNames(conn);
+                
+                for (String tableName : tableNames) {
+                    System.out.println("馃搵 瀵煎嚭琛�: " + tableName);
+                    String createTableSql = getCreateTableStatement(conn, tableName);
+                    sqlBuilder.append(createTableSql).append("\n\n");
+                }
+
+                // 鍐欏叆鏂囦欢
+                String outputPath = "db_actual.sql";
+                try (FileWriter writer = new FileWriter(outputPath)) {
+                    writer.write(sqlBuilder.toString());
+                }
+                
+                System.out.println("鉁� 鏁版嵁搴撹〃缁撴瀯瀵煎嚭瀹屾垚: " + outputPath);
+                
+                // 鐗瑰埆妫�鏌_employee琛ㄧ殑缁撴瀯
+                checkEmployeeTableStructure(conn);
+                
+            }
+        } catch (Exception e) {
+            System.err.println("鉂� 瀵煎嚭鏁版嵁搴撹〃缁撴瀯澶辫触: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    private List<String> getAllTableNames(Connection conn) throws SQLException {
+        List<String> tableNames = new ArrayList<>();
+        DatabaseMetaData metaData = conn.getMetaData();
+        
+        try (ResultSet tables = metaData.getTables(DATABASE_NAME, null, "%", new String[]{"TABLE"})) {
+            while (tables.next()) {
+                String tableName = tables.getString("TABLE_NAME");
+                if (tableName.startsWith("t_")) { // 鍙鍑轰笟鍔¤〃
+                    tableNames.add(tableName);
+                }
+            }
+        }
+        
+        return tableNames;
+    }
+
+    private String getCreateTableStatement(Connection conn, String tableName) throws SQLException {
+        try (Statement stmt = conn.createStatement();
+             ResultSet rs = stmt.executeQuery("SHOW CREATE TABLE " + tableName)) {
+            
+            if (rs.next()) {
+                String createSql = rs.getString(2);
+                return "-- Table: " + tableName + "\n" + createSql + ";";
+            }
+        }
+        return "";
+    }
+
+    private void checkEmployeeTableStructure(Connection conn) throws SQLException {
+        System.out.println("\n馃攳 妫�鏌_employee琛ㄧ粨鏋�:");
+        
+        DatabaseMetaData metaData = conn.getMetaData();
+        try (ResultSet columns = metaData.getColumns(DATABASE_NAME, null, "t_employee", null)) {
+            while (columns.next()) {
+                String columnName = columns.getString("COLUMN_NAME");
+                String dataType = columns.getString("TYPE_NAME");
+                int columnSize = columns.getInt("COLUMN_SIZE");
+                String isNullable = columns.getString("IS_NULLABLE");
+                String defaultValue = columns.getString("COLUMN_DEF");
+                
+                System.out.printf("  馃摑 %s: %s(%d) %s %s%n", 
+                    columnName, 
+                    dataType, 
+                    columnSize,
+                    "YES".equals(isNullable) ? "NULL" : "NOT NULL",
+                    defaultValue != null ? "DEFAULT " + defaultValue : ""
+                );
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/add_description_column.sql b/add_description_column.sql
new file mode 100644
index 0000000..1dda1de
--- /dev/null
+++ b/add_description_column.sql
@@ -0,0 +1,7 @@
+USE ryc;
+
+-- 娣诲姞 description 瀛楁鍒� t_employee 琛�
+ALTER TABLE t_employee ADD COLUMN description varchar(255) AFTER role_code;
+
+-- 鏌ョ湅琛ㄧ粨鏋勭‘璁�
+DESCRIBE t_employee;
\ No newline at end of file
diff --git a/backend/db_actual.sql b/backend/db_actual.sql
new file mode 100644
index 0000000..bb5e6e1
--- /dev/null
+++ b/backend/db_actual.sql
@@ -0,0 +1,398 @@
+-- Database schema dump for ryc
+-- Generated at: Wed Sep 24 16:07:24 GMT+08:00 2025
+
+-- Table: t_activity
+CREATE TABLE `t_activity` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `pid` bigint NOT NULL DEFAULT '0',
+  `path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
+  `signup_deadline` datetime NOT NULL,
+  `match_time` datetime DEFAULT NULL,
+  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `rating_scheme_id` bigint NOT NULL,
+  `player_max` int DEFAULT NULL COMMENT '浜烘暟涓婇檺',
+  `state` int NOT NULL DEFAULT '1' COMMENT '0:鏈彂甯冿紝 1锛氬彂甯冿細2锛氬叧闂�',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_activity_rating_scheme` (`rating_scheme_id`) USING BTREE,
+  KEY `idx_t_activity_deadline` (`signup_deadline`) USING BTREE,
+  CONSTRAINT `fk_t_activity_rating_scheme` FOREIGN KEY (`rating_scheme_id`) REFERENCES `t_rating_scheme` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE=InnoDB AUTO_INCREMENT=62 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_activity_judge
+CREATE TABLE `t_activity_judge` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `activity_id` bigint NOT NULL,
+  `stage_id` bigint NOT NULL,
+  `judge_id` bigint NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int DEFAULT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `uq_stage_judge` (`stage_id`,`judge_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_activity_player
+CREATE TABLE `t_activity_player` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `activity_id` bigint NOT NULL,
+  `stage_id` bigint NOT NULL COMMENT '姣旇禌闃舵锛岄�昏緫鍜宼_activity_judge 淇濇寔涓�鑷淬��',
+  `player_id` bigint NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `reject_reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `judge_id` bigint DEFAULT NULL COMMENT '璇勫',
+  `feedback` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
+  `total_score` decimal(19,4) DEFAULT NULL COMMENT '浣庡垎',
+  `rank` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '鍚嶆',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_activity_player_rating
+CREATE TABLE `t_activity_player_rating` (
+  `id` bigint NOT NULL,
+  `activity_id` bigint NOT NULL,
+  `activity_player_id` bigint DEFAULT NULL,
+  `stage_id` bigint NOT NULL,
+  `player_id` bigint NOT NULL COMMENT '鍐椾綑瀛楁',
+  `judge_id` bigint DEFAULT NULL,
+  `total_score` decimal(19,2) DEFAULT NULL,
+  `feedback` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '璇勪环鍐呭',
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+
+-- Table: t_activity_player_rating_item
+CREATE TABLE `t_activity_player_rating_item` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `activity_id` bigint NOT NULL,
+  `activity_player_id` bigint NOT NULL,
+  `activity_player_rating_id` bigint NOT NULL,
+  `stage_id` bigint NOT NULL,
+  `player_id` bigint NOT NULL,
+  `judge_id` bigint NOT NULL,
+  `rating_scheme_id` bigint NOT NULL,
+  `rating_item_id` bigint NOT NULL,
+  `score` decimal(10,2) NOT NULL,
+  `feedback` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
+  `state` int NOT NULL DEFAULT '1',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_carousel
+CREATE TABLE `t_carousel` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `title` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `sort_order` int DEFAULT NULL,
+  `state` int NOT NULL DEFAULT '1' COMMENT '0:鍏抽棴锛�1锛氫娇鐢�',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='杞挱鍥�';
+
+-- Table: t_employee
+CREATE TABLE `t_employee` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `password` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `role_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `user_id` bigint NOT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  `description` varchar(255) DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `phone` (`phone`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_employee_role
+CREATE TABLE `t_employee_role` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `employee_id` bigint NOT NULL,
+  `role_id` bigint NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_user_role_role` (`role_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_judge
+CREATE TABLE `t_judge` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `user_id` bigint DEFAULT NULL,
+  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `gender` int DEFAULT NULL,
+  `state` int NOT NULL DEFAULT '1',
+  `role_id` bigint DEFAULT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  `title` varchar(128) DEFAULT NULL COMMENT '鑱屼綅/澶磋',
+  `company` varchar(128) DEFAULT NULL COMMENT '鍏徃/鏈烘瀯',
+  `introduction` text COMMENT '涓汉浠嬬粛',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `phone` (`phone`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_judge_tag
+CREATE TABLE `t_judge_tag` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `judge_id` bigint NOT NULL,
+  `tag_id` bigint NOT NULL,
+  `state` int NOT NULL DEFAULT '1',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_judge_major_tag` (`tag_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_media
+CREATE TABLE `t_media` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `target_type` int NOT NULL,
+  `target_id` bigint NOT NULL,
+  `media_type` int NOT NULL,
+  `path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '鑵捐浜戠殑瀛樺偍妗跺湴鍧�',
+  `thumb_path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `file_ext` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `file_size` int NOT NULL,
+  `duration` int DEFAULT NULL COMMENT '瑙嗛鐨勯暱搴︾',
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_notification_task
+CREATE TABLE `t_notification_task` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `channel` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `target_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '1:瀛﹀憳锛�2锛氳瘎濮旓紝3锛氬伐浣滀汉鍛�',
+  `target_id` bigint NOT NULL,
+  `payload` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '娑堟伅鍐呭',
+  `error_message` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `retry_count` int NOT NULL,
+  `next_retry_at` datetime DEFAULT NULL,
+  `state` tinyint(1) NOT NULL DEFAULT '1',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_permission
+CREATE TABLE `t_permission` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `code` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `category` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` tinyint(1) NOT NULL DEFAULT '1',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE,
+  KEY `idx_t_permission_code` (`code`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_player
+CREATE TABLE `t_player` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `role_id` bigint NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `gender` int DEFAULT NULL COMMENT '0:濂筹紝1锛氱敺',
+  `education` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `introduction` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
+  `audit_state` int NOT NULL COMMENT '0绛夊緟瀹℃牳锛�1锛氬鏍搁�氳繃锛�2锛氫笉閫氳繃',
+  `reject_reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `final_score` decimal(10,2) DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  `user_id` bigint NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `phone` (`phone`) USING BTREE,
+  KEY `idx_t_player_activity_status` (`audit_state`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_rating_item
+CREATE TABLE `t_rating_item` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `scheme_id` bigint NOT NULL,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `max_score` int NOT NULL,
+  `order_no` int NOT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `idx_t_rating_item_scheme` (`scheme_id`) USING BTREE,
+  CONSTRAINT `fk_t_rating_item_scheme` FOREIGN KEY (`scheme_id`) REFERENCES `t_rating_scheme` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_rating_scheme
+CREATE TABLE `t_rating_scheme` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_region
+CREATE TABLE `t_region` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `pid` bigint NOT NULL COMMENT '鑷叧鑱�',
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `level` int NOT NULL,
+  `leaf_flag` tinyint(1) NOT NULL DEFAULT '0',
+  `full_path` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_role
+CREATE TABLE `t_role` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE,
+  KEY `idx_t_role_code` (`code`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_role_permission
+CREATE TABLE `t_role_permission` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `role_id` bigint NOT NULL,
+  `permission_id` bigint NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_role_permission_perm` (`permission_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_tag
+CREATE TABLE `t_tag` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `category` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE,
+  KEY `idx_t_tag_category` (`category`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_user
+CREATE TABLE `t_user` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `gender` int DEFAULT NULL,
+  `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `birthday` date DEFAULT NULL,
+  `wx_openid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `wx_unionid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `wx_oa_openid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  `mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `uq_openid` (`wx_openid`) USING BTREE,
+  KEY `uq_unionid` (`wx_unionid`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
diff --git a/backend/src/main/java/DatabaseSchemaExporter.java b/backend/src/main/java/DatabaseSchemaExporter.java
new file mode 100644
index 0000000..7f3d150
--- /dev/null
+++ b/backend/src/main/java/DatabaseSchemaExporter.java
@@ -0,0 +1,110 @@
+import java.io.FileWriter;
+import java.io.IOException;
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 鐙珛鐨勬暟鎹簱琛ㄧ粨鏋勫鍑哄伐鍏�
+ */
+public class DatabaseSchemaExporter {
+
+    private static final String URL = "jdbc:mysql://139.155.104.10:3306/ryc?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
+    private static final String USERNAME = "ryc";
+    private static final String PASSWORD = "KiYap3E8X8RLcM6T";
+    private static final String DATABASE_NAME = "ryc";
+
+    public static void main(String[] args) {
+        new DatabaseSchemaExporter().exportDatabaseSchema();
+    }
+
+    public void exportDatabaseSchema() {
+        System.out.println("馃攧 寮�濮嬪鍑烘暟鎹簱琛ㄧ粨鏋�...");
+        
+        try {
+            // 鍔犺浇MySQL椹卞姩
+            Class.forName("com.mysql.cj.jdbc.Driver");
+            
+            try (Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD)) {
+                StringBuilder sqlBuilder = new StringBuilder();
+                sqlBuilder.append("-- Database schema dump for ryc\n");
+                sqlBuilder.append("-- Generated at: ").append(new java.util.Date()).append("\n\n");
+
+                // 鑾峰彇鎵�鏈夎〃鍚�
+                List<String> tableNames = getAllTableNames(conn);
+                
+                for (String tableName : tableNames) {
+                    System.out.println("馃搵 瀵煎嚭琛�: " + tableName);
+                    String createTableSql = getCreateTableStatement(conn, tableName);
+                    sqlBuilder.append(createTableSql).append("\n\n");
+                }
+
+                // 鍐欏叆鏂囦欢
+                String outputPath = "db_actual.sql";
+                try (FileWriter writer = new FileWriter(outputPath)) {
+                    writer.write(sqlBuilder.toString());
+                }
+                
+                System.out.println("鉁� 鏁版嵁搴撹〃缁撴瀯瀵煎嚭瀹屾垚: " + outputPath);
+                
+                // 鐗瑰埆妫�鏌_employee琛ㄧ殑缁撴瀯
+                checkEmployeeTableStructure(conn);
+                
+            }
+        } catch (Exception e) {
+            System.err.println("鉂� 瀵煎嚭鏁版嵁搴撹〃缁撴瀯澶辫触: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    private List<String> getAllTableNames(Connection conn) throws SQLException {
+        List<String> tableNames = new ArrayList<>();
+        DatabaseMetaData metaData = conn.getMetaData();
+        
+        try (ResultSet tables = metaData.getTables(DATABASE_NAME, null, "%", new String[]{"TABLE"})) {
+            while (tables.next()) {
+                String tableName = tables.getString("TABLE_NAME");
+                if (tableName.startsWith("t_")) { // 鍙鍑轰笟鍔¤〃
+                    tableNames.add(tableName);
+                }
+            }
+        }
+        
+        return tableNames;
+    }
+
+    private String getCreateTableStatement(Connection conn, String tableName) throws SQLException {
+        try (Statement stmt = conn.createStatement();
+             ResultSet rs = stmt.executeQuery("SHOW CREATE TABLE " + tableName)) {
+            
+            if (rs.next()) {
+                String createSql = rs.getString(2);
+                return "-- Table: " + tableName + "\n" + createSql + ";";
+            }
+        }
+        return "";
+    }
+
+    private void checkEmployeeTableStructure(Connection conn) throws SQLException {
+        System.out.println("\n馃攳 妫�鏌_employee琛ㄧ粨鏋�:");
+        
+        DatabaseMetaData metaData = conn.getMetaData();
+        try (ResultSet columns = metaData.getColumns(DATABASE_NAME, null, "t_employee", null)) {
+            while (columns.next()) {
+                String columnName = columns.getString("COLUMN_NAME");
+                String dataType = columns.getString("TYPE_NAME");
+                int columnSize = columns.getInt("COLUMN_SIZE");
+                String isNullable = columns.getString("IS_NULLABLE");
+                String defaultValue = columns.getString("COLUMN_DEF");
+                
+                System.out.printf("  馃摑 %s: %s(%d) %s %s%n", 
+                    columnName, 
+                    dataType, 
+                    columnSize,
+                    "YES".equals(isNullable) ? "NULL" : "NOT NULL",
+                    defaultValue != null ? "DEFAULT " + defaultValue : ""
+                );
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/activity/entity/ActivityPlayerRating.java b/backend/src/main/java/com/rongyichuang/activity/entity/ActivityPlayerRating.java
new file mode 100644
index 0000000..99b1d5d
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/activity/entity/ActivityPlayerRating.java
@@ -0,0 +1,156 @@
+package com.rongyichuang.activity.entity;
+
+import com.rongyichuang.common.entity.BaseEntity;
+import jakarta.persistence.*;
+
+import java.math.BigDecimal;
+
+/**
+ * 娲诲姩閫夋墜璇勫垎瀹炰綋绫�
+ * 瀵瑰簲鏁版嵁搴撹〃锛歵_activity_player_rating
+ */
+@Entity
+@Table(name = "t_activity_player_rating")
+public class ActivityPlayerRating extends BaseEntity {
+
+    /**
+     * 娲诲姩ID
+     */
+    @Column(name = "activity_id", nullable = false)
+    private Long activityId;
+
+    /**
+     * 娲诲姩閫夋墜ID
+     */
+    @Column(name = "activity_player_id", nullable = false)
+    private Long activityPlayerId;
+
+    /**
+     * 閫夋墜ID
+     */
+    @Column(name = "player_id", nullable = false)
+    private Long playerId;
+
+    /**
+     * 璇勫ID
+     */
+    @Column(name = "judge_id", nullable = false)
+    private Long judgeId;
+
+    /**
+     * 璇勫垎鏂规ID
+     */
+    @Column(name = "rating_scheme_id", nullable = false)
+    private Long ratingSchemeId;
+
+    /**
+     * 鎬诲垎
+     */
+    @Column(name = "total_score", precision = 10, scale = 2)
+    private BigDecimal totalScore;
+
+    /**
+     * 璇勫垎鐘舵�侊細0-鏈瘎鍒嗭紝1-宸茶瘎鍒�
+     */
+    @Column(name = "status", nullable = false)
+    private Integer status = 0;
+
+    /**
+     * 璇勫垎澶囨敞
+     */
+    @Column(name = "remark", length = 500)
+    private String remark;
+
+    // 鏋勯�犲嚱鏁�
+    public ActivityPlayerRating() {}
+
+    public ActivityPlayerRating(Long activityId, Long activityPlayerId, Long playerId, 
+                               Long judgeId, Long ratingSchemeId) {
+        this.activityId = activityId;
+        this.activityPlayerId = activityPlayerId;
+        this.playerId = playerId;
+        this.judgeId = judgeId;
+        this.ratingSchemeId = ratingSchemeId;
+        this.status = 0;
+    }
+
+    // Getter鍜孲etter鏂规硶
+    public Long getActivityId() {
+        return activityId;
+    }
+
+    public void setActivityId(Long activityId) {
+        this.activityId = activityId;
+    }
+
+    public Long getActivityPlayerId() {
+        return activityPlayerId;
+    }
+
+    public void setActivityPlayerId(Long activityPlayerId) {
+        this.activityPlayerId = activityPlayerId;
+    }
+
+    public Long getPlayerId() {
+        return playerId;
+    }
+
+    public void setPlayerId(Long playerId) {
+        this.playerId = playerId;
+    }
+
+    public Long getJudgeId() {
+        return judgeId;
+    }
+
+    public void setJudgeId(Long judgeId) {
+        this.judgeId = judgeId;
+    }
+
+    public Long getRatingSchemeId() {
+        return ratingSchemeId;
+    }
+
+    public void setRatingSchemeId(Long ratingSchemeId) {
+        this.ratingSchemeId = ratingSchemeId;
+    }
+
+    public BigDecimal getTotalScore() {
+        return totalScore;
+    }
+
+    public void setTotalScore(BigDecimal totalScore) {
+        this.totalScore = totalScore;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    @Override
+    public String toString() {
+        return "ActivityPlayerRating{" +
+                "id=" + getId() +
+                ", activityId=" + activityId +
+                ", activityPlayerId=" + activityPlayerId +
+                ", playerId=" + playerId +
+                ", judgeId=" + judgeId +
+                ", ratingSchemeId=" + ratingSchemeId +
+                ", totalScore=" + totalScore +
+                ", status=" + status +
+                ", remark='" + remark + '\'' +
+                '}';
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/activity/entity/ActivityPlayerRatingItem.java b/backend/src/main/java/com/rongyichuang/activity/entity/ActivityPlayerRatingItem.java
new file mode 100644
index 0000000..51405b1
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/activity/entity/ActivityPlayerRatingItem.java
@@ -0,0 +1,184 @@
+package com.rongyichuang.activity.entity;
+
+import com.rongyichuang.common.entity.BaseEntity;
+import jakarta.persistence.*;
+
+import java.math.BigDecimal;
+
+/**
+ * 娲诲姩閫夋墜璇勫垎椤瑰疄浣撶被
+ * 瀵瑰簲鏁版嵁搴撹〃锛歵_activity_player_rating_item
+ */
+@Entity
+@Table(name = "t_activity_player_rating_item")
+public class ActivityPlayerRatingItem extends BaseEntity {
+
+    /**
+     * 娲诲姩閫夋墜璇勫垎ID锛堝叧鑱攖_activity_player_rating琛級
+     */
+    @Column(name = "activity_player_rating_id", nullable = false)
+    private Long activityPlayerRatingId;
+
+    /**
+     * 璇勫垎椤笽D锛堝叧鑱攖_rating_item琛級
+     */
+    @Column(name = "rating_item_id", nullable = false)
+    private Long ratingItemId;
+
+    /**
+     * 璇勫垎椤瑰悕绉帮紙鍐椾綑瀛楁锛屼究浜庢煡璇級
+     */
+    @Column(name = "rating_item_name", length = 100)
+    private String ratingItemName;
+
+    /**
+     * 璇勫垎椤规潈閲嶏紙鍐椾綑瀛楁锛屼究浜庤绠楋級
+     */
+    @Column(name = "weight", precision = 5, scale = 2)
+    private BigDecimal weight;
+
+    /**
+     * 璇勫垎椤规弧鍒嗭紙鍐椾綑瀛楁锛屼究浜庤绠楋級
+     */
+    @Column(name = "max_score", precision = 10, scale = 2)
+    private BigDecimal maxScore;
+
+    /**
+     * 瀹為檯寰楀垎
+     */
+    @Column(name = "score", precision = 10, scale = 2, nullable = false)
+    private BigDecimal score;
+
+    /**
+     * 鍔犳潈寰楀垎锛坰core * weight锛�
+     */
+    @Column(name = "weighted_score", precision = 10, scale = 2)
+    private BigDecimal weightedScore;
+
+    /**
+     * 璇勫垎澶囨敞
+     */
+    @Column(name = "remark", length = 500)
+    private String remark;
+
+    // 鏋勯�犲嚱鏁�
+    public ActivityPlayerRatingItem() {}
+
+    public ActivityPlayerRatingItem(Long activityPlayerRatingId, Long ratingItemId, 
+                                   String ratingItemName, BigDecimal weight, 
+                                   BigDecimal maxScore, BigDecimal score) {
+        this.activityPlayerRatingId = activityPlayerRatingId;
+        this.ratingItemId = ratingItemId;
+        this.ratingItemName = ratingItemName;
+        this.weight = weight;
+        this.maxScore = maxScore;
+        this.score = score;
+        // 璁$畻鍔犳潈寰楀垎
+        if (score != null && weight != null) {
+            this.weightedScore = score.multiply(weight);
+        }
+    }
+
+    // Getter鍜孲etter鏂规硶
+    public Long getActivityPlayerRatingId() {
+        return activityPlayerRatingId;
+    }
+
+    public void setActivityPlayerRatingId(Long activityPlayerRatingId) {
+        this.activityPlayerRatingId = activityPlayerRatingId;
+    }
+
+    public Long getRatingItemId() {
+        return ratingItemId;
+    }
+
+    public void setRatingItemId(Long ratingItemId) {
+        this.ratingItemId = ratingItemId;
+    }
+
+    public String getRatingItemName() {
+        return ratingItemName;
+    }
+
+    public void setRatingItemName(String ratingItemName) {
+        this.ratingItemName = ratingItemName;
+    }
+
+    public BigDecimal getWeight() {
+        return weight;
+    }
+
+    public void setWeight(BigDecimal weight) {
+        this.weight = weight;
+        // 閲嶆柊璁$畻鍔犳潈寰楀垎
+        updateWeightedScore();
+    }
+
+    public BigDecimal getMaxScore() {
+        return maxScore;
+    }
+
+    public void setMaxScore(BigDecimal maxScore) {
+        this.maxScore = maxScore;
+    }
+
+    public BigDecimal getScore() {
+        return score;
+    }
+
+    public void setScore(BigDecimal score) {
+        this.score = score;
+        // 閲嶆柊璁$畻鍔犳潈寰楀垎
+        updateWeightedScore();
+    }
+
+    public BigDecimal getWeightedScore() {
+        return weightedScore;
+    }
+
+    public void setWeightedScore(BigDecimal weightedScore) {
+        this.weightedScore = weightedScore;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    /**
+     * 鏇存柊鍔犳潈寰楀垎
+     */
+    private void updateWeightedScore() {
+        if (score != null && weight != null) {
+            this.weightedScore = score.multiply(weight);
+        }
+    }
+
+    /**
+     * 璁$畻寰楀垎鐜囷紙瀹為檯寰楀垎/婊″垎锛�
+     */
+    public BigDecimal getScoreRate() {
+        if (score != null && maxScore != null && maxScore.compareTo(BigDecimal.ZERO) > 0) {
+            return score.divide(maxScore, 4, BigDecimal.ROUND_HALF_UP);
+        }
+        return BigDecimal.ZERO;
+    }
+
+    @Override
+    public String toString() {
+        return "ActivityPlayerRatingItem{" +
+                "id=" + getId() +
+                ", activityPlayerRatingId=" + activityPlayerRatingId +
+                ", ratingItemId=" + ratingItemId +
+                ", ratingItemName='" + ratingItemName + '\'' +
+                ", weight=" + weight +
+                ", maxScore=" + maxScore +
+                ", score=" + score +
+                ", weightedScore=" + weightedScore +
+                ", remark='" + remark + '\'' +
+                '}';
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/activity/repository/ActivityPlayerRatingItemRepository.java b/backend/src/main/java/com/rongyichuang/activity/repository/ActivityPlayerRatingItemRepository.java
new file mode 100644
index 0000000..1420a5d
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/activity/repository/ActivityPlayerRatingItemRepository.java
@@ -0,0 +1,51 @@
+package com.rongyichuang.activity.repository;
+
+import com.rongyichuang.activity.entity.ActivityPlayerRatingItem;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 娲诲姩閫夋墜璇勫垎椤规暟鎹闂眰
+ */
+@Repository
+public interface ActivityPlayerRatingItemRepository extends JpaRepository<ActivityPlayerRatingItem, Long> {
+
+    /**
+     * 鏍规嵁娲诲姩閫夋墜璇勫垎ID鏌ユ壘鎵�鏈夎瘎鍒嗛」
+     */
+    List<ActivityPlayerRatingItem> findByActivityPlayerRatingId(Long activityPlayerRatingId);
+
+    /**
+     * 鏍规嵁璇勫垎椤笽D鏌ユ壘鎵�鏈夎瘎鍒嗚褰�
+     */
+    List<ActivityPlayerRatingItem> findByRatingItemId(Long ratingItemId);
+
+    /**
+     * 鍒犻櫎鎸囧畾娲诲姩閫夋墜璇勫垎鐨勬墍鏈夎瘎鍒嗛」
+     */
+    void deleteByActivityPlayerRatingId(Long activityPlayerRatingId);
+
+    /**
+     * 璁$畻鎸囧畾娲诲姩閫夋墜璇勫垎鐨勬�诲垎
+     */
+    @Query("SELECT SUM(i.weightedScore) FROM ActivityPlayerRatingItem i WHERE i.activityPlayerRatingId = :activityPlayerRatingId")
+    BigDecimal calculateTotalScoreByActivityPlayerRatingId(@Param("activityPlayerRatingId") Long activityPlayerRatingId);
+
+    /**
+     * 鏍规嵁娲诲姩閫夋墜璇勫垎ID鍜岃瘎鍒嗛」ID鏌ユ壘璇勫垎椤�
+     */
+    @Query("SELECT i FROM ActivityPlayerRatingItem i WHERE i.activityPlayerRatingId = :activityPlayerRatingId AND i.ratingItemId = :ratingItemId")
+    ActivityPlayerRatingItem findByActivityPlayerRatingIdAndRatingItemId(@Param("activityPlayerRatingId") Long activityPlayerRatingId, 
+                                                                         @Param("ratingItemId") Long ratingItemId);
+
+    /**
+     * 鎵归噺鏌ヨ澶氫釜娲诲姩閫夋墜璇勫垎鐨勮瘎鍒嗛」
+     */
+    @Query("SELECT i FROM ActivityPlayerRatingItem i WHERE i.activityPlayerRatingId IN :activityPlayerRatingIds ORDER BY i.activityPlayerRatingId, i.ratingItemId")
+    List<ActivityPlayerRatingItem> findByActivityPlayerRatingIdIn(@Param("activityPlayerRatingIds") List<Long> activityPlayerRatingIds);
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/activity/repository/ActivityPlayerRatingRepository.java b/backend/src/main/java/com/rongyichuang/activity/repository/ActivityPlayerRatingRepository.java
new file mode 100644
index 0000000..9b208ad
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/activity/repository/ActivityPlayerRatingRepository.java
@@ -0,0 +1,69 @@
+package com.rongyichuang.activity.repository;
+
+import com.rongyichuang.activity.entity.ActivityPlayerRating;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 娲诲姩閫夋墜璇勫垎鏁版嵁璁块棶灞�
+ */
+@Repository
+public interface ActivityPlayerRatingRepository extends JpaRepository<ActivityPlayerRating, Long> {
+
+    /**
+     * 鏍规嵁娲诲姩閫夋墜ID鍜岃瘎濮擨D鏌ユ壘璇勫垎璁板綍
+     */
+    Optional<ActivityPlayerRating> findByActivityPlayerIdAndJudgeId(Long activityPlayerId, Long judgeId);
+
+    /**
+     * 鏍规嵁娲诲姩閫夋墜ID鏌ユ壘鎵�鏈夎瘎鍒嗚褰�
+     */
+    List<ActivityPlayerRating> findByActivityPlayerId(Long activityPlayerId);
+
+    /**
+     * 鏍规嵁娲诲姩ID鏌ユ壘鎵�鏈夎瘎鍒嗚褰�
+     */
+    List<ActivityPlayerRating> findByActivityId(Long activityId);
+
+    /**
+     * 鏍规嵁璇勫ID鏌ユ壘鎵�鏈夎瘎鍒嗚褰�
+     */
+    List<ActivityPlayerRating> findByJudgeId(Long judgeId);
+
+    /**
+     * 鏍规嵁閫夋墜ID鏌ユ壘鎵�鏈夎瘎鍒嗚褰�
+     */
+    List<ActivityPlayerRating> findByPlayerId(Long playerId);
+
+    /**
+     * 妫�鏌ユ寚瀹氳瘎濮旀槸鍚﹀凡瀵规寚瀹氶�夋墜璇勫垎
+     */
+    boolean existsByActivityPlayerIdAndJudgeId(Long activityPlayerId, Long judgeId);
+
+    /**
+     * 缁熻鎸囧畾娲诲姩閫夋墜鐨勮瘎鍒嗘暟閲�
+     */
+    @Query("SELECT COUNT(r) FROM ActivityPlayerRating r WHERE r.activityPlayerId = :activityPlayerId AND r.status = 1")
+    long countCompletedRatingsByActivityPlayerId(@Param("activityPlayerId") Long activityPlayerId);
+
+    /**
+     * 鑾峰彇鎸囧畾娲诲姩閫夋墜鐨勬墍鏈夊凡瀹屾垚璇勫垎
+     */
+    @Query("SELECT r FROM ActivityPlayerRating r WHERE r.activityPlayerId = :activityPlayerId AND r.status = 1")
+    List<ActivityPlayerRating> findCompletedRatingsByActivityPlayerId(@Param("activityPlayerId") Long activityPlayerId);
+
+    /**
+     * 鏍规嵁娲诲姩ID鍜岃瘎濮擨D鏌ユ壘璇勫垎璁板綍
+     */
+    List<ActivityPlayerRating> findByActivityIdAndJudgeId(Long activityId, Long judgeId);
+
+    /**
+     * 鍒犻櫎鎸囧畾娲诲姩閫夋墜鐨勬寚瀹氳瘎濮旇瘎鍒嗚褰�
+     */
+    void deleteByActivityPlayerIdAndJudgeId(Long activityPlayerId, Long judgeId);
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/activity/repository/ActivityRepository.java b/backend/src/main/java/com/rongyichuang/activity/repository/ActivityRepository.java
index 3863043..e0ffd78 100644
--- a/backend/src/main/java/com/rongyichuang/activity/repository/ActivityRepository.java
+++ b/backend/src/main/java/com/rongyichuang/activity/repository/ActivityRepository.java
@@ -28,6 +28,9 @@
     // 涓存椂娴嬭瘯锛氭煡璇㈡墍鏈夋瘮璧涳紙涓嶄娇鐢╯tate瀛楁锛�
     List<Activity> findByPidOrderByNameAsc(Long pid);
     
+    // 鏌ヨ鎵�鏈夋湁鏁堟椿鍔紙鍖呮嫭姣旇禌鍜岄樁娈碉級锛屾寜pid鍜屽悕绉版帓搴�
+    List<Activity> findByStateOrderByPidAscNameAsc(Integer state);
+    
     // 缁熻姣旇禌鏁伴噺
     @Query("SELECT COUNT(a) FROM Activity a WHERE a.pid = 0 AND a.state = 1")
     long countActiveCompetitions();
diff --git a/backend/src/main/java/com/rongyichuang/activity/resolver/ActivityResolver.java b/backend/src/main/java/com/rongyichuang/activity/resolver/ActivityResolver.java
index 21e6266..3ab5319 100644
--- a/backend/src/main/java/com/rongyichuang/activity/resolver/ActivityResolver.java
+++ b/backend/src/main/java/com/rongyichuang/activity/resolver/ActivityResolver.java
@@ -37,11 +37,11 @@
     }
     
     /**
-     * 鑾峰彇鎵�鏈夋瘮璧涳紙鐢ㄤ簬涓嬫媺閫夋嫨锛�
+     * 鑾峰彇鎵�鏈夋瘮璧涘拰闃舵锛堢敤浜庝笅鎷夐�夋嫨锛�
      */
     @QueryMapping
     public List<ActivityResponse> allActivities() {
-        return activityService.findAllCompetitions();
+        return activityService.findAllActivitiesForSelection();
     }
     
     /**
diff --git a/backend/src/main/java/com/rongyichuang/activity/service/ActivityService.java b/backend/src/main/java/com/rongyichuang/activity/service/ActivityService.java
index 26d1ee5..216689c 100644
--- a/backend/src/main/java/com/rongyichuang/activity/service/ActivityService.java
+++ b/backend/src/main/java/com/rongyichuang/activity/service/ActivityService.java
@@ -20,6 +20,7 @@
 import org.springframework.util.StringUtils;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
@@ -267,14 +268,63 @@
     }
     
     /**
-     * 鑾峰彇鎵�鏈夋湁鏁堟瘮璧涳紙鐢ㄤ簬涓嬫媺閫夋嫨锛�
+     * 鑾峰彇鎵�鏈夋湁鏁堟瘮璧涘拰闃舵锛堢敤浜庝笅鎷夐�夋嫨锛�
      */
-    public List<ActivityResponse> findAllCompetitions() {
-        // 涓存椂淇敼锛氫笉浣跨敤state瀛楁杩涜鏌ヨ
-        List<Activity> activities = activityRepository.findByPidOrderByNameAsc(0L);
-        return activities.stream()
-            .map(ActivityResponse::new)
+    public List<ActivityResponse> findAllActivitiesForSelection() {
+        // 鑾峰彇鎵�鏈夋椿鍔紙鍖呮嫭姣旇禌鍜岄樁娈碉級
+        List<Activity> activities = activityRepository.findByStateOrderByPidAscNameAsc(1);
+        
+        // 鍒涘缓姣旇禌ID鍒版瘮璧涘璞$殑鏄犲皠锛岀敤浜庡揩閫熸煡鎵剧埗姣旇禌
+        Map<Long, Activity> competitionMap = activities.stream()
+            .filter(activity -> activity.getPid() == 0)
+            .collect(Collectors.toMap(Activity::getId, activity -> activity));
+        
+        // 杞崲涓篈ctivityResponse骞跺~鍏卲arent淇℃伅
+        List<ActivityResponse> result = activities.stream()
+            .map(activity -> {
+                ActivityResponse response = new ActivityResponse(activity);
+                // 濡傛灉鏄樁娈碉紙pid > 0锛夛紝濉厖parent淇℃伅
+                if (activity.getPid() > 0) {
+                    Activity parentActivity = competitionMap.get(activity.getPid());
+                    if (parentActivity != null) {
+                        response.setParent(new ActivityResponse(parentActivity));
+                    }
+                }
+                return response;
+            })
             .collect(Collectors.toList());
+        
+        // 鑷畾涔夋帓搴忥細姣旇禌鍜屽叾闃舵鏀惧湪涓�璧�
+        result.sort((a, b) -> {
+            // 濡傛灉閮芥槸姣旇禌锛坧id=0锛夛紝鎸夊悕绉版帓搴�
+            if (a.getPid() == 0 && b.getPid() == 0) {
+                return a.getName().compareTo(b.getName());
+            }
+            // 濡傛灉閮芥槸闃舵锛屽厛鎸夌埗姣旇禌鍚嶇О鎺掑簭锛屽啀鎸夐樁娈靛悕绉版帓搴�
+            if (a.getPid() > 0 && b.getPid() > 0) {
+                String aParentName = a.getParent() != null ? a.getParent().getName() : "";
+                String bParentName = b.getParent() != null ? b.getParent().getName() : "";
+                int parentCompare = aParentName.compareTo(bParentName);
+                if (parentCompare != 0) {
+                    return parentCompare;
+                }
+                return a.getName().compareTo(b.getName());
+            }
+            // 濡傛灉涓�涓槸姣旇禌锛屼竴涓槸闃舵
+            if (a.getPid() == 0 && b.getPid() > 0) {
+                String bParentName = b.getParent() != null ? b.getParent().getName() : "";
+                int compare = a.getName().compareTo(bParentName);
+                return compare <= 0 ? -1 : 1; // 姣旇禌鎺掑湪鍏堕樁娈靛墠闈�
+            }
+            if (a.getPid() > 0 && b.getPid() == 0) {
+                String aParentName = a.getParent() != null ? a.getParent().getName() : "";
+                int compare = aParentName.compareTo(b.getName());
+                return compare < 0 ? -1 : 1; // 闃舵鎺掑湪鍏舵瘮璧涘悗闈�
+            }
+            return 0;
+        });
+        
+        return result;
     }
     
     /**
diff --git a/backend/src/main/java/com/rongyichuang/carousel/service/CarouselService.java b/backend/src/main/java/com/rongyichuang/carousel/service/CarouselService.java
index 44f072f..bf349b2 100644
--- a/backend/src/main/java/com/rongyichuang/carousel/service/CarouselService.java
+++ b/backend/src/main/java/com/rongyichuang/carousel/service/CarouselService.java
@@ -10,6 +10,7 @@
 import com.rongyichuang.common.dto.PageResponse;
 import com.rongyichuang.common.entity.Media;
 import com.rongyichuang.common.exception.BusinessException;
+import com.rongyichuang.common.enums.MediaTargetType;
 import com.rongyichuang.common.repository.MediaRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
@@ -56,8 +57,9 @@
                     .map(CarouselResponse::getId)
                     .collect(Collectors.toList());
             
-            // 鏌ヨ濯掍綋鏁伴噺锛坱argetType=4琛ㄧず杞挱鍥撅級
-            List<Object[]> mediaCountResults = mediaRepository.countByTargetTypeAndTargetIdInAndState(4, carouselIds, 1);
+            // 鏌ヨ濯掍綋鏁伴噺锛堜娇鐢ㄦ灇涓惧父閲忚〃绀鸿疆鎾浘绫诲瀷锛�
+            List<Object[]> mediaCountResults = mediaRepository.countByTargetTypeAndTargetIdInAndState(
+                MediaTargetType.CAROUSEL.getValue(), carouselIds, 1);
             Map<Long, Integer> mediaCountMap = mediaCountResults.stream()
                     .collect(Collectors.toMap(
                             result -> (Long) result[0],
@@ -84,7 +86,8 @@
         CarouselResponse response = convertToResponse(carousel);
         
         // 鏌ヨ濯掍綋鏁伴噺
-        List<Media> mediaList = mediaRepository.findByTargetTypeAndTargetIdAndState(4, id, 1);
+        List<Media> mediaList = mediaRepository.findByTargetTypeAndTargetIdAndState(
+            MediaTargetType.CAROUSEL.getValue(), id, 1);
         response.setMediaCount(mediaList.size());
         
         return response;
diff --git a/backend/src/main/java/com/rongyichuang/common/api/MediaGraphqlApi.java b/backend/src/main/java/com/rongyichuang/common/api/MediaGraphqlApi.java
index 15e3eba..0ddc088 100644
--- a/backend/src/main/java/com/rongyichuang/common/api/MediaGraphqlApi.java
+++ b/backend/src/main/java/com/rongyichuang/common/api/MediaGraphqlApi.java
@@ -36,13 +36,13 @@
     }
 
     @QueryMapping
-    public List<MediaResponse> mediasByTarget(@Argument Integer targetType, @Argument String targetId) {
+    public List<MediaResponse> mediasByTarget(@Argument Integer targetType, @Argument Long targetId) {
         try {
             // 浣跨敤 JDBC 鐩存帴鏌ヨ锛岄伩鍏� Hibernate 绫诲瀷杞崲闂
             String sql = "SELECT id, name, path, file_size, file_ext, media_type, target_type, target_id, thumb_path, duration, description " +
-                        "FROM t_media WHERE target_type = ? AND target_id = ? AND target_id REGEXP '^[0-9]+$'";
+                        "FROM t_media WHERE target_type = ? AND target_id = ?";
             
-            List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, targetType, Long.parseLong(targetId));
+            List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, targetType, targetId);
             
             List<MediaResponse> responses = new ArrayList<>();
             for (Map<String, Object> row : rows) {
@@ -121,15 +121,12 @@
     }
 
     @MutationMapping
-    public Boolean deleteMedia(@Argument String id) {
+    public Boolean deleteMedia(@Argument Long id) {
         System.out.println("=== deleteMedia GraphQL璋冪敤 ===");
         System.out.println("瑕佸垹闄ょ殑濯掍綋ID: " + id);
         
         try {
-            Long mediaId = Long.parseLong(id);
-            System.out.println("杞崲鍚庣殑濯掍綋ID: " + mediaId);
-            
-            Boolean result = mediaService.deleteMedia(mediaId);
+            Boolean result = mediaService.deleteMedia(id);
             System.out.println("鍒犻櫎缁撴灉: " + result);
             return result;
         } catch (Exception e) {
diff --git a/backend/src/main/java/com/rongyichuang/common/api/MediaTestController.java b/backend/src/main/java/com/rongyichuang/common/api/MediaTestController.java
index 02860c8..7545101 100644
--- a/backend/src/main/java/com/rongyichuang/common/api/MediaTestController.java
+++ b/backend/src/main/java/com/rongyichuang/common/api/MediaTestController.java
@@ -18,12 +18,12 @@
     private JdbcTemplate jdbcTemplate;
 
     @GetMapping("/media")
-    public Object getMedia(@RequestParam Integer targetType, @RequestParam String targetId) {
+    public Object getMedia(@RequestParam Integer targetType, @RequestParam Long targetId) {
         try {
             String sql = "SELECT id, name, path, file_ext, media_type, target_type, target_id " +
                         "FROM t_media WHERE target_type = ? AND target_id = ?";
             
-            List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, targetType, Long.parseLong(targetId));
+            List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, targetType, targetId);
             return rows;
         } catch (Exception e) {
             return "閿欒: " + e.getMessage();
diff --git a/backend/src/main/java/com/rongyichuang/common/enums/MediaTargetType.java b/backend/src/main/java/com/rongyichuang/common/enums/MediaTargetType.java
new file mode 100644
index 0000000..1a2f481
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/common/enums/MediaTargetType.java
@@ -0,0 +1,92 @@
+package com.rongyichuang.common.enums;
+
+/**
+ * 濯掍綋鐩爣绫诲瀷鏋氫妇
+ * 瀹氫箟t_media琛ㄤ腑target_type瀛楁鐨勬墍鏈夊彲鑳藉��
+ */
+public enum MediaTargetType {
+    
+    /**
+     * 璇勫澶村儚
+     */
+    JUDGE_AVATAR(1, "璇勫澶村儚"),
+    
+    /**
+     * 娲诲姩濯掍綋
+     */
+    ACTIVITY(2, "娲诲姩"),
+    
+    /**
+     * 杞挱鍥惧獟浣�
+     */
+    CAROUSEL(4, "杞挱鍥�"),
+    
+    /**
+     * 鍙傝禌鎶ュ悕璧勬枡
+     * 瀵瑰簲t_activity_player鐨勮褰�
+     */
+    ACTIVITY_PLAYER_SUBMISSION(5, "鍙傝禌鎶ュ悕璧勬枡"),
+    
+    /**
+     * 瀛﹀憳澶村儚
+     */
+    STUDENT_AVATAR(6, "瀛﹀憳澶村儚"),
+    
+    /**
+     * 鐢ㄦ埛澶村儚
+     */
+    USER_AVATAR(7, "鐢ㄦ埛澶村儚");
+    
+    private final int value;
+    private final String description;
+    
+    MediaTargetType(int value, String description) {
+        this.value = value;
+        this.description = description;
+    }
+    
+    /**
+     * 鑾峰彇鏋氫妇鍊�
+     * @return 鏁板��
+     */
+    public int getValue() {
+        return value;
+    }
+    
+    /**
+     * 鑾峰彇鎻忚堪
+     * @return 鎻忚堪
+     */
+    public String getDescription() {
+        return description;
+    }
+    
+    /**
+     * 鏍规嵁鏁板�艰幏鍙栨灇涓�
+     * @param value 鏁板��
+     * @return 瀵瑰簲鐨勬灇涓撅紝濡傛灉娌℃湁鎵惧埌鍒欒繑鍥瀗ull
+     */
+    public static MediaTargetType fromValue(int value) {
+        for (MediaTargetType type : MediaTargetType.values()) {
+            if (type.value == value) {
+                return type;
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * 鏍规嵁鏁板�艰幏鍙栨弿杩�
+     * @param value 鏁板��
+     * @return 鎻忚堪锛屽鏋滄病鏈夋壘鍒板垯杩斿洖"鏈煡绫诲瀷"
+     */
+    public static String getDescriptionByValue(int value) {
+        MediaTargetType type = fromValue(value);
+        return type != null ? type.getDescription() : "鏈煡绫诲瀷(" + value + ")";
+    }
+    
+    @Override
+    public String toString() {
+        return String.format("%s(%d)", description, value);
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/common/util/UserContextUtil.java b/backend/src/main/java/com/rongyichuang/common/util/UserContextUtil.java
new file mode 100644
index 0000000..99ee7b1
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/common/util/UserContextUtil.java
@@ -0,0 +1,133 @@
+package com.rongyichuang.common.util;
+
+import com.rongyichuang.judge.entity.Judge;
+import com.rongyichuang.judge.repository.JudgeRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+import java.util.Optional;
+
+/**
+ * 鐢ㄦ埛涓婁笅鏂囧伐鍏风被
+ * 鐢ㄤ簬鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛淇℃伅鍜屽叧鑱旂殑璇勫淇℃伅
+ */
+@Component
+public class UserContextUtil {
+
+    private static final Logger logger = LoggerFactory.getLogger(UserContextUtil.class);
+
+    @Autowired
+    private JudgeRepository judgeRepository;
+
+    /**
+     * 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛ID
+     * 娉ㄦ剰锛氬綋鍓嶇郴缁熸殏鏃朵娇鐢ㄥ浐瀹氱敤鎴稩D锛屽悗缁渶瑕佹牴鎹疄闄呰璇佹満鍒朵慨鏀�
+     * 
+     * @return 鐢ㄦ埛ID
+     */
+    public Long getCurrentUserId() {
+        try {
+            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+            if (authentication != null && authentication.isAuthenticated() && 
+                !"anonymousUser".equals(authentication.getPrincipal())) {
+                // TODO: 浠庤璇佷俊鎭腑鑾峰彇鐪熷疄鐨勭敤鎴稩D
+                // 杩欓噷闇�瑕佹牴鎹疄闄呯殑璁よ瘉鏈哄埗鏉ュ疄鐜�
+                // 渚嬪锛氫粠JWT token涓В鏋愮敤鎴稩D锛屾垨浠嶶serDetails涓幏鍙�
+                logger.debug("鑾峰彇鍒拌璇佺敤鎴�: {}", authentication.getName());
+                return 1L; // 涓存椂杩斿洖鍥哄畾鐢ㄦ埛ID
+            }
+        } catch (Exception e) {
+            logger.warn("鑾峰彇褰撳墠鐢ㄦ埛ID鏃跺彂鐢熷紓甯�: {}", e.getMessage());
+        }
+        
+        // 濡傛灉娌℃湁璁よ瘉淇℃伅锛岃繑鍥為粯璁ょ敤鎴稩D锛堝紑鍙戦樁娈典娇鐢級
+        logger.debug("鏈壘鍒拌璇佷俊鎭紝浣跨敤榛樿鐢ㄦ埛ID");
+        return 1L;
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鐢ㄦ埛鍏宠仈鐨勮瘎濮斾俊鎭�
+     * 
+     * @return 璇勫淇℃伅锛屽鏋滃綋鍓嶇敤鎴蜂笉鏄瘎濮斿垯杩斿洖绌�
+     */
+    public Optional<Judge> getCurrentJudge() {
+        Long userId = getCurrentUserId();
+        if (userId == null) {
+            logger.warn("鏃犳硶鑾峰彇褰撳墠鐢ㄦ埛ID");
+            return Optional.empty();
+        }
+
+        try {
+            Optional<Judge> judge = judgeRepository.findByUserId(userId);
+            if (judge.isPresent()) {
+                logger.debug("鎵惧埌褰撳墠鐢ㄦ埛鍏宠仈鐨勮瘎濮�: {}", judge.get().getName());
+            } else {
+                logger.debug("褰撳墠鐢ㄦ埛(ID: {})涓嶆槸璇勫", userId);
+            }
+            return judge;
+        } catch (Exception e) {
+            logger.error("鏌ヨ璇勫淇℃伅鏃跺彂鐢熷紓甯�: {}", e.getMessage(), e);
+            return Optional.empty();
+        }
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鐢ㄦ埛鍏宠仈鐨勮瘎濮擨D
+     * 
+     * @return 璇勫ID锛屽鏋滃綋鍓嶇敤鎴蜂笉鏄瘎濮斿垯杩斿洖null
+     */
+    public Long getCurrentJudgeId() {
+        return getCurrentJudge().map(Judge::getId).orElse(null);
+    }
+
+    /**
+     * 妫�鏌ュ綋鍓嶇敤鎴锋槸鍚︿负璇勫
+     * 
+     * @return true濡傛灉褰撳墠鐢ㄦ埛鏄瘎濮旓紝鍚﹀垯false
+     */
+    public boolean isCurrentUserJudge() {
+        return getCurrentJudge().isPresent();
+    }
+
+    /**
+     * 妫�鏌ュ綋鍓嶇敤鎴锋槸鍚︿负鎸囧畾娲诲姩鐨勮瘎濮�
+     * 
+     * @param activityId 娲诲姩ID
+     * @return true濡傛灉褰撳墠鐢ㄦ埛鏄娲诲姩鐨勮瘎濮旓紝鍚﹀垯false
+     */
+    public boolean isCurrentUserJudgeForActivity(Long activityId) {
+        Optional<Judge> judge = getCurrentJudge();
+        if (judge.isEmpty()) {
+            return false;
+        }
+
+        try {
+            // 閫氳繃ActivityJudge琛ㄦ鏌ュ綋鍓嶈瘎濮旀槸鍚﹀弬涓庢寚瀹氭椿鍔�
+            return judgeRepository.existsByIdAndActivityId(judge.get().getId(), activityId);
+        } catch (Exception e) {
+            logger.error("妫�鏌ヨ瘎濮旀椿鍔ㄦ潈闄愭椂鍙戠敓寮傚父: {}", e.getMessage(), e);
+            return false;
+        }
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鐢ㄦ埛鍚嶇О锛堢敤浜庢棩蹇楄褰曪級
+     * 
+     * @return 鐢ㄦ埛鍚嶇О
+     */
+    public String getCurrentUserName() {
+        try {
+            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+            if (authentication != null && authentication.isAuthenticated()) {
+                return authentication.getName();
+            }
+        } catch (Exception e) {
+            logger.warn("鑾峰彇褰撳墠鐢ㄦ埛鍚嶇О鏃跺彂鐢熷紓甯�: {}", e.getMessage());
+        }
+        return "鏈煡鐢ㄦ埛";
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/config/DatabaseMigration.java b/backend/src/main/java/com/rongyichuang/config/DatabaseMigration.java
new file mode 100644
index 0000000..6874a5e
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/config/DatabaseMigration.java
@@ -0,0 +1,38 @@
+package com.rongyichuang.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DatabaseMigration implements CommandLineRunner {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Override
+    public void run(String... args) throws Exception {
+        System.out.println("馃攧 寮�濮嬫墽琛屾暟鎹簱杩佺Щ...");
+        try {
+            // 妫�鏌escription瀛楁鏄惁宸插瓨鍦�
+            String checkSql = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS " +
+                             "WHERE TABLE_SCHEMA = 'ryc' AND TABLE_NAME = 't_employee' AND COLUMN_NAME = 'description'";
+            
+            Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class);
+            
+            if (count == 0) {
+                // 娣诲姞description瀛楁鍒拌〃鏈熬
+                String alterSql = "ALTER TABLE t_employee ADD COLUMN description varchar(255)";
+                jdbcTemplate.execute(alterSql);
+                System.out.println("鉁� 鎴愬姛娣诲姞description瀛楁鍒皌_employee琛�");
+            } else {
+                System.out.println("鈩癸笍 description瀛楁宸插瓨鍦紝鏃犻渶娣诲姞");
+            }
+            
+        } catch (Exception e) {
+            System.err.println("鉂� 鏁版嵁搴撹縼绉诲け璐�: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/config/GraphQLConfig.java b/backend/src/main/java/com/rongyichuang/config/GraphQLConfig.java
new file mode 100644
index 0000000..3eccde8
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/config/GraphQLConfig.java
@@ -0,0 +1,27 @@
+package com.rongyichuang.config;
+
+import graphql.scalars.ExtendedScalars;
+import graphql.schema.GraphQLScalarType;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.graphql.execution.RuntimeWiringConfigurer;
+
+@Configuration
+public class GraphQLConfig {
+
+    @Bean
+    public RuntimeWiringConfigurer runtimeWiringConfigurer() {
+        return wiringBuilder -> wiringBuilder
+                .scalar(ExtendedScalars.GraphQLLong)
+                .scalar(longScalar());
+    }
+
+    @Bean
+    public GraphQLScalarType longScalar() {
+        return GraphQLScalarType.newScalar()
+                .name("Long")
+                .description("Long scalar type")
+                .coercing(new LongCoercing())
+                .build();
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/employee/dto/request/EmployeeInput.java b/backend/src/main/java/com/rongyichuang/employee/dto/request/EmployeeInput.java
new file mode 100644
index 0000000..0061b40
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/employee/dto/request/EmployeeInput.java
@@ -0,0 +1,65 @@
+package com.rongyichuang.employee.dto.request;
+
+/**
+ * 鍛樺伐杈撳叆DTO
+ */
+public class EmployeeInput {
+    private Long id;
+    private String name;
+    private String phone;
+    private String password;
+    private String roleId;
+    private String description;
+
+    // 鏋勯�犲嚱鏁�
+    public EmployeeInput() {}
+
+    // Getter鍜孲etter鏂规硶
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getRoleId() {
+        return roleId;
+    }
+
+    public void setRoleId(String roleId) {
+        this.roleId = roleId;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/employee/dto/response/EmployeeResponse.java b/backend/src/main/java/com/rongyichuang/employee/dto/response/EmployeeResponse.java
new file mode 100644
index 0000000..27a88e5
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/employee/dto/response/EmployeeResponse.java
@@ -0,0 +1,86 @@
+package com.rongyichuang.employee.dto.response;
+
+import com.rongyichuang.employee.entity.Employee;
+
+/**
+ * 鍛樺伐鍝嶅簲DTO
+ */
+public class EmployeeResponse {
+    private Long id;
+    private String name;
+    private String phone;
+    private String roleId;
+    private String description;
+    private String createTime;
+    private String updateTime;
+
+    // 鏋勯�犲嚱鏁�
+    public EmployeeResponse() {}
+
+    public EmployeeResponse(Employee employee) {
+        this.id = employee.getId();
+        this.name = employee.getName();
+        this.phone = employee.getPhone();
+        this.roleId = employee.getRoleId();
+        this.description = employee.getDescription();
+        this.createTime = employee.getCreateTime() != null ? employee.getCreateTime().toString() : null;
+        this.updateTime = employee.getUpdateTime() != null ? employee.getUpdateTime().toString() : null;
+    }
+
+    // Getter鍜孲etter鏂规硶
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public String getRoleId() {
+        return roleId;
+    }
+
+    public void setRoleId(String roleId) {
+        this.roleId = roleId;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(String updateTime) {
+        this.updateTime = updateTime;
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/employee/entity/Employee.java b/backend/src/main/java/com/rongyichuang/employee/entity/Employee.java
new file mode 100644
index 0000000..c7599ed
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/employee/entity/Employee.java
@@ -0,0 +1,152 @@
+package com.rongyichuang.employee.entity;
+
+import com.rongyichuang.common.entity.BaseEntity;
+import jakarta.persistence.*;
+import org.hibernate.annotations.Where;
+
+/**
+ * 鍛樺伐瀹炰綋绫�
+ */
+@Entity
+@Table(name = "t_employee")
+@Where(clause = "state = 1")
+public class Employee extends BaseEntity {
+
+    /**
+     * 鍛樺伐濮撳悕
+     */
+    @Column(name = "name", length = 64, nullable = false)
+    private String name;
+
+    /**
+     * 鎵嬫満鍙风爜
+     */
+    @Column(name = "phone", length = 32, nullable = false)
+    private String phone;
+
+    /**
+     * 瀵嗙爜
+     */
+    @Column(name = "password", length = 128, nullable = false)
+    private String password;
+
+    /**
+     * 瑙掕壊ID
+     */
+    @Column(name = "role_id", length = 32, nullable = false)
+    private String roleId;
+
+    /**
+     * 鎻忚堪
+     */
+    @Column(name = "description", length = 255)
+    private String description;
+
+    /**
+     * 鐢ㄦ埛ID锛堜粠鏁版嵁搴撹〃缁撴瀯鐪嬪埌鐨勶級
+     */
+    @Column(name = "user_id", nullable = false)
+    private Long userId;
+
+    /**
+     * 鍒涘缓鐢ㄦ埛ID
+     */
+    @Column(name = "create_user_id")
+    private Long createUserId;
+
+    /**
+     * 鏇存柊鐢ㄦ埛ID
+     */
+    @Column(name = "update_user_id")
+    private Long updateUserId;
+
+    /**
+     * 鐗堟湰鍙凤紙涔愯閿侊級
+     */
+    @Version
+    @Column(name = "version", nullable = false)
+    private Long version = 0L;
+
+    // 鏋勯�犲嚱鏁�
+    public Employee() {}
+
+    public Employee(String name, String phone, String password, String roleId) {
+        this.name = name;
+        this.phone = phone;
+        this.password = password;
+        this.roleId = roleId;
+    }
+
+    // Getter鍜孲etter鏂规硶
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getRoleId() {
+        return roleId;
+    }
+
+    public void setRoleId(String roleId) {
+        this.roleId = roleId;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public Long getCreateUserId() {
+        return createUserId;
+    }
+
+    public void setCreateUserId(Long createUserId) {
+        this.createUserId = createUserId;
+    }
+
+    public Long getUpdateUserId() {
+        return updateUserId;
+    }
+
+    public void setUpdateUserId(Long updateUserId) {
+        this.updateUserId = updateUserId;
+    }
+
+    public Long getVersion() {
+        return version;
+    }
+
+    public void setVersion(Long version) {
+        this.version = version;
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/employee/repository/EmployeeRepository.java b/backend/src/main/java/com/rongyichuang/employee/repository/EmployeeRepository.java
new file mode 100644
index 0000000..1ef9e6a
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/employee/repository/EmployeeRepository.java
@@ -0,0 +1,52 @@
+package com.rongyichuang.employee.repository;
+
+import com.rongyichuang.employee.entity.Employee;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 鍛樺伐鏁版嵁璁块棶灞�
+ */
+@Repository
+public interface EmployeeRepository extends JpaRepository<Employee, Long> {
+
+    /**
+     * 鏍规嵁鍚嶇О妯$硦鏌ヨ鍛樺伐鍒楄〃
+     */
+    @Query("SELECT e FROM Employee e WHERE e.name LIKE %:name%")
+    List<Employee> findByNameContaining(@Param("name") String name);
+
+    /**
+     * 鍒嗛〉鏌ヨ鍛樺伐鍒楄〃锛屾敮鎸佸悕绉版ā绯婃悳绱�
+     */
+    @Query("SELECT e FROM Employee e WHERE (:name IS NULL OR e.name LIKE %:name%) ORDER BY e.createTime DESC")
+    Page<Employee> findByNameContainingOrderByCreateTimeDesc(@Param("name") String name, Pageable pageable);
+
+    /**
+     * 鏍规嵁鎵嬫満鍙锋煡璇㈠憳宸�
+     */
+    Optional<Employee> findByPhone(String phone);
+
+    /**
+     * 妫�鏌ユ墜鏈哄彿鏄惁宸插瓨鍦�
+     */
+    boolean existsByPhone(String phone);
+
+    /**
+     * 妫�鏌ユ墜鏈哄彿鏄惁宸插瓨鍦紙鎺掗櫎鎸囧畾ID锛�
+     */
+    @Query("SELECT COUNT(e) > 0 FROM Employee e WHERE e.phone = :phone AND e.id != :id")
+    boolean existsByPhoneAndIdNot(@Param("phone") String phone, @Param("id") Long id);
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鍛樺伐鍒楄〃
+     */
+    List<Employee> findByRoleId(String roleId);
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/employee/resolver/EmployeeResolver.java b/backend/src/main/java/com/rongyichuang/employee/resolver/EmployeeResolver.java
new file mode 100644
index 0000000..d9d94e2
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/employee/resolver/EmployeeResolver.java
@@ -0,0 +1,65 @@
+package com.rongyichuang.employee.resolver;
+
+import com.rongyichuang.employee.dto.request.EmployeeInput;
+import com.rongyichuang.employee.dto.response.EmployeeResponse;
+import com.rongyichuang.employee.service.EmployeeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.graphql.data.method.annotation.Argument;
+import org.springframework.graphql.data.method.annotation.MutationMapping;
+import org.springframework.graphql.data.method.annotation.QueryMapping;
+import org.springframework.stereotype.Controller;
+
+import java.util.List;
+
+/**
+ * 鍛樺伐GraphQL瑙f瀽鍣�
+ */
+@Controller
+public class EmployeeResolver {
+
+    @Autowired
+    private EmployeeService employeeService;
+
+    /**
+     * 鏌ヨ鎵�鏈夊憳宸ュ垪琛�
+     */
+    @QueryMapping
+    public List<EmployeeResponse> employees() {
+        return employeeService.findAllEmployees();
+    }
+
+
+
+    /**
+     * 鏍规嵁鍚嶇О鎼滅储鍛樺伐
+     */
+    @QueryMapping
+    public List<EmployeeResponse> employeesByName(@Argument String name) {
+        return employeeService.searchByName(name);
+    }
+
+    /**
+     * 鏍规嵁ID鑾峰彇鍛樺伐璇︽儏
+     */
+    @QueryMapping
+    public EmployeeResponse employee(@Argument Long id) {
+        return employeeService.findById(id);
+    }
+
+    /**
+     * 淇濆瓨鍛樺伐锛堟柊澧炴垨鏇存柊锛�
+     */
+    @MutationMapping
+    public EmployeeResponse saveEmployee(@Argument EmployeeInput input) {
+        return employeeService.saveEmployee(input);
+    }
+
+    /**
+     * 鍒犻櫎鍛樺伐
+     */
+    @MutationMapping
+    public Boolean deleteEmployee(@Argument Long id) {
+        return employeeService.deleteEmployee(id);
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/employee/service/EmployeeService.java b/backend/src/main/java/com/rongyichuang/employee/service/EmployeeService.java
new file mode 100644
index 0000000..16a8e91
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/employee/service/EmployeeService.java
@@ -0,0 +1,185 @@
+package com.rongyichuang.employee.service;
+
+import com.rongyichuang.employee.dto.request.EmployeeInput;
+import com.rongyichuang.employee.dto.response.EmployeeResponse;
+import com.rongyichuang.employee.entity.Employee;
+import com.rongyichuang.employee.repository.EmployeeRepository;
+import com.rongyichuang.common.exception.BusinessException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * 鍛樺伐鏈嶅姟绫�
+ */
+@Service
+@Transactional
+public class EmployeeService {
+
+    private static final Logger logger = LoggerFactory.getLogger(EmployeeService.class);
+
+    @Autowired
+    private EmployeeRepository employeeRepository;
+
+    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+
+    // 瀵嗙爜楠岃瘉姝e垯锛氳嚦灏�6涓瓧绗︼紝蹇呴』鍖呭惈瀛楁瘝鍜屾暟瀛�
+    private static final Pattern PASSWORD_PATTERN = Pattern.compile("^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d@$!%*?&]{6,}$");
+
+    /**
+     * 鑾峰彇鎵�鏈夊憳宸ュ垪琛�
+     */
+    public List<EmployeeResponse> findAllEmployees() {
+        List<Employee> employees = employeeRepository.findAll();
+        return employees.stream()
+                .map(EmployeeResponse::new)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 鍒嗛〉鏌ヨ鍛樺伐鍒楄〃锛屾敮鎸佸悕绉版悳绱�
+     */
+    public Page<EmployeeResponse> findEmployees(String name, int page, int size) {
+        Pageable pageable = PageRequest.of(page, size);
+        Page<Employee> employeePage = employeeRepository.findByNameContainingOrderByCreateTimeDesc(name, pageable);
+        return employeePage.map(EmployeeResponse::new);
+    }
+
+    /**
+     * 鏍规嵁鍚嶇О鎼滅储鍛樺伐
+     */
+    public List<EmployeeResponse> searchByName(String name) {
+        if (name == null || name.trim().isEmpty()) {
+            return findAllEmployees();
+        }
+        List<Employee> employees = employeeRepository.findByNameContaining(name.trim());
+        return employees.stream()
+                .map(EmployeeResponse::new)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 鏍规嵁ID鑾峰彇鍛樺伐璇︽儏
+     */
+    public EmployeeResponse findById(Long id) {
+        Optional<Employee> employee = employeeRepository.findById(id);
+        if (employee.isPresent()) {
+            return new EmployeeResponse(employee.get());
+        }
+        throw new BusinessException("EMPLOYEE_NOT_FOUND", "鍛樺伐涓嶅瓨鍦�");
+    }
+
+    /**
+     * 淇濆瓨鍛樺伐锛堟柊澧炴垨鏇存柊锛�
+     */
+    public EmployeeResponse saveEmployee(EmployeeInput input) {
+        // 楠岃瘉杈撳叆
+        validateEmployeeInput(input);
+
+        Employee employee;
+        if (input.getId() != null) {
+            // 鏇存柊鍛樺伐
+            employee = employeeRepository.findById(input.getId())
+                    .orElseThrow(() -> new BusinessException("EMPLOYEE_NOT_FOUND", "鍛樺伐涓嶅瓨鍦�"));
+            
+            // 妫�鏌ユ墜鏈哄彿鏄惁琚叾浠栧憳宸ヤ娇鐢�
+            if (employeeRepository.existsByPhoneAndIdNot(input.getPhone(), input.getId())) {
+                throw new BusinessException("PHONE_ALREADY_EXISTS", "鎵嬫満鍙峰凡琚叾浠栧憳宸ヤ娇鐢�");
+            }
+        } else {
+            // 鏂板鍛樺伐
+            if (employeeRepository.existsByPhone(input.getPhone())) {
+                throw new BusinessException("PHONE_ALREADY_EXISTS", "鎵嬫満鍙峰凡瀛樺湪");
+            }
+            employee = new Employee();
+            employee.setUserId(1L); // 涓存椂璁剧疆锛屽疄闄呭簲璇ヤ粠褰撳墠鐧诲綍鐢ㄦ埛鑾峰彇
+        }
+
+        // 璁剧疆鍩烘湰淇℃伅
+        employee.setName(input.getName());
+        employee.setPhone(input.getPhone());
+        employee.setRoleId(input.getRoleId());
+        employee.setDescription(input.getDescription());
+
+        // 澶勭悊瀵嗙爜
+        if (input.getPassword() != null && !input.getPassword().trim().isEmpty()) {
+            employee.setPassword(passwordEncoder.encode(input.getPassword()));
+        }
+
+        Employee savedEmployee = employeeRepository.save(employee);
+        logger.info("鍛樺伐淇濆瓨鎴愬姛: {}", savedEmployee.getName());
+        
+        return new EmployeeResponse(savedEmployee);
+    }
+
+    /**
+     * 鍒犻櫎鍛樺伐锛堣蒋鍒犻櫎锛�
+     */
+    public boolean deleteEmployee(Long id) {
+        Optional<Employee> employee = employeeRepository.findById(id);
+        if (employee.isPresent()) {
+            Employee emp = employee.get();
+            emp.setState(0); // 杞垹闄�
+            employeeRepository.save(emp);
+            logger.info("鍛樺伐鍒犻櫎鎴愬姛: {}", emp.getName());
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 楠岃瘉鍛樺伐杈撳叆鏁版嵁
+     */
+    private void validateEmployeeInput(EmployeeInput input) {
+        if (input.getName() == null || input.getName().trim().isEmpty()) {
+            throw new BusinessException("NAME_REQUIRED", "鍛樺伐濮撳悕涓嶈兘涓虹┖");
+        }
+
+        if (input.getPhone() == null || input.getPhone().trim().isEmpty()) {
+            throw new BusinessException("PHONE_REQUIRED", "鎵嬫満鍙蜂笉鑳戒负绌�");
+        }
+
+        if (input.getRoleId() == null || input.getRoleId().trim().isEmpty()) {
+            throw new BusinessException("ROLE_REQUIRED", "瑙掕壊涓嶈兘涓虹┖");
+        }
+
+        // 鏂板鍛樺伐鏃跺瘑鐮佸繀濉�
+        if (input.getId() == null) {
+            if (input.getPassword() == null || input.getPassword().trim().isEmpty()) {
+                throw new BusinessException("PASSWORD_REQUIRED", "瀵嗙爜涓嶈兘涓虹┖");
+            }
+        }
+
+        // 濡傛灉鎻愪緵浜嗗瘑鐮侊紝楠岃瘉瀵嗙爜鏍煎紡
+        if (input.getPassword() != null && !input.getPassword().trim().isEmpty()) {
+            if (!PASSWORD_PATTERN.matcher(input.getPassword()).matches()) {
+                throw new BusinessException("INVALID_PASSWORD_FORMAT", "瀵嗙爜鑷冲皯6涓瓧绗︼紝蹇呴』鍖呭惈瀛楁瘝鍜屾暟瀛�");
+            }
+        }
+
+        // 楠岃瘉鎵嬫満鍙锋牸寮�
+        if (!isValidPhone(input.getPhone())) {
+            throw new BusinessException("INVALID_PHONE_FORMAT", "鎵嬫満鍙锋牸寮忎笉姝g‘");
+        }
+    }
+
+    /**
+     * 楠岃瘉鎵嬫満鍙锋牸寮�
+     */
+    private boolean isValidPhone(String phone) {
+        if (phone == null) return false;
+        // 绠�鍗曠殑鎵嬫満鍙烽獙璇侊細11浣嶆暟瀛�
+        return phone.matches("^1[3-9]\\d{9}$");
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/judge/dto/request/JudgeInput.java b/backend/src/main/java/com/rongyichuang/judge/dto/request/JudgeInput.java
index 82e7e71..1070444 100644
--- a/backend/src/main/java/com/rongyichuang/judge/dto/request/JudgeInput.java
+++ b/backend/src/main/java/com/rongyichuang/judge/dto/request/JudgeInput.java
@@ -8,8 +8,12 @@
     private String phone;
     private Integer gender;
     private String description;
+    private String title;
+    private String company;
+    private String introduction;
     private Long avatarMediaId;
     private List<Long> majorIds;
+    private List<String> tagNames;
 
     public Long getId() {
         return id;
@@ -66,4 +70,36 @@
     public void setMajorIds(List<Long> majorIds) {
         this.majorIds = majorIds;
     }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getCompany() {
+        return company;
+    }
+
+    public void setCompany(String company) {
+        this.company = company;
+    }
+
+    public String getIntroduction() {
+        return introduction;
+    }
+
+    public void setIntroduction(String introduction) {
+        this.introduction = introduction;
+    }
+
+    public List<String> getTagNames() {
+        return tagNames;
+    }
+
+    public void setTagNames(List<String> tagNames) {
+        this.tagNames = tagNames;
+    }
 }
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/judge/dto/response/JudgeResponse.java b/backend/src/main/java/com/rongyichuang/judge/dto/response/JudgeResponse.java
index 28e6212..be73106 100644
--- a/backend/src/main/java/com/rongyichuang/judge/dto/response/JudgeResponse.java
+++ b/backend/src/main/java/com/rongyichuang/judge/dto/response/JudgeResponse.java
@@ -8,8 +8,12 @@
     private String phone;
     private Integer gender;
     private String description;
+    private String title;
+    private String company;
+    private String introduction;
     private String avatarUrl;
     private List<TagResponse> specialties;
+    private List<TagResponse> tags;
 
     public Long getId() {
         return id;
@@ -67,6 +71,38 @@
         this.specialties = specialties;
     }
 
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getCompany() {
+        return company;
+    }
+
+    public void setCompany(String company) {
+        this.company = company;
+    }
+
+    public String getIntroduction() {
+        return introduction;
+    }
+
+    public void setIntroduction(String introduction) {
+        this.introduction = introduction;
+    }
+
+    public List<TagResponse> getTags() {
+        return tags;
+    }
+
+    public void setTags(List<TagResponse> tags) {
+        this.tags = tags;
+    }
+
     public static class TagResponse {
         private Long id;
         private String name;
diff --git a/backend/src/main/java/com/rongyichuang/judge/entity/Judge.java b/backend/src/main/java/com/rongyichuang/judge/entity/Judge.java
index 8597aa1..3baf33a 100644
--- a/backend/src/main/java/com/rongyichuang/judge/entity/Judge.java
+++ b/backend/src/main/java/com/rongyichuang/judge/entity/Judge.java
@@ -1,8 +1,10 @@
 package com.rongyichuang.judge.entity;
 
 import com.rongyichuang.common.entity.BaseEntity;
+import com.rongyichuang.tag.entity.Tag;
 import jakarta.persistence.*;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
 
 @Entity
 @Table(name = "t_judge")
@@ -26,17 +28,25 @@
     @Column(name = "role_id")
     private Long roleId;
 
-    @Column(name = "description", length = 255)
+    @Column(name = "description")
     private String description;
 
-    // 涓撲笟鏍囩锛堝瀵瑰鍏崇郴锛�
-    @ManyToMany
+    @Column(name = "title")
+    private String title;
+
+    @Column(name = "company")
+    private String company;
+
+    @Column(name = "introduction")
+    private String introduction;
+
+    @ManyToMany(fetch = FetchType.LAZY)
     @JoinTable(
-        name = "t_judge_tag",
-        joinColumns = @JoinColumn(name = "judge_id"),
-        inverseJoinColumns = @JoinColumn(name = "tag_id")
+            name = "t_judge_tag",
+            joinColumns = @JoinColumn(name = "judge_id"),
+            inverseJoinColumns = @JoinColumn(name = "tag_id")
     )
-    private List<Tag> specialties;
+    private Set<Tag> specialties = new HashSet<>();
 
     // Getter and Setter methods
     public String getName() {
@@ -95,11 +105,35 @@
         this.description = description;
     }
 
-    public List<Tag> getSpecialties() {
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getCompany() {
+        return company;
+    }
+
+    public void setCompany(String company) {
+        this.company = company;
+    }
+
+    public String getIntroduction() {
+        return introduction;
+    }
+
+    public void setIntroduction(String introduction) {
+        this.introduction = introduction;
+    }
+
+    public Set<Tag> getSpecialties() {
         return specialties;
     }
 
-    public void setSpecialties(List<Tag> specialties) {
+    public void setSpecialties(Set<Tag> specialties) {
         this.specialties = specialties;
     }
 }
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/judge/repository/JudgeRepository.java b/backend/src/main/java/com/rongyichuang/judge/repository/JudgeRepository.java
index cb0e643..e2e495e 100644
--- a/backend/src/main/java/com/rongyichuang/judge/repository/JudgeRepository.java
+++ b/backend/src/main/java/com/rongyichuang/judge/repository/JudgeRepository.java
@@ -8,6 +8,7 @@
 import org.springframework.stereotype.Repository;
 
 import java.util.List;
+import java.util.Optional;
 
 @Repository
 public interface JudgeRepository extends JpaRepository<Judge, Long>, JpaSpecificationExecutor<Judge> {
@@ -16,4 +17,15 @@
     List<Judge> findByNameContaining(@Param("name") String name);
     
     boolean existsByPhone(String phone);
+    
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ユ壘璇勫
+     */
+    Optional<Judge> findByUserId(Long userId);
+    
+    /**
+     * 妫�鏌ヨ瘎濮旀槸鍚﹀弬涓庢寚瀹氭椿鍔�
+     */
+    @Query("SELECT COUNT(aj) > 0 FROM ActivityJudge aj WHERE aj.judgeId = :judgeId AND aj.activityId = :activityId")
+    boolean existsByIdAndActivityId(@Param("judgeId") Long judgeId, @Param("activityId") Long activityId);
 }
\ No newline at end of file
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 63eef94..6f8fd7c 100644
--- a/backend/src/main/java/com/rongyichuang/judge/service/JudgeService.java
+++ b/backend/src/main/java/com/rongyichuang/judge/service/JudgeService.java
@@ -3,22 +3,27 @@
 import com.rongyichuang.judge.dto.request.JudgeInput;
 import com.rongyichuang.judge.dto.response.JudgeResponse;
 import com.rongyichuang.judge.entity.Judge;
-import com.rongyichuang.judge.entity.Tag;
+import com.rongyichuang.tag.entity.Tag;
 import com.rongyichuang.judge.repository.JudgeRepository;
 import com.rongyichuang.common.entity.Media;
 import com.rongyichuang.common.repository.MediaRepository;
 import com.rongyichuang.common.dto.request.MediaInput;
 import com.rongyichuang.common.dto.response.MediaResponse;
 import com.rongyichuang.common.service.MediaService;
-import com.rongyichuang.judge.repository.TagRepository;
+import com.rongyichuang.common.exception.BusinessException;
+import com.rongyichuang.common.enums.MediaTargetType;
+import com.rongyichuang.tag.repository.TagRepository;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.domain.Sort;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -31,6 +36,9 @@
     private final TagRepository tagRepository;
     private final MediaRepository mediaRepository;
     private final MediaService mediaService;
+    
+    @Value("${app.media-url:${app.media.url:}}")
+    private String mediaBaseUrl;
 
     public JudgeService(JudgeRepository judgeRepository, TagRepository tagRepository, 
                        MediaRepository mediaRepository, MediaService mediaService) {
@@ -63,12 +71,12 @@
         Judge judge;
         if (input.getId() != null) {
             judge = judgeRepository.findById(input.getId())
-                    .orElseThrow(() -> new RuntimeException("璇勫涓嶅瓨鍦�"));
+                    .orElseThrow(() -> new BusinessException("璇勫涓嶅瓨鍦�"));
         } else {
             judge = new Judge();
             // 鏂板璇勫鏃舵鏌ユ墜鏈哄彿鏄惁宸插瓨鍦�
             if (judgeRepository.existsByPhone(input.getPhone())) {
-                throw new RuntimeException("鎵嬫満鍙风爜宸插瓨鍦紝璇蜂娇鐢ㄥ叾浠栨墜鏈哄彿鐮�");
+                throw new BusinessException("PHONE_EXISTS", "鎵嬫満鍙风爜宸插瓨鍦紝璇蜂娇鐢ㄥ叾浠栨墜鏈哄彿鐮�");
             }
         }
 
@@ -76,16 +84,17 @@
         judge.setPhone(input.getPhone());
         judge.setGender(input.getGender());
         judge.setDescription(input.getDescription());
-
-        // 澶村儚澶勭悊宸茬Щ闄わ紝鍥犱负鏁版嵁搴撹〃缁撴瀯涓病鏈塧vatar_media_id瀛楁
+        judge.setTitle(input.getTitle());
+        judge.setCompany(input.getCompany());
+        judge.setIntroduction(input.getIntroduction());
         // 澶村儚淇℃伅閫氳繃t_media琛ㄧ殑target_type鍜宼arget_id鍏宠仈
 
         // 璁剧疆涓撲笟鏍囩
         if (input.getMajorIds() != null && !input.getMajorIds().isEmpty()) {
-            List<Tag> specialties = tagRepository.findAllById(input.getMajorIds());
-            judge.setSpecialties(specialties);
+            List<Tag> specialtiesList = tagRepository.findAllById(input.getMajorIds());
+            judge.setSpecialties(new HashSet<>(specialtiesList));
         } else {
-            judge.setSpecialties(Collections.emptyList());
+            judge.setSpecialties(Collections.emptySet());
         }
 
         Judge savedJudge = judgeRepository.save(judge);
@@ -95,7 +104,7 @@
     @Transactional
     public void delete(Long id) {
         Judge judge = judgeRepository.findById(id)
-                .orElseThrow(() -> new RuntimeException("璇勫涓嶅瓨鍦�"));
+                .orElseThrow(() -> new BusinessException("璇勫涓嶅瓨鍦�"));
         judgeRepository.delete(judge);
     }
 
@@ -108,16 +117,21 @@
         response.setPhone(judge.getPhone());
         response.setGender(judge.getGender());
         response.setDescription(judge.getDescription());
+        response.setTitle(judge.getTitle());
+        response.setCompany(judge.getCompany());
+        response.setIntroduction(judge.getIntroduction());
         
-        // 鏌ヨ澶村儚淇℃伅锛歵arget_type=1琛ㄧず璇勫锛宼arget_id涓鸿瘎濮擨D
+        // 鏌ヨ澶村儚淇℃伅锛氫娇鐢ㄦ灇涓惧父閲忚〃绀鸿瘎濮斿ご鍍忕被鍨�
         log.info("=== Querying media for judge ID: {}", judge.getId());
-        List<Media> avatarMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(1, judge.getId(), 1);
+        List<Media> avatarMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(
+            MediaTargetType.JUDGE_AVATAR.getValue(), judge.getId(), 1);
         log.info("=== Found {} media records", avatarMedias.size());
         
         if (!avatarMedias.isEmpty()) {
             // 鍙栫涓�涓獟浣撲綔涓哄ご鍍�
             Media avatarMedia = avatarMedias.get(0);
-            String avatarUrl = avatarMedia.getPath();
+            String avatarPath = avatarMedia.getPath();
+            String avatarUrl = buildFullMediaUrl(avatarPath);
             log.info("=== Setting avatarUrl: {}", avatarUrl);
             response.setAvatarUrl(avatarUrl);
         } else {
@@ -138,6 +152,33 @@
 
         return response;
     }
+    
+    /**
+     * 鏋勫缓瀹屾暣鐨勫獟浣揢RL
+     * @param path 濯掍綋璺緞
+     * @return 瀹屾暣鐨刄RL
+     */
+    private String buildFullMediaUrl(String path) {
+        if (!StringUtils.hasText(path)) {
+            return null;
+        }
+        
+        // 濡傛灉璺緞宸茬粡鏄畬鏁碪RL锛岀洿鎺ヨ繑鍥�
+        if (path.startsWith("http://") || path.startsWith("https://")) {
+            return path;
+        }
+        
+        // 鏋勫缓瀹屾暣URL
+        if (StringUtils.hasText(mediaBaseUrl)) {
+            // 纭繚baseUrl浠�/缁撳熬锛宲ath涓嶄互/寮�澶�
+            String baseUrl = mediaBaseUrl.endsWith("/") ? mediaBaseUrl : mediaBaseUrl + "/";
+            String relativePath = path.startsWith("/") ? path.substring(1) : path;
+            return baseUrl + relativePath;
+        }
+        
+        // 濡傛灉娌℃湁閰嶇疆baseUrl锛岃繑鍥炲師璺緞
+        return path;
+    }
 
     /**
      * 淇濆瓨濯掍綋淇℃伅
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 2859b75..31ae5aa 100644
--- a/backend/src/main/java/com/rongyichuang/player/api/PlayerGraphqlApi.java
+++ b/backend/src/main/java/com/rongyichuang/player/api/PlayerGraphqlApi.java
@@ -3,18 +3,26 @@
 import com.rongyichuang.player.dto.input.ActivityPlayerRatingInput;
 import com.rongyichuang.player.dto.response.ActivityPlayerApplicationResponse;
 import com.rongyichuang.player.dto.response.ActivityPlayerDetailResponse;
+import com.rongyichuang.player.dto.response.JudgeRatingStatusResponse;
+import com.rongyichuang.player.dto.response.CurrentJudgeRatingResponse;
+import com.rongyichuang.player.dto.response.CurrentJudgeInfoResponse;
 import com.rongyichuang.player.service.PlayerApplicationService;
 import com.rongyichuang.player.service.ActivityPlayerDetailService;
 import com.rongyichuang.player.service.ActivityPlayerRatingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.graphql.data.method.annotation.Argument;
 import org.springframework.graphql.data.method.annotation.MutationMapping;
 import org.springframework.graphql.data.method.annotation.QueryMapping;
 import org.springframework.stereotype.Controller;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 @Controller
 public class PlayerGraphqlApi {
+
+    private static final Logger log = LoggerFactory.getLogger(PlayerGraphqlApi.class);
 
     private final PlayerApplicationService service;
     private final ActivityPlayerDetailService detailService;
@@ -31,10 +39,11 @@
     @QueryMapping
     public List<ActivityPlayerApplicationResponse> activityPlayerApplications(
             @Argument String name,
+            @Argument Long activityId,
             @Argument Integer page,
             @Argument Integer size
     ) {
-        return service.listApplications(name, page, size);
+        return service.listApplications(name, activityId, page, size);
     }
 
     /**
@@ -50,6 +59,51 @@
      */
     @MutationMapping
     public Boolean saveActivityPlayerRating(@Argument ActivityPlayerRatingInput input) {
-        return ratingService.saveRating(input);
+        log.info("鏀跺埌璇勫垎淇濆瓨璇锋眰锛宎ctivityPlayerId: {}, ratings count: {}", 
+                input.getActivityPlayerId(), input.getRatings() != null ? input.getRatings().size() : 0);
+        try {
+            Boolean result = ratingService.saveRating(input);
+            log.info("璇勫垎淇濆瓨缁撴灉: {}", result);
+            return result;
+        } catch (Exception e) {
+            log.error("GraphQL API 灞傛崟鑾峰紓甯�: {}", e.getMessage(), e);
+            throw e;
+        }
+    }
+
+    /**
+     * 鑾峰彇鎸囧畾閫夋墜鐨勬墍鏈夎瘎濮旇瘎鍒嗙姸鎬�
+     */
+    @QueryMapping
+    public List<JudgeRatingStatusResponse> judgeRatingsForPlayer(@Argument Long activityPlayerId) {
+        log.info("鑾峰彇閫夋墜璇勫璇勫垎鐘舵�侊紝activityPlayerId: {}", activityPlayerId);
+        return ratingService.getAllJudgeRatingsForPlayer(activityPlayerId);
+    }
+
+    /**
+     * 鑾峰彇褰撳墠璇勫瀵规寚瀹氶�夋墜鐨勮瘎鍒�
+     */
+    @QueryMapping
+    public CurrentJudgeRatingResponse currentJudgeRating(@Argument Long activityPlayerId) {
+        log.info("鑾峰彇褰撳墠璇勫璇勫垎锛宎ctivityPlayerId: {}", activityPlayerId);
+        return ratingService.getCurrentJudgeRating(activityPlayerId);
+    }
+
+    /**
+     * 鑾峰彇鎸囧畾閫夋墜鐨勫钩鍧囧垎
+     */
+    @QueryMapping
+    public BigDecimal averageScoreForPlayer(@Argument Long activityPlayerId) {
+        log.info("鑾峰彇閫夋墜骞冲潎鍒嗭紝activityPlayerId: {}", activityPlayerId);
+        return ratingService.getAverageScoreForPlayer(activityPlayerId);
+    }
+
+    /**
+     * 鑾峰彇褰撳墠璇勫淇℃伅
+     */
+    @QueryMapping
+    public CurrentJudgeInfoResponse currentJudgeInfo() {
+        log.info("鑾峰彇褰撳墠璇勫淇℃伅");
+        return ratingService.getCurrentJudgeInfo();
     }
 }
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/player/dto/response/CurrentJudgeInfoResponse.java b/backend/src/main/java/com/rongyichuang/player/dto/response/CurrentJudgeInfoResponse.java
new file mode 100644
index 0000000..22a797c
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/player/dto/response/CurrentJudgeInfoResponse.java
@@ -0,0 +1,53 @@
+package com.rongyichuang.player.dto.response;
+
+/**
+ * 褰撳墠璇勫淇℃伅鍝嶅簲
+ */
+public class CurrentJudgeInfoResponse {
+    
+    private Long id;
+    private String name;
+    private String phone;
+    private String description;
+
+    public CurrentJudgeInfoResponse() {}
+
+    public CurrentJudgeInfoResponse(Long id, String name, String phone, String description) {
+        this.id = id;
+        this.name = name;
+        this.phone = phone;
+        this.description = description;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/player/dto/response/CurrentJudgeRatingResponse.java b/backend/src/main/java/com/rongyichuang/player/dto/response/CurrentJudgeRatingResponse.java
new file mode 100644
index 0000000..f71bf5c
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/player/dto/response/CurrentJudgeRatingResponse.java
@@ -0,0 +1,110 @@
+package com.rongyichuang.player.dto.response;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 褰撳墠璇勫璇勫垎鍝嶅簲
+ */
+public class CurrentJudgeRatingResponse {
+    
+    private Long id;
+    private BigDecimal totalScore;
+    private Integer status;
+    private String remark;
+    private List<CurrentJudgeRatingItemResponse> items;
+
+    public CurrentJudgeRatingResponse() {}
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public BigDecimal getTotalScore() {
+        return totalScore;
+    }
+
+    public void setTotalScore(BigDecimal totalScore) {
+        this.totalScore = totalScore;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public List<CurrentJudgeRatingItemResponse> getItems() {
+        return items;
+    }
+
+    public void setItems(List<CurrentJudgeRatingItemResponse> items) {
+        this.items = items;
+    }
+
+    /**
+     * 璇勫垎椤瑰搷搴�
+     */
+    public static class CurrentJudgeRatingItemResponse {
+        private Long ratingItemId;
+        private String ratingItemName;
+        private BigDecimal score;
+        private BigDecimal weightedScore;
+
+        public CurrentJudgeRatingItemResponse() {}
+
+        public CurrentJudgeRatingItemResponse(Long ratingItemId, String ratingItemName, 
+                                            BigDecimal score, BigDecimal weightedScore) {
+            this.ratingItemId = ratingItemId;
+            this.ratingItemName = ratingItemName;
+            this.score = score;
+            this.weightedScore = weightedScore;
+        }
+
+        public Long getRatingItemId() {
+            return ratingItemId;
+        }
+
+        public void setRatingItemId(Long ratingItemId) {
+            this.ratingItemId = ratingItemId;
+        }
+
+        public String getRatingItemName() {
+            return ratingItemName;
+        }
+
+        public void setRatingItemName(String ratingItemName) {
+            this.ratingItemName = ratingItemName;
+        }
+
+        public BigDecimal getScore() {
+            return score;
+        }
+
+        public void setScore(BigDecimal score) {
+            this.score = score;
+        }
+
+        public BigDecimal getWeightedScore() {
+            return weightedScore;
+        }
+
+        public void setWeightedScore(BigDecimal weightedScore) {
+            this.weightedScore = weightedScore;
+        }
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/player/dto/response/JudgeRatingStatusResponse.java b/backend/src/main/java/com/rongyichuang/player/dto/response/JudgeRatingStatusResponse.java
new file mode 100644
index 0000000..0782aa9
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/player/dto/response/JudgeRatingStatusResponse.java
@@ -0,0 +1,66 @@
+package com.rongyichuang.player.dto.response;
+
+import java.math.BigDecimal;
+
+/**
+ * 璇勫璇勫垎鐘舵�佸搷搴�
+ */
+public class JudgeRatingStatusResponse {
+    
+    private Long judgeId;
+    private String judgeName;
+    private BigDecimal totalScore;
+    private Integer status;
+    private Boolean isCurrentJudge;
+
+    public JudgeRatingStatusResponse() {}
+
+    public JudgeRatingStatusResponse(Long judgeId, String judgeName, BigDecimal totalScore, 
+                                   Integer status, Boolean isCurrentJudge) {
+        this.judgeId = judgeId;
+        this.judgeName = judgeName;
+        this.totalScore = totalScore;
+        this.status = status;
+        this.isCurrentJudge = isCurrentJudge;
+    }
+
+    public Long getJudgeId() {
+        return judgeId;
+    }
+
+    public void setJudgeId(Long judgeId) {
+        this.judgeId = judgeId;
+    }
+
+    public String getJudgeName() {
+        return judgeName;
+    }
+
+    public void setJudgeName(String judgeName) {
+        this.judgeName = judgeName;
+    }
+
+    public BigDecimal getTotalScore() {
+        return totalScore;
+    }
+
+    public void setTotalScore(BigDecimal totalScore) {
+        this.totalScore = totalScore;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public Boolean getIsCurrentJudge() {
+        return isCurrentJudge;
+    }
+
+    public void setIsCurrentJudge(Boolean isCurrentJudge) {
+        this.isCurrentJudge = isCurrentJudge;
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/player/dto/response/PlayerInfoResponse.java b/backend/src/main/java/com/rongyichuang/player/dto/response/PlayerInfoResponse.java
index e199d3e..ea7ee50 100644
--- a/backend/src/main/java/com/rongyichuang/player/dto/response/PlayerInfoResponse.java
+++ b/backend/src/main/java/com/rongyichuang/player/dto/response/PlayerInfoResponse.java
@@ -8,7 +8,7 @@
     private String name;
     private String phone;
     private String description; // 绠�浠�
-    private String avatarUrl; // 澶村儚URL锛堜粠 t_media 鑾峰彇锛宼arget_type=5锛�
+    private String avatarUrl; // 澶村儚URL锛堜粠 t_media 鑾峰彇锛屼娇鐢� MediaTargetType.STUDENT_AVATAR锛屽�间负6锛�
 
     // Constructors
     public PlayerInfoResponse() {}
diff --git a/backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerDetailService.java b/backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerDetailService.java
index 64f970c..00413de 100644
--- a/backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerDetailService.java
+++ b/backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerDetailService.java
@@ -5,6 +5,7 @@
 import com.rongyichuang.rating.entity.RatingScheme;
 import com.rongyichuang.rating.repository.RatingSchemeRepository;
 import com.rongyichuang.common.entity.Media;
+import com.rongyichuang.common.enums.MediaTargetType;
 import com.rongyichuang.common.repository.MediaRepository;
 import jakarta.persistence.EntityManager;
 import jakarta.persistence.PersistenceContext;
@@ -49,7 +50,7 @@
             SELECT ap.id, ap.description, ap.activity_id,
                    p.id as player_id, p.name as player_name, p.phone, p.description as player_desc,
                    a.name as activity_name, a.rating_scheme_id
-            FROM t_avtivity_player ap
+            FROM t_activity_player ap
             JOIN t_player p ON p.id = ap.player_id
             JOIN t_activity a ON a.id = ap.activity_id
             WHERE ap.id = ?
@@ -73,14 +74,15 @@
 
         // 鏋勫缓瀛﹀憳淇℃伅
         PlayerInfoResponse playerInfo = new PlayerInfoResponse();
-        playerInfo.setId(row[3] != null ? Long.valueOf(row[3].toString()) : null);
+        playerInfo.setId(row[3] != null ? ((Number) row[3]).longValue() : null);
         playerInfo.setName(row[4] != null ? row[4].toString() : "");
         playerInfo.setPhone(row[5] != null ? row[5].toString() : "");
         playerInfo.setDescription(row[6] != null ? row[6].toString() : "");
 
-        // 鏌ヨ瀛﹀憳澶村儚锛坱arget_type=5锛�
+        // 鏌ヨ瀛﹀憳澶村儚锛堜娇鐢ㄦ灇涓惧父閲忚〃绀哄鍛樺ご鍍忕被鍨嬶級
         if (playerInfo.getId() != null) {
-            List<Media> avatarMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(5, playerInfo.getId(), 1);
+            List<Media> avatarMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(
+                MediaTargetType.STUDENT_AVATAR.getValue(), playerInfo.getId(), 1);
             if (!avatarMedias.isEmpty()) {
                 Media avatar = avatarMedias.get(0);
                 String avatarUrl = avatar.getPath();
@@ -90,8 +92,9 @@
         }
         response.setPlayerInfo(playerInfo);
 
-        // 鏌ヨ鎻愪氦鐨勮祫鏂欙紙target_type=4锛�
-        List<Media> submissionMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(4, activityPlayerId, 1);
+        // 鏌ヨ鎻愪氦鐨勮祫鏂欙紙浣跨敤鏋氫妇甯搁噺琛ㄧず鍙傝禌鎶ュ悕璧勬枡绫诲瀷锛�
+        List<Media> submissionMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(
+            MediaTargetType.ACTIVITY_PLAYER_SUBMISSION.getValue(), activityPlayerId, 1);
         List<SubmissionMediaResponse> submissionFiles = submissionMedias.stream()
                 .map(this::convertToSubmissionMedia)
                 .collect(Collectors.toList());
@@ -99,7 +102,7 @@
         log.info("鎵惧埌鎻愪氦璧勬枡 {} 涓�", submissionFiles.size());
 
         // 鏌ヨ璇勫垎妯℃澘
-        Long ratingSchemeId = row[8] != null ? Long.valueOf(row[8].toString()) : null;
+        Long ratingSchemeId = row[8] != null ? ((Number) row[8]).longValue() : null;
         if (ratingSchemeId != null) {
             RatingFormResponse ratingForm = buildRatingForm(ratingSchemeId);
             response.setRatingForm(ratingForm);
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 80845c9..24ca43f 100644
--- a/backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerRatingService.java
+++ b/backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerRatingService.java
@@ -1,7 +1,19 @@
 package com.rongyichuang.player.service;
 
+import com.rongyichuang.activity.entity.ActivityPlayerRating;
+import com.rongyichuang.activity.entity.ActivityPlayerRatingItem;
+import com.rongyichuang.activity.repository.ActivityPlayerRatingRepository;
+import com.rongyichuang.activity.repository.ActivityPlayerRatingItemRepository;
+import com.rongyichuang.common.util.UserContextUtil;
+import com.rongyichuang.judge.entity.Judge;
+import com.rongyichuang.judge.repository.JudgeRepository;
 import com.rongyichuang.player.dto.input.ActivityPlayerRatingInput;
 import com.rongyichuang.player.dto.input.ActivityPlayerRatingItemInput;
+import com.rongyichuang.player.dto.response.JudgeRatingStatusResponse;
+import com.rongyichuang.player.dto.response.CurrentJudgeRatingResponse;
+import com.rongyichuang.player.dto.response.CurrentJudgeInfoResponse;
+import com.rongyichuang.rating.entity.RatingItem;
+import com.rongyichuang.rating.repository.RatingItemRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -9,7 +21,11 @@
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 
 @Service
 public class ActivityPlayerRatingService {
@@ -18,44 +34,263 @@
 
     @Autowired
     private JdbcTemplate jdbcTemplate;
+    
+    @Autowired
+    private ActivityPlayerRatingRepository activityPlayerRatingRepository;
+
+    @Autowired
+    private ActivityPlayerRatingItemRepository activityPlayerRatingItemRepository;
+
+    @Autowired
+    private RatingItemRepository ratingItemRepository;
+
+    @Autowired
+    private JudgeRepository judgeRepository;
+
+    @Autowired
+    private UserContextUtil userContextUtil;
 
     @Transactional
     public boolean saveRating(ActivityPlayerRatingInput input) {
         try {
-            log.info("寮�濮嬩繚瀛樿瘎鍒嗭紝activityPlayerId: {}", input.getActivityPlayerId());
+            log.info("寮�濮嬩繚瀛樺璇勫璇勫垎锛宎ctivityPlayerId: {}", input.getActivityPlayerId());
             
-            // 鍏堝垹闄ゅ凡鏈夌殑璇勫垎璁板綍锛堝鏋滃瓨鍦級
-            String deleteSql = "DELETE FROM t_activity_player_rating_item WHERE activity_player_id = ?";
-            int deletedCount = jdbcTemplate.update(deleteSql, input.getActivityPlayerId());
-            log.info("鍒犻櫎宸叉湁璇勫垎璁板綍: {} 鏉�", deletedCount);
-            
-            // 鎻掑叆鏂扮殑璇勫垎璁板綍
-            String insertSql = "INSERT INTO t_activity_player_rating_item " +
-                    "(activity_player_id, rating_item_id, score, comment, create_time, update_time) " +
-                    "VALUES (?, ?, ?, ?, ?, ?)";
-            
-            LocalDateTime now = LocalDateTime.now();
-            int totalInserted = 0;
-            
-            for (ActivityPlayerRatingItemInput ratingItem : input.getRatings()) {
-                int inserted = jdbcTemplate.update(insertSql,
-                        input.getActivityPlayerId(),
-                        ratingItem.getItemId(),
-                        ratingItem.getScore(),
-                        input.getComment(),
-                        now,
-                        now
-                );
-                totalInserted += inserted;
-                log.info("淇濆瓨璇勫垎椤圭洰: itemId={}, score={}", ratingItem.getItemId(), ratingItem.getScore());
+            // 鑾峰彇褰撳墠璇勫淇℃伅
+            Long currentJudgeId = userContextUtil.getCurrentJudgeId();
+            if (currentJudgeId == null) {
+                throw new RuntimeException("褰撳墠鐢ㄦ埛涓嶆槸璇勫锛屾棤娉曡繘琛岃瘎鍒�");
             }
             
-            log.info("璇勫垎淇濆瓨瀹屾垚锛屽叡鎻掑叆 {} 鏉¤褰�", totalInserted);
+            Long activityPlayerId = input.getActivityPlayerId();
+            
+            // 鏌ヨ activity_id, player_id
+            String queryPlayerSql = "SELECT activity_id, player_id FROM t_activity_player WHERE id = ?";
+            Map<String, Object> playerData = jdbcTemplate.queryForMap(queryPlayerSql, activityPlayerId);
+            Long activityId = (Long) playerData.get("activity_id");
+            Long playerId = (Long) playerData.get("player_id");
+            log.info("鏌ヨ鍒扮殑鏁版嵁 - activityId: {}, playerId: {}, judgeId: {}", activityId, playerId, currentJudgeId);
+            
+            // 楠岃瘉璇勫鏄惁鏈夋潈闄愯瘎鍒嗘娲诲姩
+            if (!userContextUtil.isCurrentUserJudgeForActivity(activityId)) {
+                throw new RuntimeException("褰撳墠璇勫鏃犳潈闄愯瘎鍒嗘娲诲姩");
+            }
+            
+            // 鏌ヨ娲诲姩鐨勮瘎鍒嗘ā鏉縄D
+            String queryActivitySql = "SELECT rating_scheme_id FROM t_activity WHERE id = ?";
+            Long ratingSchemeId = jdbcTemplate.queryForObject(queryActivitySql, Long.class, activityId);
+            log.info("鏌ヨ鍒扮殑ratingSchemeId: {}", ratingSchemeId);
+            
+            if (ratingSchemeId == null) {
+                throw new RuntimeException("娲诲姩鏈厤缃瘎鍒嗘ā鏉匡紝activityId: " + activityId);
+            }
+            
+            // 鏌ユ壘鎴栧垱寤篈ctivityPlayerRating璁板綍
+            Optional<ActivityPlayerRating> existingRating = activityPlayerRatingRepository
+                    .findByActivityPlayerIdAndJudgeId(activityPlayerId, currentJudgeId);
+            
+            ActivityPlayerRating rating;
+            if (existingRating.isPresent()) {
+                rating = existingRating.get();
+                log.info("鎵惧埌宸叉湁璇勫垎璁板綍锛孖D: {}", rating.getId());
+                // 鍒犻櫎宸叉湁鐨勮瘎鍒嗛」
+                activityPlayerRatingItemRepository.deleteByActivityPlayerRatingId(rating.getId());
+            } else {
+                // 鍒涘缓鏂扮殑璇勫垎璁板綍
+                rating = new ActivityPlayerRating(activityId, activityPlayerId, playerId, currentJudgeId, ratingSchemeId);
+                rating = activityPlayerRatingRepository.save(rating);
+                log.info("鍒涘缓鏂扮殑璇勫垎璁板綍锛孖D: {}", rating.getId());
+            }
+            
+            // 淇濆瓨璇勫垎椤�
+            BigDecimal totalScore = BigDecimal.ZERO;
+            for (ActivityPlayerRatingItemInput ratingItemInput : input.getRatings()) {
+                Long itemId = ratingItemInput.getItemId();
+                BigDecimal score = BigDecimal.valueOf(ratingItemInput.getScore());
+                
+                // 鏌ヨ璇勫垎椤逛俊鎭�
+                Optional<RatingItem> ratingItemOpt = ratingItemRepository.findById(itemId);
+                if (ratingItemOpt.isEmpty()) {
+                    log.warn("璇勫垎椤逛笉瀛樺湪锛宨temId: {}", itemId);
+                    continue;
+                }
+                
+                RatingItem ratingItem = ratingItemOpt.get();
+                
+                // 鍒涘缓璇勫垎椤硅褰�
+                ActivityPlayerRatingItem ratingItemEntity = new ActivityPlayerRatingItem(
+                        rating.getId(),
+                        itemId,
+                        ratingItem.getName(),
+                        BigDecimal.ONE, // 榛樿鏉冮噸涓�1
+                        BigDecimal.valueOf(ratingItem.getMaxScore()),
+                        score
+                );
+                ratingItemEntity.setRemark(input.getComment());
+                
+                activityPlayerRatingItemRepository.save(ratingItemEntity);
+                
+                // 绱姞鍔犳潈寰楀垎
+                if (ratingItemEntity.getWeightedScore() != null) {
+                    totalScore = totalScore.add(ratingItemEntity.getWeightedScore());
+                }
+                
+                log.info("淇濆瓨璇勫垎椤圭洰: itemId={}, score={}, weightedScore={}", 
+                        itemId, score, ratingItemEntity.getWeightedScore());
+            }
+            
+            // 鏇存柊鎬诲垎鍜岀姸鎬�
+            rating.setTotalScore(totalScore);
+            rating.setStatus(1); // 宸茶瘎鍒�
+            rating.setRemark(input.getComment());
+            activityPlayerRatingRepository.save(rating);
+            
+            log.info("璇勫垎淇濆瓨瀹屾垚锛屾�诲垎: {}", totalScore);
             return true;
             
         } catch (Exception e) {
-            log.error("淇濆瓨璇勫垎澶辫触", e);
-            throw new RuntimeException("淇濆瓨璇勫垎澶辫触: " + e.getMessage());
+            log.error("淇濆瓨璇勫垎澶辫触锛屽紓甯哥被鍨�: {}, 寮傚父淇℃伅: {}", e.getClass().getSimpleName(), e.getMessage(), e);
+            e.printStackTrace();
+            throw new RuntimeException("淇濆瓨璇勫垎澶辫触: " + e.getClass().getSimpleName() + " - " + e.getMessage(), e);
         }
     }
+    
+    /**
+     * 鑾峰彇鎸囧畾娲诲姩閫夋墜鐨勬墍鏈夎瘎濮旇瘎鍒�
+     */
+    public List<ActivityPlayerRating> getAllRatingsForPlayer(Long activityPlayerId) {
+        return activityPlayerRatingRepository.findByActivityPlayerId(activityPlayerId);
+    }
+    
+    /**
+     * 鑾峰彇鎸囧畾娲诲姩閫夋墜鐨勫钩鍧囧垎
+     */
+    public BigDecimal getAverageScoreForPlayer(Long activityPlayerId) {
+        List<ActivityPlayerRating> ratings = activityPlayerRatingRepository
+                .findCompletedRatingsByActivityPlayerId(activityPlayerId);
+        
+        if (ratings.isEmpty()) {
+            return BigDecimal.ZERO;
+        }
+        
+        BigDecimal totalScore = ratings.stream()
+                .map(ActivityPlayerRating::getTotalScore)
+                .filter(score -> score != null)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        
+        return totalScore.divide(BigDecimal.valueOf(ratings.size()), 2, BigDecimal.ROUND_HALF_UP);
+    }
+    
+    /**
+     * 鑾峰彇褰撳墠璇勫瀵规寚瀹氶�夋墜鐨勮瘎鍒�
+     */
+    public CurrentJudgeRatingResponse getCurrentJudgeRating(Long activityPlayerId) {
+        Long currentJudgeId = userContextUtil.getCurrentJudgeId();
+        if (currentJudgeId == null) {
+            return null;
+        }
+        
+        Optional<ActivityPlayerRating> ratingOpt = activityPlayerRatingRepository
+                .findByActivityPlayerIdAndJudgeId(activityPlayerId, currentJudgeId);
+        
+        if (!ratingOpt.isPresent()) {
+            return null;
+        }
+        
+        ActivityPlayerRating rating = ratingOpt.get();
+        CurrentJudgeRatingResponse response = new CurrentJudgeRatingResponse();
+        response.setId(rating.getId());
+        response.setTotalScore(rating.getTotalScore());
+        response.setStatus(rating.getStatus());
+        response.setRemark(rating.getRemark());
+        
+        // 鑾峰彇璇勫垎椤�
+        List<ActivityPlayerRatingItem> items = activityPlayerRatingItemRepository
+                .findByActivityPlayerRatingId(rating.getId());
+        
+        List<CurrentJudgeRatingResponse.CurrentJudgeRatingItemResponse> itemResponses = items.stream()
+                .map(item -> new CurrentJudgeRatingResponse.CurrentJudgeRatingItemResponse(
+                        item.getRatingItemId(),
+                        item.getRatingItemName(),
+                        item.getScore(),
+                        item.getWeightedScore()
+                ))
+                .collect(java.util.stream.Collectors.toList());
+        
+        response.setItems(itemResponses);
+        return response;
+    }
+    
+    /**
+     * 妫�鏌ュ綋鍓嶈瘎濮旀槸鍚﹀凡瀵规寚瀹氶�夋墜璇勫垎
+     */
+    public boolean hasCurrentJudgeRated(Long activityPlayerId) {
+        Long currentJudgeId = userContextUtil.getCurrentJudgeId();
+        if (currentJudgeId == null) {
+            return false;
+        }
+        
+        return activityPlayerRatingRepository.existsByActivityPlayerIdAndJudgeId(activityPlayerId, currentJudgeId);
+    }
+
+    /**
+     * 鑾峰彇鎸囧畾閫夋墜鐨勬墍鏈夎瘎濮旇瘎鍒嗙姸鎬�
+     */
+    public List<JudgeRatingStatusResponse> getAllJudgeRatingsForPlayer(Long activityPlayerId) {
+        // 棣栧厛鑾峰彇娲诲姩ID
+        String activitySql = "SELECT activity_id FROM t_activity_player WHERE id = ?";
+        Long activityId = jdbcTemplate.queryForObject(activitySql, Long.class, activityPlayerId);
+        
+        if (activityId == null) {
+            throw new RuntimeException("鏈壘鍒版椿鍔ㄩ�夋墜璁板綍锛宎ctivityPlayerId: " + activityPlayerId);
+        }
+        
+        // 鑾峰彇娲诲姩鐨勬墍鏈夎瘎濮�
+        String judgesSql = "SELECT j.id, j.name FROM t_judge j " +
+                          "JOIN t_activity_judge aj ON j.id = aj.judge_id " +
+                          "WHERE aj.activity_id = ? ORDER BY j.name";
+        
+        List<Map<String, Object>> judgeRows = jdbcTemplate.queryForList(judgesSql, activityId);
+        
+        Long currentJudgeId = userContextUtil.getCurrentJudgeId();
+        
+        return judgeRows.stream().map(row -> {
+            Long judgeId = ((Number) row.get("id")).longValue();
+            String judgeName = (String) row.get("name");
+            
+            // 鏌ユ壘璇ヨ瘎濮旂殑璇勫垎
+            Optional<ActivityPlayerRating> ratingOpt = activityPlayerRatingRepository
+                    .findByActivityPlayerIdAndJudgeId(activityPlayerId, judgeId);
+            
+            BigDecimal totalScore = null;
+            Integer status = 0;
+            
+            if (ratingOpt.isPresent()) {
+                ActivityPlayerRating rating = ratingOpt.get();
+                totalScore = rating.getTotalScore();
+                status = rating.getStatus();
+            }
+            
+            Boolean isCurrentJudge = judgeId.equals(currentJudgeId);
+            
+            return new JudgeRatingStatusResponse(judgeId, judgeName, totalScore, status, isCurrentJudge);
+        }).collect(java.util.stream.Collectors.toList());
+    }
+
+    /**
+     * 鑾峰彇褰撳墠璇勫淇℃伅
+     */
+    public CurrentJudgeInfoResponse getCurrentJudgeInfo() {
+        Optional<Judge> currentJudgeOpt = userContextUtil.getCurrentJudge();
+        if (!currentJudgeOpt.isPresent()) {
+            return null;
+        }
+        
+        Judge currentJudge = currentJudgeOpt.get();
+        return new CurrentJudgeInfoResponse(
+                currentJudge.getId(),
+                currentJudge.getName(),
+                currentJudge.getPhone(),
+                currentJudge.getDescription()
+        );
+    }
 }
\ No newline at end of file
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 62583da..2a34eb1 100644
--- a/backend/src/main/java/com/rongyichuang/player/service/PlayerApplicationService.java
+++ b/backend/src/main/java/com/rongyichuang/player/service/PlayerApplicationService.java
@@ -15,20 +15,33 @@
     private EntityManager em;
 
     /**
-     * 璇诲彇鎶ュ悕鐢宠锛屾寜鎶ュ悕鏃堕棿鍊掑簭
-     * 娉ㄦ剰锛氬疄闄呭簱琛ㄤ负 t_avtivity_player锛堟嫾鍐欎互搴撲负鍑嗭級
+     * 鏌ヨ娲诲姩鎶ュ悕淇℃伅
      */
     @SuppressWarnings("unchecked")
-    public List<ActivityPlayerApplicationResponse> listApplications(String name, Integer page, Integer size) {
+    public List<ActivityPlayerApplicationResponse> listApplications(String name, Long activityId, Integer page, Integer size) {
         String baseSql =
             "SELECT ap.id, p.name AS player_name, a.name AS activity_name, p.phone AS phone, ap.create_time AS apply_time, p.audit_state AS state " +
-            "FROM t_avtivity_player ap " +
+            "FROM t_activity_player ap " +
             "JOIN t_player p ON p.id = ap.player_id " +
             "JOIN t_activity a ON a.id = ap.activity_id ";
-        String where = "";
+        
+        StringBuilder whereClause = new StringBuilder();
+        boolean hasCondition = false;
+        
         if (name != null && !name.isEmpty()) {
-            where = "WHERE p.name LIKE CONCAT('%', :name, '%') ";
+            whereClause.append("p.name LIKE CONCAT('%', :name, '%')");
+            hasCondition = true;
         }
+        
+        if (activityId != null) {
+            if (hasCondition) {
+                whereClause.append(" AND ");
+            }
+            whereClause.append("ap.activity_id = :activityId");
+            hasCondition = true;
+        }
+        
+        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) {
@@ -37,9 +50,12 @@
         }
 
         var q = em.createNativeQuery(baseSql + where + order + limit);
-        if (!where.isEmpty()) {
+        if (name != null && !name.isEmpty()) {
             q.setParameter("name", name);
         }
+        if (activityId != null) {
+            q.setParameter("activityId", activityId);
+        }
         List<Object[]> rows = q.getResultList();
         List<ActivityPlayerApplicationResponse> list = new ArrayList<>();
         for (Object[] r : rows) {
diff --git a/backend/src/main/java/com/rongyichuang/role/api/RoleGraphqlApi.java b/backend/src/main/java/com/rongyichuang/role/api/RoleGraphqlApi.java
new file mode 100644
index 0000000..f2b39ac
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/role/api/RoleGraphqlApi.java
@@ -0,0 +1,68 @@
+package com.rongyichuang.role.api;
+
+import com.rongyichuang.role.dto.response.RoleResponse;
+import com.rongyichuang.role.service.RoleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.graphql.data.method.annotation.Argument;
+import org.springframework.graphql.data.method.annotation.QueryMapping;
+import org.springframework.stereotype.Controller;
+
+import java.util.List;
+
+/**
+ * 瑙掕壊GraphQL API鎺у埗鍣�
+ */
+@Controller
+public class RoleGraphqlApi {
+
+    @Autowired
+    private RoleService roleService;
+
+    /**
+     * 鑾峰彇鎵�鏈夎鑹插垪琛�
+     */
+    @QueryMapping
+    public List<RoleResponse> roles() {
+        return roleService.getAllRoles();
+    }
+
+    /**
+     * 鑾峰彇鎵�鏈夊惎鐢ㄧ姸鎬佺殑瑙掕壊
+     */
+    @QueryMapping
+    public List<RoleResponse> activeRoles() {
+        return roleService.getAllActiveRoles();
+    }
+
+    /**
+     * 鏍规嵁ID鑾峰彇瑙掕壊璇︽儏
+     */
+    @QueryMapping
+    public RoleResponse role(@Argument Long id) {
+        return roleService.getRoleById(id).orElse(null);
+    }
+
+    /**
+     * 鏍规嵁瑙掕壊浠g爜鑾峰彇瑙掕壊
+     */
+    @QueryMapping
+    public RoleResponse roleByCode(@Argument String code) {
+        return roleService.getRoleByCode(code).orElse(null);
+    }
+
+    /**
+     * 鏍规嵁鐘舵�佽幏鍙栬鑹�
+     */
+    @QueryMapping
+    public List<RoleResponse> rolesByState(@Argument Integer state) {
+        return roleService.getRolesByState(state);
+    }
+
+    /**
+     * 鏍规嵁鍚嶇О妯$硦鏌ヨ瑙掕壊
+     */
+    @QueryMapping
+    public List<RoleResponse> rolesByName(@Argument String name) {
+        return roleService.searchRolesByName(name);
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/role/dto/response/RoleResponse.java b/backend/src/main/java/com/rongyichuang/role/dto/response/RoleResponse.java
new file mode 100644
index 0000000..9f4e53c
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/role/dto/response/RoleResponse.java
@@ -0,0 +1,79 @@
+package com.rongyichuang.role.dto.response;
+
+public class RoleResponse {
+    private Long id;
+    private String code;
+    private String name;
+    private String description;
+    private Integer state;
+    private String createTime;
+    private String updateTime;
+    
+    // 鏋勯�犲嚱鏁�
+    public RoleResponse() {}
+    
+    public RoleResponse(Long id, String code, String name, String description, Integer state) {
+        this.id = id;
+        this.code = code;
+        this.name = name;
+        this.description = description;
+        this.state = state;
+    }
+    
+    // Getter鍜孲etter鏂规硶
+    public Long getId() {
+        return id;
+    }
+    
+    public void setId(Long id) {
+        this.id = id;
+    }
+    
+    public String getCode() {
+        return code;
+    }
+    
+    public void setCode(String code) {
+        this.code = code;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public String getDescription() {
+        return description;
+    }
+    
+    public void setDescription(String description) {
+        this.description = description;
+    }
+    
+    public Integer getState() {
+        return state;
+    }
+    
+    public void setState(Integer state) {
+        this.state = state;
+    }
+    
+    public String getCreateTime() {
+        return createTime;
+    }
+    
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+    
+    public String getUpdateTime() {
+        return updateTime;
+    }
+    
+    public void setUpdateTime(String updateTime) {
+        this.updateTime = updateTime;
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/role/entity/Role.java b/backend/src/main/java/com/rongyichuang/role/entity/Role.java
new file mode 100644
index 0000000..cbb3687
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/role/entity/Role.java
@@ -0,0 +1,150 @@
+package com.rongyichuang.role.entity;
+
+import jakarta.persistence.*;
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "t_role")
+public class Role {
+    
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    
+    @Column(name = "code", nullable = false, length = 64)
+    private String code;
+    
+    @Column(name = "name", nullable = false, length = 128)
+    private String name;
+    
+    @Column(name = "description", length = 255)
+    private String description;
+    
+    @Column(name = "state", nullable = false)
+    private Integer state;
+    
+    @Column(name = "create_time")
+    private LocalDateTime createTime;
+    
+    @Column(name = "create_user_id")
+    private Long createUserId;
+    
+    @Column(name = "update_time")
+    private LocalDateTime updateTime;
+    
+    @Column(name = "update_user_id")
+    private Long updateUserId;
+    
+    @Version
+    @Column(name = "version")
+    private Long version;
+    
+    // 鏋勯�犲嚱鏁�
+    public Role() {}
+    
+    public Role(String code, String name, String description, Integer state) {
+        this.code = code;
+        this.name = name;
+        this.description = description;
+        this.state = state;
+        this.createTime = LocalDateTime.now();
+        this.updateTime = LocalDateTime.now();
+        this.version = 0L;
+    }
+    
+    // Getter鍜孲etter鏂规硶
+    public Long getId() {
+        return id;
+    }
+    
+    public void setId(Long id) {
+        this.id = id;
+    }
+    
+    public String getCode() {
+        return code;
+    }
+    
+    public void setCode(String code) {
+        this.code = code;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public String getDescription() {
+        return description;
+    }
+    
+    public void setDescription(String description) {
+        this.description = description;
+    }
+    
+    public Integer getState() {
+        return state;
+    }
+    
+    public void setState(Integer state) {
+        this.state = state;
+    }
+    
+    public LocalDateTime getCreateTime() {
+        return createTime;
+    }
+    
+    public void setCreateTime(LocalDateTime createTime) {
+        this.createTime = createTime;
+    }
+    
+    public Long getCreateUserId() {
+        return createUserId;
+    }
+    
+    public void setCreateUserId(Long createUserId) {
+        this.createUserId = createUserId;
+    }
+    
+    public LocalDateTime getUpdateTime() {
+        return updateTime;
+    }
+    
+    public void setUpdateTime(LocalDateTime updateTime) {
+        this.updateTime = updateTime;
+    }
+    
+    public Long getUpdateUserId() {
+        return updateUserId;
+    }
+    
+    public void setUpdateUserId(Long updateUserId) {
+        this.updateUserId = updateUserId;
+    }
+    
+    public Long getVersion() {
+        return version;
+    }
+    
+    public void setVersion(Long version) {
+        this.version = version;
+    }
+    
+    @PrePersist
+    protected void onCreate() {
+        if (createTime == null) {
+            createTime = LocalDateTime.now();
+        }
+        if (updateTime == null) {
+            updateTime = LocalDateTime.now();
+        }
+    }
+    
+    @PreUpdate
+    protected void onUpdate() {
+        updateTime = LocalDateTime.now();
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/role/repository/RoleRepository.java b/backend/src/main/java/com/rongyichuang/role/repository/RoleRepository.java
new file mode 100644
index 0000000..0e4a43b
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/role/repository/RoleRepository.java
@@ -0,0 +1,35 @@
+package com.rongyichuang.role.repository;
+
+import com.rongyichuang.role.entity.Role;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface RoleRepository extends JpaRepository<Role, Long> {
+    
+    /**
+     * 鏍规嵁瑙掕壊浠g爜鏌ユ壘瑙掕壊
+     */
+    Optional<Role> findByCode(String code);
+    
+    /**
+     * 鏌ユ壘鎵�鏈夊惎鐢ㄧ姸鎬佺殑瑙掕壊
+     */
+    @Query("SELECT r FROM Role r WHERE r.state = 1 ORDER BY r.id")
+    List<Role> findAllActiveRoles();
+    
+    /**
+     * 鏍规嵁鐘舵�佹煡鎵捐鑹�
+     */
+    List<Role> findByStateOrderById(Integer state);
+    
+    /**
+     * 鏍规嵁瑙掕壊鍚嶇О妯$硦鏌ヨ
+     */
+    @Query("SELECT r FROM Role r WHERE r.name LIKE %:name% ORDER BY r.id")
+    List<Role> findByNameContaining(String name);
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/role/service/RoleService.java b/backend/src/main/java/com/rongyichuang/role/service/RoleService.java
new file mode 100644
index 0000000..f3fca44
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/role/service/RoleService.java
@@ -0,0 +1,98 @@
+package com.rongyichuang.role.service;
+
+import com.rongyichuang.role.dto.response.RoleResponse;
+import com.rongyichuang.role.entity.Role;
+import com.rongyichuang.role.repository.RoleRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@Service
+public class RoleService {
+    
+    @Autowired
+    private RoleRepository roleRepository;
+    
+    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+    
+    /**
+     * 鑾峰彇鎵�鏈夊惎鐢ㄧ姸鎬佺殑瑙掕壊
+     */
+    public List<RoleResponse> getAllActiveRoles() {
+        List<Role> roles = roleRepository.findAllActiveRoles();
+        return roles.stream()
+                .map(this::convertToResponse)
+                .collect(Collectors.toList());
+    }
+    
+    /**
+     * 鑾峰彇鎵�鏈夎鑹�
+     */
+    public List<RoleResponse> getAllRoles() {
+        List<Role> roles = roleRepository.findAll();
+        return roles.stream()
+                .map(this::convertToResponse)
+                .collect(Collectors.toList());
+    }
+    
+    /**
+     * 鏍规嵁ID鑾峰彇瑙掕壊
+     */
+    public Optional<RoleResponse> getRoleById(Long id) {
+        Optional<Role> role = roleRepository.findById(id);
+        return role.map(this::convertToResponse);
+    }
+    
+    /**
+     * 鏍规嵁瑙掕壊浠g爜鑾峰彇瑙掕壊
+     */
+    public Optional<RoleResponse> getRoleByCode(String code) {
+        Optional<Role> role = roleRepository.findByCode(code);
+        return role.map(this::convertToResponse);
+    }
+    
+    /**
+     * 鏍规嵁鐘舵�佽幏鍙栬鑹�
+     */
+    public List<RoleResponse> getRolesByState(Integer state) {
+        List<Role> roles = roleRepository.findByStateOrderById(state);
+        return roles.stream()
+                .map(this::convertToResponse)
+                .collect(Collectors.toList());
+    }
+    
+    /**
+     * 鏍规嵁鍚嶇О妯$硦鏌ヨ瑙掕壊
+     */
+    public List<RoleResponse> searchRolesByName(String name) {
+        List<Role> roles = roleRepository.findByNameContaining(name);
+        return roles.stream()
+                .map(this::convertToResponse)
+                .collect(Collectors.toList());
+    }
+    
+    /**
+     * 灏哛ole瀹炰綋杞崲涓篟oleResponse
+     */
+    private RoleResponse convertToResponse(Role role) {
+        RoleResponse response = new RoleResponse();
+        response.setId(role.getId());
+        response.setCode(role.getCode());
+        response.setName(role.getName());
+        response.setDescription(role.getDescription());
+        response.setState(role.getState());
+        
+        if (role.getCreateTime() != null) {
+            response.setCreateTime(role.getCreateTime().format(DATE_FORMATTER));
+        }
+        if (role.getUpdateTime() != null) {
+            response.setUpdateTime(role.getUpdateTime().format(DATE_FORMATTER));
+        }
+        
+        return response;
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/judge/api/TagGraphqlApi.java b/backend/src/main/java/com/rongyichuang/tag/api/TagGraphqlApi.java
similarity index 85%
rename from backend/src/main/java/com/rongyichuang/judge/api/TagGraphqlApi.java
rename to backend/src/main/java/com/rongyichuang/tag/api/TagGraphqlApi.java
index 316f347..459ce01 100644
--- a/backend/src/main/java/com/rongyichuang/judge/api/TagGraphqlApi.java
+++ b/backend/src/main/java/com/rongyichuang/tag/api/TagGraphqlApi.java
@@ -1,8 +1,8 @@
-package com.rongyichuang.judge.api;
+package com.rongyichuang.tag.api;
 
-import com.rongyichuang.judge.dto.response.TagResponse;
-import com.rongyichuang.judge.entity.Tag;
-import com.rongyichuang.judge.repository.TagRepository;
+import com.rongyichuang.tag.dto.response.TagResponse;
+import com.rongyichuang.tag.entity.Tag;
+import com.rongyichuang.tag.repository.TagRepository;
 import org.springframework.graphql.data.method.annotation.Argument;
 import org.springframework.graphql.data.method.annotation.QueryMapping;
 import org.springframework.stereotype.Controller;
diff --git a/backend/src/main/java/com/rongyichuang/judge/dto/response/TagResponse.java b/backend/src/main/java/com/rongyichuang/tag/dto/response/TagResponse.java
similarity index 94%
rename from backend/src/main/java/com/rongyichuang/judge/dto/response/TagResponse.java
rename to backend/src/main/java/com/rongyichuang/tag/dto/response/TagResponse.java
index 2b9c37d..d0d5417 100644
--- a/backend/src/main/java/com/rongyichuang/judge/dto/response/TagResponse.java
+++ b/backend/src/main/java/com/rongyichuang/tag/dto/response/TagResponse.java
@@ -1,4 +1,4 @@
-package com.rongyichuang.judge.dto.response;
+package com.rongyichuang.tag.dto.response;
 
 public class TagResponse {
     private Long id;
diff --git a/backend/src/main/java/com/rongyichuang/judge/entity/Tag.java b/backend/src/main/java/com/rongyichuang/tag/entity/Tag.java
similarity index 95%
rename from backend/src/main/java/com/rongyichuang/judge/entity/Tag.java
rename to backend/src/main/java/com/rongyichuang/tag/entity/Tag.java
index d1e3939..aa867d1 100644
--- a/backend/src/main/java/com/rongyichuang/judge/entity/Tag.java
+++ b/backend/src/main/java/com/rongyichuang/tag/entity/Tag.java
@@ -1,4 +1,4 @@
-package com.rongyichuang.judge.entity;
+package com.rongyichuang.tag.entity;
 
 import com.rongyichuang.common.entity.BaseEntity;
 import jakarta.persistence.*;
diff --git a/backend/src/main/java/com/rongyichuang/judge/repository/TagRepository.java b/backend/src/main/java/com/rongyichuang/tag/repository/TagRepository.java
similarity index 78%
rename from backend/src/main/java/com/rongyichuang/judge/repository/TagRepository.java
rename to backend/src/main/java/com/rongyichuang/tag/repository/TagRepository.java
index 4b0ef8b..b74eb45 100644
--- a/backend/src/main/java/com/rongyichuang/judge/repository/TagRepository.java
+++ b/backend/src/main/java/com/rongyichuang/tag/repository/TagRepository.java
@@ -1,6 +1,6 @@
-package com.rongyichuang.judge.repository;
+package com.rongyichuang.tag.repository;
 
-import com.rongyichuang.judge.entity.Tag;
+import com.rongyichuang.tag.entity.Tag;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
 
diff --git a/backend/src/main/java/com/rongyichuang/judge/service/DataInitService.java b/backend/src/main/java/com/rongyichuang/tag/service/DataInitService.java
similarity index 92%
rename from backend/src/main/java/com/rongyichuang/judge/service/DataInitService.java
rename to backend/src/main/java/com/rongyichuang/tag/service/DataInitService.java
index 236f77c..5dfa352 100644
--- a/backend/src/main/java/com/rongyichuang/judge/service/DataInitService.java
+++ b/backend/src/main/java/com/rongyichuang/tag/service/DataInitService.java
@@ -1,7 +1,7 @@
-package com.rongyichuang.judge.service;
+package com.rongyichuang.tag.service;
 
-import com.rongyichuang.judge.entity.Tag;
-import com.rongyichuang.judge.repository.TagRepository;
+import com.rongyichuang.tag.entity.Tag;
+import com.rongyichuang.tag.repository.TagRepository;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.stereotype.Service;
 
diff --git a/backend/src/main/java/com/rongyichuang/tools/DatabaseSchemaExporter.java b/backend/src/main/java/com/rongyichuang/tools/DatabaseSchemaExporter.java
new file mode 100644
index 0000000..ac5ea95
--- /dev/null
+++ b/backend/src/main/java/com/rongyichuang/tools/DatabaseSchemaExporter.java
@@ -0,0 +1,114 @@
+package com.rongyichuang.tools;
+
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 鏁版嵁搴撹〃缁撴瀯瀵煎嚭宸ュ叿
+ */
+@Component
+public class DatabaseSchemaExporter implements CommandLineRunner {
+
+    private static final String URL = "jdbc:mysql://139.155.104.10:3306/ryc?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
+    private static final String USERNAME = "ryc";
+    private static final String PASSWORD = "KiYap3E8X8RLcM6T";
+    private static final String DATABASE_NAME = "ryc";
+
+    @Override
+    public void run(String... args) throws Exception {
+        if (args.length > 0 && "export-schema".equals(args[0])) {
+            exportDatabaseSchema();
+        }
+    }
+
+    public void exportDatabaseSchema() {
+        System.out.println("馃攧 寮�濮嬪鍑烘暟鎹簱琛ㄧ粨鏋�...");
+        
+        try (Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD)) {
+            StringBuilder sqlBuilder = new StringBuilder();
+            sqlBuilder.append("-- Database schema dump for ryc\n");
+            sqlBuilder.append("-- Generated at: ").append(new java.util.Date()).append("\n\n");
+
+            // 鑾峰彇鎵�鏈夎〃鍚�
+            List<String> tableNames = getAllTableNames(conn);
+            
+            for (String tableName : tableNames) {
+                System.out.println("馃搵 瀵煎嚭琛�: " + tableName);
+                String createTableSql = getCreateTableStatement(conn, tableName);
+                sqlBuilder.append(createTableSql).append("\n\n");
+            }
+
+            // 鍐欏叆鏂囦欢
+            String outputPath = "d:\\code\\new-ryc\\db_actual.sql";
+            try (FileWriter writer = new FileWriter(outputPath)) {
+                writer.write(sqlBuilder.toString());
+            }
+            
+            System.out.println("鉁� 鏁版嵁搴撹〃缁撴瀯瀵煎嚭瀹屾垚: " + outputPath);
+            
+            // 鐗瑰埆妫�鏌_employee琛ㄧ殑缁撴瀯
+            checkEmployeeTableStructure(conn);
+            
+        } catch (Exception e) {
+            System.err.println("鉂� 瀵煎嚭鏁版嵁搴撹〃缁撴瀯澶辫触: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    private List<String> getAllTableNames(Connection conn) throws SQLException {
+        List<String> tableNames = new ArrayList<>();
+        DatabaseMetaData metaData = conn.getMetaData();
+        
+        try (ResultSet tables = metaData.getTables(DATABASE_NAME, null, "%", new String[]{"TABLE"})) {
+            while (tables.next()) {
+                String tableName = tables.getString("TABLE_NAME");
+                if (tableName.startsWith("t_")) { // 鍙鍑轰笟鍔¤〃
+                    tableNames.add(tableName);
+                }
+            }
+        }
+        
+        return tableNames;
+    }
+
+    private String getCreateTableStatement(Connection conn, String tableName) throws SQLException {
+        try (Statement stmt = conn.createStatement();
+             ResultSet rs = stmt.executeQuery("SHOW CREATE TABLE " + tableName)) {
+            
+            if (rs.next()) {
+                String createSql = rs.getString(2);
+                return "-- Table: " + tableName + "\n" + createSql + ";";
+            }
+        }
+        return "";
+    }
+
+    private void checkEmployeeTableStructure(Connection conn) throws SQLException {
+        System.out.println("\n馃攳 妫�鏌_employee琛ㄧ粨鏋�:");
+        
+        DatabaseMetaData metaData = conn.getMetaData();
+        try (ResultSet columns = metaData.getColumns(DATABASE_NAME, null, "t_employee", null)) {
+            while (columns.next()) {
+                String columnName = columns.getString("COLUMN_NAME");
+                String dataType = columns.getString("TYPE_NAME");
+                int columnSize = columns.getInt("COLUMN_SIZE");
+                String isNullable = columns.getString("IS_NULLABLE");
+                String defaultValue = columns.getString("COLUMN_DEF");
+                
+                System.out.printf("  馃摑 %s: %s(%d) %s %s%n", 
+                    columnName, 
+                    dataType, 
+                    columnSize,
+                    "YES".equals(isNullable) ? "NULL" : "NOT NULL",
+                    defaultValue != null ? "DEFAULT " + defaultValue : ""
+                );
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/rongyichuang/tools/MockDataInserter.java b/backend/src/main/java/com/rongyichuang/tools/MockDataInserter.java
index 7371df3..8badbed 100644
--- a/backend/src/main/java/com/rongyichuang/tools/MockDataInserter.java
+++ b/backend/src/main/java/com/rongyichuang/tools/MockDataInserter.java
@@ -148,9 +148,9 @@
         throw new SQLException("鎻掑叆瀛﹀憳澶辫触");
     }
 
-    // 娉ㄦ剰锛氳〃鍚嶄负 t_avtivity_player锛堟寜 db.sql 鎷煎啓锛�
+    // 鎻掑叆娲诲姩鎶ュ悕鏁版嵁
     private long insertActivityPlayer(Connection conn, long activityId, long playerId) throws SQLException {
-        String sql = "INSERT INTO t_avtivity_player (activity_id, player_id) VALUES (?, ?)";
+        String sql = "INSERT INTO t_activity_player (activity_id, player_id) VALUES (?, ?)";
         try (PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
             ps.setLong(1, activityId);
             ps.setLong(2, playerId);
diff --git a/backend/src/main/resources/db/migration/V2__add_judge_fields.sql b/backend/src/main/resources/db/migration/V2__add_judge_fields.sql
new file mode 100644
index 0000000..5e375c1
--- /dev/null
+++ b/backend/src/main/resources/db/migration/V2__add_judge_fields.sql
@@ -0,0 +1,7 @@
+-- 涓簍_judge琛ㄦ坊鍔犵己澶辩殑瀛楁
+ALTER TABLE t_judge 
+ADD COLUMN title VARCHAR(128) COMMENT '鑱屼綅/澶磋',
+ADD COLUMN company VARCHAR(128) COMMENT '鍏徃/鏈烘瀯',
+ADD COLUMN introduction TEXT COMMENT '涓汉浠嬬粛',
+ADD COLUMN avatar_url VARCHAR(512) COMMENT '澶村儚URL',
+ADD COLUMN avatar_media_id BIGINT COMMENT '澶村儚濯掍綋ID';
\ No newline at end of file
diff --git a/backend/src/main/resources/graphql/employee.graphqls b/backend/src/main/resources/graphql/employee.graphqls
new file mode 100644
index 0000000..78727ab
--- /dev/null
+++ b/backend/src/main/resources/graphql/employee.graphqls
@@ -0,0 +1,47 @@
+# 鍛樺伐鐩稿叧鐨凣raphQL Schema瀹氫箟
+
+# 鍛樺伐鍝嶅簲绫诲瀷
+type EmployeeResponse {
+    id: Long!
+    name: String!
+    phone: String!
+    roleId: String!
+    description: String
+    state: Int!
+    createTime: String
+    updateTime: String
+}
+
+# 鍛樺伐杈撳叆绫诲瀷
+input EmployeeInput {
+    id: Long
+    name: String!
+    phone: String!
+    password: String
+    roleId: String!
+    description: String
+}
+
+# 鍒嗛〉缁撴灉绫诲瀷 - 绠�鍖栫増鏈紝鐩存帴浣跨敤Spring Data Page瀵硅薄
+# Spring Data鐨凱age瀵硅薄浼氳嚜鍔ㄦ槧灏勫埌GraphQL
+
+# 鎵╁睍鏌ヨ绫诲瀷
+extend type Query {
+    # 鑾峰彇鎵�鏈夊憳宸ュ垪琛�
+    employees: [EmployeeResponse!]!
+    
+    # 鏍规嵁鍚嶇О鎼滅储鍛樺伐
+    employeesByName(name: String): [EmployeeResponse!]!
+    
+    # 鏍规嵁ID鑾峰彇鍛樺伐璇︽儏
+    employee(id: Long!): EmployeeResponse
+}
+
+# 鎵╁睍鍙樻洿绫诲瀷
+extend type Mutation {
+    # 淇濆瓨鍛樺伐锛堟柊澧炴垨鏇存柊锛�
+    saveEmployee(input: EmployeeInput!): EmployeeResponse!
+    
+    # 鍒犻櫎鍛樺伐
+    deleteEmployee(id: Long!): Boolean!
+}
\ No newline at end of file
diff --git a/backend/src/main/resources/graphql/player.graphqls b/backend/src/main/resources/graphql/player.graphqls
index 71bea78..f11a00a 100644
--- a/backend/src/main/resources/graphql/player.graphqls
+++ b/backend/src/main/resources/graphql/player.graphqls
@@ -1,6 +1,12 @@
 extend type Query {
-  activityPlayerApplications(name: String, page: Int, size: Int): [ActivityPlayerApplicationResponse!]!
+  activityPlayerApplications(name: String, activityId: ID, page: Int, size: Int): [ActivityPlayerApplicationResponse!]!
   activityPlayerDetail(id: ID!): ActivityPlayerDetailResponse
+  
+  # 璇勫垎鐩稿叧鏌ヨ
+  judgeRatingsForPlayer(activityPlayerId: ID!): [JudgeRatingStatusResponse!]!
+  currentJudgeRating(activityPlayerId: ID!): CurrentJudgeRatingResponse
+  averageScoreForPlayer(activityPlayerId: ID!): Float
+  currentJudgeInfo: CurrentJudgeInfoResponse
 }
 
 extend type Mutation {
@@ -64,4 +70,39 @@
 input ActivityPlayerRatingItemInput {
   itemId: ID!
   score: Int!
+}
+
+# 璇勫璇勫垎鐘舵�佸搷搴旂被鍨�
+type JudgeRatingStatusResponse {
+  judgeId: ID!
+  judgeName: String!
+  hasRated: Boolean!
+  ratingTime: String
+  totalScore: Float
+}
+
+# 褰撳墠璇勫璇勫垎鍝嶅簲绫诲瀷
+type CurrentJudgeRatingResponse {
+  activityPlayerId: ID!
+  judgeId: ID!
+  ratings: [RatingItemScoreResponse!]!
+  comment: String
+  totalScore: Float
+  ratingTime: String
+}
+
+# 璇勫垎椤圭洰鍒嗘暟鍝嶅簲绫诲瀷
+type RatingItemScoreResponse {
+  itemId: ID!
+  itemName: String!
+  score: Int!
+  maxScore: Int!
+}
+
+# 褰撳墠璇勫淇℃伅鍝嶅簲绫诲瀷
+type CurrentJudgeInfoResponse {
+  judgeId: ID!
+  judgeName: String!
+  title: String
+  company: String
 }
\ No newline at end of file
diff --git a/backend/src/main/resources/graphql/role.graphqls b/backend/src/main/resources/graphql/role.graphqls
new file mode 100644
index 0000000..bfe4d31
--- /dev/null
+++ b/backend/src/main/resources/graphql/role.graphqls
@@ -0,0 +1,51 @@
+# 瑙掕壊鐩稿叧鐨凣raphQL Schema瀹氫箟
+
+# 瑙掕壊鍝嶅簲绫诲瀷
+type RoleResponse {
+    id: Long!
+    code: String!
+    name: String!
+    description: String
+    state: Int!
+    createTime: String
+    updateTime: String
+}
+
+# 瑙掕壊杈撳叆绫诲瀷
+input RoleInput {
+    id: Long
+    code: String!
+    name: String!
+    description: String
+    state: Int
+}
+
+# 鎵╁睍鏌ヨ绫诲瀷
+extend type Query {
+    # 鑾峰彇鎵�鏈夎鑹插垪琛�
+    roles: [RoleResponse!]!
+    
+    # 鑾峰彇鎵�鏈夊惎鐢ㄧ姸鎬佺殑瑙掕壊
+    activeRoles: [RoleResponse!]!
+    
+    # 鏍规嵁ID鑾峰彇瑙掕壊璇︽儏
+    role(id: Long!): RoleResponse
+    
+    # 鏍规嵁瑙掕壊浠g爜鑾峰彇瑙掕壊
+    roleByCode(code: String!): RoleResponse
+    
+    # 鏍规嵁鐘舵�佽幏鍙栬鑹�
+    rolesByState(state: Int!): [RoleResponse!]!
+    
+    # 鏍规嵁鍚嶇О妯$硦鏌ヨ瑙掕壊
+    rolesByName(name: String!): [RoleResponse!]!
+}
+
+# 鎵╁睍鍙樻洿绫诲瀷
+extend type Mutation {
+    # 淇濆瓨瑙掕壊锛堟柊澧炴垨鏇存柊锛�
+    saveRole(input: RoleInput!): RoleResponse!
+    
+    # 鍒犻櫎瑙掕壊
+    deleteRole(id: Long!): Boolean!
+}
\ No newline at end of file
diff --git a/backend/src/main/resources/graphql/schema.graphqls b/backend/src/main/resources/graphql/schema.graphqls
index 97df1d7..df3bbd3 100644
--- a/backend/src/main/resources/graphql/schema.graphqls
+++ b/backend/src/main/resources/graphql/schema.graphqls
@@ -1,5 +1,8 @@
 # GraphQL Schema 瀹氫箟
 
+# 鑷畾涔夋爣閲忕被鍨�
+scalar Long
+
 # 鏌ヨ鏍圭被鍨�
 type Query {
     # 娴嬭瘯鏌ヨ
diff --git a/backend/src/main/resources/logback-spring.xml b/backend/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000..019ea93
--- /dev/null
+++ b/backend/src/main/resources/logback-spring.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 鎺у埗鍙拌緭鍑� -->
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <!-- 鏂囦欢杈撳嚭 -->
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>logs/ryc-backend.log</file>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>logs/ryc-backend.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>1GB</totalSizeCap>
+        </rollingPolicy>
+    </appender>
+
+    <!-- 搴旂敤绋嬪簭鏃ュ織绾у埆 -->
+    <logger name="com.rongyichuang" level="DEBUG" additivity="false">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </logger>
+
+    <!-- SQL鏃ュ織 -->
+    <logger name="org.hibernate.SQL" level="DEBUG" additivity="false">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </logger>
+
+    <!-- SQL鍙傛暟缁戝畾鏃ュ織 -->
+    <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" additivity="false">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </logger>
+
+    <!-- Spring Security鏃ュ織 -->
+    <logger name="org.springframework.security" level="DEBUG" additivity="false">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </logger>
+
+    <!-- 鏍规棩蹇楃骇鍒� -->
+    <root level="INFO">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </root>
+</configuration>
\ No newline at end of file
diff --git a/backend/src/test/java/com/rongyichuang/TableStructureTest.java b/backend/src/test/java/com/rongyichuang/TableStructureTest.java
new file mode 100644
index 0000000..1fe1e9d
--- /dev/null
+++ b/backend/src/test/java/com/rongyichuang/TableStructureTest.java
@@ -0,0 +1,151 @@
+package com.rongyichuang;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import java.util.List;
+import java.util.Map;
+
+@SpringBootTest
+public class TableStructureTest {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Test
+    public void testActivityPlayerRatingItemTableStructure() {
+        try {
+            String sql = "DESCRIBE t_activity_player_rating_item";
+            List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);
+            System.out.println("=== t_activity_player_rating_item 琛ㄧ粨鏋� ===");
+            for (Map<String, Object> row : result) {
+                System.out.println(row);
+            }
+        } catch (Exception e) {
+            System.out.println("鏌ヨ琛ㄧ粨鏋勫け璐�: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testActivityPlayerTableStructure() {
+        try {
+            String sql = "DESCRIBE t_activity_player";
+            List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);
+            System.out.println("=== t_activity_player 琛ㄧ粨鏋� ===");
+            for (Map<String, Object> row : result) {
+                System.out.println(row);
+            }
+        } catch (Exception e) {
+            System.out.println("鏌ヨ琛ㄧ粨鏋勫け璐�: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testVerifyRatingData() {
+        // 鏌ヨ鍒氭墠鎻掑叆鐨勮瘎鍒嗘暟鎹�
+        String sql = "SELECT * FROM t_activity_player_rating_item WHERE player_id = 12 ORDER BY create_time DESC LIMIT 5";
+        List<Map<String, Object>> results = jdbcTemplate.queryForList(sql);
+        
+        System.out.println("鏈�鏂扮殑璇勫垎鏁版嵁:");
+        for (Map<String, Object> row : results) {
+            System.out.println(row);
+        }
+        
+        // 鏌ヨ鎬诲垎鏇存柊鎯呭喌
+        String totalScoreSql = "SELECT id, total_score, update_time FROM t_activity_player WHERE id = 12";
+        List<Map<String, Object>> totalResults = jdbcTemplate.queryForList(totalScoreSql);
+        
+        System.out.println("鎬诲垎鏇存柊鎯呭喌:");
+        for (Map<String, Object> row : totalResults) {
+            System.out.println(row);
+        }
+    }
+
+    @Test
+    public void testInsertSample() {
+        try {
+            String sql = "INSERT INTO t_activity_player_rating_item " +
+                    "(activity_id, player_id, rating_scheme_id, rating_item_id, score, feedback, create_time, update_time, version) " +
+                    "VALUES (1, 1, 1, 1, 85.5, 'test', NOW(), NOW(), 0)";
+            int result = jdbcTemplate.update(sql);
+            System.out.println("鎻掑叆娴嬭瘯璁板綍鎴愬姛锛屽奖鍝嶈鏁�: " + result);
+        } catch (Exception e) {
+            System.out.println("鎻掑叆娴嬭瘯璁板綍澶辫触: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testJudgeTableStructure() {
+        try {
+            String sql = "DESCRIBE t_judge";
+            List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);
+            System.out.println("=== t_judge 琛ㄧ粨鏋� ===");
+            for (Map<String, Object> row : result) {
+                System.out.println(row);
+            }
+        } catch (Exception e) {
+            System.out.println("鏌ヨ琛ㄧ粨鏋勫け璐�: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testExecuteMigration() {
+        try {
+            // 涓簍_judge琛ㄦ坊鍔犵己澶辩殑瀛楁
+            String[] sqls = {
+                "ALTER TABLE t_judge ADD COLUMN title VARCHAR(128) COMMENT '鑱屼綅/澶磋'",
+                "ALTER TABLE t_judge ADD COLUMN company VARCHAR(128) COMMENT '鍏徃/鏈烘瀯'", 
+                "ALTER TABLE t_judge ADD COLUMN introduction TEXT COMMENT '涓汉浠嬬粛'"
+            };
+            
+            for (String sql : sqls) {
+                try {
+                    jdbcTemplate.execute(sql);
+                    System.out.println("鎵ц鎴愬姛: " + sql);
+                } catch (Exception e) {
+                    if (e.getMessage().contains("Duplicate column name")) {
+                        System.out.println("瀛楁宸插瓨鍦紝璺宠繃: " + sql);
+                    } else {
+                        System.out.println("鎵ц澶辫触: " + sql + " - " + e.getMessage());
+                    }
+                }
+            }
+        } catch (Exception e) {
+            System.out.println("鎵ц杩佺Щ澶辫触: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testRollbackAvatarFields() {
+        try {
+            // 绉婚櫎涓嶅繀瑕佺殑avatar鐩稿叧瀛楁
+            String[] sqls = {
+                "ALTER TABLE t_judge DROP COLUMN avatar_url",
+                "ALTER TABLE t_judge DROP COLUMN avatar_media_id"
+            };
+            
+            for (String sql : sqls) {
+                try {
+                    jdbcTemplate.execute(sql);
+                    System.out.println("鍥炴粴鎴愬姛: " + sql);
+                } catch (Exception e) {
+                    if (e.getMessage().contains("check that column/key exists")) {
+                        System.out.println("瀛楁涓嶅瓨鍦紝璺宠繃: " + sql);
+                    } else {
+                        System.out.println("鍥炴粴澶辫触: " + sql + " - " + e.getMessage());
+                    }
+                }
+            }
+        } catch (Exception e) {
+            System.out.println("鎵ц鍥炴粴澶辫触: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file
diff --git a/backend/src/test/java/com/rongyichuang/judge/JudgeAvatarTest.java b/backend/src/test/java/com/rongyichuang/judge/JudgeAvatarTest.java
new file mode 100644
index 0000000..91eabd8
--- /dev/null
+++ b/backend/src/test/java/com/rongyichuang/judge/JudgeAvatarTest.java
@@ -0,0 +1,52 @@
+package com.rongyichuang.judge;
+
+import com.rongyichuang.judge.dto.response.JudgeResponse;
+import com.rongyichuang.judge.service.JudgeService;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@SpringBootTest
+@ActiveProfiles("test")
+@Transactional
+public class JudgeAvatarTest {
+
+    @Autowired
+    private JudgeService judgeService;
+
+    @Test
+    public void testJudgeAvatarUrls() {
+        System.out.println("=== 娴嬭瘯璇勫澶村儚URL鏋勫缓 ===");
+        
+        List<JudgeResponse> judges = judgeService.findAll();
+        System.out.println("鎵惧埌 " + judges.size() + " 涓瘎濮�");
+        
+        for (JudgeResponse judge : judges) {
+            System.out.println("璇勫ID: " + judge.getId() + 
+                             ", 濮撳悕: " + judge.getName() + 
+                             ", 澶村儚URL: " + judge.getAvatarUrl());
+        }
+        
+        // 娴嬭瘯鍓�5涓瘎濮旂殑澶村儚URL
+        judges.stream()
+              .limit(5)
+              .forEach(judge -> {
+                  String avatarUrl = judge.getAvatarUrl();
+                  if (avatarUrl != null) {
+                      System.out.println("璇勫 " + judge.getName() + " 鐨勫ご鍍廢RL: " + avatarUrl);
+                      // 楠岃瘉URL鏄惁涓哄畬鏁碪RL
+                      if (avatarUrl.startsWith("https://")) {
+                          System.out.println("鉁� 澶村儚URL鏍煎紡姝g‘");
+                      } else {
+                          System.out.println("鉁� 澶村儚URL鏍煎紡鍙兘鏈夐棶棰�: " + avatarUrl);
+                      }
+                  } else {
+                      System.out.println("璇勫 " + judge.getName() + " 娌℃湁澶村儚");
+                  }
+              });
+    }
+}
\ No newline at end of file
diff --git a/backend/src/test/java/com/rongyichuang/judge/JudgeTableSchemaTest.java b/backend/src/test/java/com/rongyichuang/judge/JudgeTableSchemaTest.java
new file mode 100644
index 0000000..16c5afa
--- /dev/null
+++ b/backend/src/test/java/com/rongyichuang/judge/JudgeTableSchemaTest.java
@@ -0,0 +1,55 @@
+package com.rongyichuang.judge;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import java.util.List;
+import java.util.Map;
+
+@SpringBootTest
+public class JudgeTableSchemaTest {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Test
+    public void testJudgeAvatarData() {
+        try {
+            System.out.println("=== 鏌ョ湅璇勫鏁版嵁 ===");
+            List<Map<String, Object>> judges = jdbcTemplate.queryForList("SELECT id, name, phone FROM t_judge WHERE state = 1 LIMIT 5");
+            
+            for (Map<String, Object> judge : judges) {
+                System.out.println(String.format("璇勫ID: %s, 濮撳悕: %s, 鐢佃瘽: %s", 
+                    judge.get("id"), judge.get("name"), judge.get("phone")));
+            }
+            
+            System.out.println("\n=== 鏌ョ湅璇勫澶村儚鏁版嵁 (target_type=1) ===");
+            List<Map<String, Object>> avatars = jdbcTemplate.queryForList(
+                "SELECT target_id, path, name FROM t_media WHERE target_type = 1 AND state = 1");
+            
+            if (avatars.isEmpty()) {
+                System.out.println("娌℃湁鎵惧埌璇勫澶村儚鏁版嵁");
+            } else {
+                for (Map<String, Object> avatar : avatars) {
+                    System.out.println(String.format("璇勫ID: %s, 澶村儚璺緞: %s, 鏂囦欢鍚�: %s", 
+                        avatar.get("target_id"), avatar.get("path"), avatar.get("name")));
+                }
+            }
+            
+            System.out.println("\n=== 鏌ョ湅鎵�鏈塵edia鏁版嵁鐨則arget_type鍒嗗竷 ===");
+            List<Map<String, Object>> typeDistribution = jdbcTemplate.queryForList(
+                "SELECT target_type, COUNT(*) as count FROM t_media WHERE state = 1 GROUP BY target_type");
+            
+            for (Map<String, Object> row : typeDistribution) {
+                System.out.println(String.format("target_type: %s, 鏁伴噺: %s", 
+                    row.get("target_type"), row.get("count")));
+            }
+            
+        } catch (Exception e) {
+            System.out.println("鏌ヨ澶辫触: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file
diff --git a/backend/src/test/java/com/rongyichuang/region/RegionTableTest.java b/backend/src/test/java/com/rongyichuang/region/RegionTableTest.java
index 62b285e..eb7cad7 100644
--- a/backend/src/test/java/com/rongyichuang/region/RegionTableTest.java
+++ b/backend/src/test/java/com/rongyichuang/region/RegionTableTest.java
@@ -45,12 +45,12 @@
             ResultSet rs = stmt.executeQuery("SELECT * FROM t_region ORDER BY id");
             
             while (rs.next()) {
-                System.out.printf("ID: %d, Name: %s, PID: %s, Code: %s, Status: %d%n",
+                System.out.printf("ID: %d, Name: %s, PID: %s, Code: %s, State: %d%n",
                     rs.getLong("id"),
                     rs.getString("name"),
                     rs.getObject("pid"),
                     rs.getString("code"),
-                    rs.getInt("status")
+                    rs.getInt("state")
                 );
             }
             
diff --git a/backend/src/test/java/com/rongyichuang/tools/DataInsertTest.java b/backend/src/test/java/com/rongyichuang/tools/DataInsertTest.java
index 8788db4..68f10d0 100644
--- a/backend/src/test/java/com/rongyichuang/tools/DataInsertTest.java
+++ b/backend/src/test/java/com/rongyichuang/tools/DataInsertTest.java
@@ -122,9 +122,9 @@
         throw new SQLException("鎻掑叆瀛﹀憳澶辫触");
     }
 
-    // 娉ㄦ剰锛氭寜 db.sql 鎷煎啓涓� t_avtivity_player
+    // 鎻掑叆娲诲姩鎶ュ悕鏁版嵁
     private long insertActivityPlayer(Connection conn, long activityId, long playerId) throws SQLException {
-        String sql = "INSERT INTO t_avtivity_player (activity_id, player_id) VALUES (?, ?)";
+        String sql = "INSERT INTO t_activity_player (activity_id, player_id) VALUES (?, ?)";
         try (PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
             ps.setLong(1, activityId);
             ps.setLong(2, playerId);
diff --git a/backend/src/test/java/com/rongyichuang/tools/RatingTemplateFixer.java b/backend/src/test/java/com/rongyichuang/tools/RatingTemplateFixer.java
new file mode 100644
index 0000000..ef7b2bd
--- /dev/null
+++ b/backend/src/test/java/com/rongyichuang/tools/RatingTemplateFixer.java
@@ -0,0 +1,94 @@
+package com.rongyichuang.tools;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import java.util.List;
+import java.util.Map;
+
+@SpringBootTest
+public class RatingTemplateFixer {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Test
+    public void fixRatingTemplateData() {
+        System.out.println("=== 淇璇勫垎妯℃澘鏁版嵁 ===");
+        
+        // 1. 鏇存柊娲诲姩琛ㄧ殑rating_scheme_id涓�1
+        String updateActivitySql = "UPDATE t_activity SET rating_scheme_id = 1 WHERE id = 1";
+        int activityResult = jdbcTemplate.update(updateActivitySql);
+        System.out.println("鏇存柊娲诲姩璇勫垎妯℃澘閰嶇疆缁撴灉: " + activityResult);
+        
+        // 2. 鏇存柊鎵�鏈夎瘎鍒嗛」鐩殑scheme_id涓�1
+        String[] updateItemSqls = {
+            "UPDATE t_rating_item SET scheme_id = 1, name = '浠g爜璐ㄩ噺', max_score = 30, order_no = 1 WHERE id = 1",
+            "UPDATE t_rating_item SET scheme_id = 1, name = '鍔熻兘瀹屾暣鎬�', max_score = 25, order_no = 2 WHERE id = 2", 
+            "UPDATE t_rating_item SET scheme_id = 1, name = '鐢ㄦ埛浣撻獙', max_score = 20, order_no = 3 WHERE id = 3",
+            "UPDATE t_rating_item SET scheme_id = 1, name = '鍒涙柊鎬�', max_score = 15, order_no = 4 WHERE id = 4",
+            "UPDATE t_rating_item SET scheme_id = 1, name = '椤圭洰灞曠ず', max_score = 10, order_no = 5 WHERE id = 5"
+        };
+        
+        for (int i = 0; i < updateItemSqls.length; i++) {
+            try {
+                int itemResult = jdbcTemplate.update(updateItemSqls[i]);
+                System.out.println("鏇存柊璇勫垎椤圭洰 " + (i + 1) + " 缁撴灉: " + itemResult);
+            } catch (Exception e) {
+                System.err.println("鏇存柊璇勫垎椤圭洰 " + (i + 1) + " 澶辫触: " + e.getMessage());
+            }
+        }
+        
+        // 3. 鍒犻櫎澶氫綑鐨勮瘎鍒嗛」鐩紙ID 6, 7, 8锛�
+        String deleteExtraItemsSql = "DELETE FROM t_rating_item WHERE id IN (6, 7, 8)";
+        int deleteResult = jdbcTemplate.update(deleteExtraItemsSql);
+        System.out.println("鍒犻櫎澶氫綑璇勫垎椤圭洰缁撴灉: " + deleteResult);
+        
+        // 4. 楠岃瘉淇缁撴灉
+        System.out.println("\n=== 楠岃瘉淇缁撴灉 ===");
+        
+        // 鏌ヨ璇勫垎妯℃澘
+        String schemeSql = "SELECT * FROM t_rating_scheme WHERE id = 1";
+        List<Map<String, Object>> schemes = jdbcTemplate.queryForList(schemeSql);
+        System.out.println("璇勫垎妯℃澘:");
+        for (Map<String, Object> scheme : schemes) {
+            System.out.println(scheme);
+        }
+        
+        // 鏌ヨ璇勫垎椤圭洰
+        String itemSql = "SELECT * FROM t_rating_item WHERE scheme_id = 1 ORDER BY order_no";
+        List<Map<String, Object>> items = jdbcTemplate.queryForList(itemSql);
+        System.out.println("\n璇勫垎椤圭洰:");
+        for (Map<String, Object> item : items) {
+            System.out.println(item);
+        }
+        
+        // 鏌ヨ娲诲姩閰嶇疆
+        String activitySql = "SELECT id, name, rating_scheme_id FROM t_activity WHERE id = 1";
+        List<Map<String, Object>> activities = jdbcTemplate.queryForList(activitySql);
+        System.out.println("\n娲诲姩閰嶇疆:");
+        for (Map<String, Object> activity : activities) {
+            System.out.println(activity);
+        }
+        
+        // 璁$畻鎬诲垎
+        String totalScoreSql = """
+            SELECT 
+                rs.name as scheme_name,
+                SUM(ri.max_score) as total_max_score
+            FROM t_rating_scheme rs
+            LEFT JOIN t_rating_item ri ON rs.id = ri.scheme_id
+            WHERE rs.id = 1
+            GROUP BY rs.id, rs.name
+            """;
+        List<Map<String, Object>> totalResults = jdbcTemplate.queryForList(totalScoreSql);
+        System.out.println("\n鎬诲垎楠岃瘉:");
+        for (Map<String, Object> row : totalResults) {
+            System.out.println(row);
+        }
+        
+        System.out.println("\n鉁� 璇勫垎妯℃澘鏁版嵁淇瀹屾垚锛�");
+    }
+}
\ No newline at end of file
diff --git a/backend/src/test/java/com/rongyichuang/tools/RatingTemplateInserter.java b/backend/src/test/java/com/rongyichuang/tools/RatingTemplateInserter.java
new file mode 100644
index 0000000..4a0c3bb
--- /dev/null
+++ b/backend/src/test/java/com/rongyichuang/tools/RatingTemplateInserter.java
@@ -0,0 +1,99 @@
+package com.rongyichuang.tools;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.context.ActiveProfiles;
+
+import java.util.List;
+import java.util.Map;
+
+@SpringBootTest
+@ActiveProfiles("test")
+public class RatingTemplateInserter {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Test
+    public void insertRatingTemplate() {
+        System.out.println("寮�濮嬫彃鍏ヨ瘎鍒嗘ā鏉挎暟鎹�...");
+
+        try {
+            // 1. 鎻掑叆璇勫垎妯℃澘
+            String insertSchemeSql = """
+                INSERT INTO t_rating_scheme (id, name, description, state, create_time, create_user_id, update_time, update_user_id, version) 
+                VALUES (1, '缂栫▼澶ц禌璇勫垎鏍囧噯', '鐢ㄤ簬缂栫▼姣旇禌鐨勭患鍚堣瘎鍒嗘爣鍑嗭紝鍖呭惈浠g爜璐ㄩ噺銆佸姛鑳藉畬鏁存�с�佺敤鎴蜂綋楠屻�佸垱鏂版�у拰椤圭洰灞曠ず绛夌淮搴�', 1, NOW(), 1, NOW(), 1, 0)
+                ON DUPLICATE KEY UPDATE 
+                name = VALUES(name), 
+                description = VALUES(description), 
+                update_time = NOW()
+                """;
+            
+            int schemeResult = jdbcTemplate.update(insertSchemeSql);
+            System.out.println("鎻掑叆璇勫垎妯℃澘缁撴灉: " + schemeResult);
+
+            // 2. 鎻掑叆璇勫垎椤圭洰
+            String[] insertItemSqls = {
+                "INSERT INTO t_rating_item (id, scheme_id, name, max_score, order_no, state, create_time, create_user_id, update_time, update_user_id, version) VALUES (1, 1, '浠g爜璐ㄩ噺', 30, 1, 1, NOW(), 1, NOW(), 1, 0) ON DUPLICATE KEY UPDATE name = VALUES(name), max_score = VALUES(max_score), order_no = VALUES(order_no), state = VALUES(state), update_time = NOW()",
+                "INSERT INTO t_rating_item (id, scheme_id, name, max_score, order_no, state, create_time, create_user_id, update_time, update_user_id, version) VALUES (2, 1, '鍔熻兘瀹屾暣鎬�', 25, 2, 1, NOW(), 1, NOW(), 1, 0) ON DUPLICATE KEY UPDATE name = VALUES(name), max_score = VALUES(max_score), order_no = VALUES(order_no), state = VALUES(state), update_time = NOW()",
+                "INSERT INTO t_rating_item (id, scheme_id, name, max_score, order_no, state, create_time, create_user_id, update_time, update_user_id, version) VALUES (3, 1, '鐢ㄦ埛浣撻獙', 20, 3, 1, NOW(), 1, NOW(), 1, 0) ON DUPLICATE KEY UPDATE name = VALUES(name), max_score = VALUES(max_score), order_no = VALUES(order_no), state = VALUES(state), update_time = NOW()",
+                "INSERT INTO t_rating_item (id, scheme_id, name, max_score, order_no, state, create_time, create_user_id, update_time, update_user_id, version) VALUES (4, 1, '鍒涙柊鎬�', 15, 4, 1, NOW(), 1, NOW(), 1, 0) ON DUPLICATE KEY UPDATE name = VALUES(name), max_score = VALUES(max_score), order_no = VALUES(order_no), state = VALUES(state), update_time = NOW()",
+                "INSERT INTO t_rating_item (id, scheme_id, name, max_score, order_no, state, create_time, create_user_id, update_time, update_user_id, version) VALUES (5, 1, '椤圭洰灞曠ず', 10, 5, 1, NOW(), 1, NOW(), 1, 0) ON DUPLICATE KEY UPDATE name = VALUES(name), max_score = VALUES(max_score), order_no = VALUES(order_no), state = VALUES(state), update_time = NOW()"
+            };
+
+            for (int i = 0; i < insertItemSqls.length; i++) {
+                try {
+                    System.out.println("鎵цSQL: " + insertItemSqls[i]);
+                    int itemResult = jdbcTemplate.update(insertItemSqls[i]);
+                    System.out.println("鎻掑叆璇勫垎椤圭洰 " + (i + 1) + " 缁撴灉: " + itemResult);
+                } catch (Exception e) {
+                    System.err.println("鎻掑叆璇勫垎椤圭洰 " + (i + 1) + " 澶辫触: " + e.getMessage());
+                    e.printStackTrace();
+                }
+            }
+
+            // 3. 楠岃瘉鎻掑叆缁撴灉
+            System.out.println("\n=== 楠岃瘉鎻掑叆缁撴灉 ===");
+            
+            // 鏌ヨ璇勫垎妯℃澘
+            String querySchemeSql = "SELECT * FROM t_rating_scheme WHERE id = 1";
+            List<Map<String, Object>> schemeResults = jdbcTemplate.queryForList(querySchemeSql);
+            System.out.println("璇勫垎妯℃澘:");
+            for (Map<String, Object> row : schemeResults) {
+                System.out.println(row);
+            }
+
+            // 鏌ヨ璇勫垎椤圭洰
+            String queryItemSql = "SELECT * FROM t_rating_item WHERE scheme_id = 1 ORDER BY order_no";
+            List<Map<String, Object>> itemResults = jdbcTemplate.queryForList(queryItemSql);
+            System.out.println("\n璇勫垎椤圭洰:");
+            for (Map<String, Object> row : itemResults) {
+                System.out.println(row);
+            }
+
+            // 璁$畻鎬诲垎
+            String totalScoreSql = """
+                SELECT 
+                    rs.name as scheme_name,
+                    SUM(ri.max_score) as total_max_score
+                FROM t_rating_scheme rs
+                LEFT JOIN t_rating_item ri ON rs.id = ri.scheme_id
+                WHERE rs.id = 1
+                GROUP BY rs.id, rs.name
+                """;
+            List<Map<String, Object>> totalResults = jdbcTemplate.queryForList(totalScoreSql);
+            System.out.println("\n鎬诲垎楠岃瘉:");
+            for (Map<String, Object> row : totalResults) {
+                System.out.println(row);
+            }
+
+            System.out.println("\n鉁� 璇勫垎妯℃澘鏁版嵁鎻掑叆瀹屾垚锛�");
+
+        } catch (Exception e) {
+            System.err.println("鉂� 鎻掑叆璇勫垎妯℃澘鏁版嵁澶辫触: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file
diff --git a/backend/src/test/java/com/rongyichuang/tools/RatingTemplateVerifier.java b/backend/src/test/java/com/rongyichuang/tools/RatingTemplateVerifier.java
new file mode 100644
index 0000000..66b64cc
--- /dev/null
+++ b/backend/src/test/java/com/rongyichuang/tools/RatingTemplateVerifier.java
@@ -0,0 +1,59 @@
+package com.rongyichuang.tools;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import java.util.List;
+import java.util.Map;
+
+@SpringBootTest
+public class RatingTemplateVerifier {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Test
+    public void verifyRatingTemplateData() {
+        System.out.println("=== 楠岃瘉璇勫垎妯℃澘鏁版嵁 ===");
+        
+        // 鏌ヨ璇勫垎妯℃澘
+        String schemeSql = "SELECT * FROM t_rating_scheme WHERE id = 1";
+        List<Map<String, Object>> schemes = jdbcTemplate.queryForList(schemeSql);
+        
+        System.out.println("璇勫垎妯℃澘鏁版嵁:");
+        for (Map<String, Object> scheme : schemes) {
+            System.out.println(scheme);
+        }
+        
+        // 鏌ヨ鎵�鏈夎瘎鍒嗛」鐩�
+        String allItemSql = "SELECT * FROM t_rating_item ORDER BY id";
+        List<Map<String, Object>> allItems = jdbcTemplate.queryForList(allItemSql);
+        
+        System.out.println("\n鎵�鏈夎瘎鍒嗛」鐩暟鎹�:");
+        for (Map<String, Object> item : allItems) {
+            System.out.println(item);
+        }
+        
+        // 鏌ヨ鐗瑰畾scheme_id鐨勮瘎鍒嗛」鐩�
+        String itemSql = "SELECT * FROM t_rating_item WHERE scheme_id = 1 ORDER BY order_no";
+        List<Map<String, Object>> items = jdbcTemplate.queryForList(itemSql);
+        
+        System.out.println("\nscheme_id=1鐨勮瘎鍒嗛」鐩暟鎹�:");
+        for (Map<String, Object> item : items) {
+            System.out.println(item);
+        }
+        
+        // 鏌ヨ娲诲姩鐨勮瘎鍒嗘ā鏉块厤缃�
+        String activitySql = "SELECT id, name, rating_scheme_id FROM t_activity WHERE id = 1";
+        List<Map<String, Object>> activities = jdbcTemplate.queryForList(activitySql);
+        
+        System.out.println("\n娲诲姩璇勫垎妯℃澘閰嶇疆:");
+        for (Map<String, Object> activity : activities) {
+            System.out.println(activity);
+        }
+        
+        System.out.println("\n鉁� 璇勫垎妯℃澘鏁版嵁楠岃瘉瀹屾垚锛�");
+    }
+}
\ No newline at end of file
diff --git a/backend/src/test/java/com/rongyichuang/tools/StageIdFixTest.java b/backend/src/test/java/com/rongyichuang/tools/StageIdFixTest.java
index fbe6a8a..53eb3fa 100644
--- a/backend/src/test/java/com/rongyichuang/tools/StageIdFixTest.java
+++ b/backend/src/test/java/com/rongyichuang/tools/StageIdFixTest.java
@@ -20,7 +20,7 @@
 
             // 瑙勫垯锛氭寜姣忎釜姣旇禌閫夋嫨鍏剁涓�涓樁娈碉紙鏈�灏廔D锛夛紱鑻ユ棤闃舵锛屽垯鍥炲~涓烘瘮璧涜嚜韬� activity_id
             String sql = """
-UPDATE t_avtivity_player ap
+UPDATE t_activity_player ap
 LEFT JOIN (
   SELECT child.pid AS activity_id, MIN(child.id) AS stage_id
   FROM t_activity child
diff --git a/db.sql b/db.sql
index c3ce285..bb5e6e1 100644
--- a/db.sql
+++ b/db.sql
@@ -1,326 +1,398 @@
 -- Database schema dump for ryc
+-- Generated at: Wed Sep 24 16:07:24 GMT+08:00 2025
 
 -- Table: t_activity
-CREATE TABLE t_activity (
-  `id` bigint NOT NULL auto_increment,
+CREATE TABLE `t_activity` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
   `pid` bigint NOT NULL DEFAULT '0',
-  `path` varchar(255) NOT NULL,
-  `name` varchar(128) NOT NULL,
-  `description` text,
+  `path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
   `signup_deadline` datetime NOT NULL,
-  `match_time` datetime,
-  `address` varchar(255),
+  `match_time` datetime DEFAULT NULL,
+  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
   `rating_scheme_id` bigint NOT NULL,
-  `player_max` int COMMENT '浜烘暟涓婇檺',
+  `player_max` int DEFAULT NULL COMMENT '浜烘暟涓婇檺',
   `state` int NOT NULL DEFAULT '1' COMMENT '0:鏈彂甯冿紝 1锛氬彂甯冿細2锛氬叧闂�',
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_activity_rating_scheme` (`rating_scheme_id`) USING BTREE,
+  KEY `idx_t_activity_deadline` (`signup_deadline`) USING BTREE,
+  CONSTRAINT `fk_t_activity_rating_scheme` FOREIGN KEY (`rating_scheme_id`) REFERENCES `t_rating_scheme` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE=InnoDB AUTO_INCREMENT=62 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_activity_judge
-CREATE TABLE t_activity_judge (
-  `id` bigint NOT NULL auto_increment,
+CREATE TABLE `t_activity_judge` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
   `activity_id` bigint NOT NULL,
   `stage_id` bigint NOT NULL,
   `judge_id` bigint NOT NULL,
-  `description` varchar(255),
-  `state` int,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int DEFAULT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `uq_stage_judge` (`stage_id`,`judge_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_activity_player
+CREATE TABLE `t_activity_player` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `activity_id` bigint NOT NULL,
+  `stage_id` bigint NOT NULL COMMENT '姣旇禌闃舵锛岄�昏緫鍜宼_activity_judge 淇濇寔涓�鑷淬��',
+  `player_id` bigint NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `reject_reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `judge_id` bigint DEFAULT NULL COMMENT '璇勫',
+  `feedback` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
+  `total_score` decimal(19,4) DEFAULT NULL COMMENT '浣庡垎',
+  `rank` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '鍚嶆',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_activity_player_rating
+CREATE TABLE `t_activity_player_rating` (
+  `id` bigint NOT NULL,
+  `activity_id` bigint NOT NULL,
+  `activity_player_id` bigint DEFAULT NULL,
+  `stage_id` bigint NOT NULL,
+  `player_id` bigint NOT NULL COMMENT '鍐椾綑瀛楁',
+  `judge_id` bigint DEFAULT NULL,
+  `total_score` decimal(19,2) DEFAULT NULL,
+  `feedback` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '璇勪环鍐呭',
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
 
 -- Table: t_activity_player_rating_item
-CREATE TABLE t_activity_player_rating_item (
-  `id` bigint NOT NULL auto_increment,
+CREATE TABLE `t_activity_player_rating_item` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
   `activity_id` bigint NOT NULL,
+  `activity_player_id` bigint NOT NULL,
+  `activity_player_rating_id` bigint NOT NULL,
+  `stage_id` bigint NOT NULL,
   `player_id` bigint NOT NULL,
+  `judge_id` bigint NOT NULL,
   `rating_scheme_id` bigint NOT NULL,
   `rating_item_id` bigint NOT NULL,
   `score` decimal(10,2) NOT NULL,
-  `feedback` text,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `feedback` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
+  `state` int NOT NULL DEFAULT '1',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
--- Table: t_avtivity_player
-CREATE TABLE t_avtivity_player (
-  `id` bigint NOT NULL auto_increment,
-  `activity_id` bigint NOT NULL,
-  `player_id` bigint NOT NULL,
-  `description` varchar(255),
-  `reject_reason` varchar(255),
-  `judge_id` bigint COMMENT '璇勫',
-  `feedback` text,
-  `total_score` decimal(19,4) COMMENT '浣庡垎',
-  `rank` varchar(255) COMMENT '鍚嶆',
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
-
--- Table: t_carousel  -- 杞挱鍥�
-CREATE TABLE t_carousel (
-  `id` bigint NOT NULL auto_increment,
-  `title` varchar(128) NOT NULL,
-  `description` varchar(255),
-  `sort_order` int NOT NULL,
+-- Table: t_carousel
+CREATE TABLE `t_carousel` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `title` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `sort_order` int DEFAULT NULL,
   `state` int NOT NULL DEFAULT '1' COMMENT '0:鍏抽棴锛�1锛氫娇鐢�',
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='杞挱鍥�';
 
 -- Table: t_employee
-CREATE TABLE t_employee (
-  `id` bigint NOT NULL auto_increment,
-  `name` varchar(64) NOT NULL,
-  `phone` varchar(32) NOT NULL,
-  `password` varchar(128) NOT NULL,
-  `status` varchar(16) NOT NULL,
+CREATE TABLE `t_employee` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `password` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `role_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `user_id` bigint NOT NULL,
   `state` int NOT NULL,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
   `version` bigint NOT NULL DEFAULT '0',
-  `role_code` varchar(32) NOT NULL,
-  `user_id` bigint NOT NULL
-);
+  `description` varchar(255) DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `phone` (`phone`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_employee_role
-CREATE TABLE t_employee_role (
-  `id` bigint NOT NULL auto_increment,
+CREATE TABLE `t_employee_role` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
   `employee_id` bigint NOT NULL,
   `role_id` bigint NOT NULL,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_user_role_role` (`role_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_judge
-CREATE TABLE t_judge (
-  `id` bigint NOT NULL auto_increment,
-  `name` varchar(64) NOT NULL,
-  `user_id` bigint,
-  `phone` varchar(32) NOT NULL,
-  `gender` int,
+CREATE TABLE `t_judge` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `user_id` bigint DEFAULT NULL,
+  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `gender` int DEFAULT NULL,
   `state` int NOT NULL DEFAULT '1',
-  `role_id` bigint,
-  `description` varchar(255),
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `role_id` bigint DEFAULT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  `title` varchar(128) DEFAULT NULL COMMENT '鑱屼綅/澶磋',
+  `company` varchar(128) DEFAULT NULL COMMENT '鍏徃/鏈烘瀯',
+  `introduction` text COMMENT '涓汉浠嬬粛',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `phone` (`phone`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_judge_tag
-CREATE TABLE t_judge_tag (
-  `id` bigint NOT NULL auto_increment,
+CREATE TABLE `t_judge_tag` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
   `judge_id` bigint NOT NULL,
   `tag_id` bigint NOT NULL,
   `state` int NOT NULL DEFAULT '1',
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_judge_major_tag` (`tag_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_media
-CREATE TABLE t_media (
-  `id` int NOT NULL auto_increment,
-  `name` varchar(255),
+CREATE TABLE `t_media` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
   `target_type` int NOT NULL,
   `target_id` bigint NOT NULL,
   `media_type` int NOT NULL,
-  `path` varchar(500) NOT NULL COMMENT '鑵捐浜戠殑瀛樺偍妗跺湴鍧�',
-  `thumb_path` varchar(500),
-  `file_ext` varchar(20) NOT NULL,
+  `path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '鑵捐浜戠殑瀛樺偍妗跺湴鍧�',
+  `thumb_path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `file_ext` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
   `file_size` int NOT NULL,
-  `duration` int COMMENT '瑙嗛鐨勯暱搴︾',
-  `description` varchar(255),
-  `state` varchar(255),
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `duration` int DEFAULT NULL COMMENT '瑙嗛鐨勯暱搴︾',
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_notification_task
-CREATE TABLE t_notification_task (
-  `id` bigint NOT NULL auto_increment,
-  `type` varchar(32) NOT NULL,
-  `channel` varchar(64) NOT NULL,
-  `target_type` varchar(32) NOT NULL COMMENT '1:瀛﹀憳锛�2锛氳瘎濮旓紝3锛氬伐浣滀汉鍛�',
+CREATE TABLE `t_notification_task` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `channel` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `target_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '1:瀛﹀憳锛�2锛氳瘎濮旓紝3锛氬伐浣滀汉鍛�',
   `target_id` bigint NOT NULL,
-  `payload` text COMMENT '娑堟伅鍐呭',
-  `error_message` varchar(512),
+  `payload` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '娑堟伅鍐呭',
+  `error_message` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
   `retry_count` int NOT NULL,
-  `next_retry_at` datetime,
+  `next_retry_at` datetime DEFAULT NULL,
   `state` tinyint(1) NOT NULL DEFAULT '1',
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_permission
-CREATE TABLE t_permission (
-  `id` bigint NOT NULL auto_increment,
-  `code` varchar(128) NOT NULL,
-  `name` varchar(128) NOT NULL,
-  `category` varchar(64),
-  `description` varchar(255),
+CREATE TABLE `t_permission` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `code` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `category` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
   `state` tinyint(1) NOT NULL DEFAULT '1',
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE,
+  KEY `idx_t_permission_code` (`code`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_player
-CREATE TABLE t_player (
-  `id` bigint NOT NULL auto_increment,
-  `name` varchar(64) NOT NULL,
-  `phone` varchar(32) NOT NULL,
+CREATE TABLE `t_player` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
   `role_id` bigint NOT NULL,
-  `description` varchar(255),
-  `gender` int COMMENT '0:濂筹紝1锛氱敺',
-  `education` varchar(32),
-  `introduction` text,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `gender` int DEFAULT NULL COMMENT '0:濂筹紝1锛氱敺',
+  `education` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `introduction` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
   `audit_state` int NOT NULL COMMENT '0绛夊緟瀹℃牳锛�1锛氬鏍搁�氳繃锛�2锛氫笉閫氳繃',
-  `reject_reason` varchar(255),
-  `final_score` decimal(10,2),
+  `reject_reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `final_score` decimal(10,2) DEFAULT NULL,
   `state` int NOT NULL,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
   `version` bigint NOT NULL DEFAULT '0',
-  `user_id` bigint NOT NULL
-);
+  `user_id` bigint NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `phone` (`phone`) USING BTREE,
+  KEY `idx_t_player_activity_status` (`audit_state`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_rating_item
-CREATE TABLE t_rating_item (
-  `id` bigint NOT NULL auto_increment,
+CREATE TABLE `t_rating_item` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
   `scheme_id` bigint NOT NULL,
-  `name` varchar(128) NOT NULL,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
   `max_score` int NOT NULL,
   `order_no` int NOT NULL,
   `state` int NOT NULL,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `idx_t_rating_item_scheme` (`scheme_id`) USING BTREE,
+  CONSTRAINT `fk_t_rating_item_scheme` FOREIGN KEY (`scheme_id`) REFERENCES `t_rating_scheme` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_rating_scheme
-CREATE TABLE t_rating_scheme (
-  `id` bigint NOT NULL auto_increment,
-  `name` varchar(128) NOT NULL,
-  `description` varchar(512),
+CREATE TABLE `t_rating_scheme` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
   `state` int NOT NULL,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_region
-CREATE TABLE t_region (
-  `id` bigint NOT NULL auto_increment,
+CREATE TABLE `t_region` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
   `pid` bigint NOT NULL COMMENT '鑷叧鑱�',
-  `name` varchar(64) NOT NULL,
-  `code` varchar(32) NOT NULL,
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
   `level` int NOT NULL,
   `leaf_flag` tinyint(1) NOT NULL DEFAULT '0',
-  `full_path` varchar(256),
+  `full_path` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
   `state` int NOT NULL,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_role
-CREATE TABLE t_role (
-  `id` bigint NOT NULL auto_increment,
-  `code` varchar(64) NOT NULL,
-  `name` varchar(128) NOT NULL,
-  `description` varchar(255),
+CREATE TABLE `t_role` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
   `state` int NOT NULL,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE,
+  KEY `idx_t_role_code` (`code`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_role_permission
-CREATE TABLE t_role_permission (
-  `id` int NOT NULL auto_increment,
+CREATE TABLE `t_role_permission` (
+  `id` int NOT NULL AUTO_INCREMENT,
   `role_id` bigint NOT NULL,
   `permission_id` bigint NOT NULL,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_role_permission_perm` (`permission_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_tag
-CREATE TABLE t_tag (
-  `id` bigint NOT NULL auto_increment,
-  `name` varchar(64) NOT NULL,
-  `code` varchar(64) NOT NULL,
-  `category` varchar(32) NOT NULL,
-  `description` varchar(255),
+CREATE TABLE `t_tag` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `category` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
   `state` int NOT NULL,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
-  `version` bigint NOT NULL DEFAULT '0'
-);
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE,
+  KEY `idx_t_tag_category` (`category`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- Table: t_user
-CREATE TABLE t_user (
-  `id` bigint NOT NULL auto_increment,
-  `name` varchar(255) NOT NULL,
-  `gender` int,
-  `phone` varchar(20),
-  `birthday` date,
-  `wx_openid` varchar(50) NOT NULL,
-  `wx_unionid` varchar(50) NOT NULL,
-  `wx_oa_openid` varchar(50),
-  `password` varchar(255),
+CREATE TABLE `t_user` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `gender` int DEFAULT NULL,
+  `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `birthday` date DEFAULT NULL,
+  `wx_openid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `wx_unionid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `wx_oa_openid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
   `state` int NOT NULL,
-  `create_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED,
-  `create_user_id` bigint,
-  `update_time` datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP' DEFAULT_GENERATED on update CURRENT_TIMESTAMP,
-  `update_user_id` bigint,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
   `version` bigint NOT NULL DEFAULT '0',
-  `mobile` varchar(20)
-);
+  `mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `uq_openid` (`wx_openid`) USING BTREE,
+  KEY `uq_unionid` (`wx_unionid`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
diff --git a/db_actual.sql b/db_actual.sql
new file mode 100644
index 0000000..e034b24
--- /dev/null
+++ b/db_actual.sql
@@ -0,0 +1,376 @@
+-- Database schema dump for ryc
+-- Generated at: Wed Sep 24 15:03:51 GMT+08:00 2025
+
+-- Table: t_activity
+CREATE TABLE `t_activity` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `pid` bigint NOT NULL DEFAULT '0',
+  `path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
+  `signup_deadline` datetime NOT NULL,
+  `match_time` datetime DEFAULT NULL,
+  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `rating_scheme_id` bigint NOT NULL,
+  `player_max` int DEFAULT NULL COMMENT '浜烘暟涓婇檺',
+  `state` int NOT NULL DEFAULT '1' COMMENT '0:鏈彂甯冿紝 1锛氬彂甯冿細2锛氬叧闂�',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_activity_rating_scheme` (`rating_scheme_id`) USING BTREE,
+  KEY `idx_t_activity_deadline` (`signup_deadline`) USING BTREE,
+  CONSTRAINT `fk_t_activity_rating_scheme` FOREIGN KEY (`rating_scheme_id`) REFERENCES `t_rating_scheme` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE=InnoDB AUTO_INCREMENT=62 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_activity_judge
+CREATE TABLE `t_activity_judge` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `activity_id` bigint NOT NULL,
+  `stage_id` bigint NOT NULL,
+  `judge_id` bigint NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int DEFAULT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `uq_stage_judge` (`stage_id`,`judge_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_activity_player
+CREATE TABLE `t_activity_player` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `activity_id` bigint NOT NULL,
+  `stage_id` bigint NOT NULL COMMENT '姣旇禌闃舵锛岄�昏緫鍜宼_activity_judge 淇濇寔涓�鑷淬��',
+  `player_id` bigint NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `reject_reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `judge_id` bigint DEFAULT NULL COMMENT '璇勫',
+  `feedback` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
+  `total_score` decimal(19,4) DEFAULT NULL COMMENT '浣庡垎',
+  `rank` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '鍚嶆',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_activity_player_rating_item
+CREATE TABLE `t_activity_player_rating_item` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `activity_id` bigint NOT NULL,
+  `stage_id` bigint NOT NULL,
+  `player_id` bigint NOT NULL,
+  `rating_scheme_id` bigint NOT NULL,
+  `rating_item_id` bigint NOT NULL,
+  `score` decimal(10,2) NOT NULL,
+  `feedback` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
+  `state` int NOT NULL DEFAULT '1',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_carousel
+CREATE TABLE `t_carousel` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `title` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `sort_order` int DEFAULT NULL,
+  `state` int NOT NULL DEFAULT '1' COMMENT '0:鍏抽棴锛�1锛氫娇鐢�',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='杞挱鍥�';
+
+-- Table: t_employee
+CREATE TABLE `t_employee` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `password` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `role_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `user_id` bigint NOT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  `description` varchar(255) DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `phone` (`phone`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_employee_role
+CREATE TABLE `t_employee_role` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `employee_id` bigint NOT NULL,
+  `role_id` bigint NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_user_role_role` (`role_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_judge
+CREATE TABLE `t_judge` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `user_id` bigint DEFAULT NULL,
+  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `gender` int DEFAULT NULL,
+  `state` int NOT NULL DEFAULT '1',
+  `role_id` bigint DEFAULT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  `title` varchar(128) DEFAULT NULL COMMENT '鑱屼綅/澶磋',
+  `company` varchar(128) DEFAULT NULL COMMENT '鍏徃/鏈烘瀯',
+  `introduction` text COMMENT '涓汉浠嬬粛',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `phone` (`phone`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_judge_tag
+CREATE TABLE `t_judge_tag` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `judge_id` bigint NOT NULL,
+  `tag_id` bigint NOT NULL,
+  `state` int NOT NULL DEFAULT '1',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_judge_major_tag` (`tag_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_media
+CREATE TABLE `t_media` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `target_type` int NOT NULL,
+  `target_id` bigint NOT NULL,
+  `media_type` int NOT NULL,
+  `path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '鑵捐浜戠殑瀛樺偍妗跺湴鍧�',
+  `thumb_path` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `file_ext` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `file_size` int NOT NULL,
+  `duration` int DEFAULT NULL COMMENT '瑙嗛鐨勯暱搴︾',
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_notification_task
+CREATE TABLE `t_notification_task` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `channel` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `target_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '1:瀛﹀憳锛�2锛氳瘎濮旓紝3锛氬伐浣滀汉鍛�',
+  `target_id` bigint NOT NULL,
+  `payload` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '娑堟伅鍐呭',
+  `error_message` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `retry_count` int NOT NULL,
+  `next_retry_at` datetime DEFAULT NULL,
+  `state` tinyint(1) NOT NULL DEFAULT '1',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_permission
+CREATE TABLE `t_permission` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `code` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `category` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` tinyint(1) NOT NULL DEFAULT '1',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE,
+  KEY `idx_t_permission_code` (`code`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_player
+CREATE TABLE `t_player` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `role_id` bigint NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `gender` int DEFAULT NULL COMMENT '0:濂筹紝1锛氱敺',
+  `education` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `introduction` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
+  `audit_state` int NOT NULL COMMENT '0绛夊緟瀹℃牳锛�1锛氬鏍搁�氳繃锛�2锛氫笉閫氳繃',
+  `reject_reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `final_score` decimal(10,2) DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  `user_id` bigint NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `phone` (`phone`) USING BTREE,
+  KEY `idx_t_player_activity_status` (`audit_state`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_rating_item
+CREATE TABLE `t_rating_item` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `scheme_id` bigint NOT NULL,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `max_score` int NOT NULL,
+  `order_no` int NOT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `idx_t_rating_item_scheme` (`scheme_id`) USING BTREE,
+  CONSTRAINT `fk_t_rating_item_scheme` FOREIGN KEY (`scheme_id`) REFERENCES `t_rating_scheme` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_rating_scheme
+CREATE TABLE `t_rating_scheme` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_region
+CREATE TABLE `t_region` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `pid` bigint NOT NULL COMMENT '鑷叧鑱�',
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `level` int NOT NULL,
+  `leaf_flag` tinyint(1) NOT NULL DEFAULT '0',
+  `full_path` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_role
+CREATE TABLE `t_role` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE,
+  KEY `idx_t_role_code` (`code`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_role_permission
+CREATE TABLE `t_role_permission` (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `role_id` bigint NOT NULL,
+  `permission_id` bigint NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `fk_t_role_permission_perm` (`permission_id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_tag
+CREATE TABLE `t_tag` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `category` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `code` (`code`) USING BTREE,
+  KEY `idx_t_tag_category` (`category`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
+-- Table: t_user
+CREATE TABLE `t_user` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `gender` int DEFAULT NULL,
+  `phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `birthday` date DEFAULT NULL,
+  `wx_openid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `wx_unionid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+  `wx_oa_openid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  `state` int NOT NULL,
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `create_user_id` bigint DEFAULT NULL,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `update_user_id` bigint DEFAULT NULL,
+  `version` bigint NOT NULL DEFAULT '0',
+  `mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE,
+  KEY `uq_openid` (`wx_openid`) USING BTREE,
+  KEY `uq_unionid` (`wx_unionid`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+
diff --git a/insert_rating_template.sql b/insert_rating_template.sql
new file mode 100644
index 0000000..0284fb4
--- /dev/null
+++ b/insert_rating_template.sql
@@ -0,0 +1,30 @@
+-- 鎻掑叆璇勫垎妯℃澘鏁版嵁
+-- 娉ㄦ剰锛氳繖涓剼鏈細鍒涘缓涓�涓紪绋嬪ぇ璧涚殑璇勫垎妯℃澘
+
+-- 1. 鎻掑叆璇勫垎妯℃澘 (t_rating_scheme)
+INSERT INTO t_rating_scheme (id, name, description, state, create_time, create_user_id, update_time, update_user_id, version) 
+VALUES (1, '缂栫▼澶ц禌璇勫垎鏍囧噯', '鐢ㄤ簬缂栫▼姣旇禌鐨勭患鍚堣瘎鍒嗘爣鍑嗭紝鍖呭惈浠g爜璐ㄩ噺銆佸姛鑳藉畬鏁存�с�佺敤鎴蜂綋楠屻�佸垱鏂版�у拰椤圭洰灞曠ず绛夌淮搴�', 1, NOW(), 1, NOW(), 1, 0);
+
+-- 2. 鎻掑叆璇勫垎椤圭洰 (t_rating_item)
+INSERT INTO t_rating_item (id, scheme_id, name, max_score, order_no, create_time, create_user_id, update_time, update_user_id, version) VALUES
+(1, 1, '浠g爜璐ㄩ噺', 30, 1, NOW(), 1, NOW(), 1, 0),
+(2, 1, '鍔熻兘瀹屾暣鎬�', 25, 2, NOW(), 1, NOW(), 1, 0),
+(3, 1, '鐢ㄦ埛浣撻獙', 20, 3, NOW(), 1, NOW(), 1, 0),
+(4, 1, '鍒涙柊鎬�', 15, 4, NOW(), 1, NOW(), 1, 0),
+(5, 1, '椤圭洰灞曠ず', 10, 5, NOW(), 1, NOW(), 1, 0);
+
+-- 楠岃瘉鎻掑叆缁撴灉
+SELECT '=== 璇勫垎妯℃澘 ===' as info;
+SELECT * FROM t_rating_scheme WHERE id = 1;
+
+SELECT '=== 璇勫垎椤圭洰 ===' as info;
+SELECT * FROM t_rating_item WHERE scheme_id = 1 ORDER BY order_no;
+
+SELECT '=== 鎬诲垎楠岃瘉 ===' as info;
+SELECT 
+    rs.name as scheme_name,
+    SUM(ri.max_score) as total_max_score
+FROM t_rating_scheme rs
+LEFT JOIN t_rating_item ri ON rs.id = ri.scheme_id
+WHERE rs.id = 1
+GROUP BY rs.id, rs.name;
\ No newline at end of file
diff --git a/project.md b/project.md
index 4e079d5..7202f41 100644
--- a/project.md
+++ b/project.md
@@ -186,7 +186,7 @@
 鏁版嵁鏉ユ簮涓庡叧鑱旓細
 
 * 涓昏〃锛歵\_activity\_player锛屽叧鑱斿鍛樿〃 t\_player锛坧layer\_id锛夛紝鍏宠仈姣旇禌琛� t\_activity锛坅ctivity\_id锛�
-* 娉ㄦ剰锛歵\_activity\_player.activity\_id 濮嬬粓鍏宠仈鈥滄瘮璧涒�濓紱t\_activity\_player.stage\_id 蹇呴』鍏宠仈璇ユ瘮璧涚殑鈥滈樁娈碘�滻D銆傝嫢璇ユ瘮璧涙湭瀹氫箟闃舵锛坱\_activity 鏃犲瓙璁板綍 pid=activity\_id锛夛紝鍒欏皢 stage\_id 璁句负 activity\_id锛堟寚鍚戞瘮璧涜嚜韬級銆�
+* 娉ㄦ剰锛歵\_activity\_player.activity\_id 濮嬬粓鍏宠仈"姣旇禌"锛泃\_activity\_player.stage\_id 蹇呴』鍏宠仈璇ユ瘮璧涚殑"闃舵"ID銆傝嫢璇ユ瘮璧涙湭瀹氫箟闃舵锛坱\_activity 鏃犲瓙璁板綍 pid=activity\_id锛夛紝鍒欏皢 stage\_id 璁句负 activity\_id锛堟寚鍚戞瘮璧涜嚜韬級銆�
 
 GraphQL 瑙勮寖锛�
 
@@ -198,6 +198,89 @@
 * 0锛堟姤鍚嶆湭瀹℃牳锛夛細鏄剧ず鎸夐挳銆愬鏍搁�氳繃銆�
 * 1锛堣繘琛屼腑锛屽凡閫氳繃锛夛細鏄剧ず鎸夐挳銆愬彇娑堣祫鏍笺��
 * 2锛堝鏍告湭閫氳繃锛夛細鏄剧ず銆愬鏍告湭閫氳繃銆戯紝鏃犳搷浣滄寜閽�
+
+3.12 澶氳瘎濮旇瘎鍒嗙郴缁�
+
+3.12.1 绯荤粺姒傝堪
+
+澶氳瘎濮旇瘎鍒嗙郴缁熸敮鎸佸涓瘎濮斿鍚屼竴閫夋墜杩涜鐙珛璇勫垎锛岀郴缁熻嚜鍔ㄨ绠楀钩鍧囧垎锛岀‘淇濊瘎鍒嗙殑鍏鎬у拰閫忔槑搴︺��
+
+3.12.2 鏍稿績鍔熻兘
+
+璇勫垎椤甸潰澧炲己锛�
+* 鏄剧ず褰撳墠璇勫淇℃伅锛堝鍚嶏級
+* 灞曠ず鎵�鏈夎瘎濮旂殑璇勫垎鐘舵�侊紙宸茶瘎鍒�/鏈瘎鍒嗭級
+* 鏄剧ず閫夋墜鐨勫钩鍧囧垎
+* 鏀寔璇勫鏌ョ湅鍜屼慨鏀硅嚜宸辩殑璇勫垎
+
+璇勫垎鐘舵�佺鐞嗭細
+* 瀹炴椂鏄剧ず鍚勮瘎濮旂殑璇勫垎杩涘害
+* 鍖哄垎褰撳墠璇勫鍜屽叾浠栬瘎濮�
+* 鏄剧ず姣忎釜璇勫鐨勬�诲垎锛堝凡璇勫垎鐨勬儏鍐典笅锛�
+
+鏁版嵁璁$畻锛�
+* 鑷姩璁$畻閫夋墜鐨勫钩鍧囧垎
+* 鏀寔璇勫淇敼璇勫垎鍚庨噸鏂拌绠�
+* 淇濇寔璇勫垎鍘嗗彶璁板綍
+
+3.12.3 鎶�鏈疄鐜�
+
+鍓嶇瀹炵幇锛圴ue.js锛夛細
+* 缁勪欢锛歊atingForm.vue - 澧炲己璇勫垎琛ㄥ崟缁勪欢
+* 椤甸潰锛歳ating.vue - 璇勫垎椤甸潰
+* API锛歛ctivityPlayer.js - 鏂板澶氳瘎濮旂浉鍏虫帴鍙�
+
+鍚庣瀹炵幇锛圫pring Boot + GraphQL锛夛細
+* API锛歅layerGraphqlApi.java - 鏂板GraphQL鏌ヨ鏂规硶
+* 鏈嶅姟锛欰ctivityPlayerRatingService.java - 璇勫垎涓氬姟閫昏緫
+* DTO锛氭柊澧炲搷搴旂被鍨嬫敮鎸佸璇勫鏁版嵁
+
+鏂板GraphQL鏌ヨ锛�
+* judgeRatingsForPlayer - 鑾峰彇閫夋墜鐨勬墍鏈夎瘎濮旇瘎鍒嗙姸鎬�
+* currentJudgeRating - 鑾峰彇褰撳墠璇勫鐨勮瘎鍒嗚鎯�
+* averageScoreForPlayer - 鑾峰彇閫夋墜骞冲潎鍒�
+* currentJudgeInfo - 鑾峰彇褰撳墠璇勫淇℃伅
+
+3.12.4 鏁版嵁缁撴瀯
+
+璇勫璇勫垎鐘舵�佸搷搴旓紙JudgeRatingStatusResponse锛夛細
+* judgeId - 璇勫ID
+* judgeName - 璇勫濮撳悕
+* totalScore - 鎬诲垎
+* status - 璇勫垎鐘舵�侊紙0-鏈瘎鍒嗭紝1-宸茶瘎鍒嗭級
+* isCurrentJudge - 鏄惁涓哄綋鍓嶈瘎濮�
+
+褰撳墠璇勫璇勫垎鍝嶅簲锛圕urrentJudgeRatingResponse锛夛細
+* id - 璇勫垎璁板綍ID
+* totalScore - 鎬诲垎
+* status - 璇勫垎鐘舵��
+* remark - 璇勫垎澶囨敞
+* items - 璇勫垎椤圭洰璇︽儏鍒楄〃
+
+褰撳墠璇勫淇℃伅鍝嶅簲锛圕urrentJudgeInfoResponse锛夛細
+* id - 璇勫ID
+* name - 璇勫濮撳悕
+* phone - 鑱旂郴鐢佃瘽
+* description - 璇勫鎻忚堪
+
+3.12.5 涓氬姟瑙勫垯
+
+璇勫垎鏉冮檺锛�
+* 璇勫鍙兘鏌ョ湅鍜屼慨鏀硅嚜宸辩殑璇勫垎
+* 璇勫鍙互鏌ョ湅鍏朵粬璇勫鐨勮瘎鍒嗙姸鎬侊紙宸茶瘎鍒�/鏈瘎鍒嗭級
+* 璇勫鍙互鏌ョ湅閫夋墜鐨勫钩鍧囧垎
+
+璇勫垎娴佺▼锛�
+* 璇勫杩涘叆璇勫垎椤甸潰锛岀郴缁熸樉绀哄綋鍓嶈瘎濮斾俊鎭�
+* 鏄剧ず鎵�鏈夎瘎濮旂殑璇勫垎鐘舵��
+* 濡傛灉褰撳墠璇勫宸茶瘎鍒嗭紝鍔犺浇鍏跺巻鍙茶瘎鍒嗘暟鎹�
+* 璇勫鎻愪氦璇勫垎鍚庯紝绯荤粺閲嶆柊璁$畻骞冲潎鍒�
+* 瀹炴椂鏇存柊璇勫垎鐘舵�佹樉绀�
+
+鏁版嵁涓�鑷存�э細
+* 璇勫垎鎻愪氦鍚庣珛鍗虫洿鏂版暟鎹簱
+* 閲嶆柊鍔犺浇椤甸潰鏁版嵁纭繚鐘舵�佸悓姝�
+* 鏀寔璇勫澶氭淇敼璇勫垎
 * 3锛堢粨鏉燂級锛氭樉绀恒�愬凡缁撴潫銆戯紝鏃犳搷浣滄寜閽�
 
 鍥涖�佸井淇$闇�姹�
@@ -309,12 +392,14 @@
 璇存槑锛氫互鍚庣 application.yml 涓哄噯锛岄伩鍏嶇幆澧冧笉涓�鑷淬��
 
 褰撳墠閰嶇疆锛堟憳鑷� backend/src/main/resources/application.yml锛夛細
-- URL锛歫dbc:mysql://139.155.104.10:3306/ryc?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
-- 鐢ㄦ埛鍚嶏細ryc
-- 瀵嗙爜锛欿iYap3E8X8RLcM6T
+
+* URL锛歫dbc:mysql://139.155.104.10:3306/ryc?useUnicode=true\&characterEncoding=utf8\&useSSL=false\&serverTimezone=Asia/Shanghai
+* 鐢ㄦ埛鍚嶏細ryc
+* 瀵嗙爜锛欿iYap3E8X8RLcM6T
 
 瓒呮椂寤鸿锛�
-- 鍦ㄦ祴璇曟垨鎵归噺鎿嶄綔鍦烘櫙涓嬶紝杩藉姞 connectTimeout=60000銆乻ocketTimeout=60000 浠ユ彁楂樼ǔ瀹氭�с��
+
+* 鍦ㄦ祴璇曟垨鎵归噺鎿嶄綔鍦烘櫙涓嬶紝杩藉姞 connectTimeout=60000銆乻ocketTimeout=60000 浠ユ彁楂樼ǔ瀹氭�с��
 
 8.2 RabbitMQ 杩炴帴
 
@@ -344,3 +429,25 @@
 
 Region锛歛p-chengdu
 
+
+
+Git 鏈嶅姟:
+
+IP: http://42.193.1.25:9521/
+
+鐢ㄦ埛鍚�:ai
+
+瀵嗙爜:ai@ycl2025
+
+搴擄細
+
+
+
+寰俊灏忕▼搴忓紑鍙戣�呭伐鍏�
+
+璺緞锛欳:\\Program Files (x86)\\Tencent\\寰俊web寮�鍙戣�呭伐鍏�
+
+
+
+
+
diff --git a/test_employee_api_fix.ps1 b/test_employee_api_fix.ps1
new file mode 100644
index 0000000..c01574e
--- /dev/null
+++ b/test_employee_api_fix.ps1
@@ -0,0 +1,43 @@
+# 娴嬭瘯淇鍚庣殑鍛樺伐API
+Write-Host "娴嬭瘯鍛樺伐API淇..." -ForegroundColor Green
+
+# 娴嬭瘯鑾峰彇鍛樺伐鍒楄〃
+Write-Host "1. 娴嬭瘯鑾峰彇鍛樺伐鍒楄〃..." -ForegroundColor Yellow
+$getEmployeesQuery = @{
+    query = "query GetEmployees { employees { id name phone roleCode description status createTime updateTime } }"
+} | ConvertTo-Json -Compress
+
+try {
+    $response = Invoke-RestMethod -Uri "http://localhost:8080/api/graphql" -Method POST -Body $getEmployeesQuery -ContentType "application/json"
+    Write-Host "鑾峰彇鍛樺伐鍒楄〃鎴愬姛" -ForegroundColor Green
+    Write-Host "鍛樺伐鏁伴噺: $($response.data.employees.Count)" -ForegroundColor Cyan
+} catch {
+    Write-Host "鑾峰彇鍛樺伐鍒楄〃澶辫触: $($_.Exception.Message)" -ForegroundColor Red
+}
+
+# 娴嬭瘯娣诲姞鍛樺伐
+Write-Host "`n2. 娴嬭瘯娣诲姞鍛樺伐..." -ForegroundColor Yellow
+$addEmployeeMutation = @{
+    query = "mutation SaveEmployee(`$input: EmployeeInput!) { saveEmployee(input: `$input) { id name phone roleCode description status } }"
+    variables = @{
+        input = @{
+            name = "娴嬭瘯鍛樺伐API淇"
+            phone = "13800138000"
+            password = "123456"
+            roleCode = "EMPLOYEE"
+            description = "API淇娴嬭瘯鍛樺伐"
+        }
+    }
+} | ConvertTo-Json -Compress -Depth 3
+
+try {
+    $response = Invoke-RestMethod -Uri "http://localhost:8080/api/graphql" -Method POST -Body $addEmployeeMutation -ContentType "application/json"
+    Write-Host "娣诲姞鍛樺伐鎴愬姛" -ForegroundColor Green
+    $newEmployeeId = $response.data.saveEmployee.id
+    $newEmployeeName = $response.data.saveEmployee.name
+    Write-Host "鏂板憳宸D: $newEmployeeId, 濮撳悕: $newEmployeeName" -ForegroundColor Cyan
+} catch {
+    Write-Host "娣诲姞鍛樺伐澶辫触: $($_.Exception.Message)" -ForegroundColor Red
+}
+
+Write-Host "`n鍛樺伐API淇娴嬭瘯瀹屾垚!" -ForegroundColor Green
\ No newline at end of file
diff --git a/test_employee_management.ps1 b/test_employee_management.ps1
new file mode 100644
index 0000000..eee0157
--- /dev/null
+++ b/test_employee_management.ps1
@@ -0,0 +1,65 @@
+# Employee Management Test Script
+Write-Host "=== Employee Management Test ===" -ForegroundColor Green
+
+$baseUrl = "http://localhost:8080/api/graphql"
+$headers = @{
+    "Content-Type" = "application/json"
+}
+
+# Test 1: Get all employees
+Write-Host "`n1. Testing get all employees..." -ForegroundColor Yellow
+$query1 = '{"query":"query GetEmployees { employees { id name phone roleCode description status createTime updateTime } }"}'
+
+try {
+    $response1 = Invoke-RestMethod -Uri $baseUrl -Method POST -Body $query1 -Headers $headers
+    Write-Host "Success: Get employees list" -ForegroundColor Green
+    Write-Host "Employee count: $($response1.data.employees.Count)" -ForegroundColor Cyan
+    if ($response1.data.employees.Count -gt 0) {
+        Write-Host "First employee: $($response1.data.employees[0].name)" -ForegroundColor Cyan
+    }
+} catch {
+    Write-Host "Failed: Get employees list - $($_.Exception.Message)" -ForegroundColor Red
+}
+
+# Test 2: Add new employee
+Write-Host "`n2. Testing add new employee..." -ForegroundColor Yellow
+$mutation1 = '{"query":"mutation SaveEmployee($input: EmployeeInput!) { saveEmployee(input: $input) { id name phone roleCode description status createTime } }","variables":{"input":{"name":"Test Employee","phone":"13800138000","password":"123456","roleCode":"STAFF","description":"This is a test employee","status":"ACTIVE"}}}'
+
+try {
+    $response2 = Invoke-RestMethod -Uri $baseUrl -Method POST -Body $mutation1 -Headers $headers
+    Write-Host "Success: Add new employee" -ForegroundColor Green
+    $newEmployeeId = $response2.data.saveEmployee.id
+    Write-Host "New employee ID: $newEmployeeId" -ForegroundColor Cyan
+    Write-Host "New employee name: $($response2.data.saveEmployee.name)" -ForegroundColor Cyan
+} catch {
+    Write-Host "Failed: Add new employee - $($_.Exception.Message)" -ForegroundColor Red
+    $newEmployeeId = $null
+}
+
+# Test 3: Search employees by name
+Write-Host "`n3. Testing search employees..." -ForegroundColor Yellow
+$query2 = '{"query":"query SearchEmployees($name: String) { employeesByName(name: $name) { id name phone roleCode description status } }","variables":{"name":"Test"}}'
+
+try {
+    $response3 = Invoke-RestMethod -Uri $baseUrl -Method POST -Body $query2 -Headers $headers
+    Write-Host "Success: Search employees" -ForegroundColor Green
+    Write-Host "Search result count: $($response3.data.employeesByName.Count)" -ForegroundColor Cyan
+} catch {
+    Write-Host "Failed: Search employees - $($_.Exception.Message)" -ForegroundColor Red
+}
+
+# Test 4: Delete test employee (if created successfully)
+if ($newEmployeeId) {
+    Write-Host "`n4. Testing delete employee..." -ForegroundColor Yellow
+    $mutation2 = "{`"query`":`"mutation DeleteEmployee(`$id: Long!) { deleteEmployee(id: `$id) }`",`"variables`":{`"id`":$newEmployeeId}}"
+
+    try {
+        $response4 = Invoke-RestMethod -Uri $baseUrl -Method POST -Body $mutation2 -Headers $headers
+        Write-Host "Success: Delete employee" -ForegroundColor Green
+    } catch {
+        Write-Host "Failed: Delete employee - $($_.Exception.Message)" -ForegroundColor Red
+    }
+}
+
+Write-Host "`n=== Test Complete ===" -ForegroundColor Green
+Write-Host "Please check frontend page http://localhost:3000/#/employee to verify UI functionality" -ForegroundColor Cyan
\ No newline at end of file
diff --git a/update_employee_table.ps1 b/update_employee_table.ps1
new file mode 100644
index 0000000..17a87a6
--- /dev/null
+++ b/update_employee_table.ps1
@@ -0,0 +1,18 @@
+# 鏇存柊鍛樺伐琛ㄧ粨鏋勶紝娣诲姞description瀛楁
+Write-Host "寮�濮嬫洿鏂板憳宸ヨ〃缁撴瀯..."
+
+# 鏄剧ず闇�瑕佹墽琛岀殑SQL璇彞
+Write-Host "闇�瑕佹墽琛屼互涓婼QL璇彞鏉ユ坊鍔燿escription瀛楁锛�"
+Write-Host "================================"
+if (Test-Path "add_description_column.sql") {
+    Get-Content "add_description_column.sql"
+} else {
+    Write-Host "USE ryc;"
+    Write-Host "ALTER TABLE t_employee ADD COLUMN description varchar(255) AFTER role_code;"
+    Write-Host "DESCRIBE t_employee;"
+}
+Write-Host "================================"
+
+Write-Host ""
+Write-Host "鐢变簬MySQL杩炴帴鍣ㄤ笉鍙敤锛岃鎵嬪姩鎵ц涓婅堪SQL璇彞銆�"
+Write-Host "鎮ㄥ彲浠ヤ娇鐢∕ySQL Workbench銆乸hpMyAdmin鎴栧叾浠栨暟鎹簱绠$悊宸ュ叿銆�"
\ No newline at end of file
diff --git a/web/package.json b/web/package.json
index d8df91d..0f453d9 100644
--- a/web/package.json
+++ b/web/package.json
@@ -33,6 +33,7 @@
     "eslint-plugin-vue": "^9.18.1",
     "prettier": "^3.1.0",
     "sass": "^1.69.5",
+    "terser": "^5.44.0",
     "typescript": "^5.2.2",
     "vite": "^5.0.0",
     "vue-tsc": "^1.8.22"
diff --git a/web/public/test-rating.html b/web/public/test-rating.html
new file mode 100644
index 0000000..fcfa82f
--- /dev/null
+++ b/web/public/test-rating.html
@@ -0,0 +1,126 @@
+<!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/activity.js b/web/src/api/activity.js
index 2cca6bc..b704967 100644
--- a/web/src/api/activity.js
+++ b/web/src/api/activity.js
@@ -74,9 +74,14 @@
   query GetAllActivities {
     allActivities {
       id
+      pid
       name
       state
       stateName
+      parent {
+        id
+        name
+      }
     }
   }
 `;
diff --git a/web/src/api/activityPlayer.js b/web/src/api/activityPlayer.js
index 4dd43eb..9eb3d43 100644
--- a/web/src/api/activityPlayer.js
+++ b/web/src/api/activityPlayer.js
@@ -1,4 +1,18 @@
+import { 
+  mockActivityPlayerDetail, 
+  mockRatingScheme, 
+  mockCurrentJudgeInfo, 
+  mockJudgeRatings, 
+  mockCurrentJudgeRating, 
+  mockAverageScore,
+  createMockResponse 
+} from './mockData.js'
+
 const GRAPHQL_ENDPOINT = '/api/graphql'
+
+// 妯℃嫙鏁版嵁寮�鍏� - 璁剧疆涓簍rue鏃朵娇鐢ㄦā鎷熸暟鎹�
+// 宸插垏鎹㈠埌鐪熷疄鏁版嵁妯″紡
+const USE_MOCK_DATA = false
 
 async function graphqlRequest(query, variables = {}) {
   const response = await fetch(GRAPHQL_ENDPOINT, {
@@ -55,6 +69,11 @@
  * 鑾峰彇姣旇禌鎶ュ悕璇︽儏锛堢敤浜庤瘎鍒嗭級
  */
 export function getActivityPlayerDetail(id) {
+  if (USE_MOCK_DATA) {
+    return Promise.resolve(createMockResponse({
+      activityPlayerDetail: mockActivityPlayerDetail
+    }))
+  }
   return graphqlRequest(GET_ACTIVITY_PLAYER_DETAIL, { id })
 }
 
@@ -68,5 +87,105 @@
  * 淇濆瓨姣旇禌鎶ュ悕璇勫垎
  */
 export function saveActivityPlayerRating(input) {
+  if (USE_MOCK_DATA) {
+    console.log('妯℃嫙淇濆瓨璇勫垎鏁版嵁:', input)
+    return Promise.resolve(createMockResponse({
+      saveActivityPlayerRating: true
+    }))
+  }
   return graphqlRequest(SAVE_ACTIVITY_PLAYER_RATING, { input })
+}
+
+const GET_JUDGE_RATINGS_FOR_PLAYER = `
+  query GetJudgeRatingsForPlayer($activityPlayerId: ID!) {
+    judgeRatingsForPlayer(activityPlayerId: $activityPlayerId) {
+      judgeId
+      judgeName
+      totalScore
+      status
+      isCurrentJudge
+    }
+  }
+`
+
+/**
+ * 鑾峰彇鎸囧畾閫夋墜鐨勬墍鏈夎瘎濮旇瘎鍒嗙姸鎬�
+ */
+export function getJudgeRatingsForPlayer(activityPlayerId) {
+  if (USE_MOCK_DATA) {
+    return Promise.resolve(createMockResponse({
+      judgeRatingsForPlayer: mockJudgeRatings
+    }))
+  }
+  return graphqlRequest(GET_JUDGE_RATINGS_FOR_PLAYER, { activityPlayerId })
+}
+
+const GET_CURRENT_JUDGE_RATING = `
+  query GetCurrentJudgeRating($activityPlayerId: ID!) {
+    currentJudgeRating(activityPlayerId: $activityPlayerId) {
+      id
+      totalScore
+      status
+      remark
+      items {
+        ratingItemId
+        ratingItemName
+        score
+        weightedScore
+      }
+    }
+  }
+`
+
+/**
+ * 鑾峰彇褰撳墠璇勫瀵规寚瀹氶�夋墜鐨勮瘎鍒�
+ */
+export function getCurrentJudgeRating(activityPlayerId) {
+  if (USE_MOCK_DATA) {
+    return Promise.resolve(createMockResponse({
+      currentJudgeRating: mockCurrentJudgeRating
+    }))
+  }
+  return graphqlRequest(GET_CURRENT_JUDGE_RATING, { activityPlayerId })
+}
+
+const GET_AVERAGE_SCORE_FOR_PLAYER = `
+  query GetAverageScoreForPlayer($activityPlayerId: ID!) {
+    averageScoreForPlayer(activityPlayerId: $activityPlayerId)
+  }
+`
+
+/**
+ * 鑾峰彇鎸囧畾閫夋墜鐨勫钩鍧囧垎
+ */
+export function getAverageScoreForPlayer(activityPlayerId) {
+  if (USE_MOCK_DATA) {
+    return Promise.resolve(createMockResponse({
+      averageScoreForPlayer: mockAverageScore
+    }))
+  }
+  return graphqlRequest(GET_AVERAGE_SCORE_FOR_PLAYER, { activityPlayerId })
+}
+
+const GET_CURRENT_JUDGE_INFO = `
+  query GetCurrentJudgeInfo {
+    currentJudgeInfo {
+      id
+      name
+      phone
+      description
+    }
+  }
+`
+
+/**
+ * 鑾峰彇褰撳墠璇勫淇℃伅
+ */
+export function getCurrentJudgeInfo() {
+  if (USE_MOCK_DATA) {
+    return Promise.resolve(createMockResponse({
+      currentJudgeInfo: mockCurrentJudgeInfo
+    }))
+  }
+  return graphqlRequest(GET_CURRENT_JUDGE_INFO)
 }
\ No newline at end of file
diff --git a/web/src/api/employee.ts b/web/src/api/employee.ts
new file mode 100644
index 0000000..dd55bc7
--- /dev/null
+++ b/web/src/api/employee.ts
@@ -0,0 +1,210 @@
+// 鍛樺伐绠$悊API
+
+// 鍛樺伐鐩稿叧鐨� GraphQL 鏌ヨ鍜屽彉鏇�
+export const EMPLOYEE_QUERIES = {
+  // 鑾峰彇鎵�鏈夊憳宸�
+  GET_EMPLOYEES: `
+    query GetEmployees {
+      employees {
+        id
+        name
+        phone
+        roleId
+        description
+        createTime
+        updateTime
+      }
+    }
+  `,
+  
+  // 鏍规嵁濮撳悕鎼滅储鍛樺伐
+  SEARCH_EMPLOYEES: `
+    query SearchEmployees($name: String) {
+      employeesByName(name: $name) {
+        id
+        name
+        phone
+        roleId
+        description
+        createTime
+        updateTime
+      }
+    }
+  `,
+  
+  // 鑾峰彇鍛樺伐璇︽儏
+  GET_EMPLOYEE: `
+    query GetEmployee($id: Long!) {
+      employee(id: $id) {
+        id
+        name
+        phone
+        roleId
+        description
+        createTime
+        updateTime
+      }
+    }
+  `
+}
+
+export const EMPLOYEE_MUTATIONS = {
+  // 淇濆瓨鍛樺伐锛堟柊澧炴垨鏇存柊锛�
+  SAVE_EMPLOYEE: `
+    mutation SaveEmployee($input: EmployeeInput!) {
+      saveEmployee(input: $input) {
+        id
+        name
+        phone
+        roleId
+        description
+        createTime
+        updateTime
+      }
+    }
+  `,
+  
+  // 鍒犻櫎鍛樺伐
+  DELETE_EMPLOYEE: `
+    mutation DeleteEmployee($id: Long!) {
+      deleteEmployee(id: $id)
+    }
+  `
+}
+
+// 绫诲瀷瀹氫箟
+export interface Employee {
+  id: string
+  name: string
+  phone: string
+  roleId: string
+  description?: string
+  createTime?: string
+  updateTime?: string
+}
+
+export interface EmployeeInput {
+  id?: string
+  name: string
+  phone: string
+  password?: string
+  roleId: string
+  description?: string
+}
+
+// API 鍑芥暟
+export const employeeApi = {
+  // 鑾峰彇鎵�鏈夊憳宸�
+  async getEmployees(): Promise<Employee[]> {
+    try {
+      const response = await fetch('http://localhost:8080/api/graphql', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          query: EMPLOYEE_QUERIES.GET_EMPLOYEES
+        })
+      })
+      const result = await response.json()
+      if (result.errors) {
+        throw new Error(result.errors[0].message)
+      }
+      return result.data?.employees || []
+    } catch (error: any) {
+      throw new Error(error.message || '鑾峰彇鍛樺伐鍒楄〃澶辫触')
+    }
+  },
+
+  // 鏍规嵁鍚嶇О鎼滅储鍛樺伐
+  async searchEmployees(name?: string): Promise<Employee[]> {
+    try {
+      const response = await fetch('http://localhost:8080/api/graphql', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          query: EMPLOYEE_QUERIES.SEARCH_EMPLOYEES,
+          variables: { name }
+        })
+      })
+      const result = await response.json()
+      if (result.errors) {
+        throw new Error(result.errors[0].message)
+      }
+      return result.data?.employeesByName || []
+    } catch (error: any) {
+      throw new Error(error.message || '鎼滅储鍛樺伐澶辫触')
+    }
+  },
+
+  // 鑾峰彇鍛樺伐璇︽儏
+  async getEmployee(id: string): Promise<Employee | null> {
+    try {
+      const response = await fetch('http://localhost:8080/api/graphql', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          query: EMPLOYEE_QUERIES.GET_EMPLOYEE,
+          variables: { id }
+        })
+      })
+      const result = await response.json()
+      if (result.errors) {
+        throw new Error(result.errors[0].message)
+      }
+      return result.data?.employee || null
+    } catch (error: any) {
+      throw new Error(error.message || '鑾峰彇鍛樺伐璇︽儏澶辫触')
+    }
+  },
+
+  // 淇濆瓨鍛樺伐
+  async saveEmployee(input: EmployeeInput): Promise<Employee> {
+    try {
+      const response = await fetch('http://localhost:8080/api/graphql', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          query: EMPLOYEE_MUTATIONS.SAVE_EMPLOYEE,
+          variables: { input }
+        })
+      })
+      const result = await response.json()
+      if (result.errors) {
+        throw new Error(result.errors[0].message)
+      }
+      return result.data?.saveEmployee
+    } catch (error: any) {
+      throw new Error(error.message || '淇濆瓨鍛樺伐澶辫触')
+    }
+  },
+
+  // 鍒犻櫎鍛樺伐
+  async deleteEmployee(id: string): Promise<boolean> {
+    try {
+      const response = await fetch('http://localhost:8080/api/graphql', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          query: EMPLOYEE_MUTATIONS.DELETE_EMPLOYEE,
+          variables: { id }
+        })
+      })
+      const result = await response.json()
+      if (result.errors) {
+        throw new Error(result.errors[0].message)
+      }
+      return result.data?.deleteEmployee || false
+    } catch (error: any) {
+      throw new Error(error.message || '鍒犻櫎鍛樺伐澶辫触')
+    }
+  }
+}
\ No newline at end of file
diff --git a/web/src/api/mockData.js b/web/src/api/mockData.js
new file mode 100644
index 0000000..e8e5556
--- /dev/null
+++ b/web/src/api/mockData.js
@@ -0,0 +1,125 @@
+// 妯℃嫙鏁版嵁锛岀敤浜庢祴璇曡瘎鍒嗘祦绋�
+
+// 妯℃嫙閫夋墜璇︽儏鏁版嵁
+export const mockActivityPlayerDetail = {
+  id: "1",
+  playerInfo: {
+    id: "1",
+    name: "寮犱笁",
+    phone: "13800138000",
+    description: "璁$畻鏈轰笓涓氬鐢燂紝鎿呴暱鍓嶇寮�鍙�",
+    avatarUrl: "https://via.placeholder.com/100x100"
+  },
+  activityName: "2024骞寸紪绋嬪ぇ璧�",
+  description: "鍩轰簬Vue.js鐨勫湪绾垮涔犲钩鍙伴」鐩�",
+  submissionFiles: [
+    {
+      id: "1",
+      name: "椤圭洰婕旂ず瑙嗛.mp4",
+      url: "https://example.com/demo.mp4",
+      fileExt: "mp4",
+      fileSize: 52428800,
+      mediaType: "video"
+    },
+    {
+      id: "2", 
+      name: "椤圭洰婧愮爜.zip",
+      url: "https://example.com/source.zip",
+      fileExt: "zip",
+      fileSize: 10485760,
+      mediaType: "file"
+    }
+  ]
+}
+
+// 妯℃嫙璇勫垎妯℃澘鏁版嵁
+export const mockRatingScheme = {
+  schemeId: "1",
+  schemeName: "缂栫▼澶ц禌璇勫垎鏍囧噯",
+  items: [
+    {
+      id: "1",
+      name: "浠g爜璐ㄩ噺",
+      maxScore: 30,
+      orderNo: 1
+    },
+    {
+      id: "2", 
+      name: "鍔熻兘瀹屾暣鎬�",
+      maxScore: 25,
+      orderNo: 2
+    },
+    {
+      id: "3",
+      name: "鐢ㄦ埛浣撻獙",
+      maxScore: 20,
+      orderNo: 3
+    },
+    {
+      id: "4",
+      name: "鍒涙柊鎬�",
+      maxScore: 15,
+      orderNo: 4
+    },
+    {
+      id: "5",
+      name: "椤圭洰灞曠ず",
+      maxScore: 10,
+      orderNo: 5
+    }
+  ],
+  totalMaxScore: 100
+}
+
+// 妯℃嫙褰撳墠璇勫淇℃伅
+export const mockCurrentJudgeInfo = {
+  id: "1",
+  name: "鏉庤�佸笀",
+  phone: "13900139000", 
+  description: "楂樼骇杞欢宸ョ▼甯堬紝10骞村紑鍙戠粡楠�"
+}
+
+// 妯℃嫙鎵�鏈夎瘎濮旇瘎鍒嗙姸鎬�
+export const mockJudgeRatings = [
+  {
+    judgeId: "1",
+    judgeName: "鏉庤�佸笀",
+    totalScore: 0,
+    status: 0, // 0-鏈瘎鍒嗭紝1-宸茶瘎鍒�
+    isCurrentJudge: true
+  },
+  {
+    judgeId: "2",
+    judgeName: "鐜嬫暀鎺�", 
+    totalScore: 85,
+    status: 1,
+    isCurrentJudge: false
+  },
+  {
+    judgeId: "3",
+    judgeName: "闄堜笓瀹�",
+    totalScore: 78,
+    status: 1,
+    isCurrentJudge: false
+  },
+  {
+    judgeId: "4",
+    judgeName: "鍒樺崥澹�",
+    totalScore: 0,
+    status: 0,
+    isCurrentJudge: false
+  }
+]
+
+// 妯℃嫙褰撳墠璇勫鐨勮瘎鍒嗭紙濡傛灉宸茶瘎鍒嗭級
+export const mockCurrentJudgeRating = null // 鍒濆涓簄ull锛岃〃绀烘湭璇勫垎
+
+// 妯℃嫙骞冲潎鍒�
+export const mockAverageScore = 81.5 // (85 + 78) / 2
+
+// 妯℃嫙API鍝嶅簲鏍煎紡
+export function createMockResponse(data) {
+  return {
+    data: data
+  }
+}
\ No newline at end of file
diff --git a/web/src/api/player.js b/web/src/api/player.js
index 1006ec6..a1ada54 100644
--- a/web/src/api/player.js
+++ b/web/src/api/player.js
@@ -16,16 +16,16 @@
 }
 
 const GET_APPLICATIONS = `
-  query GetApplications($name: String, $page: Int, $size: Int) {
-    activityPlayerApplications(name: $name, page: $page, size: $size) {
+  query GetApplications($name: String, $activityId: ID, $page: Int, $size: Int) {
+    activityPlayerApplications(name: $name, activityId: $activityId, page: $page, size: $size) {
       id playerName activityName phone applyTime state
     }
   }
 `
 
 export const PlayerApi = {
-  getApplications: async (name, page, size) => {
-    const data = await graphqlRequest(GET_APPLICATIONS, { name, page, size })
+  getApplications: async (name, activityId, page, size) => {
+    const data = await graphqlRequest(GET_APPLICATIONS, { name, activityId, page, size })
     return data.activityPlayerApplications || []
   }
 }
\ No newline at end of file
diff --git a/web/src/api/role.ts b/web/src/api/role.ts
new file mode 100644
index 0000000..46aed90
--- /dev/null
+++ b/web/src/api/role.ts
@@ -0,0 +1,244 @@
+// 瑙掕壊绠$悊API
+
+// 瑙掕壊鐩稿叧鐨� GraphQL 鏌ヨ
+export const ROLE_QUERIES = {
+  // 鑾峰彇鎵�鏈夎鑹�
+  GET_ROLES: `
+    query GetRoles {
+      roles {
+        id
+        code
+        name
+        description
+        state
+        createTime
+        updateTime
+      }
+    }
+  `,
+  
+  // 鑾峰彇鎵�鏈夊惎鐢ㄧ姸鎬佺殑瑙掕壊
+  GET_ACTIVE_ROLES: `
+    query GetActiveRoles {
+      activeRoles {
+        id
+        code
+        name
+        description
+        state
+        createTime
+        updateTime
+      }
+    }
+  `,
+  
+  // 鏍规嵁ID鑾峰彇瑙掕壊璇︽儏
+  GET_ROLE: `
+    query GetRole($id: Long!) {
+      role(id: $id) {
+        id
+        code
+        name
+        description
+        state
+        createTime
+        updateTime
+      }
+    }
+  `,
+  
+  // 鏍规嵁瑙掕壊浠g爜鑾峰彇瑙掕壊
+  GET_ROLE_BY_CODE: `
+    query GetRoleByCode($code: String!) {
+      roleByCode(code: $code) {
+        id
+        code
+        name
+        description
+        state
+        createTime
+        updateTime
+      }
+    }
+  `,
+  
+  // 鏍规嵁鐘舵�佽幏鍙栬鑹�
+  GET_ROLES_BY_STATE: `
+    query GetRolesByState($state: Int!) {
+      rolesByState(state: $state) {
+        id
+        code
+        name
+        description
+        state
+        createTime
+        updateTime
+      }
+    }
+  `,
+  
+  // 鏍规嵁鍚嶇О妯$硦鏌ヨ瑙掕壊
+  GET_ROLES_BY_NAME: `
+    query GetRolesByName($name: String!) {
+      rolesByName(name: $name) {
+        id
+        code
+        name
+        description
+        state
+        createTime
+        updateTime
+      }
+    }
+  `
+}
+
+// 绫诲瀷瀹氫箟
+export interface Role {
+  id: string
+  code: string
+  name: string
+  description?: string
+  state: number
+  createTime?: string
+  updateTime?: string
+}
+
+// API 鍑芥暟
+export const roleApi = {
+  // 鑾峰彇鎵�鏈夎鑹�
+  async getRoles(): Promise<Role[]> {
+    try {
+      const response = await fetch('http://localhost:8080/api/graphql', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          query: ROLE_QUERIES.GET_ROLES
+        })
+      })
+      const result = await response.json()
+      if (result.errors) {
+        throw new Error(result.errors[0].message)
+      }
+      return result.data?.roles || []
+    } catch (error: any) {
+      throw new Error(error.message || '鑾峰彇瑙掕壊鍒楄〃澶辫触')
+    }
+  },
+
+  // 鑾峰彇鎵�鏈夊惎鐢ㄧ姸鎬佺殑瑙掕壊
+  async getActiveRoles(): Promise<Role[]> {
+    try {
+      const response = await fetch('http://localhost:8080/api/graphql', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          query: ROLE_QUERIES.GET_ACTIVE_ROLES
+        })
+      })
+      const result = await response.json()
+      if (result.errors) {
+        throw new Error(result.errors[0].message)
+      }
+      return result.data?.activeRoles || []
+    } catch (error: any) {
+      throw new Error(error.message || '鑾峰彇鍚敤瑙掕壊鍒楄〃澶辫触')
+    }
+  },
+
+  // 鏍规嵁ID鑾峰彇瑙掕壊璇︽儏
+  async getRoleById(id: string): Promise<Role | null> {
+    try {
+      const response = await fetch('http://localhost:8080/api/graphql', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          query: ROLE_QUERIES.GET_ROLE,
+          variables: { id }
+        })
+      })
+      const result = await response.json()
+      if (result.errors) {
+        throw new Error(result.errors[0].message)
+      }
+      return result.data?.role || null
+    } catch (error: any) {
+      throw new Error(error.message || '鑾峰彇瑙掕壊璇︽儏澶辫触')
+    }
+  },
+
+  // 鏍规嵁瑙掕壊浠g爜鑾峰彇瑙掕壊
+  async getRoleByCode(code: string): Promise<Role | null> {
+    try {
+      const response = await fetch('http://localhost:8080/api/graphql', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          query: ROLE_QUERIES.GET_ROLE_BY_CODE,
+          variables: { code }
+        })
+      })
+      const result = await response.json()
+      if (result.errors) {
+        throw new Error(result.errors[0].message)
+      }
+      return result.data?.roleByCode || null
+    } catch (error: any) {
+      throw new Error(error.message || '鏍规嵁浠g爜鑾峰彇瑙掕壊澶辫触')
+    }
+  },
+
+  // 鏍规嵁鐘舵�佽幏鍙栬鑹�
+  async getRolesByState(state: number): Promise<Role[]> {
+    try {
+      const response = await fetch('http://localhost:8080/api/graphql', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          query: ROLE_QUERIES.GET_ROLES_BY_STATE,
+          variables: { state }
+        })
+      })
+      const result = await response.json()
+      if (result.errors) {
+        throw new Error(result.errors[0].message)
+      }
+      return result.data?.rolesByState || []
+    } catch (error: any) {
+      throw new Error(error.message || '鏍规嵁鐘舵�佽幏鍙栬鑹插け璐�')
+    }
+  },
+
+  // 鏍规嵁鍚嶇О妯$硦鏌ヨ瑙掕壊
+  async searchRolesByName(name: string): Promise<Role[]> {
+    try {
+      const response = await fetch('http://localhost:8080/api/graphql', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify({
+          query: ROLE_QUERIES.GET_ROLES_BY_NAME,
+          variables: { name }
+        })
+      })
+      const result = await response.json()
+      if (result.errors) {
+        throw new Error(result.errors[0].message)
+      }
+      return result.data?.rolesByName || []
+    } catch (error: any) {
+      throw new Error(error.message || '鏍规嵁鍚嶇О鎼滅储瑙掕壊澶辫触')
+    }
+  }
+}
\ No newline at end of file
diff --git a/web/src/components/JudgeFormSimple.vue b/web/src/components/JudgeFormSimple.vue
index ce26bd9..6445dc7 100644
--- a/web/src/components/JudgeFormSimple.vue
+++ b/web/src/components/JudgeFormSimple.vue
@@ -114,6 +114,7 @@
 import { getMediasByTarget, deleteMedia, uploadFile } from '@/api/media'
 import type { Judge, JudgeInput, Tag } from '@/api/graphql'
 import type { Media } from '@/api/media'
+import { MediaTargetType } from '@/constants/mediaTargetType'
 
 interface Props {
   modelValue: boolean
@@ -198,7 +199,7 @@
       try {
         console.log('=== 鍔犺浇璇勫濯掍綋 ===');
         console.log('璇勫ID:', data.id);
-        const medias = await getMediasByTarget(1, parseInt(data.id))
+        const medias = await getMediasByTarget(MediaTargetType.JUDGE_AVATAR, parseInt(data.id))
         console.log('鑾峰彇鍒扮殑濯掍綋鍒楄〃:', medias);
         
         // 鍙彇绗竴涓浘鐗囦綔涓哄ご鍍忥紙璇勫鍙兘鏈変竴涓ご鍍忥級
@@ -269,7 +270,7 @@
         fileSize: uploadResult.fileSize,
         fileExt: uploadResult.fileName.split('.').pop() || 'jpg',
         mediaType: 1, // 1琛ㄧず鍥剧墖
-        targetType: 1, // 1琛ㄧず璇勫
+        targetType: MediaTargetType.JUDGE_AVATAR, // 璇勫澶村儚
         targetId: parseInt(judgeId)
       });
       
diff --git a/web/src/components/RatingForm.vue b/web/src/components/RatingForm.vue
index 4437203..bc3e575 100644
--- a/web/src/components/RatingForm.vue
+++ b/web/src/components/RatingForm.vue
@@ -2,8 +2,52 @@
   <div class="rating-form">
     <div class="form-header">
       <h3>{{ ratingForm.schemeName || '璇勫垎琛ㄥ崟' }}</h3>
-      <div class="total-score">
-        鎬诲垎锛歿{ totalScore }} / {{ ratingForm.totalMaxScore }}
+      <div class="header-info">
+        <div class="judge-info">
+          <el-tag type="primary" size="large">
+            <el-icon><User /></el-icon>
+            褰撳墠璇勫锛歿{ currentJudgeName || '鏈煡璇勫' }}
+          </el-tag>
+        </div>
+        <div class="total-score">
+          鎬诲垎锛歿{ totalScore }} / {{ ratingForm.totalMaxScore }}
+        </div>
+      </div>
+    </div>
+    
+    <!-- 澶氳瘎濮旇瘎鍒嗙姸鎬� -->
+    <div v-if="judgeRatings && judgeRatings.length > 0" class="judge-ratings-status">
+      <h4>璇勫璇勫垎鐘舵��</h4>
+      <div class="judge-status-list">
+        <div 
+          v-for="judgeRating in judgeRatings" 
+          :key="judgeRating.judgeId"
+          class="judge-status-item"
+          :class="{ 'current-judge': judgeRating.isCurrentJudge }"
+        >
+          <div class="judge-name">
+            <el-icon v-if="judgeRating.isCurrentJudge"><Star /></el-icon>
+            {{ judgeRating.judgeName }}
+          </div>
+          <div class="judge-score">
+            <el-tag 
+              :type="judgeRating.status === 1 ? 'success' : 'info'"
+              size="small"
+            >
+              {{ judgeRating.status === 1 ? `宸茶瘎鍒�: ${judgeRating.totalScore}鍒哷 : '鏈瘎鍒�' }}
+            </el-tag>
+          </div>
+        </div>
+      </div>
+      
+      <!-- 骞冲潎鍒嗘樉绀� -->
+      <div v-if="averageScore !== null" class="average-score">
+        <el-statistic 
+          title="褰撳墠骞冲潎鍒�" 
+          :value="averageScore" 
+          :precision="2"
+          suffix="鍒�"
+        />
       </div>
     </div>
     
@@ -82,7 +126,8 @@
 
 <script setup>
 import { ref, reactive, computed, watch } from 'vue'
-import { ElForm, ElFormItem, ElInputNumber, ElInput, ElButton, ElMessage } from 'element-plus'
+import { ElForm, ElFormItem, ElInputNumber, ElInput, ElButton, ElMessage, ElTag, ElIcon, ElStatistic } from 'element-plus'
+import { User, Star } from '@element-plus/icons-vue'
 
 const props = defineProps({
   ratingForm: {
@@ -92,6 +137,26 @@
   activityPlayerId: {
     type: [String, Number],
     required: true
+  },
+  // 鏂板锛氬綋鍓嶈瘎濮斾俊鎭�
+  currentJudgeName: {
+    type: String,
+    default: ''
+  },
+  // 鏂板锛氭墍鏈夎瘎濮旇瘎鍒嗙姸鎬�
+  judgeRatings: {
+    type: Array,
+    default: () => []
+  },
+  // 鏂板锛氬钩鍧囧垎
+  averageScore: {
+    type: Number,
+    default: null
+  },
+  // 鏂板锛氬綋鍓嶈瘎濮旂殑宸叉湁璇勫垎
+  existingRating: {
+    type: Object,
+    default: null
   }
 })
 
@@ -110,8 +175,19 @@
 const initScores = () => {
   if (props.ratingForm.items) {
     props.ratingForm.items.forEach(item => {
-      formData.scores[item.id] = null
+      // 濡傛灉鏈夊凡鏈夎瘎鍒嗭紝鍒欏姞杞藉凡鏈夊垎鏁�
+      if (props.existingRating && props.existingRating.items) {
+        const existingItem = props.existingRating.items.find(ratingItem => ratingItem.ratingItemId === item.id)
+        formData.scores[item.id] = existingItem ? existingItem.score : null
+      } else {
+        formData.scores[item.id] = null
+      }
     })
+  }
+  
+  // 鍔犺浇宸叉湁璇勮
+  if (props.existingRating && props.existingRating.remark) {
+    formData.comment = props.existingRating.remark
   }
 }
 
@@ -185,6 +261,11 @@
 watch(() => props.ratingForm, () => {
   initScores()
 }, { immediate: true })
+
+// 鐩戝惉宸叉湁璇勫垎鍙樺寲锛岄噸鏂板垵濮嬪寲
+watch(() => props.existingRating, () => {
+  initScores()
+}, { immediate: true })
 </script>
 
 <style scoped>
@@ -196,19 +277,29 @@
 }
 
 .form-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
   margin-bottom: 20px;
   padding-bottom: 16px;
   border-bottom: 1px solid #EBEEF5;
 }
 
 .form-header h3 {
-  margin: 0;
+  margin: 0 0 12px 0;
   color: #303133;
   font-size: 18px;
   font-weight: 600;
+}
+
+.header-info {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  flex-wrap: wrap;
+  gap: 12px;
+}
+
+.judge-info {
+  display: flex;
+  align-items: center;
 }
 
 .total-score {
@@ -220,6 +311,69 @@
   border-radius: 20px;
 }
 
+.judge-ratings-status {
+  margin-bottom: 24px;
+  padding: 16px;
+  background: #F8F9FA;
+  border-radius: 8px;
+  border: 1px solid #E9ECEF;
+}
+
+.judge-ratings-status h4 {
+  margin: 0 0 16px 0;
+  color: #303133;
+  font-size: 16px;
+  font-weight: 600;
+}
+
+.judge-status-list {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+  gap: 12px;
+  margin-bottom: 16px;
+}
+
+.judge-status-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 12px;
+  background: white;
+  border-radius: 6px;
+  border: 1px solid #E4E7ED;
+  transition: all 0.3s ease;
+}
+
+.judge-status-item:hover {
+  border-color: #409EFF;
+  box-shadow: 0 2px 4px rgba(64, 158, 255, 0.1);
+}
+
+.judge-status-item.current-judge {
+  border-color: #409EFF;
+  background: #ECF5FF;
+}
+
+.judge-name {
+  display: flex;
+  align-items: center;
+  gap: 6px;
+  font-weight: 500;
+  color: #303133;
+}
+
+.judge-score {
+  flex-shrink: 0;
+}
+
+.average-score {
+  text-align: center;
+  padding: 16px;
+  background: white;
+  border-radius: 6px;
+  border: 1px solid #E4E7ED;
+}
+
 .rating-items {
   margin-bottom: 20px;
 }
diff --git a/web/src/constants/mediaTargetType.ts b/web/src/constants/mediaTargetType.ts
new file mode 100644
index 0000000..d19fadd
--- /dev/null
+++ b/web/src/constants/mediaTargetType.ts
@@ -0,0 +1,26 @@
+/**
+ * 濯掍綋鐩爣绫诲瀷鏋氫妇
+ * 涓庡悗绔� MediaTargetType 鏋氫妇淇濇寔涓�鑷�
+ */
+export const MediaTargetType = {
+  JUDGE_AVATAR: 1,           // 璇勫澶村儚
+  ACTIVITY: 2,               // 娲诲姩
+  CAROUSEL: 4,               // 杞挱鍥�
+  ACTIVITY_PLAYER_SUBMISSION: 5,  // 鍙傝禌鎶ュ悕璧勬枡
+  STUDENT_AVATAR: 6,         // 瀛﹀憳澶村儚
+  USER_AVATAR: 7             // 鐢ㄦ埛澶村儚
+} as const;
+
+export type MediaTargetTypeValue = typeof MediaTargetType[keyof typeof MediaTargetType];
+
+/**
+ * 濯掍綋鐩爣绫诲瀷鎻忚堪
+ */
+export const MediaTargetTypeLabels = {
+  [MediaTargetType.JUDGE_AVATAR]: '璇勫澶村儚',
+  [MediaTargetType.ACTIVITY]: '娲诲姩',
+  [MediaTargetType.CAROUSEL]: '杞挱鍥�',
+  [MediaTargetType.ACTIVITY_PLAYER_SUBMISSION]: '鍙傝禌鎶ュ悕璧勬枡',
+  [MediaTargetType.STUDENT_AVATAR]: '瀛﹀憳澶村儚',
+  [MediaTargetType.USER_AVATAR]: '鐢ㄦ埛澶村儚'
+} as const;
\ No newline at end of file
diff --git a/web/src/views/ActivityForm.vue b/web/src/views/ActivityForm.vue
index eb584ee..7d972bd 100644
--- a/web/src/views/ActivityForm.vue
+++ b/web/src/views/ActivityForm.vue
@@ -447,6 +447,7 @@
 import { getMediasByTarget, saveMedia, uploadFile } from '@/api/media'
 import { getAllRatingSchemes } from '@/api/rating'
 import { getAllJudges } from '@/api/judge'
+import { MediaTargetType } from '@/constants/mediaTargetType'
 
 const router = useRouter()
 const route = useRoute()
@@ -607,7 +608,7 @@
       }
       // 鍔犺浇骞跺洖濉凡涓婁紶濯掍綋锛歵argetType=2 鍋囪涓衡�滄椿鍔ㄢ�濓紝濡備笉鍚岃璋冩暣
       try {
-        const medias = await getMediasByTarget(2, parseInt(activity.id))
+        const medias = await getMediasByTarget(MediaTargetType.ACTIVITY, parseInt(activity.id))
         console.log('=== 鍔犺浇娲诲姩濯掍綋璋冭瘯淇℃伅 ===')
         console.log('娲诲姩ID:', activity.id)
         console.log('鑾峰彇鍒扮殑濯掍綋鏁版嵁:', medias)
@@ -1027,7 +1028,7 @@
           fileSize: uploadResult.fileSize || mediaFile.file.size,
           fileExt: uploadResult.fileName ? uploadResult.fileName.split('.').pop() : mediaFile.name.split('.').pop() || 'jpg',
           mediaType: mediaFile.type === 'video' ? 2 : 1, // 1=鍥剧墖, 2=瑙嗛
-          targetType: 2, // 2=娲诲姩
+          targetType: MediaTargetType.ACTIVITY, // 娲诲姩
           targetId: parseInt(activityId) // 杞崲涓烘暟瀛楃被鍨�
         }
         
diff --git a/web/src/views/activity-player/rating.vue b/web/src/views/activity-player/rating.vue
index d21ea7b..d6aa53a 100644
--- a/web/src/views/activity-player/rating.vue
+++ b/web/src/views/activity-player/rating.vue
@@ -30,9 +30,13 @@
       <!-- 鍙充晶闈㈡澘锛氳瘎鍒嗚〃鍗� -->
       <div class="right-panel">
         <RatingForm 
-          v-if="detail.ratingForm"
-          :rating-form="detail.ratingForm"
+          v-if="ratingScheme"
+          :rating-form="ratingScheme"
           :activity-player-id="detail.id"
+          :current-judge-name="currentJudgeInfo?.name"
+          :judge-ratings="judgeRatings"
+          :average-score="averageScore"
+          :existing-rating="currentJudgeRating"
           @submit="handleRatingSubmit"
         />
         <div v-else class="no-rating">
@@ -51,7 +55,14 @@
 import { ref, onMounted } from 'vue'
 import { useRoute } from 'vue-router'
 import { ElMessage, ElSkeleton, ElEmpty } from 'element-plus'
-import { getActivityPlayerDetail, saveActivityPlayerRating } from '@/api/activityPlayer'
+import { 
+  getActivityPlayerDetail, 
+  saveActivityPlayerRating,
+  getJudgeRatingsForPlayer,
+  getCurrentJudgeRating,
+  getAverageScoreForPlayer,
+  getCurrentJudgeInfo
+} from '@/api/activityPlayer'
 import PlayerInfoCard from '@/components/PlayerInfoCard.vue'
 import SubmissionFiles from '@/components/SubmissionFiles.vue'
 import RatingForm from '@/components/RatingForm.vue'
@@ -59,16 +70,97 @@
 const route = useRoute()
 const loading = ref(true)
 const detail = ref(null)
+const ratingScheme = ref(null)
+const currentJudgeInfo = ref(null)
+const judgeRatings = ref([])
+const currentJudgeRating = ref(null)
+const averageScore = ref(0)
 
 const loadDetail = async () => {
   try {
     loading.value = true
-    const id = route.params.id
-    const response = await getActivityPlayerDetail(id)
+    const response = await getActivityPlayerDetail(route.params.id)
+    console.log('API鍝嶅簲:', response)
+    
+    // 妫�鏌ュ搷搴旀暟鎹粨鏋�
+    if (!response) {
+      throw new Error('API鍝嶅簲鏁版嵁涓虹┖')
+    }
+    
+    if (!response.activityPlayerDetail) {
+      throw new Error('鏈壘鍒伴�夋墜璇︽儏鏁版嵁')
+    }
+    
     detail.value = response.activityPlayerDetail
+    
+    // 浣跨敤浠庡悗绔幏鍙栫殑鐪熷疄璇勫垎妯℃澘鏁版嵁
+    if (detail.value.ratingForm) {
+      ratingScheme.value = {
+        schemeId: detail.value.ratingForm.schemeId,
+        schemeName: detail.value.ratingForm.schemeName,
+        items: detail.value.ratingForm.items || [],
+        totalMaxScore: detail.value.ratingForm.totalMaxScore || 0
+      }
+      console.log('浣跨敤鐪熷疄璇勫垎妯℃澘鏁版嵁:', ratingScheme.value)
+    } else {
+      console.warn('鏈壘鍒拌瘎鍒嗘ā鏉挎暟鎹紝浣跨敤榛樿妯℃澘')
+      // 濡傛灉娌℃湁璇勫垎妯℃澘鏁版嵁锛屼娇鐢ㄩ粯璁ゆā鏉�
+      ratingScheme.value = {
+        schemeId: "1",
+        schemeName: "榛樿璇勫垎鏍囧噯",
+        items: [
+          { id: "1", name: "缁煎悎璇勫垎", maxScore: 100, orderNo: 1 }
+        ],
+        totalMaxScore: 100
+      }
+    }
+
+    // 鑾峰彇褰撳墠璇勫淇℃伅
+    try {
+      const judgeInfoResponse = await getCurrentJudgeInfo()
+      console.log('璇勫淇℃伅鍝嶅簲:', judgeInfoResponse)
+      if (judgeInfoResponse && judgeInfoResponse.currentJudgeInfo) {
+        currentJudgeInfo.value = judgeInfoResponse.currentJudgeInfo
+      }
+    } catch (error) {
+      console.error('鑾峰彇璇勫淇℃伅澶辫触:', error)
+    }
+
+    // 鑾峰彇鎵�鏈夎瘎濮旇瘎鍒嗙姸鎬�
+    try {
+      const judgeRatingsResponse = await getJudgeRatingsForPlayer(route.params.id)
+      console.log('璇勫璇勫垎鐘舵�佸搷搴�:', judgeRatingsResponse)
+      if (judgeRatingsResponse && judgeRatingsResponse.judgeRatingsForPlayer) {
+        judgeRatings.value = judgeRatingsResponse.judgeRatingsForPlayer
+      }
+    } catch (error) {
+      console.error('鑾峰彇璇勫璇勫垎鐘舵�佸け璐�:', error)
+    }
+
+    // 鑾峰彇褰撳墠璇勫鐨勮瘎鍒�
+    try {
+      const currentRatingResponse = await getCurrentJudgeRating(route.params.id)
+      console.log('褰撳墠璇勫璇勫垎鍝嶅簲:', currentRatingResponse)
+      if (currentRatingResponse && currentRatingResponse.currentJudgeRating) {
+        currentJudgeRating.value = currentRatingResponse.currentJudgeRating
+      }
+    } catch (error) {
+      console.error('鑾峰彇褰撳墠璇勫璇勫垎澶辫触:', error)
+    }
+
+    // 鑾峰彇骞冲潎鍒�
+    try {
+      const averageScoreResponse = await getAverageScoreForPlayer(route.params.id)
+      console.log('骞冲潎鍒嗗搷搴�:', averageScoreResponse)
+      if (averageScoreResponse && averageScoreResponse.averageScoreForPlayer !== undefined) {
+        averageScore.value = averageScoreResponse.averageScoreForPlayer
+      }
+    } catch (error) {
+      console.error('鑾峰彇骞冲潎鍒嗗け璐�:', error)
+    }
   } catch (error) {
-    console.error('鍔犺浇鎶ュ悕璇︽儏澶辫触:', error)
-    ElMessage.error('鍔犺浇鎶ュ悕璇︽儏澶辫触')
+    console.error('鍔犺浇璇︽儏澶辫触:', error)
+    ElMessage.error('鍔犺浇璇︽儏澶辫触')
   } finally {
     loading.value = false
   }
@@ -78,13 +170,15 @@
   try {
     console.log('璇勫垎鎻愪氦:', ratingData)
     
-    // 鏋勯�犳彁浜ゆ暟鎹�
+    // 鏋勯�犳彁浜ゆ暟鎹� - 灏� scores 瀵硅薄杞崲涓� ratings 鏁扮粍
+    const ratings = Object.entries(ratingData.scores || {}).map(([itemId, score]) => ({
+      itemId: parseInt(itemId),
+      score: score
+    }))
+    
     const input = {
       activityPlayerId: detail.value.id,
-      ratings: ratingData.ratings.map(item => ({
-        itemId: item.itemId,
-        score: item.score
-      })),
+      ratings: ratings,
       comment: ratingData.comment || ''
     }
     
@@ -93,6 +187,9 @@
     
     if (result.saveActivityPlayerRating) {
       ElMessage.success('璇勫垎鎻愪氦鎴愬姛')
+      
+      // 閲嶆柊鍔犺浇鏁版嵁浠ユ洿鏂拌瘎鍒嗙姸鎬�
+      await loadDetail()
     } else {
       ElMessage.error('璇勫垎鎻愪氦澶辫触')
     }
diff --git a/web/src/views/carousel/CarouselForm.vue b/web/src/views/carousel/CarouselForm.vue
index c70e63a..d6d030b 100644
--- a/web/src/views/carousel/CarouselForm.vue
+++ b/web/src/views/carousel/CarouselForm.vue
@@ -146,6 +146,7 @@
 import { Plus } from '@element-plus/icons-vue'
 import { CarouselApi } from '@/api/carousel'
 import { getMediasByTarget, deleteMedia, uploadFile } from '@/api/media'
+import { MediaTargetType } from '@/constants/mediaTargetType'
 
 const props = defineProps({
   modelValue: Boolean,
@@ -196,7 +197,7 @@
       try {
         console.log('=== 鍔犺浇杞挱鍥惧獟浣� ===');
         console.log('杞挱鍥綢D:', data.id);
-        const medias = await getMediasByTarget(4, parseInt(data.id))
+        const medias = await getMediasByTarget(MediaTargetType.CAROUSEL, parseInt(data.id))
         console.log('鑾峰彇鍒扮殑濯掍綋鍒楄〃:', medias);
         
         // 杞崲濯掍綋鏁版嵁鏍煎紡锛屾爣璁颁负宸插瓨鍦ㄧ殑鏂囦欢
@@ -282,7 +283,7 @@
           fileSize: uploadResult.fileSize,
           fileExt: uploadResult.fileName.split('.').pop() || 'jpg',
           mediaType: isVideo(media) ? 2 : 1, // 1琛ㄧず鍥剧墖锛�2琛ㄧず瑙嗛
-          targetType: 4, // 4琛ㄧず杞挱鍥�
+          targetType: MediaTargetType.CAROUSEL, // 杞挱鍥�
           targetId: parseInt(carouselId)
         });
         
diff --git a/web/src/views/carousel/index.vue b/web/src/views/carousel/index.vue
index 9c417aa..ded5219 100644
--- a/web/src/views/carousel/index.vue
+++ b/web/src/views/carousel/index.vue
@@ -196,6 +196,7 @@
 import { Plus } from '@element-plus/icons-vue'
 import { CarouselApi } from '@/api/carousel'
 import { uploadFile, getMediasByTarget, saveMedia, deleteMedia } from '@/api/media'
+import { MediaTargetType } from '@/constants/mediaTargetType'
 
 // 鍝嶅簲寮忔暟鎹�
 const loading = ref(false)
@@ -395,7 +396,7 @@
 })
 
 // 鍔犺浇濯掍綋鍒楄〃锛圱argetType 绾﹀畾锛歝arousel锛�
-const CAROUSEL_TARGET_TYPE = 4 // 鍚庣浠g爜涓娇鐢ㄧ殑鏄� targetType=4
+const CAROUSEL_TARGET_TYPE = MediaTargetType.CAROUSEL // 杞挱鍥剧被鍨�
 const loadMedias = async () => {
   if (!formData.id) return
   try {
diff --git a/web/src/views/employee/EmployeeForm.vue b/web/src/views/employee/EmployeeForm.vue
new file mode 100644
index 0000000..d5151f8
--- /dev/null
+++ b/web/src/views/employee/EmployeeForm.vue
@@ -0,0 +1,267 @@
+<template>
+  <el-dialog
+    v-model="visible"
+    :title="isEdit ? '缂栬緫鍛樺伐' : '鏂板鍛樺伐'"
+    width="600px"
+    :before-close="handleClose"
+  >
+    <el-form
+      ref="formRef"
+      :model="form"
+      :rules="rules"
+      label-width="100px"
+      label-position="left"
+    >
+      <el-form-item label="鍛樺伐濮撳悕" prop="name">
+        <el-input 
+          v-model="form.name" 
+          placeholder="璇疯緭鍏ュ憳宸ュ鍚�"
+          maxlength="50"
+          show-word-limit
+        />
+      </el-form-item>
+
+      <el-form-item label="鑱旂郴鐢佃瘽" prop="phone">
+        <el-input 
+          v-model="form.phone" 
+          placeholder="璇疯緭鍏�11浣嶆墜鏈哄彿鐮�"
+          maxlength="11"
+        />
+      </el-form-item>
+
+      <el-form-item label="鐧诲綍瀵嗙爜" prop="password" v-if="!isEdit">
+        <el-input 
+          v-model="form.password" 
+          type="password"
+          placeholder="璇疯緭鍏ョ櫥褰曞瘑鐮侊紙6-20浣嶏級"
+          maxlength="20"
+          show-password
+        />
+      </el-form-item>
+
+      <el-form-item label="閲嶇疆瀵嗙爜" prop="password" v-if="isEdit">
+        <el-input 
+          v-model="form.password" 
+          type="password"
+          placeholder="鐣欑┖鍒欎笉淇敼瀵嗙爜"
+          maxlength="20"
+          show-password
+        />
+      </el-form-item>
+
+      <el-form-item label="鍛樺伐瑙掕壊" prop="roleId">
+        <el-select 
+          v-model="form.roleId" 
+          placeholder="璇烽�夋嫨鍛樺伐瑙掕壊"
+          style="width: 100%"
+          :loading="rolesLoading"
+        >
+          <el-option 
+            v-for="role in roles" 
+            :key="role.id" 
+            :label="role.name" 
+            :value="role.code" 
+          />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="鍛樺伐鎻忚堪" prop="description">
+        <el-input
+          v-model="form.description"
+          type="textarea"
+          :rows="4"
+          placeholder="璇疯緭鍏ュ憳宸ユ弿杩颁俊鎭紙鍙�夛級"
+          maxlength="500"
+          show-word-limit
+        />
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="handleClose">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleSubmit" :loading="submitting">
+          {{ isEdit ? '鏇存柊' : '鍒涘缓' }}
+        </el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref, computed, watch, onMounted } from 'vue'
+import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
+import { employeeApi, type Employee, type EmployeeInput } from '@/api/employee'
+import { roleApi, type Role } from '@/api/role'
+
+interface Props {
+  visible: boolean
+  employee?: Employee | null
+}
+
+interface Emits {
+  (e: 'update:visible', value: boolean): void
+  (e: 'success'): void
+}
+
+const props = withDefaults(defineProps<Props>(), {
+  employee: null
+})
+
+const emit = defineEmits<Emits>()
+
+const formRef = ref<FormInstance>()
+const submitting = ref(false)
+const roles = ref<Role[]>([])
+const rolesLoading = ref(false)
+
+// 璁$畻鏄惁涓虹紪杈戞ā寮�
+const isEdit = computed(() => !!props.employee?.id)
+
+// 鑾峰彇瑙掕壊鍒楄〃
+const fetchRoles = async () => {
+  try {
+    rolesLoading.value = true
+    roles.value = await roleApi.getActiveRoles()
+  } catch (error: any) {
+    ElMessage.error(error.message || '鑾峰彇瑙掕壊鍒楄〃澶辫触')
+    console.error('鑾峰彇瑙掕壊鍒楄〃澶辫触:', error)
+  } finally {
+    rolesLoading.value = false
+  }
+}
+
+// 缁勪欢鎸傝浇鏃惰幏鍙栬鑹插垪琛�
+onMounted(() => {
+  fetchRoles()
+})
+
+// 琛ㄥ崟鏁版嵁
+const form = reactive<EmployeeInput>({
+  id: undefined,
+  name: '',
+  phone: '',
+  password: '',
+  roleId: '',
+  description: ''
+})
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const rules: FormRules = {
+  name: [
+    { required: true, message: '璇疯緭鍏ュ憳宸ュ鍚�', trigger: 'blur' },
+    { min: 2, max: 50, message: '濮撳悕闀垮害搴斿湪2-50涓瓧绗︿箣闂�', trigger: 'blur' }
+  ],
+  phone: [
+    { required: true, message: '璇疯緭鍏ヨ仈绯荤數璇�', trigger: 'blur' },
+    { pattern: /^1[3-9]\d{9}$/, message: '璇疯緭鍏ユ纭殑11浣嶆墜鏈哄彿鐮�', trigger: 'blur' }
+  ],
+  password: [
+    { 
+      validator: (rule, value, callback) => {
+        if (isEdit.value && !value) {
+          // 缂栬緫妯″紡涓嬪瘑鐮佸彲浠ヤ负绌猴紙涓嶄慨鏀癸級
+          callback()
+        } else if (!value) {
+          callback(new Error('璇疯緭鍏ョ櫥褰曞瘑鐮�'))
+        } else if (value.length < 6 || value.length > 20) {
+          callback(new Error('瀵嗙爜闀垮害搴斿湪6-20涓瓧绗︿箣闂�'))
+        } else {
+          callback()
+        }
+      }, 
+      trigger: 'blur' 
+    }
+  ],
+  roleId: [
+    { required: true, message: '璇烽�夋嫨鍛樺伐瑙掕壊', trigger: 'change' }
+  ]
+}
+
+// 鐩戝惉 visible 鍙樺寲
+const visible = computed({
+  get: () => props.visible,
+  set: (value) => emit('update:visible', value)
+})
+
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+  form.id = undefined
+  form.name = ''
+  form.phone = ''
+  form.password = ''
+  form.roleId = ''
+  form.description = ''
+  formRef.value?.clearValidate()
+}
+
+// 鐩戝惉鍛樺伐鏁版嵁鍙樺寲锛屽垵濮嬪寲琛ㄥ崟
+watch(() => props.employee, (employee) => {
+  if (employee) {
+    // 缂栬緫妯″紡锛屽~鍏呰〃鍗曟暟鎹�
+    form.id = employee.id
+    form.name = employee.name
+    form.phone = employee.phone
+    form.password = '' // 瀵嗙爜涓嶅洖鏄�
+    form.roleId = employee.roleId
+    form.description = employee.description || ''
+  } else {
+    // 鏂板妯″紡锛岄噸缃〃鍗�
+    resetForm()
+  }
+}, { immediate: true })
+
+// 鍏抽棴瀵硅瘽妗�
+const handleClose = () => {
+  visible.value = false
+  resetForm()
+}
+
+// 鎻愪氦琛ㄥ崟
+const handleSubmit = async () => {
+  if (!formRef.value) return
+
+  try {
+    const valid = await formRef.value.validate()
+    if (!valid) return
+
+    submitting.value = true
+
+    // 鍑嗗鎻愪氦鏁版嵁
+    const submitData: EmployeeInput = {
+      id: form.id,
+      name: form.name.trim(),
+      phone: form.phone.trim(),
+      password: form.password || undefined, // 绌哄瘑鐮佷紶 undefined
+      roleId: form.roleId,
+      description: form.description?.trim() || undefined
+    }
+
+    await employeeApi.saveEmployee(submitData)
+    
+    ElMessage.success(isEdit.value ? '鍛樺伐淇℃伅鏇存柊鎴愬姛' : '鍛樺伐鍒涘缓鎴愬姛')
+    emit('success')
+    handleClose()
+  } catch (error: any) {
+    ElMessage.error(error.message || '鎿嶄綔澶辫触')
+  } finally {
+    submitting.value = false
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 12px;
+}
+
+:deep(.el-form-item__label) {
+  font-weight: 500;
+}
+
+:deep(.el-textarea__inner) {
+  resize: vertical;
+}
+</style>
\ No newline at end of file
diff --git a/web/src/views/employee/index.vue b/web/src/views/employee/index.vue
index d6f18f1..9c5663a 100644
--- a/web/src/views/employee/index.vue
+++ b/web/src/views/employee/index.vue
@@ -16,16 +16,6 @@
             <el-icon><Search /></el-icon>
           </template>
         </el-input>
-        <el-select
-          v-model="searchForm.role"
-          placeholder="閫夋嫨瑙掕壊"
-          style="width: 150px"
-          clearable
-        >
-          <el-option label="绠$悊鍛�" value="admin" />
-          <el-option label="宸ヤ綔浜哄憳" value="staff" />
-          <el-option label="瀹℃牳鍛�" value="reviewer" />
-        </el-select>
         <el-button type="primary" @click="handleSearch">
           <el-icon><Search /></el-icon>
           鎼滅储
@@ -38,21 +28,18 @@
 
       <!-- 鍛樺伐鍒楄〃 -->
       <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="phone" label="鑱旂郴鐢佃瘽" width="140" />
-        <el-table-column prop="role" label="瑙掕壊" width="120" align="center">
+        <el-table-column prop="roleId" label="瑙掕壊" width="120" align="center">
           <template #default="{ row }">
-            <el-tag :type="getRoleType(row.role)">{{ getRoleText(row.role) }}</el-tag>
+            <el-tag :type="getRoleType(row.roleId)">{{ getRoleText(row.roleId) }}</el-tag>
           </template>
         </el-table-column>
-        <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" width="180" />
+        <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" width="180">
+          <template #default="{ row }">
+            {{ formatDateTime(row.createTime) }}
+          </template>
+        </el-table-column>
         <el-table-column label="鎿嶄綔" width="150" fixed="right">
           <template #default="{ row }">
             <div class="table-actions">
@@ -67,107 +54,92 @@
         </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 v-if="!loading && tableData.length === 0" class="empty-state">
+        <el-empty description="鏆傛棤鍛樺伐鏁版嵁" />
       </div>
     </div>
+
+    <!-- 鍛樺伐璇︽儏瀵硅瘽妗� -->
+    <EmployeeForm
+      v-model:visible="formVisible"
+      :employee="currentEmployee"
+      @success="handleFormSuccess"
+    />
   </div>
 </template>
 
 <script setup lang="ts">
 import { reactive, ref, onMounted } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import { employeeApi, type Employee } from '@/api/employee'
+import EmployeeForm from './EmployeeForm.vue'
 
 const loading = ref(false)
+const formVisible = ref(false)
+const currentEmployee = ref<Employee | null>(null)
 
 // 鎼滅储琛ㄥ崟
 const searchForm = reactive({
-  name: '',
-  role: ''
-})
-
-// 鍒嗛〉淇℃伅
-const pagination = reactive({
-  page: 1,
-  size: 10,
-  total: 0
+  name: ''
 })
 
 // 琛ㄦ牸鏁版嵁
-const tableData = ref([
-  {
-    id: 1,
-    name: '绠$悊鍛�',
-    avatar: '',
-    phone: '13800138000',
-    role: 'admin',
-    createTime: '2024-01-01 09:00:00'
-  },
-  {
-    id: 2,
-    name: '宸ヤ綔浜哄憳A',
-    avatar: '',
-    phone: '13800138001',
-    role: 'staff',
-    createTime: '2024-01-02 10:30:00'
-  },
-  {
-    id: 3,
-    name: '瀹℃牳鍛楤',
-    avatar: '',
-    phone: '13800138002',
-    role: 'reviewer',
-    createTime: '2024-01-03 14:15:00'
-  }
-])
+const tableData = ref<Employee[]>([])
 
 // 鑾峰彇瑙掕壊鏍囩绫诲瀷
-const getRoleType = (role: string) => {
+const getRoleType = (roleId: string) => {
   const typeMap: Record<string, string> = {
-    'admin': 'danger',
-    'staff': 'primary',
-    'reviewer': 'success'
+    'ADMIN': 'danger',
+    'MANAGER': 'warning',
+    'STAFF': 'primary',
+    'REVIEWER': 'success'
   }
-  return typeMap[role] || 'info'
+  return typeMap[roleId] || 'info'
 }
 
 // 鑾峰彇瑙掕壊鏂囨湰
-const getRoleText = (role: string) => {
+const getRoleText = (roleId: string) => {
   const textMap: Record<string, string> = {
-    'admin': '绠$悊鍛�',
-    'staff': '宸ヤ綔浜哄憳',
-    'reviewer': '瀹℃牳鍛�'
+    'ADMIN': '绠$悊鍛�',
+    'MANAGER': '缁忕悊',
+    'STAFF': '宸ヤ綔浜哄憳',
+    'REVIEWER': '瀹℃牳鍛�'
   }
-  return textMap[role] || '鏈煡'
+  return textMap[roleId] || roleId
+}
+
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+const formatDateTime = (dateTime: string | undefined) => {
+  if (!dateTime) return '-'
+  return new Date(dateTime).toLocaleString('zh-CN', {
+    year: 'numeric',
+    month: '2-digit',
+    day: '2-digit',
+    hour: '2-digit',
+    minute: '2-digit'
+  })
 }
 
 // 鎼滅储
 const handleSearch = () => {
-  pagination.page = 1
   loadData()
 }
 
 // 鏂板鍛樺伐
 const handleAdd = () => {
-  ElMessage.info('鏂板鍛樺伐鍔熻兘寰呭紑鍙�')
+  currentEmployee.value = null
+  formVisible.value = true
 }
 
 // 缂栬緫鍛樺伐
-const handleEdit = (row: any) => {
-  ElMessage.info(`缂栬緫鍛樺伐锛�${row.name}`)
+const handleEdit = (row: Employee) => {
+  currentEmployee.value = row
+  formVisible.value = true
 }
 
 // 鍒犻櫎鍛樺伐
-const handleDelete = async (row: any) => {
+const handleDelete = async (row: Employee) => {
   try {
     await ElMessageBox.confirm(`纭畾瑕佸垹闄ゅ憳宸�"${row.name}"鍚楋紵`, '鎻愮ず', {
       confirmButtonText: '纭畾',
@@ -175,33 +147,42 @@
       type: 'warning'
     })
     
+    loading.value = true
+    await employeeApi.deleteEmployee(row.id)
     ElMessage.success('鍒犻櫎鎴愬姛')
-    loadData()
-  } catch {
-    // 鐢ㄦ埛鍙栨秷
+    await loadData()
+  } catch (error: any) {
+    if (error !== 'cancel') {
+      ElMessage.error(error.message || '鍒犻櫎澶辫触')
+    }
+  } finally {
+    loading.value = false
   }
 }
 
-// 鍒嗛〉澶у皬鏀瑰彉
-const handleSizeChange = (size: number) => {
-  pagination.size = size
-  loadData()
-}
-
-// 褰撳墠椤垫敼鍙�
-const handleCurrentChange = (page: number) => {
-  pagination.page = page
+// 琛ㄥ崟鎻愪氦鎴愬姛
+const handleFormSuccess = () => {
+  formVisible.value = false
   loadData()
 }
 
 // 鍔犺浇鏁版嵁
-const loadData = () => {
-  loading.value = true
-  // TODO: 璋冪敤API鍔犺浇鏁版嵁
-  setTimeout(() => {
-    pagination.total = 3
+const loadData = async () => {
+  try {
+    loading.value = true
+    const name = searchForm.name.trim()
+    
+    if (name) {
+      tableData.value = await employeeApi.searchEmployees(name)
+    } else {
+      tableData.value = await employeeApi.getEmployees()
+    }
+  } catch (error: any) {
+    ElMessage.error(error.message || '鍔犺浇鏁版嵁澶辫触')
+    tableData.value = []
+  } finally {
     loading.value = false
-  }, 500)
+  }
 }
 
 onMounted(() => {
diff --git a/web/src/views/player/index.vue b/web/src/views/player/index.vue
index 543137f..1780c81 100644
--- a/web/src/views/player/index.vue
+++ b/web/src/views/player/index.vue
@@ -17,7 +17,26 @@
           </template>
         </el-input>
         <el-select
-          v-model="searchForm.status"
+          v-model="searchForm.activityId"
+          placeholder="閫夋嫨姣旇禌"
+          style="width: 300px"
+          clearable
+          filterable
+        >
+          <el-option 
+            v-for="activity in activityOptions" 
+            :key="activity.id" 
+            :label="getActivityDisplayName(activity)" 
+            :value="activity.id"
+          >
+            <span>{{ getCompetitionName(activity) }}</span>
+            <span v-if="activity.pid > 0" style="color: #409eff; margin-left: 8px;">
+              {{ activity.name }}
+            </span>
+          </el-option>
+        </el-select>
+        <el-select
+          v-model="searchForm.state"
           placeholder="閫夋嫨鐘舵��"
           style="width: 150px"
           clearable
@@ -46,16 +65,16 @@
         <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="status" label="鐘舵��" width="100" align="center">
+        <el-table-column prop="state" label="鐘舵��" width="100" align="center">
           <template #default="{ row }">
-            <el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag>
+            <el-tag :type="getStateType(row.state)">{{ getStateText(row.state) }}</el-tag>
           </template>
         </el-table-column>
         <el-table-column label="鎿嶄綔" width="200" fixed="right">
           <template #default="{ row }">
             <div class="table-actions">
               <el-button 
-                v-if="row.status === 1" 
+                v-if="row.state === 1" 
                 type="success" 
                 size="small" 
                 @click="handleApprove(row)"
@@ -63,7 +82,7 @@
                 瀹℃牳閫氳繃
               </el-button>
               <el-button 
-                v-if="row.status === 1" 
+                v-if="row.state === 1" 
                 type="danger" 
                 size="small" 
                 @click="handleReject(row)"
@@ -99,14 +118,19 @@
 import { useRouter } from 'vue-router'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { PlayerApi } from '@/api/player'
+import { getAllActivities } from '@/api/activity'
 
 const loading = ref(false)
 const router = useRouter()
 
+// 娲诲姩閫夐」
+const activityOptions = ref([])
+
 // 鎼滅储琛ㄥ崟
 const searchForm = reactive({
   name: '',
-  status: ''
+  activityId: '',
+  state: ''
 })
 
 // 鍒嗛〉淇℃伅
@@ -125,48 +149,48 @@
     activityName: '2024骞村垱鏂板垱涓氬ぇ璧�',
     phone: '13800138001',
     applyTime: '2024-01-05 14:30:00',
-    status: 1 // 1-寰呭鏍�, 2-杩涜涓�, 3-宸茬粨鏉�
+    state: 1 // 1-寰呭鏍�, 2-杩涜涓�, 3-宸茬粨鏉�
   },
   {
     id: 2,
     name: '鏉庡洓',
     avatar: '',
-    activityName: '鎶�鑳界珵璧涘垵璧�',
-    phone: '13800138002',
-    applyTime: '2024-01-06 09:15:00',
-    status: 2
+    activityName: '涔︽硶姣旇禌',
+    phone: '13900139002',
+    applyTime: '2024-01-16 10:30:00',
+    state: 2
   },
   {
     id: 3,
     name: '鐜嬩簲',
     avatar: '',
-    activityName: '璁捐澶ц禌鍐宠禌',
-    phone: '13800138003',
-    applyTime: '2024-01-07 16:45:00',
-    status: 1
+    activityName: '缁樼敾姣旇禌',
+    phone: '13900139003',
+    applyTime: '2024-01-17 14:20:00',
+    state: 1
   }
 ])
 
 // 鑾峰彇鐘舵�佹爣绛剧被鍨�
-const getStatusType = (status: number | null | undefined) => {
+const getStateType = (state: number | null | undefined) => {
   const typeMap: Record<number, string> = {
     0: 'warning',   // 寰呭鏍�
     1: 'success',   // 杩涜涓�
     2: 'danger',    // 鏈�氳繃
     3: 'info'       // 宸茬粨鏉�
   }
-  return status != null ? (typeMap[status] || 'info') : 'info'
+  return state != null ? (typeMap[state] || 'info') : 'info'
 }
 
 // 鑾峰彇鐘舵�佹枃鏈�
-const getStatusText = (status: number | null | undefined) => {
+const getStateText = (state: number | null | undefined) => {
   const textMap: Record<number, string> = {
     0: '寰呭鏍�',
     1: '杩涜涓�',
     2: '鏈�氳繃',
     3: '宸茬粨鏉�'
   }
-  return status != null ? (textMap[status] || '鏈煡') : '鏈煡'
+  return state != null ? (textMap[state] || '鏈煡') : '鏈煡'
 }
 
 // 鎼滅储
@@ -185,26 +209,25 @@
     })
     
     ElMessage.success('瀹℃牳閫氳繃鎴愬姛')
-    row.status = 2
+    row.state = 2
   } catch {
     // 鐢ㄦ埛鍙栨秷
   }
 }
 
 // 瀹℃牳鎷掔粷
-const handleReject = async (row: any) => {
-  try {
-    await ElMessageBox.confirm(`纭畾鎷掔粷瀛﹀憳"${row.name}"鐨勬姤鍚嶇敵璇峰悧锛焋, '鎻愮ず', {
-      confirmButtonText: '纭畾',
-      cancelButtonText: '鍙栨秷',
-      type: 'warning'
-    })
-    
-    ElMessage.success('瀹℃牳鎷掔粷鎴愬姛')
-    // 杩欓噷鍙互璁剧疆涓哄垹闄ょ姸鎬佹垨鍏朵粬鐘舵��
-  } catch {
-    // 鐢ㄦ埛鍙栨秷
-  }
+const handleReject = (row: any) => {
+  ElMessageBox.confirm('纭鎷掔粷璇ョ敵璇凤紵', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning'
+  }).then(() => {
+    // 杩欓噷搴旇璋冪敤API鏇存柊鐘舵��
+    row.state = 3 // 鏇存柊涓哄凡缁撴潫
+    ElMessage.success('宸叉嫆缁�')
+  }).catch(() => {
+    ElMessage.info('宸插彇娑�')
+  })
 }
 
 // 鏌ョ湅璇︽儏锛堣烦杞埌璇勫垎椤甸潰锛�
@@ -228,11 +251,43 @@
   loadData()
 }
 
+// 鑾峰彇姣旇禌鍚嶇О锛堝鏋滄槸闃舵锛岃繑鍥炵埗姣旇禌鍚嶇О锛涘鏋滄槸姣旇禌锛岃繑鍥炶嚜宸辩殑鍚嶇О锛�
+const getCompetitionName = (activity: any) => {
+  if (activity.pid > 0 && activity.parent) {
+    return activity.parent.name
+  }
+  return activity.name
+}
+
+// 鑾峰彇娲诲姩鏄剧ず鍚嶇О锛堢敤浜庢悳绱㈠拰閫変腑鏃舵樉绀猴級
+const getActivityDisplayName = (activity: any) => {
+  if (activity.pid > 0 && activity.parent) {
+    return `${activity.parent.name} - ${activity.name}`
+  }
+  return activity.name
+}
+
+// 鍔犺浇娲诲姩閫夐」
+const loadActivityOptions = async () => {
+  try {
+    const activities = await getAllActivities()
+    // 鍙樉绀虹姸鎬佷负1锛堣繘琛屼腑锛夌殑姣旇禌鍙婂叾闃舵
+    activityOptions.value = (activities || []).filter(activity => activity.state === 1)
+  } catch (e: any) {
+    console.error('鍔犺浇娲诲姩閫夐」澶辫触:', e)
+  }
+}
+
 // 鍔犺浇鏁版嵁
 const loadData = async () => {
   loading.value = true
   try {
-    const list = await PlayerApi.getApplications(searchForm.name || '', pagination.page, pagination.size)
+    const list = await PlayerApi.getApplications(
+      searchForm.name || '', 
+      searchForm.activityId || null, 
+      pagination.page, 
+      pagination.size
+    )
     tableData.value = (list || []).map((item: any) => ({
       id: item.id,
       name: item.playerName,
@@ -240,7 +295,7 @@
       activityName: item.activityName,
       phone: item.phone,
       applyTime: item.applyTime,
-      status: item.state
+      state: item.state
     }))
     pagination.total = tableData.value.length
   } catch (e: any) {
@@ -251,6 +306,7 @@
 }
 
 onMounted(() => {
+  loadActivityOptions()
   loadData()
 })
 </script>

--
Gitblit v1.8.0