Files
jiang13-bbs/frontend/components/sidebar/registry.tsx
freefire 4f3f3a265c feat: 友链/书库/移动端导航/排行榜等多模块功能
新增模块:
- 友链(friendlink)后端处理 + 前端管理页与友链板
- 书库(library):导入、章节、封面、阅读页、横竖版自适应 AdaptiveCoverSlot
- 顶栏导航(header_nav)配置与 MobileTabBar/MobileRailDrawers 移动端抽屉
- 排行榜 service 测试、站点页面测试、时间线发布(timeline_release)

其它改动:
- 后端 handlers/services 全量小幅调整
- 前端组件、库函数、URL/品牌/站点 URL 工具更新
- Lightbox 图片、MdEntries 条目卡、coverColor 派生色相等前端能力
2026-09-30 16:30:07 +08:00

167 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type {
ActiveUser,
AnnouncementSummary,
Board,
BoardModerator,
BoardSidebarStats,
BoardWithCount,
CheckinStatus,
FriendLink,
NewUser,
OverviewStats,
PostListItem,
PublicAdItem,
PublicSponsorItem,
SidebarPageItem,
User,
UserProfile,
} from "@/lib/api";
import PostToc, { type TocItem } from "@/components/PostToc";
import { WorkspaceNavPanel } from "@/components/home/WorkspaceNav";
import {
PulseCard,
Announcements,
AdsPanel,
SponsorsPanel,
HotRanking,
NewUsers,
ActiveUsers,
FriendLinks,
AboutSite,
} from "@/components/home/CommunityPanels";
import {
Moderators,
BoardIntro,
BoardPulse,
BoardHot,
BoardActive,
} from "@/components/home/BoardPanels";
import {
BoardCard as PostBoardCard,
AuthorRailCard as PostAuthorCard,
AuthorPosts as PostAuthorPosts,
} from "@/components/post/PostRailBlocks";
// 侧栏块 props 汇总:页面把已有数据整包传入,块按需取用;
// 某块所需数据缺失(如板块态没传 stats)时对应块渲染为空,安全跳过。
export interface SidebarBlockProps {
allowComments: boolean;
user?: User | null;
checkin?: CheckinStatus | null;
// home 范围
boards?: BoardWithCount[];
stats?: OverviewStats;
announcements?: AnnouncementSummary[];
canManageAnnouncements?: boolean;
ads?: PublicAdItem[];
adsPanelTitle?: string;
adsEnabled?: boolean;
sponsors?: PublicSponsorItem[];
sponsorsPanelTitle?: string;
sponsorsEnabled?: boolean;
hot?: PostListItem[];
newUsers?: NewUser[];
activeUsers?: ActiveUser[];
friendLinks?: FriendLink[];
sidebarPages?: SidebarPageItem[];
siteDescription?: string;
canManagePages?: boolean;
// board 范围
board?: BoardWithCount;
moderators?: BoardModerator[];
boardStats?: BoardSidebarStats;
boardHot?: PostListItem[];
boardActiveUsers?: ActiveUser[];
// post 范围
postBoard?: Board;
authorProfile?: UserProfile;
authorPosts?: PostListItem[];
toc?: TocItem[];
// 板块 id → 名称/配色下标:板块管理员徽章展示「{板块名}板块管理员」并对齐板块色
boardNames?: Record<number, string>;
boardColors?: Record<number, number>;
}
// 内置块注册表:key → 组件。数据未就绪或未知 key 返回 null(渲染层静默跳过)。
export function renderSidebarBlock(key: string, p: SidebarBlockProps) {
switch (key) {
case "board_nav":
return p.boards ? <WorkspaceNavPanel boards={p.boards} user={p.user} /> : null;
case "pulse":
return p.stats ? (
<PulseCard stats={p.stats} checkin={p.checkin} allowComments={p.allowComments} />
) : null;
case "announcements":
return p.announcements ? (
<Announcements items={p.announcements} canManageAnnouncements={p.canManageAnnouncements} />
) : null;
case "ads":
return p.ads && p.adsEnabled !== false ? (
<AdsPanel items={p.ads} title={p.adsPanelTitle || "自助推广"} enabled />
) : null;
case "sponsors":
return p.sponsors && p.sponsorsEnabled !== false ? (
<SponsorsPanel
items={p.sponsors}
title={p.sponsorsPanelTitle || "赞助商"}
enabled
/>
) : null;
case "hot":
return p.hot ? <HotRanking posts={p.hot} allowComments={p.allowComments} /> : null;
case "new_users":
return p.newUsers ? <NewUsers users={p.newUsers} /> : null;
case "active_users":
return p.activeUsers ? (
<ActiveUsers users={p.activeUsers} allowComments={p.allowComments} />
) : null;
case "friend_links":
// 空列表也渲染(保留申请入口);显隐由侧栏布局配置控制
return <FriendLinks links={p.friendLinks ?? []} />;
case "about_site":
return p.sidebarPages || p.canManagePages ? (
<AboutSite
pages={p.sidebarPages ?? []}
siteDescription={p.siteDescription}
canManagePages={p.canManagePages}
/>
) : null;
case "board_moderators":
return p.moderators ? <Moderators items={p.moderators} /> : null;
case "board_intro":
return p.board ? <BoardIntro board={p.board} /> : null;
case "board_pulse":
return p.boardStats ? (
<BoardPulse stats={p.boardStats} checkin={p.checkin} allowComments={p.allowComments} />
) : null;
case "board_hot":
return p.boardHot ? (
<BoardHot posts={p.boardHot} allowComments={p.allowComments} />
) : null;
case "board_active":
return p.boardActiveUsers ? (
<BoardActive users={p.boardActiveUsers} allowComments={p.allowComments} />
) : null;
case "post_board":
return p.postBoard ? <PostBoardCard board={p.postBoard} /> : null;
case "post_author":
return p.authorProfile ? (
<PostAuthorCard
profile={p.authorProfile}
allowComments={p.allowComments}
boardNames={p.boardNames}
boardColors={p.boardColors}
/>
) : null;
case "post_author_posts":
return p.authorPosts ? <PostAuthorPosts posts={p.authorPosts} /> : null;
case "post_toc":
return p.toc && p.toc.length > 0 ? <PostToc items={p.toc} /> : null;
default:
return null;
}
}