package database import ( "database/sql" "fmt" "os" "path/filepath" "sync" "ssq-desk/internal/storage/models" "gorm.io/driver/sqlite" "gorm.io/gorm" _ "modernc.org/sqlite" // 使用纯 Go 的 SQLite 驱动(不需要 CGO) ) var ( sqliteDB *gorm.DB sqliteOnce sync.Once ) // InitSQLite 初始化 SQLite 连接 func InitSQLite() (*gorm.DB, error) { var err error sqliteOnce.Do(func() { // 获取应用数据目录 homeDir, err2 := os.UserHomeDir() if err2 != nil { err = fmt.Errorf("获取用户目录失败: %v", err2) return } // 创建数据目录 dataDir := filepath.Join(homeDir, ".ssq-desk") if err2 := os.MkdirAll(dataDir, 0755); err2 != nil { err = fmt.Errorf("创建数据目录失败: %v", err2) return } // SQLite 数据库文件路径 dbPath := filepath.Join(dataDir, "ssq.db") // 直接使用 database/sql 打开连接,确保使用 modernc.org/sqlite(纯 Go,不需要 CGO) sqlDB, err2 := sql.Open("sqlite", dbPath) if err2 != nil { err = fmt.Errorf("SQLite 打开连接失败: %v", err2) sqliteDB = nil return } // 测试连接 if err2 = sqlDB.Ping(); err2 != nil { err = fmt.Errorf("SQLite 连接测试失败: %v", err2) sqlDB.Close() sqliteDB = nil return } // 使用已打开的 database/sql 连接创建 GORM 实例 // 使用 sqlite.Dialector 并指定连接 sqliteDB, err2 = gorm.Open(sqlite.Dialector{Conn: sqlDB}, &gorm.Config{}) if err2 != nil { err = fmt.Errorf("SQLite GORM 初始化失败: %v", err2) sqlDB.Close() sqliteDB = nil return } // 自动迁移表结构(如果表已存在但结构不对,AutoMigrate 会尝试修改) // 如果表结构完全不匹配,可能需要手动删除旧表 err2 = sqliteDB.AutoMigrate( &models.SsqHistory{}, &models.Authorization{}, &models.Version{}, ) if err2 != nil { err = fmt.Errorf("SQLite 表迁移失败: %v", err2) sqliteDB = nil return } }) if err != nil { return nil, err } return sqliteDB, nil } // GetSQLite 获取 SQLite 连接实例 // 如果连接未初始化或初始化失败,返回 nil func GetSQLite() *gorm.DB { if sqliteDB == nil { db, err := InitSQLite() if err != nil { // 初始化失败,返回 nil return nil } sqliteDB = db } return sqliteDB }