Add SQLite support and install page

This commit is contained in:
2026-06-13 21:09:06 +00:00
parent a6f7852a10
commit c48a40d6da
22 changed files with 5865 additions and 219 deletions
+75 -4
View File
@@ -21,6 +21,7 @@ import (
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"gorm.io/driver/postgres"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
@@ -38,8 +39,23 @@ func main() {
}
defer logger.Sync()
// 检查是否已安装
if !cfg.Install.Installed {
logger.Info("系统未安装,启动安装模式")
startInstallMode(cfg, logger)
return
}
// 连接数据库
db, err := gorm.Open(postgres.Open(cfg.Database.DSN()), &gorm.Config{})
var db *gorm.DB
if cfg.Database.Type == "sqlite" {
// SQLite 连接
db, err = gorm.Open(sqlite.Open(cfg.Database.DSN()), &gorm.Config{})
} else {
// PostgreSQL 连接
db, err = gorm.Open(postgres.Open(cfg.Database.DSN()), &gorm.Config{})
}
if err != nil {
logger.Fatal("连接数据库失败", zap.Error(err))
}
@@ -53,6 +69,7 @@ func main() {
&models.IPChangeLog{},
&models.ConnectionLog{},
&models.IPRefreshRule{},
&models.InstallStatus{},
); err != nil {
logger.Fatal("数据库迁移失败", zap.Error(err))
}
@@ -100,7 +117,7 @@ func main() {
go startHealthCheck(ctx, repos.Node, healthChecker, logger, time.Duration(cfg.Scheduler.HealthCheckInterval)*time.Second)
// 启动 API 服务器
apiServer := NewAPIServer(cfg, repos, logger)
apiServer := NewAPIServer(cfg, repos, db, logger)
go func() {
if err := apiServer.Start(); err != nil && err != http.ErrServerClosed {
logger.Error("API 服务器错误", zap.Error(err))
@@ -128,6 +145,51 @@ func main() {
logger.Info("服务器已关闭")
}
// startInstallMode 启动安装模式
func startInstallMode(cfg *config.Config, logger *zap.Logger) {
gin.SetMode("release")
router := gin.New()
router.Use(gin.Recovery())
// 安装相关路由
api := router.Group("/api/v1")
{
api.GET("/install/check", handler.CheckInstall())
api.POST("/install", handler.DoInstall(logger))
api.GET("/install/status", handler.GetInstallStatus(nil))
}
// 静态文件服务(前端)
router.Static("/assets", "web/dist/assets")
router.StaticFile("/", "web/dist/index.html")
router.StaticFile("/favicon.ico", "web/dist/favicon.ico")
// 前端路由回退
router.NoRoute(func(c *gin.Context) {
c.File("web/dist/index.html")
})
server := &http.Server{
Addr: fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port),
Handler: router,
}
logger.Info("安装模式启动", zap.String("addr", server.Addr))
// 等待中断信号
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logger.Error("服务器错误", zap.Error(err))
}
}()
<-quit
logger.Info("安装模式关闭")
}
// SimpleAuthenticator 简单认证器
type SimpleAuthenticator struct {
userRepo *repository.UserRepository
@@ -253,18 +315,20 @@ func startHealthCheck(ctx context.Context, nodeRepo *repository.NodeRepository,
type APIServer struct {
cfg *config.Config
repos *repository.Repositories
db *gorm.DB
logger *zap.Logger
server *http.Server
router *gin.Engine
}
func NewAPIServer(cfg *config.Config, repos *repository.Repositories, logger *zap.Logger) *APIServer {
func NewAPIServer(cfg *config.Config, repos *repository.Repositories, db *gorm.DB, logger *zap.Logger) *APIServer {
gin.SetMode(cfg.Server.Mode)
router := gin.New()
server := &APIServer{
cfg: cfg,
repos: repos,
db: db,
logger: logger,
router: router,
server: &http.Server{
@@ -288,6 +352,13 @@ func (s *APIServer) setupRoutes() {
// API 路由组
api := s.router.Group("/api/v1")
{
// 安装相关
install := api.Group("/install")
{
install.GET("/check", handler.CheckInstall())
install.GET("/status", handler.GetInstallStatus(s.db))
}
// 用户相关
users := api.Group("/users")
{
@@ -342,4 +413,4 @@ func (s *APIServer) Start() error {
func (s *APIServer) Shutdown(ctx context.Context) {
s.server.Shutdown(ctx)
}
}