feat: 新增管理员用户管理功能与账号封禁体系
此提交完成了全站管理员后台核心功能开发: 1. 新增AdminUserService与管理接口,支持用户列表查询、角色变更与封禁解封 2. 重构认证链路,统一账号封禁错误码与处理逻辑 3. 新增全局强制下线机制,账号被封禁时自动弹出告知弹窗并清理登录态 4. 重构管理员后台路由与布局,统一权限校验逻辑 5. 优化通知轮询逻辑,页面切回前台时立即刷新未读计数 6. 合并原公告、外观管理页到统一后台面板
This commit is contained in:
53
frontend/app/admin/layout.tsx
Normal file
53
frontend/app/admin/layout.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { cookies } from "next/headers";
|
||||
import { ShieldAlert } from "lucide-react";
|
||||
import { authCookieHeader } from "@/lib/cookies";
|
||||
import { getMeCached } from "@/lib/serverData";
|
||||
import { AdminSidebar, AdminNavMobile } from "./AdminNav";
|
||||
|
||||
// 整个 /admin 树不进入索引(子页面无需重复声明)
|
||||
export const metadata: Metadata = {
|
||||
robots: { index: false, follow: false },
|
||||
};
|
||||
|
||||
// 权限以 Go 端 RequireAdmin 为唯一判定;这里仅决定管理界面是否直出,
|
||||
// 非管理员访问任意 /admin/* 时 SSR 统一给出无权限提示(所有写接口仍由后端 403 兜底)。
|
||||
export default async function AdminLayout({ children }: { children: React.ReactNode }) {
|
||||
const cookie = authCookieHeader(await cookies());
|
||||
const me = await getMeCached(cookie || undefined);
|
||||
|
||||
if (me.user?.role !== "admin") {
|
||||
return (
|
||||
<div className="max-w-md mx-auto panel p-8 text-center mt-6 lg:mt-10">
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<AdminNavMobile />
|
||||
<div className="flex items-start gap-6 xl:gap-7">
|
||||
<aside className="hidden lg:block w-60 xl:w-64 shrink-0">
|
||||
<div className="sticky" style={{ top: 84 }}>
|
||||
<AdminSidebar user={me.user} />
|
||||
</div>
|
||||
</aside>
|
||||
<section className="flex-1 min-w-0">{children}</section>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user