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 | ||
|  | } |