package main import ( "errors" "fmt" "golang.org/x/exp/maps" "strings" "github.com/mozillazg/go-pinyin" "github.com/xuri/excelize/v2" "gorm.io/gorm" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/mysqlx" ) type ExcelData struct { *excelize.File Head []string Index int IndexCell int } func (e *ExcelData) SetHead(head []string) *ExcelData { if e == nil { return nil } e.Index = 1 e.SetSheetRow("Sheet1", "A1", &head) return e } func (e *ExcelData) SetRow(row []string) *ExcelData { if e == nil { return nil } e.Index++ e.SetSheetRow("Sheet1", "A"+fmt.Sprintf("%d", e.Index), &row) return e } func (e *ExcelData) SetCell(val interface{}) *ExcelData { if e == nil { return nil } e.IndexCell++ cell := fmt.Sprintf("%c%d", 'A'+e.IndexCell-1, e.Index) e.SetCellValue("Sheet1", cell, val) return e } func (e *ExcelData) NewLine() *ExcelData { if e == nil { return nil } e.Index++ e.IndexCell = 0 return e } type ExcelMgr struct { List map[int]*ExcelData } func NewExcelMgr() *ExcelMgr { return &ExcelMgr{ List: make(map[int]*ExcelData), } } func (e *ExcelMgr) Register(id int, head []string) *ExcelData { e.List[id] = &ExcelData{ File: excelize.NewFile(), Head: head, Index: 0, } e.List[id].NewSheet("Sheet1") if len(head) > 0 { e.List[id].SetHead(head) } return e.List[id] } func (e *ExcelMgr) Get(id int) *ExcelData { return e.List[id] } func (e *ExcelMgr) Save(id int, fileName string) error { d := e.List[id] if d == nil { return nil } if VP.GetBool("IsDatabaseMode") { rows, err := d.GetRows("Sheet1") if err != nil { return err } db, err := mysqlx.GetDatabase("1") if err != nil { logger.Logger.Errorf("GetDatabase error: %v", err) return err } list := strings.Split(fileName, "_") name := ChineseToPinYin(list) if len(name) == 0 { return errors.New("tableName is empty") } tableName := fmt.Sprintf("task_%s", name[0]) files := make(map[string]string) index := make(map[string]string) for _, v := range d.Head { cl := ChineseToPinYin([]string{v})[0] files[cl] = v if strings.Contains(v, "*") { index[cl] = "INDEX" } } createSQL := buildCreateTableSQLWithIndices(tableName, list[0], files, index) if err = db.Exec(createSQL).Error; err != nil { logger.Logger.Errorf("createTable error: %v", err) return err } if err = insertData(db.DB, tableName, maps.Keys(files), rows); err != nil { logger.Logger.Errorf("insertData error: %v", err) return err } return nil } return d.SaveAs(fileName) } // 构建创建表的 SQL 语句,支持中文描述和索引 func buildCreateTableSQLWithIndices(tableName string, comment string, fields map[string]string, indices map[string]string) string { var columns []string var indexDefs []string // 遍历字段定义 for field, comment := range fields { column := fmt.Sprintf("`%s` VARCHAR(255) COMMENT '%s'", field, comment) columns = append(columns, column) // 根据索引类型添加索引定义 if indexType, ok := indices[field]; ok { switch strings.ToUpper(indexType) { case "PRIMARY": indexDefs = append(indexDefs, fmt.Sprintf("PRIMARY KEY (`%s`)", field)) case "UNIQUE": indexDefs = append(indexDefs, fmt.Sprintf("UNIQUE KEY `idx_%s` (`%s`)", field, field)) case "INDEX": indexDefs = append(indexDefs, fmt.Sprintf("KEY `idx_%s` (`%s`)", field, field)) } } } // 拼接字段和索引部分 allDefs := append(columns, indexDefs...) ret := fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n%s\n) COMMENT='%s';", tableName, strings.Join(allDefs, ",\n"), comment) logger.Logger.Tracef("createTableSQL: %s", ret) // 拼接最终的 SQL return ret } func insertData(db *gorm.DB, tableName string, header []string, rows [][]string) error { placeholders := strings.Repeat("?,", len(header)) placeholders = placeholders[:len(placeholders)-1] // 移除多余的逗号 insertSQL := fmt.Sprintf("INSERT INTO `%s` (%s) VALUES (%s)", tableName, "`"+strings.Join(header, "`,`")+"`", placeholders) for _, row := range rows { // 确保每行数据长度和表头一致 if len(row) < len(header) { for len(row) < len(header) { row = append(row, "") // 填充缺失列 } } err := db.Exec(insertSQL, interfaceSlice(row)...).Error if err != nil { return err } } return nil } func interfaceSlice(slice []string) []interface{} { result := make([]interface{}, len(slice)) for i, v := range slice { result[i] = v } return result } var args = pinyin.NewArgs() func init() { args.Style = pinyin.Normal } func joinPinyin(py [][]string) string { var result []string for _, word := range py { if len(word) > 0 { result = append(result, word[0]) // 每个字的拼音取第一个候选 } } return strings.Join(result, "_") } func ChineseToPinYin(param []string) []string { var ret []string for _, v := range param { ret = append(ret, joinPinyin(pinyin.Pinyin(v, args))) } return ret }