小程序与IM即时通讯,小程序聊天框

IM即时通讯官网
https://cloud.tencent.com/document/product/269
SDK安装

// IM 小程序 SDK
npm install tim-wx-sdk --save
// 发送图片、文件等消息需要的 COS SDK
npm install cos-wx-sdk-v5 --save

小程序使用IM

import TIM from '../miniprogram_npm/tim-wx-sdk/tim-wx.js';
import COS from "../miniprogram_npm/cos-wx-sdk-v5/index.js";

var SDKAppID = ''; // 您的即时通信 IM 应用的 SDKAppID
var admin = 'administrator'; // 您的即时通信 IM 应用的管理员,默认administrator
let options = {
  SDKAppID: SDKAppID 
};
// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
let tim = TIM.create(options); // SDK 实例通常用 tim 表示
// 注册 COS SDK 插件
tim.registerPlugin({
  'cos-wx-sdk': COS
});
tim.setLogLevel(1);  //日志打印,1或0(0时日志信息较全面)
tim.on(TIM.EVENT.KICKED_OUT, loginIM);  //实时监听IM的登录状态。
//IM登录
async function loginIM() {
  let user = await getUser();
  let usersig = await getUsreSig(user.userId);
  await checkAccount(user.userId, user.nickname, user.avatarUrl);
  tim.login({
    userID: user.userId,
    userSig: usersig
  }).then(function (imResponse) {
    console.log('登录成功'); // 登录成功
  }).catch(function (imError) {
    console.warn('login error:', imError); // 登录失败的相关信息
  });
}
//获取小程序用户信息
function getUser() {
  return new Promise((resolve) => {
    var user = {};
    user.userId = wx.getStorageSync('userId');
    user.nickname = wx.getStorageSync('nickName')
    user.avatarUrl = wx.getStorageSync('avatarUrl')
    console.log('ava', user.avatarUrl)
    resolve(user)
  })
}
// 检查IM用户是否存在,不存在就去注册
async function checkAccount(teacherID, nickname, avatarUrl) {
  let usersig = await getUsreSig(admin)
  return new wx.request({
    url: 'https://console.tim.qq.com/v4/im_open_login_svc/account_check?sdkappid=' + SDKAppID + '&identifier=' + admin + '&usersig=' + usersig + '&random=2&contenttype=json',
    method: 'post',
    data: {
      "CheckItem": [{
        "UserID": teacherID
      }]
    },
    success: function (res) {
      console.log('res',res)
      if (res.data.ResultItem[0].AccountStatus == 'NotImported') {
        importAccount(teacherID, usersig, nickname, avatarUrl)
      }
    }
  })
}
//注册IM用户
function importAccount(teacherID, usersig, nickname, avatarUrl) {
  console.log('head', avatarUrl)
  wx.request({
    url: 'https://console.tim.qq.com/v4/im_open_login_svc/account_import?sdkappid=' + SDKAppID + '&identifier=' + admin + '&usersig=' + usersig + '&random=2&contenttype=json',
    method: 'post',
    data: {
      "Identifier": teacherID,
      "Nick": nickname,
      "FaceUrl": avatarUrl
    },
    success: function (res) {
      console.log(res)
    }
  })
}
//通知后端请求获取用户登录即时通信 IM 的密码
function getUsreSig(userId) {
  return new Promise((resolve) => {
    wx.request({
      url: config.host + '/user/getSig?userId=' + userId,
      method: 'post',
      success: function (res) {
        resolve(res.data.result)
      }
    })
  })
}

获取会话列表

var getConversionList = function () {
  tim.getConversationList().then(function (imResponse) {
    const conversationList = imResponse.data.conversationList; // 会话列表,用该列表覆盖原有的会话列表
    console.log(conversationList)
  }).catch(function (imError) {
    console.warn('getConversationList error:', imError); // 获取会话列表失败的相关信息
  });
}

实时监听会话列表

tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, getConversionList);

会话框

<view class="md_header" wx:if="{{pictureUrl.length==0}}">
  <image src="{{imageList.bg2}}" style="width: 100%;height: 100%;position: absolute;z-index: -999"/>
  <!-- <view class='top' style="height:39px;">
    <view class="goback">
      <image src="{{image}}goback.png" bindtap="gobackmessage"></image>
      <view>{{nickname}}</view>
    </view>
  </view> -->
  <view class="main" style="margin-top:{{marginTop}}">
    <image src="{{image}}gobackt.png" style="width: 6%;height: 8%;position: absolute;z-index: 99;margin:2vh 1.5vw" bindtap="gobackmessage"></image>
    <view id="nickNamestyle" style="z-index:-98">{{nickname}}</view>
    <image src="{{image}}mdetailbg.png" style="width: 100%;height: {{mdetailbgheight}};position: absolute;z-index: -99"/>
    <scroll-view id="dialog_list" scroll-y="{{true}}" scroll-with-animation='{{true}}' scroll-top='{{scroll_top}}' scroll-into-view="{{toView}}" scroll-with-animation="true" enable-back-to-top="true" style="height:{{comment_bottom}};padding-top:16vh;" id="scroll-wrap">
      <!--单独一个对话-->
      <view class="loading_view" wx:if="{{isLoading}}">
        <text class="subtext">正在载入更多...</text>
      </view>
      <view class="subtext" style="text-align:center;height: 50rpx;" wx:if="{{noMore}}">没有更多了~</view>
      <view id="inner-wrap" bindtouchstart="start_fn" bindtouchend="end_fn" class="singleDialog" wx:for="{{testMessageDetail}}" wx:key="item" wx:for-index="index">
        <!--显示时间-->
        <view class="showTime" wx:if="{{item.time}}">{{item.time}}</view>
        <view wx:if="{{item.flow=='in'}}" class="left-box" id='msg-{{index}}'>
          <image src="{{image}}inviteteacher.gif" style="width: 20vh;height: 20vh;margin-left: -4vh;margin-top: -5vh;margin-right: 1vw;"></image>
          <image class="ava" src="{{testImg}}" />
          <view class="details">
            <view class="content" wx:if="{{item.payload.text}}">{{item.payload.text}}</view>
            <view style="height:{{windowWidth*0.2*item.payload.imageInfoArray[0].height/item.payload.imageInfoArray[0].width}}px;width:20vw;margin:3px 10px" wx:if="{{item.payload.imageInfoArray}}">
              <image bindlongpress="saveImage" bindtap="previewImage" data-width="{{item.payload.imageInfoArray[0].width}}" data-height="{{item.payload.imageInfoArray[0].height}}" data-index="{{index}}" src="{{item.payload.imageInfoArray[0].imageUrl}}"></image>
            </view>
            <view wx:if='{{item.payload.url}}' class="contentafter" style="margin-left:16px;margin-top:5vh"></view>
            <view wx:if='{{item.payload.url}}' class="video" style="width: 37vw;">
              <audio id="myVideo-{{index}}" src="{{item.payload.remoteAudioUrl?item.payload.remoteAudioUrl:item.payload.url}}" enable-danmu danmu-btn controls="{{false}}" autoplay='{{false}}' bindtimeupdate="videoUpdate" data-second="{{item.payload.second}}" objectFit="fill"></audio>
              <view class='process-container'>
                <image src="{{image}}luyinthree.png" class='slider-container' bindtap='videoOpreation' data-index="{{index}}"></image>
                <view class='slider-container' id="slider-container">
                  <slider bindchange="sliderChange" bindchanging="sliderChanging" step="1" value="{{item.sliderValue}}" backgroundColor="#A8A8A8" activeColor="#rgb(250, 232, 114)" block-color="#FFEE83" blockSize="1"/>
                </view>
                <view class="second">{{item.payload.second}}<text style="font-size:18px">"</text></view>
              </view>
            </view>
          </view>
        </view>
        <view wx:if="{{item.flow=='out'}}" class="right-box" id='msg-{{index}}'>
          <view class="details">
            <view class="content" wx:if="{{item.payload.text}}"><view class="contentafter"></view>{{item.payload.text}}</view>
            <view style="height:{{windowWidth*0.2*item.payload.imageInfoArray[0].height/item.payload.imageInfoArray[0].width}}px;width:20vw;margin:3px 10px" wx:if="{{item.payload.imageInfoArray}}">
              <image bindlongpress="saveImage"  bindtap="previewImage" data-index="{{index}}" data-width="{{item.payload.imageInfoArray[0].width}}" data-height="{{item.payload.imageInfoArray[0].height}}" data-url="{{item.payload.imageInfoArray[2].imageUrl}}" src="{{item.payload.imageInfoArray[2].imageUrl}}" wx:if="{{item.payload.imageInfoArray}}"></image>
            </view>
            <view wx:if='{{item.payload.url}}' class="video" style="width: 37vw">
              <audio id="myVideo-{{index}}" src="{{item.payload.remoteAudioUrl?item.payload.remoteAudioUrl:item.payload.url}}" enable-danmu danmu-btn controls="{{false}}" autoplay='{{false}}' bindtimeupdate="videoUpdate" data-second="{{item.payload.second}}" objectFit="fill"></audio>
              <view class='process-container'>
                <image src="{{image}}luyinthree.png" class='slider-container' bindtap='videoOpreation' data-index="{{index}}"></image>
                <!-- <image wx:if="{{!item.playStates}}" src="{{image}}start.png" class='slider-container' bindtap='videoOpreation' data-index="{{index}}"></image>
                <image wx:if="{{item.playStates}}" src="{{image}}en.png" class='slider-container' bindtap='videoOpreation' data-index="{{index}}"></image> -->
                <view class='slider-container' id="slider-container">
                  <slider bindchange="sliderChange" bindchanging="sliderChanging" step="1" value="{{item.sliderValue}}" backgroundColor="#A8A8A8" activeColor="#rgb(250, 232, 114)" block-color="#FFEE83" blockSize="1"/>
                </view>
                <view class="second">{{item.payload.second}}<text style="font-size:18px">"</text><view class="contentafter" style="margin-right:-6.9vw;margin-top:-7vh;position:relative;z-index:-99"></view></view>
              </view>
            </view>
          </view>
          <image src='{{image}}avabg.png' style="height: 15vh;width: 15vh;">
            <view class="userinfo-avatar">
              <open-data class="ava" style="margin-left:0vw" type="userAvatarUrl"></open-data>
            </view>
          </image>
          <!-- <image src="{{image}}inviteteacher.gif" style="width: 20vh;height: 20vh;margin-top: -5vh;margin-right: -1.5vw;"></image> -->
        </view>
      </view>
    </scroll-view>
    <!--发送信息-->
    <view class="mycomment comment_bottom" style="bottom:{{inputBottom}}">
      <image bindtap="startluyin" wx:if="{{!luyin}}" src="{{image}}luyin0.png" style="width: 5vh;height: 8vh;border-radius:50%;margin-left:1vw;margin-top:3vh"></image>
      <image bindtap="startluyin" wx:if="{{luyin}}" src="{{image}}luyin1.png" style="width: 8vh;height: 7vh;border-radius:50%;margin-left:1vw;margin-top:3vh"></image>
      <view bindtouchstart='start' bindtouchend="end" class="comment_input" wx:if="{{luyin}}" style="text-align:center;color:#9d9f90">
        <image src="{{image}}speaking.png" style="width: 21vh;height: 5vh;margin-left:0vw;margin-top:3vh"></image>
      </view>
      <input class="comment_input" wx:if="{{!luyin}}" bindinput='replyInputChange' bindconfirm='sendClick' adjust-position='{{false}}' bindfocus="focus" bindblur="blur" value='{{inputVal}}' confirm-type='send' placeholder="请输入文本 ···" confirm-hold='false'></input>
      <image class="commit_btn" src="{{image}}sendcontent.png" data-value='{{inputVal}}' bindtap='sendClick' />
      <image bindtap="sendOther" src="{{image}}sendother.png" style="width: 7vh;height: 7vh;margin-right:1vw;margin-top:3vh"></image>
      <view class="mask" catchtouchmove="preventTouchMove" bindtap="cancelReplying" wx:if="{{isReplying}}" />
    </view>
    <view wx:if="{{comment_bottom=='53vh'}}" class="sendOther">
      <image bindtap="sendPicture" src="{{image}}chat_pic.png" style="height:57px;width:57px;margin:1vh 40px 0px 40px"></image>
      <image bindtap="getpiano" src="{{image}}chat_ceping.png" style="height:57px;width:57px;margin-top:1vh"></image>
    </view>
  </view>
</view>
<view class="modal-mask"></view>
<view class='lookPiture' style="z-index:10;position:absolute;height:100vh" wx:if="{{pictureUrl.length!=0}}">
  <view class='top' style="height:39px;">
      <view class="goback">
        <image src="{{image}}goback.png" bindtap="gobackdetail"></image>
      </view>
    </view>
  <scroll-view scroll-y='true' scroll-x='true' style="text-align: center;width:100vw;height:99vh;margin-top:-11.5vh" bindtouchmove="touchmoveCallback" bindtouchstart="touchstartCallback">
    <image data-url="{{pictureUrl}}" src="{{pictureUrl}}" style="{{pictureUrlStyle}}" bindload="imgload"></image>
  </scroll-view>
</view>
.md_header{
    background-size: 100% 100%;
    height: 100vh;
}
.md_header .goback image{
  width: 8vh;
  height: 8vh;
  z-index: 2;
  position: absolute;
  margin-left: 2vw;
  margin-top: 2vh;
  background: rgba(58, 53, 53, 0.705);
  border-radius: 50%;
  padding: 1vh;
}
.md_header .goback view{
  font-weight: 600;
  font-size: 23px;
  font-family: "楷体";
  color: rgb(255, 255, 255);
  margin-left: 38px;
  position: absolute;
  z-index: 2;
  padding: 2px;
}
.modal-mask {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  background: #000;
  opacity: 0.2;
  z-index: 1;
}
.md_header .main{
  height: 100vh;
  width: 65vw;
  position: relative;
  z-index: 2;
  margin-left: 18vw;
}
#nickNamestyle{
  position: absolute;
  margin: 1.5vh 6vw;
  color: rgb(196, 124, 12, 1);
  font-size: 19px;
  font-family: '楷体';
  font-weight: 700;
}
#dialog_list {
  display: flex;
  flex-direction: column;
  overflow: auto;
  height: 75.5vh;
}
/*隐藏滚动条*/
::-webkit-scrollbar {
  width: 0;
  height: 0;
  color: transparent;
}
.singleDialog {
  width: 100%;
  flex-direction: column;
}
.ava {
  height: 10vh;
  width: 10vh;
  border-radius: 50%;
  margin-left: -16.5vh;
}
.details {
  display: flex;
  flex-direction: column;
  margin-left: 0rpx;
  max-width: 80%;
  margin: 8vh 0vh;
  margin-top: -2vh;
}
.username {
  color: gray;
  font-size: 28rpx;
  margin: auto 20rpx;
}
.showTime {
  font-size: 12px;
  text-align: center;
  color: #9d9f90;
  padding: 0vh 0vh 3vh 0vh;
  margin-top: -7vh;
}
/*加载部分*/
.loading_view {
  margin-top: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 20px;
}
.loading {
  margin-right: 10rpx;
  width: 45rpx;
  height: 45rpx;
  animation: animation 1s linear infinite;
}
@keyframes animation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(1turn);
  }
}
.subtext {
  color: gray;
  font-size: 12px;
}
/* 发送信息 */
.mycomment {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
}

.comment_input {
  width: 70%;
  font-size: 15px;
  padding: 5px 10px 5px 15px;
  margin-top: 3vh;
  border-radius: 6px;
}

.commit_btn {
  height: 7vh;
  width: 6vh;
  margin-top: 3vh;
  margin-right: 2vw;
}

.comment_bottom {
  position: relative;
  width: 100%;
  z-index: 9;
  height: 12vh;
}

.system-msg {
  text-align: center;
  margin: 20rpx;
}

.system-title {
  font-size: 32rpx;
  font-weight: bold;
}

.system-content {
  color: gray;
  font-size: 28rpx;
}

.left-box {
  display: flex;
  flex-direction: row;
  padding: 0px 10px;
  width: 100%;
}

.right-box {
  display: flex;
  flex-direction: row;
  padding: 0px 10px;
  justify-content: flex-end;
  margin-bottom: 1vh;
}
.right-box .content {
  margin-top: 14px;
  margin-right: 10px;
  font-size: 15px;
  border-radius: 5px;
  padding: 5px 15px;
  background:#fff;
  word-break: break-all;
  text-align: left;
  position: relative;
  font-family: '楷体';
  min-height: 10vh;
  line-height: 10vh;
}
.right-box .contentafter {
  content: '';
  width: 13rpx;
  height: 13rpx;
  transform: rotate(45deg);
  background-color: #fff;
  border: 1px #fff;
  border-style: solid none none solid ;
  border-radius: 2px;
  float: right;
  margin-right: -20px;
  margin-top: 7px;
}
.left-box .contentafter {
  content: '';
  width: 13rpx;
  height: 13rpx;
  transform: rotate(45deg);
  background-color: rgba(253, 225, 81, 1);
  border: 1px rgba(253, 225, 81, 1);
  border-style: solid none none solid ;
  border-radius: 2px;
  float: right;
  margin-right: -20px;
  margin-top: 7px;
}
.left-box .content {
  font-size: 15px;
  border-radius: 5px;
  padding: 5px 15px;
  background:linear-gradient(90deg,rgba(253, 225, 81, 1),rgba(253, 225, 81, 0.6));
  margin: 3px 10px;
  word-break: break-all;
  text-align: left;
  font-family: '楷体';
  position: relative;
  margin-left: 19px;
  min-height: 10vh;
  line-height: 10vh;
}
.left-box .content:after {
  content: '';
  width: 13rpx;
  height: 13rpx;
  position: absolute;
  top: 16rpx;
  left: -5px;
  transform: rotate(45deg);
  background-color: rgba(253, 225, 81, 1);
  border: 1px rgba(253, 225, 81, 1);
  border-style: solid none none solid ;
  border-radius: 2px
}
.details video{
  width: 0px !important;
  height: 0px !important;
}
.details image{
  width: 20vw;
  height: 100%;
}
.process-container image{
  width: 6vh;
  height: 6vh;
  margin-left: 2vw;
  margin-top: 4vh;
}
.details #slider-container{
 width: 27vw;
  margin-top: -11vh;
  margin-left: 5vw;
}
.right-box .second{
  margin-top: -11vh;
  margin-left: 31vw;
  color: rgb(196, 124, 12, 1);
  font-size: 13px;
}
.left-box .second{
  margin-top: -11vh;
  margin-left: 31vw;
  color: rgb(196, 124, 12, 1);
  font-size: 13px;
}
.right-box .details .video{
  margin: 3vh 3vh;
  background: #fff;
  height: 16vh;
  border-radius: 5px;
  width: 25vw;
  line-height: 9vh;
}
.left-box .details .video{
  margin: -8vh 6vh 3vh;
  background: rgba(253, 225, 81, 1);
  height: 16vh;
  border-radius: 5px;
  width: 25vw;
  line-height: 9vh;
}
.details .process-container{
  margin-top: -7vh;
  align-items: center;
  justify-content: center;
  width: 25vw;
}
.sendOther image{
  display: inline-block;
}
.sendOther{
  background:rgb(226, 208, 178);
  height: 20vh;
  margin-top: -1vh
}
.lookPiture .goback image{
  width: 8vh;
  height: 8vh;
  z-index: 2;
  position: absolute;
  margin-left: 2vw;
  margin-top: 2vh;
  background: rgba(58, 53, 53, 0.705);
  border-radius: 50%;
  padding: 1vh;
}
.userinfo-avatar {  
  overflow: hidden;
  width: 10.5vh;
  height: 10.5vh;
  border-radius: 50%;
  margin-top: -13vh;
  margin-left: 2vh;
} 

获取消息列表

getAll: function(){
    let that = this;
    var time = '';
    if (that.data.conversationID){
      let getMessageList = tim.getMessageList({ conversationID: that.data.conversationID, count: 15 }).then(async function (imResponse) { //获取15条消息
        const messageList = imResponse.data.messageList // 会话列表,用该列表覆盖原有的会话列表
        const nextReqMessageID = imResponse.data.nextReqMessageID; //获取下一页消息的标志位
        const isCompleted = imResponse.data.isCompleted;  //是否获取完了所有消息
        for (var i = 0; messageList.length > i; i++) {
          if (messageList[i].payload.url && messageList[i].payload.second>1000) {
            console.log('messageList[i].payload.second', messageList[i].payload.second)
            messageList[i].payload.second = (messageList[i].payload.second / 1000).toFixed(0);
            console.log('messageList[i].payload.second', messageList[i].payload.second)
          }
          messageList[i].playStates = false;
          messageList[i].sliderValue = 0;
          messageList[i].time = await that.getTime(messageList[i]);  //消息的时间处理
        }
        testMessageDetail = messageList
        that.setData({
          testMessageDetail: messageList,
          toView: 'msg-' + (messageList.length - 1),  //定位到最后一条消息
          nextReqMessageID: nextReqMessageID,
          isCompleted: isCompleted
        })
        console.log('metail',testMessageDetail)
      }).catch(function (imError) {
        console.warn('getMessageList error:', imError); // 获取会话列表失败的相关信息
      });
    }
    // tim.on(TIM.EVENT.SDK_READY, getMessageList)
  },
  //修改时间格式
  getTime:function(message){
    var that = this;
    return new Promise((resolve)=>{
      var messageTime = message.time+''
      if (messageTime.indexOf(":") < 0 && messageTime != '') {
        var date = new Date(message.time * 1000);
        var Y = date.getFullYear() + '-';
        var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
        var D = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
        var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
        var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + '';
        var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
        var myDate = new Date;
        var year = myDate.getFullYear() + '-'; //获取当前年
        var mon = (myDate.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'; //获取当前月
        var day = (myDate.getDate() < 10 ? '0' + myDate.getDate() : myDate.getDate()) + ' '; //获取当前日
        if ((year + mon + day) == (Y + M + D)) {
          message.time = h + m;
          if (that.data.time == h + m) {
            message.time = '';
          }
        } else if ((year == Y) && (mon == M) && (day - D == 1)) {
          message.time = '昨天' + h + m;
          if (that.data.time == h + m) {
            message.time = '';
          }
        } else {
          message.time = Y + M + D + h + m;
          if (that.data.time == h + m) {
            message.time = '';
          }
        }
      }
      this.setData({
        time: h+m
      })
      resolve(message.time)
    })
  },

消息列表下一页(下拉加载更多)
小程序scroll-view上拉加载更多,下拉刷新数据
(https://blog.csdn.net/qq_39389646/article/details/105817747)

if (!that.data.isCompleted) {
        that.setData({
          isLoading: true
        })
        console.log(that.data.conversationID)
        let getMessageList = tim.getMessageList({ conversationID: that.data.conversationID, nextReqMessageID: that.data.nextReqMessageID, count: 15 }).then(async function (imResponse) {
          const messageList = imResponse.data.messageList// 会话列表,用该列表覆盖原有的会话列表
          const nextReqMessageID = imResponse.data.nextReqMessageID;
          const isCompleted = imResponse.data.isCompleted;
          for (var i = (messageList.length - 1); 0 <= i; i--) {
            if (messageList[i].payload.url && messageList[i].payload.second > 1000) {
              console.log('messageList[i].payload.second', messageList[i].payload.second)
              messageList[i].payload.second = (messageList[i].payload.second / 1000).toFixed(0);
              console.log('messageList[i].payload.second', messageList[i].payload.second)
            }
            messageList[i].playStates = false;
            messageList[i].sliderValue = 0;
            messageList[i].time = await that.getTime(messageList[i]);
            testMessageDetail.unshift(messageList[i])
          }
          IM.nextReqMessageID = that.data.nextReqMessageID
          that.setData({
            testMessageDetail: testMessageDetail,
            nextReqMessageID: nextReqMessageID,
            isCompleted: isCompleted,
            isLoading: false,
            toView: 'msg-'+that.data.toView
          })
        }).catch(function (imError) {
          console.warn('getMessageList error:', imError); // 获取会话列表失败的相关信息
        });
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值