import type { Metadata } from "next"; import { cookies } from "next/headers"; import Link from "next/link"; import { Megaphone } from "lucide-react"; import { fetchAnnouncementsPage, fetchOverview, type Announcement } 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 Pagination from "@/components/Pagination"; import { SiteDocShell, SiteDocIdentity, SiteDocPageNav, SiteDocBreadcrumb, } from "@/components/site-doc"; export const metadata: Metadata = { title: "站点公告", description: "站点公告与通知列表", }; interface PageProps { searchParams: Promise<{ page?: string }>; } /** 粗略去掉 Markdown,取摘要 */ function plainSummary(md: string, max = 120): string { const text = md .replace(/```[\s\S]*?```/g, " ") .replace(/!\[[^\]]*\]\([^)]+\)/g, " ") .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1") .replace(/[#>*_`~\-|=]/g, "") .replace(/\s+/g, " ") .trim(); return text.length > max ? `${text.slice(0, max)}…` : text; } function FeaturedAnnouncement({ a }: { a: Announcement }) { const summary = plainSummary(a.content, 180); return (
置顶公告 {a.pinned ? 置顶 : null} {a.tag}

{a.title}

{summary ? (

{summary}

) : null} ); } function AnnouncementRow({ a, showDivider }: { a: Announcement; showDivider: boolean }) { const summary = plainSummary(a.content); return (
{a.pinned ? 置顶 : null} {a.tag}

{a.title}

{summary ? (

{summary}

) : null} ); } export default async function AnnouncementsListPage({ searchParams }: PageProps) { const sp = await searchParams; const page = Math.max(1, parseInt(sp.page || "1", 10) || 1); const size = 20; let announcements: Announcement[] = []; let total = 0; let error = ""; try { const res = await fetchAnnouncementsPage(page, size); announcements = res.announcements ?? []; total = res.total ?? 0; } catch (e) { error = e instanceof Error ? e.message : "加载公告失败"; } const cookie = authCookieHeader(await cookies()); const [overview, settings, me] = await Promise.all([ fetchOverview().catch(() => null), getPublicSettingsCached(), getMeCached(cookie || undefined), ]); const sidebarPages = overview?.sidebar_pages ?? []; const siteLead = settings.site_description?.trim() || undefined; const canManagePages = !!me.user && isAdminOrAbove(me.user.role); // 首页置顶条目作头图;其余走列表行(置顶已在头图时不再重复) const featured = page === 1 ? announcements.find((a) => a.pinned) : undefined; const rest = featured ? announcements.filter((a) => a.id !== featured.id) : announcements; const left = ; const right = ( ); return ( } >

站点公告

{error ? "加载失败" : total > 0 ? `共 ${total} 条官方通知` : "站点通知与运营公告"}

{error ? (

{error}

) : announcements.length === 0 ? (

暂无公告

有新消息时会显示在这里

) : ( <> {featured ? : null} {rest.map((a, i) => ( 0} /> ))} )}
{!error ? ( ) : null}
); }