package initialize import ( "fmt" "github.com/flipped-aurora/gin-vue-admin/server/model/system" "github.com/flipped-aurora/gin-vue-admin/server/service/monitor_service" "gorm.io/gorm" "reflect" "time" ) // 注册全局 GORM 钩子 func RegisterGlobalHooks(db *gorm.DB) { // 注册 Update 前的全局钩子 err := db.Callback().Update().Before("gorm:update").Register("monitor:before_update", func(tx *gorm.DB) { if tx.Statement == nil || tx.Statement.Schema == nil { return } // 获取表名(兼容自定义表名) tableName := tx.Statement.Schema.Table // 检查是否有监控配置(通过缓存) monitor_service.CacheMutex.RLock() monitoredFields, ok := monitor_service.MonitorCache[tableName] monitor_service.CacheMutex.RUnlock() if !ok || len(monitoredFields) == 0 { return } // 获取主键值 pkField := tx.Statement.Schema.PrioritizedPrimaryField if pkField == nil { return } pkValue, ok := pkField.ValueOf(tx.Statement.Context, tx.Statement.ReflectValue) if !ok { return } // 查询旧记录 oldModel := reflect.New(tx.Statement.Schema.ModelType).Interface() if err := tx.Session(&gorm.Session{}).First(oldModel, pkValue).Error; err != nil { return } // 遍历监控字段,对比新旧值 for field := range monitoredFields { oldVal := getFieldValue(oldModel, field) newVal := getFieldValue(tx.Statement.Dest, field) if oldVal != newVal { // 记录变更日志 logEntry := system.SysRecordLog{ SysTableName: tableName, FieldName: field, OldValue: toString(oldVal), NewValue: toString(newVal), CreateTime: time.Now(), } tx.Create(&logEntry) } } }) if err != nil { return } } // 辅助函数:获取字段值(处理指针) func getFieldValue(model interface{}, field string) interface{} { val := reflect.ValueOf(model) if val.Kind() == reflect.Ptr { val = val.Elem() } fieldVal := val.FieldByName(field) if !fieldVal.IsValid() { return nil } if fieldVal.Kind() == reflect.Ptr || fieldVal.Kind() == reflect.Interface { if fieldVal.IsNil() { return nil } return fieldVal.Elem().Interface() } return fieldVal.Interface() } // 辅助函数:安全转换为字符串 func toString(v interface{}) string { if v == nil { return "" } val := reflect.ValueOf(v) if val.Kind() == reflect.Ptr { if val.IsNil() { return "" } return fmt.Sprintf("%v", val.Elem().Interface()) } return fmt.Sprintf("%v", v) } // 在初始化数据库时调用 func MysqlTables(db *gorm.DB) { db.AutoMigrate( // ... 其他表 system.SysMonitorConfig{}, system.SysRecordLog{}, ) RegisterGlobalHooks(db) monitor_service.InitMonitorCache() // 初始化监控配置缓存 }