540 lines
13 KiB
Go
540 lines
13 KiB
Go
package handler
|
|
|
|
import (
|
|
"dianshang/internal/service"
|
|
"dianshang/pkg/response"
|
|
"dianshang/pkg/utils"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// CartHandler 购物车处理器
|
|
type CartHandler struct {
|
|
cartService *service.CartService
|
|
}
|
|
|
|
// NewCartHandler 创建购物车处理器
|
|
func NewCartHandler(cartService *service.CartService) *CartHandler {
|
|
return &CartHandler{
|
|
cartService: cartService,
|
|
}
|
|
}
|
|
|
|
// GetCart 获取购物车
|
|
func (h *CartHandler) GetCart(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
response.Unauthorized(c)
|
|
return
|
|
}
|
|
|
|
cart, err := h.cartService.GetCart(userID.(uint))
|
|
if err != nil {
|
|
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
|
return
|
|
}
|
|
|
|
// 优化: 在一次查询结果基础上计算统计信息,避免重复查询
|
|
var count int
|
|
var total float64
|
|
for _, item := range cart {
|
|
count += item.Quantity
|
|
if item.Product.ID != 0 {
|
|
// 将价格从分转换为元
|
|
total += (float64(item.Product.Price) / 100) * float64(item.Quantity)
|
|
}
|
|
}
|
|
|
|
result := map[string]interface{}{
|
|
"items": cart,
|
|
"count": count,
|
|
"total": fmt.Sprintf("%.2f", total),
|
|
}
|
|
|
|
response.Success(c, result)
|
|
}
|
|
|
|
// AddToCart 添加到购物车
|
|
func (h *CartHandler) AddToCart(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
response.Unauthorized(c)
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
ProductID uint `json:"product_id" binding:"required"`
|
|
SKUID uint `json:"sku_id"`
|
|
Quantity uint `json:"quantity" binding:"required,min=1"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "参数错误: "+err.Error())
|
|
return
|
|
}
|
|
|
|
if err := h.cartService.AddToCart(userID.(uint), req.ProductID, req.SKUID, int(req.Quantity)); err != nil {
|
|
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
|
return
|
|
}
|
|
|
|
response.Success(c, nil)
|
|
}
|
|
|
|
// UpdateCartItem 更新购物车项
|
|
func (h *CartHandler) UpdateCartItem(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
response.Unauthorized(c)
|
|
return
|
|
}
|
|
|
|
productIDStr := c.Param("product_id")
|
|
productID := utils.StringToUint(productIDStr)
|
|
if productID == 0 {
|
|
response.BadRequest(c, "无效的产品ID")
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
Quantity uint `json:"quantity" binding:"required"`
|
|
SKUID uint `json:"sku_id"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "参数错误: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// 添加调试日志
|
|
fmt.Printf("🔍 [UpdateCartItem] 用户ID: %d, 产品ID: %d, SKU ID: %d, 数量: %d\n",
|
|
userID.(uint), productID, req.SKUID, req.Quantity)
|
|
|
|
if err := h.cartService.UpdateCartItemBySKU(userID.(uint), productID, req.SKUID, int(req.Quantity)); err != nil {
|
|
fmt.Printf("❌ [UpdateCartItem] 服务层错误: %v\n", err)
|
|
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
|
return
|
|
}
|
|
|
|
response.Success(c, nil)
|
|
}
|
|
|
|
// RemoveFromCart 从购物车移除
|
|
func (h *CartHandler) RemoveFromCart(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
response.Unauthorized(c)
|
|
return
|
|
}
|
|
|
|
productIDStr := c.Param("product_id")
|
|
productID := utils.StringToUint(productIDStr)
|
|
if productID == 0 {
|
|
response.BadRequest(c, "无效的产品ID")
|
|
return
|
|
}
|
|
|
|
// 从查询参数获取sku_id
|
|
skuIDStr := c.Query("sku_id")
|
|
skuID := utils.StringToUint(skuIDStr)
|
|
|
|
if err := h.cartService.RemoveFromCartBySKU(userID.(uint), productID, skuID); err != nil {
|
|
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
|
return
|
|
}
|
|
|
|
response.Success(c, nil)
|
|
}
|
|
|
|
// ClearCart 清空购物车
|
|
func (h *CartHandler) ClearCart(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
response.Unauthorized(c)
|
|
return
|
|
}
|
|
|
|
if err := h.cartService.ClearCart(userID.(uint)); err != nil {
|
|
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
|
return
|
|
}
|
|
|
|
response.Success(c, nil)
|
|
}
|
|
|
|
// GetCartCount 获取购物车商品数量
|
|
func (h *CartHandler) GetCartCount(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
response.Unauthorized(c)
|
|
return
|
|
}
|
|
|
|
count, err := h.cartService.GetCartCount(userID.(uint))
|
|
if err != nil {
|
|
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
|
return
|
|
}
|
|
|
|
response.Success(c, map[string]interface{}{"count": count})
|
|
}
|
|
|
|
// SelectCartItem 选择/取消选择购物车项
|
|
func (h *CartHandler) SelectCartItem(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
response.Unauthorized(c)
|
|
return
|
|
}
|
|
|
|
cartIDStr := c.Param("id")
|
|
cartID := utils.StringToUint(cartIDStr)
|
|
if cartID == 0 {
|
|
response.BadRequest(c, "无效的购物车ID")
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
Selected bool `json:"selected"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "参数错误: "+err.Error())
|
|
return
|
|
}
|
|
|
|
if err := h.cartService.SelectCartItem(userID.(uint), cartID, req.Selected); err != nil {
|
|
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
|
return
|
|
}
|
|
|
|
response.Success(c, nil)
|
|
}
|
|
|
|
// SelectAllCartItems 全选/取消全选购物车
|
|
func (h *CartHandler) SelectAllCartItems(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
response.Unauthorized(c)
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
Selected bool `json:"selected"`
|
|
}
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "参数错误: "+err.Error())
|
|
return
|
|
}
|
|
|
|
if err := h.cartService.SelectAllCartItems(userID.(uint), req.Selected); err != nil {
|
|
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
|
return
|
|
}
|
|
|
|
response.Success(c, nil)
|
|
}
|
|
|
|
// BatchAddToCartRequest 批量添加到购物车请求
|
|
type BatchAddToCartRequest struct {
|
|
Items []struct {
|
|
ProductID uint `json:"product_id" binding:"required"`
|
|
SKUID uint `json:"sku_id"`
|
|
Quantity int `json:"quantity" binding:"required,min=1"`
|
|
} `json:"items" binding:"required"`
|
|
}
|
|
|
|
// BatchAddToCart 批量添加到购物车
|
|
func (h *CartHandler) BatchAddToCart(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
|
|
return
|
|
}
|
|
|
|
var req BatchAddToCartRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// 转换请求参数类型
|
|
items := make([]struct {
|
|
ProductID uint `json:"product_id"`
|
|
SKUID uint `json:"sku_id"`
|
|
Quantity int `json:"quantity"`
|
|
}, len(req.Items))
|
|
|
|
for i, item := range req.Items {
|
|
items[i] = struct {
|
|
ProductID uint `json:"product_id"`
|
|
SKUID uint `json:"sku_id"`
|
|
Quantity int `json:"quantity"`
|
|
}{
|
|
ProductID: item.ProductID,
|
|
SKUID: item.SKUID,
|
|
Quantity: item.Quantity,
|
|
}
|
|
}
|
|
|
|
err := h.cartService.BatchAddToCart(userID.(uint), items)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "批量添加成功"})
|
|
}
|
|
|
|
// BatchRemoveFromCartRequest 批量移除购物车请求
|
|
type BatchRemoveFromCartRequest struct {
|
|
CartIDs []uint `json:"cart_ids" binding:"required"`
|
|
}
|
|
|
|
// BatchRemoveFromCart 批量从购物车移除
|
|
func (h *CartHandler) BatchRemoveFromCart(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
|
|
return
|
|
}
|
|
|
|
var req BatchRemoveFromCartRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
err := h.cartService.BatchRemoveFromCart(userID.(uint), req.CartIDs)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "批量删除成功"})
|
|
}
|
|
|
|
// BatchUpdateCartItemsRequest 批量更新购物车项请求
|
|
type BatchUpdateCartItemsRequest struct {
|
|
Updates []struct {
|
|
CartID uint `json:"cart_id" binding:"required"`
|
|
Quantity int `json:"quantity" binding:"min=0"`
|
|
} `json:"updates" binding:"required"`
|
|
}
|
|
|
|
// BatchUpdateCartItems 批量更新购物车项
|
|
func (h *CartHandler) BatchUpdateCartItems(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
|
|
return
|
|
}
|
|
|
|
var req BatchUpdateCartItemsRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// 转换请求参数类型
|
|
updates := make([]struct {
|
|
CartID uint `json:"cart_id"`
|
|
Quantity int `json:"quantity"`
|
|
}, len(req.Updates))
|
|
|
|
for i, update := range req.Updates {
|
|
updates[i] = struct {
|
|
CartID uint `json:"cart_id"`
|
|
Quantity int `json:"quantity"`
|
|
}{
|
|
CartID: update.CartID,
|
|
Quantity: update.Quantity,
|
|
}
|
|
}
|
|
|
|
err := h.cartService.BatchUpdateCartItems(userID.(uint), updates)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "批量更新成功"})
|
|
}
|
|
|
|
// GetCartWithDetails 获取购物车详细信息
|
|
func (h *CartHandler) GetCartWithDetails(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
|
|
return
|
|
}
|
|
|
|
details, err := h.cartService.GetCartWithDetails(userID.(uint))
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 200,
|
|
"data": details,
|
|
})
|
|
}
|
|
|
|
// ValidateCartItems 验证购物车商品有效性
|
|
func (h *CartHandler) ValidateCartItems(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
|
|
return
|
|
}
|
|
|
|
validation, err := h.cartService.ValidateCartItems(userID.(uint))
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 200,
|
|
"data": validation,
|
|
})
|
|
}
|
|
|
|
// CleanInvalidCartItems 清理无效的购物车项
|
|
func (h *CartHandler) CleanInvalidCartItems(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
|
|
return
|
|
}
|
|
|
|
err := h.cartService.CleanInvalidCartItems(userID.(uint))
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "清理完成"})
|
|
}
|
|
|
|
// GetCartSummary 获取购物车摘要信息
|
|
func (h *CartHandler) GetCartSummary(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
|
|
return
|
|
}
|
|
|
|
summary, err := h.cartService.GetCartSummary(userID.(uint))
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 200,
|
|
"data": summary,
|
|
})
|
|
}
|
|
|
|
// MergeCartRequest 合并购物车请求
|
|
type MergeCartRequest struct {
|
|
GuestCartItems []struct {
|
|
ProductID uint `json:"product_id" binding:"required"`
|
|
SKUID uint `json:"sku_id"`
|
|
Quantity int `json:"quantity" binding:"required,min=1"`
|
|
} `json:"guest_cart_items" binding:"required"`
|
|
}
|
|
|
|
// MergeCart 合并购物车
|
|
func (h *CartHandler) MergeCart(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
|
|
return
|
|
}
|
|
|
|
var req MergeCartRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// 转换请求参数类型
|
|
guestCartItems := make([]struct {
|
|
ProductID uint `json:"product_id"`
|
|
SKUID uint `json:"sku_id"`
|
|
Quantity int `json:"quantity"`
|
|
}, len(req.GuestCartItems))
|
|
|
|
for i, item := range req.GuestCartItems {
|
|
guestCartItems[i] = struct {
|
|
ProductID uint `json:"product_id"`
|
|
SKUID uint `json:"sku_id"`
|
|
Quantity int `json:"quantity"`
|
|
}{
|
|
ProductID: item.ProductID,
|
|
SKUID: item.SKUID,
|
|
Quantity: item.Quantity,
|
|
}
|
|
}
|
|
|
|
err := h.cartService.MergeCart(userID.(uint), guestCartItems)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "购物车合并成功"})
|
|
}
|
|
|
|
// GetSelectedCartItems 获取选中的购物车项
|
|
func (h *CartHandler) GetSelectedCartItems(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
|
|
return
|
|
}
|
|
|
|
items, err := h.cartService.GetSelectedCartItems(userID.(uint))
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 200,
|
|
"data": items,
|
|
})
|
|
}
|
|
|
|
// CalculateCartDiscountRequest 计算购物车优惠请求
|
|
type CalculateCartDiscountRequest struct {
|
|
CouponID uint `json:"coupon_id"`
|
|
}
|
|
|
|
// CalculateCartDiscount 计算购物车优惠
|
|
func (h *CartHandler) CalculateCartDiscount(c *gin.Context) {
|
|
userID, exists := c.Get("user_id")
|
|
if !exists {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
|
|
return
|
|
}
|
|
|
|
var req CalculateCartDiscountRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
discount, err := h.cartService.CalculateCartDiscount(userID.(uint), req.CouponID)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 200,
|
|
"data": discount,
|
|
})
|
|
} |