当前位置:编程学习 > > 正文

vue实现pc聊天页面(vue实现web在线聊天功能)

时间:2021-10-23 10:53:32类别:编程学习

vue实现pc聊天页面

vue实现web在线聊天功能

本文实例为大家分享了vue实现web在线聊天的具体代码,供大家参考,具体内容如下

最终实现的效果

vue实现pc聊天页面(vue实现web在线聊天功能)

实现过程

无限滚动窗体的实现之前已经介绍过,这里就不在赘述了,不清楚的可以通过文档前文的传送门进行查看。

实时在线聊天主要功能点

话不多说,直接上代码

后端返回数据格式

我觉得所有的设计和功能实现都是基于数据的基础上去实现的,所以咋们先来看一下后端返回的数据格式:

  • {
     "code": 200, // 响应编码
     "msg": "OK", // 响应消息
     "total": 1, 
     "sysTime": "2020-12-16 15:23:27", // 系统响应时间
     "data": [{
      "avatar": "",  // 用户头像
      "content": "{\"type\":\"txt\",\"msg\":\"你好!\"}", // 消息内容
      "isRead": 0, // 是否已读
      "isOneself": 0,  // 是否是自己发送的消息 0否,1是
      "msgId": 10, // 消息ID,用来去重
      "nickName": "碧海燕鱼", // 用户昵称
      "userCode": "202012162030202232" // 用户编码
     }]
    }
    
  • 这里需要说明的是,content字段返回的是一个json格式的字符串数据,content内容格式如下:

  • // 文本消息
    {
      "type": "txt",
      "msg":"你好" //消息内容
    }
    
  • // 图片消息
    {
      "type": "img",
      "url": "图片地址",
      "ext":.jpg" alt="vue实现pc聊天页面(vue实现web在线聊天功能)" border="0" />
    
  • // 视频消息
    {
      "type": 'video',
      "url": "http://nimtest.nos.netease.com/cbc500e8-e19c-4b0f-834b-c32d4dc1075e",
      "ext":"mp4",
      "width":360,    //宽
      "height":480,    //高
      "size": 388245
    }
    
  • // 地理位置消息
    {
      "type": "local",
      "address":"中国 浙江省 杭州市 网商路 599号",    //地理位置
      "longitude":120.1908686708565,        // 经度
      "latitude":30.18704515647036            // 纬度
    }
    
  • HTML代码

  • <template>
      <Modal title="在线沟通" v-model="chatVisible"
       draggable
       footer-hide
       :width="580" @on-cancel="cancel">
       <li class="chat">
         <li  class="chat-message-body" id ="chatform" @scroll="scroll"
          >
          <Spin v-if="loading">
            <Icon type="ios-loading" size=18 class="spin-icon-load"></Icon>
          </Spin>
            <li  dis-hover v-for="(item,index) in data"
             :key="index" class="message-card">
             <li :class="item.isOneself == 1?'message-row-right': 'message-row-left'">
               <img :src="item.avatar?item.avatar:defualtAvatar" 
                height="35" width="35" >
                <li class="message-content"> 
                  <li :style="item.isOneself == 1?'text-align:right;display: flex;flex-direction:row-reverse':''">
                    {{item.nickName}}
                    <span class="message-time">
                       {{item.createTime}}</span>
                    </li>
                  <li class="message-body">
                    {{item.content.msg}}
                    </li>
                 </li> 
              </li>
             </li>
          </li>
            <Input
            v-model="form.msg"
            type="textarea"
            style="margin:10px 0;"
            placeholder="主动一点,世界会更大!"
            :rows="4"
          />
         </li>
         <li class="footer-btn">
            <Button @click="cancel" type="text">取消</Button>
            <Button type="primary" @click="sendMsg">发送</Button>
          </li>
      </Modal>
    </template>
    
  • 注:自己发的信息和别人发的信息展示样式不一样,所以需要通过isOneself字段进行展示样式的区分。

    JavaScript代码

  • <script>
    import {listMsg,sendMsg } from "@/api/index";
    export default {
      name: "chat",
      props: {
        value: {
          type: Boolean,
          default: false
        }
      },
      data() {
        return {
          chatVisible:this.value,
          loading:false,
          defualtAvatar:require('../../assets/defult-avatar.svg'), // 后端没有返回头像默认头像,注意:需要用require请求方式才能动态访问本地文件
          data:[],
          distincData:[], // 消息去重数组
          offsetMax:0, // 最大偏移位,记录当前获取的最大id,往后的定时轮询数据时每次只获取比这个id大的数据
          offsetMin:0,  // 最小偏移位,记录当前获取的最小id,往上滑动时每次只获取比这小id大的数据
          searchForm:{ // 每次定时获取数据或首次加载数据提交的form表单数据
            pageNumber: 1,
            pageSize: 20
          },
          form:{ // 发送数据提交数据表单
            content:"",
            msg:""
          },
          timerSwitch:0 // 定时器开关,默认关闭
        };
      },
      methods: {
        init(){
          
        },
        loadMsg(){ // 窗体打开默认加载一页数据,窗体什么周期中值运行一次
          let that = this;
          this.searchForm.offsetMax = this.offsetMax;
          listMsg(this.searchForm).then(res=>{
            if (res.code == 200) {
              res.data.forEach(e => {
                // 标记最大偏移位
                if(that.offsetMax < e.msgId){
                    that.offsetMax = e.msgId;
                }
                e.content = JSON.parse(e.content);
                that.data.unshift(e)
                that.distincData.push(e.msgId);
                // 标记最大偏移位,后端返回数据是逆序,所以最后一条id最新
                that.offsetMin = e.msgId;
               });
              // 数据加载完成,滚动条滚动到窗体底部
              this.scrollToBottom();
            }
          });
           
            
        },
        show(){ // 打开窗体初始化数据
          // 初始化数据
          this.data =[];
          this.distincData =[];
          this.offsetMax = 0;
          this.offsetMin = 0;
          this.searchForm.pageNumber = 1;
          this.searchForm.pageSize = 20;
          this.form ={
            content:"",
            msg:""
          };
          this.loadMsg();
          this.chatVisible = true;
          // 开启定时器
          this.timerSwitch = 1;
          this.reloadData();
        },
        sendMsg(){ // 发送消息
          if(!this.form.msg){
             this.$Message.warning("不能发送空白信息");
            return;
          }
          let content = { // 封装消息体
            type:"txt",
            msg:this.form.msg
          }; 
          this.form.content = JSON.stri.jpg" alt="vue实现pc聊天页面(vue实现web在线聊天功能)" border="0" />
    
  • CSS代码

  • <style lang="less">
       .message {
            height: 350px;
        }
      .ivu-card-body {
        padding:5px;
      }
      .ivu-modal-body{
        padding: 0px 16px 16px  16px;
      }
      .chat-message-body {
       background-color:#F8F8F6;
       width:545px;
       height: 350px;
       overflow: auto;
      }
      .message-card {
       margin:5px;
      }
      .message-row-left {
       display: flex;
       flex-direction:row;
      }
      .message-row-right {
       display: flex;
       flex-direction:row-reverse;
      }
      .message-content {
        margin:-5px 5px 5px 5px;
        display: flex;
        flex-direction:column;
      }
      .message-body {
        border:1px solid #D9DAD9;
        padding:5px;
        border-radius:3px;
        background-color:#FFF;
      }
      .message-time {
        margin:0 5px;
        font-size:5px;
        color:#D9DAD9;
      }
      .footer-btn {
        float:right;
        margin-bottom: 5px;
      }
      .spin-icon-load {
        animation:ani-spin 1s linear infinite;
      }
      @keyframes ani-spin{
        form{transform: rotate(0deg);}
        50% {transform: rotate(180deg);}
        to  {transform: rotate(360deg);}
      }
    </style>
    
  • 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持开心学习网。

    标签:
    上一篇下一篇

    猜您喜欢

    热门推荐