From 3821ef6657052b501d6ab53dfe121f90428528b2 Mon Sep 17 00:00:00 2001 From: tone <3341154833@qq.com> Date: Sat, 7 Jun 2025 03:21:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90=E8=AF=84?= =?UTF-8?q?=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tone-page-server/src/blog/blog.controller.ts | 29 ++++++++++- tone-page-server/src/blog/blog.module.ts | 3 +- tone-page-server/src/blog/blog.service.ts | 18 +++++++ .../src/blog/entity/Blog.entity.ts | 5 ++ .../src/blog/entity/BlogComment.ts | 33 ++++++++++++ .../blog/[id]/components/BlogCommentTool.tsx | 30 +++++++++++ .../blog/[id]/components/BlogComments.tsx | 51 +++++++++++++++++++ .../(with-header-footer)/blog/[id]/page.tsx | 8 +++ tone-page-web/lib/api/blog/createComment.ts | 15 ++++++ tone-page-web/lib/api/blog/getComments.ts | 13 +++++ tone-page-web/lib/api/blog/index.ts | 4 +- tone-page-web/lib/api/index.ts | 3 +- 12 files changed, 208 insertions(+), 4 deletions(-) create mode 100644 tone-page-server/src/blog/entity/BlogComment.ts create mode 100644 tone-page-web/app/(with-header-footer)/blog/[id]/components/BlogCommentTool.tsx create mode 100644 tone-page-web/app/(with-header-footer)/blog/[id]/components/BlogComments.tsx create mode 100644 tone-page-web/lib/api/blog/createComment.ts create mode 100644 tone-page-web/lib/api/blog/getComments.ts diff --git a/tone-page-server/src/blog/blog.controller.ts b/tone-page-server/src/blog/blog.controller.ts index a95ddab..da867ca 100644 --- a/tone-page-server/src/blog/blog.controller.ts +++ b/tone-page-server/src/blog/blog.controller.ts @@ -1,4 +1,4 @@ -import { BadRequestException, Controller, Get, Param, ParseUUIDPipe } from '@nestjs/common'; +import { BadRequestException, Body, Controller, Get, Param, ParseUUIDPipe, Post } from '@nestjs/common'; import { BlogService } from './blog.service'; @Controller('blog') @@ -31,4 +31,31 @@ export class BlogController { content: blogContent, }; } + + @Get(':id/comments') + async getBlogComments( + @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, + ) { + const blog = await this.blogService.findById(id); + if (!blog) throw new BadRequestException('文章不存在'); + + return await this.blogService.getComments(id); + } + + // TODO:鉴权,该接口允许匿名评论,但仍需验证userId合法性 + @Post(':id/comment') + async createBlogComment( + @Param('id', new ParseUUIDPipe({ version: '4' })) id: string, + @Body() commentData: { content: string }, + ) { + const blog = await this.blogService.findById(id); + if (!blog) throw new BadRequestException('文章不存在'); + + const comment = { + ...commentData, + blogId: id, + }; + + return await this.blogService.createComment(comment); + } } diff --git a/tone-page-server/src/blog/blog.module.ts b/tone-page-server/src/blog/blog.module.ts index a186635..65620cd 100644 --- a/tone-page-server/src/blog/blog.module.ts +++ b/tone-page-server/src/blog/blog.module.ts @@ -3,9 +3,10 @@ import { BlogController } from './blog.controller'; import { BlogService } from './blog.service'; import { TypeOrmModule } from '@nestjs/typeorm'; import { Blog } from './entity/Blog.entity'; +import { BlogComment } from './entity/BlogComment'; @Module({ - imports: [TypeOrmModule.forFeature([Blog])], + imports: [TypeOrmModule.forFeature([Blog, BlogComment])], controllers: [BlogController], providers: [BlogService], exports: [BlogService], diff --git a/tone-page-server/src/blog/blog.service.ts b/tone-page-server/src/blog/blog.service.ts index fb33199..d8cbb8f 100644 --- a/tone-page-server/src/blog/blog.service.ts +++ b/tone-page-server/src/blog/blog.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Blog } from './entity/Blog.entity'; import { Repository } from 'typeorm'; +import { BlogComment } from './entity/BlogComment'; @Injectable() export class BlogService { @@ -9,6 +10,8 @@ export class BlogService { constructor( @InjectRepository(Blog) private readonly blogRepository: Repository, + @InjectRepository(BlogComment) + private readonly blogCommentRepository: Repository, ) { } async list() { @@ -43,4 +46,19 @@ export class BlogService { async incrementViewCount(id: string) { await this.blogRepository.increment({ id }, 'viewCount', 1); } + + async getComments(id: string) { + return this.blogCommentRepository.find({ + where: { blogId: id }, + relations: ['user'], + order: { + createdAt: 'DESC', + } + }); + } + + async createComment(comment: Partial) { + const newComment = this.blogCommentRepository.create(comment); + return this.blogCommentRepository.save(newComment); + } } diff --git a/tone-page-server/src/blog/entity/Blog.entity.ts b/tone-page-server/src/blog/entity/Blog.entity.ts index 579eef7..ebbfcd5 100644 --- a/tone-page-server/src/blog/entity/Blog.entity.ts +++ b/tone-page-server/src/blog/entity/Blog.entity.ts @@ -1,4 +1,5 @@ import { Column, CreateDateColumn, DeleteDateColumn, Entity, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm"; +import { BlogComment } from "./BlogComment"; @Entity() export class Blog { @@ -27,4 +28,8 @@ export class Blog { deletedAt: Date; // 权限关系 TODO + + // 关系 + @OneToMany(() => BlogComment, blog => blog.id) + comments: BlogComment[]; } \ No newline at end of file diff --git a/tone-page-server/src/blog/entity/BlogComment.ts b/tone-page-server/src/blog/entity/BlogComment.ts new file mode 100644 index 0000000..4720709 --- /dev/null +++ b/tone-page-server/src/blog/entity/BlogComment.ts @@ -0,0 +1,33 @@ +import { User } from "src/user/entities/user.entity"; +import { Column, CreateDateColumn, DeleteDateColumn, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; + +@Entity() +export class BlogComment { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column() + content: string; + + // @Column() + // ip: string; + + // @Column() + // address: string; + + @CreateDateColumn({ precision: 3 }) + createdAt: Date; + + @DeleteDateColumn({ precision: 3, nullable: true }) + deletedAt: Date; + + @ManyToOne(() => User, { nullable: true }) + @JoinColumn({ name: 'userId' }) + user: User | null; + + @Column({ type: 'uuid', nullable: true }) + blogId: string | null; + + @Column({ type: 'uuid', nullable: true }) + parentId: string | null; +} \ No newline at end of file diff --git a/tone-page-web/app/(with-header-footer)/blog/[id]/components/BlogCommentTool.tsx b/tone-page-web/app/(with-header-footer)/blog/[id]/components/BlogCommentTool.tsx new file mode 100644 index 0000000..e73cd04 --- /dev/null +++ b/tone-page-web/app/(with-header-footer)/blog/[id]/components/BlogCommentTool.tsx @@ -0,0 +1,30 @@ +'use client'; + +import { Button } from "@/components/ui/button"; +import { Textarea } from "@/components/ui/textarea"; +import { BlogApi } from "@/lib/api"; +import { Send } from "lucide-react"; +import { useState } from "react"; +import { toast } from "sonner"; + +export function BlogCommentTool({ blogId }: { blogId: string }) { + + const [comment, setComment] = useState(''); + const submit = async () => { + const res = await BlogApi.createComment(blogId, comment); + if (res) { + toast.success('发布成功'); + setComment(''); + // 提交界面刷新 + } + } + + return ( +
+