美文网首页
评论插件

评论插件

作者: 七彩霞光_d533 | 来源:发表于2019-02-27 10:34 被阅读0次

    基于jquery 的评论小插件

    github项目地址:https://github.com/fancaixia/jquery-comment

    001.png
    案例思路:

    [后台建立两个表]

    • comment_list 评论表 id,userID,userName,articleID,content
    • reply_list 回复表 id,talkID,content,fromID,fromUser,toID,toUser

    [查询评论]

    • 后台获取 comment_list 表数据
    • 检索reply_list表中item.talkID == comment_list中 item.id, 并存入comment_list中对应item.child

    [发送评论]

    • 前台发送用户id,用户名称, 文章id, 评论内容到后台
    • 后台将评论存储到comment_list中

    [删除评论]

    • 前台发送此条评论ID到后台,
    • 后台reply_list判断 talkId == id 进行删除
    • 同时查询comment_list判断 id 相等的数据并进行删除

    [回复评论]

    • 前台发送评论id, 内容, fromID, fromUser, toID, toUser 到后台
    • 后台将消息存储到reply_list中

    [删除回复]

    • 前台发送此条回复ID到后台,
    • 后台reply_list判断对应 id 进行删除

    [前台判断]

    • 根据当前登录用户id判断评论或回复用户是否一致 (不可给自己评论)
    • 划过某条评论时判断是不是当前用户的评论,(只能删除自己的评论)

    代码结构

    comment_static

    config.js            接口文档
    common.js        封装 ajax 请求及提示信息
    index.html         主文件
    index.js              业务逻辑

    模拟多个用户可复制index.html,并修改index.js 中currentUserID和currentUserName

    comment_mysql_server
    app.js        主文件 连接mysql配置
    route

    activity_talk        后台逻辑处理

    项目启动

    1. cd / comment_mysql_server
    2. app.js 更改数据库连接信息
    3. npm / cnpm install
    4. npm run dev

    代码片段:

    server / route / activity_talk.js

    const express = require('express');
    const uuid = require('uuid')
    const route_talk = express.Router();
    
    route_talk.use((req,res,next)=>{
        
        //解决跨域请求
        res.header("Access-Control-Allow-Origin","*");
        res.header("Access-Control-Allow-Headers", "X-Requested-With,Origin,Content-Type,Accept");  
        res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
        next()
    
    })
    
    // 查询评论数据
    route_talk.post('/get',(req,res)=>{
        let articleID = req.body.articleID;
        let talkID = req.body.talkID;
        let replyCount = req.body.replyCount;   //查询评论对应回复的条数  默认3  查询所有时设置为10000
        req.pool.query(`SELECT * FROM comment_list WHERE articleID=${articleID}`,(err,data)=>{
            if(err){
                res.send({code:1,msg:"服务端错误"}).end();
            }else{
                //文章列表查询评论成功后  遍历数组  回复表根根talkID查 回复数据 
                
                function makePromise(item, index) {
                    return new Promise((resolve) => {
                        let newitem = JSON.parse(JSON.stringify(item));
                        //如果传入 talkID  那么此评论对应回复查询所有
                        if(talkID && talkID == newitem.id){
                            replyCount = 10000;
                        }else{
                            replyCount = 3;
                        }
                        
                        req.pool.query(`SELECT * FROM reply_list WHERE talkID="${newitem.id}" LIMIT 0,${replyCount}`,(err,replydata)=>{
                            if(err){
                                res.send({code:1,msg:"服务端错误"}).end();
                            }else{
                                //模拟查询用户表数据
                                newitem.img="./images/reply.jpg";
                                newitem.time = "2017-07-06  12:45";
                                newitem.child = JSON.parse(JSON.stringify(replydata));
    
                                //遍历回复数据  模拟查询用户表  添加用户信息
                                newitem.child.forEach((item,index) => {
                                    item.fromImg = './images/reply_01.jpg';   //模拟查询用户表数据
                                    item.time = "2017-07-06  12:45";
                                });
                            
    
                                req.pool.query(`SELECT COUNT(*) AS count FROM reply_list WHERE talkID="${newitem.id}"`,(err,num)=>{
                                    if(err){
                                        res.send({code:1,msg:"服务端错误"}).end();
                                    }else{
                                        newitem.replytotal = num[0].count;
                                        resolve(newitem)
            
                                    }
                                })
                        
    
                            }
                        })
    
                    });
                }
                
                
                Promise.all(data.map((v, k) => makePromise(v, k))).then(data => {
                    res.send({code:0,data,}).end();
                });
                
               
                
            }
        })
    })
    //添加评论  
    route_talk.post('/add',(req,res)=>{
    
        const uuid_str = uuid.v4().replace(/-/g,'');
        req.pool.query(`insert into comment_list (id,userID,userName,articleID,content) VALUES("${uuid_str}","${req.body.userID}","${req.body.userName}","${req.body.articleID}","${req.body.content}")`,(err,state)=>{
            if(err){
                res.send({code:1,msg:"添加失败"}).end();
            }else{
                //添加成功   返回评论数据
                res.send({code:0,msg:"添加成功"}).end();
            }
        })
    
    })
    //删除评论   首先删除评论对应回复  DELETE FROM reply_list WHERE talkID=""
    route_talk.post('/remove',(req,res)=>{
        req.pool.query(`delete from reply_list where talkID="${req.body.id}"`,(err,state)=>{
            if(err){
                res.send({code:1,msg:"删除回复失败"}).end();
            }else{
                req.pool.query(`delete from comment_list where id="${req.body.id}"`,(err,data)=>{
                    if(err){
                        res.send({code:1,msg:"删除评论失败"}).end();
                    }else{
                        res.send({code:0,msg:"ok"}).end();
                    }
                })
            }
        })
    
    })
    //添加回复
    route_talk.post('/addreply',(req,res)=>{
    
        const uuid_str = uuid.v4().replace(/-/g,'');
        req.pool.query(`insert into reply_list (id,talkID,content,fromID,fromUser,toID,toUser) VALUES("${uuid_str}","${req.body.talkID}","${req.body.content}","${req.body.fromID}","${req.body.fromUser}","${req.body.toID}","${req.body.toUser}")`,(err,state)=>{
            if(err){
                res.send({code:1,msg:"回复失败"}).end();
            }else{
                res.send({code:1,msg:"ok"}).end();
    
            }
        })
    
    })
    //删除回复
    route_talk.post('/removereply',(req,res)=>{
        req.pool.query(`delete from reply_list where id="${req.body.id}"`,(err,data)=>{
            if(err){
                res.send({code:1,msg:"删除回复失败"}).end();
            }else{
                res.send({code:1,msg:"删除回复成功"}).end();
            }
        })
    
    })
    
    module.exports = route_talk;
    

    static / index.js

    let replySize = 3;  //回复默认显示3条  当点击更多 则为评论相关回复total总数
    const replyCount = 3; //回复条数大于3  隐藏
    const currentUserID = '1549bd4753424d88a4f0d5839da33f96'; 
    let currentUserName = '小财神';
    // const currentUserID = '25b92f4e04d54ca5a159b46309255f7e';
    // let currentUserName = '小迷糊'; 
    
    
    let replyUser = '';   //回复人XXX
    let replyUserID = '';  //回复人ID
    let seeAlltalkID = '';   //点击查看按钮时  储存点击的评论ID  
    let articleID = '0'    // 假设此篇文章ID 为 0 (根据文章ID 请求对应评论数据)
    
    $('#current_user').html('当前用户:'+currentUserName)
    //初始化渲染评论数据
    getTalkData();
    //初始化渲染评论数据
    function getTalkData(id){
      let talkID = id || '';
    
      let data = {
        articleID,  
        talkID:talkID,
        replyCount:replyCount
      };
      commonfun.request(serverApi.getTalk,data,renderData,renderFail)
    }
    
    //获取数据成功回调
    function renderData(data){
          if(data.code != 0){
              tipObj.setErrmsg(data.msg,1);
              return;
          }
    
          let talkStr = '';  //整个评论信息
          let moreStr = '';
    
          data.data.forEach((talkitem,index)=>{
            //判断此评论是否有回复
            let replyStr = '';  //回复文本
            if(talkitem.child.length > 0){
              replyStr = '<div class="comment_reply">';
              talkitem.child.forEach((item,index)=>{
                    //渲染评论数据
                    replyStr += 
          '<div data-fromID='+item.fromID+' data-id='+item.id+' class="one_reply '+(index==talkitem.child.length-1?'one_reply_noborder':'')+'">'+
              '<div class="comment_people_info">'+
                  '<img class="fl_left" src="'+item.fromImg+'" alt="">'+
                  '<span class="first_reply fl_left"><span class="first_reply_aa">'+item.fromUser+'</span>'+
                    '<span class="first_reply_text"> 回复: </span>'+
                    
                  '<span class="first_reply_aa">'+item.toUser+'</span></span>'+
                  '<span class="date fl_right">'+item.time+'</span></div>'+
              '<div class="comment_people_content">'+
                  '<span class="fl_left">'+item.content+'</span>'+
                  
                  '<span data-userID='+item.fromID+' data-userName='+item.fromUser+' class=" reply_fn reply_btn fl_right">回复</span>'+
                  '<span id="reply_remove" class="reply_remove reply_btn fl_right reply_btn_cont none">删除</span>'+
                  '</div></div>'
              })
              moreStr = '<div class="comment_more '+(talkitem.replytotal>replyCount?'':'none')+'">'+
          '<span>剩余'+(seeAlltalkID== talkitem.id? talkitem.replytotal-replySize : talkitem.replytotal-replyCount)+'条评论</span>  <span id="see_reply" data-total='+talkitem.replytotal+' class="green see">'+(talkitem.replytotal-replySize == 0?'收起':"点击查看")+'</span></div>';
              replyStr += moreStr+'</div>'
            }
    
              talkStr += '<div data-id='+talkitem.id+' data-userID='+talkitem.userID+' class="comment">'+
          '<div class="comment_people">'+
            '<div class="comment_people_titleBox">'+
              '<div class="comment_people_info">'+
                  '<img class="fl_left" src="'+talkitem.img+'" alt="">'+
                  '<span class="first_reply fl_left">'+talkitem.userName+'</span>'+
                  '<span class="date fl_left">'+talkitem.time+'</span>'+
                  '<span data-userID='+talkitem.userID+' data-userName='+talkitem.userName+' class="reply_fn fl_right reply_btn">回复</span></div>'+
              '<div class="comment_people_content">'+
              '<span class="fl_left">'+talkitem.content+'</span>'+
                  '<span id="talk_remove" class="reply_btn fl_right none reply_btn_cont">删除</span>'+
                  '</div></div>'+replyStr+'</div></div>';
                
          })
          $('#talk_content').html(talkStr);
    
        }
    // 渲染数据失败
    function renderFail(err){
      tipObj.setErrmsg("请求失败,请重试",1);
    }
    
    //对文章评论   ++++++++++++++++++++++
    $('#textareaBox').on('focus',function () {
       $('#cancelbtn').removeClass('none')
    })
    //发布评论
    $('#talk_submit').on('click',function(){
      //提交请求
      let content = $.trim($('#textareaBox').val())
      if(content.length > 0){
    
        let data = {
          userID:currentUserID,
          userName:currentUserName,
          articleID,
          content,
        };
        commonfun.request(serverApi.addTalk,data,addTalkfun,addTalkFail)
    
      }else{
        //提示层
        tipObj.setErrmsg('请输入评论内容',1);
      }
    })
    //添加评论成功
    function addTalkfun(data){
      $('#textareaBox').val('')
      $('#cancelbtn').addClass('none')
      getTalkData();
    }
    //添加评论失败
    function addTalkFail(err){
      tipObj.setErrmsg("请求失败,请重试",1);
    }
    //发布评论回车事件处理
    $('#textareaBox').keypress(function(e){ 
      if(e.ctrlKey && e.which == 13 || e.which == 10 || e.which == 13) { 
        $('#talk_submit').trigger('click')
        e.preventDefault(); //屏蔽enter对系统作用。按后增加\r\n等换行
      } 
    });
    
    //取消评论
    $('#cancelbtn').on('click',function(){
      $('#textareaBox').val('')
      $(this).addClass('none')
    })
    
    //滑过评论控件  显示删除按钮
    $('#talk_content').on('mouseover','.comment_people_titleBox ',function(){
      if(currentUserID == $(this).parents('.comment').attr('data-userID')){
       
        $(this).find('#talk_remove').removeClass('none')
      }
    });
    
    //移出评论控件  隐藏删除按钮
    $('#talk_content').on('mouseout','.comment_people_titleBox',function(){
      $(this).find('#talk_remove').addClass('none')
    })
    
    //删除评论
    $('#talk_content').on('click','#talk_remove',function(){
      let id = $(this).parents('.comment').attr('data-id')
    
      let data = {
        id,
      }
      commonfun.request(serverApi.removeTalk,data,removeTalkfun,removeTalkFail)
    })
    
    //删除评论成功回调
    function removeTalkfun(){
        //初始化查询评论数据
        getTalkData();
    }
    //删除评论失败回调
    function removeTalkFail(){
      tipObj.setErrmsg("请求失败,请重试",1);
    }
    
    //滑过回复控件  显示删除
    $('#talk_content').on('mouseover','.one_reply ',function(){
        if(currentUserID == $(this).attr('data-fromid')){
          $(this).find('#reply_remove').removeClass('none')
        }
    });
    //移出回复控件  隐藏删除
    $('#talk_content').on('mouseout','.one_reply',function(){
        $(this).find('#reply_remove').addClass('none')
    })
    //点击回复 
    // 判断是否对自己回复  对自己回复则 return
    // 判断是否存在评论框  不存在创建 同时设置文本域值 @xxxx ++++++++++++++++++++++
    $('#talk_content').on('click','.reply_fn',function(){
    
      if($(this).attr('data-userid') == currentUserID){
        return;
      }
    
      let areachild = $('#talk_content').find('.talk_box_s')
    
      if($(areachild).length == 0){
        let textBox = setchildTextarea();
        $(this).parents('.comment').append(textBox)
    
      }else{
    
        $('#talk_content').find('.talk_box_s').remove();
        let textBox = setchildTextarea();
        $(this).parents('.comment').append(textBox)
      }
    
      let val = $(this).attr('data-username');
      $('#talk_content').find('#textareaBox_s').val('@'+val+' ')
    
      replyUser = val;
      replyUserID = $(this).attr('data-userid');
    
    })
    //回复发布   
    $('#talk_content').on('click','#talk_submit_s',function(){
    
      // 替换 @ xxx 为空
      let content = ($.trim($('#textareaBox_s').val())).replace((replyUser),'')
      content = content.replace('@','')
    
      let talkID = $(this).parents('.comment').attr('data-id')
    
      if(content.length > 0){
    
        let data = {
            talkID,
            content,
            fromID:currentUserID,
            fromUser:currentUserName,
            toID:replyUserID,
            toUser:replyUser,
        }
        commonfun.request(serverApi.addreply,data,replyfun,replyfail)
    
      }else{
        tipObj.setErrmsg('请输入评论内容',1);
      }
    
    })
    //回复发布成功
    function replyfun(){
      getTalkData();
      $(this).parents('.talk_box_s').remove();
    }
    //回复发布失败
    function replyfail(){
      tipObj.setErrmsg('请求失败,请重试',1)
    }
    
    //回复发布  回车事件处理
    $('#talk_content').keypress('#textareaBox_s',function(e){ 
      if(e.ctrlKey && e.which == 13 || e.which == 10 || e.which == 13) { 
        $('#talk_content').find('#talk_submit_s').trigger('click')
        e.preventDefault();     //屏蔽enter对系统作用。按后增加\r\n等换行
      } 
    });
    
    //删除回复
    $('#talk_content').on('click','#reply_remove',function(){
    
      let id = $(this).parents('.one_reply').attr('data-id')
      let data = {
        id:id
      }
      commonfun.request(serverApi.removereply,data,removeReplyfun,removeReplyfail)
    })
    
    //删除回复成功
    function removeReplyfun(){
      //初始化查询评论数据
      getTalkData();
    }
    //删除回复失败
    function removeReplyfail(){
      tipObj.setErrmsg('请求失败,请重试',1)
    }
    
    //点击查看  获取评论并且根据talkID获取全部评论 
    $('#talk_content').on('click','#see_reply',function(){
    
      seeAlltalkID = $(this).parents('.comment').attr('data-id')
      let replyTotal = $(this).attr('data-total') 
      if(replySize == replyTotal){
        replySize = replyCount;
        getTalkData();
      }else{
        replySize = replyTotal;
        //初始化查询评论数据
        getTalkData(seeAlltalkID);
      }
      
    
    })
    
    //回复取消
    $('#talk_content').on('click','#cancelbtn_s',function(){
      $(this).parents('.talk_box_s').remove();
    })
    
    //回复评论框
    function setchildTextarea(){
      return '<div class="talk_box talk_box_s">'+
      '<textarea name="talk" id="textareaBox_s" placeholder="写下你的评论..."></textarea>'+
      '<button id="talk_submit_s">发布</button><button id="cancelbtn_s" class="cancelbtn">取消</button></div>'
    }
    

    相关文章

      网友评论

          本文标题:评论插件

          本文链接:https://www.haomeiwen.com/subject/qccxuqtx.html