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: } 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) }