Files
jiang13-bbs/frontend/app/admin/layout.tsx

66 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { Metadata } from "next";
import Link from "next/link";
import { cookies } from "next/headers";
import { ShieldAlert } from "lucide-react";
import { authCookieHeader, TOKEN_COOKIE } from "@/lib/cookies";
import { getMeCached, getPublicSettingsCached } from "@/lib/serverData";
import { isStaff } from "@/lib/roles";
import AdminShell from "@/components/admin/AdminShell";
// 整个 /admin 树不进入索引(子页面无需重复声明)
export const metadata: Metadata = {
robots: { index: false, follow: false },
};
// 权限以 Go 端 RequireStaff 为唯一判定;这里仅决定管理界面是否直出,
// 非管理团队访问任意 /admin/* 时 SSR 统一给出无权限提示(所有写接口仍由后端 403 兜底)。
export default async function AdminLayout({ children }: { children: React.ReactNode }) {
const cookieStore = await cookies();
const cookie = authCookieHeader(cookieStore);
const me = await getMeCached(cookie || undefined);
const settings = await getPublicSettingsCached();
const theme = cookieStore.get("j13-theme")?.value === "dark" ? "dark" : "light";
if (!me.user || !isStaff(me.user.role)) {
return (
<div
data-admin-viewport
id="main"
tabIndex={-1}
className="min-h-screen flex items-center justify-center px-4 outline-none"
style={{ background: "var(--bg)" }}
>
<div className="max-w-md w-full panel p-8 text-center">
<span
className="inline-flex w-14 h-14 rounded-full items-center justify-center mb-4"
style={{ background: "var(--gold-soft)", color: "var(--gold)" }}
>
<ShieldAlert size={26} />
</span>
<h1 className="text-lg font-extrabold" style={{ color: "var(--ink)" }}>
需要管理员权限
</h1>
<p className="meta mt-2 text-[13px]">此区域仅供站点管理员访问,如有疑问请联系站长。</p>
<Link href="/" className="btn btn-primary mt-6">
返回首页
</Link>
</div>
</div>
);
}
// 未读仅在有 access cookie 时才可信;壳层铃铛用 SSR 直出避免挂载后才出红点
const unread = cookieStore.get(TOKEN_COOKIE)?.value ? me.unread_count : 0;
return (
<AdminShell
user={me.user}
siteName={settings.site_name || "姜十三论坛"}
initialTheme={theme}
initialUnread={unread}
>
{children}
</AdminShell>
);
}