feat: 添加评论功能,重构评论输入和列表组件,支持多种目标类型,更新国际化文本
All checks were successful
Push to Helm Chart Repository / build (push) Successful in 18s

This commit is contained in:
2025-09-07 23:56:25 +08:00
parent 38584e164e
commit 6237cddc87
16 changed files with 235 additions and 57 deletions

View File

@ -2,22 +2,24 @@
import type { Comment } from "@/models/comment";
import { CommentInput } from "@/components/comment/comment-input";
import { useEffect, useState } from "react";
import { Suspense, useEffect, useState } from "react";
import { listComments } from "@/api/comment";
import { OrderBy } from "@/models/common";
import { CommentItem } from "./comment-item";
import { Separator } from "../ui/separator";
import { TargetType } from "@/models/types";
import { Skeleton } from "../ui/skeleton";
interface CommentAreaProps {
targetType: 'post' | 'page';
targetType: TargetType;
targetId: number;
}
export default function CommentSection(props: CommentAreaProps) {
const { targetType, targetId } = props;
const [comments, setComments] = useState<Comment[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [newComment, setNewComment] = useState<string>("");
useEffect(() => {
@ -33,30 +35,57 @@ export default function CommentSection(props: CommentAreaProps) {
.then(response => {
setComments(response.data);
})
.catch(err => {
setError("加载评论失败,请稍后再试。");
console.error("Error loading comments:", err);
})
.finally(() => {
setLoading(false);
});
}, [targetType, targetId]);
const onCommentSubmitted = () => {
// 重新加载评论列表
listComments({
targetType,
targetId,
depth: 0,
orderBy: OrderBy.CreatedAt,
desc: true,
page: 1,
size: 10
})
.then(response => {
setComments(response.data);
})
}
return (
<div>
<Separator className="my-16" />
<div className="font-bold text-2xl"></div>
<CommentInput />
{loading && <p>...</p>}
{error && <p className="text-red-500">{error}</p>}
<CommentInput targetType={targetType} targetId={targetId} onCommentSubmitted={onCommentSubmitted} />
<div className="mt-4">
{comments.map(comment => (
<div key={comment.id}>
<Separator className="my-2" />
<CommentItem {...comment} />
</div>
))}
<Suspense fallback={<CommentLoading />}>
{comments.map(comment => (
<div key={comment.id}>
<Separator className="my-2" />
<CommentItem {...comment} />
</div>
))}
</Suspense>
</div>
</div>
);
}
function CommentLoading() {
return (
<div className="space-y-6 py-8">
{[...Array(3)].map((_, i) => (
<div key={i} className="flex gap-3">
<Skeleton className="w-10 h-10 rounded-full" />
<div className="flex-1 space-y-2">
<Skeleton className="h-4 w-1/4" />
<Skeleton className="h-4 w-3/4" />
<Skeleton className="h-4 w-2/3" />
</div>
</div>
))}
</div>
);
}