package initialize import ( "os" "wails-app/internal/dao" "go.uber.org/zap" "gorm.io/gorm" "wails-app/internal/global" "wails-app/internal/model/example" ) func Gorm() *gorm.DB { switch global.GVA_CONFIG.System.DbType { case "mysql": return GormMysql() case "pgsql": return GormPgSql() case "oracle": return GormOracle() case "mssql": return GormMssql() case "sqlite": return GormSqlite() default: return GormMysql() } } func RegisterTables() { db := global.GVA_DB err := db.AutoMigrate( dao.SysApi{}, dao.SysUser{}, dao.SysBaseMenu{}, dao.JwtBlacklist{}, dao.SysAuthority{}, dao.SysDictionary{}, dao.SysOperationRecord{}, dao.SysDictionaryDetail{}, dao.SysBaseMenuParameter{}, dao.SysBaseMenuBtn{}, dao.SysAuthorityBtn{}, example.ExaFile{}, example.ExaFileChunk{}, dao.ExaFileUploadAndDownload{}, dao.Vehicle{}, dao.VehicleType{}, dao.Owner{}, dao.FeeConfig{}, dao.Booth{}, dao.Channel{}, dao.ParkingLot{}, dao.VehicleRecord{}, dao.PaymentRecord{}, dao.PaymentMethodConfig{}, dao.PaymentEntryConfig{}, dao.PaymentEntryMethod{}, dao.UHFReader{}, dao.Camera{}, dao.Shortlist{}, dao.MonthlyCard{}, dao.DigitalTicket{}, dao.ShiftRecord{}, dao.Printer{}, ) if err != nil { global.GVA_LOG.Error("register table failed", zap.Error(err)) os.Exit(0) } if err := reconcileParkingLotOccupancy(db); err != nil { global.GVA_LOG.Error("reconcile parking lot occupancy failed", zap.Error(err)) } // 操作日志复合索引:created_at 位于 GVA_MODEL 内嵌字段(多表共用,不能加 tag),故显式创建 // 覆盖高频查询:按用户 + 时间筛选操作日志 if err := db.Exec("CREATE INDEX IF NOT EXISTS idx_op_user_time ON sys_operation_records (user_id, created_at)").Error; err != nil { global.GVA_LOG.Error("create idx_op_user_time failed", zap.Error(err)) } global.GVA_LOG.Info("register table success") } // reconcileParkingLotOccupancy 在服务启动时以未出场停车会话为准校准占用数和余位。 func reconcileParkingLotOccupancy(db *gorm.DB) error { return db.Transaction(func(tx *gorm.DB) error { var lots []dao.ParkingLot if err := tx.Find(&lots).Error; err != nil { return err } for _, lot := range lots { var occupied int64 if err := tx.Model(&dao.VehicleRecord{}). Where("parking_lot_id = ? AND exit_time IS NULL", lot.ID). Count(&occupied).Error; err != nil { return err } available := int64(lot.Capacity) - occupied if available < 0 { available = 0 } if err := tx.Model(&lot).UpdateColumns(map[string]interface{}{ "occupied": occupied, "available": available, }).Error; err != nil { return err } } return nil }) }