This commit is contained in:
2026-08-16 09:02:39 +08:00
parent c554152f4f
commit f7f6db8695
105 changed files with 2535 additions and 948 deletions
+51 -15
View File
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"kra/internal/biz"
"strconv"
"strings"
@@ -31,8 +32,11 @@ type exportTemplatePO struct {
func (exportTemplatePO) TableName() string { return "sys_export_templates" }
type exportConditionPO struct {
ID uint `gorm:"primaryKey"`
TemplateID string `gorm:"index"`
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
TemplateID string `gorm:"index"`
From string
Column string
Operator string
@@ -41,9 +45,12 @@ type exportConditionPO struct {
func (exportConditionPO) TableName() string { return "sys_export_template_condition" }
type exportJoinPO struct {
ID uint `gorm:"primaryKey"`
TemplateID string `gorm:"index"`
Join string `gorm:"column:joins"`
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
TemplateID string `gorm:"index"`
Join string `gorm:"column:joins"`
Table string
On string `gorm:"column:on"`
}
@@ -56,17 +63,17 @@ func NewExportRepo(data *Data) biz.ExportRepo { return &exportRepo{data: data} }
func exportFromPO(po exportTemplatePO, conditions []exportConditionPO, joins []exportJoinPO) *biz.ExportTemplate {
v := &biz.ExportTemplate{ID: po.ID, CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, DBName: po.DBName, Name: po.Name, TableName: po.DBTableName, TemplateID: po.TemplateID, TemplateInfo: po.TemplateInfo, SQL: po.SQL, ImportSQL: po.ImportSQL, Limit: po.Limit, Order: po.Order}
for _, x := range conditions {
v.Conditions = append(v.Conditions, biz.ExportCondition{From: x.From, Column: x.Column, Operator: x.Operator})
v.Conditions = append(v.Conditions, biz.ExportCondition{ID: x.ID, CreatedAt: x.CreatedAt, UpdatedAt: x.UpdatedAt, TemplateID: x.TemplateID, From: x.From, Column: x.Column, Operator: x.Operator})
}
for _, x := range joins {
v.Joins = append(v.Joins, biz.ExportJoin{Join: x.Join, Table: x.Table, On: x.On})
v.Joins = append(v.Joins, biz.ExportJoin{ID: x.ID, CreatedAt: x.CreatedAt, UpdatedAt: x.UpdatedAt, TemplateID: x.TemplateID, Join: x.Join, Table: x.Table, On: x.On})
}
return v
}
func exportToPO(v *biz.ExportTemplate) exportTemplatePO {
return exportTemplatePO{ID: v.ID, DBName: v.DBName, Name: v.Name, DBTableName: v.TableName, TemplateID: v.TemplateID, TemplateInfo: v.TemplateInfo, SQL: v.SQL, ImportSQL: v.ImportSQL, Limit: v.Limit, Order: v.Order}
}
func (r *exportRepo) saveRelations(tx *gorm.DB, v *biz.ExportTemplate) error {
func (r *exportRepo) saveRelations(tx *gorm.DB, v *biz.ExportTemplate, resetIDs bool) error {
if err := tx.Where("template_id = ?", v.TemplateID).Delete(&exportConditionPO{}).Error; err != nil {
return err
}
@@ -75,19 +82,45 @@ func (r *exportRepo) saveRelations(tx *gorm.DB, v *biz.ExportTemplate) error {
}
conditions := make([]exportConditionPO, 0, len(v.Conditions))
for _, x := range v.Conditions {
conditions = append(conditions, exportConditionPO{TemplateID: v.TemplateID, From: x.From, Column: x.Column, Operator: x.Operator})
id := x.ID
if resetIDs {
id = 0
}
templateID := x.TemplateID
if templateID == "" {
templateID = v.TemplateID
}
conditions = append(conditions, exportConditionPO{ID: id, CreatedAt: x.CreatedAt, UpdatedAt: x.UpdatedAt, TemplateID: templateID, From: x.From, Column: x.Column, Operator: x.Operator})
}
if len(conditions) > 0 {
if err := tx.Create(&conditions).Error; err != nil {
create := tx
if !resetIDs {
// GORM saves Create associations with ON CONFLICT DO NOTHING.
// Preserve that behavior for copied templates carrying relation IDs.
create = create.Clauses(clause.OnConflict{DoNothing: true})
}
if err := create.Create(&conditions).Error; err != nil {
return err
}
}
joins := make([]exportJoinPO, 0, len(v.Joins))
for _, x := range v.Joins {
joins = append(joins, exportJoinPO{TemplateID: v.TemplateID, Join: x.Join, Table: x.Table, On: x.On})
id := x.ID
if resetIDs {
id = 0
}
templateID := x.TemplateID
if templateID == "" {
templateID = v.TemplateID
}
joins = append(joins, exportJoinPO{ID: id, CreatedAt: x.CreatedAt, UpdatedAt: x.UpdatedAt, TemplateID: templateID, Join: x.Join, Table: x.Table, On: x.On})
}
if len(joins) > 0 {
return tx.Create(&joins).Error
create := tx
if !resetIDs {
create = create.Clauses(clause.OnConflict{DoNothing: true})
}
return create.Create(&joins).Error
}
return nil
}
@@ -98,7 +131,7 @@ func (r *exportRepo) CreateExportTemplate(ctx context.Context, v *biz.ExportTemp
return err
}
v.ID = po.ID
return r.saveRelations(tx, v)
return r.saveRelations(tx, v, false)
})
}
func (r *exportRepo) UpdateExportTemplate(ctx context.Context, v *biz.ExportTemplate) error {
@@ -107,7 +140,7 @@ func (r *exportRepo) UpdateExportTemplate(ctx context.Context, v *biz.ExportTemp
if err := tx.Model(&exportTemplatePO{}).Where("id = ?", v.ID).Updates(&po).Error; err != nil {
return err
}
return r.saveRelations(tx, v)
return r.saveRelations(tx, v, true)
})
}
func (r *exportRepo) DeleteExportTemplates(ctx context.Context, ids []uint) error {
@@ -387,7 +420,10 @@ func parseTemplateColumns(raw string) map[string]string {
return out
}
func (r *exportRepo) ImportExportRows(ctx context.Context, t *biz.ExportTemplate, rows []map[string]any) error {
sql := strings.TrimSpace(t.ImportSQL)
// ImportSQL is checked verbatim. In particular, a whitespace-only value
// is still treated as custom SQL and is allowed to return the driver's
// native error instead of silently falling back to GORM insertion.
sql := t.ImportSQL
selected, err := r.data.database(t.DBName)
if err != nil {
return err