feat: implement order export to Excel with excelize library
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
"sale/internal/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
type CartHandler struct{}
|
||||
@@ -663,7 +665,99 @@ func (h *OrderHandler) Export(c *gin.Context) {
|
||||
utils.DB.Preload("OrderItems.Product").Preload("ShippingAddress").Preload("User").
|
||||
Order("created_at DESC").Find(&orders)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": orders})
|
||||
// 创建 Excel 文件
|
||||
f := excelize.NewFile()
|
||||
defer f.Close()
|
||||
|
||||
sheetName := "订单列表"
|
||||
f.SetSheetName("Sheet1", sheetName)
|
||||
|
||||
// 设置表头
|
||||
headers := []string{"订单ID", "用户名", "订单状态", "商品信息", "商品金额", "运费", "服务费", "通道费", "包装费", "国际计算手续费", "订单总额", "收货人", "联系电话", "收货地址", "快递单号", "创建时间"}
|
||||
for i, header := range headers {
|
||||
cell, _ := excelize.CoordinatesToCellName(i+1, 1)
|
||||
f.SetCellValue(sheetName, cell, header)
|
||||
}
|
||||
|
||||
// 设置表头样式
|
||||
headerStyle, _ := f.NewStyle(&excelize.Style{
|
||||
Font: &excelize.Font{Bold: true},
|
||||
Fill: excelize.Fill{Type: "pattern", Color: []string{"#4472C4"}, Pattern: 1},
|
||||
Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
|
||||
})
|
||||
f.SetRowStyle(sheetName, 1, 1, headerStyle)
|
||||
|
||||
// 状态映射
|
||||
statusMap := map[string]string{
|
||||
"pending_payment": "待支付", "pending_confirm": "待确认", "pending_ship": "待发货",
|
||||
"shipped": "已发货", "completed": "已完成", "refunding": "退款中", "refunded": "已退款", "cancelled": "已取消",
|
||||
}
|
||||
|
||||
// 填充数据
|
||||
for i, order := range orders {
|
||||
row := i + 2
|
||||
|
||||
// 商品信息
|
||||
var productsStr string
|
||||
for _, item := range order.OrderItems {
|
||||
if productsStr != "" {
|
||||
productsStr += "; "
|
||||
}
|
||||
productsStr += fmt.Sprintf("%s x%d", item.Product.Name, item.Quantity)
|
||||
}
|
||||
|
||||
// 收货地址
|
||||
var addressStr string
|
||||
if order.ShippingAddress != nil {
|
||||
addressStr = order.ShippingAddress.Province + order.ShippingAddress.City + order.ShippingAddress.District + order.ShippingAddress.Address
|
||||
}
|
||||
|
||||
// 填充单元格
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("A%d", row), order.ID)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("B%d", row), order.User.Username)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("C%d", row), statusMap[order.Status])
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("D%d", row), productsStr)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("E%d", row), order.Subtotal)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("F%d", row), order.ShippingFee)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("G%d", row), order.ServiceFee)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("H%d", row), order.ChannelFee)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("I%d", row), order.PackagingFee)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("J%d", row), order.InternationalFee)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("K%d", row), order.TotalAmount)
|
||||
if order.ShippingAddress != nil {
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("L%d", row), order.ShippingAddress.Name)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("M%d", row), order.ShippingAddress.Phone)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("N%d", row), addressStr)
|
||||
}
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("O%d", row), order.TrackingNumber)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("P%d", row), order.CreatedAt.Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
|
||||
// 设置列宽
|
||||
f.SetColWidth(sheetName, "A", "A", 10)
|
||||
f.SetColWidth(sheetName, "B", "B", 15)
|
||||
f.SetColWidth(sheetName, "C", "C", 10)
|
||||
f.SetColWidth(sheetName, "D", "D", 40)
|
||||
f.SetColWidth(sheetName, "E", "K", 12)
|
||||
f.SetColWidth(sheetName, "L", "M", 15)
|
||||
f.SetColWidth(sheetName, "N", "N", 40)
|
||||
f.SetColWidth(sheetName, "O", "O", 20)
|
||||
f.SetColWidth(sheetName, "P", "P", 20)
|
||||
|
||||
// 设置响应头
|
||||
filename := fmt.Sprintf("orders_%s.xlsx", time.Now().Format("20060102150405"))
|
||||
c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
|
||||
c.Header("Content-Transfer-Encoding", "binary")
|
||||
|
||||
// 写入响应
|
||||
buf, err := f.WriteToBuffer()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate Excel file"})
|
||||
return
|
||||
}
|
||||
|
||||
c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", buf.Bytes())
|
||||
}
|
||||
|
||||
func (h *OrderHandler) CancelOrder(c *gin.Context) {
|
||||
|
||||
Reference in New Issue
Block a user