Files
zhengchiliu c2519c4b6d feat(clothes): 支持通过社区公开穿搭只读查看衣物
新增 outfit_uuid 查询参数,非属主可通过社区公开穿搭查看衣物详情。
同时调整点赞通知逻辑,仅在首次点赞时发送通知。
2026-09-16 02:28:59 +08:00

164 lines
4.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package v1
import (
"net/http"
"git.lzcwy.cn/zhengchiliu/zt-closet-backend/global"
"git.lzcwy.cn/zhengchiliu/zt-closet-backend/internal/dto"
"git.lzcwy.cn/zhengchiliu/zt-closet-backend/internal/middleware"
"git.lzcwy.cn/zhengchiliu/zt-closet-backend/internal/service"
"git.lzcwy.cn/zhengchiliu/zt-closet-backend/pkg/app"
"git.lzcwy.cn/zhengchiliu/zt-closet-backend/pkg/errcode"
"github.com/gin-gonic/gin"
)
// ClothesHandler 衣物相关接口。
type ClothesHandler struct {
svc *service.ClothesService
}
// NewClothesHandler 创建衣物 handler。
func NewClothesHandler() *ClothesHandler {
return &ClothesHandler{svc: service.NewClothesService()}
}
// Upload 上传衣物图片(multipart,字段名 file)。
func (h *ClothesHandler) Upload(c *gin.Context) {
response := app.NewResponse(c)
userID, ok := middleware.GetUserID(c.Request.Context())
if !ok {
response.ToErrorResponse(errcode.Unauthorized)
return
}
// 解析 multipart 前限制请求体大小(MaxSizeMB + 1MB 的 multipart 边界开销),
// 防止超大 body 在 FormFile 解析时耗尽内存/磁盘。
maxBytes := int64(global.UploadSetting.MaxSizeMB)*1024*1024 + 1024*1024
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, maxBytes)
fileHeader, err := c.FormFile("file")
if err != nil {
response.ToErrorResponse(errcode.UploadFileEmpty.WithDetails(err.Error()))
return
}
out, e := h.svc.Upload(c.Request.Context(), userID, fileHeader)
if e != nil {
response.ToErrorResponse(e)
return
}
response.ToResponse(out)
}
// List 分页查询当前用户衣物。
func (h *ClothesHandler) List(c *gin.Context) {
response := app.NewResponse(c)
userID, ok := middleware.GetUserID(c.Request.Context())
if !ok {
response.ToErrorResponse(errcode.Unauthorized)
return
}
var request dto.ClothesListRequest
if err := c.ShouldBindQuery(&request); err != nil {
response.ToErrorResponse(errcode.InvalidParams.WithDetails(err.Error()))
return
}
out, e := h.svc.List(c.Request.Context(), userID, &request)
if e != nil {
response.ToErrorResponse(e)
return
}
response.ToResponse(out)
}
// Get 获取衣物详情(uuid 来自路径参数)。
func (h *ClothesHandler) Get(c *gin.Context) {
response := app.NewResponse(c)
userID, ok := middleware.GetUserID(c.Request.Context())
if !ok {
response.ToErrorResponse(errcode.Unauthorized)
return
}
request := dto.ClothesGetByUUIDRequest{
ClothesUUID: c.Param("uuid"),
// 非属主只读查看的两个入口:穿搭分享(share_uuid)与社区公开穿搭(outfit_uuid)
ShareUUID: c.Query("share_uuid"),
OutfitUUID: c.Query("outfit_uuid"),
}
if request.ClothesUUID == "" {
response.ToErrorResponse(errcode.InvalidParams)
return
}
out, e := h.svc.GetByUUID(c.Request.Context(), userID, &request)
if e != nil {
response.ToErrorResponse(e)
return
}
response.ToResponse(out)
}
// Status 查询衣物图片处理状态(uuid 来自路径参数)。
func (h *ClothesHandler) Status(c *gin.Context) {
response := app.NewResponse(c)
userID, ok := middleware.GetUserID(c.Request.Context())
if !ok {
response.ToErrorResponse(errcode.Unauthorized)
return
}
request := dto.ClothesProcessStatusGetByUUIDRequest{ClothesUUID: c.Param("uuid")}
if request.ClothesUUID == "" {
response.ToErrorResponse(errcode.InvalidParams)
return
}
out, e := h.svc.ProcessStatusGetByUUID(c.Request.Context(), userID, &request)
if e != nil {
response.ToErrorResponse(e)
return
}
response.ToResponse(out)
}
// Update 修改衣物属性(uuid 来自路径参数)。
func (h *ClothesHandler) Update(c *gin.Context) {
response := app.NewResponse(c)
userID, ok := middleware.GetUserID(c.Request.Context())
if !ok {
response.ToErrorResponse(errcode.Unauthorized)
return
}
var request dto.ClothesUpdateByUUIDRequest
if err := c.ShouldBindJSON(&request); err != nil {
response.ToErrorResponse(errcode.InvalidParams.WithDetails(err.Error()))
return
}
request.ClothesUUID = c.Param("uuid")
if request.ClothesUUID == "" {
response.ToErrorResponse(errcode.InvalidParams)
return
}
out, e := h.svc.UpdateByUUID(c.Request.Context(), userID, &request)
if e != nil {
response.ToErrorResponse(e)
return
}
response.ToResponse(out)
}
// Delete 删除衣物(uuid 来自路径参数)。
func (h *ClothesHandler) Delete(c *gin.Context) {
response := app.NewResponse(c)
userID, ok := middleware.GetUserID(c.Request.Context())
if !ok {
response.ToErrorResponse(errcode.Unauthorized)
return
}
request := dto.ClothesDeleteByUUIDRequest{ClothesUUID: c.Param("uuid")}
if request.ClothesUUID == "" {
response.ToErrorResponse(errcode.InvalidParams)
return
}
out, e := h.svc.DeleteByUUID(c.Request.Context(), userID, &request)
if e != nil {
response.ToErrorResponse(e)
return
}
response.ToResponse(out)
}