SpringBoot + uniapp 实现App评论回复功能
效果展示:
一、 数据库表
二、 后端接口
三、 前端实现
一、 表
-
comment 评论表
content: 评论内容
art_id: 文章ID 表示属于哪篇文章的评论
u_id: 评论人ID 用来查询评论人信息的 -
reply 回复表
r_id: 回复ID
content: 回复内容
u_id: 回复人的ID
comment_id: 评论ID 属于对应评论的回复
to_r_id: 默认为null 如果不为null 则表明这是一条回复的回复 为null 则为回复
二、 后端接口 ( 这里没做分页,实现分页也非常简单 )
- 查询对应文章的所有评论及其回复的数量
Service
// 根据文章ID查询评论
List<FindCommentsVo> findCommentsVos = commentMapper.findCommentsByArtId(artId);
// 根据评论ID 查询回复的数量
for (FindCommentsVo findCommentsVo: findCommentsVos){
int replyCount = replyService.findReplyCountByCommentId(findCommentsVo.getCId());
findCommentsVo.setReplyCount(replyCount);
}
Mapper
// 根据文章ID查询评论
@Select("SELECT username,u_pic,c.id as c_id,content,c.created_time FROM comment as c inner join user on user.id = c.u_id WHERE art_id = #{artId}")
List<FindCommentsVo> findCommentsByArtId(int artId);
- 根据评论ID查询所有回复
Service
List<Object> list = new ArrayList<Object>();
// 第一次查询回复 第二次查询回复的回复
List<FindReplysVo> findReplysVos = replyMapper.findAllReplyByCommentId(commentId);
for (FindReplysVo findReplysVo: findReplysVos){
list.add(findReplysVo);
}
// 查询回复的回复
List<FindReplytoReplyByCommentId> replyToReplys = replyMapper.findAllReplytoRepleByCommentId(commentId);
for (FindReplytoReplyByCommentId replyToReply: replyToReplys){
list.add(replyToReply);
}
上述代码有一个Bug 回复的回复始终会显示在回复的下方
这个问题在前端去解决
Mapper
@Select("SELECT COUNT(*) FROM reply where comment_id = #{commentId}")
int findCountByCommentId(int commentId);
@Select(("SELECT username,u_pic,r_id,content,u_id,comment_id,to_r_id,reply.created_time " +
"FROM reply inner join user on user.id = reply.u_id where comment_id = #{commentId} AND to_r_id IS NULL "))
List<FindReplysVo> findAllReplyByCommentId(int commentId);
@Select("SELECT u1.username AS replyUsername,u1.u_pic AS replyUpic,\n" +
" r1.r_id AS replyReplyId,r1.content AS replyContent,r1.created_time,\n" +
" r2.content AS ByreplyContent,u2.username AS ByreplyUsername,u2.u_pic AS ByreplyUpic\n" +
" FROM reply AS r1,user AS u1,reply AS r2,user AS u2\n" +
" WHERE r1.u_id = u1.id AND r1.to_r_id = r2.r_id AND r2.u_id = u2.id\n" +
" AND r1.comment_id = #{commentId} ")
List<FindReplytoReplyByCommentId> findAllReplytoRepleByCommentId(int commentId);
三、 前端实现
- 评论
<view class="content">
<view class="comment animated bounceIn" v-for="(res, index) in commentList" :key="res.cid" >
<view class="left">
<image :src="res.upic" mode="aspectFill"></image>
</view>
<view class="right">
<view class="top">
{{res.username}}
</view>
<view class="content">{{ res.content }}</view>
<view class="reply-box">
<view class="all-reply" @tap="toAllReply(res)" v-if="res.replyCount != 0 ">
共{{ res.replyCount }}条回复
<u-icon class="more" name="arrow-right" :size="26"></u-icon>
</view>
</view>
<view class="bottom">
{{ res.createdTime }}
<view class="reply" @tap="toAllReply(res)">回复</view>
</view>
</view>
</view>
</view>
- 回复
<!-- 被回复的评论 -->
<view class="comment">
<view class="top">
<view class="left">
<view class="heart-photo">
<image :src="comment.upic" mode=""></image>
</view>
<view class="user-info">
<view class="name">{{ comment.username }}</view>
<view class="date">{{ comment.createdTime }}</view>
</view>
</view>
</view>
<view class="content">{{ comment.content }}</view>
</view>
<!-- 全部的回复 -->
<view class="all-reply">
<view class="all-reply-top">全部回复({{ comment.replyCount }})</view>
<view @click="replyToreply(item.username,item.rid,item.replyReplyId)" class="item animated bounceIn" hover-class="itemHover" hover-stay-time="1000"
v-for="(item, index) in replyList" :key="index">
<view class="comment">
<view class="top">
<view class="left">
<view class="heart-photo">
<image v-if="item.toRId == 0 " :src="item.upic" mode=""></image>
<image v-if="item.toRId != 0 " :src="item.replyUpic" mode=""></image>
</view>
<view class="user-info">
<view class="name">{{ item.toRId == 0 ? item.username: item.replyUsername }}</view>
<view class="date">{{ item.createdTime }}</view>
</view>
</view>
</view>
<view class="reply" v-if="item.toRId != 0 ">
<view class="username">{{ item.byreplyUsername }}</view>
<view class="text">{{ item.byreplyContent }}</view>
</view>
<view class="content">{{ item.toRId == 0 ? item.content: item.replyContent }}</view>
</view>
</view>
</view>
<!-- 发表评论组件 -->
<publishComment ref="publishComment" v-on:shuaxin="getReply()" :to_r_id="to_r_id" :comment_type="type"
:art_id="art_id" :comment_id="c_id" ></publishComment>
此外,为了能够让评论显示的更加友好一些,这里按照发表时间的时间戳进行了降序排列
var compare = function (prop){
return function (obj1, obj2) {
var v1;
var v2;
if(prop === "createdTime"){
v1 = new Date(obj1[prop]).getTime()
v2 = new Date(obj2[prop]).getTime()
}else{
v1 = new Date(obj1[prop])
v2 = new Date(obj2[prop])
}
if (v1 > v2) {
return -1;
} else if (v1 < v2) {
return 1;
} else {
return 0;
}
}
}
export default compare
prop: 是你要进行排序的属性名