Files
photowall/go/internal/handler/class_handler.go
T
hero920103 57d9866dab feat: PhotoWall 毕业照存储系统初始版本
后端: Go(Gin+GORM+MySQL+Redis)
- 17张业务表(yz_pw_前缀), 自动迁移
- JWT认证(3小时) + 盐+MD5密码 + 图形验证码
- 班级CRUD/加入(8人姓名验证/邀请码)/审核/30天自动清理
- 系统配置(16项)/菜单管理(动态路由)/数据统计
- 文件MD5去重/数据隔离/账号封禁/敏感词DFA检测

前端: Vue3+Vite+Element Plus+Less+ECharts+FontAwesome
- 动态路由(数据库菜单驱动)
- 蓝白配色, H5响应式
- 登录/注册/忘记密码/个人中心
- 班级创建向导/详情/加入/列表
- 管理后台: 审核/配置/菜单/统计/用户/敏感词

数据库: MySQL 10.31.100.3:3306/photowall
管理员: hero920103 / 920103
2026-09-03 05:55:23 +08:00

225 lines
6.4 KiB
Go

package handler
import (
"photowall/internal/middleware"
"photowall/internal/service"
"photowall/pkg/response"
"strconv"
"github.com/gin-gonic/gin"
)
type ClassHandler struct {
svc *service.ClassService
}
func NewClassHandler(svc *service.ClassService) *ClassHandler {
return &ClassHandler{svc: svc}
}
// Create POST /api/classes
func (h *ClassHandler) Create(c *gin.Context) {
userID := middleware.CurrentUserID(c)
var req service.CreateClassReq
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误:"+err.Error())
return
}
class, err := h.svc.Create(userID, &req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.Created(c, class)
}
// Detail GET /api/classes/:id
func (h *ClassHandler) Detail(c *gin.Context) {
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
userID := middleware.CurrentUserID(c)
isSuperAdmin := middleware.CurrentRole(c) == "admin"
detail, err := h.svc.GetDetail(uint(id), userID, isSuperAdmin)
if err != nil {
response.NotFound(c, err.Error())
return
}
response.OK(c, detail)
}
// Search GET /api/classes/search
func (h *ClassHandler) Search(c *gin.Context) {
var req service.SearchClassReq
if err := c.ShouldBindQuery(&req); err != nil {
response.BadRequest(c, "参数错误")
return
}
result, err := h.svc.Search(&req)
if err != nil {
response.Internal(c, err.Error())
return
}
response.OK(c, result)
}
// JoinBySearch POST /api/classes/join/search
func (h *ClassHandler) JoinBySearch(c *gin.Context) {
userID := middleware.CurrentUserID(c)
var req service.JoinBySearchReq
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误:"+err.Error())
return
}
if err := h.svc.JoinBySearch(userID, &req); err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, gin.H{"message": "加入成功"})
}
// JoinByInvitation POST /api/classes/join/invite
func (h *ClassHandler) JoinByInvitation(c *gin.Context) {
userID := middleware.CurrentUserID(c)
var req service.JoinByInvitationReq
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "邀请码不能为空")
return
}
class, err := h.svc.JoinByInvitation(userID, &req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, gin.H{"message": "加入成功", "class_id": class.ID, "class_name": class.Name})
}
// Mine GET /api/classes/mine
func (h *ClassHandler) Mine(c *gin.Context) {
userID := middleware.CurrentUserID(c)
list, err := h.svc.ListMyClasses(userID)
if err != nil {
response.Internal(c, err.Error())
return
}
response.OK(c, list)
}
// CreateInvitation POST /api/classes/:id/invitation
func (h *ClassHandler) CreateInvitation(c *gin.Context) {
userID := middleware.CurrentUserID(c)
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
var body struct {
MaxUses int `json:"max_uses"`
ExpireDays int `json:"expire_days"`
}
c.ShouldBindJSON(&body)
inv, err := h.svc.CreateInvitation(uint(id), userID, body.MaxUses, body.ExpireDays)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.Created(c, inv)
}
// ListInvitations GET /api/classes/:id/invitations
func (h *ClassHandler) ListInvitations(c *gin.Context) {
userID := middleware.CurrentUserID(c)
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
list, err := h.svc.ListInvitations(uint(id), userID)
if err != nil {
response.Forbidden(c, err.Error())
return
}
response.OK(c, list)
}
// DisableInvitation DELETE /api/classes/:id/invitations/:inv_id
func (h *ClassHandler) DisableInvitation(c *gin.Context) {
userID := middleware.CurrentUserID(c)
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
invID, _ := strconv.ParseUint(c.Param("inv_id"), 10, 64)
if err := h.svc.DisableInvitation(uint(id), uint(invID), userID); err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, gin.H{"message": "已禁用"})
}
// TransferAdmin POST /api/classes/:id/transfer
func (h *ClassHandler) TransferAdmin(c *gin.Context) {
userID := middleware.CurrentUserID(c)
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
var body struct {
ToUserID uint `json:"to_user_id" binding:"required"`
}
if err := c.ShouldBindJSON(&body); err != nil {
response.BadRequest(c, "请指定目标用户")
return
}
if err := h.svc.TransferAdmin(uint(id), userID, body.ToUserID); err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, gin.H{"message": "管理员已转移"})
}
// RemoveMember DELETE /api/classes/:id/members/:user_id
func (h *ClassHandler) RemoveMember(c *gin.Context) {
userID := middleware.CurrentUserID(c)
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
targetID, _ := strconv.ParseUint(c.Param("user_id"), 10, 64)
if err := h.svc.RemoveMember(uint(id), userID, uint(targetID)); err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, gin.H{"message": "已移除"})
}
// UploadPhoto POST /api/classes/:id/photos
func (h *ClassHandler) UploadPhoto(c *gin.Context) {
userID := middleware.CurrentUserID(c)
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
var body struct {
PhotoURL string `json:"photo_url" binding:"required"`
Caption string `json:"caption"`
}
if err := c.ShouldBindJSON(&body); err != nil {
response.BadRequest(c, "请先上传图片获取URL")
return
}
photo, err := h.svc.UploadPhoto(uint(id), userID, body.PhotoURL, body.Caption)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.Created(c, photo)
}
// DeletePhoto DELETE /api/classes/:id/photos/:photo_id
func (h *ClassHandler) DeletePhoto(c *gin.Context) {
userID := middleware.CurrentUserID(c)
isSuperAdmin := middleware.CurrentRole(c) == "admin"
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
photoID, _ := strconv.ParseUint(c.Param("photo_id"), 10, 64)
if err := h.svc.DeletePhoto(uint(id), uint(photoID), userID, isSuperAdmin); err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, gin.H{"message": "已删除"})
}
// Resubmit POST /api/classes/:id/resubmit
func (h *ClassHandler) Resubmit(c *gin.Context) {
userID := middleware.CurrentUserID(c)
id, _ := strconv.ParseUint(c.Param("id"), 10, 64)
var req service.ResubmitReq
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误")
return
}
if err := h.svc.Resubmit(uint(id), userID, &req); err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, gin.H{"message": "已重新提交审核"})
}