import { prisma } from "@/lib/prisma"; import { notFound } from "next/navigation"; import Link from "next/link"; import ForumTopicRow from "@/components/forum/ForumTopicRow"; import NewTopicDialog from "@/components/forum/NewTopicDialog"; import FollowButton from "@/components/forum/FollowButton"; import { getServerSession } from "next-auth"; import { authOptions } from "@/lib/auth"; import { ArrowLeft, MessageSquare } from "lucide-react"; export const dynamic = "force-dynamic"; interface Props { params: { category: string }; searchParams: { sort?: string; page?: string }; } export default async function CategoryPage({ params, searchParams }: Props) { const session = await getServerSession(authOptions); const category = await prisma.forumCategory.findUnique({ where: { slug: params.category }, }); if (!category) notFound(); const childCategories = await prisma.forumCategory.findMany({ where: { parentId: category.id }, select: { id: true, name: true, slug: true, icon: true, topicCount: true }, orderBy: [{ sortOrder: "asc" }], }); const sort = searchParams.sort || "latest"; const page = parseInt(searchParams.page || "1", 10); const pageSize = 20; const orderBy: any = {}; if (sort === "latest") orderBy.createdAt = "desc"; else if (sort === "hot") orderBy.viewCount = "desc"; else if (sort === "active") orderBy.lastReplyAt = "desc"; else if (sort === "likes") orderBy.likeCount = "desc"; else orderBy.createdAt = "desc"; const currentUserId = session?.user?.id ? parseInt(session.user.id) : null; const [topics, totalCount, follow] = await Promise.all([ prisma.forumTopic.findMany({ where: { categoryId: category.id }, include: { category: { select: { name: true, slug: true, icon: true } }, user: { select: { id: true, name: true, email: true, avatarUrl: true, level: true, points: true, isBot: true } }, _count: { select: { posts: true } }, tags: { include: { tag: true } }, }, orderBy: [{ isPinned: "desc" }, orderBy], skip: (page - 1) * pageSize, take: pageSize, }), prisma.forumTopic.count({ where: { categoryId: category.id } }), currentUserId ? prisma.forumCategoryFollow.findUnique({ where: { categoryId_userId: { categoryId: category.id, userId: currentUserId, }, }, }) : Promise.resolve(null), ]); const sortTabs = [ { key: "latest", label: "最新" }, { key: "active", label: "活跃" }, { key: "hot", label: "热门" }, { key: "likes", label: "高赞" }, ]; return (
{/* Breadcrumb */}
返回社区
{/* Category header */}
{category.icon || "📌"}

{category.name}

· {totalCount} 帖 · {category.followerCount} 关注
{category.description && (

{category.description}

)}
{/* Sort tabs */}
{sortTabs.map((tab) => ( {tab.label} ))}
共 {totalCount} 个话题
{/* Topics list */}
{topics.length === 0 ? (

暂无话题,来发第一帖吧 ✨

) : ( topics.map((topic) => ( tt.tag), }} showCategory={false} /> )) )}
{/* Pagination */} {totalCount > pageSize && (
{page > 1 && ( 上一页 )} {Array.from( { length: Math.ceil(totalCount / pageSize) }, (_, i) => i + 1 ) .filter((p) => Math.abs(p - page) <= 2) .map((p) => ( {p} ))} {page < Math.ceil(totalCount / pageSize) && ( 下一页 )}
)}
{/* Right sidebar: sub-categories */} {childCategories.length > 0 && ( )}
); }