feat: 多班级版班级管理系统 v2.0

技术栈:Go (Gin + GORM) + PHP + MySQL 5.7 + Redis

主要功能:
- 多班级完全隔离(class_id 贯穿全系统)
- 后端从 Python FastAPI 重写为 Go Gin(端口 56789)
- 超级管理员独立登录(env 配置路径,默认账密 admin/Admin123)
- 科任老师/课代表新角色
- 课代表作业管理页面
- 排行榜分项排行(操行分/考勤/作业)
- 角色加减分上下限由班主任配置
- 家长改密功能(可开关)
- 班级角色按需开关
- 宿舍号格式:南0-000
- 周度/月度重置功能
- MySQL 5.7 兼容
- Nginx 反向代理部署

开发者: Canglan
版权归属: Sea Network Technology Studio
许可证: Apache License 2.0
This commit is contained in:
2026-06-22 10:21:52 +08:00
commit 124d7f645e
140 changed files with 21103 additions and 0 deletions

423
sql/init.sql Normal file
View File

@@ -0,0 +1,423 @@
-- ===========================================
-- 多班级版班级管理系统 - 数据库初始化脚本 (v2.0 Go重写版)
-- 数据库: classmanagerdb
-- 字符集: utf8mb4
-- MySQL 兼容: 5.7+(不使用 CHECK 约束、窗口函数等 8.0+ 特性)
--
-- 开发者: Canglan
-- 联系方式: admin@sea-studio.top
-- 版权归属: Sea Network Technology Studio
-- 许可证: Apache License 2.0
--
-- 版权所有 © Sea Network Technology Studio
-- ===========================================
CREATE DATABASE IF NOT EXISTS `classmanagerdb`
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE `classmanagerdb`;
SET FOREIGN_KEY_CHECKS = 0;
-- ===========================================
-- 1. 班级表(多班级核心)
-- ===========================================
CREATE TABLE IF NOT EXISTS `classes` (
`class_id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '班级ID',
`class_name` VARCHAR(100) NOT NULL COMMENT '班级名称,如 高一(1)班',
`grade` VARCHAR(50) DEFAULT NULL COMMENT '年级',
`description` VARCHAR(255) DEFAULT NULL COMMENT '班级描述',
`status` TINYINT DEFAULT 1 COMMENT '状态1=启用0=禁用',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY `uk_class_name` (`class_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ===========================================
-- 2. 学期表(系统级共享)
-- ===========================================
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;
-- ===========================================
-- 3. 科目表(系统级共享)
-- ===========================================
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;
-- ===========================================
-- 4. 学生表(归属班级)
-- 宿舍号格式: 南0-000, 东12-345, 北1-001, 西5-222
-- 正则校验: ^[东南北西]\d{1,2}-\d{3}$应用层校验MySQL 5.7 不执行 CHECK 约束)
-- ===========================================
CREATE TABLE IF NOT EXISTS `students` (
`student_id` INT PRIMARY KEY AUTO_INCREMENT,
`student_no` VARCHAR(20) NOT NULL,
`class_id` INT NOT NULL COMMENT '所属班级ID',
`name` VARCHAR(50) NOT NULL,
`total_points` INT DEFAULT 60,
`parent_account` VARCHAR(50) DEFAULT NULL COMMENT '家长登录账号(推荐手机号)',
`dormitory_number` VARCHAR(20) DEFAULT NULL COMMENT '宿舍号格式南0-000',
`status` TINYINT DEFAULT 1,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`points_updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '分数最后更新时间',
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY `uk_student_no_class` (`student_no`, `class_id`),
FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ===========================================
-- 5. 用户表
-- ===========================================
CREATE TABLE IF NOT EXISTS `users` (
`user_id` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL UNIQUE,
`password_hash` VARCHAR(255) NOT NULL,
`real_name` VARCHAR(50) NOT NULL,
`user_type` ENUM('student', 'parent', 'admin', 'super_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;
-- ===========================================
-- 6. 系统管理员表(独立于班级的超级管理员)
-- ===========================================
CREATE TABLE IF NOT EXISTS `super_admins` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL UNIQUE COMMENT '登录用户名',
`password_hash` VARCHAR(255) NOT NULL COMMENT '密码哈希MD5(SHA1(password)+salt)',
`salt` VARCHAR(64) NOT NULL COMMENT '密码盐值',
`real_name` VARCHAR(50) NOT NULL COMMENT '真实姓名',
`status` TINYINT DEFAULT 1 COMMENT '状态1=启用0=禁用',
`need_change_password` TINYINT DEFAULT 1 COMMENT '是否需要修改密码1=需要0=不需要',
`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;
-- ===========================================
-- 7. 管理员角色表(归属班级)
-- ===========================================
CREATE TABLE IF NOT EXISTS `admin_roles` (
`admin_role_id` INT PRIMARY KEY AUTO_INCREMENT,
`user_id` INT NOT NULL,
`class_id` INT NOT NULL COMMENT '所属班级ID',
`role_type` ENUM('班主任', '班长', '学习委员', '考勤委员', '劳动委员', '志愿委员', '科任老师', '课代表') NOT NULL,
`subject_id` INT DEFAULT NULL COMMENT '关联科目ID科任老师/课代表必填)',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (`user_id`) REFERENCES `users`(`user_id`) ON DELETE CASCADE,
FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE RESTRICT,
FOREIGN KEY (`subject_id`) REFERENCES `subjects`(`subject_id`) ON DELETE CASCADE,
UNIQUE KEY `uk_user_class` (`user_id`, `class_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ===========================================
-- 8. 操行分记录表
-- ===========================================
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;
-- ===========================================
-- 9. 作业表(归属班级)
-- ===========================================
CREATE TABLE IF NOT EXISTS `assignments` (
`assignment_id` INT PRIMARY KEY AUTO_INCREMENT,
`class_id` INT NOT NULL COMMENT '所属班级ID',
`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 (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE RESTRICT,
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;
-- ===========================================
-- 10. 作业提交记录表
-- ===========================================
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;
-- ===========================================
-- 11. 考勤记录表
-- ===========================================
CREATE TABLE IF NOT EXISTS `attendance_records` (
`attendance_id` INT PRIMARY KEY AUTO_INCREMENT,
`student_id` INT NOT NULL,
`date` DATE NOT NULL,
`slot` ENUM('morning', 'afternoon', 'evening') DEFAULT 'morning' COMMENT '考勤时段:早上/下午/晚修',
`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_slot` (`student_id`, `date`, `slot`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ===========================================
-- 12. 操作日志表
-- ===========================================
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,
`class_id` INT DEFAULT NULL COMMENT '操作所属班级ID',
`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;
-- ===========================================
-- 13. 登录日志表
-- ===========================================
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;
-- ===========================================
-- 14. 学期归档快照表
-- ===========================================
CREATE TABLE IF NOT EXISTS `semester_archives` (
`archive_id` INT PRIMARY KEY AUTO_INCREMENT,
`semester_id` INT NOT NULL,
`class_id` INT NOT NULL COMMENT '所属班级ID',
`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 '班级总人数',
`attendance_present` INT DEFAULT 0 COMMENT '出勤次数',
`attendance_absent` INT DEFAULT 0 COMMENT '缺勤次数',
`attendance_late` INT DEFAULT 0 COMMENT '迟到次数',
`attendance_leave` INT DEFAULT 0 COMMENT '请假次数',
`homework_submitted` INT DEFAULT 0 COMMENT '已交作业数',
`homework_not_submitted` INT DEFAULT 0 COMMENT '未交作业数',
`homework_late` INT DEFAULT 0 COMMENT '迟交作业数',
`archived_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (`semester_id`) REFERENCES `semesters`(`semester_id`),
FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE RESTRICT,
FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ===========================================
-- 15. 系统设置表(全局)
-- ===========================================
CREATE TABLE IF NOT EXISTS `system_settings` (
`setting_key` VARCHAR(50) PRIMARY KEY,
`setting_value` VARCHAR(255) NOT NULL,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ===========================================
-- 16. 班级设置表(每班级独立配置,班主任可修改)
-- setting_key 约定:
-- 角色加减分上下限:
-- point_limit_班主任_max / point_limit_班主任_min
-- point_limit_班长_max / point_limit_班长_min (默认 ±5
-- point_limit_学习委员_max / point_limit_学习委员_min (默认 ±5
-- point_limit_考勤委员_max / point_limit_考勤委员_min
-- point_limit_劳动委员_max / point_limit_劳动委员_min (默认 ±1
-- point_limit_志愿委员_max / point_limit_志愿委员_min (默认 0~5
-- point_limit_科任老师_max / point_limit_科任老师_min (默认 ±5
-- 操行分初始值:
-- initial_points (默认 60
-- 扣分规则:
-- deduction_homework_not_submit (默认 2
-- deduction_homework_late (默认 1
-- deduction_attendance_absent (默认 3
-- deduction_attendance_late (默认 1
-- deduction_attendance_leave (默认 0
-- 家长相关:
-- parent_password_change_enabled (默认 true
-- parent_account_enabled (默认 true
-- 周期重置:
-- reset_frequency (默认 none: 仅学期结算; weekly: 每周; monthly: 每月)
-- reset_day_of_week (默认 1: 周重置日 1=周一 ~ 7=周日,仅 weekly 时生效)
-- reset_day_of_month (默认 1: 月重置日 1~28仅 monthly 时生效)
-- ===========================================
CREATE TABLE IF NOT EXISTS `class_settings` (
`setting_id` INT PRIMARY KEY AUTO_INCREMENT,
`class_id` INT NOT NULL COMMENT '所属班级ID',
`setting_key` VARCHAR(50) NOT NULL COMMENT '设置项键名',
`setting_value` VARCHAR(255) NOT NULL COMMENT '设置项值',
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE CASCADE,
UNIQUE KEY `uk_class_setting` (`class_id`, `setting_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ===========================================
-- 17. 周期归档快照表(周/月重置时创建)
-- ===========================================
CREATE TABLE IF NOT EXISTS `period_archives` (
`archive_id` INT PRIMARY KEY AUTO_INCREMENT,
`class_id` INT NOT NULL COMMENT '所属班级ID',
`period_type` ENUM('weekly', 'monthly') NOT NULL COMMENT '周期类型weekly=周monthly=月',
`period_label` VARCHAR(50) NOT NULL COMMENT '周期标签,如 2025-W03、2025-01',
`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,
`reset_by` VARCHAR(20) DEFAULT 'auto' COMMENT '重置触发方式auto=自动定时manual=手动触发',
`operator_id` INT DEFAULT NULL COMMENT '手动触发的操作者ID',
FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE RESTRICT,
FOREIGN KEY (`student_id`) REFERENCES `students`(`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ===========================================
-- 18. 班级功能开关表(控制班级内各功能模块的启用/禁用)
-- feature_key 约定:
-- role_班长_enabled / role_学习委员_enabled / role_考勤委员_enabled
-- role_劳动委员_enabled / role_志愿委员_enabled
-- role_科任老师_enabled / role_课代表_enabled
-- ===========================================
CREATE TABLE IF NOT EXISTS `class_features` (
`feature_id` INT PRIMARY KEY AUTO_INCREMENT,
`class_id` INT NOT NULL COMMENT '所属班级ID',
`feature_key` VARCHAR(50) NOT NULL COMMENT '功能标识',
`enabled` TINYINT DEFAULT 1 COMMENT '是否启用1=启用0=禁用',
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE CASCADE,
UNIQUE KEY `uk_class_feature` (`class_id`, `feature_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ===========================================
-- 性能索引(使用存储过程实现 MySQL 5.7 兼容的条件索引创建)
-- ===========================================
DROP PROCEDURE IF EXISTS `create_index_if_not_exists`;
DELIMITER //
CREATE PROCEDURE `create_index_if_not_exists`(
IN `p_table` VARCHAR(64),
IN `p_index` VARCHAR(64),
IN `p_columns` VARCHAR(255)
)
BEGIN
IF NOT EXISTS (
SELECT 1 FROM `information_schema`.`statistics`
WHERE `table_schema` = DATABASE()
AND `table_name` = p_table
AND `index_name` = p_index
LIMIT 1
) THEN
SET @sql = CONCAT('CREATE INDEX `', p_index, '` ON `', p_table, '`(', p_columns, ')');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END //
DELIMITER ;
CALL `create_index_if_not_exists`('conduct_records', 'idx_conduct_semester', '`semester_id`');
CALL `create_index_if_not_exists`('attendance_records', 'idx_attendance_semester', '`semester_id`');
CALL `create_index_if_not_exists`('conduct_records', 'idx_conduct_student', '`student_id`');
CALL `create_index_if_not_exists`('conduct_records', 'idx_student_created', '`student_id`, `created_at`');
CALL `create_index_if_not_exists`('conduct_records', 'idx_recorder_id', '`recorder_id`');
CALL `create_index_if_not_exists`('conduct_records', 'idx_conduct_type_semester', '`semester_id`, `related_type`, `student_id`');
CALL `create_index_if_not_exists`('attendance_records', 'idx_attendance_date', '`date`');
CALL `create_index_if_not_exists`('login_logs', 'idx_username_created', '`username`, `created_at`');
CALL `create_index_if_not_exists`('operation_logs', 'idx_operator_created', '`operator_id`, `created_at`');
CALL `create_index_if_not_exists`('semester_archives', 'idx_semester_id', '`semester_id`');
CALL `create_index_if_not_exists`('students', 'idx_student_class', '`class_id`');
CALL `create_index_if_not_exists`('admin_roles', 'idx_admin_role_class', '`class_id`');
CALL `create_index_if_not_exists`('assignments', 'idx_assignment_class', '`class_id`');
CALL `create_index_if_not_exists`('assignments', 'idx_assignment_subject', '`subject_id`');
CALL `create_index_if_not_exists`('semester_archives', 'idx_archive_class', '`class_id`');
CALL `create_index_if_not_exists`('operation_logs', 'idx_operation_class', '`class_id`');
CALL `create_index_if_not_exists`('period_archives', 'idx_period_archive_type', '`class_id`, `period_type`, `period_label`');
DROP PROCEDURE IF EXISTS `create_index_if_not_exists`;
SET FOREIGN_KEY_CHECKS = 1;
-- ===========================================
-- 初始数据
-- ===========================================
-- 插入初始科目(仅语数英,如不存在)
INSERT IGNORE INTO `subjects` (`subject_name`, `subject_code`, `sort_order`) VALUES
('语文', 'CHI', 1),
('数学', 'MATH', 2),
('英语', 'ENG', 3);
-- 初始化系统版本号
INSERT INTO `system_settings` (`setting_key`, `setting_value`)
VALUES ('db_version', '2.0')
ON DUPLICATE KEY UPDATE `setting_value` = '2.0';
-- 系统管理员独立登录路径
INSERT INTO `system_settings` (`setting_key`, `setting_value`)
VALUES ('super_admin_login_path', '/super-admin/login')
ON DUPLICATE KEY UPDATE `setting_value` = '/super-admin/login';
-- 控制台输出初始化结果(含版本号)
SELECT CONCAT('数据库初始化完成!版本: v', (SELECT setting_value FROM system_settings WHERE setting_key = 'db_version')) AS message;