diff --git a/pom.xml b/pom.xml
index b1d3582c..f3b2fe45 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,35 +30,59 @@
17
-
- org.springframework.boot
- spring-boot-starter-security
-
+
org.springframework.boot
spring-boot-starter-web
-
- com.mysql
- mysql-connector-j
- runtime
-
-
- org.projectlombok
- lombok
- true
-
+
org.springframework.boot
spring-boot-starter-test
test
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
org.springframework.security
spring-security-test
test
+
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+
+
+ com.baomidou
+ mybatis-plus-spring-boot3-starter
+ 3.5.10.1
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ io.jsonwebtoken
+ jjwt
+ 0.12.5
+
+
+
diff --git a/sql/SAMS-2025_02_13_00_21_14-dump.sql b/sql/SAMS-2025_02_13_00_21_14-dump.sql
new file mode 100644
index 00000000..64f368db
--- /dev/null
+++ b/sql/SAMS-2025_02_13_00_21_14-dump.sql
@@ -0,0 +1,406 @@
+-- MySQL dump 10.13 Distrib 8.0.41, for Linux (x86_64)
+--
+-- Host: 127.0.0.1 Database: SAMS
+-- ------------------------------------------------------
+-- Server version 8.0.41-0ubuntu0.22.04.1
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!50503 SET NAMES utf8mb4 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `ams_activity`
+--
+
+DROP TABLE IF EXISTS `ams_activity`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_activity` (
+ `act_id` bigint NOT NULL AUTO_INCREMENT COMMENT '活动ID',
+ `title` varchar(100) NOT NULL COMMENT '活动标题',
+ `description` text COMMENT '活动描述',
+ `start_time` datetime NOT NULL COMMENT '开始时间',
+ `end_time` datetime NOT NULL COMMENT '结束时间',
+ `location` varchar(255) DEFAULT NULL COMMENT '地点',
+ `budget` decimal(10,2) DEFAULT NULL COMMENT '预算',
+ `max_participants` int DEFAULT NULL COMMENT '最大参与人数',
+ `creator_id` bigint NOT NULL COMMENT '创建者ID',
+ `club_id` bigint DEFAULT NULL COMMENT '所属社团ID',
+ `visibility` enum('public','private') DEFAULT 'public' COMMENT '是否公开',
+ `status` enum('draft','approved','ongoing','completed','cancelled') DEFAULT 'draft' COMMENT '活动状态',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`act_id`),
+ KEY `creator_id` (`creator_id`),
+ KEY `club_id` (`club_id`),
+ CONSTRAINT `ams_activity_ibfk_1` FOREIGN KEY (`creator_id`) REFERENCES `sys_user` (`user_id`),
+ CONSTRAINT `ams_activity_ibfk_2` FOREIGN KEY (`club_id`) REFERENCES `sms_club` (`club_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_activity`
+--
+
+LOCK TABLES `ams_activity` WRITE;
+/*!40000 ALTER TABLE `ams_activity` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_activity` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_approval`
+--
+
+DROP TABLE IF EXISTS `ams_approval`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_approval` (
+ `appr_id` bigint NOT NULL AUTO_INCREMENT COMMENT '审批ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `user_id` bigint NOT NULL COMMENT '发起者ID',
+ `approver_id` bigint NOT NULL COMMENT '审批人ID',
+ `status` tinyint(1) DEFAULT '0' COMMENT '审批状态 (0: 待审批, 1: 通过, 2: 拒绝)',
+ `reason` text COMMENT '拒绝原因(如果适用)',
+ `approved_at` datetime DEFAULT NULL COMMENT '审批时间',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`appr_id`),
+ KEY `act_id` (`act_id`),
+ KEY `user_id` (`user_id`),
+ KEY `approver_id` (`approver_id`),
+ CONSTRAINT `ams_approval_ibfk_1` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`),
+ CONSTRAINT `ams_approval_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`),
+ CONSTRAINT `ams_approval_ibfk_3` FOREIGN KEY (`approver_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动审批表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_approval`
+--
+
+LOCK TABLES `ams_approval` WRITE;
+/*!40000 ALTER TABLE `ams_approval` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_approval` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_comment`
+--
+
+DROP TABLE IF EXISTS `ams_comment`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_comment` (
+ `comment_id` bigint NOT NULL AUTO_INCREMENT COMMENT '评论ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `parent_comment_id` bigint DEFAULT NULL COMMENT '父评论ID(为空表示是顶级评论)',
+ `content` text NOT NULL COMMENT '评论内容',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '评论时间',
+ PRIMARY KEY (`comment_id`),
+ KEY `user_id` (`user_id`),
+ KEY `act_id` (`act_id`),
+ KEY `parent_comment_id` (`parent_comment_id`),
+ CONSTRAINT `ams_comment_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE CASCADE,
+ CONSTRAINT `ams_comment_ibfk_2` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`) ON DELETE CASCADE,
+ CONSTRAINT `ams_comment_ibfk_3` FOREIGN KEY (`parent_comment_id`) REFERENCES `ams_comment` (`comment_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动评论表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_comment`
+--
+
+LOCK TABLES `ams_comment` WRITE;
+/*!40000 ALTER TABLE `ams_comment` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_comment` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_reaction`
+--
+
+DROP TABLE IF EXISTS `ams_reaction`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_reaction` (
+ `reaction_id` bigint NOT NULL AUTO_INCREMENT COMMENT '点赞/点踩ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `reaction_type` enum('like','dislike') NOT NULL COMMENT '反应类型(like: 点赞, dislike: 点踩)',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '反应时间',
+ PRIMARY KEY (`reaction_id`),
+ UNIQUE KEY `uniq_user_activity_reaction` (`user_id`,`act_id`),
+ KEY `act_id` (`act_id`),
+ CONSTRAINT `ams_reaction_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE CASCADE,
+ CONSTRAINT `ams_reaction_ibfk_2` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动点赞/点踩表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_reaction`
+--
+
+LOCK TABLES `ams_reaction` WRITE;
+/*!40000 ALTER TABLE `ams_reaction` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_reaction` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_registration`
+--
+
+DROP TABLE IF EXISTS `ams_registration`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_registration` (
+ `reg_id` bigint NOT NULL AUTO_INCREMENT COMMENT '报名ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `status` enum('registered','cancelled','attended','absent') DEFAULT 'registered' COMMENT '报名状态',
+ `register_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '报名时间',
+ `attend_time` datetime DEFAULT NULL COMMENT '参与时间',
+ PRIMARY KEY (`reg_id`),
+ KEY `act_id` (`act_id`),
+ KEY `user_id` (`user_id`),
+ CONSTRAINT `ams_registration_ibfk_1` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`),
+ CONSTRAINT `ams_registration_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动报名表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_registration`
+--
+
+LOCK TABLES `ams_registration` WRITE;
+/*!40000 ALTER TABLE `ams_registration` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_registration` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sms_club`
+--
+
+DROP TABLE IF EXISTS `sms_club`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sms_club` (
+ `club_id` bigint NOT NULL AUTO_INCREMENT COMMENT '社团ID',
+ `club_name` varchar(50) NOT NULL COMMENT '社团名称',
+ `description` text COMMENT '社团简介',
+ `category` enum('文化艺术','学术科技','社会公益','其他') NOT NULL COMMENT '社团类型',
+ `college_id` bigint NOT NULL COMMENT '所属院系',
+ `leader_id` bigint DEFAULT NULL COMMENT '负责人ID',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`club_id`),
+ KEY `college_id` (`college_id`),
+ KEY `leader_id` (`leader_id`),
+ CONSTRAINT `sms_club_ibfk_1` FOREIGN KEY (`college_id`) REFERENCES `sms_college` (`college_id`),
+ CONSTRAINT `sms_club_ibfk_2` FOREIGN KEY (`leader_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='社团表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sms_club`
+--
+
+LOCK TABLES `sms_club` WRITE;
+/*!40000 ALTER TABLE `sms_club` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sms_club` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sms_college`
+--
+
+DROP TABLE IF EXISTS `sms_college`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sms_college` (
+ `college_id` bigint NOT NULL AUTO_INCREMENT COMMENT '院系ID',
+ `college_name` varchar(255) NOT NULL COMMENT '名称(高校或院系)',
+ `parent_id` bigint DEFAULT NULL COMMENT '父院系ID(高校此值为空)',
+ `leader_id` bigint DEFAULT NULL COMMENT '负责人ID',
+ `email` varchar(50) DEFAULT '' COMMENT '邮箱',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`college_id`),
+ KEY `parent_id` (`parent_id`),
+ KEY `leader_id` (`leader_id`),
+ CONSTRAINT `sms_college_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `sms_college` (`college_id`) ON DELETE SET NULL,
+ CONSTRAINT `sms_college_ibfk_2` FOREIGN KEY (`leader_id`) REFERENCES `sys_user` (`user_id`) ON DELETE SET NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='高校及院系表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sms_college`
+--
+
+LOCK TABLES `sms_college` WRITE;
+/*!40000 ALTER TABLE `sms_college` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sms_college` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sms_user_club`
+--
+
+DROP TABLE IF EXISTS `sms_user_club`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sms_user_club` (
+ `suc_id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `club_id` bigint NOT NULL COMMENT '社团ID',
+ `role_id` bigint NOT NULL COMMENT '角色ID',
+ `is_active` tinyint(1) DEFAULT '1' COMMENT '是否活跃',
+ `join_date` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '加入日期',
+ PRIMARY KEY (`suc_id`),
+ KEY `user_id` (`user_id`),
+ KEY `club_id` (`club_id`),
+ KEY `role_id` (`role_id`),
+ CONSTRAINT `sms_user_club_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`),
+ CONSTRAINT `sms_user_club_ibfk_2` FOREIGN KEY (`club_id`) REFERENCES `sms_club` (`club_id`),
+ CONSTRAINT `sms_user_club_ibfk_3` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户社团关系表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sms_user_club`
+--
+
+LOCK TABLES `sms_user_club` WRITE;
+/*!40000 ALTER TABLE `sms_user_club` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sms_user_club` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_logs`
+--
+
+DROP TABLE IF EXISTS `sys_logs`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_logs` (
+ `log_id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `action` varchar(255) NOT NULL COMMENT '操作类型',
+ `description` text COMMENT '描述',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间',
+ PRIMARY KEY (`log_id`),
+ KEY `user_id` (`user_id`),
+ CONSTRAINT `sys_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统日志表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_logs`
+--
+
+LOCK TABLES `sys_logs` WRITE;
+/*!40000 ALTER TABLE `sys_logs` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sys_logs` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_notification`
+--
+
+DROP TABLE IF EXISTS `sys_notification`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_notification` (
+ `notification_id` bigint NOT NULL AUTO_INCREMENT COMMENT '通知ID',
+ `title` varchar(255) NOT NULL COMMENT '通知标题',
+ `content` text NOT NULL COMMENT '通知内容',
+ `receiver_id` bigint NOT NULL COMMENT '接收者ID',
+ `is_read` tinyint(1) DEFAULT '0' COMMENT '是否已读',
+ `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`notification_id`),
+ KEY `receiver_id` (`receiver_id`),
+ CONSTRAINT `sys_notification_ibfk_1` FOREIGN KEY (`receiver_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统通知表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_notification`
+--
+
+LOCK TABLES `sys_notification` WRITE;
+/*!40000 ALTER TABLE `sys_notification` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sys_notification` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_role`
+--
+
+DROP TABLE IF EXISTS `sys_role`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_role` (
+ `role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID',
+ `role_name` varchar(30) NOT NULL COMMENT '角色名称',
+ `role_key` varchar(64) NOT NULL COMMENT '角色标识',
+ `role_desc` varchar(255) DEFAULT NULL COMMENT '角色描述',
+ `status` enum('active','inactive') DEFAULT 'active' COMMENT '状态',
+ PRIMARY KEY (`role_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户角色表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_role`
+--
+
+LOCK TABLES `sys_role` WRITE;
+/*!40000 ALTER TABLE `sys_role` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sys_role` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_user`
+--
+
+DROP TABLE IF EXISTS `sys_user`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_user` (
+ `user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
+ `role_id` bigint NOT NULL COMMENT '用户角色',
+ `nick_name` varchar(30) DEFAULT '' COMMENT '用户昵称',
+ `user_name` varchar(30) NOT NULL COMMENT '真实姓名',
+ `password` varchar(100) NOT NULL COMMENT '用户密码',
+ `school_id` char(12) NOT NULL COMMENT '学号/教职工号',
+ `college_id` bigint NOT NULL COMMENT '所属院系',
+ `email` varchar(50) DEFAULT '' COMMENT '用户邮箱',
+ `avatar` varchar(100) DEFAULT '' COMMENT '头像地址',
+ `status` enum('active','inactive','banned') DEFAULT 'active' COMMENT '账号状态',
+ PRIMARY KEY (`user_id`),
+ KEY `role_id` (`role_id`),
+ CONSTRAINT `sys_user_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统用户表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_user`
+--
+
+LOCK TABLES `sys_user` WRITE;
+/*!40000 ALTER TABLE `sys_user` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sys_user` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2025-02-13 0:21:14
diff --git a/sql/SAMS-2025_02_13_00_32_38-dump.sql b/sql/SAMS-2025_02_13_00_32_38-dump.sql
new file mode 100644
index 00000000..823eb0bb
--- /dev/null
+++ b/sql/SAMS-2025_02_13_00_32_38-dump.sql
@@ -0,0 +1,407 @@
+-- MySQL dump 10.13 Distrib 8.0.41, for Linux (x86_64)
+--
+-- Host: 127.0.0.1 Database: SAMS
+-- ------------------------------------------------------
+-- Server version 8.0.41-0ubuntu0.22.04.1
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!50503 SET NAMES utf8mb4 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `ams_activity`
+--
+
+DROP TABLE IF EXISTS `ams_activity`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_activity` (
+ `act_id` bigint NOT NULL AUTO_INCREMENT COMMENT '活动ID',
+ `title` varchar(100) NOT NULL COMMENT '活动标题',
+ `description` text COMMENT '活动描述',
+ `start_time` datetime NOT NULL COMMENT '开始时间',
+ `end_time` datetime NOT NULL COMMENT '结束时间',
+ `location` varchar(255) DEFAULT NULL COMMENT '地点',
+ `budget` decimal(10,2) DEFAULT NULL COMMENT '预算',
+ `max_participants` int DEFAULT NULL COMMENT '最大参与人数',
+ `creator_id` bigint NOT NULL COMMENT '创建者ID',
+ `club_id` bigint DEFAULT NULL COMMENT '所属社团ID',
+ `visibility` enum('public','private') DEFAULT 'public' COMMENT '是否公开',
+ `status` enum('draft','approved','ongoing','completed','cancelled') DEFAULT 'draft' COMMENT '活动状态',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
+ PRIMARY KEY (`act_id`),
+ KEY `creator_id` (`creator_id`),
+ KEY `club_id` (`club_id`),
+ CONSTRAINT `ams_activity_ibfk_1` FOREIGN KEY (`creator_id`) REFERENCES `sys_user` (`user_id`),
+ CONSTRAINT `ams_activity_ibfk_2` FOREIGN KEY (`club_id`) REFERENCES `sms_club` (`club_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_activity`
+--
+
+LOCK TABLES `ams_activity` WRITE;
+/*!40000 ALTER TABLE `ams_activity` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_activity` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_approval`
+--
+
+DROP TABLE IF EXISTS `ams_approval`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_approval` (
+ `appr_id` bigint NOT NULL AUTO_INCREMENT COMMENT '审批ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `user_id` bigint NOT NULL COMMENT '发起者ID',
+ `approver_id` bigint NOT NULL COMMENT '审批人ID',
+ `status` tinyint(1) DEFAULT '0' COMMENT '审批状态 (0: 待审批, 1: 通过, 2: 拒绝)',
+ `reason` text COMMENT '拒绝原因(如果适用)',
+ `approved_at` datetime DEFAULT NULL COMMENT '审批时间',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`appr_id`),
+ KEY `act_id` (`act_id`),
+ KEY `user_id` (`user_id`),
+ KEY `approver_id` (`approver_id`),
+ CONSTRAINT `ams_approval_ibfk_1` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`),
+ CONSTRAINT `ams_approval_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`),
+ CONSTRAINT `ams_approval_ibfk_3` FOREIGN KEY (`approver_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动审批表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_approval`
+--
+
+LOCK TABLES `ams_approval` WRITE;
+/*!40000 ALTER TABLE `ams_approval` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_approval` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_comment`
+--
+
+DROP TABLE IF EXISTS `ams_comment`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_comment` (
+ `comment_id` bigint NOT NULL AUTO_INCREMENT COMMENT '评论ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `parent_comment_id` bigint DEFAULT NULL COMMENT '父评论ID(为空表示是顶级评论)',
+ `content` text NOT NULL COMMENT '评论内容',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '评论时间',
+ PRIMARY KEY (`comment_id`),
+ KEY `user_id` (`user_id`),
+ KEY `act_id` (`act_id`),
+ KEY `ams_comment_ibfk_3` (`parent_comment_id`),
+ CONSTRAINT `ams_comment_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE CASCADE,
+ CONSTRAINT `ams_comment_ibfk_2` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`) ON DELETE CASCADE,
+ CONSTRAINT `ams_comment_ibfk_3` FOREIGN KEY (`parent_comment_id`) REFERENCES `ams_comment` (`comment_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动评论表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_comment`
+--
+
+LOCK TABLES `ams_comment` WRITE;
+/*!40000 ALTER TABLE `ams_comment` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_comment` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_reaction`
+--
+
+DROP TABLE IF EXISTS `ams_reaction`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_reaction` (
+ `reaction_id` bigint NOT NULL AUTO_INCREMENT COMMENT '点赞/点踩ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `reaction_type` enum('like','dislike') NOT NULL COMMENT '反应类型(like: 点赞, dislike: 点踩)',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '反应时间',
+ PRIMARY KEY (`reaction_id`),
+ UNIQUE KEY `uniq_user_activity_reaction` (`user_id`,`act_id`),
+ KEY `act_id` (`act_id`),
+ CONSTRAINT `ams_reaction_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE CASCADE,
+ CONSTRAINT `ams_reaction_ibfk_2` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动点赞/点踩表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_reaction`
+--
+
+LOCK TABLES `ams_reaction` WRITE;
+/*!40000 ALTER TABLE `ams_reaction` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_reaction` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_registration`
+--
+
+DROP TABLE IF EXISTS `ams_registration`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_registration` (
+ `reg_id` bigint NOT NULL AUTO_INCREMENT COMMENT '报名ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `status` enum('registered','cancelled','attended','absent') DEFAULT 'registered' COMMENT '报名状态',
+ `register_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '报名时间',
+ `attend_time` datetime DEFAULT NULL COMMENT '参与时间',
+ PRIMARY KEY (`reg_id`),
+ KEY `act_id` (`act_id`),
+ KEY `user_id` (`user_id`),
+ CONSTRAINT `ams_registration_ibfk_1` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`),
+ CONSTRAINT `ams_registration_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动报名表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_registration`
+--
+
+LOCK TABLES `ams_registration` WRITE;
+/*!40000 ALTER TABLE `ams_registration` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_registration` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sms_club`
+--
+
+DROP TABLE IF EXISTS `sms_club`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sms_club` (
+ `club_id` bigint NOT NULL AUTO_INCREMENT COMMENT '社团ID',
+ `club_name` varchar(50) NOT NULL COMMENT '社团名称',
+ `description` text COMMENT '社团简介',
+ `category` enum('文化艺术','学术科技','社会公益','其他') NOT NULL COMMENT '社团类型',
+ `college_id` bigint NOT NULL COMMENT '所属院系',
+ `leader_id` bigint DEFAULT NULL COMMENT '负责人ID',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`club_id`),
+ KEY `college_id` (`college_id`),
+ KEY `leader_id` (`leader_id`),
+ CONSTRAINT `sms_club_ibfk_1` FOREIGN KEY (`college_id`) REFERENCES `sms_college` (`college_id`),
+ CONSTRAINT `sms_club_ibfk_2` FOREIGN KEY (`leader_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='社团表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sms_club`
+--
+
+LOCK TABLES `sms_club` WRITE;
+/*!40000 ALTER TABLE `sms_club` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sms_club` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sms_college`
+--
+
+DROP TABLE IF EXISTS `sms_college`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sms_college` (
+ `college_id` bigint NOT NULL AUTO_INCREMENT COMMENT '院系ID',
+ `college_name` varchar(255) NOT NULL COMMENT '名称(高校或院系)',
+ `parent_id` bigint DEFAULT NULL COMMENT '父院系ID(高校此值为空)',
+ `leader_id` bigint DEFAULT NULL COMMENT '负责人ID',
+ `email` varchar(50) DEFAULT '' COMMENT '邮箱',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`college_id`),
+ KEY `parent_id` (`parent_id`),
+ KEY `leader_id` (`leader_id`),
+ CONSTRAINT `sms_college_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `sms_college` (`college_id`) ON DELETE SET NULL,
+ CONSTRAINT `sms_college_ibfk_2` FOREIGN KEY (`leader_id`) REFERENCES `sys_user` (`user_id`) ON DELETE SET NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='高校及院系表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sms_college`
+--
+
+LOCK TABLES `sms_college` WRITE;
+/*!40000 ALTER TABLE `sms_college` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sms_college` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sms_user_club`
+--
+
+DROP TABLE IF EXISTS `sms_user_club`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sms_user_club` (
+ `suc_id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `club_id` bigint NOT NULL COMMENT '社团ID',
+ `role_id` bigint NOT NULL COMMENT '角色ID',
+ `is_active` tinyint(1) DEFAULT '1' COMMENT '是否活跃',
+ `join_date` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '加入日期',
+ PRIMARY KEY (`suc_id`),
+ KEY `user_id` (`user_id`),
+ KEY `club_id` (`club_id`),
+ KEY `role_id` (`role_id`),
+ CONSTRAINT `sms_user_club_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`),
+ CONSTRAINT `sms_user_club_ibfk_2` FOREIGN KEY (`club_id`) REFERENCES `sms_club` (`club_id`),
+ CONSTRAINT `sms_user_club_ibfk_3` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户社团关系表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sms_user_club`
+--
+
+LOCK TABLES `sms_user_club` WRITE;
+/*!40000 ALTER TABLE `sms_user_club` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sms_user_club` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_logs`
+--
+
+DROP TABLE IF EXISTS `sys_logs`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_logs` (
+ `log_id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `action` varchar(255) NOT NULL COMMENT '操作类型',
+ `description` text COMMENT '描述',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间',
+ PRIMARY KEY (`log_id`),
+ KEY `idx_user_id` (`user_id`),
+ CONSTRAINT `sys_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统日志表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_logs`
+--
+
+LOCK TABLES `sys_logs` WRITE;
+/*!40000 ALTER TABLE `sys_logs` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sys_logs` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_notification`
+--
+
+DROP TABLE IF EXISTS `sys_notification`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_notification` (
+ `notification_id` bigint NOT NULL AUTO_INCREMENT COMMENT '通知ID',
+ `title` varchar(255) NOT NULL COMMENT '通知标题',
+ `content` text NOT NULL COMMENT '通知内容',
+ `receiver_id` bigint NOT NULL COMMENT '接收者ID',
+ `is_read` tinyint(1) DEFAULT '0' COMMENT '是否已读',
+ `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`notification_id`),
+ KEY `idx_receiver_id` (`receiver_id`),
+ CONSTRAINT `sys_notification_ibfk_1` FOREIGN KEY (`receiver_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统通知表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_notification`
+--
+
+LOCK TABLES `sys_notification` WRITE;
+/*!40000 ALTER TABLE `sys_notification` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sys_notification` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_role`
+--
+
+DROP TABLE IF EXISTS `sys_role`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_role` (
+ `role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID',
+ `role_name` varchar(30) NOT NULL COMMENT '角色名称',
+ `role_key` varchar(64) NOT NULL COMMENT '角色标识',
+ `role_desc` varchar(255) DEFAULT NULL COMMENT '角色描述',
+ `status` enum('active','inactive') DEFAULT 'active' COMMENT '状态',
+ PRIMARY KEY (`role_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户角色表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_role`
+--
+
+LOCK TABLES `sys_role` WRITE;
+/*!40000 ALTER TABLE `sys_role` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sys_role` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_user`
+--
+
+DROP TABLE IF EXISTS `sys_user`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_user` (
+ `user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
+ `role_id` bigint NOT NULL COMMENT '用户角色',
+ `nick_name` varchar(30) DEFAULT '' COMMENT '用户昵称',
+ `user_name` varchar(30) NOT NULL COMMENT '真实姓名',
+ `password` varchar(100) NOT NULL COMMENT '用户密码',
+ `school_id` char(12) NOT NULL COMMENT '学号/教职工号',
+ `college_id` bigint NOT NULL COMMENT '所属院系',
+ `email` varchar(50) DEFAULT '' COMMENT '用户邮箱',
+ `avatar` varchar(100) DEFAULT '' COMMENT '头像地址',
+ `status` enum('active','inactive','banned') DEFAULT 'active' COMMENT '账号状态',
+ PRIMARY KEY (`user_id`),
+ KEY `role_id` (`role_id`),
+ CONSTRAINT `sys_user_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统用户表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_user`
+--
+
+LOCK TABLES `sys_user` WRITE;
+/*!40000 ALTER TABLE `sys_user` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sys_user` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2025-02-13 0:32:39
diff --git a/sql/SAMS-2025_02_13_12_11_06-dump.sql b/sql/SAMS-2025_02_13_12_11_06-dump.sql
new file mode 100644
index 00000000..87a56f4f
--- /dev/null
+++ b/sql/SAMS-2025_02_13_12_11_06-dump.sql
@@ -0,0 +1,435 @@
+-- MySQL dump 10.13 Distrib 8.0.41, for Linux (x86_64)
+--
+-- Host: 127.0.0.1 Database: SAMS
+-- ------------------------------------------------------
+-- Server version 8.0.41-0ubuntu0.22.04.1
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!50503 SET NAMES utf8mb4 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `ams_activity`
+--
+
+DROP TABLE IF EXISTS `ams_activity`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_activity` (
+ `act_id` bigint NOT NULL AUTO_INCREMENT COMMENT '活动ID',
+ `title` varchar(100) NOT NULL COMMENT '活动标题',
+ `description` text COMMENT '活动描述',
+ `start_time` datetime NOT NULL COMMENT '开始时间',
+ `end_time` datetime NOT NULL COMMENT '结束时间',
+ `location` varchar(255) DEFAULT NULL COMMENT '地点',
+ `budget` decimal(10,2) DEFAULT '0.00' COMMENT '预算',
+ `max_participants` int DEFAULT NULL COMMENT '最大参与人数',
+ `creator_id` bigint NOT NULL COMMENT '创建者ID',
+ `club_id` bigint DEFAULT NULL COMMENT '所属社团ID',
+ `visibility` enum('public','private') DEFAULT 'public' COMMENT '是否公开',
+ `status` enum('draft','approved','ongoing','completed','cancelled') DEFAULT 'draft' COMMENT '活动状态',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
+ PRIMARY KEY (`act_id`),
+ KEY `creator_id` (`creator_id`),
+ KEY `club_id` (`club_id`),
+ CONSTRAINT `ams_activity_ibfk_1` FOREIGN KEY (`creator_id`) REFERENCES `sys_user` (`user_id`),
+ CONSTRAINT `ams_activity_ibfk_2` FOREIGN KEY (`club_id`) REFERENCES `sms_club` (`club_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_activity`
+--
+
+LOCK TABLES `ams_activity` WRITE;
+/*!40000 ALTER TABLE `ams_activity` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_activity` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_approval`
+--
+
+DROP TABLE IF EXISTS `ams_approval`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_approval` (
+ `appr_id` bigint NOT NULL AUTO_INCREMENT COMMENT '审批ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `user_id` bigint NOT NULL COMMENT '发起者ID',
+ `approver_id` bigint NOT NULL COMMENT '审批人ID',
+ `status` tinyint(1) DEFAULT '0' COMMENT '审批状态 (0: 待审批, 1: 通过, 2: 拒绝)',
+ `reason` text COMMENT '拒绝原因(如果适用)',
+ `approved_at` datetime DEFAULT NULL COMMENT '审批时间',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`appr_id`),
+ KEY `act_id` (`act_id`),
+ KEY `user_id` (`user_id`),
+ KEY `approver_id` (`approver_id`),
+ CONSTRAINT `ams_approval_ibfk_1` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`),
+ CONSTRAINT `ams_approval_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`),
+ CONSTRAINT `ams_approval_ibfk_3` FOREIGN KEY (`approver_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动审批表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_approval`
+--
+
+LOCK TABLES `ams_approval` WRITE;
+/*!40000 ALTER TABLE `ams_approval` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_approval` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_comment`
+--
+
+DROP TABLE IF EXISTS `ams_comment`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_comment` (
+ `comment_id` bigint NOT NULL AUTO_INCREMENT COMMENT '评论ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `parent_comment_id` bigint DEFAULT NULL COMMENT '父评论ID(为空表示是顶级评论)',
+ `content` text NOT NULL COMMENT '评论内容',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '评论时间',
+ PRIMARY KEY (`comment_id`),
+ KEY `user_id` (`user_id`),
+ KEY `act_id` (`act_id`),
+ KEY `ams_comment_ibfk_3` (`parent_comment_id`),
+ CONSTRAINT `ams_comment_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE CASCADE,
+ CONSTRAINT `ams_comment_ibfk_2` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`) ON DELETE CASCADE,
+ CONSTRAINT `ams_comment_ibfk_3` FOREIGN KEY (`parent_comment_id`) REFERENCES `ams_comment` (`comment_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动评论表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_comment`
+--
+
+LOCK TABLES `ams_comment` WRITE;
+/*!40000 ALTER TABLE `ams_comment` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_comment` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_reaction`
+--
+
+DROP TABLE IF EXISTS `ams_reaction`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_reaction` (
+ `reaction_id` bigint NOT NULL AUTO_INCREMENT COMMENT '点赞/点踩ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `reaction_type` enum('like','dislike') NOT NULL COMMENT '反应类型(like: 点赞, dislike: 点踩)',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '反应时间',
+ PRIMARY KEY (`reaction_id`),
+ UNIQUE KEY `uniq_user_activity_reaction` (`user_id`,`act_id`),
+ KEY `act_id` (`act_id`),
+ CONSTRAINT `ams_reaction_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE CASCADE,
+ CONSTRAINT `ams_reaction_ibfk_2` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动点赞/点踩表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_reaction`
+--
+
+LOCK TABLES `ams_reaction` WRITE;
+/*!40000 ALTER TABLE `ams_reaction` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_reaction` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ams_registration`
+--
+
+DROP TABLE IF EXISTS `ams_registration`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `ams_registration` (
+ `reg_id` bigint NOT NULL AUTO_INCREMENT COMMENT '报名ID',
+ `act_id` bigint NOT NULL COMMENT '活动ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `status` enum('registered','cancelled','attended','absent') DEFAULT 'registered' COMMENT '报名状态',
+ `register_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '报名时间',
+ `attend_time` datetime DEFAULT NULL COMMENT '参与时间',
+ PRIMARY KEY (`reg_id`),
+ KEY `act_id` (`act_id`),
+ KEY `user_id` (`user_id`),
+ CONSTRAINT `ams_registration_ibfk_1` FOREIGN KEY (`act_id`) REFERENCES `ams_activity` (`act_id`),
+ CONSTRAINT `ams_registration_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='活动报名表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `ams_registration`
+--
+
+LOCK TABLES `ams_registration` WRITE;
+/*!40000 ALTER TABLE `ams_registration` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ams_registration` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sms_club`
+--
+
+DROP TABLE IF EXISTS `sms_club`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sms_club` (
+ `club_id` bigint NOT NULL AUTO_INCREMENT COMMENT '社团ID',
+ `club_name` varchar(50) NOT NULL COMMENT '社团名称',
+ `description` text COMMENT '社团简介',
+ `category` enum('文化艺术','学术科技','社会公益','其他') NOT NULL COMMENT '社团类型',
+ `college_id` bigint NOT NULL COMMENT '所属院系',
+ `leader_id` bigint DEFAULT NULL COMMENT '负责人ID',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`club_id`),
+ KEY `college_id` (`college_id`),
+ KEY `leader_id` (`leader_id`),
+ CONSTRAINT `sms_club_ibfk_1` FOREIGN KEY (`college_id`) REFERENCES `sms_college` (`college_id`),
+ CONSTRAINT `sms_club_ibfk_2` FOREIGN KEY (`leader_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='社团表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sms_club`
+--
+
+LOCK TABLES `sms_club` WRITE;
+/*!40000 ALTER TABLE `sms_club` DISABLE KEYS */;
+INSERT INTO `sms_club` VALUES (1,'编程爱好者协会','学习编程、算法与开发','学术科技',2,2,'2025-02-13 11:43:50'),(2,'篮球社','喜欢打篮球的同学们','其他',3,3,'2025-02-13 11:43:50');
+/*!40000 ALTER TABLE `sms_club` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sms_college`
+--
+
+DROP TABLE IF EXISTS `sms_college`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sms_college` (
+ `college_id` bigint NOT NULL AUTO_INCREMENT COMMENT '院系ID',
+ `college_name` varchar(255) NOT NULL COMMENT '名称(高校或院系)',
+ `parent_id` bigint DEFAULT NULL COMMENT '父院系ID(高校此值为空)',
+ `email` varchar(50) DEFAULT '' COMMENT '邮箱',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`college_id`),
+ KEY `parent_id` (`parent_id`),
+ CONSTRAINT `sms_college_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `sms_college` (`college_id`) ON DELETE SET NULL
+) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='高校及院系表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sms_college`
+--
+
+LOCK TABLES `sms_college` WRITE;
+/*!40000 ALTER TABLE `sms_college` DISABLE KEYS */;
+INSERT INTO `sms_college` VALUES (1,'山东建筑大学',NULL,'contact@sdu.edu.cn','2025-02-13 11:40:45'),(2,'计算机科学与技术学院',1,'cs@sdu.edu.cn','2025-02-13 11:40:45'),(3,'土木工程学院',1,'civil@sdu.edu.cn','2025-02-13 11:40:45'),(4,'管理工程学院',1,'contact4@sdu.edu.cn','2025-02-13 11:51:12'),(5,'热能工程学院',1,'contact5@sdu.edu.cn','2025-02-13 11:51:12'),(6,'市政与环境工程学院',1,'contact6@sdu.edu.cn','2025-02-13 11:51:12'),(7,'机电工程学院',1,'contact7@sdu.edu.cn','2025-02-13 11:51:12'),(8,'理学院',1,'contact8@sdu.edu.cn','2025-02-13 11:51:12'),(9,'商学院',1,'contact9@sdu.edu.cn','2025-02-13 11:51:12'),(10,'交通工程学院',1,'contact10@sdu.edu.cn','2025-02-13 11:51:12'),(11,'艺术学院',1,'contact11@sdu.edu.cn','2025-02-13 11:51:12'),(12,'法学院',1,'contact12@sdu.edu.cn','2025-02-13 11:51:12'),(13,'外国语学院',1,'contact13@sdu.edu.cn','2025-02-13 11:51:12'),(20,'山东大学',NULL,'contact@su.edu.cn','2025-02-13 11:52:27'),(21,'计算机科学与技术学院',2,'cs@sdu.edu.cn','2025-02-13 11:52:48'),(22,'土木工程学院',2,'civil@sdu.edu.cn','2025-02-13 11:52:48'),(23,'管理工程学院',2,'contact4@sdu.edu.cn','2025-02-13 11:52:48'),(24,'热能工程学院',2,'contact5@sdu.edu.cn','2025-02-13 11:52:48'),(25,'市政与环境工程学院',2,'contact6@sdu.edu.cn','2025-02-13 11:52:48'),(26,'机电工程学院',2,'contact7@sdu.edu.cn','2025-02-13 11:52:48'),(27,'理学院',2,'contact8@sdu.edu.cn','2025-02-13 11:52:48'),(28,'商学院',2,'contact9@sdu.edu.cn','2025-02-13 11:52:48'),(29,'交通工程学院',2,'contact10@sdu.edu.cn','2025-02-13 11:52:48'),(30,'艺术学院',2,'contact11@sdu.edu.cn','2025-02-13 11:52:48'),(31,'法学院',2,'contact12@sdu.edu.cn','2025-02-13 11:52:48'),(32,'外国语学院',2,'contact13@sdu.edu.cn','2025-02-13 11:52:48');
+/*!40000 ALTER TABLE `sms_college` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sms_college_leader`
+--
+
+DROP TABLE IF EXISTS `sms_college_leader`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sms_college_leader` (
+ `college_id` bigint NOT NULL COMMENT '院系ID',
+ `user_id` bigint NOT NULL COMMENT '负责人ID',
+ `assigned_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '指派时间',
+ PRIMARY KEY (`college_id`,`user_id`),
+ KEY `user_id` (`user_id`),
+ CONSTRAINT `sms_college_leader_ibfk_1` FOREIGN KEY (`college_id`) REFERENCES `sms_college` (`college_id`) ON DELETE CASCADE,
+ CONSTRAINT `sms_college_leader_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='院系负责人表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sms_college_leader`
+--
+
+LOCK TABLES `sms_college_leader` WRITE;
+/*!40000 ALTER TABLE `sms_college_leader` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sms_college_leader` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sms_user_club`
+--
+
+DROP TABLE IF EXISTS `sms_user_club`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sms_user_club` (
+ `suc_id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `club_id` bigint NOT NULL COMMENT '社团ID',
+ `role_id` bigint NOT NULL COMMENT '角色ID',
+ `is_active` tinyint(1) DEFAULT '1' COMMENT '是否活跃',
+ `join_date` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '加入日期',
+ PRIMARY KEY (`suc_id`),
+ UNIQUE KEY `uniq_user_club` (`user_id`,`club_id`),
+ KEY `club_id` (`club_id`),
+ KEY `role_id` (`role_id`),
+ CONSTRAINT `sms_user_club_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`),
+ CONSTRAINT `sms_user_club_ibfk_2` FOREIGN KEY (`club_id`) REFERENCES `sms_club` (`club_id`),
+ CONSTRAINT `sms_user_club_ibfk_3` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户社团关系表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sms_user_club`
+--
+
+LOCK TABLES `sms_user_club` WRITE;
+/*!40000 ALTER TABLE `sms_user_club` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sms_user_club` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_logs`
+--
+
+DROP TABLE IF EXISTS `sys_logs`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_logs` (
+ `log_id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志ID',
+ `user_id` bigint NOT NULL COMMENT '用户ID',
+ `action` varchar(255) NOT NULL COMMENT '操作类型',
+ `description` text COMMENT '描述',
+ `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间',
+ PRIMARY KEY (`log_id`),
+ KEY `idx_user_id` (`user_id`),
+ CONSTRAINT `sys_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统日志表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_logs`
+--
+
+LOCK TABLES `sys_logs` WRITE;
+/*!40000 ALTER TABLE `sys_logs` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sys_logs` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_notification`
+--
+
+DROP TABLE IF EXISTS `sys_notification`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_notification` (
+ `notification_id` bigint NOT NULL AUTO_INCREMENT COMMENT '通知ID',
+ `title` varchar(255) NOT NULL COMMENT '通知标题',
+ `content` text NOT NULL COMMENT '通知内容',
+ `receiver_id` bigint NOT NULL COMMENT '接收者ID',
+ `is_read` tinyint(1) DEFAULT '0' COMMENT '是否已读',
+ `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`notification_id`),
+ KEY `idx_receiver_id` (`receiver_id`),
+ CONSTRAINT `sys_notification_ibfk_1` FOREIGN KEY (`receiver_id`) REFERENCES `sys_user` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统通知表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_notification`
+--
+
+LOCK TABLES `sys_notification` WRITE;
+/*!40000 ALTER TABLE `sys_notification` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sys_notification` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_role`
+--
+
+DROP TABLE IF EXISTS `sys_role`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_role` (
+ `role_id` bigint NOT NULL AUTO_INCREMENT COMMENT '角色ID',
+ `role_name` varchar(30) NOT NULL COMMENT '角色名称',
+ `role_key` varchar(64) NOT NULL COMMENT '角色标识',
+ `role_desc` varchar(255) DEFAULT NULL COMMENT '角色描述',
+ `status` enum('active','inactive') DEFAULT 'active' COMMENT '状态',
+ PRIMARY KEY (`role_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户角色表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_role`
+--
+
+LOCK TABLES `sys_role` WRITE;
+/*!40000 ALTER TABLE `sys_role` DISABLE KEYS */;
+INSERT INTO `sys_role` VALUES (0,'系统管理员','admin','最高权限,管理所有用户与活动','active'),(1,'参与者','participant','普通用户,可以报名活动、评论、点赞','active'),(2,'管理员','leader','管理活动和人员','active');
+/*!40000 ALTER TABLE `sys_role` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sys_user`
+--
+
+DROP TABLE IF EXISTS `sys_user`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sys_user` (
+ `user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
+ `role_id` bigint NOT NULL COMMENT '用户角色',
+ `nick_name` varchar(30) DEFAULT '' COMMENT '用户昵称',
+ `user_name` varchar(30) NOT NULL COMMENT '真实姓名',
+ `password` varchar(100) NOT NULL COMMENT '用户密码',
+ `school_id` char(12) NOT NULL COMMENT '学号/教职工号',
+ `college_id` bigint DEFAULT NULL COMMENT '所属院系',
+ `email` varchar(50) DEFAULT '' COMMENT '用户邮箱',
+ `avatar` varchar(100) DEFAULT '' COMMENT '头像地址',
+ `status` enum('active','inactive','banned') DEFAULT 'active' COMMENT '账号状态',
+ PRIMARY KEY (`user_id`),
+ KEY `role_id` (`role_id`),
+ CONSTRAINT `sys_user_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统用户表';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `sys_user`
+--
+
+LOCK TABLES `sys_user` WRITE;
+/*!40000 ALTER TABLE `sys_user` DISABLE KEYS */;
+INSERT INTO `sys_user` VALUES (1,1,'张三','zhangsan','password123','202511110001',2,'zhangsan@example.com','avatar1.jpg','active'),(2,2,'李四','lisi','password123','202511110002',2,'lisi@example.com','avatar2.jpg','active'),(3,2,'王五','wangwu','password123','202511110003',2,'wangwu@example.com','avatar3.jpg','active'),(4,1,'赵六','zhaoliu','password123','202511110004',3,'zhaoliu@example.com','avatar4.jpg','active'),(6,1,'用户6','user6','password123','202588456301',4,'user6@example.com','avatar6.jpg','active'),(7,1,'用户7','user7','password123','202598705123',5,'user7@example.com','avatar7.jpg','active'),(8,1,'用户8','user8','password123','202556098765',6,'user8@example.com','avatar8.jpg','active'),(9,1,'用户9','user9','password123','202512340987',7,'user9@example.com','avatar9.jpg','active'),(10,1,'用户10','user10','password123','202599888222',8,'user10@example.com','avatar10.jpg','active'),(11,1,'用户11','user11','password123','202533665588',9,'user11@example.com','avatar11.jpg','active'),(12,1,'用户12','user12','password123','202500112233',10,'user12@example.com','avatar12.jpg','active'),(13,1,'用户13','user13','password123','202511122233',11,'user13@example.com','avatar13.jpg','active'),(14,1,'用户14','user14','password123','202522334455',12,'user14@example.com','avatar14.jpg','active'),(15,1,'用户15','user15','password123','202544556677',13,'user15@example.com','avatar15.jpg','active'),(16,1,'用户16','user16','password123','202566778899',4,'user16@example.com','avatar16.jpg','active'),(17,1,'用户17','user17','password123','202577889900',5,'user17@example.com','avatar17.jpg','active'),(18,1,'用户18','user18','password123','202500998877',6,'user18@example.com','avatar18.jpg','active'),(19,1,'用户19','user19','password123','202511223344',7,'user19@example.com','avatar19.jpg','active'),(20,1,'用户20','user20','password123','202522334455',8,'user20@example.com','avatar20.jpg','active'),(21,1,'用户21','user21','password123','202533445566',9,'user21@example.com','avatar21.jpg','active'),(22,1,'用户22','user22','password123','202544556677',10,'user22@example.com','avatar22.jpg','active'),(23,1,'用户23','user23','password123','202555667788',11,'user23@example.com','avatar23.jpg','active'),(24,1,'用户24','user24','password123','202566778899',12,'user24@example.com','avatar24.jpg','active'),(25,1,'用户25','user25','password123','202577889900',13,'user25@example.com','avatar25.jpg','active'),(26,1,'用户26','user26','password123','202588990011',4,'user26@example.com','avatar26.jpg','active'),(27,1,'用户27','user27','password123','202599001122',5,'user27@example.com','avatar27.jpg','active'),(28,1,'用户28','user28','password123','202511223344',6,'user28@example.com','avatar28.jpg','active'),(29,1,'用户29','user29','password123','202522334455',7,'user29@example.com','avatar29.jpg','active'),(30,1,'用户30','user30','password123','202533445566',8,'user30@example.com','avatar30.jpg','active');
+/*!40000 ALTER TABLE `sys_user` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2025-02-13 12:11:06
diff --git a/src/main/java/com/bruce/sams/config/SecurityConfig.java b/src/main/java/com/bruce/sams/config/SecurityConfig.java
new file mode 100644
index 00000000..8395b194
--- /dev/null
+++ b/src/main/java/com/bruce/sams/config/SecurityConfig.java
@@ -0,0 +1,32 @@
+package com.bruce.sams.config;
+
+import com.bruce.sams.filters.JwtAuthFilter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+/**
+ * Spring Security 配置类
+ */
+@Configuration
+@EnableWebSecurity
+public class SecurityConfig {
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ http
+ .csrf(csrf -> csrf.disable())
+ .authorizeHttpRequests(auth -> auth
+ .requestMatchers("/api/auth/login").permitAll()
+ .requestMatchers("/admin/**").hasAuthority("leader")
+ .requestMatchers("/user/**").hasAuthority("participant")
+ .anyRequest().authenticated()
+ )
+ .addFilterBefore(new JwtAuthFilter(), UsernamePasswordAuthenticationFilter.class);
+
+ return http.build();
+ }
+}
diff --git a/src/main/java/com/bruce/sams/controller/AuthController.java b/src/main/java/com/bruce/sams/controller/AuthController.java
new file mode 100644
index 00000000..7a6405b5
--- /dev/null
+++ b/src/main/java/com/bruce/sams/controller/AuthController.java
@@ -0,0 +1,42 @@
+package com.bruce.sams.controller;
+
+import com.bruce.sams.domain.entity.LoginRequest;
+import com.bruce.sams.service.AuthService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 认证控制器,处理用户登录请求
+ */
+@RestController
+@RequestMapping("/api/auth")
+public class AuthController {
+
+ @Autowired
+ private AuthService authService;
+
+ /**
+ * 处理用户登录请求,支持用户名、学号、邮箱 登录
+ *
+ * @param loginRequest 登录请求体
+ * @return JWT 令牌 或 错误信息
+ */
+ @PostMapping("/login")
+ public Map login(@RequestBody LoginRequest loginRequest) {
+ Map response = new HashMap<>();
+
+ // 进行认证
+ String token = authService.authenticate(loginRequest);
+
+ // 返回结果
+ if (token != null) {
+ response.put("token", token);
+ } else {
+ response.put("error", "Invalid credentials");
+ }
+ return response;
+ }
+}
diff --git a/src/main/java/com/bruce/sams/domain/entity/LoginRequest.java b/src/main/java/com/bruce/sams/domain/entity/LoginRequest.java
new file mode 100644
index 00000000..f785bfca
--- /dev/null
+++ b/src/main/java/com/bruce/sams/domain/entity/LoginRequest.java
@@ -0,0 +1,15 @@
+package com.bruce.sams.domain.entity;
+
+import lombok.Data;
+
+/**
+ * 登录请求实体类
+ * 支持用户名(username)、学号(schoolId)、邮箱(email)+ 密码(password) 登录
+ */
+@Data
+public class LoginRequest {
+ private String username;
+ private String schoolId;
+ private String email;
+ private String password;
+}
diff --git a/src/main/java/com/bruce/sams/domain/sys/Role.java b/src/main/java/com/bruce/sams/domain/sys/Role.java
new file mode 100644
index 00000000..7c4d3913
--- /dev/null
+++ b/src/main/java/com/bruce/sams/domain/sys/Role.java
@@ -0,0 +1,86 @@
+package com.bruce.sams.domain.sys;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * 用户角色表
+ * @TableName sys_role
+ */
+@TableName(value ="sys_role")
+@Data
+public class Role {
+ /**
+ * 角色ID
+ */
+ @TableId(type = IdType.AUTO)
+ private Long roleId;
+
+ /**
+ * 角色名称
+ */
+ private String roleName;
+
+ /**
+ * 角色标识
+ */
+ private String roleKey;
+
+ /**
+ * 角色描述
+ */
+ private String roleDesc;
+
+ /**
+ * 状态
+ */
+ private Object status;
+
+ @Override
+ public boolean equals(Object that) {
+ if (this == that) {
+ return true;
+ }
+ if (that == null) {
+ return false;
+ }
+ if (getClass() != that.getClass()) {
+ return false;
+ }
+ Role other = (Role) that;
+ return (this.getRoleId() == null ? other.getRoleId() == null : this.getRoleId().equals(other.getRoleId()))
+ && (this.getRoleName() == null ? other.getRoleName() == null : this.getRoleName().equals(other.getRoleName()))
+ && (this.getRoleKey() == null ? other.getRoleKey() == null : this.getRoleKey().equals(other.getRoleKey()))
+ && (this.getRoleDesc() == null ? other.getRoleDesc() == null : this.getRoleDesc().equals(other.getRoleDesc()))
+ && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()));
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((getRoleId() == null) ? 0 : getRoleId().hashCode());
+ result = prime * result + ((getRoleName() == null) ? 0 : getRoleName().hashCode());
+ result = prime * result + ((getRoleKey() == null) ? 0 : getRoleKey().hashCode());
+ result = prime * result + ((getRoleDesc() == null) ? 0 : getRoleDesc().hashCode());
+ result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getClass().getSimpleName());
+ sb.append(" [");
+ sb.append("Hash = ").append(hashCode());
+ sb.append(", roleId=").append(roleId);
+ sb.append(", roleName=").append(roleName);
+ sb.append(", roleKey=").append(roleKey);
+ sb.append(", roleDesc=").append(roleDesc);
+ sb.append(", status=").append(status);
+ sb.append("]");
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/bruce/sams/domain/sys/User.java b/src/main/java/com/bruce/sams/domain/sys/User.java
new file mode 100644
index 00000000..315ba435
--- /dev/null
+++ b/src/main/java/com/bruce/sams/domain/sys/User.java
@@ -0,0 +1,126 @@
+package com.bruce.sams.domain.sys;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * 系统用户表
+ * @TableName sys_user
+ */
+@TableName(value ="sys_user")
+@Data
+public class User {
+ /**
+ * 用户ID
+ */
+ @TableId(type = IdType.AUTO)
+ private Long userId;
+
+ /**
+ * 用户角色
+ */
+ private Long roleId;
+
+ /**
+ * 用户昵称
+ */
+ private String nickName;
+
+ /**
+ * 真实姓名
+ */
+ private String userName;
+
+ /**
+ * 用户密码
+ */
+ private String password;
+
+ /**
+ * 学号/教职工号
+ */
+ private String schoolId;
+
+ /**
+ * 所属院系
+ */
+ private Long collegeId;
+
+ /**
+ * 用户邮箱
+ */
+ private String email;
+
+ /**
+ * 头像地址
+ */
+ private String avatar;
+
+ /**
+ * 账号状态
+ */
+ private Object status;
+
+ @Override
+ public boolean equals(Object that) {
+ if (this == that) {
+ return true;
+ }
+ if (that == null) {
+ return false;
+ }
+ if (getClass() != that.getClass()) {
+ return false;
+ }
+ User other = (User) that;
+ return (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId()))
+ && (this.getRoleId() == null ? other.getRoleId() == null : this.getRoleId().equals(other.getRoleId()))
+ && (this.getNickName() == null ? other.getNickName() == null : this.getNickName().equals(other.getNickName()))
+ && (this.getUserName() == null ? other.getUserName() == null : this.getUserName().equals(other.getUserName()))
+ && (this.getPassword() == null ? other.getPassword() == null : this.getPassword().equals(other.getPassword()))
+ && (this.getSchoolId() == null ? other.getSchoolId() == null : this.getSchoolId().equals(other.getSchoolId()))
+ && (this.getCollegeId() == null ? other.getCollegeId() == null : this.getCollegeId().equals(other.getCollegeId()))
+ && (this.getEmail() == null ? other.getEmail() == null : this.getEmail().equals(other.getEmail()))
+ && (this.getAvatar() == null ? other.getAvatar() == null : this.getAvatar().equals(other.getAvatar()))
+ && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()));
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode());
+ result = prime * result + ((getRoleId() == null) ? 0 : getRoleId().hashCode());
+ result = prime * result + ((getNickName() == null) ? 0 : getNickName().hashCode());
+ result = prime * result + ((getUserName() == null) ? 0 : getUserName().hashCode());
+ result = prime * result + ((getPassword() == null) ? 0 : getPassword().hashCode());
+ result = prime * result + ((getSchoolId() == null) ? 0 : getSchoolId().hashCode());
+ result = prime * result + ((getCollegeId() == null) ? 0 : getCollegeId().hashCode());
+ result = prime * result + ((getEmail() == null) ? 0 : getEmail().hashCode());
+ result = prime * result + ((getAvatar() == null) ? 0 : getAvatar().hashCode());
+ result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getClass().getSimpleName());
+ sb.append(" [");
+ sb.append("Hash = ").append(hashCode());
+ sb.append(", userId=").append(userId);
+ sb.append(", roleId=").append(roleId);
+ sb.append(", nickName=").append(nickName);
+ sb.append(", userName=").append(userName);
+ sb.append(", password=").append(password);
+ sb.append(", schoolId=").append(schoolId);
+ sb.append(", collegeId=").append(collegeId);
+ sb.append(", email=").append(email);
+ sb.append(", avatar=").append(avatar);
+ sb.append(", status=").append(status);
+ sb.append("]");
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/bruce/sams/filters/JwtAuthFilter.java b/src/main/java/com/bruce/sams/filters/JwtAuthFilter.java
new file mode 100644
index 00000000..4a14173f
--- /dev/null
+++ b/src/main/java/com/bruce/sams/filters/JwtAuthFilter.java
@@ -0,0 +1,48 @@
+package com.bruce.sams.filters;
+
+import com.bruce.sams.utils.TokenUtil;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+/**
+ * JWT 认证过滤器,解析 Token 并设置用户身份
+ */
+@Component
+public class JwtAuthFilter extends OncePerRequestFilter {
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+ throws ServletException, IOException {
+
+ // 获取请求头中的 Authorization 令牌
+ String token = request.getHeader("Authorization");
+
+ // 判断令牌是否存在且以 "Bearer " 开头
+ if (token != null && token.startsWith("Bearer ")) {
+ token = token.substring(7); // 去掉 "Bearer " 前缀
+ try {
+ // 解析 JWT 令牌
+ String schoolId = TokenUtil.getSubjectFromToken(token);
+ String role = TokenUtil.getRoleFromToken(token);
+
+ // 设置认证信息
+ SecurityContextHolder.getContext().setAuthentication(
+ new UsernamePasswordAuthenticationToken(schoolId, null, null));
+ } catch (Exception e) {
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid Token");
+ return;
+ }
+ }
+
+ // 继续执行过滤器链
+ filterChain.doFilter(request, response);
+ }
+}
diff --git a/src/main/java/com/bruce/sams/mapper/SysRoleMapper.java b/src/main/java/com/bruce/sams/mapper/SysRoleMapper.java
new file mode 100644
index 00000000..be500a8e
--- /dev/null
+++ b/src/main/java/com/bruce/sams/mapper/SysRoleMapper.java
@@ -0,0 +1,23 @@
+package com.bruce.sams.mapper;
+
+import com.bruce.sams.domain.sys.Role;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+
+/**
+* @author bruce
+* @description 针对表【sys_role(用户角色表)】的数据库操作Mapper
+* @createDate 2025-02-13 12:15:35
+* @Entity generator.domain.SysRole
+*/
+@Mapper
+public interface SysRoleMapper extends BaseMapper {
+ @Select("SELECT * FROM sys_role WHERE role_id = #{roleId}")
+ Role findByRoleId(Long roleId);
+
+}
+
+
+
+
diff --git a/src/main/java/com/bruce/sams/mapper/SysUserMapper.java b/src/main/java/com/bruce/sams/mapper/SysUserMapper.java
new file mode 100644
index 00000000..72bf950a
--- /dev/null
+++ b/src/main/java/com/bruce/sams/mapper/SysUserMapper.java
@@ -0,0 +1,29 @@
+package com.bruce.sams.mapper;
+
+import com.bruce.sams.domain.sys.User;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+
+@Mapper
+public interface SysUserMapper extends BaseMapper {
+
+ // 通过用户名查询用户
+ @Select("SELECT * FROM sys_user WHERE user_name = #{identifier}")
+ User findByUsername(String identifier);
+
+ // 通过学号查询用户
+ @Select("SELECT * FROM sys_user WHERE school_id = #{identifier}")
+ User findBySchoolId(String identifier);
+
+ // 通过邮箱查询用户
+ @Select("SELECT * FROM sys_user WHERE email = #{identifier}")
+ User findByEmail(String identifier);
+}
+
+
+
+
+
+
+
diff --git a/src/main/java/com/bruce/sams/service/AuthService.java b/src/main/java/com/bruce/sams/service/AuthService.java
new file mode 100644
index 00000000..be8a5f73
--- /dev/null
+++ b/src/main/java/com/bruce/sams/service/AuthService.java
@@ -0,0 +1,16 @@
+package com.bruce.sams.service;
+
+import com.bruce.sams.domain.entity.LoginRequest;
+
+/**
+ * 认证服务类
+ */
+public interface AuthService {
+ /**
+ * 处理用户认证,支持用户名、学号、邮箱登录
+ *
+ * @param loginRequest 登录请求体(包含 username / schoolId / email + password)
+ * @return JWT 令牌(成功)或 null(失败)
+ */
+ public String authenticate(LoginRequest loginRequest);
+}
diff --git a/src/main/java/com/bruce/sams/service/impl/AuthServiceImpl.java b/src/main/java/com/bruce/sams/service/impl/AuthServiceImpl.java
new file mode 100644
index 00000000..7120aa77
--- /dev/null
+++ b/src/main/java/com/bruce/sams/service/impl/AuthServiceImpl.java
@@ -0,0 +1,51 @@
+package com.bruce.sams.service.impl;
+
+import com.bruce.sams.domain.entity.LoginRequest;
+import com.bruce.sams.mapper.SysRoleMapper;
+import com.bruce.sams.mapper.SysUserMapper;
+import com.bruce.sams.domain.sys.User;
+import com.bruce.sams.utils.TokenUtil;
+import com.bruce.sams.service.AuthService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 认证服务类,支持 用户名、学号、邮箱 登录
+ */
+@Service
+public class AuthServiceImpl implements AuthService {
+
+ @Autowired
+ private SysUserMapper userMapper;
+
+ @Autowired
+ private SysRoleMapper roleMapper;
+
+ /**
+ * 处理用户认证,支持用户名、学号、邮箱登录
+ *
+ * @param loginRequest 登录请求体(包含 username / schoolId / email + password)
+ * @return JWT 令牌(成功)或 null(失败)
+ */
+ public String authenticate(LoginRequest loginRequest) {
+ User user = null;
+
+ // 根据提供的信息查询用户
+ if (loginRequest.getUsername() != null) {
+ user = userMapper.findByUsername(loginRequest.getUsername());
+ } else if (loginRequest.getSchoolId() != null) {
+ user = userMapper.findBySchoolId(loginRequest.getSchoolId());
+ } else if (loginRequest.getEmail() != null) {
+ user = userMapper.findByEmail(loginRequest.getEmail());
+ }
+
+ // 校验用户是否存在,并检查密码
+ if (user != null && user.getPassword().equals(loginRequest.getPassword())) {
+ String role = roleMapper.findByRoleId(user.getRoleId()).getRoleKey();
+ // 生成 JWT 令牌
+ return TokenUtil.generateToken(user.getSchoolId(), role);
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/com/bruce/sams/utils/TokenUtil.java b/src/main/java/com/bruce/sams/utils/TokenUtil.java
new file mode 100644
index 00000000..82d81f42
--- /dev/null
+++ b/src/main/java/com/bruce/sams/utils/TokenUtil.java
@@ -0,0 +1,97 @@
+package com.bruce.sams.utils;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.security.Keys;
+
+import javax.crypto.SecretKey;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.HashMap;
+
+public class TokenUtil {
+
+
+ private static final String SECRET_KEY = "F8GdYh2EluWiWOGMEErxosf6vcdxbuDhS-Bc5KwA8lo";
+ private static final long EXPIRATION_TIME = 1000 * 60 * 60; // 1小时
+
+ private static SecretKey getSigningKey() {
+ byte[] keyBytes = SECRET_KEY.getBytes(StandardCharsets.UTF_8);
+ return Keys.hmacShaKeyFor(keyBytes);
+ }
+
+ /**
+ * 生成JWT令牌
+ *
+ * @param username 需要包含的声明
+ * @param role 令牌主体
+ * @return 生成的JWT字符串
+ */
+ public static String generateToken(String username , String role) {
+ HashMap claims = new HashMap<>();
+ claims.put("role", role);
+ return Jwts.builder()
+ .subject(username)
+ .claims(claims)
+ .issuedAt(new Date())
+ .expiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
+ .signWith(getSigningKey())
+ .compact();
+ }
+
+ /**
+ * 解析JWT令牌
+ *
+ * @param token JWT字符串
+ * @return 解析后的Claims
+ */
+ public static Claims parseToken(String token) {
+ return Jwts.parser()
+ .verifyWith(getSigningKey())
+ .build()
+ .parseSignedClaims(token)
+ .getPayload();
+ }
+
+ /**
+ * 从令牌中获取用户名
+ *
+ * @param token JWT字符串
+ * @return 令牌中的subject
+ */
+ public static String getSubjectFromToken(String token) {
+ return parseToken(token).getSubject();
+ }
+
+ /**
+ * 从令牌中获取角色信息
+ *
+ * @param token JWT字符串
+ * @return 令牌中的subject
+ */
+ public static String getRoleFromToken(String token) {
+ return parseToken(token).get("role").toString();
+ }
+
+ /**
+ * 检查JWT令牌是否过期
+ *
+ * @param token JWT字符串
+ * @return true 如果令牌过期,否则 false
+ */
+ public static boolean isTokenExpired(String token) {
+ Date expiration = parseToken(token).getExpiration();
+ return expiration.before(new Date());
+ }
+
+ /**
+ * 验证JWT令牌
+ *
+ * @param token JWT字符串
+ * @param subject 需要匹配的主体
+ * @return true 如果令牌有效,否则 false
+ */
+ public static boolean validateToken(String token, String subject) {
+ return subject.equals(getSubjectFromToken(token)) && !isTokenExpired(token);
+ }
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 88a93f83..b687694f 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -4,6 +4,6 @@ spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
- url:
+ url: jdbc:mysql://localhost:3306/SAMS
username: root
password: admin123
\ No newline at end of file
diff --git a/src/main/resources/mapper/SysRoleMapper.xml b/src/main/resources/mapper/SysRoleMapper.xml
new file mode 100644
index 00000000..8981fcbd
--- /dev/null
+++ b/src/main/resources/mapper/SysRoleMapper.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ role_id,role_name,role_key,role_desc,status
+
+
diff --git a/src/main/resources/mapper/SysUserMapper.xml b/src/main/resources/mapper/SysUserMapper.xml
new file mode 100644
index 00000000..79b9e154
--- /dev/null
+++ b/src/main/resources/mapper/SysUserMapper.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ user_id,role_id,nick_name,user_name,password,school_id,
+ college_id,email,avatar,status
+
+