如图,bilibili的评论主要分为根评论(顶级评论)和子评论(回复评论),名称我乱说的哈哈,这里的顶级评论就是最顶级的意思,他不是任何评论的回复评论,bilibili前端显示也没有那种层层递进,但我相信表的结构设计肯定是有所体现的
红色为顶级评论,蓝色为子评论
1.表结构设计
废话不多说,首先是表结构的设计,一般评论应该有的属性字段我就不说了,这里主要考虑说明的是根评论与子评论(回复评论)是一个表还是两个表的问题,考虑到如果是两张表话,那就必须得为子评论再加一张子评论点赞表以及子评论又有子评论呢,就会发现问题又回到了原点,所以基于这两点考虑我将他们设计成一张表;
那么我们需要干些什么呢?
1.如何区分子评论和顶级评论:给表添加一个rootCommentId字段,如果为null则为顶级评论,如果不为空则为顶级评论的id
2.子评论回复的哪个评论(可能为子评论,可能为顶级评论):给表添加一个toCommentId字段,如果为null则为顶级评论,否则为目标评论id,这样一来就有层层递进的设计,能溯源
最终我的表结构如下:
当然我这里应该还要有回复目标用户昵称的字段如下图:据我的观察这个值有两点要注意:1,子评论的回复评论才有这个字段,2.不是动态的,而是回复目标评论用户某一时刻昵称,也就是说之后回复目标评论用户改变昵称,这个字段的值也不会改变
这样就很简单,只需要添加就完事了
2.如何进行sql查找
还是研究第一张图片的评论结构,我们还是发现主要两部分,根评论、根评论子评论总数以及他们各自的子评论(如果多于3条就只找前三条)
红色为顶级评论,蓝色为子评论
如何做呢?
1.分页获取顶级评论列表以及各自的子评论总数,这个sql比较好写
2.根据顶级评论的id列表,获取他们各自前三条子评论(以时间排序升序),一条sql语句就能办到,如下
这里有几点关键点要说一下
1.蓝色框为顶级评论分组获取前三的关键
2.分组的关键为绿色框内,按rootCommentId分组
3.获取前三的关键是红色框,这里要特别说的是videoCommentId一定是要不能重复,否则假如有四个子评论且videoCommentId都是一样的就会获取为空的尴尬结果(需要改进),我这里是自增主键,所以能代表按时间排序
4.那么效率如何呢,先给rootCommentId添加索引,再使用explain试试
可以看到查询效率是不错的,所以查询效率没问题。
3.根据rootCommentId分页获取子评论,sql好写
后端代码设计到这里结束;
前端设计:
这里值得一说的就是,就是红色框内的分页组件
仔细观察你会发现有这些情况:
只有一页的情况:
两页的情况:
三页的情况:
四页的情况:
五页的情况:
六页的几种情况:
七页的几种情况:
大于七页的几种情况:
总结一下:
1.首先子评论是否多于两页,少于两页分页组件为空,不继续,否则继续
2.输出分页组件,如下:红色框内为必定会有的,这里说明一下5代表当前页也为中心点,1和19分别代表首页跟尾页
3.这里主要说明下蓝色框算法如何实现:
a.选一个中心点:首先判断当前页如果是首页或者尾页就进行加1或减1作为中心点,否则当前页就是中心点
b.两个循环外的变量用来分别判断是否输出左右的两个省略号,各自的值将会是下面的第二次循环左右跳后的值
c.以中心点循环进行两次左右横跳(加一减一,加二减二),左右各跳一次为一次循环
d.循环:初始化一个循环内的临时变量(初始值为false)用来判断是否继续下次循环,左跳一次后判断如果小于等于首页就不输出,否则输出,临时变量置true;右跳一次后判断如果大于等于尾页就不输出,否则输出,临时变量置true;
e.判断是否需要输出左右的省略号:大于2输左省略号出,否则不输出,小于尾页-1输出右省略号,否则不输出
算法结束;
至此前后端完成。
效果如下,这是我的毕业项目,模仿bilibili的视频直播网站
当然,我这里的分页组件算法还是跟bilibili有点区别的