package com.tanpu.community.manager; import com.google.common.collect.Sets; import com.tanpu.biz.common.enums.community.CollectionTypeEnum; import com.tanpu.biz.common.enums.community.CommentTypeEnum; import com.tanpu.biz.common.enums.community.ReportTypeEnum; import com.tanpu.common.api.CommonResp; import com.tanpu.common.constant.ErrorCodeConstant; import com.tanpu.common.exception.BizException; import com.tanpu.community.api.beans.qo.CommentQo; import com.tanpu.community.api.beans.req.comment.CreateCommentReq; import com.tanpu.community.api.beans.req.comment.LikeCommentReq; import com.tanpu.community.api.beans.req.comment.ReportCommentReq; import com.tanpu.community.api.beans.vo.feign.fatools.UserInfoResp; import com.tanpu.community.api.constants.BizConstant; import com.tanpu.community.api.enums.NotificationTypeEnum; import com.tanpu.community.api.enums.OperationTypeEnum; import com.tanpu.community.cache.RedisCache; import com.tanpu.community.dao.entity.community.CommentEntity; import com.tanpu.community.dao.entity.community.ThemeEntity; import com.tanpu.community.feign.fatools.FeignClientForFatools; import com.tanpu.community.service.CollectionService; import com.tanpu.community.service.CommentService; import com.tanpu.community.service.FeignService; import com.tanpu.community.service.NotificationService; import com.tanpu.community.service.ReportLogService; import com.tanpu.community.service.ThemeService; import com.tanpu.community.service.TopicService; import com.tanpu.community.service.quartz.TopicReportService; import com.tanpu.community.util.ConvertUtil; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.ArrayDeque; import java.util.Comparator; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import static com.tanpu.community.api.constants.RedisKeyConstant.CACHE_FEIGN_USER_INFO; @Service public class CommentManager { @Autowired private CommentService commentService; @Autowired private FeignClientForFatools feignClientForFatools; @Autowired private CollectionService collectionService; @Resource private ReportLogService reportLogService; @Autowired private RedisCache redisCache; @Autowired private NotificationService notificationService; @Autowired private ThemeService themeService; @Resource private TopicService topicService; @Resource private FeignService feignService; @Autowired private TopicReportService topicReportService; // 评论(对主题) // 发表评论(对主题) public CommentQo comment(CreateCommentReq req, String userId) { if (StringUtils.isEmpty(req.getComment())) { throw new IllegalArgumentException("评论内容不能为空"); } if (req.getComment().length() > 500) { throw new IllegalArgumentException("评论内容不能超过500字"); } LocalDateTime now = LocalDateTime.now(); CommentEntity commentEntity = CommentEntity.builder() .themeId(req.getThemeId()) .parentId(req.getParentId()) .replyId(req.getReplyId()) .replyUserId(req.getReplyUserId()) .authorId(userId) .content(req.getComment()) .commentType(CommentTypeEnum.THEME.getCode()) .createTime(now) .updateTime(now) .build(); commentService.insertComment(commentEntity); CommentQo commentQo = ConvertUtil.commentEntity2Qo(commentEntity); buildUserInfo(commentQo); // 消息通知 ThemeEntity themeEntity = themeService.queryByThemeId(req.getThemeId()); if (themeEntity == null) { throw new BizException(ErrorCodeConstant.UNREACHABLE); } // 一级回复通知发帖人,二级回复通知一级评论人 if (StringUtils.isNotBlank(req.getReplyUserId())) { notificationService.insert(userId, req.getReplyUserId(), NotificationTypeEnum.COMMENT_REPLY, commentEntity.getCommentId(), req.getComment()); notificationService.putNotifyCache(req.getReplyUserId(), userId, NotificationTypeEnum.COMMENT_REPLY); } else { notificationService.insert(userId, themeEntity.getAuthorId(), NotificationTypeEnum.COMMENT, commentEntity.getCommentId(), req.getComment()); notificationService.putNotifyCache(themeEntity.getAuthorId(), userId, NotificationTypeEnum.COMMENT); } // 评论同步转发并消息通知 if (req.getSyncForward() == BizConstant.SyncForwardType.SYNC_FORWARD) { String themeId = themeService.commentSyncForward(req, userId); // 消息通知 ThemeEntity commentTheme = themeService.queryByThemeId(req.getThemeId()); notificationService.insertForward(userId, commentTheme.getAuthorId(), commentTheme.getThemeId(), "", req.getComment(), themeId); notificationService.putNotifyCache(commentTheme.getAuthorId(), userId, NotificationTypeEnum.FORWARD); } if (StringUtils.isNotBlank(themeEntity.getTopicId())) { topicReportService.reportTopicOnTime(themeEntity.getTopicId()); } return commentQo; } // 查询评论 public List<CommentQo> queryComments(String themeId, String userId) { // 因为需要排序,所以从库中查询所有评论 List<CommentEntity> commentEntities = commentService.selectByThemeId(themeId); List<CommentQo> commentQos = ConvertUtil.commentEntity2Qos(commentEntities); Set<String> likeCommentList; if (StringUtils.isNotEmpty(userId)) { likeCommentList = collectionService.getSetByUser(userId, CollectionTypeEnum.LIKE_COMMENT); } else { likeCommentList = Sets.newHashSetWithExpectedSize(0); } // 查询管理员 ThemeEntity themeEntity = themeService.queryByThemeId(themeId); Set<String> managerId = topicService.getManagerId(themeEntity.getTopicId()); for (CommentQo commentQo : commentQos) { // 封装用户信息 buildUserInfo(commentQo); // 是否点赞及点赞数 String commentId = commentQo.getCommentId(); Integer likeCount = collectionService.getCountByTypeAndId(commentId, CollectionTypeEnum.LIKE_COMMENT); commentQo.setLikeCount(likeCount); commentQo.setHasLiked(likeCommentList.contains(commentId)); // 是否管理员 if (managerId.contains(commentQo.getAuthorId())) { commentQo.setManager(true); } else { commentQo.setManager(false); } } //排序:点赞降序+时间降序 return commentQos.stream().sorted(Comparator.comparing(CommentQo::getLikeCount, Comparator.reverseOrder()). thenComparing(CommentQo::getUpdateTime, Comparator.reverseOrder())) .collect(Collectors.toList()); } private void buildUserInfo(CommentQo commentQo) { String authorId = commentQo.getAuthorId(); UserInfoResp userInfo = redisCache.getObject(StringUtils.joinWith("_", CACHE_FEIGN_USER_INFO, authorId), 60, () -> this.getUserInfo(authorId), UserInfoResp.class); if (userInfo != null) { commentQo.setUserImg(userInfo.getHeadImageUrl()); commentQo.setNickName(userInfo.getNickName()); commentQo.setUserType(userInfo.getUserType()); commentQo.setLevelGrade(userInfo.getLevelGrade()); commentQo.setUserInvestorType(userInfo.getUserInvestorType()); commentQo.setBelongUserOrgId(userInfo.getBelongUserOrgId()); commentQo.setBelongUserOrgName(userInfo.getBelongUserOrgName()); } // 回复用户名 if (StringUtils.isNotBlank(commentQo.getReplyUserId())) { UserInfoResp userResp = feignService.getUserInfoById(commentQo.getReplyUserId()); if (userResp != null) { commentQo.setReplyUserName(userResp.getNickName()); } } commentQo.setHasLiked(false); commentQo.setLikeCount(0); } private UserInfoResp getUserInfo(String authorId) { CommonResp<UserInfoResp> userInfoNewCommonResp = feignClientForFatools.queryUserInfoNew(authorId); if (userInfoNewCommonResp.isNotSuccess()) { throw new BizException("内部接口调用失败"); } return userInfoNewCommonResp.getData(); } //点赞评论/取消点赞 public void likeComment(LikeCommentReq req, String userId) { if (OperationTypeEnum.CONFIRM.getCode().equals(req.getType())) { boolean b = collectionService.saveOrUpdate(req.getCommentId(), userId, CollectionTypeEnum.LIKE_COMMENT); if (b) { CommentEntity commentEntity = commentService.queryByCommentId(req.getCommentId()); notificationService.insertLikeComment(userId, commentEntity.getAuthorId(), req.getCommentId()); notificationService.putNotifyCache(commentEntity.getAuthorId(), userId, NotificationTypeEnum.COMMENT_LIKE); } } else if (OperationTypeEnum.CANCEL.getCode().equals(req.getType())) { collectionService.delete(req.getCommentId(), userId, CollectionTypeEnum.LIKE_COMMENT); } } //举报评论 @Transactional public void report(ReportCommentReq req, String userId) { //更改举报状态 commentService.updateReportStatus(req.getCommentId()); //写入举报记录表 CommentEntity commentEntity = commentService.queryByIdIncludeDelete(req.getCommentId()); reportLogService.insert(ReportTypeEnum.COMMENT, userId, req.getCommentId(), commentEntity.getAuthorId(), req.getReason()); } //删除评论 public void delete(String commentId, String userId) { if (StringUtils.isBlank(commentId)) { throw new BizException("commentId不能为空"); } ArrayDeque<CommentEntity> queue = new ArrayDeque<>(); queue.add(commentService.queryByIdIncludeDelete(commentId)); // 循环删除二级评论的一级评论 while (!queue.isEmpty()) { CommentEntity pop = queue.pop(); // 逻辑删除comment CommentEntity commentEntity = commentService.delete(pop.getCommentId(), pop.getAuthorId()); // 删除站内信 ThemeEntity themeEntity = themeService.queryByThemeId(commentEntity.getThemeId()); notificationService.deleteCommentNotify(themeEntity.getAuthorId(), userId, commentId, commentEntity.getCreateTime()); // 递归 queue.addAll(commentService.queryReplyForComment(commentEntity.getCommentId())); } } }