先看实现的效果图
评论及评论回复实现
- 分析
评论和评论回复可以设计成1张表也可以设计成2张表,根据使用场景的不同选择,这里我将评论和回复表设计成一张表,表结构如下
CREATE TABLE `tb_post_newcomment` (
`post_comment_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '说说评论表id',
`group_post_id` int(11) DEFAULT NULL COMMENT '说说id',
`uid` int(11) DEFAULT NULL COMMENT '用户id',
`nickname` varchar(50) DEFAULT NULL COMMENT '用户昵称',
`avatar_url` varchar(255) DEFAULT NULL COMMENT '用户头像地址',
`content` varchar(255) DEFAULT NULL COMMENT '评论内容',
`createtime` datetime DEFAULT NULL COMMENT '创建时间',
`status` varchar(2) DEFAULT NULL COMMENT '状态 -1已删除 0正常',
`to_uid` int(11) DEFAULT NULL COMMENT '目标用户id ',
`to_user_nickname` varchar(50) DEFAULT NULL COMMENT '目标用户昵称 沉余字段',
`to_user_avatar` varchar(255) DEFAULT NULL COMMENT '目标用户头像 沉余字段',
PRIMARY KEY (`post_comment_id`)
) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8mb4 COMMENT='动态评论';
其中最主要的是字段需要包含用户id和目标用户id,当然还有评论内容content字段,用户id和目标用户id这里可以理解成是谁评论了谁或谁回复了谁
- 设计完表结构之后,再来看代码实现
在小程序页面里
doNewComment(){
let content = this.commentContent;
if(!content){
return;
}
api.postNewComment({
uid:this.userid,
postid:this.curPostItem.group_post_id,
post_user_id:this.curPostItem.uid,//当前这条动态所属人 用于消息通知
content:this.commentContent,
nickname:this.xuserInfo.nickname,
avatar_url:this.xuserInfo.head_url,
to_uid:this.curCommentItem?this.curCommentItem.uid:0,//默认值0 ,为空时传0
to_user_nickname:this.curCommentItem?this.curCommentItem.nickname:'',
to_user_avatar:this.curCommentItem?this.curCommentItem.avatar_url:'',
}).then(res=>{
if(res.code==0){
this.curPostItem.comments.push(res.data);
this.commentContent = '';
this.isShowComment = false;
}
})
},
这里需要注意的是,如果是评论的话,我们将目标用户id设置为空,回复的话则将要回复的目标id传过去。
在小程序后端,通过接受前端传过来的数据,将其保存到数据库表中,保存成功后更新评论表的count字段,最后返回当前评论对象到前端进行页面显示
if (result.affectedRows === 1) {
// 更新说说表评论数量
let postResult = await this.app.mysql.select('tb_group_posts', {
where: { group_post_id: group_post_id }
})
let comment_count = postResult[0].comment_count;
comment_count += 1;
await this.app.mysql.update('tb_group_posts', { comment_count: comment_count }, {
where: {
group_post_id: group_post_id
}
});
// 返回当前评论记录
let commentResult = await this.app.mysql.select('tb_post_newcomment', {
where: { post_comment_id: result.insertId }
})
return commentResult[0];
}
前端评论及回复页面展示
<ul class="comment-list" v-if="item.comments.length>0">
<li class="comment-item" v-for="(comment,commentIndex) in item.comments" :key="commentIndex" @click="replyShow(comment);getCurPostItem(item)">
<div v-if="comment.to_uid!=0"><span class="nickname">{{comment.nickname}}</span>回复<span class="nickname">{{comment.to_user_nickname}}</span>:{{comment.content}}</div>
<div v-else><span class="nickname">{{comment.nickname}}</span>:{{comment.content}}</div>
</li>
</ul>
消息通知实现
我们创建一个消息通知表,当我们点赞和评论的时候,创建一条消息通知记录,表结构设计如下
CREATE TABLE `tb_notify` (
`notify_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '通知id',
`content` varchar(1000) DEFAULT NULL COMMENT '消息内容 公告和私信类型的消息使用',
`type` varchar(2) DEFAULT NULL COMMENT '通知类型 1、公告 2、提醒 3、私信',
`target_id` int(11) DEFAULT NULL COMMENT '目标id(如post的id)',
`action` varchar(2) DEFAULT NULL COMMENT '1、点赞 2、评论 3、回复 4、关注',
`sender_id` int(11) DEFAULT NULL COMMENT '发送者id',
`sender_type` varchar(2) DEFAULT NULL COMMENT '发送者类型 1普通用户 2管理员',
`user_id` int(11) DEFAULT NULL COMMENT '消息所属者,如post动态发布者',
`is_read` varchar(2) DEFAULT NULL COMMENT '消息是否已读 0未读 1已读',
`created_at` datetime DEFAULT NULL COMMENT '创建时间',
`nickname` varchar(50) DEFAULT NULL COMMENT '发送者昵称',
`avatar_url` varchar(255) DEFAULT NULL COMMENT '发送者头像',
`comment_id` int(11) DEFAULT NULL COMMENT '评论id 评论的时候存储',
PRIMARY KEY (`notify_id`)
) ENGINE=InnoDB AUTO_INCREMENT=120 DEFAULT CHARSET=utf8mb4 COMMENT='通知消息';
- 一般消息通知分为公告、提醒和私信三个类别的通知消息 ,type字段用于存储消息通知类型
- action用来保存动作,例如,点赞、评论、回复或关注
- user_id用来存储该条消息的接收者 ,如评论回复的目标用户id,如没有目标用户id,则消息所属人为该条动态的发布者
- is_read表示的是消息读取状态 ,已读和未读
- sender_id就是消息发送者id了 ,谁触发的这个动作 ,评论人、点赞的人
后端逻辑代码如下
try {
let result = await this.GroupService.postNewComment(params);
if (result) {
// 消息通知目标人 根据to_uid判断 0的话说明是评论 则消息通知目标人为动态发布者,否则的话消息通知目标人为to_uid
let notify_user_id = params.to_uid ? params.to_uid : params.post_user_id;
let notifyObj = {
comment_id: result.post_comment_id,//评论id
content: params.content,//评论内容
type: '2',//1、公告 2、提醒 3、私信
target_id: params.postid,
//action 1点赞 2评论 3回复 4关注
action: params.to_uid?'3':'2',
sender_id: params.uid,//发送者id
nickname: params.nickname,
avatar_url: params.avatar_url,
is_read: '0',
user_id: notify_user_id,//消息所属人
}
// 添加消息通知 如果是自己则不创建通知消息
if (params.uid != notify_user_id) {
await this.NotifyService.add(notifyObj);
}
// 返回当前评论记录
response = this.ResultResponse.createBySuccessData(result);
} else {
response = this.ResultResponse.createByErrorMsg('评论失败');
}
对于消息创建,如果是我们自己评论了自己,则此时不用去创建消息通知,只有在别人评论或者回复的时候去创建
前端页面展示及逻辑
<div class="action" v-if="list.length>0">
<span v-text="lastUnreadNotify.nickname"></span>
<span v-text="lastUnreadNotify.action==1?'赞了你的动态':lastUnreadNotify.action==2?'评论了你的动态':lastUnreadNotify.action==3?'回复了你的评论':'关注了你'"></span>
</div>
我们在小程序首页mounted方法里面创建一个定时器,每5秒或者10去请求一次未读消息接口,如果有未读消息则设置底部消息栏小红点提醒
// 轮询 每15秒请求一次
this.setNotifyRemind();
setInterval(() => {
this.setNotifyRemind();
}, 15000);
loadData(){
api.unReadNotifyList({
uid:this.uid
}).then(res=>{
if(res.code==0){
this.list = res.data
if(this.list.length>0){
this.lastUnreadNotify = this.list[0];
// 设置tab小红点
wx.setTabBarBadge({index: 3,text: `${this.list.length}`})
}else{
wx.removeTabBarBadge({index: 3})
}
}
wx.stopPullDownRefresh();
})
},
当点击消息列表的时候再将用户通知消息全部设置为已读状态就可以了
最后
以上就实现了小程序的评论、评论回复及消息通知的功能,这在小程序里面都是很常见的功能,特别是在社交小程序当中,当然,从表结构的设计到页面的展示还有很多不完善考虑不周的情况,也只有在以后的使用过程中发现问题再去优化了 。