package database import ( "log" "os" "psi/config" "psi/models" "psi/utils" "time" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" ) var DB *gorm.DB func Init() { cfg := config.AppConfig var err error // 使用MySQL驱动连接数据库,开启慢查询日志(>=200ms) slowLogger := logger.New( log.New(os.Stdout, "\r\n", log.LstdFlags), logger.Config{ SlowThreshold: 200 * time.Millisecond, // 慢SQL阈值 LogLevel: logger.Warn, // 只输出警告和错误 IgnoreRecordNotFoundError: true, // 忽略RecordNotFound Colorful: false, }, ) DB, err = gorm.Open(mysql.Open(cfg.GetDSN()), &gorm.Config{ Logger: slowLogger, }) if err != nil { log.Fatal("数据库连接失败:", err) } // 获取底层的 sql.DB 对象以配置连接池 sqlDB, err := DB.DB() if err != nil { log.Fatal("获取数据库连接失败:", err) } // 设置连接池参数 sqlDB.SetMaxIdleConns(50) // 最大空闲连接数(提升以减少连接建立开销) sqlDB.SetMaxOpenConns(200) // 最大打开连接数(提升以应对高并发) sqlDB.SetConnMaxLifetime(30 * time.Minute) // 连接最大生命周期(30分钟) sqlDB.SetConnMaxIdleTime(5 * time.Minute) // 连接最大空闲时间(5分钟,减少频繁创建连接) err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工表'").AutoMigrate(&models.Employee{}) if err != nil { log.Fatal("Employee表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='书籍信息表'").AutoMigrate(&models.BookInfo{}) if err != nil { log.Fatal("BookInfo表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户表'").AutoMigrate(&models.Customer{}) if err != nil { log.Fatal("Customer表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存表'").AutoMigrate(&models.Inventory{}) if err != nil { log.Fatal("Inventory表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存明细表'").AutoMigrate(&models.InventoryDetail{}) if err != nil { log.Fatal("InventoryDetail表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存流水表'").AutoMigrate(&models.InventoryLog{}) if err != nil { log.Fatal("InventoryLog表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库位表'").AutoMigrate(&models.Location{}) if err != nil { log.Fatal("Location表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='产品分类表'").AutoMigrate(&models.ProductCategory{}) if err != nil { log.Fatal("ProductCategory表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='产品表'").AutoMigrate(&models.Product{}) if err != nil { log.Fatal("Product表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='产品单位转换表'").AutoMigrate(&models.ProductUnitConversion{}) if err != nil { log.Fatal("ProductUnitConversion表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='产品序列号表'").AutoMigrate(&models.ProductSerial{}) if err != nil { log.Fatal("ProductSerial表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='采购订单主表'").AutoMigrate(&models.PurchaseOrder{}) if err != nil { log.Fatal("PurchaseOrder表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='采购订单明细表'").AutoMigrate(&models.PurchaseOrderItem{}) if err != nil { log.Fatal("PurchaseOrderItem表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='打印任务表'").AutoMigrate(&models.PrintTask{}) if err != nil { log.Fatal("PrintTask表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='打印日志表'").AutoMigrate(&models.PrintLog{}) if err != nil { log.Fatal("PrintLog表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='入库单主表'").AutoMigrate(&models.ReceivingOrder{}) if err != nil { log.Fatal("ReceivingOrder表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='入库单明细表'").AutoMigrate(&models.ReceivingOrderItem{}) if err != nil { log.Fatal("ReceivingOrderItem表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供应商表'").AutoMigrate(&models.Supplier{}) if err != nil { log.Fatal("Supplier表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售订单主表'").AutoMigrate(&models.SalesOrder{}) if err != nil { log.Fatal("SalesOrder表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售订单明细表'").AutoMigrate(&models.SalesOrderItem{}) if err != nil { log.Fatal("SalesOrderItem表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='仓库表'").AutoMigrate(&models.Warehouse{}) if err != nil { log.Fatal("Warehouse表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='波次单主表'").AutoMigrate(&models.WaveHeader{}) if err != nil { log.Fatal("WaveHeader表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='波次任务表'").AutoMigrate(&models.WaveTask{}) if err != nil { log.Fatal("WaveTask表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='波次任务明细表'").AutoMigrate(&models.WaveTaskDetail{}) if err != nil { log.Fatal("WaveTaskDetail表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='小车表'").AutoMigrate(&models.Car{}) if err != nil { log.Fatal("Car表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='小车店铺关联表'").AutoMigrate(&models.CarShop{}) if err != nil { log.Fatal("CarShop表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='店铺表'").AutoMigrate(&models.Shop{}) if err != nil { log.Fatal("Shop表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工等级表'").AutoMigrate(&models.EmployeeLevel{}) if err != nil { log.Fatal("EmployeeLevel表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工等级日志表'").AutoMigrate(&models.EmployeeLevelLog{}) if err != nil { log.Fatal("EmployeeLevelLog表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工配置表'").AutoMigrate(&models.EmployeeSettings{}) if err != nil { log.Fatal("EmployeeSettings表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='盘库单主表'").AutoMigrate(&models.StockCheck{}) if err != nil { log.Fatal("StockCheck表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='盘库单明细表'").AutoMigrate(&models.StockCheckItem{}) if err != nil { log.Fatal("StockCheckItem表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='外部任务表'").AutoMigrate(&models.OutTask{}) if err != nil { log.Fatal("OutTask表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='外部任务异常日志表'").AutoMigrate(&models.OutTaskLog{}) if err != nil { log.Fatal("OutTaskLog表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='出库单主表'").AutoMigrate(&models.OutboundOrder{}) if err != nil { log.Fatal("OutboundOrder表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='出库单明细表'").AutoMigrate(&models.OutboundOrderItem{}) if err != nil { log.Fatal("OutboundOrderItem表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发货单主表'").AutoMigrate(&models.ShippingOrder{}) if err != nil { log.Fatal("ShippingOrder表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发货单明细表'").AutoMigrate(&models.ShippingOrderItem{}) if err != nil { log.Fatal("ShippingOrderItem表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运费模板表'").AutoMigrate(&models.Logistics{}) if err != nil { log.Fatal("Logistics表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品日志表'").AutoMigrate(&models.ProductLog{}) if err != nil { log.Fatal("ProductLog表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户类型表'").AutoMigrate(&models.UserType{}) if err != nil { log.Fatal("UserType表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户映射表'").AutoMigrate(&models.UserMapping{}) if err != nil { log.Fatal("UserMapping表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='分账配置表'").AutoMigrate(&models.SplitAccountConfig{}) if err != nil { log.Fatal("SplitAccountConfig表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='分账扣钱日志表'").AutoMigrate(&models.SplitAccountDeductionLog{}) if err != nil { log.Fatal("SplitAccountDeductionLog表迁移失败:", err) } err = DB.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置表'").AutoMigrate(&models.Config{}) if err != nil { log.Fatal("Config表迁移失败:", err) } // 初始化商品表 InitProductBookTables() // 初始化默认管理员账号 createDefaultAdmin() // 初始化任务数据库 InitTaskDB() // 打印连接信息 log.Println("MySQL数据库连接成功:", cfg.Database.Host, cfg.Database.Name) } func createDefaultAdmin() { var count int64 DB.Model(&models.Employee{}).Where("role = ?", 255).Count(&count) if count == 0 { // 创建默认管理员账号:账号init_00000,密码admin123 hashedPassword, _ := utils.HashPassword("admin123") admin := models.Employee{ EmployeeIDStr: "00000", Username: "init_00000", Password: hashedPassword, Name: "系统管理员", Role: 255, Score: 0, Status: 1, Fid: 0, AboutId: 0, From: "system", CreatedAt: time.Now().Unix(), UpdatedAt: time.Now().Unix(), } DB.Create(&admin) log.Println("已创建默认管理员账号: init_00000 / admin123") } }