package handler import ( "dianshang/internal/model" "dianshang/internal/service" "dianshang/pkg/response" "dianshang/pkg/utils" "strconv" "strings" "github.com/gin-gonic/gin" ) // ProductHandler 浜у搧澶勭悊鍣? type ProductHandler struct { productService *service.ProductService } // NewProductHandler 鍒涘缓浜у搧澶勭悊鍣? func NewProductHandler(productService *service.ProductService) *ProductHandler { return &ProductHandler{ productService: productService, } } // GetProductList 鑾峰彇浜у搧鍒楄〃 func (h *ProductHandler) GetProductList(c *gin.Context) { page := utils.StringToInt(c.DefaultQuery("page", "1")) pageSize := utils.StringToInt(c.DefaultQuery("page_size", "20")) // 支持 category_ids (逗号分隔)或 category_id var categoryID uint if categoryIDsStr := c.Query("category_ids"); categoryIDsStr != "" { // 解析第一个分类ID ids := strings.Split(categoryIDsStr, ",") if len(ids) > 0 { categoryID = utils.StringToUint(strings.TrimSpace(ids[0])) } } else { categoryID = utils.StringToUint(c.Query("category_id")) } keyword := c.Query("keyword") minPrice, _ := strconv.ParseFloat(c.Query("min_price"), 64) maxPrice, _ := strconv.ParseFloat(c.Query("max_price"), 64) // 库存筛选参数 var inStock *bool if inStockStr := c.Query("in_stock"); inStockStr != "" { if inStockStr == "true" { trueVal := true inStock = &trueVal } else if inStockStr == "false" { falseVal := false inStock = &falseVal } } // 处理排序参数:将前端传递的数字参数转换为后端期望的字符串参数 sortParam := c.Query("sort") sortTypeParam := c.Query("sortType") var sort, sortType string // 如果sort=1,表示按价格排序 if sortParam == "1" { sort = "price" // sortType: 0=升序(asc), 1=降序(desc) if sortTypeParam == "0" { sortType = "asc" } else { sortType = "desc" } } else { // 默认排序或其他排序方式 sort = "default" sortType = "desc" } products, pagination, err := h.productService.GetProductList(page, pageSize, categoryID, keyword, minPrice, maxPrice, inStock, sort, sortType) if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Page(c, products, pagination.Total, pagination.Page, pagination.PageSize) } // GetProductDetail 鑾峰彇浜у搧璇︽儏 func (h *ProductHandler) GetProductDetail(c *gin.Context) { idStr := c.Param("id") id := utils.StringToUint(idStr) if id == 0 { response.BadRequest(c, "鏃犳晥鐨勪骇鍝両D") return } product, err := h.productService.GetProductDetail(id) if err != nil { response.ErrorWithMessage(c, response.ERROR_PRODUCT_NOT_FOUND, "产品不存在") return } response.Success(c, product) } // CreateProduct 鍒涘缓浜у搧 func (h *ProductHandler) CreateProduct(c *gin.Context) { var product model.Product if err := c.ShouldBindJSON(&product); err != nil { response.BadRequest(c, "鍙傛暟閿欒: "+err.Error()) return } if err := h.productService.CreateProduct(&product); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, product) } // UpdateProduct 鏇存柊浜у搧 func (h *ProductHandler) UpdateProduct(c *gin.Context) { idStr := c.Param("id") id := utils.StringToUint(idStr) if id == 0 { response.BadRequest(c, "鏃犳晥鐨勪骇鍝両D") return } var updates map[string]interface{} if err := c.ShouldBindJSON(&updates); err != nil { response.BadRequest(c, "鍙傛暟閿欒: "+err.Error()) return } if err := h.productService.UpdateProduct(id, updates); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, nil) } // DeleteProduct 鍒犻櫎浜у搧 func (h *ProductHandler) DeleteProduct(c *gin.Context) { idStr := c.Param("id") id := utils.StringToUint(idStr) if id == 0 { response.BadRequest(c, "鏃犳晥鐨勪骇鍝両D") return } if err := h.productService.DeleteProduct(id); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, nil) } // GetCategories 鑾峰彇鍒嗙被鍒楄〃 func (h *ProductHandler) GetCategories(c *gin.Context) { // 支持平台筛选参数:platform=web 或 platform=miniprogram platform := c.Query("platform") var categories []model.Category var err error if platform != "" { // 根据平台获取分类 categories, err = h.productService.GetCategoriesByPlatform(platform) } else { // 获取所有分类 categories, err = h.productService.GetCategories() } if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, categories) } // CreateCategory 鍒涘缓鍒嗙被 func (h *ProductHandler) CreateCategory(c *gin.Context) { var category model.Category if err := c.ShouldBindJSON(&category); err != nil { response.BadRequest(c, "鍙傛暟閿欒: "+err.Error()) return } if err := h.productService.CreateCategory(&category); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, category) } // UpdateCategory 鏇存柊鍒嗙被 func (h *ProductHandler) UpdateCategory(c *gin.Context) { idStr := c.Param("id") id := utils.StringToUint(idStr) if id == 0 { response.BadRequest(c, "鏃犳晥鐨勫垎绫籌D") return } var updates map[string]interface{} if err := c.ShouldBindJSON(&updates); err != nil { response.BadRequest(c, "鍙傛暟閿欒: "+err.Error()) return } if err := h.productService.UpdateCategory(id, updates); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, nil) } // DeleteCategory 鍒犻櫎鍒嗙被 func (h *ProductHandler) DeleteCategory(c *gin.Context) { idStr := c.Param("id") id := utils.StringToUint(idStr) if id == 0 { response.BadRequest(c, "鏃犳晥鐨勫垎绫籌D") return } if err := h.productService.DeleteCategory(id); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, nil) } // GetProductReviews 鑾峰彇浜у搧璇勪环鍒楄〃 func (h *ProductHandler) GetProductReviews(c *gin.Context) { idStr := c.Param("id") productID := utils.StringToUint(idStr) if productID == 0 { response.BadRequest(c, "鏃犳晥鐨勪骇鍝両D") return } page := utils.StringToInt(c.DefaultQuery("page", "1")) pageSize := utils.StringToInt(c.DefaultQuery("page_size", "20")) reviews, pagination, err := h.productService.GetProductReviews(productID, page, pageSize) if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Page(c, reviews, pagination.Total, pagination.Page, pagination.PageSize) } // CreateReview 鍒涘缓璇勪环 func (h *ProductHandler) CreateReview(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { response.Unauthorized(c) return } var review model.ProductReview if err := c.ShouldBindJSON(&review); err != nil { response.BadRequest(c, "鍙傛暟閿欒: "+err.Error()) return } if err := h.productService.CreateReview(userID.(uint), &review); err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, review) } // SearchProducts 鎼滅储浜у搧 func (h *ProductHandler) SearchProducts(c *gin.Context) { keyword := c.Query("keyword") if keyword == "" { response.BadRequest(c, "璇疯緭鍏ユ悳绱㈠叧閿瘝") return } page := utils.StringToInt(c.DefaultQuery("page", "1")) pageSize := utils.StringToInt(c.DefaultQuery("page_size", "20")) // 价格筛选(后端以“元”存储,参数按“元”传递) minPrice := utils.StringToFloat64(c.Query("min_price")) maxPrice := utils.StringToFloat64(c.Query("max_price")) // 排序参数(搜索页使用 sort_by / sort_order) sort := c.DefaultQuery("sort_by", "default") sortType := c.DefaultQuery("sort_order", "desc") // 兼容其它命名(若存在) if s := c.Query("sort"); s != "" { sort = s } if st := c.Query("sortType"); st != "" { sortType = st } products, pagination, err := h.productService.SearchProducts(keyword, page, pageSize, minPrice, maxPrice, sort, sortType) if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Page(c, products, pagination.Total, pagination.Page, pagination.PageSize) } // GetHotProducts 鑾峰彇鐑棬浜у搧 func (h *ProductHandler) GetHotProducts(c *gin.Context) { limit := utils.StringToInt(c.DefaultQuery("limit", "10")) products, err := h.productService.GetHotProducts(limit) if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, products) } // GetRecommendProducts 获取推荐产品 func (h *ProductHandler) GetRecommendProducts(c *gin.Context) { limit := utils.StringToInt(c.DefaultQuery("limit", "10")) products, err := h.productService.GetRecommendProducts(limit) if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, products) } // GetProductSKUs 获取产品SKU列表 func (h *ProductHandler) GetProductSKUs(c *gin.Context) { idStr := c.Param("id") productID := utils.StringToUint(idStr) if productID == 0 { response.BadRequest(c, "无效的产品ID") return } skus, err := h.productService.GetProductSKUs(productID) if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, skus) } // GetProductTags 获取产品标签列表 func (h *ProductHandler) GetProductTags(c *gin.Context) { tags, err := h.productService.GetProductTags() if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, tags) } // GetStores 获取店铺列表 func (h *ProductHandler) GetStores(c *gin.Context) { stores, err := h.productService.GetStores() if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, stores) } // GetProductReviewCount 获取产品评价统计 func (h *ProductHandler) GetProductReviewCount(c *gin.Context) { idStr := c.Param("id") productID := utils.StringToUint(idStr) if productID == 0 { response.BadRequest(c, "无效的产品ID") return } reviewCount, err := h.productService.GetProductReviewCount(productID) if err != nil { response.ErrorWithMessage(c, response.ERROR, err.Error()) return } response.Success(c, reviewCount) }