Files
SingBox-Gopanel/internal/handler/web_pages.go
CN-JS-HuiBai a3023fec39
Some checks failed
build / build (api, amd64, linux) (push) Failing after -49s
build / build (api, arm64, linux) (push) Failing after -51s
build / build (api.exe, amd64, windows) (push) Failing after -51s
修复Hybrid HTTP
2026-04-17 23:20:31 +08:00

111 lines
3.6 KiB
Go

package handler
import (
"bytes"
"encoding/json"
"html/template"
"net/http"
"path/filepath"
"strconv"
"time"
"xboard-go/internal/service"
"github.com/gin-gonic/gin"
)
type userThemeViewData struct {
Title string
Description string
Version string
Theme string
Logo string
AssetsPath string
CustomHTML template.HTML
ThemeConfigJSON template.JS
}
type adminAppViewData struct {
Title string
SettingsJS template.JS
AssetNonce string
}
func UserThemePage(c *gin.Context) {
config := map[string]any{
"accent": service.MustGetString("nebula_theme_color", "aurora"),
"slogan": service.MustGetString("nebula_hero_slogan", "One control center for login, subscriptions, sessions, and device visibility."),
"backgroundUrl": service.MustGetString("nebula_background_url", ""),
"metricsBaseUrl": service.MustGetString("nebula_metrics_base_url", ""),
"defaultThemeMode": service.MustGetString("nebula_default_theme_mode", "system"),
"lightLogoUrl": service.MustGetString("nebula_light_logo_url", ""),
"darkLogoUrl": service.MustGetString("nebula_dark_logo_url", ""),
"welcomeTarget": service.MustGetString("nebula_welcome_target", service.MustGetString("app_name", "XBoard")),
"registerTitle": service.MustGetString("nebula_register_title", "Create your access."),
"icpNo": service.MustGetString("icp_no", ""),
"psbNo": service.MustGetString("psb_no", ""),
"staticCdnUrl": service.MustGetString("nebula_static_cdn_url", ""),
"isRegisterEnabled": !service.MustGetBool("stop_register", false),
}
payload := userThemeViewData{
Title: service.MustGetString("app_name", "XBoard"),
Description: service.MustGetString("app_description", "Go rebuilt control panel"),
Version: service.MustGetString("app_version", "2.0.0"),
Theme: "Nebula",
Logo: service.MustGetString("logo", ""),
AssetsPath: "/theme/Nebula/assets",
CustomHTML: template.HTML(service.MustGetString("nebula_custom_html", "")),
ThemeConfigJSON: mustJSON(config),
}
renderPageTemplate(c, filepath.Join("frontend", "templates", "user_nebula.html"), payload)
}
func AdminAppPage(c *gin.Context) {
securePath := service.GetAdminSecurePath()
title := service.MustGetString("app_name", "XBoard") + " Admin"
settings := map[string]string{
// Keep admin API requests same-origin so reverse proxies and HTTPS termination
// don't depend on backend protocol/header inference.
"base_url": "",
"title": title,
"version": service.MustGetString("app_version", "1.0.0"),
"logo": service.MustGetString("logo", ""),
"secure_path": securePath,
}
settingsJSON, _ := json.Marshal(settings)
payload := adminAppViewData{
Title: title,
SettingsJS: template.JS(settingsJSON),
AssetNonce: strconv.FormatInt(time.Now().UnixNano(), 10),
}
renderPageTemplate(c, filepath.Join("frontend", "templates", "admin_app.html"), payload)
}
func renderPageTemplate(c *gin.Context, templatePath string, data any) {
tpl, err := template.ParseFiles(templatePath)
if err != nil {
c.String(http.StatusInternalServerError, "template parse error: %v", err)
return
}
var buf bytes.Buffer
if err := tpl.Execute(&buf, data); err != nil {
c.String(http.StatusInternalServerError, "template render error: %v", err)
return
}
c.Data(http.StatusOK, "text/html; charset=utf-8", buf.Bytes())
}
func mustJSON(value any) template.JS {
payload, err := json.Marshal(value)
if err != nil {
return template.JS("{}")
}
return template.JS(payload)
}