初始提交:姜十三论坛 Jiang13 Forum
轻量自用论坛,Go 单二进制 + React SPA 内嵌 + SQLite。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
73
embed_static/embed.go
Normal file
73
embed_static/embed.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package embed_static
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
//go:embed static/*
|
||||
var staticFS embed.FS
|
||||
|
||||
//go:embed templates/*
|
||||
var templatesFS embed.FS
|
||||
|
||||
// SetupEmbed 配置内嵌资源:SPA 前端 + 后台 HTML 模板
|
||||
func SetupEmbed(r *gin.Engine) error {
|
||||
tmpl, err := LoadTemplates()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.SetHTMLTemplate(tmpl)
|
||||
|
||||
// React SPA 构建产物(Vite)
|
||||
if sub, err := fs.Sub(staticFS, "static/spa/assets"); err == nil {
|
||||
r.GET("/assets/*filepath", gin.WrapH(http.StripPrefix("/assets", http.FileServer(http.FS(sub)))))
|
||||
}
|
||||
|
||||
// 后台管理遗留静态资源
|
||||
if sub, err := fs.Sub(staticFS, "static/legacy"); err == nil {
|
||||
r.GET("/legacy/*filepath", gin.WrapH(http.StripPrefix("/legacy", http.FileServer(http.FS(sub)))))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ServeSPA 返回 React SPA 入口
|
||||
func ServeSPA(c *gin.Context) {
|
||||
data, err := staticFS.ReadFile("static/spa/index.html")
|
||||
if err != nil {
|
||||
c.String(http.StatusNotFound, "前端未构建,请运行: cd frontend && npm run build")
|
||||
return
|
||||
}
|
||||
c.Data(http.StatusOK, "text/html; charset=utf-8", data)
|
||||
}
|
||||
|
||||
// IsSPARoute 判断是否应由 SPA 处理
|
||||
func IsSPARoute(path string) bool {
|
||||
if strings.HasPrefix(path, "/api") ||
|
||||
strings.HasPrefix(path, "/admin") ||
|
||||
strings.HasPrefix(path, "/uploads") ||
|
||||
strings.HasPrefix(path, "/legacy") ||
|
||||
strings.HasPrefix(path, "/assets") {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func LoadTemplates() (*template.Template, error) {
|
||||
sub, err := fs.Sub(templatesFS, "templates")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tmpl := template.New("").Funcs(template.FuncMap{
|
||||
"safeHTML": func(s string) template.HTML { return template.HTML(s) },
|
||||
"add": func(a, b int) int { return a + b },
|
||||
"sub": func(a, b int) int { return a - b },
|
||||
})
|
||||
return tmpl.ParseFS(sub, "*.html", "admin/*.html")
|
||||
}
|
||||
Reference in New Issue
Block a user