-- =========================================== -- 班级操行分管理系统 - 数据库初始化脚本 -- =========================================== -- 开发者: Canglan -- 联系方式: admin@sea-studio.top -- 版权归属: Sea Network Technology Studio -- 许可证: MIT License -- 版权所有: Copyright (c) 2024 Sea Network Technology Studio -- =========================================== -- 数据库: classmanagerdb -- 字符集: utf8mb4 -- =========================================== -- 创建数据库(如果不存在) CREATE DATABASE IF NOT EXISTS `classmanagerdb` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE `classmanagerdb`; -- =========================================== -- 1. 班级表 -- =========================================== DROP TABLE IF EXISTS `classes`; CREATE TABLE `classes` ( `class_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '班级ID', `class_name` VARCHAR(50) NOT NULL COMMENT '班级名称', `grade` VARCHAR(20) DEFAULT NULL COMMENT '年级', `academic_year` VARCHAR(20) DEFAULT NULL COMMENT '学年', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', INDEX `idx_class_name` (`class_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='班级表'; -- =========================================== -- 2. 科目表(支持动态增删) -- =========================================== DROP TABLE IF EXISTS `subjects`; CREATE TABLE `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 '是否启用(0禁用/1启用)', `sort_order` INT DEFAULT 0 COMMENT '排序序号', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', INDEX `idx_active` (`is_active`), UNIQUE KEY `uk_subject_name` (`subject_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='科目表'; -- =========================================== -- 3. 学生表 -- =========================================== DROP TABLE IF EXISTS `students`; CREATE TABLE `students` ( `student_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '学生ID', `student_no` VARCHAR(20) NOT NULL COMMENT '学号', `name` VARCHAR(50) NOT NULL COMMENT '学生姓名', `class_id` INT NOT NULL COMMENT '班级ID', `total_points` INT DEFAULT 100 COMMENT '操行分总分', `parent_phone` VARCHAR(20) DEFAULT NULL COMMENT '家长手机号', `status` TINYINT DEFAULT 1 COMMENT '状态(0离校/1在校)', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE RESTRICT, UNIQUE KEY `uk_student_no` (`student_no`), INDEX `idx_class_id` (`class_id`), INDEX `idx_parent_phone` (`parent_phone`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='学生表'; -- =========================================== -- 4. 用户表(统一账号) -- =========================================== DROP TABLE IF EXISTS `users`; CREATE TABLE `users` ( `user_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID', `username` VARCHAR(50) NOT NULL COMMENT '登录账号', `password_hash` VARCHAR(64) NOT NULL COMMENT '密码哈希(SHA1+MD5)', `real_name` VARCHAR(50) NOT NULL COMMENT '真实姓名', `user_type` ENUM('student', 'parent', 'admin') NOT NULL COMMENT '用户类型', `student_id` INT DEFAULT NULL COMMENT '关联学生ID(学生/家长)', `status` TINYINT DEFAULT 1 COMMENT '状态(0禁用/1启用)', `need_change_password` TINYINT DEFAULT 1 COMMENT '是否需要修改密码(1需要/0不需要)', `last_login_time` DATETIME DEFAULT NULL COMMENT '最后登录时间', `last_login_ip` VARCHAR(45) DEFAULT NULL COMMENT '最后登录IP', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', UNIQUE KEY `uk_username` (`username`), INDEX `idx_user_type` (`user_type`), INDEX `idx_student_id` (`student_id`), FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表'; -- =========================================== -- 5. 管理员角色表 -- =========================================== DROP TABLE IF EXISTS `admin_roles`; CREATE TABLE `admin_roles` ( `admin_role_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '管理员角色ID', `user_id` INT NOT NULL COMMENT '用户ID', `role_type` ENUM('班主任', '班长', '科代表', '考勤委员', '劳动委员') NOT NULL COMMENT '角色类型', `class_id` INT NOT NULL COMMENT '管理的班级ID', `subject_id` INT DEFAULT NULL COMMENT '关联科目ID(科代表专用)', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', FOREIGN KEY (`user_id`) REFERENCES `users`(`user_id`) ON DELETE CASCADE, FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE CASCADE, FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`subject_id`) ON DELETE CASCADE, INDEX `idx_user_id` (`user_id`), INDEX `idx_role_type` (`role_type`), UNIQUE KEY `uk_user_class_subject` (`user_id`, `class_id`, `subject_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='管理员角色表'; -- =========================================== -- 6. 操行分记录表 -- =========================================== DROP TABLE IF EXISTS `conduct_records`; CREATE TABLE `conduct_records` ( `record_id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '记录ID', `student_id` INT NOT NULL COMMENT '学生ID', `points_change` INT NOT NULL COMMENT '分数变动(正数加分,负数扣分)', `reason` VARCHAR(255) NOT NULL COMMENT '变动原因', `recorder_id` INT NOT NULL COMMENT '操作人ID', `recorder_name` VARCHAR(50) DEFAULT NULL COMMENT '操作人姓名(冗余字段)', `related_type` ENUM('manual', 'homework', 'attendance') DEFAULT 'manual' COMMENT '关联类型', `related_id` INT DEFAULT NULL COMMENT '关联ID(作业ID/考勤ID)', `is_revoked` TINYINT DEFAULT 0 COMMENT '是否已撤销(0未撤销/1已撤销)', `revoked_by` INT DEFAULT NULL COMMENT '撤销人ID', `revoked_at` DATETIME DEFAULT NULL COMMENT '撤销时间', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE, FOREIGN KEY (`recorder_id`) REFERENCES `users`(`user_id`) ON DELETE RESTRICT, FOREIGN KEY (`revoked_by`) REFERENCES `users`(`user_id`) ON DELETE RESTRICT, INDEX `idx_student_id` (`student_id`), INDEX `idx_recorder_id` (`recorder_id`), INDEX `idx_created_at` (`created_at`), INDEX `idx_related` (`related_type`, `related_id`), INDEX `idx_is_revoked` (`is_revoked`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='操行分记录表'; -- =========================================== -- 7. 作业表 -- =========================================== DROP TABLE IF EXISTS `assignments`; CREATE TABLE `assignments` ( `assignment_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '作业ID', `class_id` INT NOT NULL COMMENT '班级ID', `subject_id` INT NOT NULL COMMENT '科目ID', `title` VARCHAR(100) NOT NULL COMMENT '作业标题', `description` TEXT COMMENT '作业描述', `deadline` DATE NOT NULL COMMENT '截止日期', `created_by` INT NOT NULL COMMENT '发布人ID', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE CASCADE, FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`subject_id`) ON DELETE RESTRICT, FOREIGN KEY (`created_by`) REFERENCES `users`(`user_id`) ON DELETE RESTRICT, INDEX `idx_class_id` (`class_id`), INDEX `idx_deadline` (`deadline`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='作业表'; -- =========================================== -- 8. 作业提交记录表 -- =========================================== DROP TABLE IF EXISTS `homework_submissions`; CREATE TABLE `homework_submissions` ( `submission_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '提交记录ID', `assignment_id` INT NOT NULL COMMENT '作业ID', `student_id` INT NOT NULL COMMENT '学生ID', `status` ENUM('submitted', 'not_submitted', 'late') DEFAULT 'not_submitted' COMMENT '提交状态', `submit_time` DATETIME DEFAULT NULL COMMENT '提交时间', `comments` TEXT COMMENT '备注', `deduction_applied` TINYINT DEFAULT 0 COMMENT '是否已应用扣分', `deduction_record_id` BIGINT DEFAULT NULL COMMENT '关联的扣分记录ID', `updated_by` INT DEFAULT NULL COMMENT '最后更新人ID', `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', FOREIGN KEY (`assignment_id`) REFERENCES `assignments`(`assignment_id`) ON DELETE CASCADE, FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE, FOREIGN KEY (`updated_by`) REFERENCES `users`(`user_id`) ON DELETE RESTRICT, FOREIGN KEY (`deduction_record_id`) REFERENCES `conduct_records`(`record_id`) ON DELETE SET NULL, INDEX `idx_assignment_id` (`assignment_id`), INDEX `idx_student_id` (`student_id`), INDEX `idx_status` (`status`), UNIQUE KEY `uk_assignment_student` (`assignment_id`, `student_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='作业提交记录表'; -- =========================================== -- 9. 考勤记录表 -- =========================================== DROP TABLE IF EXISTS `attendance_records`; CREATE TABLE `attendance_records` ( `attendance_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '考勤记录ID', `student_id` INT NOT NULL COMMENT '学生ID', `date` DATE NOT NULL COMMENT '考勤日期', `status` ENUM('present', 'absent', 'late', 'leave') DEFAULT 'present' COMMENT '考勤状态', `reason` VARCHAR(255) DEFAULT NULL COMMENT '原因', `recorder_id` INT NOT NULL COMMENT '记录人ID', `deduction_applied` TINYINT DEFAULT 0 COMMENT '是否已应用扣分', `deduction_record_id` BIGINT DEFAULT NULL COMMENT '关联的扣分记录ID', `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`) ON DELETE CASCADE, FOREIGN KEY (`recorder_id`) REFERENCES `users`(`user_id`) ON DELETE RESTRICT, FOREIGN KEY (`deduction_record_id`) REFERENCES `conduct_records`(`record_id`) ON DELETE SET NULL, INDEX `idx_student_id` (`student_id`), INDEX `idx_date` (`date`), INDEX `idx_status` (`status`), UNIQUE KEY `uk_student_date` (`student_id`, `date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='考勤记录表'; -- =========================================== -- 10. 操作日志表 -- =========================================== DROP TABLE IF EXISTS `operation_logs`; CREATE TABLE `operation_logs` ( `log_id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '日志ID', `operator_id` INT NOT NULL COMMENT '操作人ID', `operator_name` VARCHAR(50) DEFAULT NULL COMMENT '操作人姓名', `operator_role` VARCHAR(50) DEFAULT NULL COMMENT '操作人角色', `operation_type` VARCHAR(50) NOT NULL COMMENT '操作类型', `target_type` VARCHAR(50) DEFAULT NULL COMMENT '目标类型', `target_id` INT DEFAULT NULL COMMENT '目标ID', `details` TEXT COMMENT '详细信息', `ip_address` VARCHAR(45) DEFAULT NULL COMMENT 'IP地址', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', INDEX `idx_operator_id` (`operator_id`), INDEX `idx_operation_type` (`operation_type`), INDEX `idx_created_at` (`created_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='操作日志表'; -- =========================================== -- 11. 登录日志表 -- =========================================== DROP TABLE IF EXISTS `login_logs`; CREATE TABLE `login_logs` ( `log_id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '日志ID', `username` VARCHAR(50) NOT NULL COMMENT '登录账号', `login_result` TINYINT NOT NULL COMMENT '登录结果(0失败/1成功)', `fail_reason` VARCHAR(100) DEFAULT NULL COMMENT '失败原因', `ip_address` VARCHAR(45) DEFAULT NULL COMMENT 'IP地址', `user_agent` VARCHAR(255) DEFAULT NULL COMMENT '用户代理', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', INDEX `idx_username` (`username`), INDEX `idx_created_at` (`created_at`), INDEX `idx_login_result` (`login_result`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='登录日志表'; -- =========================================== -- 创建存储过程:撤销扣分记录 -- =========================================== DROP PROCEDURE IF EXISTS `revoke_conduct_record`; DELIMITER // CREATE PROCEDURE `revoke_conduct_record`( IN p_record_id BIGINT, IN p_revoker_id INT ) BEGIN DECLARE v_student_id INT; DECLARE v_points_change INT; DECLARE v_is_revoked TINYINT; SELECT `student_id`, `points_change`, `is_revoked` INTO v_student_id, v_points_change, v_is_revoked FROM `conduct_records` WHERE `record_id` = p_record_id; IF v_is_revoked = 1 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '该记录已被撤销'; END IF; UPDATE `conduct_records` SET `is_revoked` = 1, `revoked_by` = p_revoker_id, `revoked_at` = NOW() WHERE `record_id` = p_record_id; UPDATE `students` SET `total_points` = `total_points` - v_points_change WHERE `student_id` = v_student_id; END // DELIMITER ; -- =========================================== -- 创建触发器:更新学生总分 -- =========================================== DROP TRIGGER IF EXISTS `update_student_points_on_insert`; DELIMITER // CREATE TRIGGER `update_student_points_on_insert` AFTER INSERT ON `conduct_records` FOR EACH ROW BEGIN IF NEW.is_revoked = 0 THEN UPDATE `students` SET `total_points` = `total_points` + NEW.points_change WHERE `student_id` = NEW.student_id; END IF; END // DELIMITER ; -- =========================================== -- 创建视图:学生操行分排行榜 -- =========================================== DROP VIEW IF EXISTS `v_student_ranking`; CREATE VIEW `v_student_ranking` AS SELECT s.student_id, s.student_no, s.name, c.class_name, s.total_points, RANK() OVER (PARTITION BY s.class_id ORDER BY s.total_points DESC) as rank_in_class FROM `students` s JOIN `classes` c ON s.class_id = c.class_id WHERE s.status = 1; -- =========================================== -- 创建视图:今日考勤汇总 -- =========================================== DROP VIEW IF EXISTS `v_today_attendance`; CREATE VIEW `v_today_attendance` AS SELECT c.class_name, COUNT(CASE WHEN a.status = 'present' THEN 1 END) as present_count, COUNT(CASE WHEN a.status = 'absent' THEN 1 END) as absent_count, COUNT(CASE WHEN a.status = 'late' THEN 1 END) as late_count, COUNT(CASE WHEN a.status = 'leave' THEN 1 END) as leave_count, COUNT(*) as total_count FROM `attendance_records` a JOIN `students` s ON a.student_id = s.student_id JOIN `classes` c ON s.class_id = c.class_id WHERE a.date = CURDATE() GROUP BY c.class_id;