Files
mengyastore/mengyastore-backend-go/internal/handlers/wishlist.go
2026-05-16 19:03:36 +08:00

125 lines
4.0 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 handlers
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
"mengyastore-backend/internal/auth"
"mengyastore-backend/internal/storage"
)
type WishlistHandler struct {
wishlistStore *storage.WishlistStore
authClient *auth.SproutGateClient
}
func NewWishlistHandler(wishlistStore *storage.WishlistStore, authClient *auth.SproutGateClient) *WishlistHandler {
return &WishlistHandler{wishlistStore: wishlistStore, authClient: authClient}
}
func (h *WishlistHandler) requireUser(c *gin.Context) (string, bool) {
authHeader := c.GetHeader("Authorization")
if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") {
c.JSON(http.StatusUnauthorized, gin.H{"error": "请先登录"})
return "", false
}
token := strings.TrimPrefix(authHeader, "Bearer ")
result, err := h.authClient.VerifyToken(token)
if err != nil || !result.Valid || result.User == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "登录已过期,请重新登录"})
return "", false
}
return result.User.Account, true
}
// GetWishlist 当前用户收藏的商品 ID 列表。
// @Summary 获取当前用户收藏列表
// @Description 需 Bearer 登录。返回该账号已收藏的商品 ID 数组(顺序由存储实现决定)。
// @Tags 收藏
// @Produce json
// @Security BearerAuth
// @Success 200 {object} SwaggerWishlistWrap
// @Failure 401 {object} SwaggerErrorBody
// @Failure 500 {object} SwaggerErrorBody
// @Router /api/wishlist [get]
func (h *WishlistHandler) GetWishlist(c *gin.Context) {
account, ok := h.requireUser(c)
if !ok {
return
}
ids, err := h.wishlistStore.Get(account)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": gin.H{"items": ids}})
}
// WishlistItemPayload 添加收藏请求体。
type WishlistItemPayload struct {
ProductID string `json:"productId"`
}
// AddToWishlist 添加收藏。
// @Summary 添加商品到收藏
// @Description 需 Bearer。请求体为 `{ "productId": "..." }`;幂等语义由存储层实现(重复添加可忽略或报错以实际为准)。
// @Tags 收藏
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param body body WishlistItemPayload true "包含 productId 的 JSON"
// @Success 200 {object} SwaggerWishlistWrap
// @Failure 400 {object} SwaggerErrorBody
// @Failure 401 {object} SwaggerErrorBody
// @Failure 500 {object} SwaggerErrorBody
// @Router /api/wishlist [post]
func (h *WishlistHandler) AddToWishlist(c *gin.Context) {
account, ok := h.requireUser(c)
if !ok {
return
}
var payload WishlistItemPayload
if err := c.ShouldBindJSON(&payload); err != nil || payload.ProductID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数有误"})
return
}
if err := h.wishlistStore.Add(account, payload.ProductID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
ids, _ := h.wishlistStore.Get(account)
c.JSON(http.StatusOK, gin.H{"data": gin.H{"items": ids}})
}
// RemoveFromWishlist 按商品 ID 移除收藏。
// @Summary 从收藏中移除商品
// @Description 需 Bearer。路径参数为要移除的商品 ID。
// @Tags 收藏
// @Produce json
// @Security BearerAuth
// @Param id path string true "商品ID路径"
// @Success 200 {object} SwaggerWishlistWrap
// @Failure 400 {object} SwaggerErrorBody
// @Failure 401 {object} SwaggerErrorBody
// @Failure 500 {object} SwaggerErrorBody
// @Router /api/wishlist/{id} [delete]
func (h *WishlistHandler) RemoveFromWishlist(c *gin.Context) {
account, ok := h.requireUser(c)
if !ok {
return
}
productID := c.Param("id")
if productID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "缺少商品 ID"})
return
}
if err := h.wishlistStore.Remove(account, productID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
ids, _ := h.wishlistStore.Get(account)
c.JSON(http.StatusOK, gin.H{"data": gin.H{"items": ids}})
}