package business import ( "encoding/json" "slices" "strconv" "gorm.io/gorm" ) // 旧迁移 SQL 保留日志附件 JSON。只转换有原始备份且尚未变更的旧日志,避免误映射新文件 ID。 func migrateAlertAttachments(db *gorm.DB) error { tables, err := db.Migrator().GetTables() if err != nil { return err } for _, name := range []string{"sys_alert_operation_log", "sw_kra_id_map", "bak_sw2kra_20261103_sys_alert_operation_log"} { if !slices.Contains(tables, name) { return nil } } var lastID uint64 for { var rows []struct { ID uint64 Current *string Legacy *string } if err := db.Table("sys_alert_operation_log l").Select("l.id,l.attachment_ids AS current,b.attachment_ids AS legacy").Joins("JOIN bak_sw2kra_20261103_sys_alert_operation_log b ON b.id=l.id").Where("l.id > ?", lastID).Order("l.id").Limit(500).Scan(&rows).Error; err != nil { return err } if len(rows) == 0 { return nil } pending := map[uint64][]int64{} oldIDs := []string{} for _, row := range rows { lastID = row.ID current, ids := decodeAlertAttachments(row.Current) legacy, legacyIDs := decodeAlertAttachments(row.Legacy) if len(ids) == 0 || len(legacyIDs) == 0 || !slices.Equal(current, legacy) { continue } pending[row.ID] = ids for _, id := range ids { oldIDs = append(oldIDs, strconv.FormatInt(id, 10)) } } if len(pending) == 0 { continue } mapped := map[int64]int64{} for start := 0; start < len(oldIDs); start += 500 { var mappings []struct { OldID string NewID int64 } if err := db.Table("sw_kra_id_map").Select("old_id,new_id").Where("entity = ? AND old_id IN ?", "file", oldIDs[start:min(start+500, len(oldIDs))]).Scan(&mappings).Error; err != nil { return err } for _, m := range mappings { id, err := strconv.ParseInt(m.OldID, 10, 64) if err == nil { mapped[id] = m.NewID } } } if err := db.Transaction(func(tx *gorm.DB) error { for logID, ids := range pending { newIDs := []int64{} for _, id := range ids { // 缺失旧文件原本不展示,不能把旧 ID 当成同号的新文件;原始引用仍保留在备份中。 if newID, ok := mapped[id]; ok { newIDs = append(newIDs, newID) } } raw, _ := json.Marshal(newIDs) if err := tx.Table("sys_alert_operation_log").Where("id = ?", logID).Update("attachment_ids", string(raw)).Error; err != nil { return err } } return nil }); err != nil { return err } } }