This commit is contained in:
2026-05-28 14:43:13 +08:00
parent c16a8dfbc4
commit 957a594a0f
7 changed files with 353 additions and 64 deletions
+67 -19
View File
@@ -6,50 +6,98 @@ import (
"os"
"path/filepath"
"simple_portal/config"
_ "github.com/go-sql-driver/mysql"
_ "modernc.org/sqlite"
)
// DB is the global database connection pointer.
var DB *sql.DB
// InitDB initializes the SQLite database, creates the data directory,
// opens the connection, sets WAL mode, and creates default tables and data.
// InitDB 根据配置初始化数据库,支持 SQLite 和 MySQL
func InitDB() error {
dbPath := filepath.Join(".", "data", "portal.db")
dbType := config.Cfg.Database.Type
dataDir := config.Cfg.Data.Dir
// Create data directory if not exists
switch dbType {
case "mysql":
return initMySQL()
case "sqlite":
return initSQLite(dataDir)
default:
return fmt.Errorf("不支持的数据库类型: %s(可选: sqlite, mysql", dbType)
}
}
// initSQLite 初始化 SQLite 数据库
func initSQLite(dataDir string) error {
dbPath := config.GetDBPath()
// 创建数据目录
if err := os.MkdirAll(filepath.Dir(dbPath), 0755); err != nil {
return fmt.Errorf("failed to create data directory: %w", err)
return fmt.Errorf("创建数据目录失败: %w", err)
}
var err error
DB, err = sql.Open("sqlite", dbPath)
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
return fmt.Errorf("打开 SQLite 数据库失败: %w", err)
}
// SQLite requires max open conns = 1 for safe writes
// SQLite 需要限制最大连接数为 1 以保证写安全
DB.SetMaxOpenConns(1)
// Enable WAL mode for better concurrent read performance
// 启用 WAL 模式提升并发读性能
if _, err := DB.Exec("PRAGMA journal_mode=WAL"); err != nil {
return fmt.Errorf("failed to set WAL mode: %w", err)
return fmt.Errorf("设置 WAL 模式失败: %w", err)
}
// Create tables
// 创建表
if err := createTables(); err != nil {
return fmt.Errorf("failed to create tables: %w", err)
return fmt.Errorf("创建数据表失败: %w", err)
}
// Seed default data
// 初始化默认数据
if err := seedData(); err != nil {
return fmt.Errorf("failed to seed data: %w", err)
return fmt.Errorf("初始化默认数据失败: %w", err)
}
return nil
}
// createTables creates the cards, settings, and admins tables.
// initMySQL 初始化 MySQL 数据库
func initMySQL() error {
dsn := config.Cfg.Database.MySQL.GetDSN()
var err error
DB, err = sql.Open("mysql", dsn)
if err != nil {
return fmt.Errorf("打开 MySQL 数据库失败: %w", err)
}
// 测试连接
if err := DB.Ping(); err != nil {
return fmt.Errorf("连接 MySQL 失败: %w", err)
}
// MySQL 不限制最大连接数(使用默认池)
DB.SetMaxOpenConns(0)
// 创建表
if err := createTables(); err != nil {
return fmt.Errorf("创建数据表失败: %w", err)
}
// 初始化默认数据
if err := seedData(); err != nil {
return fmt.Errorf("初始化默认数据失败: %w", err)
}
return nil
}
// createTables 创建所有数据表
func createTables() error {
_, err := DB.Exec(`
CREATE TABLE IF NOT EXISTS cards (
@@ -110,9 +158,9 @@ func createTables() error {
return err
}
// seedData inserts default admin account and search engine setting if not present.
// seedData 插入默认管理员和搜索引擎配置
func seedData() error {
// Insert default admin if not exists
// 插入默认管理员
var count int
err := DB.QueryRow("SELECT COUNT(*) FROM admins WHERE username = ?", "admin").Scan(&count)
if err != nil {
@@ -129,7 +177,7 @@ func seedData() error {
}
}
// Insert default search engine setting if not exists
// 插入默认搜索引擎设置
var settingCount int
err = DB.QueryRow("SELECT COUNT(*) FROM settings WHERE key = ?", "search_engine").Scan(&settingCount)
if err != nil {
@@ -146,7 +194,7 @@ func seedData() error {
}
}
// Insert default homepage settings if not exists
// 插入默认主页设置
defaultSettings := []struct {
key string
value string
@@ -172,7 +220,7 @@ func seedData() error {
return nil
}
// CloseDB closes the database connection.
// CloseDB 关闭数据库连接
func CloseDB() error {
if DB != nil {
return DB.Close()