package nju.seec.helper.service.impl; import nju.seec.helper.dao.CommentDAO; import nju.seec.helper.dao.SlideDAO; import nju.seec.helper.dao.UserDAO; import nju.seec.helper.dto.CommentDTO; import nju.seec.helper.dto.LoginUser; import nju.seec.helper.entity.Comment; import nju.seec.helper.entity.Slide; import nju.seec.helper.service.CommentService; import nju.seec.helper.service.MessageService; import nju.seec.helper.service.util.AuthUtils; import nju.seec.helper.util.enums.MessageType; import nju.seec.helper.vo.CommentVO; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.stream.Collectors; /** * @author cst */ @Service public class CommentServiceImpl implements CommentService { private final CommentDAO commentDAO; private final SlideDAO slideDAO; private final UserDAO userDAO; private final MessageService messageService; public CommentServiceImpl(CommentDAO commentDAO, SlideDAO slideDAO, UserDAO userDAO, MessageService messageService) { this.commentDAO = commentDAO; this.slideDAO = slideDAO; this.userDAO = userDAO; this.messageService = messageService; } @Transactional(rollbackFor = Exception.class) @Override public CommentVO createComment(LoginUser user, CommentDTO commentDTO) { Comment comment = new Comment() .setSlideId(commentDTO.getSlideId()) .setPageNumber(commentDTO.getPageNumber()) .setUser(userDAO.findUserById(user.getId())) .setTitle(commentDTO.getTitle()) .setContent(commentDTO.getContent()); comment = commentDAO.save(comment); // 增加通知 Slide slide = slideDAO.findSlideById(comment.getSlideId()); if (!user.getId().equals(slide.getTeacher().getId())) { messageService.createMessage(Collections.singleton(slide.getTeacher().getId()), MessageType.COMMENT_NEW, String.format("课程 [%s] 的课件 [%s] 在第%d页有新评论", slide.getCourse().getName(), slide.getName(), comment.getPageNumber()), slide.getId()); } return new CommentVO(comment); } @Transactional(rollbackFor = Exception.class) @Override public void removeComment(LoginUser user, Long commentId) { Comment comment = commentDAO.findCommentById(commentId); AuthUtils.checkDataAuth(user.getId(), comment.getUser().getId(), "您无权删除该评论"); unTopComment(comment); commentDAO.deleteById(commentId); } @Transactional(rollbackFor = Exception.class) @Override public void topComment(LoginUser user, Long commentId) { Comment comment = commentDAO.findCommentById(commentId); AuthUtils.checkDataAuth(user.getId(), slideDAO.findSlideById(comment.getSlideId()).getTeacher().getId(), "您无权在该评论区置顶评论"); unTopComment(comment); comment.setTopNumber((int) countTopComments(comment.getSlideId(), comment.getPageNumber()) + 1); commentDAO.save(comment); } @Transactional(rollbackFor = Exception.class) @Override public void unTopComment(LoginUser user, Long commentId) { Comment comment = commentDAO.findCommentById(commentId); AuthUtils.checkDataAuth(user.getId(), slideDAO.findSlideById(comment.getSlideId()).getTeacher().getId(), "您无权在该评论区取消置顶评论"); unTopComment(comment); commentDAO.save(comment); } @Transactional(readOnly = true) @Override public Page getCommentsBySlideAndPageNumber(Long slideId, Integer pageNumber, Pageable pageable) { return findBySlideIdAndPageNumber(slideId, pageNumber, pageable).map(CommentVO::new); } @Transactional(readOnly = true) @Override public CommentVO getOneComment(Long commentId) { return new CommentVO(commentDAO.findCommentById(commentId)); } private void unTopComment(Comment comment) { Integer topNumber = comment.getTopNumber(); comment.setTopNumber(0); decTopNumber(comment.getSlideId(), comment.getPageNumber(), topNumber); } long countTopComments(Long slideId, Integer pageNumber) { return commentDAO.count( (Specification) (root, query, cb) -> cb.and( cb.equal(root.get("slideId"), slideId), cb.equal(root.get("pageNumber"), pageNumber), cb.notEqual(root.get("topNumber"), 0))); } Page findBySlideIdAndPageNumber(Long slideId, Integer pageNumber, Pageable pageable) { return commentDAO.findAll( (Specification) (root, query, cb) -> cb.and( cb.equal(root.get("slideId"), slideId), cb.equal(root.get("pageNumber"), pageNumber)), pageable); } void decTopNumber(Long slideId, Integer pageNumber, Integer topNumber) { commentDAO.saveAll( commentDAO .findAll((Specification) (root, query, cb) -> cb.and( cb.equal(root.get("slideId"), slideId), cb.equal(root.get("pageNumber"), pageNumber), cb.gt(root.get("topNumber"), topNumber))) .parallelStream() .peek(comment -> comment.setTopNumber(comment.getTopNumber() - 1)) .collect(Collectors.toSet())); } }