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