feat: 多班级版 v2.0 - Go后端重写 + 43轮代码审查

- 后端从 Python FastAPI 重写为 Go Gin(端口 56789)
- 多班级完全隔离
- 超级管理员独立登录
- 课代表作业管理、排行榜分项排行
- 角色加减分上下限可配置
- 家长改密功能(可开关)
- 周度/月度重置功能
- MySQL 5.7 兼容
- 43轮代码审查+全部修复
- Apache 2.0 许可证
This commit is contained in:
2026-06-22 10:06:10 +08:00
parent 4084afc53c
commit d6dec878bd
214 changed files with 12622 additions and 9725 deletions

View File

@@ -0,0 +1,152 @@
// ===========================================
// 多班级版班级管理系统 - 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/schema"
"hz-gitea.sea-studio.top/canglan/SharedClassManager/internal/service"
"hz-gitea.sea-studio.top/canglan/SharedClassManager/pkg/response"
)
// SubjectHandler 科目管理处理器
type SubjectHandler struct {
subjectService *service.SubjectService
}
// NewSubjectHandler 创建科目管理处理器
func NewSubjectHandler(subjectService *service.SubjectService) *SubjectHandler {
return &SubjectHandler{subjectService: subjectService}
}
// SubjectList 科目列表
func (h *SubjectHandler) SubjectList(c *gin.Context) {
var isActive *bool
if v := c.Query("is_active"); v == "true" {
b := true
isActive = &b
} else if v == "false" {
b := false
isActive = &b
}
result, err := h.subjectService.GetSubjects(isActive)
if err != nil {
response.InternalError(c, "获取科目列表失败")
return
}
response.Success(c, result, "操作成功")
}
// SubjectCreate 创建科目
func (h *SubjectHandler) SubjectCreate(c *gin.Context) {
var req schema.SubjectCreateRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误")
return
}
result, err := h.subjectService.CreateSubject(req.SubjectName, req.SubjectCode, req.SortOrder)
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, "操作成功")
}
// SubjectUpdate 更新科目
func (h *SubjectHandler) SubjectUpdate(c *gin.Context) {
subjectID, ok := parseID(c, "subject_id")
if !ok {
return
}
var req schema.SubjectUpdateRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误")
return
}
updates := make(map[string]interface{})
if req.SubjectName != nil {
updates["subject_name"] = *req.SubjectName
}
if req.SubjectCode != nil {
updates["subject_code"] = *req.SubjectCode
}
if req.IsActive != nil {
updates["is_active"] = *req.IsActive
}
if req.SortOrder != nil {
updates["sort_order"] = *req.SortOrder
}
if err := h.subjectService.UpdateSubject(subjectID, updates); err != nil {
response.InternalError(c, err.Error())
return
}
response.SuccessWithMessage(c, "更新成功")
}
// SubjectDelete 删除科目
func (h *SubjectHandler) SubjectDelete(c *gin.Context) {
subjectID, ok := parseID(c, "subject_id")
if !ok {
return
}
if err := h.subjectService.DeleteSubject(subjectID); err != nil {
response.InternalError(c, err.Error())
return
}
response.SuccessWithMessage(c, "删除成功")
}
// SubjectToggle 切换科目启用/禁用状态
func (h *SubjectHandler) SubjectToggle(c *gin.Context) {
subjectID, ok := parseID(c, "subject_id")
if !ok {
return
}
var req struct {
IsActive bool `json:"is_active"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误")
return
}
var err error
if req.IsActive {
err = h.subjectService.EnableSubject(subjectID)
} else {
err = h.subjectService.DisableSubject(subjectID)
}
if err != nil {
response.InternalError(c, err.Error())
return
}
if req.IsActive {
response.SuccessWithMessage(c, "科目已启用")
} else {
response.SuccessWithMessage(c, "科目已禁用")
}
}