Files
SharedClassManager/backend-go/internal/handler/class_handler.go
canglan 124d7f645e 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
2026-06-22 10:21:52 +08:00

272 lines
7.5 KiB
Go

// ===========================================
// 多班级版班级管理系统 - Go 后端
//
// 开发者: Canglan
// 联系方式: admin@sea-studio.top
// 版权归属: Sea Network Technology Studio
// 许可证: Apache License 2.0
//
// 版权所有 © Sea Network Technology Studio
// ===========================================
package handler
import (
"github.com/gin-gonic/gin"
"hz-gitea.sea-studio.top/canglan/SharedClassManager/internal/middleware"
"hz-gitea.sea-studio.top/canglan/SharedClassManager/internal/schema"
"hz-gitea.sea-studio.top/canglan/SharedClassManager/internal/service"
"hz-gitea.sea-studio.top/canglan/SharedClassManager/pkg/response"
)
// ClassHandler 班级管理处理器
type ClassHandler struct {
classService *service.ClassService
}
// NewClassHandler 创建班级管理处理器
func NewClassHandler(classService *service.ClassService) *ClassHandler {
return &ClassHandler{classService: classService}
}
// ClassList 班级列表
func (h *ClassHandler) ClassList(c *gin.Context) {
includeDisabled := c.Query("include_disabled") == "true"
result, err := h.classService.ListClasses(includeDisabled)
if err != nil {
response.InternalError(c, "获取班级列表失败")
return
}
response.Success(c, result, "操作成功")
}
// ClassDetail 班级详情
func (h *ClassHandler) ClassDetail(c *gin.Context) {
classID, ok := parseID(c, "class_id")
if !ok {
return
}
result, err := h.classService.GetClassDetail(classID)
if err != nil {
response.NotFound(c, "班级不存在")
return
}
response.Success(c, result, "操作成功")
}
// ClassCreate 创建班级
func (h *ClassHandler) ClassCreate(c *gin.Context) {
var req schema.ClassCreateRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误")
return
}
result, err := h.classService.CreateClass(req.ClassName, req.Grade, req.Description)
if err != nil {
response.InternalError(c, err.Error())
return
}
if success, _ := result["success"].(bool); !success {
response.BadRequest(c, result["message"].(string))
return
}
response.Success(c, result, "班级创建成功")
}
// ClassUpdate 更新班级
func (h *ClassHandler) ClassUpdate(c *gin.Context) {
classID, ok := parseID(c, "class_id")
if !ok {
return
}
var req schema.ClassUpdateRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误")
return
}
if err := h.classService.UpdateClass(classID, req.ClassName, req.Grade, req.Description, req.Status); err != nil {
response.InternalError(c, err.Error())
return
}
response.SuccessWithMessage(c, "更新成功")
}
// ClassDelete 删除班级
func (h *ClassHandler) ClassDelete(c *gin.Context) {
classID, ok := parseID(c, "class_id")
if !ok {
return
}
if err := h.classService.DeleteClass(classID); err != nil {
response.InternalError(c, err.Error())
return
}
response.SuccessWithMessage(c, "删除成功")
}
// SwitchClass 切换班级上下文
func (h *ClassHandler) SwitchClass(c *gin.Context) {
var req schema.SwitchClassRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误")
return
}
userID := middleware.GetUserID(c)
result, err := h.classService.SwitchClass(userID, req.ClassID)
if err != nil {
response.InternalError(c, err.Error())
return
}
response.Success(c, result, "切换成功")
}
// GetSettings 获取班级设置
func (h *ClassHandler) GetSettings(c *gin.Context) {
classID := middleware.GetClassID(c)
result, err := h.classService.GetSettings(classID)
if err != nil {
response.InternalError(c, "获取设置失败")
return
}
response.Success(c, result, "操作成功")
}
// allowedSettingKeys 允许通过 SaveSetting 端点写入的配置键白名单
var allowedSettingKeys = map[string]bool{
"initial_password": true,
"initial_points": true,
"deduction_attendance_absent": true,
"deduction_attendance_late": true,
"deduction_attendance_leave": true,
"deduction_homework_not_submit": true,
"deduction_homework_late": true,
"reset_frequency": true,
"reset_day_of_week": true,
"reset_day_of_month": true,
}
// SaveSetting 保存班级设置
func (h *ClassHandler) SaveSetting(c *gin.Context) {
classID := middleware.GetClassID(c)
var req schema.SettingRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误")
return
}
if !allowedSettingKeys[req.SettingKey] {
response.BadRequest(c, "不允许的配置项: "+req.SettingKey)
return
}
if err := h.classService.SaveSetting(classID, req.SettingKey, req.SettingValue); err != nil {
response.InternalError(c, "保存设置失败")
return
}
response.SuccessWithMessage(c, "保存成功")
}
// GetPointLimits 获取角色加减分配置
func (h *ClassHandler) GetPointLimits(c *gin.Context) {
classID := middleware.GetClassID(c)
result, err := h.classService.GetSettings(classID)
if err != nil {
response.InternalError(c, "获取配置失败")
return
}
response.Success(c, result, "操作成功")
}
// allowedPointLimitKeys 允许的操行分限制配置键白名单(与 conduct_service 读取 key 一致)
var allowedPointLimitKeys = map[string]bool{
"point_limit_班长_max": true,
"point_limit_班长_min": true,
"point_limit_学习委员_max": true,
"point_limit_学习委员_min": true,
"point_limit_考勤委员_max": true,
"point_limit_考勤委员_min": true,
"point_limit_劳动委员_max": true,
"point_limit_劳动委员_min": true,
"point_limit_志愿委员_max": true,
"point_limit_志愿委员_min": true,
"point_limit_科任老师_max": true,
"point_limit_科任老师_min": true,
}
// SavePointLimits 保存角色加减分配置
func (h *ClassHandler) SavePointLimits(c *gin.Context) {
classID := middleware.GetClassID(c)
var req map[string]string
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误")
return
}
for key, value := range req {
if !allowedPointLimitKeys[key] {
response.BadRequest(c, "不允许的配置项: "+key)
return
}
if err := h.classService.SaveSetting(classID, key, value); err != nil {
response.InternalError(c, "保存配置失败")
return
}
}
response.SuccessWithMessage(c, "保存成功")
}
// GetFeatures 获取功能开关
func (h *ClassHandler) GetFeatures(c *gin.Context) {
classID := middleware.GetClassID(c)
result, err := h.classService.GetFeatures(classID)
if err != nil {
response.InternalError(c, "获取功能开关失败")
return
}
response.Success(c, result, "操作成功")
}
// allowedFeatureKeys 允许的功能开关键白名单
var allowedFeatureKeys = map[string]bool{
"parent_account_enabled": true,
"parent_password_change_enabled": true,
"parent_view_attendance": true,
"parent_view_ranking": true,
"student_view_ranking": true,
"homework_management": true,
"attendance_management": true,
"cadre_homework": true,
}
// SaveFeature 保存功能开关
func (h *ClassHandler) SaveFeature(c *gin.Context) {
classID := middleware.GetClassID(c)
var req schema.FeatureToggleRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误")
return
}
if !allowedFeatureKeys[req.FeatureKey] {
response.BadRequest(c, "不允许的功能开关: "+req.FeatureKey)
return
}
if err := h.classService.SaveFeature(classID, req.FeatureKey, req.Enabled); err != nil {
response.InternalError(c, "保存功能开关失败")
return
}
response.SuccessWithMessage(c, "保存成功")
}