-- =========================================== -- 班级操行分管理系统 - 数据库初始化脚本 -- 数据库: classmanagerdb -- 字符集: utf8mb4 -- -- 开发者: Canglan -- 联系方式: admin@sea-studio.top -- 版权归属: Sea Network Technology Studio -- 许可证: MIT License -- -- 版权所有 © Sea Network Technology Studio -- =========================================== CREATE DATABASE IF NOT EXISTS `classmanagerdb` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE `classmanagerdb`; SET FOREIGN_KEY_CHECKS = 0; -- 学期表 CREATE TABLE IF NOT EXISTS `semesters` ( `semester_id` INT PRIMARY KEY AUTO_INCREMENT, `semester_name` VARCHAR(100) NOT NULL COMMENT '学期名称,如 2025春季学期', `start_date` DATE DEFAULT NULL COMMENT '学期开始日期', `end_date` DATE DEFAULT NULL COMMENT '学期结束日期', `is_active` TINYINT DEFAULT 0 COMMENT '是否为当前活跃学期', `is_archived` TINYINT DEFAULT 0 COMMENT '是否已归档', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 科目表(仅保留语数英) CREATE TABLE IF NOT EXISTS `subjects` ( `subject_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '科目ID', `subject_name` VARCHAR(50) NOT NULL COMMENT '科目名称', `subject_code` VARCHAR(20) DEFAULT NULL COMMENT '科目代码', `is_active` TINYINT DEFAULT 1 COMMENT '是否启用', `sort_order` INT DEFAULT 0 COMMENT '排序序号', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY `uk_subject_name` (`subject_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 学生表(无班级ID) CREATE TABLE IF NOT EXISTS `students` ( `student_id` INT PRIMARY KEY AUTO_INCREMENT, `student_no` VARCHAR(20) NOT NULL UNIQUE, `name` VARCHAR(50) NOT NULL, `total_points` INT DEFAULT 60, `parent_phone` VARCHAR(20) DEFAULT NULL, `status` TINYINT DEFAULT 1, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 用户表 CREATE TABLE IF NOT EXISTS `users` ( `user_id` INT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(50) NOT NULL UNIQUE, `password_hash` VARCHAR(64) NOT NULL, `real_name` VARCHAR(50) NOT NULL, `user_type` ENUM('student', 'parent', 'admin') NOT NULL, `student_id` INT DEFAULT NULL, `status` TINYINT DEFAULT 1, `need_change_password` TINYINT DEFAULT 1, `last_login_time` DATETIME DEFAULT NULL, `last_login_ip` VARCHAR(45) DEFAULT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 管理员角色表(无班级ID) CREATE TABLE IF NOT EXISTS `admin_roles` ( `admin_role_id` INT PRIMARY KEY AUTO_INCREMENT, `user_id` INT NOT NULL, `role_type` ENUM('班主任', '班长', '学习委员', '考勤委员', '劳动委员', '志愿委员') NOT NULL, `subject_id` INT DEFAULT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (`user_id`) REFERENCES `users`(`user_id`) ON DELETE CASCADE, FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`subject_id`) ON DELETE CASCADE, UNIQUE KEY `uk_user_subject` (`user_id`, `subject_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 操行分记录表 CREATE TABLE IF NOT EXISTS `conduct_records` ( `record_id` BIGINT PRIMARY KEY AUTO_INCREMENT, `student_id` INT NOT NULL, `points_change` INT NOT NULL, `reason` VARCHAR(255) NOT NULL, `recorder_id` INT NOT NULL, `recorder_name` VARCHAR(50) DEFAULT NULL, `related_type` ENUM('manual', 'homework', 'attendance') DEFAULT 'manual', `related_id` INT DEFAULT NULL, `is_revoked` TINYINT DEFAULT 0, `revoked_by` INT DEFAULT NULL, `revoked_at` DATETIME DEFAULT NULL, `semester_id` INT DEFAULT NULL COMMENT '所属学期ID', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE, FOREIGN KEY (`recorder_id`) REFERENCES `users`(`user_id`), FOREIGN KEY (`revoked_by`) REFERENCES `users`(`user_id`), FOREIGN KEY (`semester_id`) REFERENCES `semesters`(`semester_id`) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 作业表(无班级ID) CREATE TABLE IF NOT EXISTS `assignments` ( `assignment_id` INT PRIMARY KEY AUTO_INCREMENT, `subject_id` INT NOT NULL, `title` VARCHAR(100) NOT NULL, `description` TEXT, `deadline` DATE NOT NULL, `created_by` INT NOT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`subject_id`), FOREIGN KEY (`created_by`) REFERENCES `users`(`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 作业提交记录表 CREATE TABLE IF NOT EXISTS `homework_submissions` ( `submission_id` INT PRIMARY KEY AUTO_INCREMENT, `assignment_id` INT NOT NULL, `student_id` INT NOT NULL, `status` ENUM('submitted', 'not_submitted', 'late') DEFAULT 'not_submitted', `submit_time` DATETIME DEFAULT NULL, `comments` TEXT, `deduction_applied` TINYINT DEFAULT 0, `deduction_record_id` BIGINT DEFAULT NULL, `updated_by` INT DEFAULT NULL, `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (`assignment_id`) REFERENCES `assignments`(`assignment_id`) ON DELETE CASCADE, FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE, FOREIGN KEY (`deduction_record_id`) REFERENCES `conduct_records`(`record_id`) ON DELETE SET NULL, UNIQUE KEY `uk_assignment_student` (`assignment_id`, `student_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 考勤记录表 CREATE TABLE IF NOT EXISTS `attendance_records` ( `attendance_id` INT PRIMARY KEY AUTO_INCREMENT, `student_id` INT NOT NULL, `date` DATE NOT NULL, `status` ENUM('present', 'absent', 'late', 'leave') DEFAULT 'present', `reason` VARCHAR(255) DEFAULT NULL, `recorder_id` INT NOT NULL, `deduction_applied` TINYINT DEFAULT 0, `deduction_record_id` BIGINT DEFAULT NULL, `semester_id` INT DEFAULT NULL COMMENT '所属学期ID', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE, FOREIGN KEY (`recorder_id`) REFERENCES `users`(`user_id`), FOREIGN KEY (`deduction_record_id`) REFERENCES `conduct_records`(`record_id`) ON DELETE SET NULL, FOREIGN KEY (`semester_id`) REFERENCES `semesters`(`semester_id`) ON DELETE SET NULL, UNIQUE KEY `uk_student_date` (`student_id`, `date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 操作日志表 CREATE TABLE IF NOT EXISTS `operation_logs` ( `log_id` BIGINT PRIMARY KEY AUTO_INCREMENT, `operator_id` INT NOT NULL, `operator_name` VARCHAR(50) DEFAULT NULL, `operator_role` VARCHAR(50) DEFAULT NULL, `operation_type` VARCHAR(50) NOT NULL, `target_type` VARCHAR(50) DEFAULT NULL, `target_id` INT DEFAULT NULL, `details` TEXT, `ip_address` VARCHAR(45) DEFAULT NULL, `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 登录日志表 CREATE TABLE IF NOT EXISTS `login_logs` ( `log_id` BIGINT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(50) NOT NULL, `login_result` TINYINT NOT NULL, `fail_reason` VARCHAR(100) DEFAULT NULL, `ip_address` VARCHAR(45) DEFAULT NULL, `user_agent` VARCHAR(255) DEFAULT NULL, `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- 学期归档快照表 CREATE TABLE IF NOT EXISTS `semester_archives` ( `archive_id` INT PRIMARY KEY AUTO_INCREMENT, `semester_id` INT NOT NULL, `student_id` INT NOT NULL, `student_no` VARCHAR(20) NOT NULL, `student_name` VARCHAR(50) NOT NULL, `final_points` INT NOT NULL COMMENT '学期最终操行分', `rank_position` INT DEFAULT NULL COMMENT '排名', `total_students` INT DEFAULT NULL COMMENT '班级总人数', `archived_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (`semester_id`) REFERENCES `semesters`(`semester_id`), FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; SET FOREIGN_KEY_CHECKS = 1; -- =========================================== -- 迁移语句:为现有表新增字段(仅在字段不存在时添加) -- =========================================== -- conduct_records 表:添加 semester_id 字段(如不存在) SET @column_exists = ( SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'classmanagerdb' AND TABLE_NAME = 'conduct_records' AND COLUMN_NAME = 'semester_id' ); SET @sql = IF(@column_exists = 0, 'ALTER TABLE `conduct_records` ADD COLUMN `semester_id` INT DEFAULT NULL COMMENT ''所属学期ID'' AFTER `revoked_at`', 'SELECT ''conduct_records.semester_id already exists'' AS message' ); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 为新增的 semester_id 添加外键(如不存在) SET @fk_exists = ( SELECT COUNT(*) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = 'classmanagerdb' AND TABLE_NAME = 'conduct_records' AND COLUMN_NAME = 'semester_id' AND REFERENCED_TABLE_NAME IS NOT NULL ); SET @sql = IF(@fk_exists = 0, 'ALTER TABLE `conduct_records` ADD FOREIGN KEY (`semester_id`) REFERENCES `semesters`(`semester_id`) ON DELETE SET NULL', 'SELECT ''conduct_records semester_id FK already exists'' AS message' ); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- attendance_records 表:添加 semester_id 字段(如不存在) SET @column_exists = ( SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'classmanagerdb' AND TABLE_NAME = 'attendance_records' AND COLUMN_NAME = 'semester_id' ); SET @sql = IF(@column_exists = 0, 'ALTER TABLE `attendance_records` ADD COLUMN `semester_id` INT DEFAULT NULL COMMENT ''所属学期ID'' AFTER `deduction_record_id`', 'SELECT ''attendance_records.semester_id already exists'' AS message' ); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 为新增的 semester_id 添加外键(如不存在) SET @fk_exists = ( SELECT COUNT(*) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = 'classmanagerdb' AND TABLE_NAME = 'attendance_records' AND COLUMN_NAME = 'semester_id' AND REFERENCED_TABLE_NAME IS NOT NULL ); SET @sql = IF(@fk_exists = 0, 'ALTER TABLE `attendance_records` ADD FOREIGN KEY (`semester_id`) REFERENCES `semesters`(`semester_id`) ON DELETE SET NULL', 'SELECT ''attendance_records semester_id FK already exists'' AS message' ); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 插入初始科目(仅语数英,如不存在) INSERT IGNORE INTO `subjects` (`subject_name`, `subject_code`, `sort_order`) VALUES ('语文', 'CHI', 1), ('数学', 'MATH', 2), ('英语', 'ENG', 3); SELECT '数据库初始化/迁移完成!' AS message;