From f07adec658b6573ded5c871c20650df4f31a2fe0 Mon Sep 17 00:00:00 2001
From: forely <1605769034@qq.com>
Date: Sat, 10 May 2025 00:31:10 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E9=83=A8=E5=88=86=E8=A1=A8?=
=?UTF-8?q?=E4=B8=8E=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=B8=96?=
=?UTF-8?q?=E5=AD=90=EF=BC=8C=E8=AF=84=E8=AE=BA=E7=9A=84=E7=9B=B8=E5=85=B3?=
=?UTF-8?q?=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../luojia-island/pom.xml | 6 +
.../message/config/WebSocketConfig.java | 17 +++
.../mq/AbstractSendProduceTemplate.java | 44 ++++++
.../modules/message/mq/BaseSendExtendDTO.java | 18 +++
.../modules/message/mq/MessageWrapper.java | 41 ++++++
.../post/controller/CommentController.java | 41 +++---
.../post/controller/PostController.java | 3 +-
.../post/dto/req/CommentPageQueryDTO.java | 3 +-
.../modules/post/dto/req/PostSaveDTO.java | 1 +
.../modules/post/dto/resp/CommentInfoDTO.java | 6 +-
.../modules/post/dto/resp/PostInfoDTO.java | 22 ---
.../modules/post/entity/Comment.java | 3 +-
.../modules/post/service/CommentService.java | 9 +-
.../modules/post/service/PostService.java | 3 +-
.../post/service/impl/CommentServiceImpl.java | 128 +++++++++++++-----
.../post/service/impl/PostServiceImpl.java | 46 +++++--
.../modules/post/utils/ValidatePostUtil.java | 35 ++++-
.../src/main/resources/db/luojia_channel.sql | 5 +-
18 files changed, 331 insertions(+), 100 deletions(-)
create mode 100644 珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/config/WebSocketConfig.java
create mode 100644 珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/AbstractSendProduceTemplate.java
create mode 100644 珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/BaseSendExtendDTO.java
create mode 100644 珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/MessageWrapper.java
delete mode 100644 珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/resp/PostInfoDTO.java
diff --git a/珞珈岛-项目相关文件/luojia-island/pom.xml b/珞珈岛-项目相关文件/luojia-island/pom.xml
index 984db35..c0249b9 100644
--- a/珞珈岛-项目相关文件/luojia-island/pom.xml
+++ b/珞珈岛-项目相关文件/luojia-island/pom.xml
@@ -106,6 +106,12 @@
commons-codec
1.15
+
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/config/WebSocketConfig.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/config/WebSocketConfig.java
new file mode 100644
index 0000000..e039eb2
--- /dev/null
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/config/WebSocketConfig.java
@@ -0,0 +1,17 @@
+package com.luojia_channel.modules.message.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+
+@Configuration
+@EnableWebSocket
+public class WebSocketConfig implements WebSocketConfigurer {
+ @Override
+ public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
+ registry.addHandler(new MyWebSocketHandler(), "/ws")
+ .setAllowedOrigins("*"); // 允许跨域
+ }
+
+}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/AbstractSendProduceTemplate.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/AbstractSendProduceTemplate.java
new file mode 100644
index 0000000..343a078
--- /dev/null
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/AbstractSendProduceTemplate.java
@@ -0,0 +1,44 @@
+package com.luojia_channel.modules.message.mq;
+
+import com.alibaba.fastjson.JSON;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.messaging.MessageHeaders;
+
+@Slf4j
+@RequiredArgsConstructor
+// 模板方法类,提供消息发送的模板方法
+public abstract class AbstractSendProduceTemplate {
+
+ private final RabbitTemplate rabbitTemplate;
+ private static final String KEYS = "keys";
+
+ protected abstract BaseSendExtendDTO buildBaseSendParam(T messageSendEvent);
+
+ public void sendMessage(T messageSendEvent) {
+ BaseSendExtendDTO baseSendDTO = buildBaseSendParam(messageSendEvent);
+ try {
+ // 发送消息
+ rabbitTemplate.convertAndSend(
+ baseSendDTO.getExchange(),
+ baseSendDTO.getRoutingKey(),
+ new MessageWrapper(baseSendDTO.getKeys(), messageSendEvent),
+ m -> {
+ // 设置消息头
+ m.getMessageProperties().setHeader(KEYS, baseSendDTO.getKeys());
+ // 设置消息属性(如延迟时间) TODO 若需要延迟消息,需安装延时插件
+ if (baseSendDTO.getDelay() != null) {
+ // m.getMessageProperties().setDelay(baseSendDTO.getDelay());
+ }
+ return m;
+ }
+ );
+ log.info("[{}] 消息发送成功,Exchange:{},Routing Key:{}",
+ baseSendDTO.getEventName(), baseSendDTO.getExchange(), baseSendDTO.getRoutingKey());
+ } catch (Throwable ex) {
+ log.error("[{}] 消息发送失败,消息体:{}", baseSendDTO.getEventName(), JSON.toJSONString(messageSendEvent), ex);
+ throw ex;
+ }
+ }
+}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/BaseSendExtendDTO.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/BaseSendExtendDTO.java
new file mode 100644
index 0000000..4893713
--- /dev/null
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/BaseSendExtendDTO.java
@@ -0,0 +1,18 @@
+package com.luojia_channel.modules.message.mq;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public final class BaseSendExtendDTO {
+ private String eventName; //业务名称
+ private String exchange; //交换机
+ private String routingKey; //路由键
+ private String keys; // 消息唯一标识
+ private Long delay; // 延迟时间(毫秒),需RabbitMQ安装延迟插件
+}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/MessageWrapper.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/MessageWrapper.java
new file mode 100644
index 0000000..2d07daf
--- /dev/null
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/message/mq/MessageWrapper.java
@@ -0,0 +1,41 @@
+package com.luojia_channel.modules.message.mq;
+
+import lombok.*;
+
+import java.io.Serializable;
+import java.util.UUID;
+
+/**
+ * 消息体包装器
+ */
+@Data
+@Builder
+@NoArgsConstructor(force = true)
+@AllArgsConstructor
+@RequiredArgsConstructor
+public final class MessageWrapper implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 消息发送 Keys
+ */
+ @NonNull
+ private String keys;
+
+ /**
+ * 消息体
+ */
+ @NonNull
+ private T message;
+
+ /**
+ * 唯一标识,用于客户端幂等验证
+ */
+ private String uuid = UUID.randomUUID().toString();
+
+ /**
+ * 消息发送时间
+ */
+ private Long timestamp = System.currentTimeMillis();
+}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/controller/CommentController.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/controller/CommentController.java
index 9e6cc5a..616cb10 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/controller/CommentController.java
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/controller/CommentController.java
@@ -4,61 +4,58 @@ import com.luojia_channel.common.domain.Result;
import com.luojia_channel.common.domain.page.PageResponse;
import com.luojia_channel.common.utils.UserContext;
import com.luojia_channel.modules.post.dto.req.CommentPageQueryDTO;
+import com.luojia_channel.modules.post.dto.req.CommentSaveDTO;
import com.luojia_channel.modules.post.dto.resp.CommentInfoDTO;
import com.luojia_channel.modules.post.entity.Comment;
import com.luojia_channel.modules.post.service.CommentService;
+import com.luojia_channel.modules.post.utils.ValidatePostUtil;
+import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
-
+@RequiredArgsConstructor
@RestController
@RequestMapping("/comments")
public class CommentController {
private final CommentService commentService;
- @Autowired
- public CommentController(CommentService commentService) {
- this.commentService = commentService;
- }
-
// 创建评论
@PostMapping
- public Result saveComment(@RequestBody Comment comment) {
- commentService.saveComment(comment);
+ public Result saveComment(@RequestBody CommentSaveDTO commentSaveDTO) {
+ commentService.saveComment(commentSaveDTO);
return Result.success();
}
// 更新评论
- @PutMapping("/{id}")
- public Result updateComment(@PathVariable Long id, @RequestBody Comment comment) {
- Long currentUserId = UserContext.getUserId();
- commentService.updateComment(comment, currentUserId);
+ @PutMapping
+ public Result updateComment(@RequestBody CommentSaveDTO commentSaveDTO) {
+ commentService.updateComment(commentSaveDTO);
return Result.success();
}
// 删除评论
- @DeleteMapping("/{id}")
- public Result deleteComment(@PathVariable Long id) {
- Long currentUserId = UserContext.getUserId();
- commentService.deleteComment(id, currentUserId);
+ @DeleteMapping
+ public Result deleteComment(@RequestParam("id") Long id) {
+ commentService.deleteComment(id);
return Result.success();
}
- // 根据帖子ID分页获取评论
+ // 根据帖子ID分页获取根评论
@GetMapping("/list")
public Result> getCommentsByPostId(@RequestBody CommentPageQueryDTO commentPageQueryDTO) {
PageResponse commentList = commentService.getCommentsByPostId(commentPageQueryDTO);
return Result.success(commentList);
}
- // 根据帖子ID获取嵌套评论
- @GetMapping("/nested/post/{postId}")
- public Result> getNestedCommentsByPostId(@PathVariable Long postId) {
- List nestedComments = commentService.getNestedCommentsByPostId(postId);
- return Result.success(nestedComments);
+
+ // 根据评论ID获取回复
+ @GetMapping("/list/reply")
+ public Result> getReplyById(@RequestBody CommentPageQueryDTO commentPageQueryDTO) {
+ PageResponse commentInfoDTOList = commentService.getReplyById(commentPageQueryDTO);
+ return Result.success(commentInfoDTOList);
}
}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/controller/PostController.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/controller/PostController.java
index 944385a..1dd7fff 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/controller/PostController.java
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/controller/PostController.java
@@ -6,6 +6,7 @@ import com.luojia_channel.common.domain.page.PageResponse;
import com.luojia_channel.modules.post.dto.req.PostSaveDTO;
import com.luojia_channel.modules.post.dto.req.PostPageQueryDTO;
import com.luojia_channel.modules.post.dto.resp.PostBasicInfoDTO;
+import com.luojia_channel.modules.post.dto.resp.PostInfoDTO;
import com.luojia_channel.modules.post.entity.Post;
import com.luojia_channel.modules.post.service.PostService;
import lombok.RequiredArgsConstructor;
@@ -48,7 +49,7 @@ public class PostController {
// 根据ID获取帖子详情
@GetMapping("/detail")
- public Post getPostDetail(@RequestParam("id") Long id) {
+ public PostInfoDTO getPostDetail(@RequestParam("id") Long id) {
return postService.getPostDetail(id);
}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/req/CommentPageQueryDTO.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/req/CommentPageQueryDTO.java
index b83ac08..3af2096 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/req/CommentPageQueryDTO.java
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/req/CommentPageQueryDTO.java
@@ -5,5 +5,6 @@ import lombok.Data;
@Data
public class CommentPageQueryDTO extends PageRequest {
- private Integer postId;
+ private Long postId;
+ private Long commentId;
}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/req/PostSaveDTO.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/req/PostSaveDTO.java
index f23957a..de2299a 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/req/PostSaveDTO.java
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/req/PostSaveDTO.java
@@ -4,6 +4,7 @@ import lombok.Data;
@Data
public class PostSaveDTO {
+ private Long id;
private String title;
private String image;
private String content;
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/resp/CommentInfoDTO.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/resp/CommentInfoDTO.java
index 335ef53..b2e0663 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/resp/CommentInfoDTO.java
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/resp/CommentInfoDTO.java
@@ -15,12 +15,16 @@ import java.util.List;
public class CommentInfoDTO {
private Long id;
private String content;
+ private Long likeCount;
+ private Long replyCount;
private Long userId;
- private String postType;
private Long postId;
private Long parentCommentId;
private Long topId;
private LocalDateTime createTime;
+ private String userName;
+ private String userAvatar;
+
private List commentInfoDTOList;
}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/resp/PostInfoDTO.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/resp/PostInfoDTO.java
deleted file mode 100644
index 6680971..0000000
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/dto/resp/PostInfoDTO.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.luojia_channel.modules.post.dto.resp;
-
-import com.luojia_channel.modules.post.entity.Comment;
-
-import java.util.List;
-
-public class PostInfoDTO {
- private Long id;
- private String image;
- private String title;
- private Integer likeCount;
- private Integer commentCount;
- private Integer favoriteCount;
- private String content;
-
- private Boolean isLike;
- private Long userId;
- private String userName;
- private String userAvatar;
-
- private List commentList;
-}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/entity/Comment.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/entity/Comment.java
index bb55476..a00ac09 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/entity/Comment.java
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/entity/Comment.java
@@ -16,8 +16,9 @@ import java.time.LocalDateTime;
public class Comment {
private Long id;
private String content;
+ private Long likeCount;
+ private Long replyCount;
private Long userId;
- private String postType;
private Long postId;
private Long parentCommentId;
private Long topId;
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/CommentService.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/CommentService.java
index 9523485..3ebeab1 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/CommentService.java
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/CommentService.java
@@ -2,6 +2,7 @@ package com.luojia_channel.modules.post.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.luojia_channel.common.domain.page.PageResponse;
import com.luojia_channel.modules.post.dto.req.CommentPageQueryDTO;
+import com.luojia_channel.modules.post.dto.req.CommentSaveDTO;
import com.luojia_channel.modules.post.dto.resp.CommentInfoDTO;
import com.luojia_channel.modules.post.entity.Comment;
import org.springframework.stereotype.Service;
@@ -11,13 +12,13 @@ import java.util.List;
@Service
public interface CommentService {
- void saveComment(Comment comment);
+ void saveComment(CommentSaveDTO commentSaveDTO);
- void updateComment(Comment comment, Long userId);
+ void updateComment(CommentSaveDTO commentSaveDTO);
- void deleteComment(Long id, Long userId);
+ void deleteComment(Long id);
PageResponse getCommentsByPostId(CommentPageQueryDTO commentPageQueryDTO);
- List getNestedCommentsByPostId(Long postId);
+ PageResponse getReplyById(CommentPageQueryDTO commentPageQueryDTO);
}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/PostService.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/PostService.java
index 8c7136e..68cecb0 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/PostService.java
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/PostService.java
@@ -5,6 +5,7 @@ import com.luojia_channel.common.domain.page.PageResponse;
import com.luojia_channel.modules.post.dto.req.PostSaveDTO;
import com.luojia_channel.modules.post.dto.req.PostPageQueryDTO;
import com.luojia_channel.modules.post.dto.resp.PostBasicInfoDTO;
+import com.luojia_channel.modules.post.dto.resp.PostInfoDTO;
import com.luojia_channel.modules.post.entity.Post;
import org.springframework.web.multipart.MultipartFile;
@@ -17,7 +18,7 @@ public interface PostService extends IService {
void deletePost(Long id);
- Post getPostDetail(Long id);
+ PostInfoDTO getPostDetail(Long id);
PageResponse pagePost(PostPageQueryDTO postPageQueryDTO);
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/impl/CommentServiceImpl.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/impl/CommentServiceImpl.java
index f78d52a..794da2b 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/impl/CommentServiceImpl.java
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/impl/CommentServiceImpl.java
@@ -1,91 +1,150 @@
package com.luojia_channel.modules.post.service.impl;
+import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.luojia_channel.common.domain.page.PageResponse;
import com.luojia_channel.common.exception.PostException;
import com.luojia_channel.common.utils.PageUtil;
+import com.luojia_channel.common.utils.UserContext;
import com.luojia_channel.modules.post.dto.req.CommentPageQueryDTO;
+import com.luojia_channel.modules.post.dto.req.CommentSaveDTO;
import com.luojia_channel.modules.post.dto.resp.CommentInfoDTO;
import com.luojia_channel.modules.post.dto.resp.PostBasicInfoDTO;
import com.luojia_channel.modules.post.entity.Comment;
import com.luojia_channel.modules.post.entity.Post;
import com.luojia_channel.modules.post.mapper.CommentMapper;
import com.luojia_channel.modules.post.service.CommentService;
+import com.luojia_channel.modules.post.utils.ValidatePostUtil;
+import com.luojia_channel.modules.user.entity.User;
+import com.luojia_channel.modules.user.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class CommentServiceImpl extends ServiceImpl implements CommentService {
- private CommentMapper commentMapper;
+ private final ValidatePostUtil validatePostUtil;
+ private final CommentMapper commentMapper;
+ private final UserMapper userMapper;
@Override
- public void saveComment(Comment comment) {
- comment.setCreateTime(LocalDateTime.now());
- comment.setUpdateTime(LocalDateTime.now());
- commentMapper.insert(comment);
+ @Transactional(rollbackFor = Exception.class)
+ public void saveComment(CommentSaveDTO commentSaveDTO) {
+ validatePostUtil.validateComment(commentSaveDTO);
+ Comment comment = BeanUtil.copyProperties(commentSaveDTO, Comment.class);
+ if(!save(comment)){
+ throw new PostException("创建评论失败");
+ }
+ Long parentCommentId = commentSaveDTO.getParentCommentId();
+ if(parentCommentId != null){
+ LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(Comment.class)
+ .eq(Comment::getId, parentCommentId)
+ .setSql("reply_count = reply_count + 1");
+ int update = commentMapper.update(null, updateWrapper);
+ if(update <= 0) {
+ throw new PostException("回复评论失败");
+ }
+ Long topId = commentSaveDTO.getTopId();
+ // 更新顶级评论回复数
+ if(!parentCommentId.equals(topId)){
+ updateWrapper = Wrappers.lambdaUpdate(Comment.class)
+ .eq(Comment::getId, topId)
+ .setSql("reply_count = reply_count + 1");
+ update = commentMapper.update(null, updateWrapper);
+ if(update <= 0) {
+ throw new PostException("回复顶级评论失败");
+ }
+ }
+
+ // TODO 消息通知
+
+ }
+
}
@Override
- public void updateComment(Comment comment, Long userId) {
- validatePostOwnership(comment.getId(), userId);
+ public void updateComment(CommentSaveDTO commentSaveDTO) {
+ validatePostUtil.validateComment(commentSaveDTO);
+ validatePostUtil.validateCommentOwnership(commentSaveDTO.getId());
+ Comment comment = BeanUtil.copyProperties(commentSaveDTO, Comment.class);
comment.setUpdateTime(LocalDateTime.now());
if(!updateById(comment)){
- throw new PostException("更新帖子失败");
+ throw new PostException("更新评论失败");
}
}
@Override
- public void deleteComment(Long id, Long userId) {
- validatePostOwnership(id, userId);
- commentMapper.deleteById(id);
+ public void deleteComment(Long id) {
+ validatePostUtil.validateCommentOwnership(id);
+ LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(Comment.class)
+ .eq(Comment::getTopId, id);
+ int delete = commentMapper.delete(queryWrapper);
+ if(delete <= 0) {
+ throw new PostException("删除评论失败");
+ }
+ // TODO 如果根评论删除,那么其他评论怎么办,目前做法是删除其下所有的子评论
}
+ // 分页查询一系列根评论
@Override
public PageResponse getCommentsByPostId(CommentPageQueryDTO commentPageQueryDTO) {
+ if(commentPageQueryDTO.getPostId() == null || commentPageQueryDTO.getPostId() < 0){
+ throw new PostException("帖子id不合法");
+ }
LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(Comment.class)
.eq(Comment::getPostId, commentPageQueryDTO.getPostId())
+ .eq(Comment::getParentCommentId, 0L)
.orderByDesc(Comment::getCreateTime);
- IPage commentPage = commentMapper.selectPage(PageUtil.convert(commentPageQueryDTO), queryWrapper);
- return PageUtil.convert(commentPage, CommentInfoDTO.class);
+ return getCommentInfoDTOPageResponse(commentPageQueryDTO, queryWrapper);
}
@Override
- public List getNestedCommentsByPostId(Long postId) {
- LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(Comment::getPostId, postId)
- .orderByAsc(Comment::getCreateTime);
-
- List comments = commentMapper.selectList(queryWrapper);
- return buildNestedComments(comments);
+ public PageResponse getReplyById(CommentPageQueryDTO commentPageQueryDTO) {
+ if(commentPageQueryDTO.getCommentId() == null || commentPageQueryDTO.getCommentId() < 0){
+ throw new PostException("评论id不合法");
+ }
+ LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(Comment.class)
+ .eq(Comment::getTopId, commentPageQueryDTO.getCommentId())
+ .orderByDesc(Comment::getCreateTime);
+ return getCommentInfoDTOPageResponse(commentPageQueryDTO, queryWrapper);
}
- private void validatePostOwnership(Long commentId, Long userId) {
- Comment comment = commentMapper.selectById(commentId);
- if (comment == null) {
- throw new PostException("评论不存在");
- }
- if (!userId.equals(comment.getUserId())) {
- throw new PostException("你无权操作他人的评论");
- }
+ private PageResponse getCommentInfoDTOPageResponse(CommentPageQueryDTO commentPageQueryDTO, LambdaQueryWrapper queryWrapper) {
+ IPage commentPage = commentMapper.selectPage(PageUtil.convert(commentPageQueryDTO), queryWrapper);
+ List userIds = new ArrayList<>();
+ commentPage.getRecords().forEach(comment -> {
+ userIds.add(comment.getUserId());
+ });
+ List users = userMapper.selectBatchIds(userIds);
+ Map userMap = users.stream()
+ .collect(Collectors.toMap(User::getId, user -> user));
+ return PageUtil.convert(commentPage, (comment) -> {
+ CommentInfoDTO commentInfoDTO = BeanUtil.copyProperties(comment, CommentInfoDTO.class);
+ User user = userMap.getOrDefault(comment.getUserId(), new User());
+ commentInfoDTO.setUserAvatar(user.getAvatar());
+ commentInfoDTO.setUserName(user.getUsername());
+ return commentInfoDTO;
+ });
}
- private List convertToDTO(List comments) {
+ private List convertToDTO(List commentList) {
List dtos = new ArrayList<>();
- for (Comment comment : comments) {
+ for (Comment comment : commentList) {
CommentInfoDTO dto = new CommentInfoDTO();
BeanUtils.copyProperties(comment, dto);
dtos.add(dto);
@@ -93,16 +152,14 @@ public class CommentServiceImpl extends ServiceImpl impl
return dtos;
}
- private List buildNestedComments(List comments) {
+ // 根据评论创建嵌套评论,目前没用到
+ private List buildNestedCommentList(List comments) {
Map map = new HashMap<>();
List rootComments = new ArrayList<>();
-
for (Comment comment : comments) {
CommentInfoDTO dto = new CommentInfoDTO();
BeanUtils.copyProperties(comment, dto);
-
map.put(comment.getId(), dto);
-
if (comment.getParentCommentId() == null) {
rootComments.add(dto);
} else {
@@ -115,7 +172,6 @@ public class CommentServiceImpl extends ServiceImpl impl
}
}
}
-
return rootComments;
}
}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/impl/PostServiceImpl.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/impl/PostServiceImpl.java
index 0f31108..7c80b53 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/impl/PostServiceImpl.java
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/service/impl/PostServiceImpl.java
@@ -11,18 +11,28 @@ import com.luojia_channel.common.utils.PageUtil;
import com.luojia_channel.common.utils.RedisUtil;
import com.luojia_channel.common.utils.UserContext;
import com.luojia_channel.modules.file.service.impl.FileServiceImpl;
+import com.luojia_channel.modules.post.dto.req.CommentPageQueryDTO;
import com.luojia_channel.modules.post.dto.req.PostSaveDTO;
import com.luojia_channel.modules.post.dto.req.PostPageQueryDTO;
+import com.luojia_channel.modules.post.dto.resp.CommentInfoDTO;
import com.luojia_channel.modules.post.dto.resp.PostBasicInfoDTO;
+import com.luojia_channel.modules.post.dto.resp.PostInfoDTO;
+import com.luojia_channel.modules.post.entity.Comment;
import com.luojia_channel.modules.post.entity.Post;
import com.luojia_channel.modules.post.mapper.PostMapper;
import com.luojia_channel.modules.post.service.PostService;
import com.luojia_channel.modules.post.utils.ValidatePostUtil;
+import com.luojia_channel.modules.user.entity.User;
+import com.luojia_channel.modules.user.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@@ -32,13 +42,12 @@ public class PostServiceImpl extends ServiceImpl implements Po
private final FileServiceImpl fileService;
private final ValidatePostUtil validatePostUtil;
private final RedisUtil redisUtil;
+ private final UserMapper userMapper;
@Override
public void createPost(PostSaveDTO postSaveDTO) {
validatePostUtil.validatePost(postSaveDTO);
- Long userId = UserContext.getUserId();
Post post = BeanUtil.copyProperties(postSaveDTO, Post.class);
- post.setUserId(userId);
if(!save(post)){
throw new PostException("创建帖子失败");
}
@@ -52,6 +61,7 @@ public class PostServiceImpl extends ServiceImpl implements Po
@Override
public void updatePost(PostSaveDTO postSaveDTO) {
validatePostUtil.validatePost(postSaveDTO);
+ validatePostUtil.validatePostOwnership(postSaveDTO.getId());
Post post = BeanUtil.copyProperties(postSaveDTO, Post.class);
post.setUpdateTime(LocalDateTime.now());
if(!updateById(post)){
@@ -69,15 +79,21 @@ public class PostServiceImpl extends ServiceImpl implements Po
}
@Override
- public Post getPostDetail(Long id) {
- return redisUtil.safeGet("post:detail" + id.toString(), Post.class,
+ public PostInfoDTO getPostDetail(Long id) {
+ return redisUtil.safeGet("post:detail" + id.toString(), PostInfoDTO.class,
() -> {
Post post = getById(id);
if(post == null){
throw new PostException("帖子不存在或被删除");
}
- return post;
- }, 10, TimeUnit.MINUTES);
+ PostInfoDTO postInfoDTO = BeanUtil.copyProperties(post, PostInfoDTO.class);
+ User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
+ .eq(User::getId, post.getUserId()));
+ postInfoDTO.setUserAvatar(user.getAvatar());
+ postInfoDTO.setUserName(user.getUsername());
+ return postInfoDTO;
+ },
+ 60, TimeUnit.MINUTES);
}
@Override
@@ -86,10 +102,23 @@ public class PostServiceImpl extends ServiceImpl implements Po
LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(Post.class)
.orderByDesc(Post::getCreateTime);
IPage postPage = postMapper.selectPage(PageUtil.convert(postPageQueryDTO), queryWrapper);
- return PageUtil.convert(postPage, PostBasicInfoDTO.class);
+ List userIds = new ArrayList<>();
+ postPage.getRecords().forEach(comment -> {
+ userIds.add(comment.getUserId());
+ });
+ List users = userMapper.selectBatchIds(userIds);
+ Map userMap = users.stream()
+ .collect(Collectors.toMap(User::getId, user -> user));
+ // 组装用户头像与名称,批量查询只要查一次数据库
+ return PageUtil.convert(postPage, post -> {
+ PostBasicInfoDTO postBasicInfoDTO = BeanUtil.copyProperties(post, PostBasicInfoDTO.class);
+ User user = userMap.getOrDefault(post.getUserId(), new User());
+ postBasicInfoDTO.setUserAvatar(user.getAvatar());
+ postBasicInfoDTO.setUserName(user.getUsername());
+ return postBasicInfoDTO;
+ });
}
-
@Override
public PageResponse pagePostOfMe(PostPageQueryDTO postPageQueryDTO) {
Long userId = UserContext.getUserId();
@@ -99,4 +128,5 @@ public class PostServiceImpl extends ServiceImpl implements Po
IPage postPage = postMapper.selectPage(PageUtil.convert(postPageQueryDTO), queryWrapper);
return PageUtil.convert(postPage, PostBasicInfoDTO.class);
}
+
}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/utils/ValidatePostUtil.java b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/utils/ValidatePostUtil.java
index 9a0c2ba..ba5236b 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/utils/ValidatePostUtil.java
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/java/com/luojia_channel/modules/post/utils/ValidatePostUtil.java
@@ -3,8 +3,11 @@ package com.luojia_channel.modules.post.utils;
import cn.hutool.core.util.StrUtil;
import com.luojia_channel.common.exception.PostException;
import com.luojia_channel.common.utils.UserContext;
+import com.luojia_channel.modules.post.dto.req.CommentSaveDTO;
import com.luojia_channel.modules.post.dto.req.PostSaveDTO;
+import com.luojia_channel.modules.post.entity.Comment;
import com.luojia_channel.modules.post.entity.Post;
+import com.luojia_channel.modules.post.mapper.CommentMapper;
import com.luojia_channel.modules.post.mapper.PostMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@@ -16,6 +19,8 @@ public class ValidatePostUtil {
private final PostMapper postMapper;
+ private final CommentMapper commentMapper;
+
public void validatePost(PostSaveDTO postSaveDTO) {
// 非空字段检验
if (StrUtil.isBlank(postSaveDTO.getTitle())) {
@@ -34,6 +39,9 @@ public class ValidatePostUtil {
public void validatePostOwnership(Long id){
Long userId = UserContext.getUserId();
+ if(id == null){
+ throw new PostException("传入id不能为空");
+ }
Post post = postMapper.selectById(id);
if(post == null){
throw new PostException("帖子不存在");
@@ -43,7 +51,32 @@ public class ValidatePostUtil {
}
}
- public void AIValidate(PostSaveDTO postSaveDTO){
+ public void validateComment(CommentSaveDTO commentSaveDTO) {
+ if (StrUtil.isBlank(commentSaveDTO.getContent())) {
+ throw new PostException("内容不能为空");
+ }
+ if (commentSaveDTO.getPostId() == null || commentSaveDTO.getPostId() < 0){
+ throw new PostException("帖子id不合法");
+ }
+ if(commentSaveDTO.getParentCommentId() != null && commentSaveDTO.getParentCommentId() < 0){
+ throw new PostException("父评论id不合法");
+ }
+ if(commentSaveDTO.getTopId() != null && commentSaveDTO.getTopId() <= 0){
+ throw new PostException("顶级评论id不合法");
+ }
+ }
+ public void validateCommentOwnership(Long id) {
+ Long userId = UserContext.getUserId();
+ if(id == null){
+ throw new PostException("传入id不能为空");
+ }
+ Comment comment = commentMapper.selectById(id);
+ if(comment == null){
+ throw new PostException("评论不存在");
+ }
+ if(!userId.equals(comment.getUserId())){
+ throw new PostException("你无权操作他人的评论");
+ }
}
}
diff --git a/珞珈岛-项目相关文件/luojia-island/service/src/main/resources/db/luojia_channel.sql b/珞珈岛-项目相关文件/luojia-island/service/src/main/resources/db/luojia_channel.sql
index b801e0d..d3da488 100644
--- a/珞珈岛-项目相关文件/luojia-island/service/src/main/resources/db/luojia_channel.sql
+++ b/珞珈岛-项目相关文件/luojia-island/service/src/main/resources/db/luojia_channel.sql
@@ -101,10 +101,11 @@ DROP TABLE IF EXISTS `comment`;
CREATE TABLE `comment` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
`content` TEXT NOT NULL COMMENT '评论内容',
+ `like_count` INT DEFAULT 0 COMMENT '点赞数',
+ `reply_count` INT DEFAULT 0 COMMENT '回复数',
`user_id` BIGINT NOT NULL COMMENT '评论用户ID',
- `post_type` VARCHAR(20) NOT NULL COMMENT '帖子类型(post/video)',
`post_id` BIGINT NOT NULL COMMENT '关联的帖子ID',
- `parent_comment_id` BIGINT COMMENT '父评论ID',
+ `parent_comment_id` BIGINT DEFAULT 0 COMMENT '父评论ID',
`top_id` BIGINT COMMENT '顶层评论ID',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',