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:
264
sql/upgrades/v1.0.sql
Normal file
264
sql/upgrades/v1.0.sql
Normal file
@@ -0,0 +1,264 @@
|
||||
-- ===========================================
|
||||
-- 多班级版班级管理系统 - v1.0 升级脚本
|
||||
-- 从旧版单班级系统升级到多班级版
|
||||
--
|
||||
-- 开发者: Canglan
|
||||
-- 联系方式: admin@sea-studio.top
|
||||
-- 版权归属: Sea Network Technology Studio
|
||||
-- 许可证: Apache License 2.0
|
||||
--
|
||||
-- 版权所有 © Sea Network Technology Studio
|
||||
--
|
||||
-- 升级说明:
|
||||
-- 1. 创建班级表、班级设置表、班级功能开关表
|
||||
-- 2. 将现有学生迁移到默认班级
|
||||
-- 3. 扩展管理员角色枚举(科任老师、课代表)
|
||||
-- 4. 修改学生表字段(parent_phone → parent_account)
|
||||
-- 5. 为所有现有表添加 class_id 字段
|
||||
-- 6. 创建系统管理员表(super_admins)
|
||||
-- 7. 添加班级设置预置项和功能开关预置项
|
||||
-- 8. 添加系统管理员登录路径配置
|
||||
-- ===========================================
|
||||
|
||||
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 `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;
|
||||
|
||||
-- ===========================================
|
||||
-- 3. 创建班级功能开关表
|
||||
-- ===========================================
|
||||
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;
|
||||
|
||||
-- ===========================================
|
||||
-- 4. 创建系统管理员表(super_admins)
|
||||
-- ===========================================
|
||||
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=禁用',
|
||||
`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;
|
||||
|
||||
-- ===========================================
|
||||
-- 5. 插入默认班级(现有数据迁移)
|
||||
-- ===========================================
|
||||
INSERT INTO `classes` (`class_name`, `grade`, `description`)
|
||||
VALUES ('默认班级', NULL, '系统升级时自动创建的默认班级')
|
||||
ON DUPLICATE KEY UPDATE `class_id` = `class_id`;
|
||||
|
||||
-- 获取默认班级ID
|
||||
SET @default_class_id = (SELECT `class_id` FROM `classes` WHERE `class_name` = '默认班级' LIMIT 1);
|
||||
|
||||
-- ===========================================
|
||||
-- 6. 学生表:添加 class_id 字段
|
||||
-- ===========================================
|
||||
ALTER TABLE `students`
|
||||
ADD COLUMN `class_id` INT NOT NULL DEFAULT 1 COMMENT '所属班级ID' AFTER `student_no`,
|
||||
ADD FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE RESTRICT;
|
||||
|
||||
-- 将现有学生关联到默认班级
|
||||
UPDATE `students` SET `class_id` = @default_class_id WHERE `class_id` = 1;
|
||||
|
||||
-- 修改唯一约束(学号+班级联合唯一)
|
||||
ALTER TABLE `students` DROP INDEX `student_no`;
|
||||
ALTER TABLE `students` ADD UNIQUE KEY `uk_student_no_class` (`student_no`, `class_id`);
|
||||
|
||||
-- ===========================================
|
||||
-- 7. 学生表:parent_phone → parent_account
|
||||
-- ===========================================
|
||||
ALTER TABLE `students` CHANGE COLUMN `parent_phone` `parent_account` VARCHAR(50) DEFAULT NULL COMMENT '家长登录账号(推荐手机号)';
|
||||
|
||||
-- 更新宿舍号字段注释(格式:南0-000)
|
||||
ALTER TABLE `students` MODIFY COLUMN `dormitory_number` VARCHAR(20) DEFAULT NULL COMMENT '宿舍号,格式:南0-000';
|
||||
|
||||
-- ===========================================
|
||||
-- 8. 用户表:扩展 user_type 枚举
|
||||
-- ===========================================
|
||||
ALTER TABLE `users` MODIFY COLUMN `user_type` ENUM('student', 'parent', 'admin', 'super_admin') NOT NULL;
|
||||
|
||||
-- ===========================================
|
||||
-- 9. 管理员角色表:添加 class_id 和扩展枚举
|
||||
-- ===========================================
|
||||
ALTER TABLE `admin_roles`
|
||||
ADD COLUMN `class_id` INT NOT NULL DEFAULT 1 COMMENT '所属班级ID' AFTER `user_id`,
|
||||
ADD FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE RESTRICT;
|
||||
|
||||
-- 将现有管理员关联到默认班级
|
||||
UPDATE `admin_roles` SET `class_id` = @default_class_id WHERE `class_id` = 1;
|
||||
|
||||
-- 扩展角色枚举
|
||||
ALTER TABLE `admin_roles` MODIFY COLUMN `role_type` ENUM('班主任', '班长', '学习委员', '考勤委员', '劳动委员', '志愿委员', '科任老师', '课代表') NOT NULL;
|
||||
|
||||
-- 添加班级级唯一约束
|
||||
ALTER TABLE `admin_roles` ADD UNIQUE KEY `uk_user_class` (`user_id`, `class_id`);
|
||||
|
||||
-- ===========================================
|
||||
-- 10. 作业表:添加 class_id
|
||||
-- ===========================================
|
||||
ALTER TABLE `assignments`
|
||||
ADD COLUMN `class_id` INT NOT NULL DEFAULT 1 COMMENT '所属班级ID' AFTER `assignment_id`,
|
||||
ADD FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE RESTRICT;
|
||||
|
||||
UPDATE `assignments` SET `class_id` = @default_class_id WHERE `class_id` = 1;
|
||||
|
||||
-- ===========================================
|
||||
-- 11. 学期归档表:添加 class_id
|
||||
-- ===========================================
|
||||
ALTER TABLE `semester_archives`
|
||||
ADD COLUMN `class_id` INT NOT NULL DEFAULT 1 COMMENT '所属班级ID' AFTER `semester_id`,
|
||||
ADD FOREIGN KEY (`class_id`) REFERENCES `classes`(`class_id`) ON DELETE RESTRICT;
|
||||
|
||||
UPDATE `semester_archives` SET `class_id` = @default_class_id WHERE `class_id` = 1;
|
||||
|
||||
-- ===========================================
|
||||
-- 12. 操作日志表:添加 class_id
|
||||
-- ===========================================
|
||||
ALTER TABLE `operation_logs`
|
||||
ADD COLUMN `class_id` INT DEFAULT NULL COMMENT '操作所属班级ID' AFTER `operator_role`;
|
||||
|
||||
-- ===========================================
|
||||
-- 13. 添加新索引(MySQL 5.7 兼容:使用存储过程检查索引是否存在)
|
||||
-- ===========================================
|
||||
DROP PROCEDURE IF EXISTS `add_index_if_not_exists`;
|
||||
DELIMITER //
|
||||
CREATE PROCEDURE `add_index_if_not_exists`(
|
||||
IN p_table VARCHAR(64),
|
||||
IN p_index VARCHAR(64),
|
||||
IN p_columns VARCHAR(512)
|
||||
)
|
||||
BEGIN
|
||||
DECLARE index_count INT DEFAULT 0;
|
||||
SELECT COUNT(*) INTO index_count
|
||||
FROM information_schema.statistics
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = p_table
|
||||
AND index_name = p_index;
|
||||
IF index_count = 0 THEN
|
||||
SET @sql = CONCAT('ALTER TABLE `', p_table, '` ADD INDEX `', p_index, '` (', p_columns, ')');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
END IF;
|
||||
END //
|
||||
DELIMITER ;
|
||||
|
||||
CALL `add_index_if_not_exists`('students', 'idx_student_class', '`class_id`');
|
||||
CALL `add_index_if_not_exists`('admin_roles', 'idx_admin_role_class', '`class_id`');
|
||||
CALL `add_index_if_not_exists`('assignments', 'idx_assignment_class', '`class_id`');
|
||||
CALL `add_index_if_not_exists`('assignments', 'idx_assignment_subject', '`subject_id`');
|
||||
CALL `add_index_if_not_exists`('semester_archives', 'idx_archive_class', '`class_id`');
|
||||
CALL `add_index_if_not_exists`('operation_logs', 'idx_operation_class', '`class_id`');
|
||||
CALL `add_index_if_not_exists`('conduct_records', 'idx_conduct_type_semester', '`semester_id`, `related_type`, `student_id`');
|
||||
CALL `add_index_if_not_exists`('conduct_records', 'idx_conduct_semester', '`semester_id`');
|
||||
CALL `add_index_if_not_exists`('conduct_records', 'idx_conduct_student', '`student_id`');
|
||||
CALL `add_index_if_not_exists`('conduct_records', 'idx_student_created', '`student_id`, `created_at`');
|
||||
CALL `add_index_if_not_exists`('conduct_records', 'idx_recorder_id', '`recorder_id`');
|
||||
CALL `add_index_if_not_exists`('attendance_records', 'idx_attendance_semester', '`semester_id`');
|
||||
CALL `add_index_if_not_exists`('attendance_records', 'idx_date', '`date`');
|
||||
CALL `add_index_if_not_exists`('login_logs', 'idx_username_created', '`username`, `created_at`');
|
||||
CALL `add_index_if_not_exists`('operation_logs', 'idx_operator_created', '`operator_id`, `created_at`');
|
||||
CALL `add_index_if_not_exists`('semester_archives', 'idx_semester_id', '`semester_id`');
|
||||
|
||||
DROP PROCEDURE IF EXISTS `add_index_if_not_exists`;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
-- ===========================================
|
||||
-- 14. 为默认班级插入预置班级设置
|
||||
-- ===========================================
|
||||
INSERT INTO `class_settings` (`class_id`, `setting_key`, `setting_value`) VALUES
|
||||
-- 角色加减分上下限
|
||||
(@default_class_id, 'point_limit_班主任_max', '10'),
|
||||
(@default_class_id, 'point_limit_班主任_min', '-10'),
|
||||
(@default_class_id, 'point_limit_班长_max', '5'),
|
||||
(@default_class_id, 'point_limit_班长_min', '-5'),
|
||||
(@default_class_id, 'point_limit_学习委员_max', '5'),
|
||||
(@default_class_id, 'point_limit_学习委员_min', '-5'),
|
||||
(@default_class_id, 'point_limit_考勤委员_max', '8'),
|
||||
(@default_class_id, 'point_limit_考勤委员_min', '-8'),
|
||||
(@default_class_id, 'point_limit_劳动委员_max', '1'),
|
||||
(@default_class_id, 'point_limit_劳动委员_min', '-1'),
|
||||
(@default_class_id, 'point_limit_志愿委员_max', '5'),
|
||||
(@default_class_id, 'point_limit_志愿委员_min', '0'),
|
||||
(@default_class_id, 'point_limit_科任老师_max', '5'),
|
||||
(@default_class_id, 'point_limit_科任老师_min', '-5'),
|
||||
-- 操行分初始值
|
||||
(@default_class_id, 'initial_points', '60'),
|
||||
-- 扣分规则
|
||||
(@default_class_id, 'deduction_homework_not_submit', '2'),
|
||||
(@default_class_id, 'deduction_homework_late', '1'),
|
||||
(@default_class_id, 'deduction_attendance_absent', '3'),
|
||||
(@default_class_id, 'deduction_attendance_late', '1'),
|
||||
(@default_class_id, 'deduction_attendance_leave', '0'),
|
||||
-- 家长相关
|
||||
(@default_class_id, 'parent_password_change_enabled', 'true'),
|
||||
(@default_class_id, 'parent_account_enabled', 'true')
|
||||
ON DUPLICATE KEY UPDATE `setting_value` = VALUES(`setting_value`);
|
||||
|
||||
-- ===========================================
|
||||
-- 15. 为默认班级插入预置功能开关
|
||||
-- ===========================================
|
||||
INSERT INTO `class_features` (`class_id`, `feature_key`, `enabled`) VALUES
|
||||
(@default_class_id, 'role_班长_enabled', 1),
|
||||
(@default_class_id, 'role_学习委员_enabled', 1),
|
||||
(@default_class_id, 'role_考勤委员_enabled', 1),
|
||||
(@default_class_id, 'role_劳动委员_enabled', 1),
|
||||
(@default_class_id, 'role_志愿委员_enabled', 1),
|
||||
(@default_class_id, 'role_科任老师_enabled', 1),
|
||||
(@default_class_id, 'role_课代表_enabled', 1)
|
||||
ON DUPLICATE KEY UPDATE `enabled` = VALUES(`enabled`);
|
||||
|
||||
-- ===========================================
|
||||
-- 16. 添加系统管理员登录路径配置
|
||||
-- ===========================================
|
||||
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';
|
||||
|
||||
-- ===========================================
|
||||
-- 17. 更新系统版本号
|
||||
-- ===========================================
|
||||
INSERT INTO `system_settings` (`setting_key`, `setting_value`)
|
||||
VALUES ('db_version', '1.0')
|
||||
ON DUPLICATE KEY UPDATE `setting_value` = '1.0';
|
||||
|
||||
-- 升级完成
|
||||
SELECT CONCAT('升级完成!版本: v1.0,默认班级ID: ', @default_class_id) AS message;
|
||||
53
sql/upgrades/v2.1.sql
Normal file
53
sql/upgrades/v2.1.sql
Normal file
@@ -0,0 +1,53 @@
|
||||
-- ===========================================
|
||||
-- 多班级版班级管理系统 - v2.1 升级脚本
|
||||
-- 修复 review-report-v14 中发现的安全和逻辑问题
|
||||
--
|
||||
-- 开发者: Canglan
|
||||
-- 联系方式: admin@sea-studio.top
|
||||
-- 版权归属: Sea Network Technology Studio
|
||||
-- 许可证: Apache License 2.0
|
||||
--
|
||||
-- 版权所有 © Sea Network Technology Studio
|
||||
--
|
||||
-- 升级说明:
|
||||
-- 1. 为 super_admins 表添加 need_change_password 字段
|
||||
-- 2. 为 existing 超级管理员设置默认值(首次登录强制改密)
|
||||
-- ===========================================
|
||||
|
||||
USE `classmanagerdb`;
|
||||
|
||||
-- 为 super_admins 表添加 need_change_password 字段
|
||||
-- 已存在则跳过(使用存储过程检测)
|
||||
DROP PROCEDURE IF EXISTS `add_column_if_not_exists`;
|
||||
DELIMITER //
|
||||
CREATE PROCEDURE `add_column_if_not_exists`(
|
||||
IN p_table VARCHAR(64),
|
||||
IN p_column VARCHAR(64),
|
||||
IN p_definition VARCHAR(512)
|
||||
)
|
||||
BEGIN
|
||||
DECLARE col_count INT DEFAULT 0;
|
||||
SELECT COUNT(*) INTO col_count
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = p_table
|
||||
AND column_name = p_column;
|
||||
IF col_count = 0 THEN
|
||||
SET @sql = CONCAT('ALTER TABLE `', p_table, '` ADD COLUMN `', p_column, '` ', p_definition);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
END IF;
|
||||
END //
|
||||
DELIMITER ;
|
||||
|
||||
CALL `add_column_if_not_exists`('super_admins', 'need_change_password', 'TINYINT DEFAULT 1 COMMENT \'是否需要修改密码:1=需要,0=不需要\' AFTER `status`');
|
||||
|
||||
DROP PROCEDURE IF EXISTS `add_column_if_not_exists`;
|
||||
|
||||
-- 更新系统版本号
|
||||
INSERT INTO `system_settings` (`setting_key`, `setting_value`)
|
||||
VALUES ('db_version', '2.1')
|
||||
ON DUPLICATE KEY UPDATE `setting_value` = '2.1';
|
||||
|
||||
SELECT '升级完成!版本: v2.1' AS message;
|
||||
Reference in New Issue
Block a user