"use client" import { User } from "@/models/user"; import { useTranslations } from "next-intl"; import { Suspense, useEffect, useState } from "react"; import { toast } from "sonner"; import { Comment } from "@/models/comment"; import { createComment, deleteComment, getComment, listComments } from "@/api/comment"; import { TargetType } from "@/models/types"; import { OrderBy } from "@/models/common"; import { Separator } from "@/components/ui/separator"; import { getLoginUser } from "@/api/user"; import { Skeleton } from "@/components/ui/skeleton"; import { CommentInput } from "./comment-input"; import { CommentItem } from "./comment-item"; import config from "@/config"; import "./style.css"; export function CommentSection( { targetType, targetId, totalCount = 0 }: { targetType: TargetType, targetId: number, totalCount?: number } ) { const t = useTranslations('Comment') const [currentUser, setCurrentUser] = useState(null); const [comments, setComments] = useState([]); const [activeInput, setActiveInput] = useState<{ id: number; type: 'reply' | 'edit' } | null>(null); const [page, setPage] = useState(1); // 当前页码 const [totalCommentCount, setTotalCommentCount] = useState(totalCount); // 评论总数 const [needLoadMore, setNeedLoadMore] = useState(true); // 是否需要加载更多,当最后一次获取的评论数小于分页大小时设为false // 获取当前登录用户 useEffect(() => { getLoginUser() .then(response => { setCurrentUser(response.data); }) }, []) // 加载0/顶层评论 useEffect(() => { listComments({ targetType, targetId, depth: 0, orderBy: OrderBy.CreatedAt, desc: true, page: page, size: config.commentsPerPage, commentId: 0 }).then(response => { setComments(response.data.comments); }); }, []) const onCommentSubmitted = ({ commentContent, isPrivate }: { commentContent: string, isPrivate: boolean }) => { createComment({ targetType, targetId, content: commentContent, replyId: null, isPrivate, }).then(res => { toast.success(t("comment_success")); setTotalCommentCount(c => c + 1); getComment({ id: res.data.id }).then(response => { console.log("New comment fetched:", response.data); setComments(prevComments => [response.data, ...prevComments]); }); setActiveInput(null); }) } const onReplySubmitted = ({ }: { commentContent: string, isPrivate: boolean }) => { setTotalCommentCount(c => c + 1); } const onCommentDelete = ({ commentId }: { commentId: number }) => { deleteComment({ id: commentId }).then(() => { toast.success(t("delete_success")); setComments(prevComments => prevComments.filter(comment => comment.id !== commentId)); setTotalCommentCount(c => c - 1); }).catch(error => { toast.error(t("delete_failed") + ": " + error.message); }); } const handleLoadMore = () => { const nextPage = page + 1; listComments({ targetType, targetId, depth: 0, orderBy: OrderBy.CreatedAt, desc: true, page: nextPage, size: config.commentsPerPage, commentId: 0 }).then(response => { if (response.data.comments.length < config.commentsPerPage) { setNeedLoadMore(false); } setComments(prevComments => [...prevComments, ...response.data.comments]); setPage(nextPage); }); } return (
{t("comment")} ({totalCommentCount})
}> {comments.map((comment, idx) => (
))}
{needLoadMore ?

{t("load_more")}

:

{t("no_more")}

}
) } function CommentLoading() { return (
{[...Array(3)].map((_, i) => (
))}
); }