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