此评论样式采用valine 的样式,JavaScript由博主个人独立编写
目前不会公布源码(因为有些安全问题与一些小bug),这篇文章主要如果你想体验这个评论可以返回主页看公告栏。
问题 一张表实现子
评论父
评论 假设: A==父评论 B==子评论 C==父评论 D==子评论 问题1:如何判断是子评论还是父评论 问题2:如何判断B评论是A的子评论 问题3:如何判断B评论不是C的子评论(如何区分开来) 问题4:如何判断回复评论时,回复的是子评论还是父评论 (如:如果我回复的是A评论,那么我(我是D)的这条评论就是A的子评论,要是我回复了B,如何将我(我是D)显示在在A评论下) 还有几个小问题就不列举了
正文 Maven依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-thymeleaf</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-jdbc</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > org.mybatis.spring.boot</groupId > <artifactId > mybatis-spring-boot-starter</artifactId > <version > 2.1.4</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <scope > runtime</scope > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > </dependency > </dependencies >
创建数据表 数据库表结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 CREATE TABLE `comment` ( `id` BIGINT (20 ) NOT NULL AUTO_INCREMENT COMMENT '主键id' , `artitle` BIGINT (20 ) NOT NULL DEFAULT '0' COMMENT '关联的blog主键' , # 根据需求使用,去过你只是单纯的做个人主页留言的话,每个人评论全部设置为1 即可,当然你也可以直接删除 `nick` VARCHAR (50 ) NOT NULL DEFAULT '' COMMENT '昵称' , `mail` VARCHAR (100 ) NOT NULL DEFAULT '' COMMENT '邮箱' , `link` VARCHAR (50 ) NOT NULL DEFAULT '' COMMENT '网址' , `content` VARCHAR (200 ) NOT NULL DEFAULT '' COMMENT '内容' , `commentatorIP` VARCHAR (20 ) NOT NULL DEFAULT '' COMMENT 'ip地址' , `createTime` DATETIME DEFAULT NULL COMMENT '评论时间' , `isReply` INT (4 ) BIGINT '0' COMMENT '是否是回复 0为否 1为是' , `commentStatus` BIGINT (4 ) NOT NULL DEFAULT '0' COMMENT '是否审核通过 0-未审核 1-审核通过' , `commentUrl` VARCHAR (100 ) NOT NULL COMMENT '评论对应的页面地址' , PRIMARY KEY (`id`) ) ENGINE= INNODB AUTO_INCREMENT= 53 DEFAULT CHARSET= utf8;
关键代码 实体类、Service接口、ApiUtil类(调用QQ头像、Gravatar、QQ昵称等api)、MD5Util类(MD5加密)、PatternUtil类(正则表达式类,判断邮箱、网站地址等)js,css等 以上代码将忽略 CommentMapper.xml
也将忽略,本文只围绕文章开头的几个问题进行处理,并不展示回复等功能(就insert操作很简单)
CommentMapper.java(接口)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Mapper public interface CommentMapper { int count () ; int reply (Comment comment) ; @Select("select * from comment where isReply=0 AND commentStatus=1 ORDER BY createTime DESC") List<Comment> CommentListf () ; @Select("select * from comment where isReply!=0 AND commentStatus=1 ORDER BY createTime ") List<Comment> CommentListz () ; }
CommentServiceImpl.java(实现类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 @Service public class CommentServiceImpl implements CommentService { @Autowired(required=false) CommentMapper mapper; @Override public int count () { return mapper.count(); } @Override public int reply (Comment comment) { if (comment.getIsReply()==null )comment.setIsReply(0 ); if (comment.getId()!=0 )comment.setIsReply(comment.getId()); comment.setCreateTime(new Date ()); comment.setCommentStatus(0 ); return mapper.reply(comment); } @Override public List<Comment> CommentListf () { return mapper.CommentListf(); } @Override public List<Comment> CommentListz () { return mapper.CommentListz(); } }
ControllerComment.java(Controller层)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 @Controller public class ControllerComment { @Autowired(required = false) private CommentServiceImpl commentService; private List<Comment> Mail (List<Comment> list) throws IOException, ParseException { for (Comment comment: list){ if (PatternUtil.isQQEmail(comment.getMail())){ Integer qq = Integer.valueOf(comment.getMail().substring(0 , comment.getMail().indexOf("@" ))); comment.setMail(ApiUtil.getHeadImage(qq)); }else { comment.setMail(ApiUtil.getGravatar(MD5Util.MD5Encode(comment.getMail()))); } } return list; } @RequestMapping("/") public String comment (Model mod) throws IOException, ParseException { mod.addAttribute("count" ,commentService.count()); List<Comment> listf = commentService.CommentListf(); mod.addAttribute("commentsf" ,Mail(listf)); List<Comment> listz = commentService.CommentListz(); mod.addAttribute("commentsz" ,Mail(listz)); return "index" ; } }
最后在template下新建index.html
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 <!DOCTYPE html > <html lang ="zh-CN" xmlns:th ="http://www.thymeleaf.org" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <script src ="https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js" > </script > <div id ="post-comment" > <div class ="comment-head" > <div class ="comment-headline" > <i class ="fas fa-comments fa-fw" > </i > <span > 评论</span > </div > </div > <div class ="comment-wrap" > <div > <div class ="vcomment v" id ="vcomment" > <div class ="vpanel" > </div > <div class ="vcount" style ="display: block; color: #e58a8a;" > <span class ="vnum" th:text ="${count}" > </span > 评论</div > <div class ="vcards" > <th:block th:each ="listf:${commentsf}" > <div class ="vcard" > <img class ="vimg lazyload" th:src ="${listf.getMail()}" referrerpolicy ="no-referrer" > <div class ="vh" > <div class ="vhead" > <a class ="vnick" rel ="nofollow" th:href ="${listf.getLink()}" target ="_blank" th:text ="${listf.getNick()}" > </a > </div > <div class ="vmeta" > <span style ="color: #828282;" class ="vtime" th:text ="${#dates.format(listf.getCreateTime(),'yyyy-MM-dd HH:mm')}" > </span > <span class ="vat" th:value ="${listf.getId()}" > 回复</span > </div > <div class ="vcontent" data-expand ="查看更多..." th:utext ="${listf.getContent()}" > </div > <div class ="vreply-wrapper" > </div > <th:block th:each ="listz:${commentsz}" > <div class ="vquote" th:if ="${listz.getIsReply()}==${listf.getId()}" > <div class ="vcard" > <img class ="vimg lazyload" th:src ="${listz.getMail()}" referrerpolicy ="no-referrer" > <div class ="vh" > <div class ="vhead" > <a class ="vnick" th:href ="${listz.getLink()}" th:text ="${listz.getNick()}" > </a > </div > <div class ="vmeta" > <span style ="color: red;" class ="vtime" th:text ="${#dates.format(listz.getCreateTime(),'yyyy-MM-dd HH:mm')}" > </span > <span class ="vat" th:value ="${listf.getId()}" > 回复</span > </div > <div class ="vcontent" data-expand ="查看更多..." th:utext ="${listz.getContent()}" > </div > <div class ="vreply-wrapper" > </div > </div > </div > </div > </th:block > </div > </div > </th:block > </div > <div class ="vload-top text-center" style ="display:none;" > <i class ="vspinner" style ="width:30px;height:30px;" > </i > </div > <div class ="vcards" > </div > <div class ="vload-bottom text-center" style ="display:none;" > <i class ="vspinner" style ="width:30px;height:30px;" > </i > </div > <div class ="vempty" style ="display: block;" > 来发评论吧~ </div > <div class ="vpage txt-center" style ="display:none" > <button type ="button" class ="vmore vbtn" > 加载更多...</button > </div > </div > </div > </div > </div > <link rel ="stylesheet" href ="/font/comment.css" > <link rel ="stylesheet" href ="/css/Comment.css" > <script src ="/js/article.js" > </script > </body > </html >
运行后的效果图
看不懂?很迷? 非常抱歉,由于目前部分功能为完善(其实我觉得完善了,但总感觉哪里不对劲,手动捂嘴笑),待处理完毕会发布到Github上