Files
backend/internal/handler/texture_handler.go

304 lines
7.2 KiB
Go

package handler
import (
"carrotskin/internal/container"
"carrotskin/internal/model"
"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,
}
}
// 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 := h.container.TextureService.GetByID(c.Request.Context(), 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 := h.container.TextureService.Search(c.Request.Context(), keyword, textureType, publicOnly, page, pageSize)
if err != nil {
h.logger.Error("搜索材质失败", zap.String("keyword", keyword), zap.Error(err))
RespondServerError(c, "搜索材质失败", err)
return
}
// 返回格式:
// {
// "code": 200,
// "message": "操作成功",
// "data": {
// "list": [...],
// "total": 1,
// "page": 1,
// "per_page": 5
// }
// }
RespondSuccess(c, gin.H{
"list": TexturesToTextureInfos(textures),
"total": total,
"page": page,
"per_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 := h.container.TextureService.Update(c.Request.Context(), 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 := h.container.TextureService.Delete(c.Request.Context(), 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 := h.container.TextureService.ToggleFavorite(c.Request.Context(), 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 := h.container.TextureService.GetByUserID(c.Request.Context(), userID, page, pageSize)
if err != nil {
h.logger.Error("获取用户材质列表失败", zap.Int64("user_id", userID), zap.Error(err))
RespondServerError(c, "获取材质列表失败", err)
return
}
RespondSuccess(c, gin.H{
"list": TexturesToTextureInfos(textures),
"total": total,
"page": page,
"per_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 := h.container.TextureService.GetUserFavorites(c.Request.Context(), userID, page, pageSize)
if err != nil {
h.logger.Error("获取用户收藏列表失败", zap.Int64("user_id", userID), zap.Error(err))
RespondServerError(c, "获取收藏列表失败", err)
return
}
RespondSuccess(c, gin.H{
"list": TexturesToTextureInfos(textures),
"total": total,
"page": page,
"per_page": pageSize,
})
}
// Upload 直接上传材质文件
func (h *TextureHandler) Upload(c *gin.Context) {
userID, ok := GetUserIDFromContext(c)
if !ok {
return
}
// 解析multipart表单
if err := c.Request.ParseMultipartForm(32 << 20); err != nil { // 32MB
RespondBadRequest(c, "解析表单失败", err)
return
}
// 获取文件
file, err := c.FormFile("file")
if err != nil {
RespondBadRequest(c, "获取文件失败", err)
return
}
// 读取文件内容
src, err := file.Open()
if err != nil {
RespondBadRequest(c, "打开文件失败", err)
return
}
defer src.Close()
fileData := make([]byte, file.Size)
if _, err := src.Read(fileData); err != nil {
RespondBadRequest(c, "读取文件失败", err)
return
}
// 获取表单字段
name := c.PostForm("name")
if name == "" {
RespondBadRequest(c, "名称不能为空", nil)
return
}
description := c.PostForm("description")
textureType := c.PostForm("type")
if textureType == "" {
textureType = "SKIN" // 默认值
}
isPublic := c.PostForm("is_public") == "true"
isSlim := c.PostForm("is_slim") == "true"
// 检查上传限制
maxTextures := h.container.UserService.GetMaxTexturesPerUser()
if err := h.container.TextureService.CheckUploadLimit(c.Request.Context(), userID, maxTextures); err != nil {
RespondBadRequest(c, err.Error(), nil)
return
}
// 调用服务上传
texture, err := h.container.TextureService.UploadTexture(
c.Request.Context(),
userID,
name,
description,
textureType,
fileData,
file.Filename,
isPublic,
isSlim,
)
if err != nil {
h.logger.Error("上传材质失败",
zap.Int64("user_id", userID),
zap.String("file_name", file.Filename),
zap.Error(err),
)
RespondBadRequest(c, err.Error(), nil)
return
}
RespondSuccess(c, TextureToTextureInfo(texture))
}