feat(site): homepage 落地页 + docsify 用户手册文档站(/docs /homepage 随二进制发布)

- homepage/:品牌落地页(Hero/特性/快速开始),参考 opsxapi 站点风格,绿色品牌系
- docs/:docsify 文档站 + user-guide 十篇手册(安装/向导/采集/查询/分析/告警/授权/备份/FAQ)
- 后端 serveStaticDir 挂载 /docs 与 /homepage(可执行文件相对定位,独立于前端 dist)
This commit is contained in:
opsx committed 2026-10-29 14:04:24 +08:00
1 parent b8d08ef6d1
commit 3ea7f2dcc6
17 files changed
+605

No files matched your search

+40
View File
@@ -152,6 +152,7 @@ func SetupRouter() *gin.Engine {
system.POST("/restore/apply", systemCtrl.RestoreApply)
system.GET("/backups", systemCtrl.Backups)
system.GET("/self-check", systemCtrl.Health)
system.GET("/metrics-summary", middleware.AdminAuth(), systemCtrl.MetricsSummary)
}
// 审计日志:仅管理员可查(含他人操作记录)
@@ -235,6 +236,11 @@ func SetupRouter() *gin.Engine {
authorized.POST("/collectors/:id/preview", collectorCtrl.Preview)
authorized.GET("/collectors/:id/logs", collectorCtrl.Logs)
// 文档站(docsify,docs/)与落地页(homepage/)随二进制一起发布;
// 独立于前端 dist 存在与否注册,目录不存在时路由不生效
serveStaticDir(r, "/docs", "docs")
serveStaticDir(r, "/homepage", "homepage")
// Static files - use executable directory as base
distPath := findDistPath()
@@ -267,6 +273,40 @@ func SetupRouter() *gin.Engine {
return r
}
// serveStaticDir 把本地目录挂为只读静态站点:目录回退到 fallbackFile(SPA/docsify 需要)。
// baseDir 候选与 findDistPath 同源:可执行文件相对路径优先,再退工作目录。
func serveStaticDir(r *gin.Engine, urlPrefix, dirName string) {
root := findAuxDir(dirName)
if root == "" {
return
}
// http.FileServer 自带目录回退:访问 /docs 自动 301 到 /docs/ 并命中 index.html
r.Static(urlPrefix, root)
}
// findAuxDir 定位 dist 之外的附属静态目录(docs/homepage),规则与 findDistPath 对齐
func findAuxDir(dirName string) string {
if ex, err := os.Executable(); err == nil {
execDir := filepath.Dir(ex)
if !strings.Contains(execDir, "/tmp/go-build") {
for _, rel := range []string{dirName, "../" + dirName, "../../" + dirName} {
p := filepath.Join(execDir, rel)
if _, err := os.Stat(filepath.Join(p, "index.html")); err == nil {
return p
}
}
}
}
for _, p := range []string{"./" + dirName, "../" + dirName, "/app/" + dirName} {
if abs, err := filepath.Abs(p); err == nil {
if _, err := os.Stat(filepath.Join(abs, "index.html")); err == nil {
return abs
}
}
}
return ""
}
// findDistPath finds the frontend dist directory
func findDistPath() string {
// Try relative to executable