Files
backend_v2/internal/handler/favorite_handler.go
toom1996 dbee704c95 update
2026-09-13 00:52:35 +08:00

119 lines
3.3 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"
"fashionapi/internal/dto"
"fashionapi/internal/middleware"
"fashionapi/internal/pkg/pagination"
"fashionapi/internal/pkg/response"
"fashionapi/internal/service"
"github.com/gin-gonic/gin"
)
// FavoriteHandler 收藏接口(需 Bearer 鉴权,主挂载于 /api/v1/me,legacy /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/me/favorites?page=1&per_page=24&kind=(per_page 上限 100)
// kind 留空=不限粒度;gallery=只要图集收藏;image=只要单图收藏。
// 成功: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
}
p := pagination.Parse(c, "page", "per_page", 1, 24, 100)
kind := c.Query("kind")
if kind != "" && kind != dto.FavoriteKindGallery && kind != dto.FavoriteKindImage {
response.Error(c, http.StatusBadRequest, "invalid kind")
return
}
items, total, err := h.favs.ListPaged(c.Request.Context(), userID, p.Page, p.PageSize, kind)
if err != nil {
fail(c, err)
return
}
response.Data(c, http.StatusOK, gin.H{
"items": items,
"total": total,
"last_page": response.LastPage(total, p.PageSize),
})
}
// Add 新增收藏(幂等:重复添加不报错)。
//
// POST /api/v1/me/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/me/favorites/: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("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/me/favorites/checks
// 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)
}