feat: 添加安装向导功能

- 后端:安装状态检测API、数据库连接测试、配置文件生成
- 后端:支持SQLite/MySQL数据库选择
- 后端:JWT密钥自动生成或手动设置
- 前端:安装向导界面(数据库配置、安全配置、管理员账号)
- 前端:路由守卫检测安装状态,未安装自动跳转安装页面
This commit is contained in:
2026-05-03 11:52:34 +08:00
parent 507e00df52
commit 41fe48e128
8 changed files with 880 additions and 27 deletions
+90 -22
View File
@@ -30,15 +30,92 @@ var (
RDB *redis.Client
)
// Init 初始化数据库连接
func Init() {
initMySQL()
initDatabase()
initRedis()
}
// initMySQL 初始化MySQL连接
func initMySQL() {
// 尝试连接MySQL
func initDatabase() {
dbType := config.GetString("database.type")
if dbType == "" {
dbType = "auto"
}
switch dbType {
case "sqlite":
initSQLite()
case "mysql":
initMySQLExplicit()
default:
initAutoDetect()
}
}
func initSQLite() {
dbPath := "verification_platform.db"
absPath, err := filepath.Abs(dbPath)
if err != nil {
log.Fatal("Failed to get absolute path:", err.Error())
}
wd, err := os.Getwd()
if err == nil && filepath.Base(wd) == "cmd" {
absPath = filepath.Join(filepath.Dir(wd), "verification_platform.db")
}
var errOpen error
DB, errOpen = gorm.Open(sqlite.Open(absPath), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
DisableForeignKeyConstraintWhenMigrating: true,
})
if errOpen != nil {
log.Fatal("Failed to create SQLite database:", errOpen.Error())
}
log.Printf("Using SQLite database: %s\n", absPath)
if sqlDB, err := DB.DB(); err == nil {
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
sqlDB.SetConnMaxLifetime(time.Hour)
}
runMigrations()
}
func initMySQLExplicit() {
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=True&loc=Local",
config.GetString("database.username"),
config.GetString("database.password"),
config.GetString("database.host"),
config.GetString("database.port"),
config.GetString("database.name"),
config.GetString("database.charset"),
)
var err error
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
DisableForeignKeyConstraintWhenMigrating: true,
})
if err != nil {
log.Fatal("Failed to connect to MySQL:", err.Error())
}
log.Printf("Connected to MySQL: %s@%s:%s/%s\n",
config.GetString("database.username"),
config.GetString("database.host"),
config.GetString("database.port"),
config.GetString("database.name"))
if sqlDB, err := DB.DB(); err == nil {
sqlDB.SetMaxIdleConns(config.GetInt("database.max_idle_conns"))
sqlDB.SetMaxOpenConns(config.GetInt("database.max_open_conns"))
sqlDB.SetConnMaxLifetime(time.Hour)
}
runMigrations()
}
func initAutoDetect() {
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=True&loc=Local",
config.GetString("database.username"),
config.GetString("database.password"),
@@ -54,28 +131,18 @@ func initMySQL() {
DisableForeignKeyConstraintWhenMigrating: true,
})
// 如果MySQL连接失败,创建一个SQLite数据库用于开发
if err != nil {
log.Println("Failed to connect to MySQL, using SQLite database for development:", err.Error())
log.Println("Using file database for development")
dbPath := "verification_platform.db"
absPath, err := filepath.Abs(dbPath)
if err != nil {
log.Fatal("Failed to get absolute path:", err.Error())
}
wd, err := os.Getwd()
if err != nil {
log.Fatal("Failed to get working directory:", err.Error())
}
log.Printf("Working directory: %s, basename: %s\n", wd, filepath.Base(wd))
if filepath.Base(wd) == "cmd" {
dbPath = filepath.Join(filepath.Dir(wd), "verification_platform.db")
absPath = dbPath
if err == nil && filepath.Base(wd) == "cmd" {
absPath = filepath.Join(filepath.Dir(wd), "verification_platform.db")
}
DB, err = gorm.Open(sqlite.Open(absPath), &gorm.Config{
@@ -88,14 +155,16 @@ func initMySQL() {
log.Printf("Database file path: %s\n", absPath)
}
// 设置连接池(仅对非内存数据库有效)
if sqlDB, err := DB.DB(); err == nil {
sqlDB.SetMaxIdleConns(config.GetInt("database.max_idle_conns"))
sqlDB.SetMaxOpenConns(config.GetInt("database.max_open_conns"))
sqlDB.SetConnMaxLifetime(time.Hour)
}
// 检查applications表结构
runMigrations()
}
func runMigrations() {
var columns []struct {
CID int
Name string
@@ -126,7 +195,7 @@ func initMySQL() {
}
// 自动迁移数据库表
err = DB.AutoMigrate(
if err := DB.AutoMigrate(
&model.User{},
&model.AppUser{},
&model.UserLevel{},
@@ -180,8 +249,7 @@ func initMySQL() {
&model.EmailTemplate{},
&model.VersionFile{},
&model.CloudVariableRecord{},
)
if err != nil {
); err != nil {
log.Println("Failed to migrate database:", err.Error())
}