From 236c1a24da0fe836a1f3a8b3fd8cd490adfb619e Mon Sep 17 00:00:00 2001 From: zetaloop Date: Sun, 1 Mar 2026 22:40:29 +0800 Subject: [PATCH] feat(comments): migrate to backend API --- app/(main)/post/[id]/page.tsx | 2 +- components/post-comment-count.tsx | 9 +-- components/post-comments.tsx | 106 ++++++++++++++++++++++---- lib/api/comments.ts | 121 ++++++++++++++++++------------ 4 files changed, 169 insertions(+), 69 deletions(-) diff --git a/app/(main)/post/[id]/page.tsx b/app/(main)/post/[id]/page.tsx index 7e85708..f736c42 100644 --- a/app/(main)/post/[id]/page.tsx +++ b/app/(main)/post/[id]/page.tsx @@ -90,7 +90,7 @@ export default async function PostDetailPage({ params }: { params: Promise<{ id: initialLiked={post.liked} initialLikeCount={post.likeCount} /> - + diff --git a/components/post-comment-count.tsx b/components/post-comment-count.tsx index fdd63c6..1f11de8 100644 --- a/components/post-comment-count.tsx +++ b/components/post-comment-count.tsx @@ -1,17 +1,12 @@ "use client" -import { useCommentStore } from "@/store/comments" import { MessageCircle } from "lucide-react" interface PostCommentCountProps { - postId: string + count: number } -export function PostCommentCount({ postId }: PostCommentCountProps) { - const count = useCommentStore( - (state) => state.comments.filter((comment) => comment.postId === postId).length, - ) - +export function PostCommentCount({ count }: PostCommentCountProps) { return ( diff --git a/components/post-comments.tsx b/components/post-comments.tsx index bd0a476..97e6cc8 100644 --- a/components/post-comments.tsx +++ b/components/post-comments.tsx @@ -1,10 +1,12 @@ "use client" -import { addComment, toggleCommentLike } from "@/lib/api/comments" +import { addComment, listCommentsByPost, toggleCommentLike } from "@/lib/api/comments" +import { toApiError } from "@/lib/errors" +import { notifyInfo } from "@/lib/toast" +import type { Comment } from "@/lib/types" import { useRequireAuth } from "@/lib/use-require-auth" -import { useCommentStore } from "@/store/comments" import { Heart } from "lucide-react" -import { useMemo, useState } from "react" +import { useCallback, useEffect, useState } from "react" import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar" import { Button } from "./ui/button" import { Textarea } from "./ui/textarea" @@ -14,28 +16,58 @@ interface PostCommentsProps { } export function PostComments({ postId }: PostCommentsProps) { - const allComments = useCommentStore((state) => state.comments) - const comments = useMemo( - () => allComments.filter((comment) => comment.postId === postId), - [allComments, postId], - ) + const [comments, setComments] = useState([]) + const [loading, setLoading] = useState(true) + const [loadError, setLoadError] = useState(null) const [content, setContent] = useState("") + const [submitting, setSubmitting] = useState(false) + const [pendingLike, setPendingLike] = useState>({}) const { requireAuth } = useRequireAuth() + const refresh = useCallback(async () => { + setLoading(true) + setLoadError(null) + try { + const items = await listCommentsByPost(postId) + setComments(items) + } catch (err: unknown) { + setLoadError(toApiError(err).msg) + } finally { + setLoading(false) + } + }, [postId]) + + useEffect(() => { + void refresh() + }, [refresh]) + return (
-

评论 ({comments.length})

+

+ 评论 ({loading && comments.length === 0 ? "..." : comments.length}) +

{ event.preventDefault() - requireAuth(() => { + requireAuth(async () => { + if (submitting) return + const nextContent = content.trim() if (!nextContent) return - const decision = addComment(postId, nextContent) - if (!decision.ok) return + + setSubmitting(true) + const decision = await addComment(postId, nextContent) + if (!decision.ok) { + notifyInfo(decision.error.msg) + setSubmitting(false) + return + } + setContent("") + await refresh() + setSubmitting(false) }) }} > @@ -46,12 +78,16 @@ export function PostComments({ postId }: PostCommentsProps) { value={content} onChange={(event) => setContent(event.target.value)} /> -
- {comments.length === 0 ? ( + {loading && comments.length === 0 ? ( +

加载中...

+ ) : loadError ? ( +

加载失败:{loadError}

+ ) : comments.length === 0 ? (

还没有评论

) : (
@@ -71,10 +107,50 @@ export function PostComments({ postId }: PostCommentsProps) {

{comment.content}