119 lines
3.3 KiB
Go
119 lines
3.3 KiB
Go
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)
|
||
}
|