feat: 首页 Go SSR 与 React hydrate 同构,消壳层与帖行闪动

补齐侧栏/右栏图标与徽章、鉴权种子、StaticFeedList,并修正嵌套 a 与标题徽章对齐。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-01 07:07:38 +08:00
parent 9e134916a4
commit 44eed97fe0
26 changed files with 2530 additions and 159 deletions

View File

@@ -0,0 +1,43 @@
import type { User } from '../api/types';
/** 首页 SSR boot 注入的鉴权种子(consumeHomeBoot 写入;AuthProvider 仅 peek,保留至下次 boot) */
let seededUser: User | null | undefined;
let seededUnread = 0;
let hasAuthSeed = false;
/** 未读数可被 MainLayout 同步读取 */
let bootUnread = 0;
export function seedAuthFromHomeBoot(user: User | null | undefined, unread: number) {
hasAuthSeed = true;
seededUser = user ?? null;
seededUnread = Math.max(0, unread | 0);
bootUnread = seededUnread;
}
type AuthSeed = { hasSeed: boolean; user: User | null; unread: number };
/** 只读种子,不清空(StrictMode 双挂 / useState initializer 可重复调用) */
export function peekAuthSeed(): AuthSeed {
if (!hasAuthSeed) {
return { hasSeed: false, user: null, unread: bootUnread };
}
return { hasSeed: true, user: seededUser ?? null, unread: seededUnread };
}
/** mount 后清除用户种子,避免后续误用 */
export function clearAuthSeed() {
hasAuthSeed = false;
seededUser = undefined;
seededUnread = 0;
}
/** @deprecated 改用 peekAuthSeed + clearAuthSeed;保留兼容 */
export function takeAuthSeed(): AuthSeed {
const s = peekAuthSeed();
if (s.hasSeed) clearAuthSeed();
return s;
}
export function getBootUnread(): number {
return bootUnread;
}