import type { Metadata } from "next";
import { cookies } from "next/headers";
import Link from "next/link";
import { PenSquare, SearchX, MessagesSquare } from "lucide-react";
import {
fetchPosts,
fetchOverview,
fetchBoardSidebar,
type OverviewResponse,
type BoardSidebarResponse,
} from "@/lib/api";
import { authCookieHeader } from "@/lib/cookies";
import { getMeCached } from "@/lib/serverData";
import Pagination from "@/components/Pagination";
import PostRow from "@/components/PostRow";
import FeedTabs, { type FeedSort } from "@/components/home/FeedTabs";
import FeedNewTip from "@/components/home/FeedNewTip";
import { WorkspaceNav, WorkspaceNavMobile } from "@/components/home/WorkspaceNav";
import { CommunityPanels, CommunityPanelsMobile } from "@/components/home/CommunityPanels";
import {
BoardPanels,
BoardPanelsMobile,
BoardMissingPanel,
} from "@/components/home/BoardPanels";
export const metadata: Metadata = {
title: "姜十三论坛 · 技术讨论社区",
description: "姜十三论坛,分享技术、讨论问题、交流心得的社区",
};
interface HomePageProps {
searchParams: Promise<{ q?: string; page?: string; sort?: string; board?: string }>;
}
function normalizeSort(v?: string): FeedSort {
if (v === "new" || v === "recommended") return v;
return "latest";
}
// 空结果面板(无帖 / 无搜索结果)
function EmptyState({ keyword }: { keyword: string }) {
return (
{keyword ? : }
{keyword ? "没有找到相关帖子" : "还没有帖子"}
{keyword ? `换个关键词试试,或者发起“${keyword}”相关的话题` : "成为第一个发起讨论的人吧"}
{keyword ? (
) : (
写新帖
)}
);
}
export default async function HomePage({ searchParams }: HomePageProps) {
const sp = await searchParams;
const keyword = sp.q?.trim() || "";
const page = Math.max(1, parseInt(sp.page || "1", 10) || 1);
const sort = normalizeSort(sp.sort);
const boardId = Math.max(0, parseInt(sp.board || "0", 10) || 0);
const isSearch = keyword.length > 0;
const cookie = authCookieHeader(await cookies());
// 与 layout 共享同一份 /me 请求(React cache 去重)
const mePromise = getMeCached(cookie || undefined);
const postsPromise = fetchPosts(
page,
20,
isSearch || boardId <= 0 ? undefined : boardId,
sort,
keyword,
sort === "recommended",
cookie
);
// 聚合面板失败不阻塞帖子流
const overviewPromise: Promise = fetchOverview(cookie).catch(() => null);
const boardSidebarPromise: Promise =
boardId > 0 && !isSearch
? fetchBoardSidebar(boardId, cookie).catch(() => null)
: Promise.resolve(null);
const [me, postsData, overview, boardSidebar] = await Promise.all([
mePromise,
postsPromise,
overviewPromise,
boardSidebarPromise,
]);
const user = me.user;
const boards = overview?.boards ?? [];
const activeBoard = boards.find((b) => b.id === boardId) || boardSidebar?.board || null;
const showBoardPanels = boardId > 0 && !isSearch;
// boardId 有效但接口失败 → 显示简卡;成功则板级右栏;否则全站右栏
const boardPanelsMissing = showBoardPanels && !boardSidebar;
// 搜索态:单栏占满,无 Tabs/侧栏
if (isSearch) {
return (
搜索“{keyword}”
共 {postsData.total} 篇结果 · 按相关度与时间排序
{postsData.posts.length > 0 ? (
postsData.posts.map((post, i) => (
))
) : (
)}
);
}
// 置顶帖直接按后端 pinned DESC 顺序并入统一信息流;标题仅供屏幕阅读器
const heading = activeBoard
? activeBoard.name
: sort === "new"
? "最新发布"
: sort === "recommended"
? "推荐帖"
: "最新讨论";
const pageQuery: Record = {};
if (boardId > 0) pageQuery.board = String(boardId);
if (sort !== "latest") pageQuery.sort = sort;
return (
{/* 中栏:tab 栏与帖子流为同一个整体卡片(左栏切板块只替换这一列) */}
{heading}
共 {postsData.total} 篇
{user && (
)}
{postsData.posts.length > 0 ? (
postsData.posts.map((post, i) => (
))
) : (
)}
0 ? pageQuery : undefined}
/>
{/* 右栏:选中板块时切板级面板,否则全站社区面板 */}
{showBoardPanels ? (
boardSidebar ? (
) : boardPanelsMissing ? (
) : null
) : (
overview && (
)
)}
{/* 窄屏:面板下沉到帖子流之后 */}
{showBoardPanels ? (
boardSidebar ? (
) : null
) : (
overview && (
)
)}
);
}