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, err := excelize.CoordinatesToCellName(i+1, 1) if err != nil { return nil, fmt.Errorf("生成表头单元格坐标失败: %v", err) } 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 } // 计算表头范围 lastCol, err := excelize.CoordinatesToCellName(len(config.Headers), 1) if err != nil { return nil, fmt.Errorf("生成表头范围失败: %v", err) } headerRange := fmt.Sprintf("A1:%s", lastCol) f.SetCellStyle(sheetName, headerRange, headerRange, headerStyle) // 批量写入数据 for i, rowData := range config.Data { row := i + 2 // 从第2行开始写入数据 for j, value := range rowData { cell, err := excelize.CoordinatesToCellName(j+1, row) if err != nil { return nil, fmt.Errorf("生成数据单元格坐标失败: %v", err) } f.SetCellValue(sheetName, cell, value) } } // 设置列宽 for i, width := range config.ColumnWidths { col, err := excelize.ColumnNumberToName(i + 1) if err != nil { return nil, fmt.Errorf("生成列名失败: %v", err) } f.SetColWidth(sheetName, col, col, width) } buf, err := f.WriteToBuffer() if err != nil { return nil, err } m.logger.Info("Excel文件生成完成", zap.Int("file_size", len(buf.Bytes()))) 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 }