Java单表实现评论回复功能
•
Jave
Java单表实现评论回复功能
- 1.简介
- 2.功能实现图
- 3.数据库设计
- 4.实体类
- 5.实现思路
- 6.功能实现
-
- 6.1 Sql入手
- 6.2 业务实现
- 7.前端实现
- 8.最终成果
1.简介
最近在写毕业设计的时候发现需要实现一个评论功能,然后看了一下掘金和csdn的评论区,如何实现评论功能?
评论功能有多种实现方式:
- 单层型
- 套娃型(多层型)
- 两层型
单层型:

套娃型:

两层型:

2.功能实现图

3.数据库设计
这个地方有个answer_id 很容易让人迷糊:是回复哪个用户的id
CREATE TABLE `tb_blog_comments` ( `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键', `user_id` bigint(20) UNSIGNED NOT NULL COMMENT '用户id', `blog_id` bigint(20) UNSIGNED NOT NULL COMMENT '探店id', `parent_id` bigint(20) UNSIGNED NOT NULL COMMENT '关联的1级评论id,如果是一级评论,则值为0', `answer_id` bigint(20) UNSIGNED NOT NULL COMMENT '回复的评论id', `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '回复的内容', `liked` int(8) UNSIGNED NULL DEFAULT 0 COMMENT '点赞数', `status` tinyint(1) UNSIGNED NULL DEFAULT 0 COMMENT '状态,0:正常,1:被举报,2:禁止查看', `create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '创建时间', `update_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = COMPACT; SET FOREIGN_KEY_CHECKS = 1;
4.实体类
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import java.io.Serializable; import java.time.LocalDateTime; import java.util.List; /** ** *
* * @author 尹稳健 * @since 2022-11-09 */ @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("tb_blog_comments") public class BlogComments implements Serializable { private static final long serialVersionUID = 1L; /** * 主键 */ @TableId(value = "id", type = IdType.AUTO) private Long id; /** * 用户id */ private Long userId; /** * 探店id */ private Long blogId; /** * 关联的1级评论id,如果是一级评论,则值为0 */ private Long parentId; /** * 回复的评论id */ private Long answerId; /** * 回复的内容 */ private String content; /** * 点赞数 */ private Integer liked; /** * 状态,0:正常,1:被举报,2:禁止查看 */ private Boolean status; /** * 创建时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; /** * 更新时间 */ private LocalDateTime updateTime; /** * 是否点赞 */ @TableField(exist = false) private Boolean isLike; /** * 子评论 */ @TableField(exist = false) List children; /** * 评论者的昵称 */ @TableField(exist = false) private String nickName; /** 评论者的头像 */ @TableField(exist = false) private String icon; /** 评论者的上级昵称 */ @TableField(exist = false) private String pNickName; /** 评论者的的上级头像 */ @TableField(exist = false) private String pIcon; }
5.实现思路
- 因为有评论区有两层,所以肯定有一个parent_id,这样你才能知道你是哪个评论下面的回复内容,如果继续评论,那么那条评论的parent_id还是之前那条评论的parent_id,而不是那条子评论的id。
- 回复内容也同样是一个评论实体类,只不过是一个集合,所以用List 存储,泛型使用实体类
- 我的功能实现也用到了父评论的用户名和头像,这样可以更好看出这是谁评论的,回复给谁的评论
6.功能实现
6.1 Sql入手
首先,我们需要知道自己需要哪些数据,返回给前端
如果你连mybatis都不会,那就看下思路吧
从这里获取到了评论表的所有数据,以及评论的人的信息,比如说昵称、头像、id,可以展示在前端
SELECT
bl.*,
u.icon,
u.nick_name
FROM `tb_blog_comments` bl
left join tb_user u
on u.id = bl.user_id
where bl.blog_id = #{blogId}
order by bl.id desc
对应的mapper接口
package com.sky.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.sky.pojo.BlogComments; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** ** Mapper 接口 *
* * @author 尹稳健 * @since 2022-11-09 */ @Mapper public interface BlogCommentsMapper extends BaseMapper { /** * 查询所有的评论信息 * @param blogId * @return */ List findCommentDetail(Long blogId); }
6.2 业务实现
- 1.首先我们需要从数据中获取所有的数据
- 2.然后我们需要找到所有的一级评论,一级评论就是最高级,他不在谁的下面,他就是最大的,我这里在添加评论的时候前端做了处理,只要是一级评论,他的paren_id = 0
- 3.然后我们需要从一级评论下面添加他下面所有的子评论
- 最主要的就是如何将父级评论的信息添加到自己的数据中?
- 4.通过子评论中的paren_id 找到父评论,然后通过子评论的answer_id == 父评论的user_id 这样就可以拿到父评论的那一条数据
- 最后通过Optional 添加到子评论的数据中
@Override
public Result showBlogComments(Long blogId) {
// 先将数据库中的数据全部查询出来,包括评论作者的信息,昵称和头像
List blogComments = blogCommentsMapper.findCommentDetail(blogId);
// 获取所有的一级评论
List rootComments = blogComments.stream().filter(blogComments1 -> blogComments1.getParentId() == 0).collect(Collectors.toList());
// 从一级评论中获取回复评论
for (BlogComments rootComment : rootComments) {
// 回复的评论
List comments = blogComments.stream()
.filter(blogComment -> blogComment.getParentId().equals(rootComment.getId()))
.collect(Collectors.toList());
// 回复评论中含有父级评论的信息
comments.forEach(comment -> {
// 无法判断pComment是否存在,可以使用Optional
Optional pComment
= blogComments
.stream()
// 获取所有的评论的回复id也就是父级id的userid,这样就可以获取到父级评论的信息
.filter(blogComment -> comment.getAnswerId().equals(blogComment.getUserId())).findFirst();
// 这里使用了Optional 只有pcomment!=null 的时候才会执行下面的代码
pComment.ifPresent(v -> {
comment.setPNickName(v.getNickName());
comment.setPIcon(v.getIcon());
});
// 判断是否点赞
isBlogCommentLiked(comment);
});
rootComment.setChildren(comments);
// 判断是否点赞
isBlogCommentLiked(rootComment);
}
return Result.ok(rootComments);
}
7.前端实现
因为前端代码很多,只copy关键代码
{{comment.nickName}}
{{comment.createTime}}
{{comment.liked}}
回复
删除
{{comment.content}}
{{reply.nickName}} 回复: {{reply.pnickName}}
{{reply.createTime}}
{{reply.liked}}
回复
删除
{{reply.content}}
let each = function (ary, callback) {
for (let i = 0, l = ary.length; i < l; i++) {
if (callback(ary[i], i) === false) break
}
}
const app = new Vue({
el: "#app",
data: {
util,
showPopover: false,
actions: [{ text: '回复', icon: '' }, { text: '删除', icon: '' }],
commentsTotal: '', // 评论总数
checkCommentInputVisible: false, // 判断是否点击回复
commnetList: {}, // 评论回复列表
placeholderText: '发条友善评论吧~~',
commentForm: {
content: '',
userId: '',
blogId: '',
parentId: 0,
answerId: 0,
}, // 评论表单
blog: {},
shop: {},
likes: [],
user: {}, // 登录用户
methods: {
replyCommentForm(comment) {
this.placeholderText = "回复 " + comment.nickName
this.checkCommentInputVisible = true;
if (comment.parentId == 0) {
this.commentForm.parentId = comment.id;
} else {
this.commentForm.parentId = comment.parentId;
}
this.commentForm.answerId = comment.userId;
},
submitCommentForm() {
this.commentForm.userId = this.user.id;
this.commentForm.blogId = this.blog.id;
axios.post("/blog-comments/saveBlogComment", this.commentForm)
.then(res => {
this.loadComments(this.blog.id);
this.checkCommentInputVisible = false;
})
.catch(err => this.$message.error(err))
},
loadComments(id) {
axios.get("/blog-comments/showBlogComments/" + id)
.then(res => {
this.commnetList = res.data
})
.catch(err => this.$message.err(error))
},
}
8.最终成果

点赞、评论、回复、删除

如果需要源码,可以评论区留言,我天天都会看的哦!感谢!
本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/0265c5be5a.html
