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

607 lines
15 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/service"
"dianshang/pkg/response"
"dianshang/pkg/utils"
"strconv"
"time"
"github.com/gin-gonic/gin"
)
// AdminOrderHandler 管理后台订单处理器
type AdminOrderHandler struct {
orderService *service.OrderService
}
// NewAdminOrderHandler 创建管理后台订单处理器
func NewAdminOrderHandler(orderService *service.OrderService) *AdminOrderHandler {
return &AdminOrderHandler{
orderService: orderService,
}
}
// GetOrderList 获取订单列表
func (h *AdminOrderHandler) GetOrderList(c *gin.Context) {
page := utils.StringToInt(c.DefaultQuery("page", "1"))
pageSize := utils.StringToInt(c.DefaultQuery("page_size", "10"))
status := c.Query("status")
orderNo := c.Query("order_no")
userID := utils.StringToUint(c.Query("user_id"))
startDate := c.Query("start_date")
endDate := c.Query("end_date")
if page <= 0 {
page = 1
}
if pageSize <= 0 || pageSize > 100 {
pageSize = 10
}
// 构建查询条件
conditions := make(map[string]interface{})
if status != "" {
conditions["status"] = status
}
if orderNo != "" {
conditions["order_no"] = orderNo
}
if userID > 0 {
conditions["user_id"] = userID
}
if startDate != "" {
conditions["start_date"] = startDate
}
if endDate != "" {
conditions["end_date"] = endDate
}
orders, pagination, err := h.orderService.GetOrderListForAdmin(page, pageSize, conditions)
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, gin.H{
"list": orders,
"pagination": pagination,
})
}
// GetOrderDetail 获取订单详情
func (h *AdminOrderHandler) GetOrderDetail(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的订单ID")
return
}
order, err := h.orderService.GetOrderDetailForAdmin(uint(id))
if err != nil {
response.ErrorWithMessage(c, response.ERROR, "订单不存在")
return
}
response.Success(c, order)
}
// UpdateOrderStatus 更新订单状态
func (h *AdminOrderHandler) UpdateOrderStatus(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 {
Status int `json:"status" binding:"required"`
Remark string `json:"remark"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
if err := h.orderService.UpdateOrderStatusByAdmin(uint(id), req.Status, req.Remark); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// ShipOrder 发货
func (h *AdminOrderHandler) ShipOrder(c *gin.Context) {
idStr := c.Param("id")
if idStr == "" {
response.BadRequest(c, "无效的订单ID")
return
}
orderID, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的订单ID")
return
}
var req struct {
LogisticsCompany string `json:"logistics_company" binding:"required"`
TrackingNumber string `json:"tracking_number" binding:"required"`
Remark string `json:"remark"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
if err := h.orderService.ShipOrderByID(uint(orderID), req.LogisticsCompany, req.TrackingNumber); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// RefundOrder 退款
func (h *AdminOrderHandler) RefundOrder(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 {
RefundAmount float64 `json:"refund_amount" binding:"required"`
RefundReason string `json:"refund_reason" binding:"required"`
Remark string `json:"remark"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
// 获取管理员ID
adminID := uint(0)
if adminIDValue, exists := c.Get("user_id"); exists {
adminID = adminIDValue.(uint)
}
if err := h.orderService.RefundOrder(uint(id), req.RefundAmount, req.RefundReason, adminID); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// CancelOrder 取消订单
func (h *AdminOrderHandler) CancelOrder(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 {
CancelReason string `json:"cancel_reason" binding:"required"`
Remark string `json:"remark"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
// 获取管理员ID
adminID := uint(0)
if adminIDValue, exists := c.Get("user_id"); exists {
adminID = adminIDValue.(uint)
}
if err := h.orderService.CancelOrderByAdmin(uint(id), req.CancelReason, adminID); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// GetLogisticsInfo 获取物流信息
func (h *AdminOrderHandler) GetLogisticsInfo(c *gin.Context) {
orderNo := c.Param("orderNo")
if orderNo == "" {
response.BadRequest(c, "无效的订单号")
return
}
logisticsInfo, err := h.orderService.GetLogisticsInfo(orderNo)
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, logisticsInfo)
}
// UpdateOrderStatusNew 更新订单状态(新版本)
func (h *AdminOrderHandler) UpdateOrderStatusNew(c *gin.Context) {
orderIDStr := c.Param("id")
orderID, err := strconv.ParseUint(orderIDStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的订单ID")
return
}
var req struct {
Status int `json:"status" binding:"required"`
Reason string `json:"reason"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
// 获取管理员ID
adminID := uint(0)
if id, exists := c.Get("user_id"); exists {
adminID = id.(uint)
}
if err := h.orderService.UpdateOrderStatus(uint(orderID), req.Status, adminID); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// BatchUpdateOrderStatus 批量更新订单状态
func (h *AdminOrderHandler) BatchUpdateOrderStatus(c *gin.Context) {
var req struct {
OrderIDs []uint `json:"order_ids" binding:"required"`
Status int `json:"status" binding:"required"`
Reason string `json:"reason"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
// 获取管理员ID
adminID := uint(0)
if id, exists := c.Get("user_id"); exists {
adminID = id.(uint)
}
if err := h.orderService.BatchUpdateOrderStatus(req.OrderIDs, req.Status, adminID); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// ProcessRefund 处理退款
func (h *AdminOrderHandler) ProcessRefund(c *gin.Context) {
orderIDStr := c.Param("id")
orderID, err := strconv.ParseUint(orderIDStr, 10, 32)
if err != nil {
response.BadRequest(c, "无效的订单ID")
return
}
var req struct {
RefundAmount float64 `json:"refund_amount" binding:"required"`
RefundReason string `json:"refund_reason" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
// 获取管理员ID
adminID := uint(0)
if id, exists := c.Get("user_id"); exists {
adminID = id.(uint)
}
if err := h.orderService.ProcessRefund(uint(orderID), req.RefundAmount, req.RefundReason, adminID); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, nil)
}
// GetOrderStatistics 获取订单统计
func (h *AdminOrderHandler) 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 *AdminOrderHandler) GetDailyOrderStatistics(c *gin.Context) {
daysStr := c.DefaultQuery("days", "7")
days, err := strconv.Atoi(daysStr)
if err != nil || days <= 0 {
days = 7
}
statistics, err := h.orderService.GetDailyOrderStatistics(days)
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, statistics)
}
// GetOrdersByDateRange 根据日期范围获取订单
func (h *AdminOrderHandler) GetOrdersByDateRange(c *gin.Context) {
startDate := c.Query("start_date")
endDate := c.Query("end_date")
statusStr := c.DefaultQuery("status", "0")
pageStr := c.DefaultQuery("page", "1")
limitStr := c.DefaultQuery("limit", "20")
status, _ := strconv.Atoi(statusStr)
page, _ := strconv.Atoi(pageStr)
limit, _ := strconv.Atoi(limitStr)
if page <= 0 {
page = 1
}
if limit <= 0 {
limit = 20
}
offset := (page - 1) * limit
orders, total, err := h.orderService.GetOrdersByDateRange(startDate, endDate, status, offset, limit)
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, gin.H{
"list": orders,
"total": total,
"page": page,
"limit": limit,
})
}
// ExportOrdersToExcel 导出订单到Excel
func (h *AdminOrderHandler) ExportOrdersToExcel(c *gin.Context) {
// 获取查询条件
conditions := make(map[string]interface{})
if startDate := c.Query("start_date"); startDate != "" {
conditions["start_date"] = startDate
}
if endDate := c.Query("end_date"); endDate != "" {
conditions["end_date"] = endDate
}
if statusStr := c.Query("status"); statusStr != "" {
if status, err := strconv.Atoi(statusStr); err == nil && status > 0 {
conditions["status"] = status
}
}
if orderNo := c.Query("order_no"); orderNo != "" {
conditions["order_no"] = orderNo
}
exportData, err := h.orderService.ExportOrdersToExcel(conditions)
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
// 这里应该生成Excel文件并返回下载链接
// 暂时返回数据实际项目中需要使用Excel库生成文件
response.Success(c, gin.H{
"data": exportData,
"filename": "orders_" + time.Now().Format("20060102_150405") + ".xlsx",
"message": "导出成功",
})
}
// GetOrderTrends 获取订单趋势
func (h *AdminOrderHandler) GetOrderTrends(c *gin.Context) {
daysStr := c.DefaultQuery("days", "30")
days, err := strconv.Atoi(daysStr)
if err != nil || days <= 0 {
days = 30
}
trends, err := h.orderService.GetOrderTrends(days)
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, trends)
}
// GetPendingOrdersCount 获取待处理订单数量
func (h *AdminOrderHandler) GetPendingOrdersCount(c *gin.Context) {
count, err := h.orderService.GetPendingOrdersCount()
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, gin.H{
"pending_count": count,
})
}
// GetOrderSummary 获取订单概览
func (h *AdminOrderHandler) GetOrderSummary(c *gin.Context) {
// 获取基本统计
statistics, err := h.orderService.GetOrderStatistics()
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
// 获取待处理订单数量
pendingCount, err := h.orderService.GetPendingOrdersCount()
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
// 获取7天趋势
trends, err := h.orderService.GetOrderTrends(7)
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
summary := gin.H{
"statistics": statistics,
"pending_count": pendingCount,
"trends": trends,
"updated_at": time.Now().Format("2006-01-02 15:04:05"),
}
response.Success(c, summary)
}
// BatchProcessOrders 批量处理订单
func (h *AdminOrderHandler) BatchProcessOrders(c *gin.Context) {
var req struct {
OrderIDs []uint `json:"order_ids" binding:"required"`
Action string `json:"action" binding:"required"` // "ship", "cancel", "refund"
Data gin.H `json:"data"` // 额外数据,如物流信息等
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "请求参数错误")
return
}
// 获取管理员ID
adminID := uint(0)
if id, exists := c.Get("user_id"); exists {
adminID = id.(uint)
}
switch req.Action {
case "ship":
// 批量发货
logisticsCompany, _ := req.Data["logistics_company"].(string)
trackingNumber, _ := req.Data["tracking_number"].(string)
if logisticsCompany == "" || trackingNumber == "" {
response.BadRequest(c, "发货需要提供物流公司和运单号")
return
}
for _, orderID := range req.OrderIDs {
// 这里需要根据订单ID获取订单号
order, err := h.orderService.GetOrderDetailForAdmin(orderID)
if err != nil {
response.ErrorWithMessage(c, response.ERROR, "订单不存在: "+err.Error())
return
}
if err := h.orderService.ShipOrder(order.OrderNo, logisticsCompany, trackingNumber); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
}
case "cancel":
// 批量取消
cancelReason, _ := req.Data["cancel_reason"].(string)
if cancelReason == "" {
cancelReason = "管理员批量取消"
}
for _, orderID := range req.OrderIDs {
if err := h.orderService.CancelOrderByAdmin(orderID, cancelReason, adminID); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
}
case "status":
// 批量更新状态
status, ok := req.Data["status"].(float64)
if !ok {
response.BadRequest(c, "状态更新需要提供status字段")
return
}
if err := h.orderService.BatchUpdateOrderStatus(req.OrderIDs, int(status), adminID); err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
default:
response.BadRequest(c, "不支持的操作类型")
return
}
response.Success(c, nil)
}
// ExportOrders 导出订单
func (h *AdminOrderHandler) ExportOrders(c *gin.Context) {
startDate := c.Query("start_date")
endDate := c.Query("end_date")
status := c.Query("status")
// 构建查询条件
conditions := make(map[string]interface{})
if status != "" {
conditions["status"] = status
}
if startDate != "" {
conditions["start_date"] = startDate
}
if endDate != "" {
conditions["end_date"] = endDate
}
// 获取所有符合条件的订单(不分页)
orders, _, err := h.orderService.GetOrderListForAdmin(1, 10000, conditions)
if err != nil {
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
// 设置响应头
c.Header("Content-Type", "application/vnd.ms-excel")
c.Header("Content-Disposition", "attachment; filename=orders_"+time.Now().Format("20060102150405")+".csv")
// 简单的CSV格式导出
csvData := "订单号,用户ID,订单状态,订单金额,创建时间\n"
for _, order := range orders {
csvData += order.OrderNo + "," +
strconv.Itoa(int(order.UserID)) + "," +
strconv.Itoa(order.Status) + "," +
strconv.FormatFloat(order.TotalAmount, 'f', 2, 64) + "," +
order.CreatedAt.Format("2006-01-02 15:04:05") + "\n"
}
c.String(200, csvData)
}