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,
type OverviewResponse,
} 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 { WorkspaceNav, WorkspaceNavMobile } from "@/components/home/WorkspaceNav";
import { CommunityPanels, CommunityPanelsMobile } from "@/components/home/CommunityPanels";
export const metadata: Metadata = {
title: "姜十三论坛 · 技术讨论社区",
description: "姜十三论坛,分享技术、讨论问题、交流心得的社区",
};
interface HomePageProps {
searchParams: Promise<{ q?: string; page?: string; sort?: string; board?: string }>;
}
function normalizeSort(v?: string): FeedSort {
return v === "hot" || v === "recommended" ? v : "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 === "recommended" ? "hot" : sort,
keyword,
sort === "recommended",
cookie
);
// 聚合面板失败不阻塞帖子流
const overviewPromise: Promise = fetchOverview(cookie).catch(() => null);
const [me, postsData, overview] = await Promise.all([
mePromise,
postsPromise,
overviewPromise,
]);
const user = me.user;
const boards = overview?.boards ?? [];
const activeBoard = boards.find((b) => b.id === boardId) || null;
// 搜索态:单栏占满,无 Tabs/侧栏
if (isSearch) {
return (
搜索“{keyword}”
共 {postsData.total} 篇结果 · 按相关度与时间排序
{postsData.posts.length > 0 ? (
postsData.posts.map((post, i) => (
))
) : (
)}
);
}
// 置顶帖直接按后端 pinned DESC 顺序并入统一信息流,同样的行布局
const heading = activeBoard
? activeBoard.name
: sort === "hot"
? "热门讨论"
: sort === "recommended"
? "精华内容"
: "最新讨论";
const headingHint = activeBoard
? sort === "hot"
? "该板块按点赞与评论热度排序"
: sort === "recommended"
? "该板块管理员精选的优质内容"
: "该板块新发帖与新评论都会浮到顶部"
: sort === "hot"
? "按点赞与评论热度排序"
: sort === "recommended"
? "管理员精选的优质内容"
: "新发帖与新评论都会浮到顶部";
const pageQuery: Record = {};
if (boardId > 0) pageQuery.board = String(boardId);
if (sort !== "latest") pageQuery.sort = sort;
return (
{/* 中栏:帖子流(左栏切板块只替换这一列) */}
{heading}
共 {postsData.total} 篇 · {headingHint}
{postsData.posts.length > 0 ? (
postsData.posts.map((post, i) => (
))
) : (
)}
0 ? pageQuery : undefined}
/>
{/* 右栏:社区面板 */}
{overview && (
)}
{/* 窄屏:面板下沉到帖子流之后 */}
{overview && (
)}
);
}