118 lines
2.7 KiB
Go
118 lines
2.7 KiB
Go
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 "<nil>"
|
|
}
|
|
|
|
val := reflect.ValueOf(v)
|
|
if val.Kind() == reflect.Ptr {
|
|
if val.IsNil() {
|
|
return "<nil>"
|
|
}
|
|
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() // 初始化监控配置缓存
|
|
}
|