后台可注入全站 CSS/JS(SSR 生效,CSS 可热换);发帖/编辑改为锁一屏工作室;经济看板增加存量健康度;主题令牌与弹层误关一并收紧。 Co-authored-by: Cursor <cursoragent@cursor.com>
157 lines
4.7 KiB
TypeScript
157 lines
4.7 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { cookies } from "next/headers";
|
|
import Link from "next/link";
|
|
import { Info } from "lucide-react";
|
|
import {
|
|
fetchPublishedSitePages,
|
|
fetchOverview,
|
|
type SitePageSummary,
|
|
} from "@/lib/api";
|
|
import { authCookieHeader } from "@/lib/cookies";
|
|
import { getMeCached, getPublicSettingsCached } from "@/lib/serverData";
|
|
import { isAdminOrAbove } from "@/lib/roles";
|
|
import { formatDate } from "@/lib/format";
|
|
import { pageGlyph } from "@/lib/pageGlyph";
|
|
import {
|
|
SiteDocShell,
|
|
SiteDocIdentity,
|
|
SiteDocAnnoNav,
|
|
SiteDocBreadcrumb,
|
|
} from "@/components/site-doc";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "关于本站",
|
|
description: "站点说明、政策与帮助文档",
|
|
};
|
|
|
|
function PageRow({
|
|
p,
|
|
showDivider,
|
|
}: {
|
|
p: SitePageSummary;
|
|
showDivider: boolean;
|
|
}) {
|
|
const Icon = pageGlyph(p.slug);
|
|
return (
|
|
<Link
|
|
href={`/p/${p.slug}`}
|
|
className="block px-5 sm:px-6 py-4 sm:py-5 transition-colors hover:bg-[var(--panel-2)] focus-visible:bg-[var(--panel-2)]"
|
|
style={showDivider ? { borderTop: "1px solid var(--line)" } : undefined}
|
|
>
|
|
<div className="flex items-start gap-3 min-w-0">
|
|
<span
|
|
className="w-9 h-9 rounded-lg flex items-center justify-center shrink-0 mt-0.5"
|
|
style={{ background: "var(--accent-soft)", color: "var(--accent)" }}
|
|
aria-hidden
|
|
>
|
|
<Icon size={16} strokeWidth={2} />
|
|
</span>
|
|
<span className="min-w-0 flex-1">
|
|
<span className="flex items-center gap-2 flex-wrap">
|
|
<h2
|
|
className="text-[16px] sm:text-[17px] font-semibold leading-snug tracking-tight"
|
|
style={{ color: "var(--ink)" }}
|
|
>
|
|
{p.title}
|
|
</h2>
|
|
<time className="meta text-[12px] tabular-nums ml-auto" dateTime={p.updated_at}>
|
|
{formatDate(p.updated_at || p.created_at)}
|
|
</time>
|
|
</span>
|
|
{p.excerpt ? (
|
|
<p className="mt-1.5 text-[13.5px] leading-relaxed line-clamp-2" style={{ color: "var(--ink-2)" }}>
|
|
{p.excerpt}
|
|
</p>
|
|
) : null}
|
|
</span>
|
|
</div>
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
export default async function AboutIndexPage() {
|
|
const cookie = authCookieHeader(await cookies());
|
|
let pages: SitePageSummary[] = [];
|
|
let error = "";
|
|
try {
|
|
const res = await fetchPublishedSitePages();
|
|
pages = res.pages ?? [];
|
|
} catch (e) {
|
|
error = e instanceof Error ? e.message : "加载页面失败";
|
|
}
|
|
|
|
const [overview, settings, me] = await Promise.all([
|
|
fetchOverview().catch(() => null),
|
|
getPublicSettingsCached(),
|
|
getMeCached(cookie || undefined),
|
|
]);
|
|
const announcements = overview?.announcements ?? [];
|
|
const siteLead = settings.site_description?.trim() || undefined;
|
|
const canManagePages = !!me.user && isAdminOrAbove(me.user.role);
|
|
|
|
const left = <SiteDocIdentity kind="about" lead={siteLead} />;
|
|
const right = <SiteDocAnnoNav items={announcements} />;
|
|
|
|
return (
|
|
<SiteDocShell
|
|
left={left}
|
|
right={right}
|
|
breadcrumb={
|
|
<SiteDocBreadcrumb
|
|
items={[
|
|
{ href: "/", label: "首页" },
|
|
{ label: "关于本站" },
|
|
]}
|
|
/>
|
|
}
|
|
mobileExtras={
|
|
announcements.length > 0 ? <SiteDocAnnoNav items={announcements} /> : null
|
|
}
|
|
>
|
|
<header className="mb-5 flex items-end justify-between gap-3">
|
|
<div>
|
|
<h1
|
|
className="text-[24px] sm:text-[28px] font-extrabold tracking-tight flex items-center gap-2"
|
|
style={{ color: "var(--ink)" }}
|
|
>
|
|
<Info size={26} style={{ color: "var(--accent)" }} aria-hidden />
|
|
关于本站
|
|
</h1>
|
|
<p className="meta mt-2">
|
|
{error
|
|
? "加载失败"
|
|
: pages.length > 0
|
|
? `共 ${pages.length} 篇站点文档`
|
|
: "站点说明与政策文档"}
|
|
</p>
|
|
</div>
|
|
{canManagePages ? (
|
|
<Link
|
|
href="/admin/pages"
|
|
className="meta text-[13px] shrink-0 mb-0.5 transition-colors hover:text-[var(--accent)]"
|
|
>
|
|
管理
|
|
</Link>
|
|
) : null}
|
|
</header>
|
|
|
|
{error ? (
|
|
<p className="alert-error">{error}</p>
|
|
) : pages.length === 0 ? (
|
|
<div className="panel p-10 text-center">
|
|
<p className="font-medium" style={{ color: "var(--ink)" }}>
|
|
暂无介绍
|
|
</p>
|
|
<p className="meta mt-1.5">有新文档时会显示在这里</p>
|
|
</div>
|
|
) : (
|
|
<div className="panel overflow-hidden">
|
|
{pages.map((p, i) => (
|
|
<PageRow key={p.id} p={p} showDivider={i > 0} />
|
|
))}
|
|
</div>
|
|
)}
|
|
</SiteDocShell>
|
|
);
|
|
}
|