完善站点运营设置:分路由管理、登录可见评论、邮件模板内联与关闭注册 SSR。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-23 00:17:00 +08:00
parent acde7ee288
commit 6f054a903c
98 changed files with 8239 additions and 2073 deletions

View File

@@ -1,3 +1,4 @@
import OperationalBanner from "@/components/OperationalBanner";
import type { Metadata } from "next";
import { cookies, headers } from "next/headers";
import { Plus_Jakarta_Sans, Noto_Sans_SC, JetBrains_Mono } from "next/font/google";
@@ -22,7 +23,8 @@ import { accentStyleCSS } from "@/lib/theme";
import { bgConfigFromSettings, bgStyleCSS } from "@/lib/bg";
import { siteDocumentTitle } from "@/lib/brand";
import { motionConfigFromSettings } from "@/lib/motion";
import { requestMetadataBase } from "@/lib/canonicalMeta";
import { peekPublicMetaSnapshot, publishPublicMetaSnapshot } from "@/lib/publicMetaSnapshot";
import { metadataBaseURL } from "@/lib/siteUrl";
// 构建期下载并自托管字体:同源加载 + 自动 preload + fallback 度量校正,
// 消除 F5 时 Google CDN 字体到达后整页"由粗变细"的 FOUT 闪动
@@ -47,15 +49,16 @@ const jetbrainsMono = JetBrains_Mono({
display: "swap",
});
export async function generateMetadata(): Promise<Metadata> {
const settings = await getPublicSettingsCached();
// 必须同步:根 layout 若在此 await(拉设置 / headers),Next 流式 metadata
// 会在等待期把标签临时写成 localhost:3000,开发态 RSC/HMR 一密就来回闪。
export function generateMetadata(): Metadata {
const settings = peekPublicMetaSnapshot();
const name = settings.site_name || "姜十三论坛";
const title = siteDocumentTitle(name, settings.site_slogan || "");
const desc = settings.site_description || "姜十三论坛 - 技术分享与讨论社区";
const keywords = settings.site_keywords?.length ? settings.site_keywords : undefined;
const metadataBase = await requestMetadataBase();
const metadataBase = metadataBaseURL();
return {
// 只提供解析相对 URL 的基址;Canonical 由各公开页自行声明,避免子路由继承首页
...(metadataBase ? { metadataBase } : {}),
title: {
default: title,
@@ -63,9 +66,7 @@ export async function generateMetadata(): Promise<Metadata> {
},
description: desc,
keywords,
...(settings.favicon_url
? { icons: { icon: settings.favicon_url } }
: {}),
...(settings.favicon_url ? { icons: { icon: settings.favicon_url } } : {}),
openGraph: {
title,
description: desc,
@@ -94,6 +95,7 @@ export default async function RootLayout({
// 站点主题色(公开设置):派生浅/暗两套 accent CSS 变量后随首屏 HTML 内联,
// 覆盖 globals.css 默认令牌——无主题闪动(FOUC),后端不可用时降级为默认靛蓝
const settings = await getPublicSettingsCached();
publishPublicMetaSnapshot(settings);
const accent = settings.accent;
const accentCSS = accentStyleCSS(accent || "");
const bgCfg = bgConfigFromSettings(settings);
@@ -147,7 +149,10 @@ export default async function RootLayout({
</a>
<SiteBrandProvider initial={settings}>
<MotionProvider initial={motionCfg}>
<CommentsPolicyProvider allowComments={settings.allow_comments !== false}>
<CommentsPolicyProvider
allowComments={settings.allow_comments !== false}
requireLogin={settings.comments_require_login === true}
>
<MessagesPolicyProvider allowMessages={settings.allow_messages !== false}>
<PostLinkProvider openInNewTab={settings.post_link_new_tab !== false}>
<CodeFoldProvider
@@ -160,8 +165,8 @@ export default async function RootLayout({
unread={unread}
chatUnread={settings.allow_messages !== false ? chatUnread : 0}
theme={theme}
allowRegister={settings.allow_register}
>
<OperationalBanner />
{children}
</SiteChrome>
</CodeFoldProvider>