package com.ican.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ican.entity.*;
import com.ican.mapper.ArticleMapper;
import com.ican.mapper.CommentMapper;
import com.ican.mapper.TalkMapper;
import com.ican.mapper.UserMapper;
import com.ican.model.dto.CheckDTO;
import com.ican.model.dto.CommentDTO;
import com.ican.model.dto.ConditionDTO;
import com.ican.model.dto.MailDTO;
import com.ican.model.vo.*;
import com.ican.service.CommentService;
import com.ican.service.RedisService;
import com.ican.service.SiteConfigService;
import com.ican.utils.HTMLUtils;
import com.ican.utils.PageUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import static com.ican.constant.CommonConstant.*;
import static com.ican.constant.MqConstant.*;
import static com.ican.constant.RedisConstant.COMMENT_LIKE_COUNT;
import static com.ican.enums.CommentTypeEnum.*;
/**
* 评论业务接口实现类
*
* @author ican
*/
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {
@Value("${blog.url}")
private String websiteUrl;
@Autowired
private ArticleMapper articleMapper;
@Autowired
private TalkMapper talkMapper;
@Autowired
private CommentMapper commentMapper;
@Autowired
private UserMapper userMapper;
@Autowired
private SiteConfigService siteConfigService;
@Autowired
private RedisService redisService;
@Autowired
private RabbitTemplate rabbitTemplate;
@Override
public PageResult<CommentBackVO> listCommentBackVO(ConditionDTO condition) {
// 查询后台评论数量
Long count = commentMapper.countComment(condition);
if (count == 0) {
return new PageResult<>();
}
// 查询后台评论集合
List<CommentBackVO> commentBackVOList = commentMapper.listCommentBackVO(PageUtils.getLimit(),
PageUtils.getSize(), condition);
return new PageResult<>(commentBackVOList, count);
}
@Override
public void addComment(CommentDTO comment) {
// 校验评论参数
verifyComment(comment);
SiteConfig siteConfig = siteConfigService.getSiteConfig();
Integer commentCheck = siteConfig.getCommentCheck();
// 过滤标签
comment.setCommentContent(HTMLUtils.filter(comment.getCommentContent()));
Comment newComment = Comment.builder()
.fromUid(StpUtil.getLoginIdAsInt())
.toUid(comment.getToUid())
.typeId(comment.getTypeId())
.commentType(comment.getCommentType())
.parentId(comment.getParentId())
.replyId(comment.getReplyId())
.commentContent(comment.getCommentContent())
.isCheck(commentCheck.equals(FALSE) ? TRUE : FALSE)
.build();
// 保存评论
commentMapper.insert(newComment);
// 查询评论用户昵称
String fromNickname = userMapper.selectOne(new LambdaQueryWrapper<User>()
.select(User::getNickname)
.eq(User::getId, StpUtil.getLoginIdAsInt()))
.getNickname();
// 通知用户
if (siteConfig.getEmailNotice().equals(TRUE)) {
CompletableFuture.runAsync(() -> {
System.out.println("你好");
notice(newComment, fromNickname);
});
}
}
@Override
public void updateCommentCheck(CheckDTO check) {
// 修改评论审核状态
List<Comment> commentList = check.getIdList().stream().map(id -> Comment.builder().id(id).isCheck(check.getIsCheck()).build()).collect(Collectors.toList());
this.updateBatchById(commentList);
}
@Override
public List<RecentCommentVO> listRecentCommentVO() {
return commentMapper.selectRecentComment();
}
@Override
public PageResult<CommentVO> listCommentVO(ConditionDTO condition) {
// 查询父评论数量
Long count = commentMapper.selectCount(new LambdaQueryWrapper<Comment>()
.eq(Objects.nonNull(condition.getTypeId()), Comment::getTypeId, condition.getTypeId())
.eq(Comment::getCommentType, condition.getCommentType())
.eq(Comment::getIsCheck, TRUE).isNull(Comment::getParentId));
if (count == 0) {
return new PageResult<>();
}
// 分页查询父评论
List<CommentVO> commentVOList = commentMapper.selectParentComment(PageUtils.getLimit(), PageUtils.getSize(), condition);
if (CollectionUtils.isEmpty(commentVOList)) {
return new PageResult<>();
}
// 评论点赞
Map<String, Integer> likeCountMap = redisService.getHashAll(COMMENT_LIKE_COUNT);
// 父评论id集合
List<Integer> parentCommentIdList = commentVOList.stream().map(CommentVO::getId).collect(Collectors.toList());
// 分组查询每组父评论下的子评论前三条
List<ReplyVO> replyVOList = commentMapper.selectReplyByParentIdList(parentCommentIdList);
// 封装子评论点赞量
replyVOList.forEach(item -> item.setLikeCount(Optional.ofNullable(likeCountMap.get(item.getId().toString())).orElse(0)));
// 根据父评论id生成对应子评论的Map
Map<Integer, List<ReplyVO>> replyMap = replyVOList.stream().collect(Collectors.groupingBy(ReplyVO::getParentId));
// 父评论的回复数量
List<ReplyCountVO> replyCountList = commentMapper.selectReplyCountByParentId(parentCommentIdList);
// 转换Map
Map<Integer, Integer> replyCountMap = replyCountList.stream().collect(Collectors.toMap(ReplyCountVO::getCommentId, ReplyCountVO::getReplyCount));
// 封装评论数据
commentVOList.forEach(item -> {
item.setLikeCount(Optional.ofNullable(likeCountMap.get(item.getId().toString())).orElse(0));
item.setReplyVOList(replyMap.get(item.getId()));
item.setReplyCount(Optional.ofNullable(replyCountMap.get(item.getId())).orElse(0));
});
return new PageResult<>(commentVOList, count);
}
@Override
public List<ReplyVO> listReply(Integer commentId) {
// 分页查询子评论
List<ReplyVO> replyVOList = commentMapper.selectReplyByParentId(PageUtils.getLimit(), PageUtils.getSize(), commentId);
// 子评论点赞Map
Map<String, Integer> likeCountMap = redisService.getHashAll(COMMENT_LIKE_COUNT);
replyVOList.forEach(item -> item.setLikeCount(likeCountMap.get(item.getId().toString())));
return replyVOList;
}
private void verifyComment(CommentDTO comment) {
if (comment.getCommentType().equals(ARTICLE.getType())) {
Article article = articleMapper.selectOne(new LambdaQueryWrapper<Article>().select(Article::getId).eq(Article::getId, comment.getTypeId()));
Assert.notNull(article, "文章不存在");
}
if (comment.getCommentType().equals(TALK.getType())) {
Talk talk = talkMapper.selectOne(new LambdaQueryWrapper<Talk>().select(Talk::getId).eq(Talk::getId, comment.getTypeId()));
Assert.notNull(talk, "说说不存在");
}
// 评论为子评论,判断回复的评论和用户是否存在
Optional.ofNullable(comment.getParentId()).i
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
博客介绍 借助Springboot + Vue3 工具开发的前后端分离的个人博客系统 技术介绍 前端: Vue3 + Pinia + Vue Router + TypeScript + Axios + Element Plus + Naive UI + Echarts 后端: SpringBoot + Mysql + Redis + Quartz + Thymeleaf + Nginx + Docker ElasticSearch + RabbitMQ 项目特点 前台界面参考 Hexo 的 Shoka 和 Butterfly 设计,页面美观,响应式布局 后台管理基于若依二次开发,含有侧边栏,历史标签,面包屑等 前后端分离,Docker Compose 一键部署 采用 RABC 权限模型,使用 Sa-Token 进行权限管理 支持动态权限修改、动态菜单和路由 说说、友链、相册、留言弹幕墙、音乐播放器 支持代码高亮、图片预览、黑夜模式、点赞、取消点赞等功能 发布评论、回复评论、表情包 发送 HTML 邮件评论回复提醒,内容详细 接入第三方登录,减少注册成本 文章搜索支持关键字高亮分词
资源推荐
资源详情
资源评论
收起资源包目录
基于Springboot + Vue3 开发的前后端分离的个人博客系统源码+数据库 (937个子文件)
font.css 165B
normal.cur 4KB
link.cur 4KB
Dockerfile 500B
.env 580B
404.gif 101KB
loading.gif 45KB
.gitignore 259B
.gitignore 258B
.gitignore 47B
.gitignore 47B
user.html 3KB
author.html 2KB
common.html 2KB
index.html 1020B
index.html 505B
favicon.ico 3KB
blog-springboot.iml 19KB
Blog-master.iml 336B
CommentServiceImpl.java 15KB
UserServiceImpl.java 14KB
ArticleServiceImpl.java 13KB
BlogFileServiceImpl.java 9KB
RedisService.java 8KB
TalkServiceImpl.java 8KB
ArticleController.java 7KB
RedisServiceImpl.java 7KB
TaskServiceImpl.java 7KB
BlogInfoServiceImpl.java 6KB
PhotoServiceImpl.java 6KB
MenuServiceImpl.java 6KB
LoginServiceImpl.java 5KB
TaskInvokeUtils.java 5KB
TalkController.java 5KB
RoleServiceImpl.java 5KB
AlbumServiceImpl.java 5KB
LogController.java 5KB
CategoryServiceImpl.java 5KB
UserController.java 4KB
OptLogAspect.java 4KB
PhotoController.java 4KB
CommentController.java 4KB
ExceptionLogAspect.java 4KB
MySaTokenListener.java 4KB
SaTokenConfig.java 4KB
TagServiceImpl.java 4KB
AlbumController.java 4KB
ScheduleUtils.java 4KB
CategoryController.java 4KB
GithubLoginStrategyImpl.java 4KB
IpUtils.java 4KB
TaskController.java 4KB
RoleController.java 3KB
MenuController.java 3KB
TagController.java 3KB
MessageServiceImpl.java 3KB
EsSearchStrategyImpl.java 3KB
GiteeLoginStrategyImpl.java 3KB
AbstractLoginStrategyImpl.java 3KB
SiteConfigServiceImpl.java 3KB
BlogFileController.java 3KB
MessageController.java 3KB
GlobalExceptionHandler.java 3KB
CosUploadStrategyImpl.java 3KB
FriendController.java 3KB
AbstractQuartzJob.java 3KB
ArticleMapper.java 3KB
LoginController.java 3KB
CommentMapper.java 3KB
UserInfoController.java 3KB
FileUtils.java 3KB
VisitLogAspect.java 3KB
AccessLimitInterceptor.java 3KB
SiteConfig.java 3KB
MysqlSearchStrategyImpl.java 3KB
ConditionDTO.java 3KB
RedisConfig.java 2KB
CommentDTO.java 2KB
ArticleService.java 2KB
ElasticsearchConfig.java 2KB
ThreadPoolConfig.java 2KB
UserService.java 2KB
SiteConfigController.java 2KB
FriendServiceImpl.java 2KB
ArticleLikeStrategyImpl.java 2KB
CommentLikeStrategyImpl.java 2KB
EmailServiceImpl.java 2KB
ArticleConsumer.java 2KB
RabbitMqConfig.java 2KB
ThreadUtils.java 2KB
MenuVO.java 2KB
ArticleBackVO.java 2KB
OssUploadStrategyImpl.java 2KB
StpInterfaceImpl.java 2KB
AbstractUploadStrategyImpl.java 2KB
BlogInfoController.java 2KB
TaskBackVO.java 2KB
OperationLogServiceImpl.java 2KB
ArticleVO.java 2KB
ExceptionLogServiceImpl.java 2KB
共 937 条
- 1
- 2
- 3
- 4
- 5
- 6
- 10
资源评论
云哲-吉吉2021
- 粉丝: 3207
- 资源: 1130
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功