评论回复 评论树形列表 评论点赞 回复点赞 具体实现思路。

最近做的社交ai项目 涉及到评论回复这一功能模块的实现。

数据层用的jpa

-- mixmix.t_agents_comment definition

CREATE TABLE `t_agents_comment` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '评论ID',
  `content` text NOT NULL COMMENT '评论内容',
  `user_id` bigint(20) NOT NULL COMMENT '评论用户ID',
  `target_id` bigint(20) NOT NULL COMMENT '评论目标ID(如文章ID、视频ID等)',
  `target_type` tinyint(4) NOT NULL COMMENT '评论目标类型(1.智能体评论 2.文章等等)',
  `like_count` int(11) DEFAULT '0' COMMENT '点赞数',
  `reply_count` int(11) DEFAULT '0' COMMENT '回复数',
  `status` tinyint(4) DEFAULT '1' COMMENT '状态(0:删除 1:正常)',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_target` (`target_id`,`target_type`),
  KEY `idx_user` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='评论表';
-- mixmix.t_agents_comment_like definition

CREATE TABLE `t_agents_comment_like` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `comment_id` bigint(20) NOT NULL COMMENT '评论ID',
  `user_id` bigint(20) NOT NULL COMMENT '用户ID',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_comment_user` (`comment_id`,`user_id`) COMMENT '评论用户联合唯一索引'
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='评论点赞表';
-- mixmix.t_agents_reply definition

CREATE TABLE `t_agents_reply` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '回复ID',
  `content` text NOT NULL COMMENT '回复内容',
  `comment_id` bigint(20) NOT NULL COMMENT '原评论ID',
  `reply_id` bigint(20) DEFAULT NULL COMMENT '回复ID',
  `user_id` bigint(20) NOT NULL COMMENT '回复用户ID',
  `reply_user_id` bigint(20) DEFAULT NULL COMMENT '被回复用户ID',
  `like_count` int(11) DEFAULT '0' COMMENT '点赞数',
  `reply_level` int(11) DEFAULT '1' COMMENT '回复层级(1级为直接回复评论,2级及以上为回复其他回复)',
  `status` tinyint(4) DEFAULT '1' COMMENT '状态(0:删除 1:正常)',
  `parent_id` bigint(20) DEFAULT NULL COMMENT '父回复ID(回复其他回复时使用)',
  `root_id` bigint(20) DEFAULT NULL COMMENT '回复树根ID(用于优化查询)',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_comment` (`comment_id`),
  KEY `idx_parent` (`parent_id`),
  KEY `idx_user` (`user_id`),
  KEY `idx_root` (`root_id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COMMENT='评论回复表';
-- mixmix.t_agents_reply_like definition

CREATE TABLE `t_agents_reply_like` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `reply_id` bigint(20) NOT NULL COMMENT '回复ID',
  `user_id` bigint(20) NOT NULL COMMENT '用户ID',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_reply_user` (`reply_id`,`user_id`) COMMENT '回复用户联合唯一索引'
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='回复点赞记录表';

主要是评论回复表,评论表中的target_id 就是要评论的实体(如评论智能体,评论文章等等),每条评论也会有自己的回复总数和点赞总数,此处需要考虑线程安全问题。回复表中有评论id号作为关联,reply_id相当于paraentid,这张表parentid rootid暂时没用到,当评论时 如果是第一条评论 ,不需要传reply_id,这里也是有点赞数的统计。

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CommentDTO {
    private Long id;
    private Long userId;
    private Long targetId;
    private Integer targetType;
    private String content;
    private Integer likeCount;
    private Integer replyCount;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    // 用户信息,需要根据实际情况补充
    private String user;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CommentReplyDTO {
    private Long id;
    private Long commentId;
    private Long userId;
    private Long replyId;
    private Long replyUserId;
    private String content;
    private Integer likeCount;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    // 用户信息,需要根据实际情况补充
    private String user;
    private String replyUser;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CommentReplyTreeDTO {
    private Long id;
    private Long commentId;
    private Long userId;
    private Long replyId;
    private Long replyUserId;
    private String content;
    private Integer likeCount;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    private List<CommentReplyTreeDTO> children;
    private String avatarUrl;
    private String nickname;
    private String userName;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CommentTreeDTO {
    private Long id;
    private Long userId;
    private String avatarUrl;
    private String nickname;
    private String userName;
    private Long targetId;
    private Integer targetType;
    private String content;
    private Integer likeCount;
    private Integer replyCount;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    private List<CommentReplyTreeDTO> replies;
}
@Entity
@Table(name = "t_agents_comment")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Comment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "user_id", nullable = false)
    private Long userId;

    @Column(name = "target_id", nullable = false)
    private Long targetId;

    @Column(name = "target_type", nullable = false)
    private Integer targetType;

    @Column(nullable = false)
    private String content;

    @Column(name = "like_count")
    private Integer likeCount;

    @Column(name = "reply_count")
    private Integer replyCount;

    @Column(nullable = false)
    private Integer status;

    @Column(name = "create_time", nullable = false)
    private LocalDateTime createTime;

    @Column(name = "update_time", nullable = false)
    private LocalDateTime updateTime;
}
@Entity
@Table(name = "t_agents_comment_like", uniqueConstraints = {
        @UniqueConstraint(columnNames = {"comment_id", "user_id"})
})
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CommentLike {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "comment_id", nullable = false)
    private Long commentId;

    @Column(name = "user_id", nullable = false)
    private Long userId;

    @Column(name = "create_time", nullable = false)
    private LocalDateTime createTime;
}
@Entity
@Table(name = "t_agents_reply")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CommentReply {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "comment_id", nullable = false)
    private Long commentId;

    @Column(name = "parent_id")
    private Long parentId;

    @Column(name = "user_id", nullable = false)
    private Long userId;

    @Column(name = "reply_id")
    private Long replyId;

    @Column(name = "reply_user_id")
    private Long replyUserId;

    @Column(nullable = false)
    private String content;

    @Column(name = "like_count")
    private Integer likeCount;

    @Column(nullable = false)
    private Integer status;

    @Column(name = "reply_level", nullable = false)
    private Integer replyLevel;

    @Column(name = "create_time", nullable = false)
    private LocalDateTime createTime;

    @Column(name = "update_time", nullable = false)
    private LocalDateTime updateTime;
}@Entity
@Table(name = "t_agents_reply_like", uniqueConstraints = {
        @UniqueConstraint(columnNames = {"reply_id", "user_id"})
})
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ReplyLike {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "reply_id", nullable = false)
    private Long replyId;

    @Column(name = "user_id", nullable = false)
    private Long userId;

    @Column(name = "create_time", nullable = false)
    private LocalDateTime createTime;
}

public interface TAgentsCommentLikeRepo extends EnhancedRepo<CommentLike, Long> {
    boolean existsByCommentIdAndUserId(Long commentId, Long userId);
}
public interface TAgentsCommentRepo extends EnhancedRepo<Comment, Long> {
    @Query("SELECT c FROM Comment c WHERE c.targetId = :targetId AND c.targetType = :targetType AND c.status = 1 ORDER BY c.createTime asc")
    Page<Comment> findByTargetIdAndType(
            @Param("targetId") Long targetId,
            @Param("targetType") Integer targetType,
            Pageable pageable
    );

    @Query("SELECT COUNT(c) > 0 FROM CommentLike c WHERE c.commentId = :commentId AND c.userId = :userId")
    boolean existsByCommentIdAndUserId(@Param("commentId") Long commentId, @Param("userId") Long userId);

    @Modifying
    @Query("UPDATE Comment c SET c.likeCount = c.likeCount + 1 WHERE c.id = :commentId")
    void incrementLikeCount(@Param("commentId") Long commentId);

    @Modifying
    @Query("UPDATE Comment c SET c.replyCount = c.replyCount + 1 WHERE c.id = :commentId")
    void incrementReplyCount(@Param("commentId") Long commentId);

    @Modifying
    @Query("UPDATE Comment c SET c.replyCount = c.replyCount - 1 WHERE c.id = :commentId AND c.replyCount > 0")
    void decrementReplyCount(@Param("commentId") Long commentId);
}

public interface TAgentsReplyLikeRepo extends EnhancedRepo<ReplyLike, Long> {
    boolean existsByReplyIdAndUserId(Long replyId, Long userId);
}
public interface TAgentsReplyRepo extends EnhancedRepo<CommentReply, Long> {
    @Query("SELECT r FROM CommentReply r WHERE r.commentId = :commentId AND r.status = 1 ORDER BY r.createTime asc")
    Page<CommentReply> findByCommentId(@Param("commentId") Long commentId, Pageable pageable);

    @Query("SELECT COUNT(c) > 0 FROM ReplyLike c WHERE c.replyId = :replyId AND c.userId = :userId")
    boolean existsByReplyIdAndUserId(@Param("replyId") Long replyId, @Param("userId") Long userId);

    @Modifying
    @Query("UPDATE CommentReply r SET r.likeCount = r.likeCount + 1 WHERE r.id = :replyId")
    void incrementLikeCount(@Param("replyId") Long replyId);

    @Modifying
    @Query("UPDATE CommentReply r SET r.status = :status WHERE r.commentId = :commentId")
    void updateStatusByCommentId(@Param("commentId") Long commentId, @Param("status") Integer status);

    /**
     * 获取评论下的所有回复
     *
     * @param commentId 评论ID
     * @return 回复列表
     */
    @Query("SELECT r FROM CommentReply r WHERE r.commentId = :commentId AND r.status = 1 ORDER BY r.createTime asc")
    List<CommentReply> findAllByCommentId(@Param("commentId") Long commentId);
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CommentReplyRequest {
    @NotNull(message = "评论ID不能为空")
    private Long commentId;

    @NotNull(message = "用户ID不能为空")
    private Long userId;

    private Long replyId;

    private Long parentId;

    @NotBlank(message = "回复内容不能为空")
    @Length(max = 500, message = "回复内容不能超过500字")
    private String content;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CommentRequest {
    @NotNull(message = "用户ID不能为空")
    private Long userId;

    @NotNull(message = "目标ID不能为空")
    private Long targetId;

    private Integer targetType = 1;

    @NotBlank(message = "评论内容不能为空")
    @Length(max = 500, message = "评论内容不能超过500字")
    private String content;
}

上边是vo和dto request repo数据层 

@ModelService(ModelEnum.UNDEFINED)
@Slf4j
public class CommentServiceImpl {

    @Autowired
    private TAgentsCommentRepo commentRepository;

    @Autowired
    private TAgentsReplyRepo replyRepository;
    @Autowired
    private TAgentsCommentLikeRepo commentLikeRepository;

    @Autowired
    private TAgentsReplyLikeRepo replyLikeRepository;

    @Autowired
    private PcMemberRepo pcMemberRepo;

    @Transactional
    public CommentDTO createComment(CommentRequest request) {
        // 参数校验
        if (StringUtils.isBlank(request.getContent())) {
            throw new IllegalArgumentException("评论内容不能为空");
        }

        // 构建评论实体
        Comment comment = Comment.builder()
                .userId(request.getUserId())
                .targetId(request.getTargetId())
                .targetType(request.getTargetType())
                .content(request.getContent())
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .likeCount(0)
                .replyCount(0)
                .status(1)
                .build();

        // 保存评论
        comment = commentRepository.save(comment);

        // 转换为DTO返回
        return convertToDTO(comment);
    }

    @Transactional
    public CommentReplyDTO createReply(CommentReplyRequest request) {
        // 参数校验
        if (StringUtils.isBlank(request.getContent())) {
            throw new IllegalArgumentException("回复内容不能为空");
        }
        // 检查评论是否存在
        Comment comment = commentRepository.findById(request.getCommentId())
                .orElseThrow(() -> new IllegalArgumentException("评论不存在"));
        Long replyId = request.getReplyId();
        int replyLevel = 1;
        if (replyId != null && replyId >= 0) {
            CommentReply commentReply = replyRepository.findById(replyId)
                    .orElseThrow(() -> new IllegalArgumentException("回复目标不存在"));
            replyLevel = 2;
        }

        // 构建回复实体
        CommentReply.CommentReplyBuilder builder = CommentReply.builder()
                .commentId(request.getCommentId())
                .userId(request.getUserId())
                .content(request.getContent())
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .likeCount(0)
                .replyLevel(replyLevel)
                .status(1);

        // 设置回复目标
        if (request.getReplyId() != null) {
            CommentReply targetReply = replyRepository.findById(request.getReplyId())
                    .orElseThrow(() -> new IllegalArgumentException("回复的目标不存在"));
            builder.replyId(request.getReplyId())
                    .replyUserId(targetReply.getUserId());
        }

        // 保存回复
        CommentReply reply = replyRepository.save(builder.build());

        // 更新评论的回复数
        commentRepository.incrementReplyCount(comment.getId());

        // 转换为DTO返回
        return convertToReplyDTO(reply);
    }

    public List<CommentDTO> getCommentTree(Long targetId, Integer targetType, Integer page, Integer size) {
        // 分页查询评论列表
        PageRequest pageRequest = PageRequest.of(page - 1, size);
        Page<Comment> commentPage = commentRepository.findByTargetIdAndType(targetId, targetType, pageRequest);

        // 转换为DTO
        return commentPage.getContent().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    public List<CommentReplyDTO> getReplyList(Long commentId, Integer page, Integer size) {
        // 分页查询回复列表
        PageRequest pageRequest = PageRequest.of(page - 1, size);
        Page<CommentReply> replyPage = replyRepository.findByCommentId(commentId, pageRequest);

        // 转换为DTO
        return replyPage.getContent().stream()
                .map(this::convertToReplyDTO)
                .collect(Collectors.toList());
    }

    @Transactional
    public void deleteComment(Long commentId, Long userId) {
        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new IllegalArgumentException("评论不存在"));

        // 检查权限
        if (!comment.getUserId().equals(userId)) {
            throw new IllegalArgumentException("无权删除该评论");
        }

        // 删除评论(软删除)
        comment.setStatus(0);
        comment.setUpdateTime(LocalDateTime.now());
        commentRepository.save(comment);

        // 删除关联的回复
        replyRepository.updateStatusByCommentId(commentId, 0);
    }

    @Transactional
    public void deleteReply(Long replyId, Long userId) {
        CommentReply reply = replyRepository.findById(replyId)
                .orElseThrow(() -> new IllegalArgumentException("回复不存在"));

        // 检查权限
        if (!reply.getUserId().equals(userId)) {
            throw new IllegalArgumentException("无权删除该回复");
        }

        // 删除回复(软删除)
        reply.setStatus(0);
        reply.setUpdateTime(LocalDateTime.now());
        replyRepository.save(reply);

        // 更新评论的回复数
        commentRepository.decrementReplyCount(reply.getCommentId());
    }

    private CommentDTO convertToDTO(Comment comment) {
        if (comment == null) {
            return null;
        }

        return CommentDTO.builder()
                .id(comment.getId())
                .userId(comment.getUserId())
                .targetId(comment.getTargetId())
                .targetType(comment.getTargetType())
                .content(comment.getContent())
                .likeCount(comment.getLikeCount())
                .replyCount(comment.getReplyCount())
                .createTime(comment.getCreateTime())
                .build();
    }

    private CommentReplyDTO convertToReplyDTO(CommentReply reply) {
        if (reply == null) {
            return null;
        }

        return CommentReplyDTO.builder()
                .id(reply.getId())
                .commentId(reply.getCommentId())
                .userId(reply.getUserId())
                .replyId(reply.getReplyId())
                .replyUserId(reply.getReplyUserId())
                .content(reply.getContent())
                .likeCount(reply.getLikeCount())
                .createTime(reply.getCreateTime())
                .build();
    }

    @Transactional
    public void likeComment(Long commentId, Long userId) {
        // 检查评论是否存在
        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new IllegalArgumentException("评论不存在"));

        // 检查是否已点赞
        if (commentLikeRepository.existsByCommentIdAndUserId(commentId, userId)) {
            throw new IllegalArgumentException("已经点赞过该评论");
        }

        // 添加点赞记录
        CommentLike like = CommentLike.builder()
                .commentId(commentId)
                .userId(userId)
                .createTime(LocalDateTime.now())
                .build();
        commentLikeRepository.save(like);

        // 更新点赞数
        commentRepository.incrementLikeCount(commentId);
    }

    @Transactional
    public void likeReply(Long replyId, Long userId) {
        // 检查回复是否存在
        CommentReply reply = replyRepository.findById(replyId)
                .orElseThrow(() -> new IllegalArgumentException("回复不存在"));

        // 检查是否已点赞
        if (replyLikeRepository.existsByReplyIdAndUserId(replyId, userId)) {
            throw new IllegalArgumentException("已经点赞过该回复");
        }

        // 添加点赞记录
        ReplyLike like = ReplyLike.builder()
                .replyId(replyId)
                .userId(userId)
                .createTime(LocalDateTime.now())
                .build();
        replyLikeRepository.save(like);

        // 更新点赞数
        replyRepository.incrementLikeCount(replyId);
    }

    public List<CommentTreeDTO> getCommentTreeList(Long targetId, Integer targetType, Integer page, Integer size) {
        // 获取评论列表
        PageRequest pageRequest = PageRequest.of(page - 1, size);
        Page<Comment> commentPage = commentRepository.findByTargetIdAndType(targetId, targetType, pageRequest);
        List<Comment> content = commentPage.getContent();
        if (CollectionUtils.isEmpty(content)) {
            return Collections.emptyList();
        }
        // 转换为树形结构
        return content.stream()
                .map(comment -> {
                    Long userId = comment.getUserId();
                    List<PcMember> member = pcMemberRepo.findAll(SpecTool.and(SpecTool.eq(PcMember_.id, userId.intValue())));
                    PcMember pcMember = member.get(0);
                    CommentTreeDTO dto = CommentTreeDTO.builder()
                            .id(comment.getId())
                            .userId(comment.getUserId())
                            .targetId(comment.getTargetId())
                            .targetType(comment.getTargetType())
                            .content(comment.getContent())
                            .likeCount(comment.getLikeCount())
                            .replyCount(comment.getReplyCount())
                            .createTime(comment.getCreateTime())
                            .avatarUrl(pcMember.getNewImg())
                            .nickname(pcMember.getNickname())
                            .userName(pcMember.getGagaNo())
                            .build();

                    // 获取该评论的所有回复
                    List<CommentReply> replies = replyRepository.findAllByCommentId(comment.getId());
                    dto.setReplies(buildReplyTree(replies));
                    return dto;
                })
                .collect(Collectors.toList());
    }

    private List<CommentReplyTreeDTO> buildReplyTree(List<CommentReply> replies) {
        // 收集所有涉及的用户ID
        Set<Long> userIds = new HashSet<>();
        replies.forEach(reply -> {
            userIds.add(reply.getUserId());
            if (reply.getReplyUserId() != null) {
                userIds.add(reply.getReplyUserId());
            }
        });

        // 批量查询所有用户信息
        Map<Long, PcMember> userMap = new HashMap<>();
        if (!userIds.isEmpty()) {
            List<PcMember> members = pcMemberRepo.findAll(
                    SpecTool.and(SpecTool.in(PcMember_.id, userIds.stream().map(Long::intValue).collect(Collectors.toList())))
            );
            members.forEach(member -> userMap.put((long) member.getId(), member));
        }

        // 构建回复ID到回复对象的映射,并关联用户信息
        Map<Long, CommentReplyTreeDTO> replyMap = replies.stream()
                .map(reply -> {
                    // 从缓存中获取用户信息
                    PcMember pcMember = userMap.get(reply.getUserId());
                    if (pcMember == null) {
                        pcMember = new PcMember(); // 默认值或空对象
                    }

                    // 构建 DTO
                    return CommentReplyTreeDTO.builder()
                            .id(reply.getId())
                            .commentId(reply.getCommentId())
                            .userId(reply.getUserId())
                            .replyId(reply.getReplyId())
                            .replyUserId(reply.getReplyUserId())
                            .content(reply.getContent())
                            .likeCount(reply.getLikeCount())
                            .createTime(reply.getCreateTime())
                            .avatarUrl(pcMember.getNewImg())
                            .nickname(pcMember.getNickname())
                            .userName(pcMember.getGagaNo())
                            .children(new ArrayList<>())
                            .build();
                })
                .collect(Collectors.toMap(CommentReplyTreeDTO::getId, dto -> dto));

        // 构建树形结构
        List<CommentReplyTreeDTO> rootReplies = new ArrayList<>();
        replyMap.values().forEach(reply -> {
            if (reply.getReplyId() == null) {
                rootReplies.add(reply);
            } else {
                CommentReplyTreeDTO parent = replyMap.get(reply.getReplyId());
                if (parent != null) {
                    parent.getChildren().add(reply);
                }
            }
        });

        return rootReplies;
    }} 
@RestController
@RequestMapping("/comments")
@Slf4j
@Tag(name = "评论管理", description = "评论、回复及点赞相关接口")
@Validated
public class CommentController {

    @Autowired
    private CommentServiceImpl commentService;

    @PostMapping
    @Operation(summary = "发表评论")
    public R<CommentDTO> createComment(@RequestBody @Valid CommentRequest request) {
        return R.success(commentService.createComment(request));
    }

    @PostMapping("/replies")
    @Operation(summary = "发表回复")
    public R<CommentReplyDTO> createReply(
            @RequestBody @Valid CommentReplyRequest request) {
        return R.success(commentService.createReply(request));
    }

    @GetMapping("/tree")
    @Operation(summary = "获取评论树形列表")
    public R<List<CommentTreeDTO>> getCommentTree(
            @RequestParam Long targetId,
            @RequestParam(defaultValue = "1") Integer targetType,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size) {
        return R.success(commentService.getCommentTreeList(targetId, targetType, page, size));
    }

    @GetMapping
    @Operation(summary = "获取评论列表")
    public R<List<CommentDTO>> getComments(
            @RequestParam Long targetId,
            @RequestParam(defaultValue = "1") Integer targetType,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size) {
        return R.success(commentService.getCommentTree(targetId, targetType, page, size));
    }

    @GetMapping("/{commentId}/replies")
    @Operation(summary = "获取回复列表")
    public R<List<CommentReplyDTO>> getReplies(
            @PathVariable Long commentId,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer size) {
        return R.success(commentService.getReplyList(commentId, page, size));
    }

    @DeleteMapping("/{commentId}")
    @Operation(summary = "删除评论")
    public R<Void> deleteComment(
            @PathVariable Long commentId,
            @RequestParam Long userId) {
        commentService.deleteComment(commentId, userId);
        return R.success();
    }

    @DeleteMapping("/replies/{replyId}")
    @Operation(summary = "删除回复")
    public R<Void> deleteReply(
            @PathVariable Long replyId,
            @RequestParam Long userId) {
        commentService.deleteReply(replyId, userId);
        return R.success();
    }

    @PostMapping("/{commentId}/like")
    @Operation(summary = "点赞评论")
    public R<Void> likeComment(
            @PathVariable Long commentId,
            @RequestParam Long userId) {
        commentService.likeComment(commentId, userId);
        return R.success();
    }

    @PostMapping("/replies/{replyId}/like")
    @Operation(summary = "点赞回复")
    public R<Void> likeReply(
            @PathVariable Long replyId,
            @RequestParam Long userId) {
        commentService.likeReply(replyId, userId);
        return R.success();
    }

}
getCommentTree这个接口就是包含评论和所有回复的树形列表。
posted @ 2025-07-19 08:47  Fyy发大财  阅读(13)  评论(0)    收藏  举报