mirror of
https://github.com/snowykami/neo-blog.git
synced 2025-09-27 19:46:24 +00:00
Refactor comment components and update OIDC configuration
- Updated OIDC configuration to include additional fields in the UpdateOidcConfig method. - Enhanced CommentService to include IsPrivate field in the comment DTO. - Refactored comment components: renamed neo-comment to comment, and moved related files. - Implemented new CommentInput and CommentItem components for better structure and readability. - Removed obsolete files related to the old comment system. - Added CSS animations for comment components to improve user experience.
This commit is contained in:
125
web/src/components/comment/index.tsx
Normal file
125
web/src/components/comment/index.tsx
Normal file
@ -0,0 +1,125 @@
|
||||
"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, 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
|
||||
}: {
|
||||
targetType: TargetType,
|
||||
targetId: number
|
||||
}
|
||||
) {
|
||||
const t = useTranslations('Comment')
|
||||
|
||||
const [currentUser, setCurrentUser] = useState<User | null>(null);
|
||||
const [comments, setComments] = useState<Comment[]>([]);
|
||||
const [refreshCommentsKey, setRefreshCommentsKey] = useState(0);
|
||||
|
||||
// 获取当前登录用户
|
||||
useEffect(() => {
|
||||
getLoginUser()
|
||||
.then(response => {
|
||||
setCurrentUser(response.data);
|
||||
})
|
||||
}, [])
|
||||
|
||||
// 加载0/顶层评论
|
||||
useEffect(() => {
|
||||
listComments({
|
||||
targetType,
|
||||
targetId,
|
||||
depth: 0,
|
||||
orderBy: OrderBy.CreatedAt,
|
||||
desc: true,
|
||||
page: 1,
|
||||
size: config.commentsPerPage,
|
||||
commentId: 0
|
||||
}).then(response => {
|
||||
setComments(response.data);
|
||||
});
|
||||
}, [refreshCommentsKey])
|
||||
|
||||
const onCommentSubmitted = ({ commentContent, isPrivate }: { commentContent: string, isPrivate: boolean }) => {
|
||||
createComment({
|
||||
targetType,
|
||||
targetId,
|
||||
content: commentContent,
|
||||
replyId: null,
|
||||
isPrivate,
|
||||
}).then(() => {
|
||||
toast.success(t("comment_success"));
|
||||
setRefreshCommentsKey(k => k + 1);
|
||||
})
|
||||
}
|
||||
|
||||
const onCommentDelete = ({ commentId }: { commentId: number }) => {
|
||||
deleteComment({ id: commentId }).then(() => {
|
||||
toast.success(t("delete_success"));
|
||||
setRefreshCommentsKey(k => k + 1);
|
||||
}).catch(error => {
|
||||
toast.error(t("delete_failed") + ": " + error.message);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Separator className="my-16" />
|
||||
<div className="font-bold text-2xl">{t("comment")}</div>
|
||||
<CommentInput
|
||||
user={currentUser}
|
||||
onCommentSubmitted={onCommentSubmitted}
|
||||
/>
|
||||
<div className="mt-4">
|
||||
<Suspense fallback={<CommentLoading />}>
|
||||
{comments.map((comment, idx) => (
|
||||
<div key={comment.id} className="fade-in-up" style={{ animationDelay: `${idx * 60}ms` }}>
|
||||
<Separator className="my-2" />
|
||||
<CommentItem
|
||||
user={currentUser}
|
||||
comment={comment}
|
||||
parentComment={null}
|
||||
onCommentDelete={onCommentDelete}
|
||||
/>
|
||||
</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 fade-in-up" style={{ animationDelay: `${i * 80}ms` }}>
|
||||
<Skeleton className="w-10 h-10 rounded-full fade-in" />
|
||||
<div className="flex-1 space-y-2">
|
||||
<Skeleton className="h-4 w-1/4 fade-in" />
|
||||
<Skeleton className="h-4 w-3/4 fade-in" />
|
||||
<Skeleton className="h-4 w-2/3 fade-in" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user