package main import ( "log" "github.com/gin-gonic/gin" "github.com/gouki/lunar-server/internal/config" "github.com/gouki/lunar-server/internal/handler" "github.com/gouki/lunar-server/internal/middleware" "github.com/gouki/lunar-server/internal/service" "github.com/joho/godotenv" ) // 版本信息由 CI 通过 ldflags 注入: // -X main.Version=... -X main.BuildTime=... -X main.CommitSha=... var ( Version = "dev" BuildTime = "unknown" CommitSha = "unknown" ) func main() { // 加载本地环境变量文件(生产环境由容器注入,忽略缺失;../.env.local 兼容从 server/ 目录启动) _ = godotenv.Load(".env.local", "../.env.local", ".env") // 将构建时注入的版本信息传递给 handler handler.Version = Version handler.BuildTime = BuildTime handler.CommitSha = CommitSha log.Printf("lunar-server %s (commit %s, built at %s)", Version, CommitSha, BuildTime) // 加载配置 cfg := config.Load() // 初始化数据库 if err := config.InitDB(cfg); err != nil { log.Fatalf("Failed to initialize database: %v", err) } // 启动机器人许愿定时任务 wishService := service.NewWishService() wishService.StartRobotWishJob() // 设置运行模式 if cfg.Server.Env == "production" { gin.SetMode(gin.ReleaseMode) } // 创建路由(gin.Default 自带访问日志与 Recovery) r := gin.Default() // 中间件 r.Use(middleware.CORS()) // 静态文件与管理后台模板 r.Static("/static", "./web/static") r.StaticFile("/", "./web/index.html") r.LoadHTMLFiles("./web/index.html") // API 路由 api := r.Group("/api") { // 版本信息(无需认证) api.GET("/version", handler.GetVersion) // 用户相关 user := api.Group("/user") { user.POST("/login", handler.UserLogin) user.POST("/logout", handler.UserLogout) user.GET("/profile", middleware.Auth(), handler.GetUserProfile) user.PUT("/profile", middleware.Auth(), handler.UpdateUserProfile) user.POST("/auth", handler.WechatAuth) } // 支付相关 pay := api.Group("/pay") { pay.POST("/create", middleware.Auth(), handler.CreateOrder) pay.POST("/notify", handler.PayNotify) pay.GET("/status/:orderId", handler.GetPayStatus) } // 订单相关 order := api.Group("/order") { order.GET("/list", middleware.Auth(), handler.GetOrderList) order.GET("/:id", middleware.Auth(), handler.GetOrderDetail) order.POST("/cancel/:id", middleware.Auth(), handler.CancelOrder) } // 许愿相关 wish := api.Group("/wish") { wish.GET("/trees", handler.GetWishTrees) wish.GET("/tree", handler.GetWishTree) wish.GET("/tree/:id/wishes", handler.GetTreeWishes) wish.POST("/create", middleware.Auth(), handler.CreateWish) wish.GET("/list", handler.GetWishList) wish.GET("/:id", handler.GetWishDetail) wish.DELETE("/:id", middleware.Auth(), handler.DeleteWish) wish.GET("/products", handler.GetWishProducts) } } // 管理后台路由(Inertia.js) admin := r.Group("/admin") { // 登录/登出接口无需认证;未配置 ADMIN_PASSWORD 时登录返回 503 admin.POST("/login", handler.AdminLogin) admin.POST("/logout", handler.AdminLogout) authed := admin.Group("") authed.Use(middleware.AdminAuth()) { authed.GET("/", handler.AdminDashboard) authed.GET("/users", handler.AdminUsers) authed.GET("/orders", handler.AdminOrders) authed.GET("/wishes", handler.AdminWishes) authed.GET("/settings", handler.AdminSettings) } } // 启动服务器 addr := ":" + cfg.Server.Port log.Printf("Server starting on %s", addr) if err := r.Run(addr); err != nil { log.Fatalf("Failed to start server: %v", err) } }