diff --git a/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/controller/CommentController.java b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/controller/CommentController.java index f5ec963..c60dbdb 100644 --- a/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/controller/CommentController.java +++ b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/controller/CommentController.java @@ -3,9 +3,7 @@ package com.hanserwei.hannote.comment.biz.controller; import com.hanserwei.framework.biz.operationlog.aspect.ApiOperationLog; import com.hanserwei.framework.common.response.PageResponse; import com.hanserwei.framework.common.response.Response; -import com.hanserwei.hannote.comment.biz.model.vo.FindCommentItemRspVO; -import com.hanserwei.hannote.comment.biz.model.vo.FindCommentPageListReqVO; -import com.hanserwei.hannote.comment.biz.model.vo.PublishCommentReqVO; +import com.hanserwei.hannote.comment.biz.model.vo.*; import com.hanserwei.hannote.comment.biz.service.CommentService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -35,4 +33,10 @@ public class CommentController { return commentService.findCommentPageList(findCommentPageListReqVO); } + @PostMapping("/child/list") + @ApiOperationLog(description = "二级评论分页查询") + public PageResponse findChildCommentPageList(@Validated @RequestBody FindChildCommentPageListReqVO findChildCommentPageListReqVO) { + return commentService.findChildCommentPageList(findChildCommentPageListReqVO); + } + } \ No newline at end of file diff --git a/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/domain/mapper/CommentDOMapper.java b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/domain/mapper/CommentDOMapper.java index e3cc5ef..c69b38d 100644 --- a/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/domain/mapper/CommentDOMapper.java +++ b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/domain/mapper/CommentDOMapper.java @@ -82,4 +82,24 @@ public interface CommentDOMapper extends BaseMapper { * @return 热门评论 */ List selectHeatComments(Long noteId); + + /** + * 查询一级评论下子评论总数 + * + * @param commentId 一级评论 ID + * @return 一级评论下子评论总数 + */ + Long selectChildCommentTotalById(Long commentId); + + /** + * 查询二级评论分页数据 + * + * @param parentId 一级评论 ID + * @param offset 偏移量 + * @param pageSize 页大小 + * @return 二级评论分页数据 + */ + List selectChildPageList(@Param("parentId") Long parentId, + @Param("offset") long offset, + @Param("pageSize") long pageSize); } \ No newline at end of file diff --git a/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/model/vo/FindChildCommentItemRspVO.java b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/model/vo/FindChildCommentItemRspVO.java new file mode 100644 index 0000000..e39650e --- /dev/null +++ b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/model/vo/FindChildCommentItemRspVO.java @@ -0,0 +1,63 @@ +package com.hanserwei.hannote.comment.biz.model.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class FindChildCommentItemRspVO { + + /** + * 评论 ID + */ + private Long commentId; + + /** + * 发布者用户 ID + */ + private Long userId; + + /** + * 头像 + */ + private String avatar; + + /** + * 昵称 + */ + private String nickname; + + /** + * 评论内容 + */ + private String content; + + /** + * 评论内容 + */ + private String imageUrl; + + /** + * 发布时间 + */ + private String createTime; + + /** + * 被点赞数 + */ + private Long likeTotal; + + /** + * 回复的用户昵称 + */ + private String replyUserName; + + /** + * 回复的用户 ID + */ + private Long replyUserId; +} \ No newline at end of file diff --git a/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/model/vo/FindChildCommentPageListReqVO.java b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/model/vo/FindChildCommentPageListReqVO.java new file mode 100644 index 0000000..1c3970e --- /dev/null +++ b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/model/vo/FindChildCommentPageListReqVO.java @@ -0,0 +1,20 @@ +package com.hanserwei.hannote.comment.biz.model.vo; + +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class FindChildCommentPageListReqVO { + + @NotNull(message = "父评论 ID 不能为空") + private Long parentCommentId; + + @NotNull(message = "页码不能为空") + private Integer pageNo = 1; +} \ No newline at end of file diff --git a/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/service/CommentService.java b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/service/CommentService.java index c808945..b6baf24 100644 --- a/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/service/CommentService.java +++ b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/service/CommentService.java @@ -4,9 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.hanserwei.framework.common.response.PageResponse; import com.hanserwei.framework.common.response.Response; import com.hanserwei.hannote.comment.biz.domain.dataobject.CommentDO; -import com.hanserwei.hannote.comment.biz.model.vo.FindCommentItemRspVO; -import com.hanserwei.hannote.comment.biz.model.vo.FindCommentPageListReqVO; -import com.hanserwei.hannote.comment.biz.model.vo.PublishCommentReqVO; +import com.hanserwei.hannote.comment.biz.model.vo.*; public interface CommentService extends IService { /** @@ -24,4 +22,12 @@ public interface CommentService extends IService { * @return 响应 */ PageResponse findCommentPageList(FindCommentPageListReqVO findCommentPageListReqVO); + + /** + * 二级评论分页查询 + * + * @param findChildCommentPageListReqVO 二级评论分页查询参数 + * @return 响应 + */ + PageResponse findChildCommentPageList(FindChildCommentPageListReqVO findChildCommentPageListReqVO); } diff --git a/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/service/impl/CommentServiceImpl.java b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/service/impl/CommentServiceImpl.java index 35fa263..29ec7a2 100644 --- a/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/service/impl/CommentServiceImpl.java +++ b/han-note-comment/han-note-comment-biz/src/main/java/com/hanserwei/hannote/comment/biz/service/impl/CommentServiceImpl.java @@ -8,6 +8,7 @@ import com.github.benmanes.caffeine.cache.Caffeine; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import com.hanserwei.framework.biz.context.holder.LoginUserContextHolder; import com.hanserwei.framework.common.constant.DateConstants; import com.hanserwei.framework.common.exception.ApiException; @@ -22,9 +23,7 @@ import com.hanserwei.hannote.comment.biz.domain.mapper.CommentDOMapper; import com.hanserwei.hannote.comment.biz.domain.mapper.NoteCountDOMapper; import com.hanserwei.hannote.comment.biz.enums.ResponseCodeEnum; import com.hanserwei.hannote.comment.biz.model.dto.PublishCommentMqDTO; -import com.hanserwei.hannote.comment.biz.model.vo.FindCommentItemRspVO; -import com.hanserwei.hannote.comment.biz.model.vo.FindCommentPageListReqVO; -import com.hanserwei.hannote.comment.biz.model.vo.PublishCommentReqVO; +import com.hanserwei.hannote.comment.biz.model.vo.*; import com.hanserwei.hannote.comment.biz.retry.SendMqRetryHelper; import com.hanserwei.hannote.comment.biz.rpc.DistributedIdGeneratorRpcService; import com.hanserwei.hannote.comment.biz.rpc.KeyValueRpcService; @@ -300,6 +299,133 @@ public class CommentServiceImpl extends ServiceImpl return PageResponse.success(commentRspVOS, pageNo, count, pageSize); } + @Override + public PageResponse findChildCommentPageList(FindChildCommentPageListReqVO findChildCommentPageListReqVO) { + // 父评论 ID + Long parentCommentId = findChildCommentPageListReqVO.getParentCommentId(); + // 当前页码 + Integer pageNo = findChildCommentPageListReqVO.getPageNo(); + // 每页展示的二级评论数 (小红书 APP 中是一次查询 6 条) + long pageSize = 6; + + // TODO:先从缓存中查询,待完善 + + // 查询一级评论下的子评论数目 + Long count = commentDOMapper.selectChildCommentTotalById(parentCommentId); + + // 若一级评论不存在或者评论数目为0,则直接返回 + if (Objects.isNull(count) || count == 0) { + return PageResponse.success(null, pageNo, 0); + } + + // 分页返回参数VO + List childCommentRspVOS = Lists.newArrayList(); + + // 计算分页查询的偏移量offset(需要加1,因为最早回复的二级评论已经被展示了) + long offset = PageResponse.getOffset(pageNo, pageSize) + 1; + + // 分页查询子评论 + List childCommentDOS = commentDOMapper.selectChildPageList(parentCommentId, offset, pageSize); + + // 调用KV服务需要的入参 + List findCommentContentReqDTOS = Lists.newArrayList(); + // 调用用户服务需要的入参 + Set userIds = Sets.newHashSet(); + + // 归属的笔记ID + Long noteId = null; + + // 循环提取RPC调用所需要的入参数据 + for (CommentDO childCommentDO : childCommentDOS) { + noteId = childCommentDO.getNoteId(); + // 构建调用KV服务批量查询评论内容的入参 + Boolean isContentEmpty = childCommentDO.getIsContentEmpty(); + if (!isContentEmpty) { + FindCommentContentReqDTO findCommentContentReqDTO = FindCommentContentReqDTO.builder() + .contentId(childCommentDO.getContentUuid()) + .yearMonth(DateConstants.DATE_FORMAT_Y_M.format(childCommentDO.getCreateTime())) + .build(); + findCommentContentReqDTOS.add(findCommentContentReqDTO); + } + // 构建调用用户服务批量查询用户信息入参 + userIds.add(childCommentDO.getUserId()); + + Long parentId = childCommentDO.getParentId(); + Long replyCommentId = childCommentDO.getReplyCommentId(); + // 若当前评论的 replyCommentId 不等于 parentId,则前端需要展示回复的哪个用户,如 “回复 Hanserwei:” + if (!Objects.equals(parentId, replyCommentId)) { + userIds.add(childCommentDO.getReplyUserId()); + } + } + + // RPC 调用KV服务批量查询评论内容 + List findCommentContentRspDTOS = keyValueRpcService.batchFindCommentContent(noteId, findCommentContentReqDTOS); + + // DTO转Map方便后续拼接数据 + Map commentUuidAndContentMap = null; + if (CollUtil.isNotEmpty(findCommentContentRspDTOS)) { + commentUuidAndContentMap = findCommentContentRspDTOS.stream() + .collect(Collectors.toMap(FindCommentContentRspDTO::getContentId, FindCommentContentRspDTO::getContent)); + } + + // RPC 调用用户服务批量查询用户信息 + List findUserByIdRspDTOS = userRpcService.findByIds(userIds.stream().toList()); + + // DTO转Map方便后续拼接数据 + Map userIdAndDTOMap = null; + if (CollUtil.isNotEmpty(findUserByIdRspDTOS)) { + userIdAndDTOMap = findUserByIdRspDTOS.stream() + .collect(Collectors.toMap(FindUserByIdRspDTO::getId, e -> e)); + } + + // DO 转 VO + for (CommentDO childCommentDO : childCommentDOS) { + // 构建 VO 实体类 + Long userId = childCommentDO.getUserId(); + FindChildCommentItemRspVO childCommentRspVO = FindChildCommentItemRspVO.builder() + .userId(userId) + .commentId(childCommentDO.getId()) + .imageUrl(childCommentDO.getImageUrl()) + .createTime(DateUtils.formatRelativeTime(childCommentDO.getCreateTime())) + .likeTotal(childCommentDO.getLikeTotal()) + .build(); + + // 填充用户信息(包括评论发布者、回复的用户) + if (CollUtil.isNotEmpty(userIdAndDTOMap)) { + FindUserByIdRspDTO findUserByIdRspDTO = userIdAndDTOMap.get(userId); + // 评论发布者用户信息(头像、昵称) + if (Objects.nonNull(findUserByIdRspDTO)) { + childCommentRspVO.setAvatar(findUserByIdRspDTO.getAvatar()); + childCommentRspVO.setNickname(findUserByIdRspDTO.getNickName()); + } + + // 评论回复的哪个 + Long replyCommentId = childCommentDO.getReplyCommentId(); + Long parentId = childCommentDO.getParentId(); + + if (Objects.nonNull(replyCommentId) + && !Objects.equals(replyCommentId, parentId)) { + Long replyUserId = childCommentDO.getReplyUserId(); + FindUserByIdRspDTO replyUser = userIdAndDTOMap.get(replyUserId); + childCommentRspVO.setReplyUserName(replyUser.getNickName()); + childCommentRspVO.setReplyUserId(replyUser.getId()); + } + } + + // 评论内容 + if (CollUtil.isNotEmpty(commentUuidAndContentMap)) { + String contentUuid = childCommentDO.getContentUuid(); + if (StringUtils.isNotBlank(contentUuid)) { + childCommentRspVO.setContent(commentUuidAndContentMap.get(contentUuid)); + } + } + + childCommentRspVOS.add(childCommentRspVO); + } + + return PageResponse.success(childCommentRspVOS, pageNo, count, pageSize); + } + /** * 同步评论详情到本地缓存中 * diff --git a/han-note-comment/han-note-comment-biz/src/main/resources/mapperxml/CommentDOMapper.xml b/han-note-comment/han-note-comment-biz/src/main/resources/mapperxml/CommentDOMapper.xml index 2f48c0b..8a80971 100644 --- a/han-note-comment/han-note-comment-biz/src/main/resources/mapperxml/CommentDOMapper.xml +++ b/han-note-comment/han-note-comment-biz/src/main/resources/mapperxml/CommentDOMapper.xml @@ -154,4 +154,30 @@ order by heat desc limit 500 + + + + \ No newline at end of file diff --git a/http-client/gateApi.http b/http-client/gateApi.http index 687727f..d3c0382 100644 --- a/http-client/gateApi.http +++ b/http-client/gateApi.http @@ -356,3 +356,13 @@ Content-Type: application/json "noteId": 1862481582414102549, "pageNo": 1 } + +### 分页查询子评论 +POST http://localhost:8000/comment/comment/child/list +Content-Type: application/json +Authorization: Bearer {{token}} + +{ + "parentCommentId": 4002, + "pageNo": 1 +}