From a8f6ce4e4f8bb89c7a2826f44294b5c5c6a58c49 Mon Sep 17 00:00:00 2001 From: freefire Date: Sat, 12 Sep 2026 01:35:37 +0800 Subject: [PATCH] =?UTF-8?q?refactor(frontend):=20=E5=AE=8C=E5=96=84SSR?= =?UTF-8?q?=E9=89=B4=E6=9D=83=E4=B8=8E=E7=82=B9=E8=B5=9E=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 修正类型文件导入路径到.dev目录 2. 为API请求添加cookie传递支持,实现SSR用户登录态识别 3. 重构LikeButton组件,新增compact变体适配列表页展示 4. 调整首页和板块页的帖子列表布局,添加点赞按钮 5. 拆分帖子列表点击区域,优化交互体验 --- frontend/app/board/[id]/page.tsx | 33 +++++++++++++++----------- frontend/app/page.tsx | 37 ++++++++++++++++++------------ frontend/app/post/[id]/page.tsx | 4 +++- frontend/components/LikeButton.tsx | 11 ++++++--- frontend/lib/api.ts | 27 +++++++++++++++++----- frontend/next-env.d.ts | 4 ++-- 6 files changed, 76 insertions(+), 40 deletions(-) diff --git a/frontend/app/board/[id]/page.tsx b/frontend/app/board/[id]/page.tsx index e6504a4..7d7f385 100644 --- a/frontend/app/board/[id]/page.tsx +++ b/frontend/app/board/[id]/page.tsx @@ -1,7 +1,9 @@ import Link from "next/link"; import { Metadata } from "next"; +import { cookies } from "next/headers"; import { fetchPosts, fetchBoards } from "@/lib/api"; import Pagination from "@/components/Pagination"; +import LikeButton from "@/components/LikeButton"; interface PageProps { params: Promise<{ id: string }>; @@ -22,8 +24,9 @@ export default async function BoardPage({ params, searchParams }: PageProps) { const { id } = await params; const { page: pageStr } = await searchParams; const page = Math.max(1, parseInt(pageStr || "1", 10) || 1); + const cookie = (await cookies()).toString(); const [postsData, boardsData] = await Promise.all([ - fetchPosts(page, 20, Number(id)), + fetchPosts(page, 20, Number(id), "latest", "", cookie), fetchBoards(), ]); const board = boardsData.boards.find((b) => b.id === Number(id)); @@ -41,10 +44,9 @@ export default async function BoardPage({ params, searchParams }: PageProps) {
{postsData.posts.map((post) => ( -
@@ -55,16 +57,21 @@ export default async function BoardPage({ params, searchParams }: PageProps) { 推荐 )}
-

{post.title}

-
- - {post.user.nickname} - - {new Date(post.created_at).toLocaleDateString("zh-CN")} - 💬 {post.comment_count} - 👁 {post.view_count} + +

{post.title}

+ +
+
+ + {post.user.nickname} + + {new Date(post.created_at).toLocaleDateString("zh-CN")} + 💬 {post.comment_count} + 👁 {post.view_count} +
+
- +
))} {postsData.posts.length === 0 && (

diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index b0138a1..d35df34 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -1,7 +1,9 @@ import Link from "next/link"; import { Metadata } from "next"; +import { cookies } from "next/headers"; import { fetchPosts, fetchBoards } from "@/lib/api"; import Pagination from "@/components/Pagination"; +import LikeButton from "@/components/LikeButton"; export const metadata: Metadata = { title: "姜十三论坛 - 技术分享与讨论社区", @@ -21,8 +23,9 @@ export default async function HomePage({ searchParams }: HomePageProps) { const { q, page: pageStr } = await searchParams; const keyword = q?.trim() || ""; const page = Math.max(1, parseInt(pageStr || "1", 10) || 1); + const cookie = (await cookies()).toString(); const [postsData, boardsData] = await Promise.all([ - fetchPosts(page, 20, undefined, "latest", keyword), + fetchPosts(page, 20, undefined, "latest", keyword, cookie), fetchBoards(), ]); @@ -35,10 +38,9 @@ export default async function HomePage({ searchParams }: HomePageProps) {

{postsData.posts.map((post) => ( -
@@ -55,18 +57,23 @@ export default async function HomePage({ searchParams }: HomePageProps) { 推荐 )}
-

- {post.title} -

-
- - {post.user.nickname} - - {new Date(post.created_at).toLocaleDateString("zh-CN")} - 💬 {post.comment_count} - 👁 {post.view_count} + +

+ {post.title} +

+ +
+
+ + {post.user.nickname} + + {new Date(post.created_at).toLocaleDateString("zh-CN")} + 💬 {post.comment_count} + 👁 {post.view_count} +
+
- +
))} {postsData.posts.length === 0 && (

diff --git a/frontend/app/post/[id]/page.tsx b/frontend/app/post/[id]/page.tsx index 92ae184..5034dc3 100644 --- a/frontend/app/post/[id]/page.tsx +++ b/frontend/app/post/[id]/page.tsx @@ -1,5 +1,6 @@ import { Metadata } from "next"; import Link from "next/link"; +import { cookies } from "next/headers"; import ReactMarkdown from "react-markdown"; import { fetchPostDetail, fetchComments } from "@/lib/api"; import CommentSection from "@/components/CommentSection"; @@ -30,7 +31,8 @@ export async function generateMetadata({ params }: PageProps): Promise export default async function PostDetailPage({ params }: PageProps) { const { id } = await params; - const { post } = await fetchPostDetail(id); + const cookie = (await cookies()).toString(); + const { post } = await fetchPostDetail(id, cookie); const { comments } = await fetchComments(id); const jsonLd = { diff --git a/frontend/components/LikeButton.tsx b/frontend/components/LikeButton.tsx index d38f83f..125fe85 100644 --- a/frontend/components/LikeButton.tsx +++ b/frontend/components/LikeButton.tsx @@ -8,9 +8,10 @@ interface LikeButtonProps { postId: string; liked: boolean; likeCount: number; + variant?: "default" | "compact"; } -export default function LikeButton({ postId, liked: initialLiked, likeCount: initialCount }: LikeButtonProps) { +export default function LikeButton({ postId, liked: initialLiked, likeCount: initialCount, variant = "default" }: LikeButtonProps) { const [liked, setLiked] = useState(initialLiked); const [count, setCount] = useState(initialCount); const [loading, setLoading] = useState(false); @@ -33,17 +34,21 @@ export default function LikeButton({ postId, liked: initialLiked, likeCount: ini } }; + const sizing = variant === "compact" ? "px-2 py-1 gap-1" : "px-3 py-1.5 gap-1.5"; + const iconSize = variant === "compact" ? 14 : 16; + return ( ); diff --git a/frontend/lib/api.ts b/frontend/lib/api.ts index 28116ce..9dedc11 100644 --- a/frontend/lib/api.ts +++ b/frontend/lib/api.ts @@ -189,17 +189,26 @@ async function fetchWithRefresh(url: string, init: RequestInit): Promise { const params = new URLSearchParams({ page: String(page), size: String(size), sort }); if (boardId) params.set("board_id", String(boardId)); if (keyword) params.set("keyword", keyword); - const res = await fetch(`${API_BASE}/api/posts?${params}`, { cache: "no-store" }); + const res = await fetch(`${API_BASE}/api/posts?${params}`, { + cache: "no-store", + headers: cookieHeaders(cookieHeader), + }); if (!res.ok) throw new Error("获取帖子失败"); return res.json(); } @@ -210,8 +219,11 @@ export async function fetchBoards(): Promise<{ boards: Board[] }> { return res.json(); } -export async function fetchPostDetail(id: string): Promise<{ post: Post }> { - const res = await fetch(`${API_BASE}/api/posts/${id}`, { cache: "no-store" }); +export async function fetchPostDetail(id: string, cookieHeader?: string): Promise<{ post: Post }> { + const res = await fetch(`${API_BASE}/api/posts/${id}`, { + cache: "no-store", + headers: cookieHeaders(cookieHeader), + }); if (!res.ok) throw new Error("获取帖子失败"); return res.json(); } @@ -222,9 +234,12 @@ export async function fetchComments(postId: string): Promise<{ comments: Comment return res.json(); } -export async function fetchUserProfile(id: string, page = 1): Promise { +export async function fetchUserProfile(id: string, page = 1, cookieHeader?: string): Promise { const params = new URLSearchParams({ page: String(page), size: "20" }); - const res = await fetch(`${API_BASE}/api/users/${id}?${params}`, { cache: "no-store" }); + const res = await fetch(`${API_BASE}/api/users/${id}?${params}`, { + cache: "no-store", + headers: cookieHeaders(cookieHeader), + }); if (res.status === 404) throw new Error("用户不存在"); if (!res.ok) throw new Error("获取用户资料失败"); return res.json(); diff --git a/frontend/next-env.d.ts b/frontend/next-env.d.ts index ce4e94a..a419cbe 100644 --- a/frontend/next-env.d.ts +++ b/frontend/next-env.d.ts @@ -1,7 +1,7 @@ /// /// -import "./.next/types/routes.d.ts"; -import "./.next/types/root-params.d.ts"; +import "./.next/dev/types/routes.d.ts"; +import "./.next/dev/types/root-params.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.