Files
2025-11-28 15:18:10 +08:00

404 lines
10 KiB
Go
Raw Permalink 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 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)
}