70 lines
2.5 KiB
TypeScript
70 lines
2.5 KiB
TypeScript
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 { canAccessAdminMessages, isStaff } from "@/lib/roles";
|
||
import AdminShell from "@/components/admin/AdminShell";
|
||
|
||
// 整个 /admin 树不进入索引(子页面无需重复声明)
|
||
export const metadata: Metadata = {
|
||
robots: { index: false, follow: false },
|
||
};
|
||
|
||
// 权限以 Go 端为唯一判定;此处仅决定管理界面是否直出。
|
||
// 允许:管理角色,或仅有消息管理/群管权限的用户(仅消息菜单可见)。
|
||
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";
|
||
|
||
const allowed =
|
||
!!me.user && (isStaff(me.user.role) || canAccessAdminMessages(me.user));
|
||
|
||
if (!allowed || !me.user) {
|
||
return (
|
||
<div
|
||
data-admin-viewport
|
||
id="main"
|
||
tabIndex={-1}
|
||
className="min-h-screen flex items-center justify-center px-4 outline-none"
|
||
>
|
||
<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>
|
||
);
|
||
}
|
||
|
||
const user = me.user;
|
||
|
||
// 未读仅在有 access cookie 时才可信;壳层铃铛用 SSR 直出避免挂载后才出红点
|
||
const unread = cookieStore.get(TOKEN_COOKIE)?.value ? me.unread_count : 0;
|
||
|
||
return (
|
||
<AdminShell
|
||
user={user}
|
||
siteName={settings.site_name || "姜十三论坛"}
|
||
initialTheme={theme}
|
||
initialUnread={unread}
|
||
>
|
||
{children}
|
||
</AdminShell>
|
||
);
|
||
}
|