gva-pms/server/initialize/monitor.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() // 初始化监控配置缓存
}