博文评论与在线消息提示[开发日志-SpringBoot+Vue]

Posted Huterox

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了博文评论与在线消息提示[开发日志-SpringBoot+Vue]相关的知识,希望对你有一定的参考价值。

文章目录

前言

没想到就两个礼拜左右没有碰一起的项目代码,就忘得差不多了。还熟悉了一下代码,跪了。

okey~接下来的话,来看到今天实现的效果:

每次就是这样的一个评论区

并且在评论成功之后,还要发送消息给博主。
然后如果博主在线的话,那么就要实时进行一个推送,告诉博主,然后博主可以在消息的一个页面看到这个消息:

整个过程的话,和一个正常的博文社区,例如CSDN,掘金,思否,知乎是类似的。

然后我们要做的就是实现这个东西。

要点

那么实现这个功能的话,大概由一下几个点需要明确一下:

  1. 评论的数据格式
  2. 评论的过滤审核
  3. 消息的转发与接收
  4. 前端页面的功能实现
    1. 评论展示
    2. 评论回复
    3. 消息展示与通知显示

那么在这里的话,由于篇幅问题,加上这个消息推送服务并不一定是需要的,并且消息的实现也稍微麻烦一点儿,因此本文消息部分的话会缩略一下。重点是咱们的这个评论的一个实现。

评论结构

OKey,那么在开始之前的话,我们也是需要去确定一下这个评论的数据结构的,这个结构的话是这样的:


      comments:[
        
          name:'Huterox',
          id:19870621,
          commentid: 777,
          headImg:'https://ae01.alicdn.com/kf/Hd60a3f7c06fd47ae85624badd32ce54dv.jpg',
          comment:'Huterox is best',
          time:'2022年9月16日 18:43',
          inputShow:false,
          reply:[
            
              from:'Huterox03',
              fromId:19891221,
              replyid: 666,
              fromHeadImg:'https://ae01.alicdn.com/kf/H94c78935ffa64e7e977544d19ecebf06L.jpg',
              to:'Huterox',
              toId:19870621,
              comment:'66666666666666',
              time:'2022年9月26日 20:43',
              inputShow:false
            ,
          ]
        
      ]

是的这里的话,我将这个评论部分拆分为两个部分,就是图中这样的两个部分:

那么在我们的数据库里面的话也是这样设计的:

这里说明一下的就是 blogs_com_coment 这个表其实就是回复的那个表。没办法语文没学好,原来评论的评论可以叫做回复(giao)。

okey,那么这个的话就是我们大概的一个数据结构的样子。

获取评论

okey,我们按照功能来开始进行一个简要的分析和概述。

评论组件

那么在开始之前的话,我们先来看到整个评论组件的完整代码。是的这里的话还没有去做封装,主要是方便我进行一个博文的编写,同时,也方便给别人用,如果你的流程和我的类似,你直接CV然后改数据结构即可。当然还有个原因是方便我调试,开发阶段。

那么我们完整的代码是这样的:

<template>

  <div>
    <div v-if="!isLoginFlag" style="height: 300px;width: 100%">
      <el-empty image="/static/image/go_login.gif"  :description="badTips"></el-empty>
    </div>

    <div v-if="isLoginFlag">
          <div v-clickoutside="hideReplyBtn" @click="inputFocus" class="my-reply">
              <el-avatar class="header-img" :size="40" :src="myHeader"></el-avatar>
              <div class="reply-info" >
                  <div
                          tabindex="0"
                          contenteditable="true"
                          id="replyInput"
                          spellcheck="false"
                          placeholder="输入评论..."
                          class="reply-input"
                          @focus="showReplyBtn"
                          @input="onDivInput($event)"
                  >
                  </div>
              </div>
              <div class="reply-btn-box" v-show="btnShow">
                  <el-button class="reply-btn" size="medium" @click="sendComment" type="primary">发表评论</el-button>
              </div>
          </div>
          <div v-for="(item,i) in comments" :key="i" class="author-title reply-father">
              <el-avatar
                class="header-img" :size="40" :src="item.headImg"
                @click="gotoSpace(item.id)"
              ></el-avatar>
              <div class="author-info">
                  <span class="author-name">item.name</span>
                  <span class="author-time">item.time</span>
              </div>
              <div class="icon-btn">
                  <span @click="showReplyInput(i,item.name,item.id)">
                    <i style="font-size: 6px" class="iconfont el-icon-s-comment">回复</i>
                  </span>
              </div>
              <div class="talk-box">
                  <p>
                      <span class="reply">item.comment</span>
                  </p>
              </div>
              <div class="reply-box">
                  <div v-for="(reply,j) in item.reply" :key="j" class="author-title">
                      <el-avatar class="header-img" :size="40" :src="reply.fromHeadImg"
                                 @click="gotoSpace(reply.fromId)"
                      ></el-avatar>
                      <div class="author-info">
                          <span class="author-name">reply.from</span>
                          <span class="author-time">reply.time</span>
                      </div>
                      <div class="icon-btn">
                          <span @click="showReplyInput(i,reply.from,reply.id)">
                            <i style="font-size: 6px" class="iconfont el-icon-s-comment">回复</i>
                          </span>
                      </div>
                      <div class="talk-box">
                          <p>
                              <span style="font-size: 8px">@ reply.to:</span>
                              <span class="reply">reply.comment</span>
                          </p>
                      </div>
                      <div class="reply-box">

                      </div>
                  </div>
              </div>
              <div  v-show="_inputShow(i)" class="my-reply my-comment-reply">
                  <el-avatar class="header-img" :size="40" :src="myHeader"></el-avatar>
                  <div class="reply-info" >
                      <div tabindex="0" contenteditable="true" spellcheck="false" placeholder="输入回复..."   @input="onDivInput($event)"  class="reply-input reply-comment-input"></div>
                  </div>
                  <div class=" reply-btn-box">
                      <el-button class="reply-btn" size="medium" @click="sendCommentReply(i,j)" type="primary">点击回复</el-button>
                  </div>
              </div>
          </div>
          <div>
            <el-pagination
              background
              layout="total, prev, pager, next"
              :current-page="page"
              page-size=5
              @current-change="handleCurrentChange"
              :total=total>
            </el-pagination>
          </div>
      </div>
  </div>
</template>

<script>
const clickoutside = 
  // 初始化指令
  bind(el, binding, vnode) 
    function documentHandler(e) 
      // 这里判断点击的元素是否是本身,是本身,则返回
      if (el.contains(e.target)) 
        return false;
      
      // 判断指令中是否绑定了函数
      if (binding.expression) 
        // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
        binding.value(e);
      
    
    // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
    el.vueClickOutside = documentHandler;
    document.addEventListener('click', documentHandler);
  ,
  update() ,
  unbind(el, binding) 
    // 解除事件监听
    document.removeEventListener('click', el.vueClickOutside);
    delete el.vueClickOutside;
  ,
;
export default 
  name:'comment_article',
  // 接受父组件的值
  props: 
    blogid: String,
    myuserid: String,
    isLoginFlag: String,
    blogTitle: String,
    blogUserid: String,
    loginToken: String,
    required: true
  ,


  data()
    return
      total: 10,
      page: 1,
      limit: 5,
      badTips: "登录后才能查看和发表评论呦~",
      btnShow: false,
      index:'0',
      replyComment:'',
      myName:'Lana Del Rey',
      myHeader:'https://ae01.alicdn.com/kf/Hd60a3f7c06fd47ae85624badd32ce54dv.jpg',
      myId:19870621,
      to:'',
      toId:-1,

      comments:[
      ]
    
  ,
  directives: clickoutside,

  created() 
    this.getMyInfo(this.myuserid);
    this.getComments();
  ,

  methods: 
    gotoSpace(userid)
      this.$router.push(path: "/userinfo",query:'userid':userid);
    ,


    handleCurrentChange(val)
      //换页
      this.page = val;
      this.getComments();
    ,

    getComments()
      //得到当前博文的评论
      this.axios(
        url: "/blog/blog/comment/getCommentList",
        method: 'post',
        headers: 
          "userid": this.myuserid,
          "loginType": "PcType",
          "loginToken": this.loginToken,
        ,
        data: 
          'userid': this.myuserid,
          "blogid": this.blogid,
          'page': this.page,
          'limit': this.limit
        
      ).then((res) => 
        res = res.data;
        if(res.code === 0) 
          this.comments = res.page.list;
          this.total = res.page.totalCount;
          this.page = res.page.currPage;

        else 
          this.isLoginFlag=false;
          this.badTips = res.msg;
        
      ).catch(reason => 
        this.isLoginFlag=false;
        this.badTips = "当前访问异常";
      )
    ,


    sendReply(comment,i,j)
      let commentid = null;
      let commentUserid = null;
      let commentNickname = null;
      let commentUserimg = null;
      if(j)
        commentid = comment[j].replyid;
        commentUserid = comment[j].fromId;
        commentNickname = comment[j].from;
        commentUserimg = comment[j].fromHeadImg;
      else 
        commentid = comment.commentid;
        commentUserid = comment.id;
        commentNickname = comment.name;
        commentUserimg = comment.headImg;
      
      //发送回复
      this.axios(
        url: "/blog/blog/comment/upReply",
        method: 嘿从零开始基于SpringBoot 打造在线聊天室(4.4W字最长博文)

6.29个人日志

集博文,项目,手册,在线工具,在线图书,在线代码,开发平台的网站

FastAPI(七十八)实战开发《在线课程学习系统》接口开发-- 评论

Node JS mongoose 创建博文评论系统

第三百七十六节,Django+Xadmin打造上线标准的在线教育平台—创建用户操作app,在models.py文件生成5张表,用户咨询表课程评论表用户收藏表用户消息表用户学习表