117 lines
2.9 KiB
Go
117 lines
2.9 KiB
Go
|
|
package export
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"github.com/xuri/excelize/v2"
|
||
|
|
"go.uber.org/zap"
|
||
|
|
)
|
||
|
|
|
||
|
|
// ExportConfig 定义了导出所需的配置
|
||
|
|
type ExportConfig struct {
|
||
|
|
SheetName string // 工作表名称
|
||
|
|
Headers []string // 表头
|
||
|
|
Data [][]interface{} // 导出数据
|
||
|
|
ColumnWidths []float64 // 列宽
|
||
|
|
}
|
||
|
|
|
||
|
|
// ExportManager 负责管理不同格式的导出
|
||
|
|
type ExportManager struct {
|
||
|
|
logger *zap.Logger
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewExportManager 创建一个新的ExportManager
|
||
|
|
func NewExportManager(logger *zap.Logger) *ExportManager {
|
||
|
|
return &ExportManager{
|
||
|
|
logger: logger,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Export 根据配置和格式生成导出文件
|
||
|
|
func (m *ExportManager) Export(ctx context.Context, config *ExportConfig, format string) ([]byte, error) {
|
||
|
|
switch format {
|
||
|
|
case "excel":
|
||
|
|
return m.generateExcel(ctx, config)
|
||
|
|
case "csv":
|
||
|
|
return m.generateCSV(ctx, config)
|
||
|
|
default:
|
||
|
|
return nil, fmt.Errorf("不支持的导出格式: %s", format)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// generateExcel 生成Excel导出文件
|
||
|
|
func (m *ExportManager) generateExcel(ctx context.Context, config *ExportConfig) ([]byte, error) {
|
||
|
|
f := excelize.NewFile()
|
||
|
|
defer func() {
|
||
|
|
if err := f.Close(); err != nil {
|
||
|
|
m.logger.Error("关闭Excel文件失败", zap.Error(err))
|
||
|
|
}
|
||
|
|
}()
|
||
|
|
|
||
|
|
sheetName := config.SheetName
|
||
|
|
index, err := f.NewSheet(sheetName)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
f.SetActiveSheet(index)
|
||
|
|
|
||
|
|
// 设置表头
|
||
|
|
for i, header := range config.Headers {
|
||
|
|
cell := fmt.Sprintf("%c1", 'A'+i)
|
||
|
|
f.SetCellValue(sheetName, cell, header)
|
||
|
|
}
|
||
|
|
|
||
|
|
// 设置表头样式
|
||
|
|
headerStyle, err := f.NewStyle(&excelize.Style{
|
||
|
|
Font: &excelize.Font{Bold: true},
|
||
|
|
Fill: excelize.Fill{Type: "pattern", Color: []string{"#E6F3FF"}, Pattern: 1},
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
headerRange := fmt.Sprintf("A1:%c1", 'A'+len(config.Headers)-1)
|
||
|
|
f.SetCellStyle(sheetName, headerRange, headerRange, headerStyle)
|
||
|
|
|
||
|
|
// 批量写入数据
|
||
|
|
for i, rowData := range config.Data {
|
||
|
|
row := i + 2 // 从第2行开始写入数据
|
||
|
|
for j, value := range rowData {
|
||
|
|
cell := fmt.Sprintf("%c%d", 'A'+j, row)
|
||
|
|
f.SetCellValue(sheetName, cell, value)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 设置列宽
|
||
|
|
for i, width := range config.ColumnWidths {
|
||
|
|
col := fmt.Sprintf("%c", 'A'+i)
|
||
|
|
f.SetColWidth(sheetName, col, col, width)
|
||
|
|
}
|
||
|
|
|
||
|
|
buf, err := f.WriteToBuffer()
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return buf.Bytes(), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// generateCSV 生成CSV导出文件
|
||
|
|
func (m *ExportManager) generateCSV(ctx context.Context, config *ExportConfig) ([]byte, error) {
|
||
|
|
var csvData strings.Builder
|
||
|
|
|
||
|
|
// 写入CSV头部
|
||
|
|
csvData.WriteString(strings.Join(config.Headers, ",") + "\n")
|
||
|
|
|
||
|
|
// 写入数据行
|
||
|
|
for _, rowData := range config.Data {
|
||
|
|
rowStrings := make([]string, len(rowData))
|
||
|
|
for i, value := range rowData {
|
||
|
|
rowStrings[i] = fmt.Sprintf("%v", value) // 使用%v通用格式化
|
||
|
|
}
|
||
|
|
csvData.WriteString(strings.Join(rowStrings, ",") + "\n")
|
||
|
|
}
|
||
|
|
|
||
|
|
return []byte(csvData.String()), nil
|
||
|
|
}
|