mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
152 lines
6.1 KiB
Vue
152 lines
6.1 KiB
Vue
<template>
|
|
<div class="relative z-[1] mx-auto flex min-h-screen max-w-[720px] flex-col px-5 pb-16 pt-[72px]">
|
|
<div class="mb-10 text-center">
|
|
<div
|
|
class="mb-5 inline-flex h-14 w-14 items-center justify-center rounded-2xl bg-accent text-xl font-extrabold tracking-tight text-white shadow-[0_8px_24px_-8px_var(--accent)]"
|
|
>
|
|
WH
|
|
</div>
|
|
<h1 class="mb-2.5 text-[34px] font-extrabold tracking-[-0.03em]">
|
|
Web<span class="text-accent">Hooker</span>
|
|
</h1>
|
|
<p class="m-0 text-[15px] leading-relaxed text-muted">
|
|
{{
|
|
lang === "zh"
|
|
? "将 GitHub webhook 事件转发到 Discord 频道,并支持在 Discord 中以你本人身份操作 GitHub。"
|
|
: "Forward GitHub webhook events to Discord, and act on GitHub from Discord as yourself."
|
|
}}
|
|
</p>
|
|
</div>
|
|
<nav class="grid gap-3">
|
|
<a
|
|
v-for="it in items"
|
|
:key="it.label"
|
|
class="flex items-center gap-4 rounded-[14px] border border-border bg-surface px-5 py-[18px] text-text no-underline shadow-card transition-all duration-150 hover:-translate-y-0.5 hover:border-border-strong hover:shadow-card-hover"
|
|
:class="
|
|
it.primary
|
|
? 'border-accent bg-accent shadow-none hover:border-accent hover:shadow-accent-lg'
|
|
: ''
|
|
"
|
|
:href="it.href"
|
|
:target="it.external ? '_blank' : undefined"
|
|
:rel="it.external ? 'noopener noreferrer' : undefined"
|
|
>
|
|
<span
|
|
class="flex h-11 w-11 flex-none items-center justify-center rounded-[11px] text-accent"
|
|
:class="it.primary ? 'bg-white/15 text-white' : 'bg-surface-2'"
|
|
v-html="icon(it.icon)"
|
|
/>
|
|
<span class="flex min-w-0 flex-1 flex-col gap-0.5">
|
|
<span class="text-[15px] font-bold" :class="it.primary ? 'text-white' : ''">{{
|
|
it.label
|
|
}}</span>
|
|
<span class="text-[13px]" :class="it.primary ? 'text-white/80' : 'text-muted'">{{
|
|
it.desc
|
|
}}</span>
|
|
</span>
|
|
<span class="flex-none text-lg" :class="it.primary ? 'text-white' : 'text-faint'">{{
|
|
it.external ? "↗" : "→"
|
|
}}</span>
|
|
</a>
|
|
</nav>
|
|
<footer class="mt-auto flex flex-wrap items-center justify-between gap-3 pt-10">
|
|
<span class="text-[13px] text-muted">WebHooker · GitHub → Discord</span>
|
|
<NuxtLink
|
|
class="rounded-full border border-border bg-surface px-3.5 py-1.5 text-[13px] text-muted no-underline transition-colors hover:border-border-strong hover:text-text"
|
|
:to="`/?lang=${altLang}`"
|
|
>{{ lang === "zh" ? "English" : "中文" }}</NuxtLink
|
|
>
|
|
</footer>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from "vue";
|
|
|
|
const DEFAULT_REPO = "https://github.com/ReCloudStudio/WebHooker";
|
|
const DEFAULT_DOCS = "https://webhooker.docs.worldexecute.me";
|
|
|
|
const route = useRoute();
|
|
const config = useRuntimeConfig();
|
|
|
|
const lang = computed(() => (route.query.lang === "en" ? "en" : "zh"));
|
|
const altLang = computed(() => (lang.value === "zh" ? "en" : "zh"));
|
|
const repo = computed(() => (config.public.repoUrl as string) || DEFAULT_REPO);
|
|
const docsBase = computed(() =>
|
|
((config.public.docsUrl as string) || DEFAULT_DOCS).replace(/\/+$/, ""),
|
|
);
|
|
|
|
const t = (zh: string, en: string): string => (lang.value === "zh" ? zh : en);
|
|
|
|
const items = computed(() => {
|
|
const docs = lang.value === "zh" ? `${docsBase.value}/zh` : `${docsBase.value}/`;
|
|
const q = (p: string): string => `${p}?lang=${lang.value}`;
|
|
return [
|
|
{
|
|
href: docs,
|
|
label: t("文档", "Documentation"),
|
|
desc: t("部署、配置与事件参考", "Deployment, configuration & event reference"),
|
|
icon: "docs",
|
|
external: true,
|
|
},
|
|
{
|
|
href: repo.value,
|
|
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 ICON_PATHS: Record<string, string> = {
|
|
docs: '<path d="M4 4a2 2 0 0 1 2-2h7l5 5v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4z"/><path d="M13 2v5h5"/><path d="M8 12h8M8 16h6"/>',
|
|
github:
|
|
'<path d="M12 2a10 10 0 0 0-3.16 19.49c.5.09.68-.22.68-.48v-1.7c-2.78.6-3.37-1.34-3.37-1.34-.45-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.9 1.53 2.36 1.09 2.94.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.94 0-1.09.39-1.98 1.03-2.68-.1-.25-.45-1.27.1-2.65 0 0 .84-.27 2.75 1.02a9.5 9.5 0 0 1 5 0c1.91-1.29 2.75-1.02 2.75-1.02.55 1.38.2 2.4.1 2.65.64.7 1.03 1.59 1.03 2.68 0 3.84-2.34 4.68-4.57 4.93.36.31.68.92.68 1.85v2.74c0 .27.18.58.69.48A10 10 0 0 0 12 2z"/>',
|
|
terms:
|
|
'<path d="M9 12h6M9 16h6M9 8h2"/><path d="M6 2h9l5 5v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2z"/>',
|
|
privacy:
|
|
'<path d="M12 2l7 3v6c0 5-3.5 8.5-7 10-3.5-1.5-7-5-7-10V5l7-3z"/><path d="M9 12l2 2 4-4"/>',
|
|
login:
|
|
'<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><path d="M10 17l5-5-5-5"/><path d="M15 12H3"/>',
|
|
};
|
|
|
|
function icon(name: string): string {
|
|
return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" width="22" height="22">${ICON_PATHS[name] ?? ""}</svg>`;
|
|
}
|
|
|
|
useHead({
|
|
title: "WebHooker",
|
|
meta: [
|
|
{
|
|
name: "description",
|
|
content:
|
|
lang.value === "zh"
|
|
? "GitHub webhook 转发到 Discord"
|
|
: "GitHub webhooks forwarded to Discord",
|
|
},
|
|
],
|
|
});
|
|
</script>
|