Files
backend_v2/internal/handler/favorite_handler.go
toom1996 1fd9c48f58 update
2026-09-02 21:51:35 +08:00

120 lines
3.1 KiB
Go
Raw 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 handler
import (
"net/http"
"strconv"
"fashionapi/internal/dto"
"fashionapi/internal/middleware"
"fashionapi/internal/pkg/response"
"fashionapi/internal/service"
"github.com/gin-gonic/gin"
)
// FavoriteHandler 收藏接口(需 Bearer 鉴权,挂在 /api/v1/auth 下)。
type FavoriteHandler struct {
favs service.FavoriteService
}
// NewFavoriteHandler 创建收藏 handler。
func NewFavoriteHandler(favs service.FavoriteService) *FavoriteHandler {
return &FavoriteHandler{favs: favs}
}
// List 当前用户收藏(服务端分页)。
//
// GET /api/v1/auth/favorites?page=1&per_page=24(per_page 上限 100)
// 成功:200 { data: { items:[...], total, last_page } }
func (h *FavoriteHandler) List(c *gin.Context) {
userID, ok := middleware.UserIDFrom(c)
if !ok {
response.Error(c, http.StatusUnauthorized, "unauthorized")
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
perPage, _ := strconv.Atoi(c.DefaultQuery("per_page", "24"))
if page < 1 {
page = 1
}
if perPage < 1 || perPage > 100 {
perPage = 24
}
items, total, err := h.favs.ListPaged(c.Request.Context(), userID, page, perPage)
if err != nil {
fail(c, err)
return
}
response.Data(c, http.StatusOK, gin.H{
"items": items,
"total": total,
"last_page": response.LastPage(total, perPage),
})
}
// Add 新增收藏(幂等:重复添加不报错)。
//
// POST /api/v1/auth/favorites
// body: { target_type, target_uid, title?, cover?, brand? }
// 成功:200 { data: <FavoriteItem> }
func (h *FavoriteHandler) Add(c *gin.Context) {
userID, ok := middleware.UserIDFrom(c)
if !ok {
response.Error(c, http.StatusUnauthorized, "unauthorized")
return
}
var req dto.FavoriteAdd
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, http.StatusBadRequest, "invalid request")
return
}
item, err := h.favs.Add(c.Request.Context(), userID, req)
if err != nil {
fail(c, err)
return
}
response.Data(c, http.StatusOK, item)
}
// Remove 删除收藏。
//
// DELETE /api/v1/auth/favorites/:target_uid
// 成功:200 { data: { ok: true } }
func (h *FavoriteHandler) Remove(c *gin.Context) {
userID, ok := middleware.UserIDFrom(c)
if !ok {
response.Error(c, http.StatusUnauthorized, "unauthorized")
return
}
uid := c.Param("target_uid")
if err := h.favs.Remove(c.Request.Context(), userID, uid); err != nil {
fail(c, err)
return
}
response.Data(c, http.StatusOK, gin.H{"ok": true})
}
// Check 批量查询给定 ids 中哪些已收藏(列表页打勾用,与收藏总量解耦)。
//
// POST /api/v1/auth/favorites/check
// body: { ids: ["r=...","s=..."] }
// 成功:200 { data: ["r=..."] }(仅返回已收藏的 id)
func (h *FavoriteHandler) Check(c *gin.Context) {
userID, ok := middleware.UserIDFrom(c)
if !ok {
response.Error(c, http.StatusUnauthorized, "unauthorized")
return
}
var req dto.FavoriteCheck
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, http.StatusBadRequest, "invalid request")
return
}
ids, err := h.favs.Check(c.Request.Context(), userID, req.IDs)
if err != nil {
fail(c, err)
return
}
response.Data(c, http.StatusOK, ids)
}