小程序对接腾讯云IM即时聊天

步骤如下

  • 下载sdk并引入(tim-wx-sdk、cos-wx-sdk-v5)
  • 建立监听(Event.js)
  • 初始化IM
  • 登录IM
  • 监听IM各个状态钩子
  • 聊天(获取聊天记录、发送消息、接受消息、发送图片、发送自定义消息)

一:下载sdk

一:下载sdk(1)npm方式下载// IM 小程序 SDKnpm install tim-wx-sdk --save// 发送图片、文件等消息需要的 COS SDKnpm install cos-wx-sdk-v5 --save(2)直接下载js文件下载链接(https://cloud.tencent.com/document/product/269/36887)或(文章最后会提供完整代码)

二:初始化IM

  • 开发过程遇到的其中一个问题就是数据同步,应该是有很多方法的,这儿采用的是引入一个监听器,在app.js里面,将Event监听器挂载到wx对象上
  • 初始化im
  • 登录im
//app.jsimport Event from './plugin/tencentIM/event'
wx.event = new Event();import {initTIM,loginTIM}  from './plugin/im-init'App({require ($uri){return require($uri)},onLaunch() {initTIM(this.globalData);//初始化IMloginTIM(this.globalData);//登录IM},globalData: {TIM: null,TIM_INIT:false}});
//im-init.jsimport TIM from "tim-wx-sdk";//npm方式引入
import COS from "cos-wx-sdk-v5";//npm方式引入let DATA_APP = getApp() && getApp().globalData || {};
let DATA_TIM = DATA_APP.TIM || {};/*** IM初始化* @return null*/
export function initTIM(item) {let options = {SDKAppID: '这里填写你自己SDKAppID'};if(item){DATA_APP = item;}//避免重复创建im实例if (DATA_APP.TIM_INIT) {return}let DATA_TIM_READY = false;// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例DATA_TIM = TIM.create(options);// SDK 实例通常用 DATA_TIM 表示// 设置 SDK 日志输出级别,详细分级请参见 setLogLevel 接口的说明DATA_TIM.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用// DATA_TIM.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用// 注册 COS SDK 插件   此处暂时隐藏有需求要传图片,文件等的请放开进行配置,记住头部引入DATA_TIM.registerPlugin({'cos-wx-sdk': COS});// 监听事件,例如:DATA_TIM.on(TIM.EVENT.SDK_READY, function (event) {//此回调函数中发布'conversationInit'对话列表初始化事件触发页面js中的//需要注意的是DATA_TIM.getMessageList({})这个方法必须要在SDK_READY状态才能调用,所以要放在这个回调函数中wx.event.emit('conversationList');// 会话列表的监听函数wx.event.emit('conversationInit');// 聊天记录的监听函数DATA_TIM_READY = true;// 收到离线消息和会话列表同步完毕通知,接入侧可以调用 sendMessage 等需要鉴权的接口// event.name - TIM.EVENT.SDK_READY});DATA_TIM.on(TIM.EVENT.MESSAGE_RECEIVED, function (event) {console.log('收到消息');// 这里收到消息,调用setGlobalMsg方法来处理数据,传入方式标记为'received'接收消息wx.event.emit('received', event) // 会话列表的监听函数// setGlobalMsg(event,'received');// 收到推送的单聊、群聊、群提示、群系统通知的新消息,可通过遍历 event.data 获取消息列表数据并渲染到页面// event.name - TIM.EVENT.MESSAGE_RECEIVED// event.data - 存储 Message 对象的数组 - [Message]});DATA_TIM.on(TIM.EVENT.MESSAGE_REVOKED, function (event) {// 收到消息被撤回的通知// event.name - TIM.EVENT.MESSAGE_REVOKED// event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isRevoked 属性值为 true});DATA_TIM.on(TIM.EVENT.MESSAGE_READ_BY_PEER, function (event) {// SDK 收到对端已读消息的通知,即已读回执。使用前需要将 SDK 版本升级至 v2.7.0 或以上。仅支持单聊会话。// event.name - TIM.EVENT.MESSAGE_READ_BY_PEER// event.data - event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isPeerRead 属性值为 true});DATA_TIM.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, function (event) {// 收到会话列表更新通知,可通过遍历 event.data 获取会话列表数据并渲染到页面// event.name - TIM.EVENT.CONVERSATION_LIST_UPDATED// event.data - 存储 Conversation 对象的数组 - [Conversation]if(DATA_TIM_READY){wx.event.emit('conversationList') // 会话列表的监听函数}});DATA_TIM.on(TIM.EVENT.GROUP_LIST_UPDATED, function (event) {// 收到群组列表更新通知,可通过遍历 event.data 获取群组列表数据并渲染到页面// event.name - TIM.EVENT.GROUP_LIST_UPDATED// event.data - 存储 Group 对象的数组 - [Group]});DATA_TIM.on(TIM.EVENT.PROFILE_UPDATED, function (event) {// 收到自己或好友的资料变更通知// event.name - TIM.EVENT.PROFILE_UPDATED// event.data - 存储 Profile 对象的数组 - [Profile]});DATA_TIM.on(TIM.EVENT.BLACKLIST_UPDATED, function (event) {// 收到黑名单列表更新通知// event.name - TIM.EVENT.BLACKLIST_UPDATED// event.data - 存储 userID 的数组 - [userID]});DATA_TIM.on(TIM.EVENT.ERROR, function (event) {// 收到 SDK 发生错误通知,可以获取错误码和错误信息// event.name - TIM.EVENT.ERROR// event.data.code - 错误码// event.data.message - 错误信息});DATA_TIM.on(TIM.EVENT.SDK_NOT_READY, function (event) {// 收到 SDK 进入 not ready 状态通知,此时 SDK 无法正常工作// event.name - TIM.EVENT.SDK_NOT_READY});DATA_TIM.on(TIM.EVENT.KICKED_OUT, function (event) {// 收到被踢下线通知// event.name - TIM.EVENT.KICKED_OUT// event.data.type - 被踢下线的原因,例如://    - TIM.TYPES.KICKED_OUT_MULT_ACCOUNT 多实例登录被踢//    - TIM.TYPES.KICKED_OUT_MULT_DEVICE 多终端登录被踢//    - TIM.TYPES.KICKED_OUT_USERSIG_EXPIRED 签名过期被踢 (v2.4.0起支持)。});DATA_TIM.on(TIM.EVENT.NET_STATE_CHANGE, function (event) {//  网络状态发生改变(v2.5.0 起支持)。// event.name - TIM.EVENT.NET_STATE_CHANGE// event.data.state 当前网络状态,枚举值及说明如下://     \- TIM.TYPES.NET_STATE_CONNECTED - 已接入网络//     \- TIM.TYPES.NET_STATE_CONNECTING - 连接中。很可能遇到网络抖动,SDK 在重试。接入侧可根据此状态提示“当前网络不稳定”或“连接中”//    \- TIM.TYPES.NET_STATE_DISCONNECTED - 未接入网络。接入侧可根据此状态提示“当前网络不可用”。SDK 仍会继续重试,若用户网络恢复,SDK 会自动同步消息});DATA_APP.TIM_INIT = true;  //完成im实例创建后设置标志为trueDATA_APP.TIM = DATA_TIM;console.log(DATA_APP)
}/*** IM登录* @param {Object} item 数据* @param {String} item.IM_ID* @param {Date} item.IM_KEY* @return null*/
export function loginTIM(item) {if(item){DATA_TIM = item.TIM;}DATA_TIM.login({userID: '从后端获取的IM userID',userSig: '从后端获取的IM userSig'}).then((imResponse) => {console.log('IM登录成功:', imResponse);}).catch((imError) => {console.log('IM登录失败:', imError);});
}/*** IM退出* @return null*/
export function loginOutTIM(item) {if(item){DATA_APP = item;}DATA_TIM.logout().then((imResponse) => {console.log('IM退出成功:', imError);}).catch((imError) => {console.log('IM退出失败:', imError);});
}
//Event.jsclass Event {/*** on 方法把订阅者所想要订阅的事件及相应的回调函数记录在 Event 对象的 _cbs 属性中*/on(event, fn) {if (typeof fn != "function") {console.error('fn must be a function')return}this._cbs = this._cbs || {};(this._cbs[event] = this._cbs[event] || []).push(fn)}/*** emit 方法接受一个事件名称参数,在 Event 对象的 _cbs 属性中取出对应的数组,并逐个执行里面的回调函数*/emit(event) {this._cbs = this._cbs || {}var callbacks = this._cbs[event], argsif (callbacks) {callbacks = callbacks.slice(0)args = [].slice.call(arguments, 1)for (var i = 0, len = callbacks.length; i < len; i++) {callbacks[i].apply(null, args)}}}/*** off 方法接受事件名称和当初注册的回调函数作参数,在 Event 对象的 _cbs 属性中删除对应的回调函数。*/off(event, fn) {this._cbs = this._cbs || {}// allif (!arguments.length) {this._cbs = {}return}var callbacks = this._cbs[event]if (!callbacks) return// remove all handlersif (arguments.length === 1) {delete this._cbs[event]return}// remove specific handlervar cbfor (var i = 0, len = callbacks.length; i < len; i++) {cb = callbacks[i]if (cb === fn || cb.fn === fn) {callbacks.splice(i, 1)break}}return}
}
export default Event

三:一对一聊天

(1)index.wxml(图片部分自行补充)


<view class="chat-area"><scroll-view scroll-into-view="{{ colToView }}" scroll-y="true" bindscrolltoupper="onLoadMore" bindtap="onHideSendMore"><view class="loader-wrap" wx:if="{{showLoading}}" ><text class="loader"></text></view><block wx:for="{{ arrMsg }}" wx:key="index"><view class="{{ item.from === colUserId?'':'chat-his'}}"><view wx:if="{{item.type == 'TIMImageElem'}}" class="chat-row flex-box-end" id="msg-{{index}}"><view class="chat-img"><image wx:if="{{item.status=='success'}}" class="chat-pic" mode="heightFix" lazy-load="{{true}}" src="{{item.payload.imageInfoArray[0].url}}" bindtap="previewImage" data-url="{{item.payload.imageInfoArray[2].url}}"></image><image wx:elif="{{item.status=='fail'}}" class="chat-pic" mode="heightFix" lazy-load="{{true}}" src="{{item.sendPic}}" data-url="{{item.payload.imageInfoArray[2].url}}"><view class="chat-progress">发送失败</view></image><image wx:else class="chat-pic" mode="heightFix" lazy-load="{{true}}" src="{{item.sendPic}}" data-url="{{item.payload.imageInfoArray[2].url}}"><view class="chat-progress"><text class="loader"></text><text>{{colPercent}}%</text></view></image></view><view class="chat-head"><image class="chat-headPortrait" src="/images/pic_1.png"></image></view></view><view wx:elif="{{item.type == 'TIMCustomElem'}}" class="chat-row flex-box-end" id="msg-{{index}}"><view class="chat-main"><view class="chat-msg chat-custom"><view class="row">{{item.dataCustom.name}}就诊信息</view><view class="row"><text class="item">{{item.dataCustom.sex}}</text><text class="item">{{item.dataCustom.age}}</text><text class="item">{{item.dataCustom.height}}</text><text class="item">{{item.dataCustom.weight}}</text></view><view class="row"><view class="row-left">病情描述:</view><view class="row-right">{{item.dataCustom.desc}}</view></view><view class="row"><view class="row-left">患病时长:</view><view class="row-right">{{item.dataCustom.descTime||'未知'}}</view></view><view class="row"><view class="row-left">病史:</view><view class="row-right">{{item.dataCustom.history||'暂无'}}</view></view><view class="row"><view class="row-left">过敏史:</view><view class="row-right">{{item.dataCustom.allergy||'无'}}</view></view></view><view class="chat-time">{{ item.timeFormat }}</view></view><view class="chat-head"><image class="chat-headPortrait" src="/images/pic_1.png"></image></view></view><view wx:else class="chat-row flex-box-end" id="msg-{{index}}"><view class="chat-main"><!--  <view class="left-chat-name">{{ item.from }}</view>--><view class="chat-msg">{{ item.payload.text }}</view><view class="chat-time">{{ item.timeFormat }}</view></view><view class="chat-head"><image class="chat-headPortrait" src="/images/pic_1.png"></image></view></view></view></block></scroll-view><view class="chat-footer"><view class="chat-input-box"><input bindinput='onInputMsg' bindconfirm='TIM_createMsg' value="{{colSendMsg}}" placeholder='输入内容' class="input" cursor-spacing="20"></input><view class='footer-send' bindtap='onShowSendMore'>更多</view></view><view class="open-more" wx:if="{{showSendMore}}"><view class="open-more-item" bindtap="TIM_createPhoto" data-name="album"><image src="/images/im-img.png" mode="widthFix" class="msg-img"></image><view class="msg-text">相册</view></view><view class="open-more-item" bindtap="TIM_createPhoto" data-name="camera"><image src="/images/im-photo.png" class="msg-img" mode="widthFix"></image><view class="msg-text">拍摄</view></view><view class="open-more-item" bindtap="TIM_createMsgCustom" data-name="camera"><image src="/images/im-edit.png" class="msg-img" mode="widthFix"></image><view class="msg-text">自定义消息</view></view></view></view>
</view>

(2)index.wxss


view,text,image{box-sizing: border-box;
}.flex-box-start{display: flex;justify-content: start;
}.flex-box-end{display: flex;justify-content: flex-end;
}.chat-area{width: 100%;height: calc(100vh - 120rpx);background-color: #f9f9f9;font-weight: 400;/*padding-bottom: 140rpx;*/
}.chat-area > scroll-view{position: relative;height: 100%;padding: 20rpx 20rpx 10rpx 20rpx;box-sizing: border-box;
}.chat-his{}.chat-his .flex-box-end{flex-direction: row-reverse;justify-content: flex-start!important;
}.chat-his .chat-main{align-items: flex-start!important;
}.chat-his .chat-msg{background: #ffffff!important;color: #000000;
}.chat-his .chat-msg:before{content: '';position: absolute;width: 0;height: 0;border-width: 14rpx 20rpx;border-style: solid;border-color: transparent white transparent transparent;left: -40rpx;top: 30rpx;
}.chat-his .chat-msg:after{display: none;
}.chat-his .chat-head{margin-right: 30rpx;margin-left: 0!important;
}.chat-his .chat-img{justify-content: flex-start!important;
}.chat-his .chat-custom .item:after{background: #000000!important;
}.chat-headPortrait{width: 100%;height: 100%;border-radius: 50%;
}.chat-head{width: 100rpx;height: 100rpx;margin-left: 30rpx;flex: none;
}.chat-end{display: flex;align-items: center;justify-content: center;font-size: 24rpx;color: #8B8B8B;margin-bottom: 40rpx;
}.chat-main{width: 100%;display: flex;flex-direction: column;align-items: flex-end;
}.chat-row{margin: 30rpx 0;
}.chat-name{font-size: 26rpx;color: #7C7C7C;padding-left: 20rpx;margin-bottom: 10rpx;
}.chat-time{font-size: 24rpx;color: #b7b7b7;padding-left: 12rpx;margin-top: 16rpx;
}.chat-msg{display: inline-block;position: relative;max-width: calc(100% - 100rpx);background-color: #0093A2;padding: 26rpx 30rpx;border-radius: 10rpx;font-size: 28rpx;word-wrap: break-word;color: #FEFEFE;margin-left: 6rpx;/*font-weight: bold;*/min-height: 90rpx;
}.chat-msg:after{content: '';position: absolute;width: 0;height: 0;border-width: 14rpx 20rpx;border-style: solid;border-color: transparent transparent transparent #0093A2;right: -40rpx;top: 30rpx;
}.chat-custom{}.chat-custom .row{display: flex;width: 100%;margin: 10rpx 0;
}.chat-custom .row-left{width: 150rpx;flex: none;
}.chat-custom .row-right{flex: auto;white-space: initial;
}.chat-custom .row .item{position: relative;margin-right: 32rpx;
}.chat-custom .item:after{content: '';width: 2rpx;height: 30rpx;background: #ffffff;position: absolute;right: -16rpx;top: 50%;transform: translateY(-50%);
}.chat-custom .row .item:last-child:after{width: 0;
}.btn-wrap{display: flex;flex-direction: column;align-items: center;
}.btn-wrap .item{width: 80%;display: flex;align-items: center;justify-content: center;height: 100rpx;margin: 20rpx 0;border-radius: 20rpx;background: dodgerblue;color: white;font-size: 40rpx;font-weight: bold;z-index: 9999;
}/* 图片消息 */
.chat-img{width: 100%;margin: 30rpx 0;display: flex;flex-grow: 1;justify-content: flex-end;
}.chat-pic {max-width: 360rpx;height: 360rpx;background-repeat: no-repeat;background-size: center;background-position: center;border-radius: 4rpx;position: relative;
}.chat-progress{position: absolute;left: 0;right: 0;top: 0;bottom: 0;margin: auto;display: flex;flex-direction: column;justify-content: center;align-items: center;background-color: rgba(29, 29, 29, 0.548);color: #fff;
}@keyframes loader {0% {-webkit-transform:rotate(0deg);transform:rotate(0deg);}100% {-webkit-transform:rotate(360deg);transform:rotate(360deg);}
}.loader {border-top:8rpx solid rgba(0,0,0,0.1);border-right:8rpx solid rgba(0,0,0,0.1);border-bottom:8rpx solid rgba(0,0,0,0.1);border-left:8rpx solid #555;transform:translateZ(0);animation:loader 600ms infinite linear;transition:all 500ms ease;opacity:1;
}.loader,.loader:after {border-radius:50%;width:40rpx;height:40rpx;
}/* 底部样式 */
.chat-footer{position: fixed;bottom: 0;left: 0;width: 100%;background:rgba(248,248,248,1);box-sizing: border-box;
}.chat-input-box{display: flex;justify-content: space-between;align-items: center;background: #ffffff;padding: 20rpx 25rpx;
}.chat-wait{display: flex;align-items: center;justify-content: center;height: 120rpx;background: #ffffff;font-size: 26rpx;
}.msg-icon{width: 58rpx;height: 58rpx;
}.chat-input-box .input{height:76rpx;line-height: 76rpx;background:rgba(255,255,255,1);border: none;border-radius:6rpx;font-size: 30rpx;padding:0 30rpx;display: flex;flex-direction: row;align-items: center;position: relative;flex-grow: 1;background: #F1F1F1;
}.inputArea{width: 100%;height: 98%;flex-grow: 1;
}
.placeHolder{position: absolute;font-size: 26rpx;color: #cccccc;height: 100%;box-sizing: border-box;top: 0;z-index: 0;
}
.footer-send{height: 76rpx;border-radius: 12rpx;display: flex;justify-content: center;align-items: center;font-size: 26rpx;margin-left: 20rpx;padding: 0 10rpx;
}
.footer-send-item{font-size: 60rpx;font-weight: bold;
}
.footer-h{position: fixed;top: 100px;
}
.more{display: flex;justify-content: center;align-items: center;
}
.more-text{padding: 6rpx 14rpx;background:rgba(216,216,216,1);border-radius:4rpx;color: #FFFFFF;font-size: 20rpx;margin: 30rpx auto;
}.open-more{display: flex;flex-wrap: wrap;padding: 40rpx 0;min-height: 360rpx;
}.open-more-item{flex-basis: 25%;display: flex;flex-direction: column;align-items: center;justify-items: center;
}.open-more-item .msg-img{width: 100rpx;height: 100rpx;margin-bottom: 16rpx;
}.open-more-item .msg-text{font-size: 28rpx;color: #888888;
}.loader-wrap {display: flex;align-items: center;justify-content: center;height: 80rpx;width: 100%;opacity:1;z-index:99;color: #b7b7b7;font-size: 28rpx;
}.loader-tip{background: #E7E7E7;display: flex;align-items: center;justify-content: center;color: #8B8B8B;padding:20rpx 30rpx;font-size: 24rpx;border-radius: 6rpx;
}.loader {border-top:8rpx solid rgba(0,0,0,0.1);border-right:8rpx solid rgba(0,0,0,0.1);border-bottom:8rpx solid rgba(0,0,0,0.1);border-left:8rpx solid #555;transform:translateZ(0);animation:loader 600ms infinite linear;transition:all 500ms ease;opacity:1;
}.loader,.loader:after {border-radius:50%;width:40rpx;height:40rpx;
}@keyframes loader {0% {-webkit-transform:rotate(0deg);transform:rotate(0deg);}100% {-webkit-transform:rotate(360deg);transform:rotate(360deg);}
}.z-btn-wrap{display: flex;align-items: center;justify-content: center;height: 120rpx;background: #ffffff;
}.z-btn{background: #06CAD8;color: #ffffff;display: flex;justify-content: center;align-items: center;padding: 24rpx 40rpx;font-size: 32rpx;font-weight: 500;border-radius: 10rpx;min-width: 400rpx;
}

(3)index.js

import TIM from "tim-wx-sdk";const {getDatePattern,isJSON} = getApp().require('utils/util');let DATA_APP = getApp() && getApp().globalData || {};
let DATA_TIM = DATA_APP.TIM || {};
let TIM_MSG = [];Page({data: {colToView: '',colUserId: '自己的IM userID',colUserOtherId: '对方的IM userID',colSendMsg: '',colPercent: 0,pageLastLength: 1,pageNext: '',pageCompleted: '',showSendMore: false,showLoading: false,showThree: false,showEnd: false,arrMsg: [],arrImg: [],},onLoad(options) {this.TIM_getMsgList();//订阅初始化获取聊天记录wx.event.on('conversationInit', () => {this.TIM_getMsgList();});//订阅收到消息wx.event.on('received', (e) => {this.TIM_setGlobalMsg(e,'received');});},//im获取消息、打开某个会话时,第一次拉取消息列表TIM_getMsgList() {this.onShowLoading();let param = {conversationID: 'C2C' + this.data.colUserOtherId,count: 15,nextReqMessageID: this.data.pageNext};let promise = DATA_TIM.getMessageList(param);promise.then((imResponse) => {this.TIM_setGlobalMsg(imResponse, 'load', true);});},//im获取消息、打开某个会话时,第一次拉取消息列表TIM_getMsgListMore() {this.onShowLoading();let param = {conversationID: 'C2C' + this.data.colUserOtherId,count: 15,nextReqMessageID: this.data.pageNext};let promise = DATA_TIM.getMessageList(param);promise.then((imResponse) => {this.TIM_setGlobalMsg(imResponse, 'load');});},//im创建文本消息TIM_createMsg() {let param = {to: this.data.colUserOtherId,conversationType: TIM.TYPES.CONV_C2C,payload: {text: this.data.colSendMsg}};let message = DATA_TIM.createTextMessage(param);this.TIM_sendMessageFun(message);this.onClearInput();},//im创建自定义消息TIM_createMsgCustom(msg) {let paramText = {name:'名字',sex:'男',age:'27',weight:'60kg',height:'171cm',desc:'长期肥胖,需要减肥',descTime:'一年',history:'暂无',allergy:'无',type:'describe'};let param = {to: this.data.colUserOtherId,conversationType: TIM.TYPES.CONV_C2C,payload: {data: JSON.stringify(paramText), // 用于标识该消息是骰子类型消息description: '描述主题', // 获取骰子点数extension: '描述说明'}};let message = DATA_TIM.createCustomMessage(param);this.TIM_sendMessageFun(message);},// im创建图片- 选择图片TIM_createPhoto(e) {let that = this;let name = e.currentTarget.dataset.name;if (name === 'album') {that.TIM_createPhotoNow(name)} else if (name === 'camera') {wx.getSetting({success: function (res) {if (!res.authSetting['scope.camera']) { // 无权限,跳转设置权限页面wx.authorize({scope: 'scope.camera',success: function () {that.TIM_createPhotoNow(name)}})} else {that.TIM_createPhotoNow(name)}}})}},// im创建图片- 创建完成TIM_createPhotoNow(name) {let that = this;let colUserId = this.data.colUserId;wx.chooseImage({sourceType: [name],count: 1,success: (res) => {// 在发送之前先push进去一张图片let messageList = that.data.arrMsg;let data = {type: 'TIMImageElem',send: true,from: colUserId,showSendMore: res.tempFilePaths[0]};messageList.push(data);that.setData({arrMsg: messageList});that.onHideSendMore();that.pageScrollToBottom(true);// 2. 创建消息实例,接口返回的实例可以上屏let message = DATA_TIM.createImageMessage({to: that.data.colUserOtherId, // 消息的接收方,conversationType: TIM.TYPES.CONV_C2C,payload: {file: res},onProgress: (event) => {event = event || 0;that.setData({colPercent: event * 100})}});that.TIM_sendMessageFun(message,'TIMImageElem')}})},//im发送-处理TIM_sendMessageFun(message, type) {DATA_TIM.sendMessage(message).then((imResponse) => {// 发送成功if (type === 'TIMImageElem') {let messageList = this.data.arrMsg;messageList.pop();this.setData({arrMsg: messageList})}this.TIM_setGlobalMsg(imResponse, 'send');this.onHideSendMore();this.onClearInput();}).catch((imError) => {console.warn('发送失败:', imError);})},//im处理数据TIM_setGlobalMsg(imResponse, type, loadFirst) {console.log('消息列表',imResponse);if (type === 'send'||type === 'received') {let data = {};if(type === 'received'){data = imResponse.data[0];// this.setData({//     showThree:false,// })}else {data = imResponse.data.message||{};}let arrMsg = this.data.arrMsg;let arrImg = this.data.arrImg;if (data.type === 'TIMImageElem') {arrImg.push(data.payload.imageInfoArray[0].url);}if(data.type === 'TIMCustomElem') {data.dataCustom = isJSON(data.payload.data)? JSON.parse(data.payload.data):{};}data.timeFormat = getDatePattern(new Date(data.time * 1000), 'yyyy-MM-dd HH:mm');arrMsg.push(data);this.setData({arrMsg: arrMsg,arrImg: arrImg,}, () => {this.pageScrollToBottom(true)});}else {let data = imResponse.data||{};let arrData = data.messageList || [];let arrImg = [];arrData = arrData.map(x => {if (x.type === 'TIMImageElem') {arrImg.push(x.payload.imageInfoArray[0].url);}if(x.type === 'TIMCustomElem') {x.dataCustom = isJSON(x.payload.data)? JSON.parse(x.payload.data):{};}x.timeFormat = getDatePattern(new Date(x.time * 1000), 'yyyy-MM-dd HH:mm')return x});arrImg = arrImg.concat(this.data.arrImg);TIM_MSG = arrData.concat(this.data.arrMsg);// 全局消息列表this.setData({'arrMsg': TIM_MSG,'arrImg': arrImg,'pageNext': data.nextReqMessageID,// 用于续拉,分页续拉时需传入该字段。'pageCompleted': data.isCompleted,// 表示是否已经拉完所有消息。'pageLastLength':arrData.length//用户定位滚动位置}, () => {this.onHideLoading();this.pageScrollToBottom(loadFirst)});}},//实时更新输入框的数据onInputMsg(e) {this.setData({'colSendMsg': e.detail.value})},onClearInput() {this.setData({'colSendMsg': ''})},//显示加载框onShowLoading() {this.setData({'showLoading': true});},//隐藏加载框onHideLoading() {this.setData({'showLoading': false});},// 点更多出现图片和相册onShowSendMore() {this.setData({showSendMore: true})},// 点击屏幕 发消息更多的弹框下去onHideSendMore() {this.setData({showSendMore: false})},// 预览previewImage(e) {let url = e.currentTarget.dataset.url;wx.previewImage({current: url, // 当前显示图片的http链接urls: this.data.arrImg})},//滚动到页面底部pageScrollToBottom(isBottom) {let index = null;if (isBottom) {index = 'msg-' + (this.data.arrMsg.length - 1);} else {index = 'msg-' + 0;}this.setData({colToView: index})},//加载更多onLoadMore() {if (!this.data.pageCompleted) {this.TIM_getMsgListMore()}},});

四:资料

  • 以上所有文件附上(链接:https://pan.baidu.com/s/1hJkXUfaeoY5Y0O6ceQeLYw 提取码:x4h6 )
  • 腾讯云IM官网
  • 腾讯云IM技术文档
  • 参考博客1
  • 参考博客2

五:我的项目部分截图


小程序对接腾讯云IM即时聊天相关推荐

  1. 微信小程序接入腾讯云IM即时通讯(获取聊天历史记录开发步骤)

    微信小程序接入腾讯云IM即时通讯(获取聊天历史记录开发步骤) 1.先看文档: 获取 C2C 历史消息 :https://cloud.tencent.com/document/product/269/1 ...

  2. 微信小程序利用腾讯云IM发送语音 + 图片

    微信小程序利用腾讯云IM发送语音 + 图片 能做到这里 说明你已经可以发送普通文本了 如果没有的话可以看一下我的上一篇文章 有完整的讲解 效果图 语音聊天 发送图片 传送 → 发送图片 发送语音 ** ...

  3. 【小程序】微信小程序使用腾讯云IM(一):登录

    微信小程序使用腾讯云IM 新项目已经写了很久啦 这个项目里主要的难点其实是1v1聊天.他们对比了好几家的即时通讯,最后选择了腾讯云通信.我猜,可能是因为腾讯云上说日活低于10w可以不付费吧.省钱嘛~踩 ...

  4. 微信小程序基于腾讯云对象存储的图片上传

    在使用腾讯云对象存储之前,公司一直使用的是传统的FTP的上传模式,而随着用户量的不断增加,FTP所暴露出来的问题也越来越多,1.传输效率低,上传速度慢.2.时常有上传其他文件来攻击服务器,安全上得不到 ...

  5. 微信小程序授权腾讯云

    前言: 如果之前没有授权过腾讯云,现在在开发者工具页面已经没有腾讯云选项,只有一个腾讯位置服务. 在开发者工具里面也没有腾讯云按钮(我这是己经授权才出现的,之前并没有) 但是目前的项目并不想使用云开发 ...

  6. 微信小程序实现腾讯云接口 图象识别

    微信小程序实现腾讯云接口 图象识别 注:操作环境:springboot+微信小程序 1.导入maven 腾讯云图象识别接口 jar包 <!-- 腾讯云文字识别接口--><depend ...

  7. 微信小程序开通腾讯云开发环境

    目录 微信小程序开通"腾讯云"开发环境 注册腾讯云账号 配置开发环境 微信小程序开通"腾讯云"开发环境 这里强调以下,标题是"腾讯云"开发环 ...

  8. 小程序引入腾讯IM实现即时通讯

    记录一下小程序引入腾讯第三方SDK包 实现即时通讯功能,就是常见的客服聊天功能, 腾讯IM官方文档 踩坑开发完整个项目,当初碰到问题时,网上可参考的信息几乎为零,马马虎虎整理一下 希望对大家有所帮助. ...

  9. 微信小程序集成腾讯云即时通信IM

    这里写自定义目录标题 腾讯云即时通信IM 新的改变 功能快捷键 合理的创建标题,有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适合你的列表 创建一个表格 设定 ...

  10. 微信小程序集成腾讯云 IM SDK

    1.背景 因业务功能需求需要接入IM(即时聊天)功能,一开始想到的是使用 WebSocket 来实现这个功能,然天意捉弄(哈哈)服务器版本太低不支持 wx 协议(也就不支持 WebSocket了)不得 ...

最新文章

  1. 浙大吴飞「舌战」阿里贾扬清:AI内卷与年薪百万,哪个才是真实?
  2. C++ Primer 5th笔记(chap 16 模板和泛型编程)模板特例化
  3. JUC多线程:JMM内存模型与volatile内存语义
  4. [深度学习基础] 4. 卷积神经网络
  5. 自定义的注解校验器的实现
  6. 网络技术学习资料分享
  7. 优化级别linux gcc,c - 有多少GCC优化级别?
  8. (3)zynq FPGA AXI4_Stream总线介绍
  9. 斐波那契 —— 矩阵形式推导
  10. Python在线 基础教程
  11. 整理总结:深入浅出统计学 —— 卡方分布
  12. 基于HLW8112的直流测量原理及校准方法
  13. win32-字体名称中文名和英文名的对照-c++
  14. kudu底层存储引擎的数据组织方式
  15. 根据生日自动计算年龄
  16. ios 发光字体文字的实现
  17. 关于组装电脑注意事项
  18. 二台电脑之间数据库文件进行备份
  19. Spring Boot 集成Quartz
  20. 中创专利|中国5G标准必要专利达1.8万项,尊重知识产权,共建知识产权强国

热门文章

  1. 微信公众号网页开发逻辑梳理
  2. 方舟手游机服务器修改,方舟生存进化私服怎么设置 方舟手游私服设置教程
  3. 谷歌浏览器如何在不登录的情况下保存书签
  4. [lua]紫猫lua教程-命令宝典-L1-01-07. table表
  5. Python调用有道智云文本翻译API接口实现“智能”伪原创
  6. word文档怎么转换成jpg格式图片
  7. 正则表达式中的?表示匹配前面的正则表达式0次或者1次
  8. python 查找字符第一次出现位置_python 字符串第n次出现的位置 | 学步园
  9. 笔记本电脑BIOS和硬盘加密密码设置方法
  10. error LNK1123: failure during conversion to COFF: file invalid or corrupt