From 1eaf3903d447d024c26eb6ad55adc8eca6b1ab84 Mon Sep 17 00:00:00 2001 From: freefire Date: Sat, 12 Sep 2026 04:30:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=A4=A7=E9=87=8F?= =?UTF-8?q?=E7=A4=BE=E5=8C=BA=E5=8A=9F=E8=83=BD=E4=B8=8E=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=EF=BC=8C=E4=BC=98=E5=8C=96=E7=AB=99=E7=82=B9?= =?UTF-8?q?=E6=95=B4=E4=BD=93=E4=BD=93=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增事件总线式toast通知系统 - 新增头像、阅读进度、404/500错误页等基础组件 - 重构页脚、布局、分页、点赞按钮等现有组件 - 新增用户个人页、通知中心、帖子编辑/发布/置顶/推荐管理功能 - 优化登录注册页面样式与交互 - 修复路径类型文件引用,更新站点元信息与字体配置 --- frontend/app/board/[id]/page.tsx | 151 ++++--- frontend/app/compose/page.tsx | 88 ++-- frontend/app/error.tsx | 45 ++ frontend/app/globals.css | 488 ++++++++++++++++++++-- frontend/app/layout.tsx | 29 +- frontend/app/login/page.tsx | 53 ++- frontend/app/not-found.tsx | 32 ++ frontend/app/notifications/page.tsx | 108 +++-- frontend/app/page.tsx | 255 +++++++---- frontend/app/post/[id]/edit/page.tsx | 63 +-- frontend/app/post/[id]/page.tsx | 114 +++-- frontend/app/register/page.tsx | 59 ++- frontend/app/settings/page.tsx | 67 +-- frontend/app/u/[id]/UserProfileClient.tsx | 178 ++++---- frontend/app/u/[id]/page.tsx | 120 +++--- frontend/components/Avatar.tsx | 35 ++ frontend/components/CommentSection.tsx | 147 ++++--- frontend/components/FeaturePost.tsx | 95 +++++ frontend/components/Footer.tsx | 32 +- frontend/components/Header.tsx | 316 ++++++++++---- frontend/components/Icons.tsx | 84 ++++ frontend/components/LikeButton.tsx | 47 ++- frontend/components/NotificationBell.tsx | 119 +++--- frontend/components/Pagination.tsx | 36 +- frontend/components/PinnedPosts.tsx | 91 ++++ frontend/components/PostActions.tsx | 68 ++- frontend/components/PostRow.tsx | 91 ++++ frontend/components/ReadingProgress.tsx | 37 ++ frontend/components/Toaster.tsx | 66 +++ frontend/lib/toast.ts | 17 + frontend/next-env.d.ts | 4 +- 31 files changed, 2395 insertions(+), 740 deletions(-) create mode 100644 frontend/app/error.tsx create mode 100644 frontend/app/not-found.tsx create mode 100644 frontend/components/Avatar.tsx create mode 100644 frontend/components/FeaturePost.tsx create mode 100644 frontend/components/Icons.tsx create mode 100644 frontend/components/PinnedPosts.tsx create mode 100644 frontend/components/PostRow.tsx create mode 100644 frontend/components/ReadingProgress.tsx create mode 100644 frontend/components/Toaster.tsx create mode 100644 frontend/lib/toast.ts diff --git a/frontend/app/board/[id]/page.tsx b/frontend/app/board/[id]/page.tsx index 7d7f385..16e4005 100644 --- a/frontend/app/board/[id]/page.tsx +++ b/frontend/app/board/[id]/page.tsx @@ -1,9 +1,11 @@ import Link from "next/link"; -import { Metadata } from "next"; +import type { Metadata } from "next"; import { cookies } from "next/headers"; +import { PenSquare, MessagesSquare, ChevronRight } from "lucide-react"; import { fetchPosts, fetchBoards } from "@/lib/api"; import Pagination from "@/components/Pagination"; -import LikeButton from "@/components/LikeButton"; +import PostRow from "@/components/PostRow"; +import PinnedPosts from "@/components/PinnedPosts"; interface PageProps { params: Promise<{ id: string }>; @@ -15,7 +17,7 @@ export async function generateMetadata({ params }: PageProps): Promise const { boards } = await fetchBoards(); const board = boards.find((b) => b.id === Number(id)); return { - title: board ? `${board.name} - 姜十三论坛` : "板块 - 姜十三论坛", + title: board ? `${board.name} · 姜十三论坛` : "板块 · 姜十三论坛", description: board?.description || "板块帖子列表", }; } @@ -29,62 +31,111 @@ export default async function BoardPage({ params, searchParams }: PageProps) { fetchPosts(page, 20, Number(id), "latest", "", cookie), fetchBoards(), ]); - const board = boardsData.boards.find((b) => b.id === Number(id)); + const boardIndex = boardsData.boards.findIndex((b) => b.id === Number(id)); + const board = boardIndex >= 0 ? boardsData.boards[boardIndex] : null; + + // 第一页:置顶帖独立成区,列表只保留非置顶 + const pinned = page === 1 ? postsData.posts.filter((p) => p.pinned > 0) : []; + const rows = page === 1 ? postsData.posts.filter((p) => p.pinned <= 0) : postsData.posts; return (
-