package main import ( "errors" "flag" "fmt" "log" "net/http" "time" "goalfymax-admin/internal/api/routes" "goalfymax-admin/internal/config" "goalfymax-admin/internal/jobs" "goalfymax-admin/internal/models" "goalfymax-admin/internal/notifier" "goalfymax-admin/internal/services" "goalfymax-admin/internal/storage" "goalfymax-admin/pkg/middleware" "goalfymax-admin/pkg/redis" "goalfymax-admin/pkg/utils" "github.com/gin-gonic/gin" "go.uber.org/zap" ) func main() { // 解析命令行参数 var configPath string flag.StringVar(&configPath, "config", "", "配置文件路径(可选,优先级最高)") var env string flag.StringVar(&env, "env", "dev", "运行环境(dev/test/prod等)") flag.Parse() // 加载配置 // 根据env推导配置文件路径(当未显式指定 --config 时) if configPath == "" { // 优先匹配 etc/config-.yaml,不存在则回退 etc/config.yaml guessed := fmt.Sprintf("etc/config-%s.yaml", env) if err := config.LoadConfig(guessed); err != nil { // 回退默认 if err2 := config.LoadConfig("etc/config.yaml"); err2 != nil { log.Fatalf("加载配置失败: %v (fallback error: %v)", err, err2) } } } else if err := config.LoadConfig(configPath); err != nil { log.Fatalf("加载配置失败: %v", err) } cfg := config.GetConfig() // 初始化日志 logger, err := utils.NewLogger(cfg.Log.Level, cfg.Log.Format, cfg.Log.Output) if err != nil { log.Fatalf("初始化日志失败: %v", err) } logger.Info("应用启动中...") // 初始化通知服务 notifier.Init(cfg.Alert, env, logger) // 初始化数据库 if err := storage.InitDatabase(logger); err != nil { logger.Fatal("初始化数据库失败", zap.Error(err)) } // 自动迁移数据库 if err := storage.AutoMigrate(); err != nil { logger.Fatal("数据库迁移失败", zap.Error(err)) } // 初始化PostgreSQL(用于 MCP 配置) if err := storage.InitPostgres(logger); err != nil { logger.Warn("PostgreSQL初始化失败,MCP配置将不可用", zap.Error(err)) } else { logger.Info("PostgreSQL初始化完成") } logger.Info("数据库初始化完成") // 初始化Redis客户端 redisClient, err := redis.NewClient(cfg.Redis) if err != nil { logger.Warn("Redis初始化失败,余额查询功能将不可用", zap.Error(err)) redisClient = nil // 设置为nil,服务会优雅处理 } else { logger.Info("Redis初始化完成") defer redisClient.Close() } // 创建服务实例 ssoAdminService := services.NewSSOAdminService() userService := services.NewUserService( storage.NewUserStorage(), storage.NewRBACStorage(), storage.NewGoalfyMaxUserStorage(), utils.NewJWTManager("your-jwt-secret"), logger, ssoAdminService, ) roleService := services.NewRoleService( storage.NewRoleStorage(), logger, ) pageService := services.NewPageService( storage.NewPageStorage(), logger, ) // 创建网关客户端和配额服务 gatewayClient := services.NewGatewayClient( cfg.Gateway.BaseURL, time.Duration(cfg.Gateway.Timeout)*time.Second, logger, ) quotaService := services.NewQuotaService(gatewayClient, logger) // 创建SSO客户端和SSO服务 ssoConfig := &models.SSOConfig{ SSOServerURL: cfg.SSO.SSOServerURL, ClientID: cfg.SSO.ClientID, ClientSecret: cfg.SSO.ClientSecret, RedirectURI: cfg.SSO.RedirectURI, Scope: cfg.SSO.Scope, ResourceAud: cfg.SSO.ResourceAud, Timeout: cfg.SSO.Timeout, } // 创建RBAC服务 rbacService := services.NewRBACService( storage.NewRBACStorage(), storage.NewUserStorage(), logger, ) ssoClient := middleware.NewSSOClient(ssoConfig, logger) ssoService := services.NewSSOService( ssoClient, storage.NewPKCEStateStorage(), storage.NewLoginInfoStorage(), rbacService, logger, ) // 创建用户等级配置服务 userLevelConfigService := services.NewUserLevelConfigService( storage.NewUserLevelConfigStorage(), logger, ) // 创建系统配置服务 systemConfigService := services.NewSystemConfigService( storage.NewSystemConfigStorage(), logger, ) // 设置路由 router := routes.SetupRoutes( userService, roleService, pageService, quotaService, ssoService, rbacService, userLevelConfigService, systemConfigService, redisClient, logger, cfg, ) // 启动定时任务 jobs.StartMcpUsageBalanceScheduler(cfg.Jobs.McpUsageBalance, logger) jobs.StartModelTokenBalanceScheduler(cfg.Jobs.ModelTokenBalance, logger) // 启动HTTP服务器 startHTTPServer(cfg, router, logger) } // startHTTPServer 启动HTTP服务器 func startHTTPServer(cfg *config.Config, router *gin.Engine, logger *utils.Logger) { // 构建服务器地址 addr := fmt.Sprintf("%s:%d", cfg.Server.Addr, cfg.Server.Port) // 启动服务器 server := &http.Server{ Addr: addr, Handler: router, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 60 * time.Second, } logger.Info("HTTP服务器启动", zap.String("addr", addr)) logger.Info("应用启动完成") // 启动服务器 if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { logger.Fatal("HTTP服务器启动失败", zap.Error(err)) } }