文章

!评论功能的实现 !

Title01.png

内容概述

现在我的小程序功能开发几近尾声,还有一个重中之重的功能尚未实现——评论功能

在我的构想中如果做一个一层结构不带回复的评论功能略显潦草,所以我想要做出一个带回复的双层结构评论功能。

Title02.png

数据库表格的创建

对于我这样双层结构评论的数据库表格实现本来可采用两张表分别装主评论和回复评论,但是这样涉及到多表联查,我们不想搞得如此复杂,最终我决定采用一张表装下所有评论的方式,不过对于这张表需要增加一个新的字段来标识主评论和回复评论。

此表全部字段如下:

分别代表评论本身id,项目id,评论用户id,评论内容,父评论id,创建时间,更新时间。

我们规定父评论id为0的评论为主评论,父评论id为几则为对应id的评论的回复评论。

这样就又双叒叕涉及一个问题就是我们在后端创建的java实体类comment中不包含自己下边的回复评论这个属性。

所以我们需要引入一个更大的commentVo类,这个Vo类单独存在并且包含了comment类中的所有属性,还多包含了它的所有回复评论以及发表该评论的用户名。

public class CommentVo extends Comment {
    private Page<CommentVo> children;
    private User user;
}

如此这般,我们在后端通过各项逻辑查询到对应的数据和内容之后可以将想要用的内容全部塞在这个commentVo类中做出返回,这样我们所需要展示的所有信息皆在一个类中,方便获取和使用。

Title03.png

后端逻辑的实现

代码如下:

@GetMapping
    public ResponseResult<Page<CommentVo>> list(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10")Integer size, Integer userId, Integer programId,Integer parentId){
        Page<Comment> commentPage = new Page<>(page, size);
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(userId != null,Comment::getUserId,userId);
        queryWrapper.eq(programId != null,Comment::getProgramId,programId);
        queryWrapper.eq(parentId != null,Comment::getParentId,parentId);
        queryWrapper.eq(parentId == null,Comment::getParentId,0);

        Page<Comment> pageList = commentService.page(commentPage, queryWrapper);

        List<CommentVo> collect = pageList.getRecords().stream().map(i -> {
            CommentVo commentVo = new CommentVo();
            BeanUtils.copyProperties(i, commentVo);
            commentVo.setUser(userService.getById(commentVo.getUserId()));

            Page<Comment> childrenPage = new Page<>(1, 1);
            LambdaQueryWrapper<Comment> childrenQueryWrapper = new LambdaQueryWrapper<>();
            childrenQueryWrapper.eq(i.getId() != 0, Comment::getParentId, i.getId());
            Page<Comment> childrenPageList = commentService.page(childrenPage, childrenQueryWrapper);

            if (childrenPageList.getRecords().size()>0){
                ArrayList<CommentVo> commentVos = new ArrayList<>();
                Comment comment = childrenPageList.getRecords().get(0);
                CommentVo vo = new CommentVo();
                BeanUtils.copyProperties(comment,vo);

                User byId = userService.getById(comment.getUserId());
                vo.setUser(byId);

                commentVos.add(vo);

                Page<CommentVo> voPage = new Page<>();
                BeanUtils.copyProperties(childrenPageList,voPage);

                voPage.setRecords(commentVos);


                commentVo.setChildren(voPage);
            }

            return commentVo;

        }).collect(Collectors.toList());

        Page<CommentVo> commentVoPage = new Page<>();
        pageList.setRecords(null);
        BeanUtils.copyProperties(pageList,commentVoPage);
        commentVoPage.setRecords(collect);

        return ResponseResult.success(commentVoPage);
    }

关于这段代码最基础的理解就是首先按照需求查询我们需要的评论内容并传入page对象pageList,接着,通过streammap方法对查询结果进行处理,将Comment对象转换为CommentVo对象,并设置CommentVo对象中的用户信息。

在处理过程中,还对每个顶级评论查询了其子评论。如果存在子评论,则将第一个子评论转换为CommentVo对象,并设置到对应的顶级评论的children属性中。

最后,创建一个新的Page<CommentVo>对象commentVoPage,将pageList中的分页信息复制到commentVoPage中,并将转换后的评论列表赋值给commentVoPagerecords属性。

最后,通过ResponseResult.success方法将commentVoPage对象包装成一个成功的响应结果进行返回。

License:  CC BY 4.0