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": "已重新提交审核"}) }