欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

前端整合腾讯云IM实现即时通讯

最编程 2024-08-11 12:45:17
...

近期需求 : 在项目里面开发IM 即时通讯 之前对接过融云 GoEasy 极光 这次在微信小程序里面集成 本着" 同源策略 " 采用了腾讯云IM 即时通讯 虽然腾讯方面的文档对我来说并不是那么的友好 ☺

即时通信 IM官网地址: cloud.tencent.com/document/pr…

image.png

鉴于小程序体积的限制外加本公司对UI还原程度 "高度重视" , 并没有采用含UI集成方案 , 采用了无UI集成方案

半成品

image.png

image.png

image.png

步骤:

集成 SDK

  • 通过 npm 和 script 方式将 IM SDK 集成到您的 Web 项目中,推荐使用 npm 集成。
  • 通过 npm 方式将 IM SDK 集成到您的小程序或者 uni-app 项目中。
  • 通过集成上传插件 tim-upload-plugin,实现更快更安全的富文本消息资源上传。
  • 通过集成本地审核插件 tim-profanity-filter-plugin,在客户端本地检测由即时通信 SDK 发送的文本内容,支持对已配置的敏感词进行拦截或者替换处理,为您的产品体验和业务安全保驾护航。本地审核功能的开通和配置方法,详情请参见 控制台指南
// 从v2.11.2起,SDK 支持了 WebSocket,推荐接入;v2.10.2及以下版本,使用 HTTP
npm install tim-wx-sdk --save
// 发送图片、文件等消息需要腾讯云 即时通信 IM 上传插件
npm install tim-upload-plugin --save
// 拦截或替换敏感词需要本地审核插件
npm install tim-profanity-filter-plugin --save

初始化

初始化 SDK 需要操作以下步骤:

  1. 准备 SDKAppID。
  2. 调用 TIM.create 初始化 SDK。
  3. 添加 SDK 事件监听器。
// 从v2.11.2起,SDK 支持了 WebSocket,推荐接入;v2.10.2及以下版本,使用 HTTP
// v2.24.0起,SDK 支持使用本地审核插件
import TIM from 'tim-js-sdk';
import TIMUploadPlugin from 'tim-upload-plugin';
import TIMProfanityFilterPlugin from 'tim-profanity-filter-plugin';

let options = {
  SDKAppID: 0 // 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID
};
// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
let tim = TIM.create(options); // SDK 实例通常用 tim 表示

// 设置 SDK 日志输出级别,详细分级请参见 <a href="https://web.sdk.qcloud.com/im/doc/zh-cn/SDK.html#setLogLevel">setLogLevel 接口的说明</a>
tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用
// tim.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用

// 注册腾讯云即时通信 IM 上传插件
tim.registerPlugin({'tim-upload-plugin': TIMUploadPlugin});

// 注册腾讯云即时通信 IM 本地审核插件
tim.registerPlugin({'tim-profanity-filter-plugin': TIMProfanityFilterPlugin});

登录

let promise = tim.login({userID: 'your userID', userSig: 'your userSig'});
promise.then(function(imResponse) {
  console.log(imResponse.data); // 登录成功
  if (imResponse.data.repeatLogin === true) {
    // 标识帐号已登录,本次登录操作为重复登录。v2.5.1 起支持
    console.log(imResponse.data.errorInfo);
  }
}).catch(function(imError) {
  console.warn('login error:', imError); // 登录失败的相关信息
});

创建消息

image.png

接收消息 事件监听

let onMessageReceived = function(event) {
  // event.data - 存储 Message 对象的数组 - [Message]
  const messageList = event.data;
  messageList.forEach((message) => {
    if (message.type === TIM.TYPES.MSG_TEXT) {
      // 文本消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.TextPayload
    } else if (message.type === TIM.TYPES.MSG_IMAGE) {
      // 图片消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.ImagePayload
    } else if (message.type === TIM.TYPES.MSG_SOUND) {
      // 音频消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.AudioPayload
    } else if (message.type === TIM.TYPES.MSG_VIDEO) {
      // 视频消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.VideoPayload
    } else if (message.type === TIM.TYPES.MSG_FILE) {
      // 文件消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.FilePayload
    } else if (message.type === TIM.TYPES.MSG_CUSTOM) {
      // 自定义消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.CustomPayload
    } else if (message.type === TIM.TYPES.MSG_MERGER) {
      // 合并消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.MergerPayload
    } else if (message.type === TIM.TYPES.MSG_LOCATION) {
      // 地理位置消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.LocationPayload
    } else if (message.type === TIM.TYPES.MSG_GRP_TIP) {
      // 群提示消息 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.GroupTipPayload
    } else if (message.type === TIM.TYPES.MSG_GRP_SYS_NOTICE) {
      // 群系统通知 - https://web.sdk.qcloud.com/im/doc/zh-cn/Message.html#.GroupSystemNoticePayload
    }
  });
};
tim.on(TIM.EVENT.MESSAGE_RECEIVED, onMessageReceived);

历史消息

// 打开某个会话时,第一次拉取消息列表
let promise = tim.getMessageList({conversationID: 'C2Ctest'});
promise.then(function(imResponse) {
  const messageList = imResponse.data.messageList; // 消息列表。
  const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。
  const isCompleted = imResponse.data.isCompleted; // 表示是否已经拉完所有消息。
});
// 下拉查看更多消息
let promise = tim.getMessageList({conversationID: 'C2Ctest', nextReqMessageID});
promise.then(function(imResponse) {
  const messageList = imResponse.data.messageList; // 消息列表。
  const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。
  const isCompleted = imResponse.data.isCompleted; // 表示是否已经拉完所有消息。
});

获取会话列表

接入侧可通过调用 getConversationList 接口主动获取会话列表。

获取全量的会话列表

// 获取全量的会话列表
let promise = tim.getConversationList();
promise.then(function(imResponse) {
  const conversationList = imResponse.data.conversationList; // 全量的会话列表,用该列表覆盖原有的会话列表
  const isSyncCompleted = imResponse.data.isSyncCompleted; // 从云端同步会话列表是否完成
}).catch(function(imError) {
  console.warn('getConversationList error:', imError); // 获取会话列表失败的相关信息
});

获取指定的会话列表

// 获取指定的会话列表
let promise = tim.getConversationList([conversationID1, conversationID2]);
promise.then(function(imResponse) {
  const conversationList = imResponse.data.conversationList; // 缓存中已存在的指定的会话列表
}).catch(function(imError) {
  console.warn('getConversationList error:', imError); // 获取会话列表失败的相关信息
});

获取所有的群会话

// 获取所有的群会话
let promise = tim.getConversationList({ type: TIM.TYPES.CONV_GROUP });
promise.then(function(imResponse) {
  const conversationList = imResponse.data.conversationList; // 会话列表
});

获取所有的“标星”会话

// 获取所有的“标星”会话
let promise = tim.getConversationList({ markType: TIM.TYPES.CONV_MARK_TYPE_STAR });
promise.then(function(imResponse) {
  const conversationList = imResponse.data.conversationList; // 会话列表
});

获取指定会话分组下的所有会话

// 获取指定会话分组下的所有会话
let promise = tim.getConversationList({ groupName: 'Suppliers' });
promise.then(function(imResponse) {
  const conversationList = imResponse.data.conversationList; // 会话列表
});

监听会话列表更新事件

接入侧监听 TIM.EVENT.CONVERSATION_LIST_UPDATED 事件,获取会话列表更新的通知。

示例

let onConversationListUpdated = function(event) {
  console.log(event.data); // 包含 Conversation 实例的数组
};
tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, onConversationListUpdated);

置顶会话

功能描述

会话置顶,指的是把好友或者群会话固定在会话列表的最前面,方便用户查找。置顶状态会存储在服务器,切换终端设备后,置顶状态会同步到新设备上。
调用接口成功后会话列表重新排序,SDK 会派发事件 TIM.EVENT.CONVERSATION_LIST_UPDATED

// 置顶会话,v2.14.0起支持
let promise = tim.pinConversation({ conversationID: 'C2CExample', isPinned: true });
promise.then(function(imResponse) {
  // 置顶会话成功
  const { conversationID } = imResponse.data; // 被置顶的会话 ID
}).catch(function(imError) {
  console.warn('pinConversation error:', imError); // 置顶会话失败的相关信息
});
// 取消置顶会话,v2.14.0起支持
let promise = tim.pinConversation({ conversationID: 'C2CExample', isPinned: false });
promise.then(function(imResponse) {
  // 取消置顶会话成功
  const { conversationID } = imResponse.data; // 被取消置顶的会话 ID
}).catch(function(imError) {
  console.warn('pinConversation error:', imError); // 取消置顶会话失败的相关信息
});

删除会话

功能描述

在删除好友或退出群组后,如果不需要查看好友或群会话的历史消息,可以选择删除会话。会话删除默认关闭多端同步,可在 即时通信 IM 控制台 开启多端同步。

let promise = tim.deleteConversation('C2CExample');
promise.then(function(imResponse) {
  // 删除会话成功
  const { conversationID } = imResponse.data; // 被删除的会话 ID
}).catch(function(imError) {
  console.warn('deleteConversation error:', imError); // 删除会话失败的相关信息
});

具体建议还是打开官网进行开发 功能不难 本次记录只是方便后期相同需求开发快速迭代

chitchat.wxml

<!--pages/contact/contact.wxml-->


<custom-nav-bar backgroundColor="#000" color="#fff" isBottomBorder="{{false}}">
  <view class="nav-box">
    {{ navbarTitle }}
  </view>
</custom-nav-bar>

<view class="msg-list-box">
  <scroll-view scroll-y scroll-into-view='{{toView}}' scroll-with-animation bindscrolltoupper="bindscrolltoupperHandler" style='height: 80vh;' enable-passive bindtap="clickScrollView">
    <!-- <view class='scrollMsg'> -->
    <block wx:key="{{ index }}" wx:for='{{messageList}}'>
      <view wx:if="{{ item.showMessageTime }}" class="message-time">
        <text>{{ item.messageTime }}</text>
      </view>
      <!--(右) -->
      <view wx:if="{{ item.flow == 'out' }}" id='msg-{{index}}' class="right-msg-list-box">
        <view class="remoteAudioUrl" bindtap="innerAudioHandler" data-audio="{{ item.payload.remoteAudioUrl }}"  style="justify-content: flex-end;padding-right: 30rpx;width: {{ item.payload.second*20 }}rpx;max-width: 650rpx;min-width: 132rpx;" wx:if="{{ item.type == 'TIMSoundElem' }}">
          <text style="color: #fff;margin-right: 20rpx;">{{ item.payload.second }}''</text>
          <image src="https://tongxuecool.oss-cn-beijing.aliyuncs.com/applet-tongxuecool/im-202302281147%E8%AF%AD%E9%9F%B3%20%E6%8B%B7%E8%B4%9D%402x.png" mode="widthFix" style="width: 22rpx;" />
        </view>
        <view class='rightMsg' wx:if="{{ item.type == 'TIMTextElem' }}">{{item.payload.text}}</view>
        <image style="width: 300rpx;border-radius: 10rpx;" bindtap="getLookBigImage" data-imgurl="{{item.payload.imageInfoArray[0].imageUrl}}" mode="widthFix" wx:if="{{ item.type == 'TIMImageElem' }}" src="{{ item.payload.imageInfoArray[0].imageUrl }}"></image>
        <!-- <view wx:if="{{ item.type == 'TIMTextElem' || item.type == 'TIMSoundElem' }}" style='width: 4vw; height: 11vw; margin-right: 16rpx; display: flex; align-items: center; z-index: 9;'>
          <image style='width: 4vw;' src='https://tongxuecool.oss-cn-beijing.aliyuncs.com/applet-tongxuecool/im---%E4%B8%89%E8%A7%92%E5%BD%A2%201%20%E6%8B%B7%E8%B4%9D%207%402x.png' mode='widthFix'></image>
        </view> -->
        <view class="right-msg-list-avatar-box">
          <image class="right-msg-list-avatar" src='https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F4582899c-cff4-4363-a04f-908be3513443%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1679795943&t=da989d03216a8a1f6ad8dc989399f1c0'></image>
        </view>
      </view>
      <!-- (左) -->
      <view wx:else id='msg-{{index}}' class="left-msg-list">
        <view style='width: 70rpx; height: 70rpx;margin-right: 30rpx;'>
          <image style='width: 70rpx; height: 70rpx; border-radius: 50%;' src='https://img1.baidu.com/it/u=4131860888,2773799558&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800'></image>
        </view>
        <!-- <view wx:if="{{ item.type == 'TIMTextElem' || item.type == 'TIMSoundElem' }}" style='width: 4vw; height: 11vw; margin-left: 16rpx; display: flex; align-items: center; z-index: 9;'>
          <image style='width: 4vw;' src='https://tongxuecool.oss-cn-beijing.aliyuncs.com/applet-tongxuecool/im---%E4%B8%89%E8%A7%92%E5%BD%A2%201%20%E6%8B%B7%E8%B4%9D%206%402x.png' mode='widthFix'></image>
        </view> -->
        <view class='leftMsg' wx:if="{{ item.type == 'TIMTextElem' }}">{{item.payload.text}}</view>
        <image bindtap="getLookBigImage" data-imgurl="{{ item.payload.imageInfoArray[0].imageUrl  }}" style="width: 300rpx;border-radius: 10rpx;" mode="widthFix" wx:if="{{ item.type == 'TIMImageElem' }}" src="{{ item.payload.imageInfoArray[0].imageUrl }}"></image>
        <view class="remoteAudioUrl" bindtap="innerAudioHandler" data-audio="{{ item.payload.remoteAudioUrl }}" style="justify-content: flex-start;padding-left: 30rpx;width: {{ item.payload.second*20 }}rpx;max-width: 650rpx;min-width: 132rpx;" wx:if="{{ item.type == 'TIMSoundElem' }}">
          <image src="https://tongxuecool.oss-cn-beijing.aliyuncs.com/applet-tongxuecool/im-20230228%E8%AF%AD%E9%9F%B3%402x.png" mode="widthFix" style="width: 22rpx;" />
          <text style="color: #fff;margin-right: 20rpx;">{{ item.payload.second }}''</text>
        </view>
      </view>

    </block>
    <!-- </view> -->

    <!-- 占位 -->
    <view style='width: 100%; height: 18vw;'></view>
  </scroll-view>
  <!-- {{inputBottom}} -->
  <view class="inputRoom" style='bottom: {{ inputBottom }};height: {{ inputRoomHeight }};'>
    <view style="display: flex;align-items: center;box-sizing: border-box;padding: 20rpx;width: 100%;background-color: #000000;">
      <image style='width: 7vw;' bindtap="changeAudioHandler" data-flag="{{ true }}" wx:if="{{ !audioFlag }}" src='https://tongxuecool.oss-cn-beijing.aliyuncs.com/applet-tongxuecool/im-20230224%E8%AF%AD%E9%9F%B3%20%281%29%402x.png' mode='widthFix'></image>
      <image style='width: 7vw;' bindtap="changeAudioHandler" data-flag="{{ false }}" wx:else src='https://tongxuecool.oss-cn-beijing.aliyuncs.com/applet-tongxuecool/im-20230227%E9%94%AE%E7%9B%98%402x.png' mode='widthFix'></image>
      <input bindconfirm='sendClick' wx:if="{{ !audioFlag }}" adjust-position='{{false}}' model:value='{{inputVal}}' confirm-type='send' bindfocus='focus' bindblur='blur'></input>
      <view wx:else class="audio" bind:longpress="handleRecordStart" bind:touchmove="handleTouchMove" bind:touchend="handleRecordStop">
        <text>按住</text>
        <text>说话</text>
      </view>
      <image style='width: 7vw; margin-left: 3.2vw;' bindtap="changeEmoji" src='https://tongxuecool.oss-cn-beijing.aliyuncs.com/applet-tongxuecool/im-20230224%E8%A1%A8%E6%83%85%402x.png' mode='widthFix'></image>
      <image style='width: 7vw; margin-left: 3.2vw;' bindtap="multimediaHandler" src='https://tongxuecool.oss-cn-beijing.aliyuncs.com/applet-tongxuecool/im-20230224icon_%E6%B7%BB%E5%8A%A0%402x.png' mode='widthFix'></image>
    </view>
    <!-- 表情 -->
    <view wx:if="{{displayFlag === 'emoji'}}" class="TUI-Emoji-area">
      <Emoji bind:enterEmoji="appendMessage" />
    </view>
    <!-- 图片 -->
    <view wx:if="{{displayFlag === 'extension'}}" class="TUI-Extensions">
      <view class="TUI-Extension-slot" style="margin-left: 40rpx;" bindtap="handleSendImage">
        <view class="extension-box">
          <image class="TUI-Extension-icon" mode="widthFix" src="https://tongxuecool.oss-cn-beijing.aliyuncs.com/applet-tongxuecool/im-20230227%E6%8B%8D%E6%91%84-%E9%80%89%E4%B8%AD%402x%20%282%29.png" />
        </view>
        <view class="TUI-Extension-slot-name">照片</view>
      </view>
      <view class="TUI-Extension-slot" style="margin-left: 90rpx;" bindtap="handleSendPicture">
        <view class="extension-box">
          <image class="TUI-Extension-icon" mode="widthFix" src="https://tongxuecool.oss-cn-beijing.aliyuncs.com/applet-tongxuecool/im-20230227%E6%8B%8D%E6%91%84-%E9%80%89%E4%B8%AD%402x%20%281%29.png" />
        </view>
        <view class="TUI-Extension-slot-name">拍摄</view>
      </view>
    </view>
  </view>

  <!-- 正在录音动效 -->
  <view class="record-modal" wx:if="{{recordFlag}}" bind:longpress="handleRecordStart" bind:touchmove="handleTouchMove" bind:touchend="handleRecordStop">
    <view class="wrapper">
      <view class="modal-loading">
      </view>
    </view>
    <view class="modal-title">
      正在录音
    </view>
  </view>
</view>

chitchat.wxss

/* pages/contact/contact.wxss */

page {
  background-color: #080808;
}

.msg-list-box {
  margin-top: 150rpx;
  background-color: #080808;
}

.nav-box {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  font-size: 30rpx;
  font-family: PingFang SC;
  font-weight: 500;
  color: #F5F5F5;
}

.inputRoom {
  box-sizing: border-box;
  width: 100vw;
  background-color: #000000;
  position: fixed;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  z-index: 20;
}

input {
  /* width: 76vw; */
  /* height: 9.33vw; */
  width: 518rpx;
  height: 64rpx;
  background-color: #333333;
  border-radius: 40rpx;
  margin-left: 2vw;
  padding: 0 3vw;
  font-size: 28rpx;
  color: #e6e6e6;
}

.right-msg-list-box {
  display: flex;
  justify-content: flex-end;
  padding: 3vw 3vw 3vw 11vw;
}

.right-msg-list-avatar-box {
  width: 70rpx;
  height: 70rpx;
  margin-left: 30rpx;
}

.right-msg-list-avatar {
  width: 70rpx;
  height: 70rpx;
  border-radius: 50%;
}

.left-msg-list {
  display: flex;
  padding: 3vw 11vw 3vw 3vw;
}

.leftMsg {
  font-size: 35rpx;
  color: #E6E6E6;
  line-height: 7vw;
  padding: 2vw 2.5vw;
  background: #1F1F1F;
  /* margin-left: -1.6vw; */
  border-radius: 10rpx;
  z-index: 10;
}

.rightMsg {
  font-size: 35rpx;
  color: #E6E6E6;
  line-height: 7vw;
  padding: 2vw 2.5vw;
  background: #1F1F1F;
  /* margin-right: -1.6vw; */
  border-radius: 10rpx;
  z-index: 10;
}

/* 表情 */
.TUI-Emoji-area {
  width: 100vw;
  height: 200px;
  background-color: #000000;
  padding-bottom: 100rpx;
}

/* 多媒体 */
.TUI-Extensions {
  display: flex;
  flex-wrap: wrap;
  width: 100vw;
  height: 400rpx;
  background-color: #000000;
}

.TUI-Extension-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 48rpx;
}

.extension-box {
  width: 100rpx;
  height: 100rpx;
  background: #333333;
  border-radius: 28rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}

.TUI-Extension-icon {
  width: 51rpx;
  border-radius: 0;
}

.TUI-Extension-slot-name {
  font-size: 26rpx;
  font-family: PingFang SC;
  font-weight: 500;
  color: #B3B3B3;
  margin-top: 12rpx;
  text-align: center;
}

.message-time {
  font-size: 22rpx;
  font-family: PingFang SC;
  font-weight: 500;
  color: #CCCCCC;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 30rpx;
}

.audio {
  width: 518rpx;
  height: 64rpx;
  background-color: #333333;
  border-radius: 40rpx;
  margin-left: 2vw;
  padding: 0 3vw;
  font-size: 28rpx;
  color: #e6e6e6;
  display: flex;
  justify-content: center;
  align-items: center;
}

.audio:active {
  background-color: #5e5c5c;
}

/* 正在录音 */

.record-modal {
  height: 300rpx;
  width: 60vw;
  background-color: #333;
  opacity: 0.8;
  position: fixed;
  top: 670rpx;
  z-index: 9999;
  left: 20vw;
  border-radius: 24rpx;
  display: flex;
  flex-direction: column;
}

.record-modal .wrapper {
  display: flex;
  height: 200rpx;
  box-sizing: border-box;
  padding: 10vw;
}

.record-modal .wrapper .modal-loading {
  opacity: 1;
  width: 40rpx;
  height: 16rpx;
  border-radius: 4rpx;
  background-color: #006fff;
  animation: loading 2s cubic-bezier(0.17, 0.37, 0.43, 0.67) infinite;
}

.modal-title {
  text-align: center;
  color: #fff;
}

@keyframes loading {
  0% {
    transform: translate(0, 0)
  }

  50% {
    transform: translate(30vw, 0);
    background-color: #f5634a;
    width: 40px;
  }

  100% {
    transform: translate(0, 0);
  }
}

.remoteAudioUrl {
  box-sizing: border-box;
  height: 75rpx;
  background: #1F1F1F;
  border-radius: 10rpx;
  display: flex;
  align-items: center;
  font-size: 30rpx;
  color: #e6e6e6;
}

chitchat.js

import dayjs from './../../../../utils/dayjs'
const app = getApp();
var windowHeight = wx.getSystemInfoSync().windowHeight;
var keyHeight = 0;

/**
 * 计算msg总高度
 */
function calScrollHeight(that, keyHeight) {
  var query = wx.createSelectorQuery();
  query.select('.scrollMsg').boundingClientRect(function (rect) {}).exec();
}
const recorderManager = wx.getRecorderManager();

const innerAudioContext = wx.createInnerAudioContext({
  useWebAudioImplement: true
})

Page({

  /**
   * 页面的初始数据
   */
  data: {
    navbarTitle: "",
    audioFlag: false,
    messageTime: "",
    showMessageTime: false,
    inputRoomHeight: '16vw',
    scrollHeight: '',
    inputBottom: 0,
    toUserId: null, //被发送人的用户id
    messageList: [], //历史记录的消息列表
    displayFlag: '',
    inputVal: '',
    nextReqMessageID: null,
    isCompleted: false,
    recordFlag: false,
    recordOptions: {
      duration: 60000,
      sampleRate: 44100,
      numberOfChannels: 1,
      encodeBitRate: 192000,
      format: 'aac'
    },
  },
  changeEmoji() {
    this.setData({
      scrollHeight: '',
      inputBottom: 0,