优化结构
This commit is contained in:
@@ -191,12 +191,103 @@ func (r *exportRepo) QueryExport(ctx context.Context, t *system.ExportTemplate,
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
var rows []map[string]any
|
||||
preview := query.ToSQL(func(tx *gorm.DB) *gorm.DB { return tx.Find(&[]map[string]any{}) })
|
||||
err = query.Find(&rows).Error
|
||||
rows, err := queryExportRows(query)
|
||||
return rows, preview, err
|
||||
}
|
||||
|
||||
func queryExportRows(query *gorm.DB) ([]map[string]any, error) {
|
||||
rows, err := query.Rows()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
columns, err := rows.Columns()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
columnTypes, err := rows.ColumnTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]map[string]any, 0)
|
||||
for rows.Next() {
|
||||
values := make([]any, len(columns))
|
||||
destinations := make([]any, len(values))
|
||||
for index := range values {
|
||||
destinations[index] = &values[index]
|
||||
}
|
||||
if err := rows.Scan(destinations...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item := make(map[string]any, len(columns))
|
||||
for index, column := range columns {
|
||||
typeName := ""
|
||||
if index < len(columnTypes) {
|
||||
typeName = columnTypes[index].DatabaseTypeName()
|
||||
}
|
||||
item[column] = exportQueryValue(values[index], typeName)
|
||||
}
|
||||
result = append(result, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func exportQueryValue(value any, databaseType string) any {
|
||||
bytesValue, ok := value.([]byte)
|
||||
if !ok {
|
||||
return value
|
||||
}
|
||||
raw := string(bytesValue)
|
||||
typeName := strings.ToUpper(databaseType)
|
||||
if strings.Contains(typeName, "INT") || strings.Contains(typeName, "SERIAL") {
|
||||
if integer, err := strconv.ParseInt(raw, 10, 64); err == nil {
|
||||
return integer
|
||||
}
|
||||
}
|
||||
if strings.Contains(typeName, "DECIMAL") || strings.Contains(typeName, "NUMERIC") || strings.Contains(typeName, "NUMBER") || strings.Contains(typeName, "REAL") || strings.Contains(typeName, "DOUBLE") || strings.Contains(typeName, "FLOAT") {
|
||||
if decimal, ok := exactExportFloat(raw); ok {
|
||||
return decimal
|
||||
}
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
func exactExportFloat(value string) (float64, bool) {
|
||||
decimal, err := strconv.ParseFloat(value, 64)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
return decimal, normalizeDecimal(value) == normalizeDecimal(strconv.FormatFloat(decimal, 'f', -1, 64))
|
||||
}
|
||||
|
||||
func normalizeDecimal(value string) string {
|
||||
value = strings.TrimSpace(value)
|
||||
negative := strings.HasPrefix(value, "-")
|
||||
value = strings.TrimPrefix(value, "+")
|
||||
value = strings.TrimPrefix(value, "-")
|
||||
parts := strings.SplitN(value, ".", 2)
|
||||
whole := strings.TrimLeft(parts[0], "0")
|
||||
if whole == "" {
|
||||
whole = "0"
|
||||
}
|
||||
fraction := ""
|
||||
if len(parts) == 2 {
|
||||
fraction = strings.TrimRight(parts[1], "0")
|
||||
}
|
||||
result := whole
|
||||
if fraction != "" {
|
||||
result += "." + fraction
|
||||
}
|
||||
if negative && result != "0" {
|
||||
result = "-" + result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func exportColumns(raw string) ([]string, error) {
|
||||
columns := make([]string, 0)
|
||||
decoder := json.NewDecoder(strings.NewReader(raw))
|
||||
@@ -338,17 +429,6 @@ func (r *exportRepo) PreviewExport(ctx context.Context, t *system.ExportTemplate
|
||||
}
|
||||
return query.ToSQL(func(tx *gorm.DB) *gorm.DB { return tx.Find(&[]map[string]any{}) }), nil
|
||||
}
|
||||
func parseTemplateColumns(raw string) map[string]string {
|
||||
out := map[string]string{}
|
||||
parts := strings.Split(strings.Trim(strings.TrimSpace(raw), "{}"), ",")
|
||||
for _, part := range parts {
|
||||
pair := strings.SplitN(part, ":", 2)
|
||||
if len(pair) == 2 {
|
||||
out[strings.Trim(strings.TrimSpace(pair[0]), `"`)] = strings.Trim(strings.TrimSpace(pair[1]), `"`)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
func (r *exportRepo) ImportExportRows(ctx context.Context, t *system.ExportTemplate, rows []map[string]any) error {
|
||||
if err := system.ValidateExportTemplate(t); err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user