package handler import ( "carrotskin/internal/container" "carrotskin/internal/model" "carrotskin/internal/service" "carrotskin/internal/types" "strconv" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // TextureHandler 材质处理器(依赖注入版本) type TextureHandler struct { container *container.Container logger *zap.Logger } // NewTextureHandler 创建TextureHandler实例 func NewTextureHandler(c *container.Container) *TextureHandler { return &TextureHandler{ container: c, logger: c.Logger, } } // GenerateUploadURL 生成材质上传URL func (h *TextureHandler) GenerateUploadURL(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } var req types.GenerateTextureUploadURLRequest if err := c.ShouldBindJSON(&req); err != nil { RespondBadRequest(c, "请求参数错误", err) return } if h.container.Storage == nil { RespondServerError(c, "存储服务不可用", nil) return } result, err := service.GenerateTextureUploadURL( c.Request.Context(), h.container.Storage, userID, req.FileName, string(req.TextureType), ) if err != nil { h.logger.Error("生成材质上传URL失败", zap.Int64("user_id", userID), zap.String("file_name", req.FileName), zap.String("texture_type", string(req.TextureType)), zap.Error(err), ) RespondBadRequest(c, err.Error(), nil) return } RespondSuccess(c, &types.GenerateTextureUploadURLResponse{ PostURL: result.PostURL, FormData: result.FormData, TextureURL: result.FileURL, ExpiresIn: 900, }) } // Create 创建材质记录 func (h *TextureHandler) Create(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } var req types.CreateTextureRequest if err := c.ShouldBindJSON(&req); err != nil { RespondBadRequest(c, "请求参数错误", err) return } maxTextures := service.GetMaxTexturesPerUser() if err := service.CheckTextureUploadLimit(h.container.DB, userID, maxTextures); err != nil { RespondBadRequest(c, err.Error(), nil) return } texture, err := service.CreateTexture(h.container.DB, userID, req.Name, req.Description, string(req.Type), req.URL, req.Hash, req.Size, req.IsPublic, req.IsSlim, ) if err != nil { h.logger.Error("创建材质失败", zap.Int64("user_id", userID), zap.String("name", req.Name), zap.Error(err), ) RespondBadRequest(c, err.Error(), nil) return } RespondSuccess(c, TextureToTextureInfo(texture)) } // Get 获取材质详情 func (h *TextureHandler) Get(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { RespondBadRequest(c, "无效的材质ID", err) return } texture, err := service.GetTextureByID(h.container.DB, id) if err != nil { RespondNotFound(c, err.Error()) return } RespondSuccess(c, TextureToTextureInfo(texture)) } // Search 搜索材质 func (h *TextureHandler) Search(c *gin.Context) { keyword := c.Query("keyword") textureTypeStr := c.Query("type") publicOnly := c.Query("public_only") == "true" page := parseIntWithDefault(c.DefaultQuery("page", "1"), 1) pageSize := parseIntWithDefault(c.DefaultQuery("page_size", "20"), 20) var textureType model.TextureType switch textureTypeStr { case "SKIN": textureType = model.TextureTypeSkin case "CAPE": textureType = model.TextureTypeCape } textures, total, err := service.SearchTextures(h.container.DB, keyword, textureType, publicOnly, page, pageSize) if err != nil { h.logger.Error("搜索材质失败", zap.String("keyword", keyword), zap.Error(err)) RespondServerError(c, "搜索材质失败", err) return } c.JSON(200, model.NewPaginationResponse(TexturesToTextureInfos(textures), total, page, pageSize)) } // Update 更新材质 func (h *TextureHandler) Update(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } textureID, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { RespondBadRequest(c, "无效的材质ID", err) return } var req types.UpdateTextureRequest if err := c.ShouldBindJSON(&req); err != nil { RespondBadRequest(c, "请求参数错误", err) return } texture, err := service.UpdateTexture(h.container.DB, textureID, userID, req.Name, req.Description, req.IsPublic) if err != nil { h.logger.Error("更新材质失败", zap.Int64("user_id", userID), zap.Int64("texture_id", textureID), zap.Error(err), ) RespondForbidden(c, err.Error()) return } RespondSuccess(c, TextureToTextureInfo(texture)) } // Delete 删除材质 func (h *TextureHandler) Delete(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } textureID, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { RespondBadRequest(c, "无效的材质ID", err) return } if err := service.DeleteTexture(h.container.DB, textureID, userID); err != nil { h.logger.Error("删除材质失败", zap.Int64("user_id", userID), zap.Int64("texture_id", textureID), zap.Error(err), ) RespondForbidden(c, err.Error()) return } RespondSuccess(c, nil) } // ToggleFavorite 切换收藏状态 func (h *TextureHandler) ToggleFavorite(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } textureID, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { RespondBadRequest(c, "无效的材质ID", err) return } isFavorited, err := service.ToggleTextureFavorite(h.container.DB, userID, textureID) if err != nil { h.logger.Error("切换收藏状态失败", zap.Int64("user_id", userID), zap.Int64("texture_id", textureID), zap.Error(err), ) RespondBadRequest(c, err.Error(), nil) return } RespondSuccess(c, map[string]bool{"is_favorited": isFavorited}) } // GetUserTextures 获取用户上传的材质列表 func (h *TextureHandler) GetUserTextures(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } page := parseIntWithDefault(c.DefaultQuery("page", "1"), 1) pageSize := parseIntWithDefault(c.DefaultQuery("page_size", "20"), 20) textures, total, err := service.GetUserTextures(h.container.DB, userID, page, pageSize) if err != nil { h.logger.Error("获取用户材质列表失败", zap.Int64("user_id", userID), zap.Error(err)) RespondServerError(c, "获取材质列表失败", err) return } c.JSON(200, model.NewPaginationResponse(TexturesToTextureInfos(textures), total, page, pageSize)) } // GetUserFavorites 获取用户收藏的材质列表 func (h *TextureHandler) GetUserFavorites(c *gin.Context) { userID, ok := GetUserIDFromContext(c) if !ok { return } page := parseIntWithDefault(c.DefaultQuery("page", "1"), 1) pageSize := parseIntWithDefault(c.DefaultQuery("page_size", "20"), 20) textures, total, err := service.GetUserTextureFavorites(h.container.DB, userID, page, pageSize) if err != nil { h.logger.Error("获取用户收藏列表失败", zap.Int64("user_id", userID), zap.Error(err)) RespondServerError(c, "获取收藏列表失败", err) return } c.JSON(200, model.NewPaginationResponse(TexturesToTextureInfos(textures), total, page, pageSize)) }