806 lines
25 KiB
Go
806 lines
25 KiB
Go
package handler
|
||
|
||
import (
|
||
"dianshang/internal/model"
|
||
"dianshang/internal/service"
|
||
"dianshang/pkg/response"
|
||
"dianshang/pkg/utils"
|
||
"fmt"
|
||
"log"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
// OrderHandler 订单处理器
|
||
type OrderHandler struct {
|
||
orderService *service.OrderService
|
||
wechatPayService *service.WeChatPayService
|
||
}
|
||
|
||
// NewOrderHandler 创建订单处理器
|
||
func NewOrderHandler(orderService *service.OrderService, wechatPayService *service.WeChatPayService) *OrderHandler {
|
||
return &OrderHandler{
|
||
orderService: orderService,
|
||
wechatPayService: wechatPayService,
|
||
}
|
||
}
|
||
|
||
// CreateOrder 创建订单
|
||
func (h *OrderHandler) CreateOrder(c *gin.Context) {
|
||
userID, exists := c.Get("user_id")
|
||
if !exists {
|
||
response.Unauthorized(c)
|
||
return
|
||
}
|
||
|
||
var req service.CreateOrderRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
fmt.Printf("DEBUG: 订单创建请求绑定失败: %v\n", err)
|
||
fmt.Printf("DEBUG: 请求体内容: %s\n", c.Request.Body)
|
||
response.BadRequest(c, "鍙傛暟閿欒: "+err.Error())
|
||
return
|
||
}
|
||
|
||
fmt.Printf("DEBUG: 成功绑定的订单请求: AddressID=%d, Items=%+v, Remark=%s\n", req.AddressID, req.Items, req.Remark)
|
||
|
||
order, err := h.orderService.CreateOrder(userID.(uint), &req)
|
||
if err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, order)
|
||
}
|
||
|
||
// GetUserOrders 获取用户订单列表
|
||
func (h *OrderHandler) GetUserOrders(c *gin.Context) {
|
||
userID, exists := c.Get("user_id")
|
||
if !exists {
|
||
response.Unauthorized(c)
|
||
return
|
||
}
|
||
|
||
page := utils.StringToInt(c.DefaultQuery("page", "1"))
|
||
pageSize := utils.StringToInt(c.DefaultQuery("page_size", "20"))
|
||
statusStr := c.Query("status")
|
||
status := 0
|
||
if statusStr != "" {
|
||
frontendStatus := utils.StringToInt(statusStr)
|
||
// 前端和数据库状态保持一致:
|
||
// 1=未付款, 2=已付款/待发货, 3=待发货, 4=已发货, 5=待收货, 6=已完成, 7=已取消, 8=退货中, 9=已退款
|
||
status = frontendStatus
|
||
}
|
||
|
||
orders, pagination, err := h.orderService.GetUserOrders(userID.(uint), status, page, pageSize)
|
||
if err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
// 格式化订单列表数据
|
||
formattedOrders := h.formatOrderList(orders)
|
||
|
||
response.Page(c, formattedOrders, pagination.Total, pagination.Page, pagination.PageSize)
|
||
}
|
||
|
||
// OrderListResponse 订单列表响应结构
|
||
type OrderListResponse struct {
|
||
ID string `json:"id"`
|
||
OrderNo string `json:"order_no"`
|
||
StoreID uint `json:"store_id"`
|
||
StoreName string `json:"store_name"`
|
||
Status int `json:"status"`
|
||
StatusName string `json:"status_name"`
|
||
TotalAmount float64 `json:"total_amount"`
|
||
PayAmount float64 `json:"pay_amount"`
|
||
PayStatus int `json:"pay_status"`
|
||
ReceiverName string `json:"receiver_name"`
|
||
ReceiverPhone string `json:"receiver_phone"`
|
||
ReceiverAddress string `json:"receiver_address"`
|
||
ExpressCompany string `json:"express_company"`
|
||
ExpressNo string `json:"express_no"`
|
||
CreatedAt string `json:"created_at"`
|
||
Items []OrderItemResponse `json:"items"`
|
||
}
|
||
|
||
// formatOrderList 格式化订单列表响应
|
||
func (h *OrderHandler) formatOrderList(orders []model.Order) []OrderListResponse {
|
||
result := make([]OrderListResponse, len(orders))
|
||
|
||
for i, order := range orders {
|
||
// 获取状态描述 - 使用统一状态机
|
||
statusName := "未知状态"
|
||
switch order.Status {
|
||
case 1:
|
||
statusName = "未付款"
|
||
case 2:
|
||
statusName = "待发货" // 统一为待发货
|
||
case 3:
|
||
statusName = "待发货" // 统一为待发货
|
||
case 4:
|
||
statusName = "已发货"
|
||
case 5:
|
||
statusName = "待收货"
|
||
case 6:
|
||
statusName = "已完成"
|
||
case 7:
|
||
statusName = "已取消"
|
||
case 8:
|
||
statusName = "退货中"
|
||
case 9:
|
||
statusName = "已退款"
|
||
}
|
||
|
||
// 格式化订单项
|
||
items := make([]OrderItemResponse, len(order.OrderItems))
|
||
for j, item := range order.OrderItems {
|
||
items[j] = OrderItemResponse{
|
||
ID: fmt.Sprintf("%d", item.ID),
|
||
OrderID: fmt.Sprintf("%d", item.OrderID),
|
||
ProductID: item.ProductID,
|
||
SpecID: item.SpecID,
|
||
SKUID: item.SKUID,
|
||
Quantity: item.Quantity,
|
||
Price: item.Price,
|
||
TotalPrice: item.TotalPrice,
|
||
ProductName: item.ProductName,
|
||
ProductImage: item.ProductImage, // 这里包含了商品图片
|
||
SpecName: item.SpecName,
|
||
SpecValue: item.SpecValue,
|
||
SpecInfo: item.SpecInfo,
|
||
}
|
||
}
|
||
|
||
// 获取店铺名称
|
||
storeName := "默认店铺"
|
||
if order.Store.Name != "" {
|
||
storeName = order.Store.Name
|
||
}
|
||
|
||
result[i] = OrderListResponse{
|
||
ID: fmt.Sprintf("%d", order.ID),
|
||
OrderNo: order.OrderNo,
|
||
StoreID: order.StoreID,
|
||
StoreName: storeName,
|
||
Status: order.Status,
|
||
StatusName: statusName,
|
||
TotalAmount: order.TotalAmount,
|
||
PayAmount: order.PayAmount,
|
||
PayStatus: order.PayStatus,
|
||
ReceiverName: order.ReceiverName,
|
||
ReceiverPhone: order.ReceiverPhone,
|
||
ReceiverAddress: order.ReceiverAddress,
|
||
ExpressCompany: order.LogisticsCompany,
|
||
ExpressNo: order.LogisticsNo,
|
||
CreatedAt: order.CreatedAt.Format("2006-01-02 15:04:05"),
|
||
Items: items,
|
||
}
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
// OrderDetailResponse 订单详情响应结构 - 匹配前端期望格式
|
||
type OrderDetailResponse struct {
|
||
OrderID string `json:"orderId"`
|
||
OrderNo string `json:"orderNo"`
|
||
ParentOrderNo string `json:"parentOrderNo"`
|
||
StoreID uint `json:"storeId"`
|
||
StoreName string `json:"storeName"`
|
||
OrderStatus int `json:"orderStatus"`
|
||
OrderStatusName string `json:"orderStatusName"`
|
||
PaymentAmount int64 `json:"paymentAmount"`
|
||
GoodsAmountApp int64 `json:"goodsAmountApp"`
|
||
TotalAmount int64 `json:"totalAmount"`
|
||
PayAmount int64 `json:"payAmount"`
|
||
CouponAmount int64 `json:"couponAmount"`
|
||
Status int `json:"status"`
|
||
PayStatus int `json:"payStatus"`
|
||
CreatedAt string `json:"createdAt"`
|
||
LogisticsVO *LogisticsVOResponse `json:"logisticsVO"`
|
||
OrderItemVOs []OrderItemVOResponse `json:"orderItemVOs"`
|
||
ButtonVOs []OrderButtonVO `json:"buttonVOs"`
|
||
}
|
||
|
||
// OrderButtonVO 订单按钮响应结构
|
||
type OrderButtonVO struct {
|
||
Primary bool `json:"is_primary"`
|
||
Type int `json:"type"`
|
||
Name string `json:"text"`
|
||
}
|
||
|
||
// LogisticsVOResponse 物流信息响应结构
|
||
type LogisticsVOResponse struct {
|
||
LogisticsNo string `json:"logisticsNo"`
|
||
ReceiverProvince string `json:"receiverProvince"`
|
||
ReceiverCity string `json:"receiverCity"`
|
||
ReceiverCountry string `json:"receiverCountry"` // 区县
|
||
ReceiverAddress string `json:"receiverAddress"`
|
||
ReceiverName string `json:"receiverName"`
|
||
ReceiverPhone string `json:"receiverPhone"`
|
||
}
|
||
|
||
// OrderItemVOResponse 订单项响应结构
|
||
type OrderItemVOResponse struct {
|
||
ID string `json:"id"`
|
||
GoodsName string `json:"goodsName"`
|
||
GoodsPictureUrl string `json:"goodsPictureUrl"`
|
||
ActualPrice int64 `json:"actualPrice"`
|
||
OriginPrice int64 `json:"originPrice"`
|
||
BuyQuantity int `json:"buyQuantity"`
|
||
SkuID uint `json:"skuId"`
|
||
SpuID uint `json:"spuId"`
|
||
Specifications []SpecificationResponse `json:"specifications"`
|
||
ButtonVOs []interface{} `json:"buttonVOs"`
|
||
}
|
||
|
||
// SpecificationResponse 规格响应结构
|
||
type SpecificationResponse struct {
|
||
SpecTitle string `json:"specTitle"`
|
||
SpecValue string `json:"specValue"`
|
||
}
|
||
|
||
// AddressResponse 地址响应结构
|
||
type AddressResponse struct {
|
||
Name string `json:"name"`
|
||
Phone string `json:"phone"`
|
||
Province string `json:"province"`
|
||
City string `json:"city"`
|
||
District string `json:"district"`
|
||
Detail string `json:"detail"`
|
||
FullAddress string `json:"full_address"`
|
||
}
|
||
|
||
// OrderItemResponse 订单项响应结构
|
||
type OrderItemResponse struct {
|
||
ID string `json:"id"`
|
||
OrderID string `json:"order_id"`
|
||
ProductID uint `json:"product_id"`
|
||
SpecID *uint `json:"spec_id"`
|
||
SKUID *uint `json:"sku_id"`
|
||
Quantity int `json:"quantity"`
|
||
Price float64 `json:"price"`
|
||
TotalPrice float64 `json:"total_price"`
|
||
ProductName string `json:"product_name"`
|
||
ProductImage string `json:"product_image"`
|
||
SpecName string `json:"spec_name"`
|
||
SpecValue string `json:"spec_value"`
|
||
SpecInfo map[string]interface{} `json:"spec_info"`
|
||
Product *ProductResponse `json:"product,omitempty"`
|
||
SKU *SKUResponse `json:"sku,omitempty"`
|
||
}
|
||
|
||
// ProductResponse 商品响应结构
|
||
type ProductResponse struct {
|
||
ID uint `json:"id"`
|
||
Name string `json:"name"`
|
||
MainImage string `json:"main_image"`
|
||
}
|
||
|
||
// SKUResponse SKU响应结构
|
||
type SKUResponse struct {
|
||
ID uint `json:"id"`
|
||
Name string `json:"name"`
|
||
Value string `json:"value"`
|
||
}
|
||
|
||
// StoreResponse 店铺响应结构
|
||
type StoreResponse struct {
|
||
ID uint `json:"id"`
|
||
Name string `json:"name"`
|
||
}
|
||
|
||
// GetOrderDetail 获取订单详情(支持订单ID、订单号、微信订单号)
|
||
// 参数 id 可以是:
|
||
// 1. 订单ID(纯数字)
|
||
// 2. 订单号(如:WX20251111134319259VLQCPCC1)
|
||
// 3. 微信支付订单号(如:wx1234567890abcdef)
|
||
func (h *OrderHandler) GetOrderDetail(c *gin.Context) {
|
||
userID, exists := c.Get("user_id")
|
||
if !exists {
|
||
response.Unauthorized(c)
|
||
return
|
||
}
|
||
|
||
idStr := c.Param("id")
|
||
|
||
// 尝试解析为uint,如果失败则当作订单号或微信订单号处理
|
||
orderID := utils.StringToUint(idStr)
|
||
if orderID == 0 {
|
||
// 当作订单号或微信订单号处理(service层会自动判断)
|
||
order, err := h.orderService.GetOrderDetailByOrderNo(userID.(uint), idStr)
|
||
if err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR_ORDER_NOT_FOUND, err.Error())
|
||
return
|
||
}
|
||
response.Success(c, h.formatOrderDetail(order))
|
||
return
|
||
}
|
||
|
||
// 当作订单ID处理
|
||
order, err := h.orderService.GetOrderDetail(userID.(uint), orderID)
|
||
if err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR_ORDER_NOT_FOUND, err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, h.formatOrderDetail(order))
|
||
}
|
||
|
||
// formatOrderDetail 格式化订单详情响应
|
||
func (h *OrderHandler) formatOrderDetail(order *model.Order) *OrderDetailResponse {
|
||
// 构建物流信息对象
|
||
logisticsVO := &LogisticsVOResponse{
|
||
LogisticsNo: order.LogisticsNo,
|
||
ReceiverProvince: "", // 省份,如果有的话
|
||
ReceiverCity: "", // 城市,如果有的话
|
||
ReceiverCountry: "", // 区县,如果有的话
|
||
ReceiverAddress: order.ReceiverAddress,
|
||
ReceiverName: order.ReceiverName,
|
||
ReceiverPhone: order.ReceiverPhone,
|
||
}
|
||
|
||
// 构建订单项列表
|
||
orderItemVOs := make([]OrderItemVOResponse, len(order.OrderItems))
|
||
for i, item := range order.OrderItems {
|
||
// 构建规格信息数组
|
||
specifications := []SpecificationResponse{}
|
||
if item.SpecInfo != nil {
|
||
// JSONMap 就是 map[string]interface{}
|
||
for key, value := range item.SpecInfo {
|
||
if value != nil {
|
||
specifications = append(specifications, SpecificationResponse{
|
||
SpecTitle: key,
|
||
SpecValue: fmt.Sprintf("%v", value),
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
var skuID uint
|
||
if item.SKUID != nil {
|
||
skuID = *item.SKUID
|
||
}
|
||
|
||
orderItemVOs[i] = OrderItemVOResponse{
|
||
ID: fmt.Sprintf("%d", item.ID),
|
||
GoodsName: item.ProductName,
|
||
GoodsPictureUrl: item.ProductImage,
|
||
ActualPrice: int64(item.Price), // 数据库已存储元为单位,无需乘100
|
||
OriginPrice: int64(item.Price), // 数据库已存储元为单位,无需乘100
|
||
BuyQuantity: item.Quantity,
|
||
SkuID: skuID,
|
||
SpuID: item.ProductID,
|
||
Specifications: specifications,
|
||
ButtonVOs: []interface{}{}, // 空数组
|
||
}
|
||
}
|
||
|
||
// 获取状态描述 - 使用统一状态机
|
||
statusName := "未知状态"
|
||
switch order.Status {
|
||
case 1:
|
||
statusName = "未付款"
|
||
case 2:
|
||
statusName = "待发货" // 统一为待发货
|
||
case 3:
|
||
statusName = "待发货" // 统一为待发货
|
||
case 4:
|
||
statusName = "已发货"
|
||
case 5:
|
||
statusName = "待收货"
|
||
case 6:
|
||
statusName = "已完成"
|
||
case 7:
|
||
statusName = "已取消"
|
||
case 8:
|
||
statusName = "退货中"
|
||
case 9:
|
||
statusName = "已退款"
|
||
}
|
||
|
||
// 生成订单操作按钮
|
||
buttonVOs := generateOrderButtons(order.Status, order)
|
||
|
||
return &OrderDetailResponse{
|
||
OrderID: fmt.Sprintf("%d", order.ID),
|
||
OrderNo: order.OrderNo,
|
||
ParentOrderNo: order.OrderNo, // 如果没有父订单号,使用订单号
|
||
StoreID: order.StoreID,
|
||
StoreName: order.Store.Name,
|
||
OrderStatus: order.Status,
|
||
OrderStatusName: statusName,
|
||
PaymentAmount: int64(order.PayAmount), // 数据库已存储元为单位,无需乘100
|
||
GoodsAmountApp: int64(order.TotalAmount), // 数据库已存储元为单位,无需乘100
|
||
TotalAmount: int64(order.TotalAmount), // 数据库已存储元为单位,无需乘100
|
||
PayAmount: int64(order.PayAmount), // 数据库已存储元为单位,无需乘100
|
||
CouponAmount: int64(order.CouponAmount), // 直接返回数据库数据
|
||
Status: order.Status,
|
||
PayStatus: order.PayStatus,
|
||
CreatedAt: order.CreatedAt.Format("2006-01-02 15:04:05"),
|
||
LogisticsVO: logisticsVO,
|
||
OrderItemVOs: orderItemVOs,
|
||
ButtonVOs: buttonVOs,
|
||
}
|
||
}
|
||
|
||
// PayOrder 支付订单
|
||
func (h *OrderHandler) PayOrder(c *gin.Context) {
|
||
userID, exists := c.Get("user_id")
|
||
if !exists {
|
||
response.Unauthorized(c)
|
||
return
|
||
}
|
||
|
||
// 从URL路径参数获取订单号
|
||
orderNo := c.Param("id")
|
||
if orderNo == "" {
|
||
response.BadRequest(c, "订单号不能为空")
|
||
return
|
||
}
|
||
|
||
// 解析请求体获取支付方式
|
||
var req struct {
|
||
PaymentMethod string `json:"payment_method"`
|
||
}
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
// 如果没有提供支付方式,默认使用微信支付
|
||
req.PaymentMethod = "wechat"
|
||
}
|
||
|
||
// 获取订单详情
|
||
order, err := h.orderService.GetOrderByOrderNo(orderNo)
|
||
if err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, "订单不存在")
|
||
return
|
||
}
|
||
|
||
// 验证订单归属
|
||
if order.UserID != userID.(uint) {
|
||
response.ErrorWithMessage(c, response.ERROR, "无权限操作此订单")
|
||
return
|
||
}
|
||
|
||
// 验证订单状态
|
||
if order.Status != 1 { // 1 = 待付款
|
||
response.ErrorWithMessage(c, response.ERROR, "订单状态不允许支付")
|
||
return
|
||
}
|
||
|
||
// 如果是微信支付,返回支付二维码
|
||
if req.PaymentMethod == "wechat" {
|
||
// 调用微信Native扫码支付
|
||
if h.wechatPayService != nil {
|
||
paymentResp, err := h.wechatPayService.CreateNativeOrder(c.Request.Context(), order)
|
||
if err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, paymentResp.Data)
|
||
return
|
||
} else {
|
||
// 如果没有微信支付服务,返回模拟数据
|
||
response.Success(c, gin.H{
|
||
"qrcode_url": "https://api.example.com/qrcode/" + orderNo,
|
||
"order_no": orderNo,
|
||
"amount": order.TotalAmount,
|
||
"sandbox": true,
|
||
})
|
||
return
|
||
}
|
||
}
|
||
|
||
// 其他支付方式,直接标记为已支付
|
||
if err := h.orderService.PayOrder(userID.(uint), orderNo); err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, nil)
|
||
}
|
||
|
||
// CancelOrder 取消订单
|
||
func (h *OrderHandler) CancelOrder(c *gin.Context) {
|
||
userID, exists := c.Get("user_id")
|
||
if !exists {
|
||
response.Unauthorized(c)
|
||
return
|
||
}
|
||
|
||
var req struct {
|
||
OrderNo string `json:"order_no" binding:"required"`
|
||
}
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "鍙傛暟閿欒: "+err.Error())
|
||
return
|
||
}
|
||
|
||
if err := h.orderService.CancelOrder(userID.(uint), req.OrderNo); err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, nil)
|
||
}
|
||
|
||
// RemindShip 提醒发货
|
||
func (h *OrderHandler) RemindShip(c *gin.Context) {
|
||
log.Printf("[后端处理] ===== 提醒发货请求开始 =====")
|
||
|
||
userID, exists := c.Get("user_id")
|
||
if !exists {
|
||
log.Printf("[后端处理] 提醒发货失败: 用户未认证")
|
||
response.Unauthorized(c)
|
||
return
|
||
}
|
||
|
||
// 从URL路径参数获取订单号
|
||
orderNo := c.Param("id")
|
||
log.Printf("[后端处理] 提醒发货请求参数: userID=%v, orderNo=%s", userID, orderNo)
|
||
|
||
if orderNo == "" {
|
||
log.Printf("[后端处理] 提醒发货失败: 订单号为空")
|
||
response.BadRequest(c, "订单号不能为空")
|
||
return
|
||
}
|
||
|
||
log.Printf("[后端处理] 调用服务层提醒发货方法...")
|
||
if err := h.orderService.RemindShip(userID.(uint), orderNo); err != nil {
|
||
log.Printf("[后端处理] 提醒发货失败: %v", err)
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
log.Printf("[后端处理] 提醒发货成功")
|
||
response.Success(c, gin.H{"message": "提醒发货成功"})
|
||
}
|
||
|
||
// ConfirmReceive方法前的注释
|
||
func (h *OrderHandler) RefundOrder(c *gin.Context) {
|
||
log.Printf("[后端处理] ===== 退款申请请求开始 =====")
|
||
|
||
userID, exists := c.Get("user_id")
|
||
if !exists {
|
||
log.Printf("[后端处理] 退款申请失败: 用户未认证")
|
||
response.Unauthorized(c)
|
||
return
|
||
}
|
||
|
||
// 从URL路径参数获取订单号
|
||
orderNo := c.Param("id")
|
||
log.Printf("[后端处理] 退款申请请求参数: userID=%v, orderNo=%s", userID, orderNo)
|
||
|
||
if orderNo == "" {
|
||
log.Printf("[后端处理] 退款申请失败: 订单号为空")
|
||
response.BadRequest(c, "订单号不能为空")
|
||
return
|
||
}
|
||
|
||
log.Printf("[后端处理] 调用服务层退款申请方法...")
|
||
// 调用服务层的退款方法
|
||
if err := h.orderService.RefundOrderDuplicate(userID.(uint), orderNo); err != nil {
|
||
log.Printf("[后端处理] 退款申请失败: %v", err)
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
log.Printf("[后端处理] 退款申请成功")
|
||
response.Success(c, gin.H{"message": "退款申请已提交"})
|
||
}
|
||
|
||
// ConfirmReceive 确认收货
|
||
func (h *OrderHandler) ConfirmReceive(c *gin.Context) {
|
||
userID, exists := c.Get("user_id")
|
||
if !exists {
|
||
response.Unauthorized(c)
|
||
return
|
||
}
|
||
|
||
var req struct {
|
||
OrderNo string `json:"order_no" binding:"required"`
|
||
}
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "鍙傛暟閿欒: "+err.Error())
|
||
return
|
||
}
|
||
|
||
if err := h.orderService.ConfirmReceive(userID.(uint), req.OrderNo); err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, nil)
|
||
}
|
||
|
||
// GetOrderList 获取订单列表(支持条件查询)
|
||
func (h *OrderHandler) GetOrderList(c *gin.Context) {
|
||
page := utils.StringToInt(c.DefaultQuery("page", "1"))
|
||
pageSize := utils.StringToInt(c.DefaultQuery("page_size", "20"))
|
||
|
||
conditions := make(map[string]interface{})
|
||
if status := c.Query("status"); status != "" {
|
||
conditions["status"] = utils.StringToInt(status)
|
||
}
|
||
if userID := c.Query("user_id"); userID != "" {
|
||
conditions["user_id"] = utils.StringToUint(userID)
|
||
}
|
||
if orderNo := c.Query("order_no"); orderNo != "" {
|
||
conditions["order_no"] = orderNo
|
||
}
|
||
if startDate := c.Query("start_date"); startDate != "" {
|
||
conditions["start_date"] = startDate
|
||
}
|
||
if endDate := c.Query("end_date"); endDate != "" {
|
||
conditions["end_date"] = endDate
|
||
}
|
||
|
||
orders, pagination, err := h.orderService.GetOrderList(page, pageSize, conditions)
|
||
if err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
response.Page(c, orders, pagination.Total, pagination.Page, pagination.PageSize)
|
||
}
|
||
|
||
// ShipOrder 发货
|
||
func (h *OrderHandler) ShipOrder(c *gin.Context) {
|
||
var req struct {
|
||
OrderNo string `json:"order_no" binding:"required"`
|
||
LogisticsCompany string `json:"logistics_company" binding:"required"`
|
||
LogisticsNo string `json:"logistics_no" binding:"required"`
|
||
}
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "鍙傛暟閿欒: "+err.Error())
|
||
return
|
||
}
|
||
|
||
if err := h.orderService.ShipOrder(req.OrderNo, req.LogisticsCompany, req.LogisticsNo); err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, nil)
|
||
}
|
||
|
||
// GetOrderStatistics 获取订单统计
|
||
func (h *OrderHandler) GetOrderStatistics(c *gin.Context) {
|
||
statistics, err := h.orderService.GetOrderStatistics()
|
||
if err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, statistics)
|
||
}
|
||
|
||
// GetDailyOrderStatistics 获取每日订单统计
|
||
func (h *OrderHandler) GetDailyOrderStatistics(c *gin.Context) {
|
||
days := utils.StringToInt(c.DefaultQuery("days", "30"))
|
||
|
||
statistics, err := h.orderService.GetDailyOrderStatistics(days)
|
||
if err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, statistics)
|
||
}
|
||
|
||
// MergeOrders 合并订单
|
||
func (h *OrderHandler) MergeOrders(c *gin.Context) {
|
||
userID, exists := c.Get("user_id")
|
||
if !exists {
|
||
response.Unauthorized(c)
|
||
return
|
||
}
|
||
|
||
var req service.MergeOrdersRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.BadRequest(c, "参数错误: "+err.Error())
|
||
return
|
||
}
|
||
|
||
// 验证订单数量
|
||
if len(req.OrderIDs) < 2 {
|
||
response.BadRequest(c, "至少需要选择2个订单进行合并")
|
||
return
|
||
}
|
||
|
||
mergedOrder, err := h.orderService.MergeOrders(userID.(uint), &req)
|
||
if err != nil {
|
||
response.ErrorWithMessage(c, response.ERROR, err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, gin.H{
|
||
"message": "订单合并成功",
|
||
"order": mergedOrder,
|
||
})
|
||
}
|
||
|
||
// generateOrderButtons 根据订单状态生成操作按钮
|
||
func generateOrderButtons(status int, order *model.Order) []OrderButtonVO {
|
||
log.Printf("[后端按钮生成] ===== 开始生成按钮 =====")
|
||
log.Printf("[后端按钮生成] 输入状态: %d", status)
|
||
|
||
var buttons []OrderButtonVO
|
||
|
||
switch status {
|
||
case 1: // 待付款
|
||
log.Printf("[后端按钮生成] 状态1-待付款: 生成取消订单(type=1)和立即付款(type=2)按钮")
|
||
buttons = []OrderButtonVO{
|
||
{Primary: false, Type: 1, Name: "取消订单"},
|
||
{Primary: true, Type: 2, Name: "立即付款"},
|
||
}
|
||
case 2: // 已付款/待发货
|
||
log.Printf("[后端按钮生成] 状态2-已付款/待发货: 生成申请退款(type=7)和提醒发货(type=3)按钮")
|
||
buttons = []OrderButtonVO{
|
||
{Primary: false, Type: 7, Name: "申请退款"},
|
||
{Primary: true, Type: 3, Name: "提醒发货"},
|
||
}
|
||
case 3: // 待发货
|
||
log.Printf("[后端按钮生成] 状态3-待发货: 生成申请退款(type=7)和提醒发货(type=3)按钮")
|
||
buttons = []OrderButtonVO{
|
||
{Primary: false, Type: 7, Name: "申请退款"},
|
||
{Primary: true, Type: 3, Name: "提醒发货"},
|
||
}
|
||
case 4: // 已发货/待收货
|
||
log.Printf("[后端按钮生成] 状态4-已发货/待收货: 生成确认收货(type=4)按钮")
|
||
buttons = []OrderButtonVO{
|
||
{Primary: true, Type: 4, Name: "确认收货"},
|
||
}
|
||
case 5: // 待收货
|
||
log.Printf("[后端按钮生成] 状态5-待收货: 生成确认收货(type=4)按钮")
|
||
buttons = []OrderButtonVO{
|
||
{Primary: true, Type: 4, Name: "确认收货"},
|
||
}
|
||
case 6: // 已完成
|
||
log.Printf("[后端按钮生成] 状态6-已完成: 检查是否有未评价的订单项")
|
||
|
||
// 检查是否有未评价的订单项
|
||
hasUncommentedItems := false
|
||
for _, item := range order.OrderItems {
|
||
if !item.IsCommented {
|
||
hasUncommentedItems = true
|
||
log.Printf("[后端按钮生成] 发现未评价的订单项: ID=%d, ProductID=%d", item.ID, item.ProductID)
|
||
break
|
||
}
|
||
}
|
||
|
||
if hasUncommentedItems {
|
||
log.Printf("[后端按钮生成] 状态6-已完成: 有未评价订单项,生成申请售后(type=5)和评价(type=6)按钮")
|
||
buttons = []OrderButtonVO{
|
||
{Primary: false, Type: 5, Name: "申请售后"},
|
||
{Primary: true, Type: 6, Name: "评价"},
|
||
}
|
||
} else {
|
||
log.Printf("[后端按钮生成] 状态6-已完成: 所有订单项已评价,只生成申请售后(type=5)按钮")
|
||
buttons = []OrderButtonVO{
|
||
{Primary: false, Type: 5, Name: "申请售后"},
|
||
}
|
||
}
|
||
case 7: // 已取消
|
||
log.Printf("[后端按钮生成] 状态7-已取消: 不生成任何按钮")
|
||
buttons = []OrderButtonVO{}
|
||
case 8: // 退货中
|
||
log.Printf("[后端按钮生成] 状态8-退货中: 不生成任何按钮")
|
||
buttons = []OrderButtonVO{}
|
||
case 9: // 已退款
|
||
log.Printf("[后端按钮生成] 状态9-已退款: 不生成任何按钮")
|
||
buttons = []OrderButtonVO{}
|
||
default:
|
||
log.Printf("[后端按钮生成] 未知状态%d: 不生成任何按钮", status)
|
||
buttons = []OrderButtonVO{}
|
||
}
|
||
|
||
log.Printf("[后端按钮生成] ===== 按钮生成完成 =====")
|
||
log.Printf("[后端按钮生成] 生成的按钮数量: %d", len(buttons))
|
||
for i, btn := range buttons {
|
||
log.Printf("[后端按钮生成] 按钮%d: type=%d, name=%s, primary=%t", i, btn.Type, btn.Name, btn.Primary)
|
||
}
|
||
|
||
return buttons
|
||
}
|