文件生成补充
This commit is contained in:
+91
@@ -0,0 +1,91 @@
|
||||
package fun.nojava.module.comment.controller;
|
||||
|
||||
import fun.nojava.common.model.ApiResult;
|
||||
import fun.nojava.common.model.PageResult;
|
||||
import fun.nojava.module.comment.dto.CommentVO;
|
||||
import fun.nojava.module.comment.dto.CreateCommentDTO;
|
||||
import fun.nojava.module.comment.service.CommentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "评论接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/comment")
|
||||
@RequiredArgsConstructor
|
||||
public class CommentController {
|
||||
|
||||
private final CommentService commentService;
|
||||
|
||||
@Operation(summary = "发表评论")
|
||||
@PostMapping
|
||||
public ApiResult<Long> createComment(
|
||||
@AuthenticationPrincipal Long userId,
|
||||
@Valid @RequestBody CreateCommentDTO dto) {
|
||||
return ApiResult.success(commentService.createComment(userId, dto));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除评论")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<Void> deleteComment(
|
||||
@AuthenticationPrincipal Long userId,
|
||||
@PathVariable Long id) {
|
||||
commentService.deleteComment(userId, id);
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "文章评论列表")
|
||||
@GetMapping("/article/{articleId}")
|
||||
public ApiResult<List<CommentVO>> listArticleComments(
|
||||
@PathVariable Long articleId,
|
||||
@AuthenticationPrincipal Long userId) {
|
||||
return ApiResult.success(commentService.listArticleComments(articleId, userId));
|
||||
}
|
||||
|
||||
@Operation(summary = "点赞评论")
|
||||
@PostMapping("/{id}/like")
|
||||
public ApiResult<Boolean> toggleLike(
|
||||
@PathVariable Long id,
|
||||
@AuthenticationPrincipal Long userId) {
|
||||
return ApiResult.success(commentService.toggleLike(userId, id));
|
||||
}
|
||||
}
|
||||
|
||||
@Tag(name = "管理员-评论管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/admin/comment")
|
||||
@RequiredArgsConstructor
|
||||
class AdminCommentController {
|
||||
|
||||
private final CommentService commentService;
|
||||
|
||||
@Operation(summary = "评论列表")
|
||||
@GetMapping("/list")
|
||||
public ApiResult<PageResult<CommentVO>> listComments(
|
||||
@RequestParam(defaultValue = "1") int page,
|
||||
@RequestParam(defaultValue = "15") int pageSize,
|
||||
@RequestParam(required = false) Integer status) {
|
||||
return ApiResult.success(commentService.listAdminComments(page, pageSize, status));
|
||||
}
|
||||
|
||||
@Operation(summary = "审核评论")
|
||||
@PostMapping("/{id}/audit")
|
||||
public ApiResult<Void> auditComment(
|
||||
@PathVariable Long id,
|
||||
@RequestParam Integer status) {
|
||||
commentService.auditComment(id, status);
|
||||
return ApiResult.success();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除评论")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<Void> deleteComment(@PathVariable Long id) {
|
||||
commentService.auditComment(id, 3);
|
||||
return ApiResult.success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package fun.nojava.module.comment.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CommentVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long articleId;
|
||||
|
||||
private Long userId;
|
||||
|
||||
private String nickname;
|
||||
|
||||
private String avatar;
|
||||
|
||||
private Long parentId;
|
||||
|
||||
private Long replyToId;
|
||||
|
||||
private String replyToNickname;
|
||||
|
||||
private String content;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private Integer likeCount;
|
||||
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
private Boolean liked;
|
||||
|
||||
private List<CommentVO> replies;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package fun.nojava.module.comment.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CreateCommentDTO {
|
||||
|
||||
@NotNull(message = "文章ID不能为空")
|
||||
private Long articleId;
|
||||
|
||||
private Long parentId;
|
||||
|
||||
private Long replyToId;
|
||||
|
||||
@NotBlank(message = "评论内容不能为空")
|
||||
private String content;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package fun.nojava.module.comment.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("comment")
|
||||
public class Comment {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private Long articleId;
|
||||
|
||||
private Long userId;
|
||||
|
||||
private Long parentId;
|
||||
|
||||
private Long replyToId;
|
||||
|
||||
private String content;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private Integer likeCount;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package fun.nojava.module.comment.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("comment_like")
|
||||
public class CommentLike {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private Long commentId;
|
||||
|
||||
private Long userId;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package fun.nojava.module.comment.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import fun.nojava.module.comment.entity.CommentLike;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CommentLikeMapper extends BaseMapper<CommentLike> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package fun.nojava.module.comment.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import fun.nojava.module.comment.entity.Comment;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CommentMapper extends BaseMapper<Comment> {
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package fun.nojava.module.comment.service;
|
||||
|
||||
import fun.nojava.common.model.PageResult;
|
||||
import fun.nojava.module.comment.dto.CommentVO;
|
||||
import fun.nojava.module.comment.dto.CreateCommentDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CommentService {
|
||||
|
||||
Long createComment(Long userId, CreateCommentDTO dto);
|
||||
|
||||
void deleteComment(Long userId, Long commentId);
|
||||
|
||||
List<CommentVO> listArticleComments(Long articleId, Long currentUserId);
|
||||
|
||||
PageResult<CommentVO> listAdminComments(int page, int pageSize, Integer status);
|
||||
|
||||
void auditComment(Long commentId, Integer status);
|
||||
|
||||
boolean toggleLike(Long userId, Long commentId);
|
||||
}
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
package fun.nojava.module.comment.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import fun.nojava.common.enums.CommentStatus;
|
||||
import fun.nojava.common.exception.BusinessException;
|
||||
import fun.nojava.common.exception.ErrorCode;
|
||||
import fun.nojava.common.model.PageResult;
|
||||
import fun.nojava.module.comment.dto.CommentVO;
|
||||
import fun.nojava.module.comment.dto.CreateCommentDTO;
|
||||
import fun.nojava.module.comment.entity.Comment;
|
||||
import fun.nojava.module.comment.entity.CommentLike;
|
||||
import fun.nojava.module.comment.mapper.CommentLikeMapper;
|
||||
import fun.nojava.module.comment.mapper.CommentMapper;
|
||||
import fun.nojava.module.comment.service.CommentService;
|
||||
import fun.nojava.module.system.entity.User;
|
||||
import fun.nojava.module.system.mapper.UserMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CommentServiceImpl implements CommentService {
|
||||
|
||||
private final CommentMapper commentMapper;
|
||||
private final CommentLikeMapper commentLikeMapper;
|
||||
private final UserMapper userMapper;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Long createComment(Long userId, CreateCommentDTO dto) {
|
||||
if (dto.getParentId() != null) {
|
||||
Comment parent = commentMapper.selectById(dto.getParentId());
|
||||
if (parent == null) {
|
||||
throw new BusinessException(ErrorCode.COMMENT_NOT_FOUND);
|
||||
}
|
||||
if (parent.getParentId() != null) {
|
||||
throw new BusinessException(ErrorCode.COMMENT_LEVEL_LIMIT);
|
||||
}
|
||||
}
|
||||
|
||||
Comment comment = new Comment();
|
||||
comment.setArticleId(dto.getArticleId());
|
||||
comment.setUserId(userId);
|
||||
comment.setParentId(dto.getParentId());
|
||||
comment.setReplyToId(dto.getReplyToId());
|
||||
comment.setContent(dto.getContent());
|
||||
comment.setStatus(CommentStatus.APPROVED.getCode());
|
||||
comment.setLikeCount(0);
|
||||
comment.setDeleted(0);
|
||||
commentMapper.insert(comment);
|
||||
|
||||
return comment.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteComment(Long userId, Long commentId) {
|
||||
Comment comment = commentMapper.selectById(commentId);
|
||||
if (comment == null) {
|
||||
throw new BusinessException(ErrorCode.COMMENT_NOT_FOUND);
|
||||
}
|
||||
if (!comment.getUserId().equals(userId)) {
|
||||
throw new BusinessException(ErrorCode.PERMISSION_DENIED);
|
||||
}
|
||||
commentMapper.deleteById(commentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommentVO> listArticleComments(Long articleId, Long currentUserId) {
|
||||
List<Comment> rootComments = commentMapper.selectList(
|
||||
new LambdaQueryWrapper<Comment>()
|
||||
.eq(Comment::getArticleId, articleId)
|
||||
.eq(Comment::getParentId, null)
|
||||
.eq(Comment::getStatus, CommentStatus.APPROVED.getCode())
|
||||
.orderByDesc(Comment::getCreatedAt)
|
||||
);
|
||||
|
||||
List<CommentVO> result = new ArrayList<>();
|
||||
for (Comment root : rootComments) {
|
||||
CommentVO vo = buildCommentVO(root, currentUserId);
|
||||
List<Comment> replies = commentMapper.selectList(
|
||||
new LambdaQueryWrapper<Comment>()
|
||||
.eq(Comment::getParentId, root.getId())
|
||||
.eq(Comment::getStatus, CommentStatus.APPROVED.getCode())
|
||||
.orderByAsc(Comment::getCreatedAt)
|
||||
);
|
||||
vo.setReplies(replies.stream().map(r -> buildCommentVO(r, currentUserId)).toList());
|
||||
result.add(vo);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CommentVO> listAdminComments(int page, int pageSize, Integer status) {
|
||||
LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
|
||||
if (status != null) {
|
||||
wrapper.eq(Comment::getStatus, status);
|
||||
}
|
||||
wrapper.orderByDesc(Comment::getCreatedAt);
|
||||
|
||||
Page<Comment> commentPage = commentMapper.selectPage(new Page<>(page, pageSize), wrapper);
|
||||
List<CommentVO> records = commentPage.getRecords().stream()
|
||||
.map(c -> buildCommentVO(c, null))
|
||||
.toList();
|
||||
|
||||
return new PageResult<>(records, commentPage.getTotal(), page, pageSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void auditComment(Long commentId, Integer status) {
|
||||
Comment comment = commentMapper.selectById(commentId);
|
||||
if (comment == null) {
|
||||
throw new BusinessException(ErrorCode.COMMENT_NOT_FOUND);
|
||||
}
|
||||
comment.setStatus(status);
|
||||
commentMapper.updateById(comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean toggleLike(Long userId, Long commentId) {
|
||||
CommentLike existing = commentLikeMapper.selectOne(
|
||||
new LambdaQueryWrapper<CommentLike>()
|
||||
.eq(CommentLike::getCommentId, commentId)
|
||||
.eq(CommentLike::getUserId, userId)
|
||||
);
|
||||
|
||||
Comment comment = commentMapper.selectById(commentId);
|
||||
if (comment == null) {
|
||||
throw new BusinessException(ErrorCode.COMMENT_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (existing != null) {
|
||||
commentLikeMapper.deleteById(existing.getId());
|
||||
comment.setLikeCount(comment.getLikeCount() - 1);
|
||||
commentMapper.updateById(comment);
|
||||
return false;
|
||||
} else {
|
||||
CommentLike like = new CommentLike();
|
||||
like.setCommentId(commentId);
|
||||
like.setUserId(userId);
|
||||
commentLikeMapper.insert(like);
|
||||
comment.setLikeCount(comment.getLikeCount() + 1);
|
||||
commentMapper.updateById(comment);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private CommentVO buildCommentVO(Comment comment, Long currentUserId) {
|
||||
User user = userMapper.selectById(comment.getUserId());
|
||||
User replyToUser = comment.getReplyToId() != null ? userMapper.selectById(comment.getReplyToId()) : null;
|
||||
|
||||
boolean liked = false;
|
||||
if (currentUserId != null) {
|
||||
liked = commentLikeMapper.selectCount(
|
||||
new LambdaQueryWrapper<CommentLike>()
|
||||
.eq(CommentLike::getCommentId, comment.getId())
|
||||
.eq(CommentLike::getUserId, currentUserId)
|
||||
) > 0;
|
||||
}
|
||||
|
||||
return CommentVO.builder()
|
||||
.id(comment.getId())
|
||||
.articleId(comment.getArticleId())
|
||||
.userId(comment.getUserId())
|
||||
.nickname(user != null ? user.getNickname() : null)
|
||||
.avatar(user != null ? user.getAvatar() : null)
|
||||
.parentId(comment.getParentId())
|
||||
.replyToId(comment.getReplyToId())
|
||||
.replyToNickname(replyToUser != null ? replyToUser.getNickname() : null)
|
||||
.content(comment.getContent())
|
||||
.status(comment.getStatus())
|
||||
.likeCount(comment.getLikeCount())
|
||||
.createdAt(comment.getCreatedAt())
|
||||
.liked(liked)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
|
||||
artifactId=jog-module-comment
|
||||
groupId=fun.nojava
|
||||
version=1.0.0
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fun\nojava\module\comment\dto\CreateCommentDTO.class
|
||||
fun\nojava\module\comment\dto\CommentVO.class
|
||||
fun\nojava\module\comment\entity\Comment.class
|
||||
fun\nojava\module\comment\entity\CommentLike.class
|
||||
fun\nojava\module\comment\controller\CommentController.class
|
||||
fun\nojava\module\comment\service\CommentService.class
|
||||
fun\nojava\module\comment\service\impl\CommentServiceImpl.class
|
||||
fun\nojava\module\comment\dto\CommentVO$CommentVOBuilder.class
|
||||
fun\nojava\module\comment\mapper\CommentLikeMapper.class
|
||||
fun\nojava\module\comment\mapper\CommentMapper.class
|
||||
fun\nojava\module\comment\controller\AdminCommentController.class
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
E:\person\Jog\jog-module-comment\src\main\java\fun\nojava\module\comment\controller\CommentController.java
|
||||
E:\person\Jog\jog-module-comment\src\main\java\fun\nojava\module\comment\dto\CommentVO.java
|
||||
E:\person\Jog\jog-module-comment\src\main\java\fun\nojava\module\comment\dto\CreateCommentDTO.java
|
||||
E:\person\Jog\jog-module-comment\src\main\java\fun\nojava\module\comment\entity\Comment.java
|
||||
E:\person\Jog\jog-module-comment\src\main\java\fun\nojava\module\comment\entity\CommentLike.java
|
||||
E:\person\Jog\jog-module-comment\src\main\java\fun\nojava\module\comment\mapper\CommentLikeMapper.java
|
||||
E:\person\Jog\jog-module-comment\src\main\java\fun\nojava\module\comment\mapper\CommentMapper.java
|
||||
E:\person\Jog\jog-module-comment\src\main\java\fun\nojava\module\comment\service\CommentService.java
|
||||
E:\person\Jog\jog-module-comment\src\main\java\fun\nojava\module\comment\service\impl\CommentServiceImpl.java
|
||||
Reference in New Issue
Block a user