Files
ai_dianshang/server/internal/handler/admin_product.go
2025-11-17 14:11:46 +08:00

1059 lines
27 KiB
Go
Raw 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"
"fmt"
"strconv"
"strings"
"github.com/gin-gonic/gin"
)
// AdminProductHandler 管理后台商品处理器
type AdminProductHandler struct {
productService *service.ProductService
}
// NewAdminProductHandler 创建管理后台商品处理器
func NewAdminProductHandler(productService *service.ProductService) *AdminProductHandler {
return &AdminProductHandler{
productService: productService,
}
}
// GetProductList 获取商品列表
func (h *AdminProductHandler) GetProductList(c *gin.Context) {
page := utils.StringToInt(c.DefaultQuery("page", "1"))
pageSize := utils.StringToInt(c.DefaultQuery("page_size", "10"))
categoryID := utils.StringToUint(c.Query("category_id"))
keyword := c.Query("keyword")
status := c.DefaultQuery("status", "all") // 管理系统默认获取所有状态的商品
if page <= 0 {
page = 1
}
if pageSize <= 0 || pageSize > 100 {
pageSize = 10
}
// 构建查询条件
minPrice := utils.StringToFloat64(c.Query("min_price"))
maxPrice := utils.StringToFloat64(c.Query("max_price"))
sort := c.DefaultQuery("sort", "created_at")
sortType := c.DefaultQuery("sort_type", "desc")
// 获取热门、新品、推荐筛选条件
isHot := c.Query("is_hot")
isNew := c.Query("is_new")
isRecommend := c.Query("is_recommend")
products, pagination, err := h.productService.GetProductListForAdmin(page, pageSize, categoryID, keyword, minPrice, maxPrice, sort, sortType, status, isHot, isNew, isRecommend)
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.PageQuery(c, products, pagination.Total, pagination.Page, pagination.PageSize)
}
// GetProductDetail 获取商品详情
func (h *AdminProductHandler) GetProductDetail(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的商品ID")
return
}
product, err := h.productService.GetProductDetail(uint(id))
if err != nil {
response.ErrorWithMessage(c, response.ERROR, "商品不存在")
return
}
response.Success(c, product)
}
// CreateProduct 创建商品
func (h *AdminProductHandler) CreateProduct(c *gin.Context) {
var product model.Product
if err := c.ShouldBindJSON(&product); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
// 商品创建时间会自动设置
if err := h.productService.CreateProduct(&product); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, product)
}
// UpdateProduct 更新商品
func (h *AdminProductHandler) UpdateProduct(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的商品ID")
return
}
var updates map[string]interface{}
if err := c.ShouldBindJSON(&updates); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
// 商品更新时间会自动设置
if err := h.productService.UpdateProduct(uint(id), updates); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// DeleteProduct 删除商品
func (h *AdminProductHandler) DeleteProduct(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的商品ID")
return
}
if err := h.productService.DeleteProduct(uint(id)); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// UpdateStock 更新商品库存
func (h *AdminProductHandler) UpdateStock(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的商品ID")
return
}
var req struct {
Quantity int `json:"quantity" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
if err := h.productService.UpdateStock(uint(id), req.Quantity); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// BatchUpdateStatus 批量更新商品状态
func (h *AdminProductHandler) BatchUpdateStatus(c *gin.Context) {
var req struct {
ProductIDs []uint `json:"product_ids" binding:"required"`
Status uint8 `json:"status" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
// 批量更新状态
for _, productID := range req.ProductIDs {
updates := map[string]interface{}{
"status": req.Status,
}
if adminID, exists := c.Get("user_id"); exists {
updates["updated_by"] = adminID.(uint)
}
if err := h.productService.UpdateProduct(productID, updates); err != nil {
response.ErrorWithMessage(c, response.ERROR, "更新商品状态失败")
return
}
}
response.Success(c, nil)
}
// GetCategories 获取分类列表
func (h *AdminProductHandler) GetCategories(c *gin.Context) {
categories, err := h.productService.GetCategories()
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.SuccessWithMessage(c, "", categories)
}
// CreateCategory 创建分类
func (h *AdminProductHandler) CreateCategory(c *gin.Context) {
var category model.Category
if err := c.ShouldBindJSON(&category); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
if err := h.productService.CreateCategory(&category); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, category)
}
// UpdateCategory 更新分类
func (h *AdminProductHandler) UpdateCategory(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的分类ID")
return
}
var updates map[string]interface{}
if err := c.ShouldBindJSON(&updates); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
if err := h.productService.UpdateCategory(uint(id), updates); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// DeleteCategory 删除分类
func (h *AdminProductHandler) DeleteCategory(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的分类ID")
return
}
if err := h.productService.DeleteCategory(uint(id)); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// GetProductSKUs 获取商品SKU列表
func (h *AdminProductHandler) GetProductSKUs(c *gin.Context) {
idStr := c.Param("id")
productID, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的商品ID")
return
}
skus, err := h.productService.GetProductSKUs(uint(productID))
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, skus)
}
// GetProductReviews 获取商品评价列表
func (h *AdminProductHandler) GetProductReviews(c *gin.Context) {
idStr := c.Param("id")
productID, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的商品ID")
return
}
page := utils.StringToInt(c.DefaultQuery("page", "1"))
pageSize := utils.StringToInt(c.DefaultQuery("page_size", "10"))
if page <= 0 {
page = 1
}
if pageSize <= 0 || pageSize > 100 {
pageSize = 10
}
reviews, pagination, err := h.productService.GetProductReviews(uint(productID), page, pageSize)
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, gin.H{
"list": reviews,
"pagination": pagination,
})
}
// GetStores 获取店铺列表
func (h *AdminProductHandler) GetStores(c *gin.Context) {
stores, err := h.productService.GetStores()
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, stores)
}
// BatchUpdateProductStatus 批量更新商品状态
func (h *AdminProductHandler) BatchUpdateProductStatus(c *gin.Context) {
var req struct {
IDs []uint `json:"ids" binding:"required"`
Status int `json:"status" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if err := h.productService.BatchUpdateProductStatus(req.IDs, req.Status); err != nil {
c.JSON(500, gin.H{"error": "批量更新商品状态失败"})
return
}
c.JSON(200, gin.H{"message": "批量更新商品状态成功"})
}
// BatchUpdateProductPrice 批量更新商品价格
func (h *AdminProductHandler) BatchUpdateProductPrice(c *gin.Context) {
var req struct {
Updates []map[string]interface{} `json:"updates" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if err := h.productService.BatchUpdateProductPrice(req.Updates); err != nil {
c.JSON(500, gin.H{"error": "批量更新商品价格失败"})
return
}
c.JSON(200, gin.H{"message": "批量更新商品价格成功"})
}
// BatchDeleteProducts 批量删除商品
func (h *AdminProductHandler) BatchDeleteProducts(c *gin.Context) {
var req struct {
IDs []uint `json:"ids" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
if err := h.productService.BatchDeleteProducts(req.IDs); err != nil {
response.ErrorWithMessage(c, response.ERROR, "批量删除商品失败")
return
}
response.SuccessWithMessage(c, "批量删除商品成功", nil)
}
// CreateProductSKU 创建商品SKU
func (h *AdminProductHandler) CreateProductSKU(c *gin.Context) {
var req struct {
ProductID uint `json:"product_id" binding:"required"`
SpecValues string `json:"spec_values" binding:"required"`
Price float64 `json:"price" binding:"required"`
OriginalPrice float64 `json:"original_price"` // 划线价
Stock int `json:"stock" binding:"required"`
SKUCode string `json:"sku_code" binding:"required"`
Image string `json:"image"`
Weight float64 `json:"weight"`
Volume float64 `json:"volume"`
Sort int `json:"sort"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
// 将SpecValues字符串转换为JSONMap
specValuesMap := make(model.JSONMap)
if req.SpecValues != "" {
// 这里简化处理实际应该解析JSON字符串
specValuesMap["spec"] = req.SpecValues
}
sku := &model.ProductSKU{
ProductID: req.ProductID,
SpecValues: specValuesMap,
Price: req.Price,
OriginalPrice: req.OriginalPrice,
Stock: req.Stock,
SKUCode: req.SKUCode,
Image: req.Image,
Weight: req.Weight,
}
err := h.productService.CreateProductSKU(sku)
if err != nil {
c.JSON(500, gin.H{"error": "创建商品SKU失败"})
return
}
c.JSON(200, gin.H{
"message": "创建商品SKU成功",
"data": sku,
})
}
// UpdateProductSKU 更新商品SKU
func (h *AdminProductHandler) UpdateProductSKU(c *gin.Context) {
id := c.Param("id")
skuID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的SKU ID"})
return
}
var req struct {
SpecValues *string `json:"spec_values"`
Price *float64 `json:"price"`
OriginalPrice *float64 `json:"original_price"` // 划线价
Stock *int `json:"stock"`
SKUCode *string `json:"sku_code"`
Image *string `json:"image"`
Weight *float64 `json:"weight"`
Volume *float64 `json:"volume"`
Sort *int `json:"sort"`
Status *int `json:"status"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
updates := make(map[string]interface{})
if req.SpecValues != nil {
updates["spec_values"] = *req.SpecValues
}
if req.Price != nil {
updates["price"] = *req.Price
}
if req.OriginalPrice != nil {
updates["original_price"] = *req.OriginalPrice
}
if req.Stock != nil {
updates["stock"] = *req.Stock
}
if req.SKUCode != nil {
updates["sku_code"] = *req.SKUCode
}
if req.Image != nil {
updates["image"] = *req.Image
}
if req.Weight != nil {
updates["weight"] = *req.Weight
}
if req.Status != nil {
updates["status"] = *req.Status
}
if err := h.productService.UpdateProductSKU(uint(skuID), updates); err != nil {
c.JSON(500, gin.H{"error": "更新商品SKU失败"})
return
}
c.JSON(200, gin.H{"message": "更新商品SKU成功"})
}
// DeleteProductSKU 删除商品SKU
func (h *AdminProductHandler) DeleteProductSKU(c *gin.Context) {
id := c.Param("id")
skuID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的SKU ID"})
return
}
if err := h.productService.DeleteProductSKU(uint(skuID)); err != nil {
c.JSON(500, gin.H{"error": "删除商品SKU失败"})
return
}
c.JSON(200, gin.H{"message": "删除商品SKU成功"})
}
// GetProductImages 获取商品图片列表
func (h *AdminProductHandler) GetProductImages(c *gin.Context) {
id := c.Param("id")
productID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的商品ID"})
return
}
images, err := h.productService.GetProductImages(uint(productID))
if err != nil {
c.JSON(500, gin.H{"error": "获取商品图片失败"})
return
}
c.JSON(200, gin.H{
"message": "获取商品图片成功",
"data": images,
})
}
// CreateProductImage 创建商品图片
func (h *AdminProductHandler) CreateProductImage(c *gin.Context) {
var req struct {
ProductID uint `json:"product_id" binding:"required"`
ImageURL string `json:"image_url" binding:"required"`
Sort int `json:"sort"`
Type int `json:"type"` // 0:普通图片 1:主图
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
productImage := &model.ProductImage{
ProductID: req.ProductID,
ImageURL: req.ImageURL,
Sort: req.Sort,
}
err := h.productService.CreateProductImage(productImage)
if err != nil {
c.JSON(500, gin.H{"error": "创建商品图片失败"})
return
}
c.JSON(200, gin.H{
"message": "创建商品图片成功",
"data": productImage,
})
}
// UpdateProductImageSort 更新商品图片排序
func (h *AdminProductHandler) UpdateProductImageSort(c *gin.Context) {
id := c.Param("id")
imageID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的图片ID"})
return
}
var req struct {
Sort int `json:"sort" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if err := h.productService.UpdateProductImageSort(uint(imageID), req.Sort); err != nil {
c.JSON(500, gin.H{"error": "更新图片排序失败"})
return
}
c.JSON(200, gin.H{"message": "更新图片排序成功"})
}
// DeleteProductImage 删除商品图片
func (h *AdminProductHandler) DeleteProductImage(c *gin.Context) {
id := c.Param("id")
imageID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的图片ID"})
return
}
if err := h.productService.DeleteProductImage(uint(imageID)); err != nil {
c.JSON(500, gin.H{"error": "删除商品图片失败"})
return
}
c.JSON(200, gin.H{"message": "删除商品图片成功"})
}
// CreateProductSpec 创建商品规格
func (h *AdminProductHandler) CreateProductSpec(c *gin.Context) {
var req struct {
ProductID uint `json:"product_id" binding:"required"`
Name string `json:"name" binding:"required"`
Values string `json:"values" binding:"required"`
Sort int `json:"sort"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
productSpec := &model.ProductSpec{
ProductID: req.ProductID,
Name: req.Name,
Value: req.Values,
Sort: req.Sort,
}
err := h.productService.CreateProductSpec(productSpec)
if err != nil {
c.JSON(500, gin.H{"error": "创建商品规格失败"})
return
}
c.JSON(200, gin.H{
"message": "创建商品规格成功",
"data": productSpec,
})
}
// UpdateProductSpec 更新商品规格
func (h *AdminProductHandler) UpdateProductSpec(c *gin.Context) {
id := c.Param("id")
specID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的规格ID"})
return
}
var req struct {
Name *string `json:"name"`
Values *string `json:"values"`
Sort *int `json:"sort"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
updates := make(map[string]interface{})
if req.Name != nil {
updates["name"] = *req.Name
}
if req.Values != nil {
updates["value"] = *req.Values
}
if req.Sort != nil {
updates["sort"] = *req.Sort
}
if err := h.productService.UpdateProductSpec(uint(specID), updates); err != nil {
c.JSON(500, gin.H{"error": "更新商品规格失败"})
return
}
c.JSON(200, gin.H{"message": "更新商品规格成功"})
}
// DeleteProductSpec 删除商品规格
func (h *AdminProductHandler) DeleteProductSpec(c *gin.Context) {
id := c.Param("id")
specID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的规格ID"})
return
}
if err := h.productService.DeleteProductSpec(uint(specID)); err != nil {
c.JSON(500, gin.H{"error": "删除商品规格失败"})
return
}
c.JSON(200, gin.H{"message": "删除商品规格成功"})
}
// GetProductSpecs 获取商品规格列表
func (h *AdminProductHandler) GetProductSpecs(c *gin.Context) {
id := c.Param("id")
productID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的商品ID"})
return
}
specs, err := h.productService.GetProductSpecs(uint(productID))
if err != nil {
c.JSON(500, gin.H{"error": "获取商品规格失败"})
return
}
c.JSON(200, gin.H{
"message": "获取商品规格成功",
"data": specs,
})
}
// CreateProductTag 创建商品标签
func (h *AdminProductHandler) CreateProductTag(c *gin.Context) {
var req struct {
Name string `json:"name" binding:"required"`
Color string `json:"color"`
Sort int `json:"sort"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
productTag := &model.ProductTag{
Name: req.Name,
Color: req.Color,
Sort: req.Sort,
}
err := h.productService.CreateProductTag(productTag)
if err != nil {
c.JSON(500, gin.H{"error": "创建商品标签失败"})
return
}
c.JSON(200, gin.H{
"message": "创建商品标签成功",
"data": productTag,
})
}
// UpdateProductTag 更新商品标签
func (h *AdminProductHandler) UpdateProductTag(c *gin.Context) {
id := c.Param("id")
tagID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的标签ID"})
return
}
var req struct {
Name *string `json:"name"`
Color *string `json:"color"`
Sort *int `json:"sort"`
Status *int `json:"status"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
updates := make(map[string]interface{})
if req.Name != nil {
updates["name"] = *req.Name
}
if req.Color != nil {
updates["color"] = *req.Color
}
if req.Sort != nil {
updates["sort"] = *req.Sort
}
if req.Status != nil {
updates["status"] = *req.Status
}
if err := h.productService.UpdateProductTag(uint(tagID), updates); err != nil {
c.JSON(500, gin.H{"error": "更新商品标签失败"})
return
}
c.JSON(200, gin.H{"message": "更新商品标签成功"})
}
// DeleteProductTag 删除商品标签
func (h *AdminProductHandler) DeleteProductTag(c *gin.Context) {
id := c.Param("id")
tagID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的标签ID"})
return
}
if err := h.productService.DeleteProductTag(uint(tagID)); err != nil {
c.JSON(500, gin.H{"error": "删除商品标签失败"})
return
}
c.JSON(200, gin.H{"message": "删除商品标签成功"})
}
// AssignTagsToProduct 为商品分配标签
func (h *AdminProductHandler) AssignTagsToProduct(c *gin.Context) {
id := c.Param("id")
productID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的商品ID"})
return
}
var req struct {
TagIDs []uint `json:"tag_ids" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if err := h.productService.AssignTagsToProduct(uint(productID), req.TagIDs); err != nil {
c.JSON(500, gin.H{"error": "分配商品标签失败"})
return
}
c.JSON(200, gin.H{"message": "分配商品标签成功"})
}
// GetLowStockProducts 获取低库存商品
func (h *AdminProductHandler) GetLowStockProducts(c *gin.Context) {
threshold := 10 // 默认阈值
if t := c.Query("threshold"); t != "" {
if th, err := strconv.Atoi(t); err == nil {
threshold = th
}
}
products, err := h.productService.GetLowStockProducts(threshold)
if err != nil {
c.JSON(500, gin.H{"error": "获取低库存商品失败"})
return
}
c.JSON(200, gin.H{
"message": "获取低库存商品成功",
"data": products,
})
}
// GetInventoryStatistics 获取库存统计
func (h *AdminProductHandler) GetInventoryStatistics(c *gin.Context) {
stats, err := h.productService.GetInventoryStatistics()
if err != nil {
c.JSON(500, gin.H{"error": "获取库存统计失败"})
return
}
c.JSON(200, gin.H{
"message": "获取库存统计成功",
"data": stats,
})
}
// ExportProducts 导出商品数据
func (h *AdminProductHandler) ExportProducts(c *gin.Context) {
// 获取查询条件
conditions := make(map[string]interface{})
if categoryID := c.Query("category_id"); categoryID != "" {
if id, err := strconv.ParseUint(categoryID, 10, 32); err == nil {
conditions["category_id"] = uint(id)
}
}
if status := c.Query("status"); status != "" {
if s, err := strconv.Atoi(status); err == nil {
conditions["status"] = s
}
}
if keyword := c.Query("keyword"); keyword != "" {
conditions["keyword"] = keyword
}
// 导出商品数据
products, err := h.productService.ExportProducts(conditions)
if err != nil {
c.JSON(500, gin.H{"error": "导出商品数据失败"})
return
}
// TODO: 这里需要实现将products转换为Excel文件并保存的逻辑
// 暂时直接返回产品数据
c.JSON(200, gin.H{
"message": "导出商品数据成功",
"data": products,
})
}
// ImportProducts 导入商品数据
func (h *AdminProductHandler) ImportProducts(c *gin.Context) {
file, header, err := c.Request.FormFile("file")
if err != nil {
c.JSON(400, gin.H{"error": "获取上传文件失败"})
return
}
defer file.Close()
// 检查文件类型
if !strings.HasSuffix(header.Filename, ".xlsx") && !strings.HasSuffix(header.Filename, ".xls") {
c.JSON(400, gin.H{"error": "文件格式不支持请上传Excel文件"})
return
}
// TODO: 这里需要实现Excel文件解析逻辑将文件内容解析为[]model.Product
// 暂时返回错误,提示功能未实现
c.JSON(500, gin.H{"error": "导入功能暂未实现需要添加Excel文件解析逻辑"})
}
// SyncProductStock 同步单个商品库存
func (h *AdminProductHandler) SyncProductStock(c *gin.Context) {
id := c.Param("id")
productID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(400, gin.H{"error": "无效的商品ID"})
return
}
if err := h.productService.SyncProductStock(uint(productID)); err != nil {
c.JSON(500, gin.H{"error": "同步商品库存失败: " + err.Error()})
return
}
c.JSON(200, gin.H{"message": "同步商品库存成功"})
}
// SyncAllProductsStock 同步所有商品库存
func (h *AdminProductHandler) SyncAllProductsStock(c *gin.Context) {
if err := h.productService.SyncAllProductsStock(); err != nil {
c.JSON(500, gin.H{"error": "同步所有商品库存失败: " + err.Error()})
return
}
c.JSON(200, gin.H{"message": "同步所有商品库存成功"})
}
// BatchUpdateOrigPrice 批量更新SPU划线价
func (h *AdminProductHandler) BatchUpdateOrigPrice(c *gin.Context) {
var req struct {
Products []struct {
ID uint `json:"id" binding:"required"`
OrigPrice float64 `json:"orig_price" binding:"required"`
} `json:"products" binding:"required,min=1"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误: "+err.Error())
return
}
// 批量更新
successCount := 0
failedCount := 0
var errors []string
for _, item := range req.Products {
updates := map[string]interface{}{
"orig_price": item.OrigPrice,
}
if err := h.productService.UpdateProduct(item.ID, updates); err != nil {
failedCount++
errors = append(errors, fmt.Sprintf("商品ID %d 更新失败: %v", item.ID, err))
} else {
successCount++
}
}
response.Success(c, gin.H{
"message": fmt.Sprintf("批量更新完成,成功 %d 个,失败 %d 个", successCount, failedCount),
"success_count": successCount,
"failed_count": failedCount,
"errors": errors,
})
}
// BatchUpdateSKUOrigPrice 批量更新SKU划线价
func (h *AdminProductHandler) BatchUpdateSKUOrigPrice(c *gin.Context) {
var req struct {
SKUs []struct {
ID uint `json:"id" binding:"required"`
OriginalPrice float64 `json:"original_price" binding:"required"`
} `json:"skus" binding:"required,min=1"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误: "+err.Error())
return
}
// 批量更新
successCount := 0
failedCount := 0
var errors []string
for _, item := range req.SKUs {
updates := map[string]interface{}{
"original_price": item.OriginalPrice,
}
if err := h.productService.UpdateProductSKU(item.ID, updates); err != nil {
failedCount++
errors = append(errors, fmt.Sprintf("SKU ID %d 更新失败: %v", item.ID, err))
} else {
successCount++
}
}
response.Success(c, gin.H{
"message": fmt.Sprintf("批量更新完成,成功 %d 个,失败 %d 个", successCount, failedCount),
"success_count": successCount,
"failed_count": failedCount,
"errors": errors,
})
}
// UpdateProductOrigPrice 更新单个商品SPU划线价
func (h *AdminProductHandler) UpdateProductOrigPrice(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的商品ID")
return
}
var req struct {
OrigPrice float64 `json:"orig_price" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
updates := map[string]interface{}{
"orig_price": req.OrigPrice,
}
if err := h.productService.UpdateProduct(uint(id), updates); err != nil {
response.ErrorWithMessage(c, response.ERROR, "更新划线价失败: "+err.Error())
return
}
response.SuccessWithMessage(c, "更新划线价成功", nil)
}