366 lines
9.5 KiB
Go
366 lines
9.5 KiB
Go
|
|
package handler
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"dianshang/internal/model"
|
|||
|
|
"dianshang/internal/service"
|
|||
|
|
"dianshang/pkg/response"
|
|||
|
|
"dianshang/pkg/utils"
|
|||
|
|
"strconv"
|
|||
|
|
|
|||
|
|
"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"))
|
|||
|
|
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)
|
|||
|
|
|
|||
|
|
// 处理排序参数:将前端传递的数字参数转换为后端期望的字符串参数
|
|||
|
|
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, 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) {
|
|||
|
|
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)
|
|||
|
|
}
|