" />

小言_互联网的博客

vue+elementUI 集成融云 实现IM即时通讯

727人阅读  评论(0)

这几天有个需求,做一个im,有app端和web端,能发文字、语音、图片、视频、视频、emoji,能看聊天记录,最终敲定融云。但融云没有现成的web端的UI,给的web端demo对我这个纯后端来说,看不太懂,所以准备自己写个简单点的,代码如下,token需要从后端获取,比较简单所以就不贴了,只贴一下效果图和前端代码。

<template>
  <div class="whole-wrapper">
    <!-- 左边的聊天列表 -->
    <div class="left_whole_wrapper">
      <!-- 搜索框 -->
      <div class="search">
        <el-input placeholder="搜索联系人" suffix-icon="el-icon-search" v-model="find" @input="searchChange"></el-input>
      </div>
      <!-- 聊天列表 -->
      <div class="left_wrapper" style="overflow-y:auto;" v-if="chatList">
        <div class="left-item" v-for="(item,index) in chatList" :key="index" @click="clickItem(item,index)" :class="{active:targetId==item.targetId}">
          <div class="left-item-left">
            <div class="left-item-head"><img :src="item.head"></div>
            <div class="left-item-info">
              <div class="left-item-info_title">{
  {item.name}}</div>
              <div class="left-item-info_content">{
  {item.info}}</div>
            </div>
          </div>
          <div class="left-item-time">
            <div class="left-item-time-time">{
  {item.time}}</div>
            <div class="left-item-time-number" v-if="item.number">{
  {item.number}}</div>
          </div>
        </div>
      </div>
    </div>
    <!-- 中间的对话-->
    <div class="center_whole_wrapper" v-if="dialogueInfo">
      <div class="center_wrapper">
        <!-- 上面的表头 -->
        <div class="center_wrapper_top">
          <div class="center_wrapper_top_name">{
  {dialogueInfo.name}}</div>
          <div class="center_wrapper_top_number">{
  {dialogueInfo.phone}}</div>
        </div>
        <!-- 中间的聊天框,尝试模拟数据 -->
        <div class="center_wrapper_center" style="overflow-y:auto;" ref="dialogue_box">
          <div class="item loading">{
  {loadText}}<span>{
  {"第" + pageNum + "页"}}</span></div>
          <div v-for="(item,index) in dialogueInfo.dialogueList" :key="index" :class="item.other?center_wrapper_center_item:center_wrapper_center_item_reserve">
            <div class="left-item-head"><img :src="item.head"></div>
            <!-- 文字 -->
            <div class="center-item-info_wrapper" v-if="item.text">
              <div class="center-item-tip">
                <div class="center-item-info">{
  {item.text}}</div>
                <div class="error-tip" v-if="item.send"><img src="../../../public/img/bg/error.png"></div>
              </div>
              <div class="center-item-time">{
  {item.date}}</div>
            </div>
            <!-- 图片 -->
            <div class="center-item-info_wrapper" v-if="item.img">
              <div class="center-item-tip">
                <div class="center-item-info_img">
                  <el-image :src="item.img" :preview-src-list="item.srcList" :fit="contain" v-loading="item.loading">
                  </el-image>
                </div>
                <div class="error-tip" v-if="item.send"><img src="../../../public/img/bg/error.png"></div>
              </div>
              <div class="center-item-time">{
  {item.date}}</div>
            </div>
            <!-- 音频 -->
            <div class="center-item-info_wrapper" v-if="item.audio">
              <div class="center-item-tip">
                <audio :src="item.audio" controls></audio>
                <div class="error-tip" v-if="item.send"><img src="../../../public/img/bg/error.png"></div>
              </div>
              <div class="center-item-time">{
  {item.date}}</div>
            </div>
            <!-- 视频 -->
            <div class="center-item-info_wrapper" v-if="item.video">
              <div class="center-item-tip">
                <video :src="item.video" controls></video>
                <div class="error-tip" v-if="item.send"><img src="../../../public/img/bg/error.png"></div>
              </div><strong></strong>
              <div class="center-item-time">{
  {item.date}}</div>
            </div>
          </div>
        </div>
        <!-- 下面的输入框,发送 -->
        <div class="center_wrapper_right">
          <div class="icon-list">
            <!-- 表情 -->
            <div class="icon-item" title="表情">
              <el-popover placement="top" width="450" trigger="click">
                <div style="width: 100%;height: 280px;display: flex;flex-wrap: wrap;overflow-y:auto;">
                  <div class="emoji_icon" style="width: 5%;padding: 10px;" v-for="(item,index) in emojiList" :key="index"
                    @click="clickEmoji(item.emoji)">{
  {item.emoji}}
                  </div>
                </div>
                <el-button slot="reference" style="border: none;padding:0;"><img class="icon-item-img" src="../../../public/img/bg/emoji.png"></el-button>
              </el-popover>
            </div>
            <!-- 上传文件 -->
            <div class="icon-item">
              <el-upload class="avatar-uploader" action="/api/blade-app/filemgr/upload" :show-file-list="false"
                :before-upload="beforeAvatarUpload" :on-success="handleAvatarSuccess">
                <div class="icon-item" title="发送文件"><img class="icon-item-img" src="../../../public/img/bg/photo.png"></div>
              </el-upload>
            </div>
            <!-- 聊天记录 -->
            <div class="icon-item" title="聊天记录" @click="clickHistory"><img class="icon-item-img" src="../../../public/img/bg/record.png"></div>
            <!-- 模拟消息提醒弹框 -->
            <!-- <el-button
              plain
              @click="notifyByOrder">
              使用 HTML 片段
            </el-button> -->
          </div>
          <el-input type="textarea" :rows="2" placeholder="请输入内容" v-model="textarea" @keyup.enter.native="sendTextarea"></el-input>
          <el-button type="primary" @click="sendTextarea">发送</el-button>
        </div>
      </div>
    </div>

    <!-- 右边的聊天记录 -->
    <div class="center_whole_wrapper right_whole_wrapper">
      <div class="center_wrapper right_wrapper" v-if="showHistory">
        <div class="center_wrapper_center right_wrapper_center" style="overflow-y:auto;" ref="dialogue_record">
          <div class="item loading">{
  {loadText1}}<span>{
  {"第" + pageNum1 + "页"}}</span></div>
          <div v-for="(item,index) in dialogueInfo.dialogueList" :key="index" :class="isOther?center_wrapper_center_item:center_wrapper_center_item_reserve">
            <div class="left-item-head"><img :src="item.head"></div>
            <!-- 文字 -->
            <div class="center-item-info_wrapper" v-if="item.text">
              <div class="center-item-name">{
  {item.name}}</div>
              <div class="center-item-info">{
  {item.text}}</div>
              <div class="center-item-time">{
  {item.date}}</div>
            </div>
            <!-- 图片 -->
            <div class="center-item-info_wrapper" v-if="item.img">
              <div class="center-item-name">{
  {item.name}}</div>
              <div class="center-item-info_img">
                <el-image :src="item.img" :preview-src-list="item.srcList" :fit="contain">
                </el-image>
              </div>
              <div class="center-item-time">{
  {item.date}}</div>
            </div>
            <!-- 音频 -->
            <div class="center-item-info_wrapper" v-if="item.audio">
              <div class="center-item-name">{
  {item.name}}</div>
              <audio :src="item.audio" controls></audio>
              <div class="center-item-time">{
  {item.date}}</div>
            </div>
            <!-- 视频 -->
            <div class="center-item-info_wrapper" v-if="item.video">
              <div class="center-item-name">{
  {item.name}}</div>
              <video :src="item.video" controls></video>
              <div class="center-item-time">{
  {item.date}}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  import {
    
    getToken,
    getChatList
  } from "@/api/app/chat";
  import {
    
    dateFormat
  } from "@/util/date.js";

  var RongIMLib = window.RongIMLib;
  var RongIMClient = RongIMLib.RongIMClient;
  var RongIMEmoji = RongIMLib.RongIMEmoji;
  export default {
    
    data() {
    
      return {
    
        chatList: [
          // {
    
          //   "targetId": "1123598821738675201",
          //   "head": "https://gitee.com/uploads/61/632261_smallweigit.jpg",
          //   "name": "济南亨达通汽修厂1",
          //   "info": "转账了,麻烦下午尽快发货。转账了,麻烦下午尽快发货。转账了,麻烦下午尽快发货。",
          //   "time": "17:45",
          //   "phone": "18888888888",
          //   "number": "3"
          // }
        ],
        //存储条件查询时 原来的数组
        findList: [],
        // 搜索联系人
        find: '',
        // 发送文字
        textarea: '',
        // 模拟对话
        dialogueInfo: {
    
          index: 0,
          hasMsg: true,
          targetId: "", //对方的id
          name: "", //对方的名字
          phone: "", //对方的手机号
          head: "https://gitee.com/uploads/61/632261_smallweigit.jpg", //对方的头像
          dialogueList: [
            //   {
    
            //   // 判断是对方
            //   other: true,
            //   head: "https://gitee.com/uploads/61/632261_smallweigit.jpg",
            //   text: "在吗?我发询价了(右后减震器、左后减震器防尘套)需要原厂件请尽快报价。",
            //   // img: "http://124.128.226.225:8083/upload/1301812392719626241.png",
            //   // audio: "https://www.w3school.com.cn/i/horse.ogg",
            //   // video: "https://www.w3school.com.cn/i/movie.ogg",
            //   date: "2019-07-17 9:25:15",
            //   send: false,
            //   name: "济南亨达通汽修厂1"
            // },
          ],
        },
        // 右边的聊天记录,用于判断是对方说的,ture,选择样式1
        isOther: true,
        center_wrapper_center_item: "center_wrapper_center_item",
        center_wrapper_center_item_reserve: "center_wrapper_center_item_reserve",
        // 判断是否显示聊天记录
        showHistory: false,
        // 点击的子项
        targetId: "",
        //我的targetId
        mytargetId: "",
        //我的头像
        myhead: '',
        //我的名字
        myname: '',
        // 上传文件
        fileList: [],
        imageUrl: '',
        // 新增上滚方法
        scrollHeight: 0,
        list: [],
        loadText: "加载中...",
        pageNum: 1,
        loadText1: "加载中...",
        pageNum1: 1,
        // 模拟图片放大
        url: 'http://gudian-qpc.oss-cn-hangzhou.aliyuncs.com/2020/1329338563854811138.png',
        srcList: [
          'http://gudian-qpc.oss-cn-hangzhou.aliyuncs.com/2020/1329338563854811138.png',
        ],
        loading: false,
        // 表情包列表
        emojiList: []
      }
    },
    created() {
    
      this.loadComments();
      getToken().then(res => {
    
        var appkey = 'vnroth0kvb2mo'
        var token = res.data.data;
        this.init(appkey, token)
        // 默认是当前对话
        this.targetId = this.dialogueInfo.targetId
      });
      // this.notifyByOrder();
    },
    // 将滚动条定位到底部
    updated() {
    
      // 中间的聊天框
      const dialogue_box = this.$refs.dialogue_box;
      dialogue_box.scrollTop = dialogue_box.scrollHeight;
      // 右边的聊天记录
      if (this.$refs.dialogue_record) {
    
        const dialogue_record = this.$refs.dialogue_record;
        dialogue_record.scrollTop = dialogue_record.scrollHeight;
        this.handleRightScroll();
      }
    },
    mounted() {
    
      this.handleCenterScroll();
    },
    methods: {
    
      //初始化个人信息
      loadComments() {
    
        var info = JSON.parse(localStorage.getItem("saber-userInfo"));
        this.myhead = info.content.avatar;
        this.myname = info.content.nick_name;
      },

      //初始化链接方法
      init: function(appkey, token) {
    
        var _this = this;
        var params = {
    
          appkey: appkey,
          token: token
        }
        RongIMEmoji.init();
        this.emojiList = RongIMLib.RongIMEmoji.list;
        RongIMClient.init(appkey, null, params);
        RongIMClient.setConnectionStatusListener({
    
          onChanged: function(status) {
    
            switch (status) {
    
              case RongIMLib.ConnectionStatus['CONNECTED']:
              case 0:
                console.log('连接成功')
                _this.$store.commit("SET_LINK_STATE", 1);
                break
              case RongIMLib.ConnectionStatus['CONNECTING']:
              case 1:
                console.log('连接中')
                break
              case RongIMLib.ConnectionStatus['DISCONNECTED']:
              case 2:
                console.log('当前用户主动断开链接')
                break
              case RongIMLib.ConnectionStatus['NETWORK_UNAVAILABLE']:
              case 3:
                console.log('网络不可用')
                break
              case RongIMLib.ConnectionStatus['CONNECTION_CLOSED']:
              case 4:
                console.log('未知原因,连接关闭')
                break
              case RongIMLib.ConnectionStatus['KICKED_OFFLINE_BY_OTHER_CLIENT']:
              case 6:
                console.log('用户账户在其他设备登录,本机被踢掉线')
                break
              case RongIMLib.ConnectionStatus['DOMAIN_INCORRECT']:
              case 12:
                console.log('当前运行域名错误,请检查安全域名配置')
                break
            }
          }
        })
        RongIMClient.setOnReceiveMessageListener({
    
          // 接收到的消息
          onReceived: function(message) {
    
            // 判断消息类型
            switch (message.messageType) {
    
              case RongIMClient.MessageType.TextMessage:
                _this.handleGetTxt(message);
                break;
              case RongIMClient.MessageType.ImageMessage:
                _this.handleGetImg(message);
                break;
              case RongIMClient.MessageType.VoiceMessage:
                _this.handleGetVoice(message);
                break;
            }
          }
        })
        RongIMClient.connect(token, {
    
          onSuccess: function(userId) {
    
            console.log('链接成功,id:' + userId)
            _this.mytargetId = userId
            _this.getChatList(true);
          },
          onTokenIncorrect: function() {
    
            console.log('token无效')
          },
          onError: function(errorCode) {
    
            switch (errorCode) {
    
              case RongIMLib.ErrorCode.TIMEOUT:
                console.log('超时')
                break;
              case RongIMLib.ConnectionState.UNACCEPTABLE_PAROTOCOL_VERSION:
                console.log('不可接受的协议版本')
                break;
              case RongIMLib.ConnectionState.IDENTIFIER_REJECTED:
                console.log('appkey不正确')
                break;
              case RongIMLib.ConnectionState.SERVER_UNAVAILABLE:
                console.log('服务器不可用')
                break;
            }
          }
        }, null)
      },

      //处理接收到的文字消息
      handleGetTxt: function(message) {
    
        var info = {
    
          text: RongIMEmoji.symbolToEmoji(message.content.content),
          date: dateFormat(new Date(message.sentTime), 'yyyy-MM-dd hh:mm:ss'),
          send: false
        }
        if (message.senderUserId == this.mytargetId) {
    
          //我发出去的(比如app端发出去的,pc端会收到)
          info.other = false;
          info.head = this.myhead
          info.name = this.myname
          this.chatList[this.dialogueInfo.index].info = RongIMEmoji.symbolToEmoji(message.content.content);
          this.dialogueInfo.dialogueList.push(info)
        } else if (message.senderUserId == this.dialogueInfo.targetId) {
    
          //对方发出去的
          info.other = true;
          info.head = this.dialogueInfo.head
          info.name = this.dialogueInfo.name
          this.chatList[this.dialogueInfo.index].info = RongIMEmoji.symbolToEmoji(message.content.content);
          this.dialogueInfo.dialogueList.push(info)
        } else {
    
          //聊天列表其他人发出去的(不是现在聊天的人)
          var flag = false;
          for (var i = 0; i < this.chatList.length; i++) {
    
            if (this.chatList[i].targetId == message.senderUserId) {
    
              flag = true;
              this.chatList[i].info = RongIMEmoji.symbolToEmoji(message.content.content);
              if (this.chatList[i].number == '') {
    
                this.chatList[i].number = '1'
              } else {
    
                this.chatList[i].number = (parseInt(this.chatList[i].number) + 1).toString();
              }
              break;
            }
          }
          if (!flag) {
    
            this.getChatList(false)
          }
        }
        // console.log('新消息 ' + message.targetId + ':' + JSON.stringify(message))
      },

      //处理图片方法
      handleGetImg: function(message) {
    
        var info = {
    
          srcList: [
            message.content.imageUri
          ],
          img: message.content.imageUri,
          date: dateFormat(new Date(message.sentTime), 'yyyy-MM-dd hh:mm:ss'),
          send: false
        }
        if (message.senderUserId == this.mytargetId) {
    
          //我发出去的(比如app端发出去的,pc端会收到)
          info.other = false;
          info.head = this.myhead
          info.name = this.myname
          this.chatList[this.dialogueInfo.index].info = '[图片]';
          this.dialogueInfo.dialogueList.push(info)
        } else if (message.senderUserId == this.dialogueInfo.targetId) {
    
          //对方发出去的
          info.other = true;
          info.head = this.dialogueInfo.head
          info.name = this.dialogueInfo.name
          this.chatList[this.dialogueInfo.index].info = '[图片]';
          this.dialogueInfo.dialogueList.push(info)
        } else {
    
          //聊天列表其他人发出去的(不是现在聊天的人)
          var flag = false;
          for (var i = 0; i < this.chatList.length; i++) {
    
            if (this.chatList[i].targetId == message.senderUserId) {
    
              flag = true;
              this.chatList[i].info = '[图片]';
              if (this.chatList[i].number == '') {
    
                this.chatList[i].number = '1'
              } else {
    
                this.chatList[i].number = (parseInt(this.chatList[i].number) + 1).toString();
              }
              break;
            }
          }
          if (!flag) {
    
            this.getChatList(false)
          }
        }
      },

      //处理语音方法
      handleGetVoice: function(message) {
    
        var info = {
    
          video: message.content.remoteUrl,
          date: dateFormat(new Date(message.sentTime), 'yyyy-MM-dd hh:mm:ss'),
          send: false
        }
        if (message.senderUserId == this.mytargetId) {
    
          //我发出去的(比如app端发出去的,pc端会收到)
          info.other = false;
          info.head = this.myhead
          info.name = this.myname
          this.chatList[this.dialogueInfo.index].info = '[语音]';
          this.dialogueInfo.dialogueList.push(info)
        } else if (message.senderUserId == this.dialogueInfo.targetId) {
    
          //对方发出去的
          info.other = true;
          info.head = this.dialogueInfo.head
          info.name = this.dialogueInfo.name
          this.chatList[this.dialogueInfo.index].info = '[语音]';
          this.dialogueInfo.dialogueList.push(info)
        } else {
    
          //聊天列表其他人发出去的(不是现在聊天的人)
          var flag = false;
          for (var i = 0; i < this.chatList.length; i++) {
    
            if (this.chatList[i].targetId == message.senderUserId) {
    
              flag = true;
              this.chatList[i].info = '[语音]';
              if (this.chatList[i].number == '') {
    
                this.chatList[i].number = '1'
              } else {
    
                this.chatList[i].number = (parseInt(this.chatList[i].number) + 1).toString();
              }
              break;
            }
          }
          if (!flag) {
    
            this.getChatList(false)
          }
        }
      },

      //获取左侧聊天列表方法
      getChatList: function(flag) {
    
        var _this = this;
        RongIMClient.getInstance().getConversationList({
    
          onSuccess: function(list) {
    
            //处理一下图片和语音
            list.forEach((item) => {
    
              switch (item.latestMessage.messageType) {
    
                case "ImageMessage":
                  item.latestMessage.content.content = '[图片]'
                  break;
                case "HQVoiceMessage":
                  item.latestMessage.content.content = '[语音]'
                  break;
              }
            })
            getChatList(JSON.stringify(list)).then(res => {
    
              var chatList = res.data.data
              chatList.forEach((item) => {
    
                item.info = RongIMEmoji.symbolToEmoji(item.info)
                if (item.time > new Date(new Date().toLocaleDateString()).getTime()) {
    
                  item.time = dateFormat(new Date(item.time), 'hh:mm')
                } else if (item.time > (new Date(new Date().toLocaleDateString()).getTime() -
                    86400000)) {
    
                  item.time = '昨天'
                } else {
    
                  item.time = dateFormat(new Date(item.time), 'MM-dd')
                }
              })
              _this.chatList = chatList
              if (flag && _this.chatList.length > 0) {
    
                _this.clickItem(_this.chatList[0], 0)
              }
            });
          },
          onError: function(error) {
    
            console(error)
          }
        }, null);
      },

      //清除未读方法(聊天列表左侧角标)
      clearCount: function(item) {
    
        var conversationType = RongIMLib.ConversationType.PRIVATE;
        var targetId = item.targetId;
        RongIMClient.getInstance().clearUnreadCount(conversationType, targetId, {
    
          onSuccess: function() {
    },
          onError: function(error) {
    }
        });
        item.number = ''
      },

      //获取聊天记录
      getDialogueInfo: function(targetId, flag) {
    
        var _this = this;
        var conversationType = RongIMLib.ConversationType.PRIVATE;
        var targetId = targetId; // 想获取自己和谁的历史消息,targetId 赋值为对方的 Id
        var timestrap = flag ? 0 : null; // 默认传 null,若从头开始获取历史消息,请赋值为 0, timestrap = 0;
        var count = 20; // 每次获取的历史消息条数,范围 0-20 条,可以多次获取
        var data = [];
        RongIMLib.RongIMClient.getInstance().getHistoryMessages(conversationType, targetId, timestrap, count, {
    
          onSuccess: function(list, hasMsg) {
    

            _this.dialogueInfo.hasMsg = hasMsg;
            list.forEach((item) => {
    
              var info = {
    
                date: dateFormat(new Date(item.sentTime), 'yyyy-MM-dd hh:mm:ss'),
                send: false
              }
              switch (item.messageType) {
    
                case 'TextMessage':
                  info.text = RongIMEmoji.symbolToEmoji(item.content.content);
                  break;
                case 'ImageMessage':
                  info.srcList = [
                    item.content.imageUri
                  ];
                  info.img = item.content.imageUri;
                  break;
                case 'HQVoiceMessage':
                  info.video = item.content.remoteUrl;
                  break;
              }
              if (item.senderUserId == _this.mytargetId) {
    
                info.other = false;
                info.head = _this.myhead
                info.name = _this.myname
              } else {
    
                info.other = true;
                info.head = _this.dialogueInfo.head
                info.name = _this.dialogueInfo.name
              }
              data.push(info)
            })
            _this.dialogueInfo.dialogueList = [...data, ..._this.dialogueInfo.dialogueList]
          },
          onError: function(error) {
    
            console.log('GetHistoryMessages, errorcode:' + error);
          }
        });
      },

      //发送文字方法
      sendTxt: function(txt) {
    
        var msg = new RongIMLib.TextMessage({
    
          content: txt
        });
        var conversationType = RongIMLib.ConversationType.PRIVATE; // 单聊, 其他会话选择相应的会话类型即可
        var targetId = this.dialogueInfo.targetId; // 目标 Id
        var _this = this;
        var param = {
    
          other: false,
          head: _this.myhead,
          text: _this.textarea,
          send: false,
          date: dateFormat(new Date(), 'yyyy-MM-dd hh:mm:ss'),
          name: "我"
        }
        RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {
    
          onSuccess: function(message) {
    
            _this.dialogueInfo.dialogueList.push(param)
          },
          onError: function(errorCode, message) {
    
            param.send = true;
            _this.dialogueInfo.dialogueList.push(param);
            console.log('发送失败: ' + info + errorCode);
          },
        });
      },

      // 点击聊天列表的某一项
      clickItem(item, index) {
    
        this.dialogueInfo.index = index;
        this.dialogueInfo.targetId = item.targetId;
        this.dialogueInfo.name = item.name;
        this.dialogueInfo.head = item.head;
        this.dialogueInfo.phone = item.phone;
        this.dialogueInfo.hasMsg = true;
        // 设置选中的 targetId
        this.targetId = item.targetId;
        this.clearCount(item);
        this.dialogueInfo.dialogueList = [];
        //从头获取聊天记录
        this.getDialogueInfo(item.targetId, true);
        this.dialogueInfo.hasMsg = true;
        this.pageNum = 1;
        this.pageNum1 = 1;
      },
      getMore() {
    
        this.getDialogueInfo(this.dialogueInfo.targetId, false);
        this.pageNum++;
        this.pageNum1++;
      },
      // 搜索框变化
      searchChange() {
    
        //初始化的时候,给findList赋值
        if (this.findList.length == 0 && this.chatList.length != 0) {
    
          this.findList = this.chatList;
        }
        if (this.find == null || this.find == '') {
    
          this.chatList = this.findList;
          this.findList = [];
        } else {
    
          var list = [];
          this.findList.forEach((item) => {
    
            if (item.name.indexOf(this.find) != -1) {
    
              list.push(item)
            }
          })
          this.chatList = list
        }
      },
      // 点击发送
      sendTextarea() {
    
        if (this.textarea != '' && this.textarea != null) {
    
          this.sendTxt(this.textarea);
          this.chatList[this.dialogueInfo.index].info = this.textarea;
          this.chatList[this.dialogueInfo.index].time = dateFormat(new Date(), 'hh:mm')
          this.textarea = '';
        }
      },
      // 点击出现聊天记录
      clickHistory() {
    
        this.showHistory = !this.showHistory;
      },
      // 上传前校验
      beforeAvatarUpload(file) {
    
        const isImage = file.type.includes("image");
        const isLt2M = file.size / 1024 / 1024 < 20;
        if (!isImage) {
    
          this.$message.error("上传文件类型必须是图片!");
        }
        if (!isLt2M) {
    
          this.$message.error('上传头像图片大小不能超过 2MB!');
        }
        return isImage && isLt2M;
      },
      // 上传成功
      handleAvatarSuccess(res, file) {
    
        var url = res.data.url;
        var info = {
    
          srcList: [
            url
          ],
          loading: true,
          img: URL.createObjectURL(file.raw),
          date: dateFormat(new Date(), 'yyyy-MM-dd hh:mm:ss'),
          send: false,
          other: false,
          head: this.myhead,
          name: this.myname,
        }
        this.chatList[this.dialogueInfo.index].info = '[图片]';
        this.chatList[this.dialogueInfo.index].time = dateFormat(new Date(), 'hh:mm');
        this.dialogueInfo.dialogueList.push(info);

        var index = this.dialogueInfo.dialogueList.length;

        var a = 150;
        var base64 = "";
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext('2d');
        var Img = new Image();
        Img.setAttribute("crossOrigin", 'anonymous')
        Img.src = url;
        Img.onload = function() {
    
          var width = ""
          var height = ""
          if (Img.width > Img.height) {
    
            width = a;
            height = a * Img.height / Img.width;
          } else {
    
            width = a * Img.width / Img.height;
            height = a;
          }
          canvas.width = width;
          canvas.height = height;
          ctx.drawImage(Img, 0, 0, width, height)
          base64 = canvas.toDataURL('image/jpeg')
        };
        var msg = new RongIMLib.ImageMessage({
    
          content: base64,
          imageUri: url
        });
        var conversationType = RongIMLib.ConversationType.PRIVATE; // 单聊, 其他会话选择相应的会话类型即可
        var targetId = this.dialogueInfo.targetId; // 目标 Id
        var _this = this;
        RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {
    
          onSuccess: function(message) {
    
            if (_this.dialogueInfo.dialogueList.length >= index) {
    
              _this.dialogueInfo.dialogueList[index - 1].loading = false;
            }
          },
          onError: function(errorCode, message) {
    
            console.log('发送失败:' + info + errorCode);
          }
        });
      },
      // 中间聊天框的上滚事件
      handleCenterScroll() {
    
        // this.getMore();
        const dialogue_box = this.$refs.dialogue_box;
        //这里的定时是为了列表首次渲染后获取scrollHeight并滑动到底部
        setTimeout(() => {
    
          this.scrollHeight = dialogue_box.scrollHeight;
          dialogue_box.scrollTo(0, this.scrollHeight);
        }, 10);
        dialogue_box.addEventListener('scroll', (e) => {
    
          //这里的2秒钟定时是为了避免滑动频繁,节流
          setTimeout(() => {
    
            if (!this.dialogueInfo.hasMsg) {
    
              this.loadText = "加载完成";
              return;
            }
            //滑到顶部时触发下次数据加载
            if (e.target.scrollTop == 0) {
    
              //将scrollTop置为10以便下次滑到顶部
              e.target.scrollTop = 10;
              //加载数据
              this.getMore();
              setTimeout(() => {
    
                e.target.scrollTo(0, this.scrollHeight - 30); //-30是为了露出最新加载的一行数据
              }, 100);
            }
          }, 2000);
        });
      },
      // 右边聊天记录的上滚事件
      handleRightScroll() {
    
        // this.getMore();
        const dialogue_record = this.$refs.dialogue_record;
        //这里的定时是为了列表首次渲染后获取scrollHeight并滑动到底部
        // setTimeout(() => {
    
        //   this.scrollHeight = dialogue_record.scrollHeight;
        //   dialogue_record.scrollTo(0, this.scrollHeight);
        // }, 10);
        dialogue_record.addEventListener('scroll', (e) => {
    
          //这里的2秒钟定时是为了避免滑动频繁,节流
          setTimeout(() => {
    
            if (!this.dialogueInfo.hasMsg) {
    
              // this.loadText = "加载完成";
              this.loadText1 = "加载完成";
              return;
            }
            //滑到顶部时触发下次数据加载
            if (e.target.scrollTop == 0) {
    
              //将scrollTop置为10以便下次滑到顶部
              e.target.scrollTop = 10;
              //加载数据
              this.getMore();
              //这里的定时是为了在列表渲染之后才使用scrollTo。
              setTimeout(() => {
    
                e.target.scrollTo(0, this.scrollHeight - 30); //-30是为了露出最新加载的一行数据
              }, 100);
            }
          }, 2000);
        });
      },
      // 点击单个表情包
      clickEmoji(emoji) {
    
        this.textarea += emoji
      },
    }
  }
</script>


<style scoped>
  .whole-wrapper {
    
    display: flex;
    background: #fff;
    /* height: 700px; */
    height: 90%;
  }

  /* 左边部分 */
  .left_whole_wrapper {
    
    display: flex;
    flex-direction: column;
    width: 24%;
  }

  .left_wrapper {
    
    flex: 1;
  }

  .left-item {
    
    display: flex;
    justify-content: space-between;
    padding: 18px 24px;
  }

  .active {
    
    background: #ebebeb;
  }

  .left-item-left {
    
    display: flex;
  }

  .left-item-head>img {
    
    width: 48px;
    height: 48px;
    border-radius: 50%;
  }

  .left-item-info {
    
    margin-left: 12px;
    max-width: 220px;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
  }

  .left-item-info_title {
    
    font-size: 14px;
    font-family: PingFang SC, PingFang SC-Regular;
    font-weight: 400;
    text-align: left;
    color: #292929;
    /* 文字超出处理 */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .left-item-info_content {
    
    font-size: 14px;
    font-family: PingFang SC, PingFang SC-Regular;
    font-weight: 400;
    text-align: left;
    color: #909090;
    margin-top: 4px;
    /* 文字超出处理 */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .left-item-time {
    
    display: flex;
    flex-direction: column;
    text-align: right;
    align-items: flex-end;
    margin-left: 20px;
  }

  .left-item-time-time {
    
    font-size: 14px;
    font-family: PingFang SC, PingFang SC-Regular;
    font-weight: 400;
    text-align: right;
    color: #909090;
  }

  .left-item-time-number {
    
    width: 20px;
    height: 20px;
    line-height: 20px;
    border-radius: 50%;
    background: #ff4949;
    color: #ffffff;
    text-align: center;
    font-size: 12px;
    font-family: PingFang SC, PingFang SC-Regular;
    font-weight: 400;
    margin-top: 5px;
  }

  .search {
    
    padding: 36px 24px;
    height: 5%;
  }

  /* 中间部分*/
  .center_whole_wrapper {
    
    flex: 1;
    background: #f8f8f8;
  }

  .center_wrapper {
    
    height: 100%;
    display: flex;
    flex-direction: column;
  }

  .center_wrapper_top {
    
    display: flex;
    align-items: center;
    padding: 30px 24px;
    flex: 1;
  }

  .center_wrapper_top_name {
    
    font-size: 18px;
    font-family: PingFang SC, PingFang SC-Bold;
    font-weight: 700;
    text-align: left;
    color: #292929;
  }

  .center_wrapper_top_number {
    
    font-size: 14px;
    font-family: PingFang SC, PingFang SC-Regular;
    font-weight: 400;
    text-align: left;
    color: #292929;
    margin-left: 12px;
  }

  .center_wrapper_center {
    
    flex: 10;
    padding: 30px 24px 0px 24px;
    border-top: 1px solid #c7c7c7;
    border-bottom: 1px solid #c7c7c7;
  }

  .center_wrapper_center_item {
    
    display: flex;
    margin-bottom: 32px;
  }

  .center_wrapper_right {
    
    flex: 4;
    padding: 20px 20px;
    position: relative;
  }

  .center-item-info_wrapper {
    
    margin: 0px 16px;
  }

  .center-item-tip {
    
    display: flex;
    align-items: center;
  }

  .error-tip>img {
    
    width: 20px;
    margin: 0 10px;
  }

  .center-item-info {
    
    max-width: 336px;
    font-size: 14px;
    font-family: PingFang SC, PingFang SC-Regular;
    font-weight: 400;
    text-align: left;
    color: #909090;
    line-height: 22px;
    background: #f1f1f1;
    padding: 16px;
  }

  .center-item-time {
    
    font-size: 12px;
    font-family: PingFang SC, PingFang SC-Regular;
    font-weight: 400;
    text-align: left;
    color: #909090;
    line-height: 22px;
    margin-top: 12px;
  }

  /* 反向样式开始*/
  .center_wrapper_center_item_reserve {
    
    display: flex;
    flex-direction: row-reverse;
    margin-bottom: 32px;
  }

  .center_wrapper_center_item_reserve .center-item-time {
    
    text-align: right;
  }

  .center_wrapper_center_item_reserve {
    
    display: flex;
    flex-direction: row-reverse;
    margin-bottom: 32px;
  }

  .center_wrapper_center_item_reserve .center-item-tip {
    
    display: flex;
    flex-direction: row-reverse;
    align-items: center;
  }

  .center_wrapper_center_item_reserve .error-tip>img {
    
    width: 20px;
    margin: 0 10px;
  }

  /* 反向样式结束*/

  /* 右边样式 */
  .right_whole_wrapper {
    
    background: #fff;
  }

  .right_wrapper {
    
    flex: 1;
  }

  .right_wrapper_center {
    
    border: none;
    color: #909090;
  }

  .center-item-name {
    
    font-size: 12px;
  }

  .center-item-info {
    
    margin-top: 10px;
  }

  .center-item-info_img {
    
    width: 150px;
    /* height: 100px; */
  }

  .center-item-info_img>img {
    
    width: 100%;
    height: 100%;
  }

  /* 几个图标 */
  .icon-list {
    
    display: flex;
  }

  .icon-list>div:not(:first-child) {
    
    margin-left: 15px;
  }

  .icon-item-img {
    
    width: 25px;
  }

  /* 修改组件样式 */
  .whole-wrapper>>>.el-input__inner {
    
    border-radius: 30px;
  }

  .whole-wrapper>>>.el-textarea__inner {
    
    min-height: 80px;
    resize: none;
    border: none;
    background: #f8f8f8;
    padding: 5px 0px;
  }

  .whole-wrapper>>>.el-button--primary {
    
    width: 100px;
    height: 40px;
    position: absolute;
    bottom: 20px;
    right: 20px;
  }

  .loading {
    
    text-align: center;
    color: #909090;
  }

  .loading span {
    
    margin-left: 10px;
  }
</style>


转载:https://blog.csdn.net/weixin_44076536/article/details/110110241
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场