客户端评论盖楼(内涵段子评论盖楼)实现思路

前言

出来上班也2~3年了,总觉得作为一个程序员,我们应该有一个自己的产品,无论是从提升技术角度出发,还是作为对自己行业认知的检验。所以从2016年8月中旬,我开始动工自己的第一个APP开发。

也由于最近一直忙于APP开发,以至于好久都没有时间写博客了,或许有人会说分明是我懒,时间是一定可以挤出来的,但是有时候真的是没有时间。

一开始跟一个朋友合作开发,他负责做后台(接口,数据管理系统),本人做安卓前端,产品定位,需求,以及其他一些零零碎碎的东西,因为这个东西是我热衷的,他算是帮助我完成梦想,可是我们都知道,要坚持一件事情是有多么难啊,何况我们没有共同的愿景,没有共同的热血心态,因此他中途离开了。。。

我想了很久,感觉自己花费了太多的心血,真的是心血,,从画草图开始,到产品定位越来越清晰,,实在不愿意放弃这个自己喜欢的东西,,于是,我决定自己硬着头皮上了,,,把后台的工作也揽过来一起上。

或许只有真正经历过的人才知道,这期间的到底有多累,无论是体力还是脑力,虽然说编程的思想是想通的,但是做一门自己不熟悉的语言,还是有一定的难度,况且大家都知道其实后台是比较难的,相对于前端来说,,,

现在客户端做的差不多了,在陆陆续续写数据接口对接数据,过程就不多说了,今天就来说说关于 评论盖楼实现的思路,由于本人经常看内涵段子,于是就打算仿照内涵段子实现一下

网上搜索了一番没有找到明确的答案,于是静下心来想想一些可行的思路,先不说是不是最优的解决方案,至少是可以实现,打算第一版本就用这种方式实现了。先看看客户端效果图

这里写图片描述

(对了我的APP叫“纯粹美食”,一个跟美食相关的APP,看客们可以留意一下,暂时没有上线,到时候上线了,可以下载体验一下)

后台分析(JAVA 语言,SSM框架,MYSQL数据库)

1.评论表基本分析

最基本的评论信息: 用户信息,评论内容,评论对象,评论时间
这个是毫无疑问的

2.回复评论

现在产品经理说要添加一个功能: 回复评论
那我们只能添加一个字段:回复ID (约定:回复ID默认为0,如果不为0表示回复别人的评论)

3.删除评论

啪啪啪,三两下就把这个功能做好了,产品经理又走过来说要加一个功能: 删除评论

对于数据的删除问题一般分为两种:1.逻辑删除,2物理删除
1.逻辑删除:一般是指修改字段的值来控制某些数据的状态,达到删除的效果
2.物理删除:直接删除数据库记录
个人觉得,对于重要数据,或者操作性比较强的数据,一般使用逻辑删除,一些无关重要的数据可以使用物理删除,我们都知道现在 最值钱的就是数据了,哪能那么轻易删掉

这么一想,删除评论好像也不难哦,添加一个字段来控制吧:is_delete (约定:默认为0,1表示删除)

4.评论盖楼
这个时候你嘴贱问一下产品,还有什么功能要做的没,一次性说完,产品经理想了一下:要不评论盖楼也实现一下。

真的是 hit the dog ,为什么要嘴贱多问一句呢?没办法,现在只能实现了
(我不一样,我自己是程序又是产品,只要有利于产品的我都尽可能的去实现)

评论盖楼的问题,不是简单的通过添加字段就能实现的。所以现在表设计如下

这里写图片描述

基本上这些字段已经足够实现评论模块的内容了。

那么评论盖楼要怎么实现呢?

我的想法是把压力放在服务端,就是服务端查询评论列表的时候处理好数据格式,再返回给客户端
一条基本评论信息之外添加一个实体属性:回复列表 List< Comment > replyList;

在服务端获取到评论集合之后,循环遍历,查看哪些是回复评论,哪些是普通评论 ,通过 replyId 值是否为0判断,如果是回复评论,根据 replyId 查询到被回复的评论信息,然后递归查询被回复评论的 replyId ,直到replyId =0,然后将这些被回复的评论添加到 回复列表 replyList 集合中

简单代码示例:实体类

public class Comment {

    private int id;

    // 评论内容
    private String content;

    // 回复ID[默认为0,表示普通评论,回复评论时:replyId值是被评论数据的ID]
    private int replyId;

    // 用户ID
    private int userId;

    // 被评论的对象ID[文章ID,新闻ID...]
    private int objectId;

    // 是否已经删除[0:正常状态,1:已删除]
    private int isDelete;

    // 评论时间
    private int createTime;

    // 回复评论集合[辅助属性]
    private List<Comment> replyList;

    // getter/setter省略,,,

}

下面是service代码:评论接口实现方法

    /**
     * 获取评论列表
     * @param objectId 被评论对象ID
     * @param pageNumber 前端分页页码
     * @return
     * @author Ruffian
     * @date 2017年1月24日
     */
    @Override
    public XResponse<Object> getCommentList(int objectId, int pageNumber) {

        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("XXX", "ZZZZ");

        //连接数据库,获取满足条件的数据列表,,,详情省略...
        List<Comment> list = mCommentMapper.getList(map);

        if (list != null) {
            /**
             * 处理回复评论 <br/>
             * 1.循环评论列表 2.设置回复列表内容,没有则为空
             */
            Comment comment = new Comment();
            for (int i = 0; i < list.size(); i++) {

                comment = list.get(i);
                comment.setReplyList(mCommentHandle.getReplyCommentList(comment));//这里处理回复列表逻辑
                list.set(i, comment);

            }
        }

        //返回接口数据
        return new XResponse<Object>(RCode.SUCCESS, RMessage.SUCCESS, list);
    }

处理回复列表逻辑方法

    /**
     * 获取某一条评论的 回复列表数据
     * 循环遍历 replyId,只要不为0 则继续根据replyId 查找被回复的评论数据,同时添加到 回复列表
     * @param comment
     * @return
     */
    public List<Comment> getReplyCommentList(Comment comment) {
        List<Comment> replyList = new ArrayList<>();//回复评论列表
        Comment replyCom = comment;
        boolean flag = true;
        while (flag) {
            int replyId = replyCom.getReplyId();
            if (replyId > 0) {
                Map<String, Integer> map = new HashMap<>();
                map.put("id", replyId);
                replyCom = mCommentMapper.getCommentById(map);// 根据 replyId 查询被回复的评论数据
                replyCom.setReplyList(null);// 设置   被回复评论 的 replyList 为空
                replyList.add(replyCom);// 添加回复评论数据
            } else {
                flag = false;
            }
        }
        return replyList;
    }

懵逼吗?希望不会,那么现在得到的数据是怎么样的呢?

这里写图片描述

来看看这张图,圈出来这条数据是一个普通评论,可以看到,replyList的数据是null,replyId=0表示这是一条普通评论没有回复别人的评论。

然后再看看有回复评论的数据
这里写图片描述

我们看到这个评论列表有两条数据,一条是普通评论,一条是回复评论,其中我们注意到有一个条评论已经被删除了,所以一开始效果图中会展示 灰色 字体,用来区分,同时不再展示被删除的评论内容。

那我们客户端拿到这样的数据列表要怎么操作呢?
得到数据列表之后,前端要怎么实现盖楼UI就各自发挥了,也很简单,如果说按照一开始的效果图实现的话,我前端是这样实现的:

由于我们能拿到每一条评论的基本数据,无论是普通评论还是回复评论,回复评论就多了一个 replyList 列表数据。

那就简单啦,以上图数据举例: 拿到评论ID=7的数据,循环遍历replyList数据,拼接replyList评论内容,最后再把ID=7的评论内容再拼接上。搞定。

Android客户端示例代码:

这里写图片描述

获取到评论内容,通过Android自带接口解析html就可以了。

由于是在项目中使用了这些代码,很难抠出代码开提供下载,所以这个就当做是一种解决思路吧。如果刚好在研究这方面的小伙伴可以留言探讨一下更好的实现方式。

PS:一个人做一个产品是在太累了,本来想做完安卓客户端之后就去学习IOS,可是时间太紧迫了,后期更多时间想投入到运营和维护中,这里特招一名自认为能力出众的IOS小哥一起完成梦想。如果你对我的美食项目有兴趣可以主页找我的联系方式,一起做点事情。
春节临近,今年连年终总结都没时间写,一直埋头写代码,还有貌似前段时间小程序正式上线了,特想抽点时间去看看到底有多厉害,口口声声说要抢APP的饭碗,吓得我赶紧去学习了后台开发,哈哈

实现评论盖楼系统一般需要以下步骤: 1. 创建评论表:在MySQL中创建一个表来存储评论数据,包括评论内容、时间戳、用户ID、回复的评论ID等字段。例如: ``` CREATE TABLE comments ( id INT(11) NOT NULL AUTO_INCREMENT, user_id INT(11) NOT NULL, content TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, parent_id INT(11), PRIMARY KEY (id) ); ``` 2. 编写PHP脚本:编写PHP脚本来处理用户提交的评论,并将其保存到数据库表中。需要注意的是,当用户回复某条评论时,需要保存该评论的ID作为回复的评论ID。 ``` // 连接数据库 $conn = mysqli_connect($host, $username, $password, $dbname); // 处理用户提交的评论 if ($_SERVER['REQUEST_METHOD'] == 'POST') { $user_id = $_POST['user_id']; $content = $_POST['content']; $parent_id = $_POST['parent_id']; $sql = "INSERT INTO comments (user_id, content, parent_id) VALUES ('$user_id', '$content', '$parent_id')"; mysqli_query($conn, $sql); } ``` 3. 显示评论列表:编写PHP脚本来查询数据库中的评论数据,并将其显示在页面上。需要使用递归算法来处理评论的嵌套结构,并使用CSS和JavaScript来实现评论盖楼的效果。 ``` // 获取根评论列表 $sql = "SELECT * FROM comments WHERE parent_id IS NULL"; $result = mysqli_query($conn, $sql); // 递归处理子评论列表 function showComments($parent_id, $level) { global $conn; $sql = "SELECT * FROM comments WHERE parent_id=$parent_id"; $result = mysqli_query($conn, $sql); while ($row = mysqli_fetch_assoc($result)) { echo '<div style="margin-left: ' . ($level * 20) . 'px;">'; echo '<p>' . $row['content'] . '</p>'; echo '<small>' . $row['created_at'] . '</small>'; echo '<a href="#" onclick="showReplyForm(' . $row['id'] . ')">回复</a>'; echo '<div id="reply-form-' . $row['id'] . '" style="display: none;">'; echo '<form method="post" action="#">'; echo '<input type="hidden" name="parent_id" value="' . $row['id'] . '">'; echo '<input type="text" name="content">'; echo '<input type="submit" value="提交">'; echo '</form>'; echo '</div>'; showComments($row['id'], $level + 1); echo '</div>'; } } // 显示评论列表 while ($row = mysqli_fetch_assoc($result)) { echo '<div>'; echo '<p>' . $row['content'] . '</p>'; echo '<small>' . $row['created_at'] . '</small>'; echo '<a href="#" onclick="showReplyForm(' . $row['id'] . ')">回复</a>'; echo '<div id="reply-form-' . $row['id'] . '" style="display: none;">'; echo '<form method="post" action="#">'; echo '<input type="hidden" name="parent_id" value="' . $row['id'] . '">'; echo '<input type="text" name="content">'; echo '<input type="submit" value="提交">'; echo '</form>'; echo '</div>'; showComments($row['id'], 1); echo '</div>'; } ``` 需要注意的是,为了避免SQL注入攻击,需要使用参数化查询或预处理语句来处理用户提交的数据。另外,为了安全起见,还需要进行用户身份验证和数据过滤。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值