-
目录
- 评论管理必须要和其他的功能关联起来不然是做不出来的
首先要创建一个数据库
-
/* SQLyog v10.2 MySQL - 5.7.17-log : Database - blog_system ********************************************************************* */ /*!40101 SET NAMES utf8 */; /*!40101 SET SQL_MODE=''*/; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; CREATE DATABASE /*!32312 IF NOT EXISTS*/`blog_system` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_polish_ci */; USE `blog_system`; /*Table structure for table `t_comment` */ DROP TABLE IF EXISTS `t_comment`; CREATE TABLE `t_comment` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '评论id', `article_id` int(11) NOT NULL COMMENT '关联的文章id', `created` date NOT NULL COMMENT '评论时间', `ip` varchar(200) DEFAULT NULL COMMENT '评论用户登录的ip地址', `content` text NOT NULL COMMENT '评论内容', `status` varchar(200) NOT NULL DEFAULT 'approved' COMMENT '评论状态', `author` varchar(200) NOT NULL COMMENT '评论用户用户名', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8; /*Data for the table `t_comment` */ insert into `t_comment`(`id`,`article_id`,`created`,`ip`,`content`,`status`,`author`) values (3,10,'2018-12-13','0:0:0:0:0:0:0:1','关于Docker虚拟容器的讲解挺好的额,学习中','approved','李四'),(9,1,'2018-12-13','0:0:0:0:0:0:0:1','非常不错,赞一个!','approved','李四'),(10,1,'2018-12-13','0:0:0:0:0:0:0:1','博主,这资料怎么弄的?有相关资源和教材推荐吗?','approved','李四'),(11,1,'2018-12-13','0:0:0:0:0:0:0:1','很详细,感谢...','approved','东方不败'),(12,1,'2018-12-13','0:0:0:0:0:0:0:1','很全,努力学习中...','approved','东方不败'),(13,1,'2018-12-13','0:0:0:0:0:0:0:1','好东西,先收藏起来,哈哈','approved','tom'),(14,8,'2018-12-13','0:0:0:0:0:0:0:1','very good blog','approved','tom'),(15,17,'2023-11-11','0:0:0:0:0:0:0:1','11111','approved','admin'),(17,16,'2023-11-11','0:0:0:0:0:0:0:1','1111','approved','admin'),(18,1,'2023-11-11','0:0:0:0:0:0:0:1','1111','approved','admin'),(19,1,'2023-11-11','0:0:0:0:0:0:0:1','1111111111111','approved','admin'),(20,10,'2023-11-13','0:0:0:0:0:0:0:1','kkkmmvvv','approved','admin'),(21,10,'2023-11-13','0:0:0:0:0:0:0:1','发','approved','admin'),(22,10,'2023-11-13','0:0:0:0:0:0:0:1','啊','approved','admin'),(23,18,'2023-11-13','0:0:0:0:0:0:0:1','kkk','approved','admin'),(24,18,'2023-11-13','0:0:0:0:0:0:0:1','反反复复','approved','admin'),(25,18,'2023-11-13','0:0:0:0:0:0:0:1','发发发发发','approved','admin'),(26,18,'2023-11-13','0:0:0:0:0:0:0:1','发发发发发发','approved','admin'),(28,18,'2023-11-13','0:0:0:0:0:0:0:1','发发发发发','approved','admin'),(29,18,'2023-11-13','0:0:0:0:0:0:0:1','发发发发发','approved','admin'),(30,18,'2023-11-13','0:0:0:0:0:0:0:1','啊啊啊啊啊','approved','admin'),(31,18,'2023-11-13','0:0:0:0:0:0:0:1','发发发vvvv','approved','admin'),(32,18,'2023-11-13','0:0:0:0:0:0:0:1','vvvvvv','approved','admin'),(33,18,'2023-11-13','0:0:0:0:0:0:0:1','VB不不不不','approved','admin'),(34,18,'2023-11-13','0:0:0:0:0:0:0:1','vvvvvv','approved','admin'),(35,18,'2023-11-13','0:0:0:0:0:0:0:1','谢谢小星星','approved','admin'),(36,18,'2023-11-13','0:0:0:0:0:0:0:1','vvvvvv','approved','admin'),(37,18,'2023-11-13','0:0:0:0:0:0:0:1','湘西自治州','approved','admin'),(38,18,'2023-11-13','0:0:0:0:0:0:0:1','英语与银行','approved','admin'),(39,18,'2023-11-13','0:0:0:0:0:0:0:1','看看嘛密密麻麻','approved','admin'),(40,18,'2023-11-13','0:0:0:0:0:0:0:1','啧啧啧啧啧啧','approved','admin'),(41,18,'2023-11-13','0:0:0:0:0:0:0:1','热热热热热','approved','admin'),(42,18,'2023-11-13','0:0:0:0:0:0:0:1','发发发','approved','admin'),(43,18,'2023-11-13','0:0:0:0:0:0:0:1','反反复复','approved','admin'); /*Table structure for table `t_statistic` */ DROP TABLE IF EXISTS `t_statistic`; CREATE TABLE `t_statistic` ( `id` int(11) NOT NULL AUTO_INCREMENT, `article_id` int(11) NOT NULL COMMENT '关联的文章id', `hits` int(11) NOT NULL DEFAULT '0' COMMENT '文章点击总量', `comments_num` int(11) NOT NULL DEFAULT '0' COMMENT '文章评论总量', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8; /*Data for the table `t_statistic` */ insert into `t_statistic`(`id`,`article_id`,`hits`,`comments_num`) values (1,1,106,7),(2,2,3,0),(3,3,4,0),(4,4,4,0),(5,5,4,0),(6,6,16,0),(7,7,9,0),(8,8,24,1),(9,9,18,0),(10,10,25,4),(11,11,11,1),(12,12,50,1),(13,13,1,0),(14,14,1,0),(15,15,2,0),(16,16,19,1),(17,17,19,2),(18,18,30,21),(19,19,14,5),(20,20,1,0),(22,22,6,0),(23,23,0,0),(24,24,1,0),(25,25,0,0),(26,26,0,0); /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
然后再创建实体类
-
public class Comment { private Integer id; // 评论id private Integer articleId; // 评论的文章id private String content; // 评论内容 private Date created; // 评论日期 private String author; // 评论作者名 private String ip; // 评论用户登录ip private String status; // 评论状态,默认审核通过approved //此处省略get、set语句 //此处省略toString语句
public class Statistic { private Integer id; private Integer articleId; // 评论的文章id private Integer hits; // 点击量 private Integer commentsNum; // 评论总量 //此处省略get、set语句
-
再写个Service类
public interface ICommentService {
// 获取文章下的评论
public PageInfo<Comment> getComments(Integer aid, int page, int count);
// 用户发表评论
public void pushComment(Comment comment);
public interface ISiteService {
// 最新收到的评论
public List<Comment> recentComments(int count);
// 最新发表的文章
public List<Article> recentArticles(int count);
// 获取后台统计数据
public StaticticsBo getStatistics();
// 更新某个文章的统计数据
public void updateStatistics(Article article);
}
@Service
@Transactional
public class CommentServiceImpl implements ICommentService {
@Autowired
private CommentMapper commentMapper;
// 根据文章id分页查询评论
@Override
public PageInfo<Comment> getComments(Integer aid, int page, int count) {
PageHelper.startPage(page,count);
List<Comment> commentList = commentMapper.selectCommentWithPage(aid);
PageInfo<Comment> commentInfo = new PageInfo<>(commentList);
return commentInfo;
}
// 用户发表评论
@Override
public void pushComment(Comment comment){
commentMapper.pushComment(comment);
// 更新文章评论数据量
Statistic statistic = statisticMapper.selectStatisticWithArticleId(comment.getArticleId());
statistic.setCommentsNum(statistic.getCommentsNum()+1);
statisticMapper.updateArticleCommentsWithId(statistic);
}
@Service
@Transactional
public class SiteServiceImpl implements ISiteService {
@Autowired
private CommentMapper commentMapper;
@Override
public void updateStatistics(Article article) {
Statistic statistic = statisticMapper.selectStatisticWithArticleId(article.getId());
statistic.setHits(statistic.getHits() + 1);
statisticMapper.updateArticleHitsWithId(statistic);
}
@Override
public List<Comment> recentComments(int limit) {
PageHelper.startPage(1, limit > 10 || limit < 1 ? 10 : limit);
List<Comment> byPage = commentMapper.selectNewComment();
return byPage;
}
最后再创个Controller类,后端就完成了
@Controller
@RequestMapping("/admin")
public class CommentController {
private static final Logger logger = LoggerFactory.getLogger(CommentController.class);
@Autowired
private ICommentService commentServcieImpl;
// 发表评论操作
@PostMapping(value = "/publish")
@ResponseBody
public ArticleResponseData publishComment(HttpServletRequest request, @RequestParam Integer aid, @RequestParam String text) {
// 去除js脚本
text = MyUtils.cleanXSS(text);
text = EmojiParser.parseToAliases(text);
// 获取当前登录用户
User user=(User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
// 封装评论信息
Comment comments = new Comment();
comments.setArticleId(aid);
comments.setIp(request.getRemoteAddr());
comments.setCreated(new Date());
comments.setAuthor(user.getUsername());
comments.setContent(text);
try {
commentServcieImpl.pushComment(comments);
logger.info("发布评论成功,对应文章id: "+aid);
return ArticleResponseData.ok();
} catch (Exception e) {
logger.error("发布评论失败,对应文章id: "+aid +";错误描述: "+e.getMessage());
return ArticleResponseData.fail();
}
}
前端
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" th:fragment="comments"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<body>
<div th:if="${article}!=null">
<div th:id="${article.id ?: 0}" class="comment-container">
<div id="comments" class="clearfix">
<div th:if="${article.allowComment}">
<span class="response">
<form name="logoutform" th:action="@{/logout}" method="post"></form>
<th:block sec:authorize="isAuthenticated()">
Hello,<a data-no-instant="" sec:authentication="name"></a>
如果你想 <a href="javascript:document.logoutform.submit();">注销</a> ?
</th:block>
<th:block sec:authorize="isAnonymous()">
用户想要评论,请先<a th:href="@{/login}" title="登录" data-no-instant="">登录</a>!
</th:block>
</span>
<div sec:authorize="isAuthenticated()">
<form id="comment-form" class="comment-form" role="form" onsubmit="return TaleComment.subComment();">
<input type="hidden" name="aid" id="aid" th:value="${article.id}"/>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
<textarea name="text" id="textarea" class="form-control" placeholder="以上信息可以为空,评论不能为空哦!"
required="required" minlength="1" maxlength="100"></textarea>
<button type="submit" class="submit" id="misubmit">提交</button>
</form>
</div>
</div>
<!-- 分页显示其他评论内容 -->
<div th:if="${comments}">
<ol class="comment-list">
<th:block th:each="comment :${comments.list}">
<li th:id="'li-comment-'+${comment.id}" class="comment-body comment-parent comment-odd">
<div th:id="'comment-'+${comment.id}">
<div class="comment-view" onclick="">
<div class="comment-header">
<!--设置人物头像和名称-->
<img class="avatar" th:src="@{/assets/img/avatars.jpg}" height="50"/>
<a class="comment-author" rel="external nofollow" th:text="${comment.author}" />
</div>
<!-- 评论内容 -->
<div class="comment-content">
<span class="comment-author-at"></span>
<p th:utext="${commons.article(comment.content)}"></p>
</div>
<!-- 评论日期 -->
<div class="comment-meta">
<time class="comment-time" th:text="${commons.dateFormat(comment.created)}"></time>
<a sec:authorize="isAuthenticated()" th:if="${comment.author}!= ${session.SPRING_SECURITY_CONTEXT.authentication.principal.username}" href="javascript:void(0)" style="color: #1b961b">
回复
</a>
</div>
</div>
</div>
</li>
</th:block>
</ol>
<!-- 进行评论分页 -->
<div class="lists-navigator clearfix">
<ol class="page-navigator">
<!-- 判断并展示上一页 -->
<th:block th:if="${comments.hasPreviousPage}">
<li class="prev"><a th:href="'?cp='+${comments.prePage}+'#comments'">上一页</a></li>
</th:block>
<!-- 判断并展示中间页 -->
<th:block th:each="navIndex : ${comments.navigatepageNums}">
<th:block th:if="${comments.pages} <= 5">
<li th:class="${comments.pageNum}==${navIndex}?'current':''">
<a th:href="'?cp='+${navIndex}+'#comments'" th:text="${navIndex}"></a>
</li>
</th:block>
<th:block th:if="${comments.pages} > 5">
<li th:if="${comments.pageNum <=3 && navIndex <= 5}" th:class="${comments.pageNum}==${navIndex}?'current':''">
<a th:href="'?cp='+${navIndex}+'#comments'" th:text="${navIndex}"></a>
</li>
<li th:if="${comments.pageNum >= comments.pages-2 && navIndex > comments.pages-5}" th:class="${comments.pageNum}==${navIndex}?'current':''">
<a th:href="'?cp='+${navIndex}+'#comments'" th:text="${navIndex}"></a>
</li>
<li th:if="${comments.pageNum >=4 && comments.pageNum <= comments.pages-3 && navIndex >= comments.pageNum-2 && navIndex <= comments.pageNum+2}" th:class="${comments.pageNum}==${navIndex}?'current':''">
<a th:href="'?cp='+${navIndex}+'#comments'" th:text="${navIndex}"></a>
</li>
</th:block>
</th:block>
<!-- 判断并展示下一页 -->
<th:block th:if="${comments.hasNextPage}">
<li class="next"><a th:href="'?cp='+${comments.nextPage}+'#comments'">下一页</a></li>
</th:block>
</ol>
</div>
</div>
</div>
</div>
</div>
</body>
<div th:replace="comm/tale_comment::tale_comment"></div>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" th:fragment="tale_comment" >
<body>
<script type="text/javascript">
/*<![CDATA[*/
(function () {
window.TaleComment = {
subComment: function () {
$.ajax({
type: 'post',
url: '/admin/publish',
data: $('#comment-form').serialize(),
async: false,
dataType: 'json',
success: function (result) {
if (result && result.success) {
window.alert("评论提交成功!");
window.location.reload();
} else {
window.alert("发送失败")
if (result.msg) {
alert(result.msg);
}
}
}
});
return false;
}
};
})();
</script>
</body>
</html>
这样就完成了,小萌新希望可以帮到大家