package router import ( "io/fs" "net/http" "strings" "github.com/gin-gonic/gin" "gorm.io/gorm" "git.sundynix.cn/Blizzard/sundynix-site/server/internal/handler" "git.sundynix.cn/Blizzard/sundynix-site/server/internal/middleware" "git.sundynix.cn/Blizzard/sundynix-site/server/internal/pkg/resp" "git.sundynix.cn/Blizzard/sundynix-site/server/internal/webfs" ) func New(db *gorm.DB) (*gin.Engine, error) { r := gin.New() r.Use(gin.Logger(), gin.Recovery(), middleware.CORS()) // ── 公开 API ── api := r.Group("/api") { api.GET("/healthz", func(c *gin.Context) { resp.OK(c, gin.H{"status": "ok"}) }) posts := handler.NewPostHandler(db) api.GET("/posts", posts.List) api.GET("/posts/:slug", posts.Get) } // ── 管理端 API ── adminAuth := handler.NewAdminAuthHandler() api.POST("/admin/login", adminAuth.Login) adminAPI := api.Group("/admin", middleware.Auth()) { posts := handler.NewAdminPostHandler(db) adminAPI.GET("/posts", posts.List) adminAPI.POST("/posts", posts.Create) adminAPI.GET("/posts/:id", posts.Get) adminAPI.PUT("/posts/:id", posts.Update) adminAPI.DELETE("/posts/:id", posts.Delete) } // ── 静态站点:/admin → 管理端,其余 → 用户端 ── webDist, err := webfs.WebDist() if err != nil { return nil, err } adminDist, err := webfs.AdminDist() if err != nil { return nil, err } webServer := http.FileServer(http.FS(webDist)) adminServer := http.StripPrefix("/admin", http.FileServer(http.FS(adminDist))) r.NoRoute(func(c *gin.Context) { path := c.Request.URL.Path if strings.HasPrefix(path, "/api/") { resp.NotFound(c, "接口不存在") return } if path == "/admin" || strings.HasPrefix(path, "/admin/") { serveSPA(c, adminDist, adminServer, strings.TrimPrefix(path, "/admin"), "/admin/") return } serveSPA(c, webDist, webServer, path, "/") }) return r, nil } // serveSPA 真实文件直接吐,否则回退 index.html 交给前端路由。 func serveSPA(c *gin.Context, dist fs.FS, server http.Handler, rel, fallback string) { p := strings.TrimPrefix(rel, "/") if p != "" { if _, err := fs.Stat(dist, p); err == nil { server.ServeHTTP(c.Writer, c.Request) return } } c.Request.URL.Path = fallback server.ServeHTTP(c.Writer, c.Request) }