diff --git a/bj_power_mes/bj_power_mes.go b/bj_power_mes/bj_power_mes.go index 052abfc..e4aa2ea 100644 --- a/bj_power_mes/bj_power_mes.go +++ b/bj_power_mes/bj_power_mes.go @@ -4,9 +4,13 @@ import ( "bufio" "context" "crypto/subtle" + "embed" "flag" "fmt" + "io/fs" + "net/http" "os" + "path" "strings" "bj_power_mes/common/logx" @@ -22,6 +26,12 @@ import ( "github.com/zeromicro/go-zero/rest" ) +// 前端静态资源(Vue 构建产物:frontend/ npm run build 输出到 public/)。 +// 8888 一个端口同时提供管理后台页面与 API。 +// +//go:embed all:public +var webFS embed.FS + var configFile = flag.String("f", "etc/bj_power_mes-api.yaml", "the config file") // promptPassword 从终端读取一行输入(不隐藏回显,用于运维终端操作) @@ -116,6 +126,30 @@ func runResetAll(c config.Config) { fmt.Println("reset-all: 已清空并重建全部表,写入基础数据(管理员 admin/123456)。") } +// newStaticHandler 嵌入式静态文件:命中则直接返回;未命中的非 /api 路径 +// 回退到 index.html(SPA history 路由),由浏览器端 Vue Router 接管。 +func newStaticHandler(fsys embed.FS) http.Handler { + sub, err := fs.Sub(fsys, "public") + if err != nil { + panic(fmt.Sprintf("嵌入静态目录不可用: %v", err)) + } + fileServer := http.FileServer(http.FS(sub)) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + name := strings.TrimPrefix(path.Clean(r.URL.Path), "/") + if name == "" { + name = "index.html" + } + if f, openErr := sub.Open(name); openErr == nil { + f.Close() + fileServer.ServeHTTP(w, r) + return + } + r2 := r.Clone(r.Context()) + r2.URL.Path = "/" + fileServer.ServeHTTP(w, r2) + }) +} + func main() { flag.Parse() @@ -158,7 +192,19 @@ func main() { os.Exit(1) } - server := rest.MustNewServer(c.RestConf) + staticHandler := newStaticHandler(webFS) + + // 兜底路由:已注册的 /api/* 走正常匹配;未注册的非 /api 路径走嵌入式静态资源 + //(/api 下未注册的路径仍返回 404,不回退页面) + notFound := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if strings.HasPrefix(r.URL.Path, "/api/") || r.URL.Path == "/api" { + http.NotFound(w, r) + return + } + staticHandler.ServeHTTP(w, r) + }) + + server := rest.MustNewServer(c.RestConf, rest.WithNotFoundHandler(notFound)) defer server.Stop() ctx := svc.NewServiceContext(c)