From 81d21ffb08051541fe1279efffce1fe6d8c50e5c Mon Sep 17 00:00:00 2001 From: RhenCloud Date: Sun, 2 Aug 2026 07:40:14 +0800 Subject: [PATCH] feat(web): add public landing page and move console to /admin Serve a public landing page at / with buttons to the docs, GitHub repo, Terms, Privacy and the admin login. Relocate the Nuxt admin console from / to /admin so the root is no longer the private console. - add home-routes.ts (bilingual landing, auto dark mode, configurable DOCS_URL / GITHUB_REPO_URL) mounted at / - move console to admin/pages/admin.vue; redirect / and unknown SPA routes to /admin - point admin login/logout redirects at /admin --- admin/pages/[...slug].vue | 2 +- admin/pages/admin.vue | 170 +++++++++++++++++++++++++++++++++ admin/pages/index.vue | 167 +-------------------------------- src/home-routes.ts | 191 ++++++++++++++++++++++++++++++++++++++ src/server.ts | 2 + src/types.ts | 2 + 6 files changed, 368 insertions(+), 166 deletions(-) create mode 100644 admin/pages/admin.vue create mode 100644 src/home-routes.ts diff --git a/admin/pages/[...slug].vue b/admin/pages/[...slug].vue index 7f716e7..eff5d5f 100644 --- a/admin/pages/[...slug].vue +++ b/admin/pages/[...slug].vue @@ -3,5 +3,5 @@ diff --git a/admin/pages/admin.vue b/admin/pages/admin.vue new file mode 100644 index 0000000..2923e7c --- /dev/null +++ b/admin/pages/admin.vue @@ -0,0 +1,170 @@ + + + diff --git a/admin/pages/index.vue b/admin/pages/index.vue index 2923e7c..eff5d5f 100644 --- a/admin/pages/index.vue +++ b/admin/pages/index.vue @@ -1,170 +1,7 @@ diff --git a/src/home-routes.ts b/src/home-routes.ts new file mode 100644 index 0000000..e76edba --- /dev/null +++ b/src/home-routes.ts @@ -0,0 +1,191 @@ +import { Hono } from "hono"; +import type { Env } from "./types"; + +type Lang = "zh" | "en"; + +const DEFAULT_REPO = "https://github.com/ReCloudStudio/WebHooker"; + +function pickLang(raw: string | undefined): Lang { + return raw === "en" ? "en" : "zh"; +} + +interface LinkItem { + href: string; + label: string; + desc: string; + icon: string; + external: boolean; + primary?: boolean; +} + +function icon(name: string): string { + const paths: Record = { + docs: '', + github: + '', + terms: + '', + privacy: + '', + login: + '', + }; + return `${paths[name] ?? ""}`; +} + +function layout(lang: Lang, repo: string, docs: string): string { + const t = (zh: string, en: string): string => (lang === "zh" ? zh : en); + const q = (p: string): string => `${p}?lang=${lang}`; + const altLang: Lang = lang === "zh" ? "en" : "zh"; + + const items: LinkItem[] = [ + { + href: docs, + label: t("文档", "Documentation"), + desc: t("部署、配置与事件参考", "Deployment, configuration & event reference"), + icon: "docs", + external: true, + }, + { + href: repo, + label: t("GitHub 仓库", "GitHub Repository"), + desc: t("源代码、问题与发布", "Source code, issues & releases"), + icon: "github", + external: true, + }, + { + href: q("/terms"), + label: t("服务条款", "Terms of Service"), + desc: t("使用本服务的条款", "The terms for using this service"), + icon: "terms", + external: false, + }, + { + href: q("/privacy"), + label: t("隐私政策", "Privacy Policy"), + desc: t("我们如何处理你的数据", "How we handle your data"), + icon: "privacy", + external: false, + }, + { + href: "/admin/login", + label: t("登录控制台", "Sign in to Console"), + desc: t("管理路由与分组", "Manage routes and groups"), + icon: "login", + external: false, + primary: true, + }, + ]; + + const cards = items + .map((it) => { + const attrs = it.external ? ' target="_blank" rel="noopener noreferrer"' : ""; + return ` + ${icon(it.icon)} + + ${it.label} + ${it.desc} + + ${it.external ? "↗" : "→"} +`; + }) + .join("\n"); + + return ` + + + + + +WebHooker + + + + + +
+
+
WH
+

WebHooker

+

${t( + "将 GitHub webhook 事件转发到 Discord 频道,并支持在 Discord 中以你本人身份操作 GitHub。", + "Forward GitHub webhook events to Discord, and act on GitHub from Discord as yourself.", + )}

+
+ + +
+ +`; +} + +export function createHomeRoutes(): Hono<{ Bindings: Env }> { + const app = new Hono<{ Bindings: Env }>(); + + app.get("/", (c) => { + const lang = pickLang(c.req.query("lang")); + const repo = c.env.GITHUB_REPO_URL ?? DEFAULT_REPO; + const docs = c.env.DOCS_URL ?? `${repo}#readme`; + return c.html(layout(lang, repo, docs)); + }); + + return app; +} diff --git a/src/server.ts b/src/server.ts index 2f538d0..8ef9cb6 100644 --- a/src/server.ts +++ b/src/server.ts @@ -6,6 +6,7 @@ import { createOAuthRoutes } from "./oauth-routes"; import { createActionRoutes } from "./action-routes"; import { createAdminRoutes } from "./admin-routes"; import { createLegalRoutes } from "./legal-routes"; +import { createHomeRoutes } from "./home-routes"; import { log } from "./log"; const MAX_BODY_SIZE = 1024 * 1024; @@ -18,6 +19,7 @@ export function createServer(): Hono<{ Bindings: Env }> { app.route("/auth", createOAuthRoutes()); app.route("/", createActionRoutes()); app.route("/", createLegalRoutes()); + app.route("/", createHomeRoutes()); app.route("/admin", createAdminRoutes()); app.post("/webhook", async (c) => { diff --git a/src/types.ts b/src/types.ts index 743aa4a..62db692 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,6 +10,8 @@ export interface Env { ADMIN_USER_IDS?: string; DISCORD_GATEWAY_ENABLED?: string; LEGAL_CONTACT?: string; + DOCS_URL?: string; + GITHUB_REPO_URL?: string; ASSETS?: Fetcher; KV: KVNamespace; DISCORD_GATEWAY: DurableObjectNamespace;