package main import ( "log" "os" "path/filepath" "strings" "github.com/gin-gonic/gin" "github.com/wmms/wmms/internal/handler" "github.com/wmms/wmms/internal/repository" "github.com/wmms/wmms/internal/service" "github.com/wmms/wmms/pkg/database" ) func main() { dsn := os.Getenv("DB_DSN") if dsn == "" { dsn = "root:1234@tcp(localhost:3306)/wmms?charset=utf8mb4&parseTime=true" } err := database.Init(dsn) if err != nil { log.Fatalf("Failed to initialize database: %v", err) } defer database.Close() if err := service.LoadRevokedSessions(); err != nil { log.Fatalf("Failed to load revoked sessions; verify database upgrade: %v", err) } // 初始化用户表并创建默认用户 if err := repository.InitUserTable(); err != nil { log.Fatalf("Failed to initialize users table: %v", err) } if err := repository.CreateDefaultUsers(); err != nil { log.Fatalf("Failed to create default users: %v", err) } // 申请表的数据库结构统一由 scripts/init.sql(空库)或增量 SQL(升级)管理; // 服务启动只校验运行所需的组织列是否已到位,缺列时报明确的升级错误,不再建表。 appRepo := repository.NewApplicationRepository() if err := appRepo.CheckApplicationSchema(); err != nil { log.Fatalf("Failed to verify applications schema: %v", err) } r := gin.Default() registerFrontendRoutes(r, "./frontend/dist") // 提供上传的文件 r.Static("/uploads", "./uploads") h := handler.NewHandler() h.RegisterRoutes(r) // WebSocket route // 建连不走中间件:浏览器先凭 JWT 与公司头调用 /api/auth/websocket-ticket 换票, // 再以 /ws?ticket=... 握手;HandleWebSocket 消费一次性票据并实时复核授权。 r.GET("/ws", handler.HandleWebSocket) // 端口可通过 APP_PORT 覆盖,默认 8082,便于试用脚本探测空闲端口。 port := os.Getenv("APP_PORT") if port == "" { port = "8082" } addr := ":" + port log.Printf("Server starting on %s", addr) log.Println("Default users: admin/admin123, user/user123") if err := r.Run(addr); err != nil { log.Fatalf("Failed to start server: %v", err) } } func registerFrontendRoutes(r *gin.Engine, distDir string) { r.Static("/web", distDir) r.Static("/assets", filepath.Join(distDir, "assets")) r.GET("/", func(c *gin.Context) { c.File(filepath.Join(distDir, "index.html")) }) r.NoRoute(func(c *gin.Context) { path := c.Request.URL.Path if c.Request.Method != "GET" || path == "/api" || strings.HasPrefix(path, "/api/") || path == "/ws" || strings.HasPrefix(path, "/uploads/") || filepath.Ext(path) != "" { c.Status(404) return } c.File(filepath.Join(distDir, "index.html")) }) }