From a740c48d128078a02c45f4844350c55e43151886 Mon Sep 17 00:00:00 2001 From: Snowykami Date: Thu, 31 Jul 2025 08:32:24 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20=E6=9B=B4=E6=96=B0=E8=AF=84?= =?UTF-8?q?=E8=AE=BA=E5=8A=9F=E8=83=BD=EF=BC=8C=E9=87=8D=E6=9E=84=E8=AF=84?= =?UTF-8?q?=E8=AE=BA=E5=88=97=E8=A1=A8=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=88=86=E9=9A=94=E7=AC=A6=E7=BB=84=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=94=A8=E6=88=B7=E5=A4=B4=E5=83=8F=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/repo/comment.go | 2 +- web/package.json | 1 + web/pnpm-lock.yaml | 25 +++++++++++++++ web/src/api/comment.ts | 33 +++++++++++++++----- web/src/components/comment/comment-input.tsx | 18 +++++++++-- web/src/components/comment/comment-item.tsx | 27 +++++++++------- web/src/components/comment/index.tsx | 25 +++++++++++++-- web/src/components/ui/separator.tsx | 28 +++++++++++++++++ 8 files changed, 135 insertions(+), 24 deletions(-) create mode 100644 web/src/components/ui/separator.tsx diff --git a/internal/repo/comment.go b/internal/repo/comment.go index 9d5d3ba..04b56ec 100644 --- a/internal/repo/comment.go +++ b/internal/repo/comment.go @@ -190,7 +190,7 @@ func (cr *CommentRepo) ListComments(currentUserID uint, targetID uint, targetTyp query := GetDB().Model(&model.Comment{}).Preload("User") if currentUserID > 0 { - query = query.Where("is_private = ? OR (is_private = ? AND (user_id = ? OR user_id = ?))", false, true, currentUserID, masterID) + query = query.Where("(is_private = ? OR (is_private = ? AND (user_id = ? OR user_id = ?)))", false, true, currentUserID, masterID) } else { query = query.Where("is_private = ?", false) } diff --git a/web/package.json b/web/package.json index 51210e3..4c0fe1b 100644 --- a/web/package.json +++ b/web/package.json @@ -12,6 +12,7 @@ "@radix-ui/react-dialog": "^1.1.14", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-navigation-menu": "^1.2.13", + "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-switch": "^1.2.5", "axios": "^1.11.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 8c0d119..df5a36a 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@radix-ui/react-navigation-menu': specifier: ^1.2.13 version: 1.2.13(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-separator': + specifier: ^1.1.7 + version: 1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-slot': specifier: ^1.2.3 version: 1.2.3(@types/react@19.1.8)(react@19.1.0) @@ -595,6 +598,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-separator@1.1.7': + resolution: {integrity: sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-slot@1.2.3': resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} peerDependencies: @@ -3185,6 +3201,15 @@ snapshots: '@types/react': 19.1.8 '@types/react-dom': 19.1.6(@types/react@19.1.8) + '@radix-ui/react-separator@1.1.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) + '@radix-ui/react-slot@1.2.3(@types/react@19.1.8)(react@19.1.0)': dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.8)(react@19.1.0) diff --git a/web/src/api/comment.ts b/web/src/api/comment.ts index 7f7a3f5..17a3f14 100644 --- a/web/src/api/comment.ts +++ b/web/src/api/comment.ts @@ -23,18 +23,35 @@ export async function deleteComment(id: number): Promise { await axiosClient.delete(`/comment/c/${id}`) } -export async function listComments( - targetType: 'post' | 'page', - targetId: number, - pagination: PaginationParams = { orderBy: OrderBy.CreatedAt, desc: false, page: 1, size: 10 }, - depth: number = 1 -): Promise> { +export interface ListCommentsParams { + targetType: 'post' | 'page' + targetId: number + depth?: number + orderBy?: OrderBy + desc?: boolean + page?: number + size?: number +} + +export async function listComments(params: ListCommentsParams): Promise> { + const { + targetType, + targetId, + depth = 0, + orderBy = OrderBy.CreatedAt, + desc = true, + page = 1, + size = 10, + } = params const res = await axiosClient.get>(`/comment/list`, { params: { targetType, targetId, - ...pagination, - depth + depth, + orderBy, + desc, + page, + size } }) return res.data diff --git a/web/src/components/comment/comment-input.tsx b/web/src/components/comment/comment-input.tsx index 9627069..2d9217c 100644 --- a/web/src/components/comment/comment-input.tsx +++ b/web/src/components/comment/comment-input.tsx @@ -1,14 +1,28 @@ "use client"; import { Textarea } from "@/components/ui/textarea" -import Gravatar from "@/components/common/gravatar" +import { getGravatarByUser } from "@/components/common/gravatar" + +import { useState, useEffect } from "react"; +import type { User } from "@/models/user"; +import { getLoginUser } from "@/api/user"; export function CommentInput() { + const [user, setUser] = useState(null); // 假设 User 是你的用户模型 + useEffect(()=>{ + getLoginUser() + .then(response => { + setUser(response.data); + }) + .catch(error => { + console.error("获取用户信息失败:", error); + }); + }, []); return (
{/* Avatar */}
- + {user && getGravatarByUser(user)}
{/* Input Area */}
diff --git a/web/src/components/comment/comment-item.tsx b/web/src/components/comment/comment-item.tsx index 4c84f06..e04683a 100644 --- a/web/src/components/comment/comment-item.tsx +++ b/web/src/components/comment/comment-item.tsx @@ -2,19 +2,24 @@ import type { Comment } from "@/models/comment"; import { CardHeader, CardTitle } from "@/components/ui/card"; -import {useState, useEffect} from "react"; +import { getGravatarByUser } from "@/components/common/gravatar"; +import { useState, useEffect } from "react"; +import { get } from "http"; -export function CommentItem(comment: Comment){ +export function CommentItem(comment: Comment) { + const [replies, setReplies] = useState([]); + const [loadingReplies, setLoadingReplies] = useState(false); return ( -
- - - {comment.user.nickname} - - -

{comment.content}

-
- {new Date(comment.updatedAt).toLocaleString()} +
+
+ {getGravatarByUser(comment.user)} +
+
+
{comment.user.nickname}
+

{comment.content}

+
+ {new Date(comment.updatedAt).toLocaleString()} +
); diff --git a/web/src/components/comment/index.tsx b/web/src/components/comment/index.tsx index 4d81e92..8796006 100644 --- a/web/src/components/comment/index.tsx +++ b/web/src/components/comment/index.tsx @@ -5,6 +5,8 @@ import { CommentInput } from "@/components/comment/comment-input"; import { useEffect, useState } from "react"; import { listComments } from "@/api/comment"; import { OrderBy } from "@/models/common"; +import { CommentItem } from "./comment-item"; +import { Separator } from "../ui/separator"; interface CommentAreaProps { targetType: 'post' | 'page'; @@ -19,7 +21,15 @@ export default function CommentSection(props: CommentAreaProps) { const [newComment, setNewComment] = useState(""); useEffect(() => { - listComments({ page: 1, size: 10, orderBy: OrderBy.CreatedAt, desc: true }, 1) + listComments({ + targetType, + targetId, + depth: 0, + orderBy: OrderBy.CreatedAt, + desc: true, + page: 1, + size: 10 + }) .then(response => { setComments(response.data); }) @@ -34,8 +44,19 @@ export default function CommentSection(props: CommentAreaProps) { return (
-

评论区

+ +
评论
+ {loading &&

加载中...

} + {error &&

{error}

} +
+ {comments.map(comment => ( +
+ + +
+ ))} +
); } \ No newline at end of file diff --git a/web/src/components/ui/separator.tsx b/web/src/components/ui/separator.tsx new file mode 100644 index 0000000..275381c --- /dev/null +++ b/web/src/components/ui/separator.tsx @@ -0,0 +1,28 @@ +"use client" + +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" + +import { cn } from "@/lib/utils" + +function Separator({ + className, + orientation = "horizontal", + decorative = true, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { Separator }