小程序对接腾讯云IM即时聊天
小程序对接腾讯云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即时聊天相关推荐
- 微信小程序接入腾讯云IM即时通讯(获取聊天历史记录开发步骤)
微信小程序接入腾讯云IM即时通讯(获取聊天历史记录开发步骤) 1.先看文档: 获取 C2C 历史消息 :https://cloud.tencent.com/document/product/269/1 ...
- 微信小程序利用腾讯云IM发送语音 + 图片
微信小程序利用腾讯云IM发送语音 + 图片 能做到这里 说明你已经可以发送普通文本了 如果没有的话可以看一下我的上一篇文章 有完整的讲解 效果图 语音聊天 发送图片 传送 → 发送图片 发送语音 ** ...
- 【小程序】微信小程序使用腾讯云IM(一):登录
微信小程序使用腾讯云IM 新项目已经写了很久啦 这个项目里主要的难点其实是1v1聊天.他们对比了好几家的即时通讯,最后选择了腾讯云通信.我猜,可能是因为腾讯云上说日活低于10w可以不付费吧.省钱嘛~踩 ...
- 微信小程序基于腾讯云对象存储的图片上传
在使用腾讯云对象存储之前,公司一直使用的是传统的FTP的上传模式,而随着用户量的不断增加,FTP所暴露出来的问题也越来越多,1.传输效率低,上传速度慢.2.时常有上传其他文件来攻击服务器,安全上得不到 ...
- 微信小程序授权腾讯云
前言: 如果之前没有授权过腾讯云,现在在开发者工具页面已经没有腾讯云选项,只有一个腾讯位置服务. 在开发者工具里面也没有腾讯云按钮(我这是己经授权才出现的,之前并没有) 但是目前的项目并不想使用云开发 ...
- 微信小程序实现腾讯云接口 图象识别
微信小程序实现腾讯云接口 图象识别 注:操作环境:springboot+微信小程序 1.导入maven 腾讯云图象识别接口 jar包 <!-- 腾讯云文字识别接口--><depend ...
- 微信小程序开通腾讯云开发环境
目录 微信小程序开通"腾讯云"开发环境 注册腾讯云账号 配置开发环境 微信小程序开通"腾讯云"开发环境 这里强调以下,标题是"腾讯云"开发环 ...
- 小程序引入腾讯IM实现即时通讯
记录一下小程序引入腾讯第三方SDK包 实现即时通讯功能,就是常见的客服聊天功能, 腾讯IM官方文档 踩坑开发完整个项目,当初碰到问题时,网上可参考的信息几乎为零,马马虎虎整理一下 希望对大家有所帮助. ...
- 微信小程序集成腾讯云即时通信IM
这里写自定义目录标题 腾讯云即时通信IM 新的改变 功能快捷键 合理的创建标题,有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适合你的列表 创建一个表格 设定 ...
- 微信小程序集成腾讯云 IM SDK
1.背景 因业务功能需求需要接入IM(即时聊天)功能,一开始想到的是使用 WebSocket 来实现这个功能,然天意捉弄(哈哈)服务器版本太低不支持 wx 协议(也就不支持 WebSocket了)不得 ...
最新文章
- 浙大吴飞「舌战」阿里贾扬清:AI内卷与年薪百万,哪个才是真实?
- C++ Primer 5th笔记(chap 16 模板和泛型编程)模板特例化
- JUC多线程:JMM内存模型与volatile内存语义
- [深度学习基础] 4. 卷积神经网络
- 自定义的注解校验器的实现
- 网络技术学习资料分享
- 优化级别linux gcc,c - 有多少GCC优化级别?
- (3)zynq FPGA AXI4_Stream总线介绍
- 斐波那契 —— 矩阵形式推导
- Python在线 基础教程
- 整理总结:深入浅出统计学 —— 卡方分布
- 基于HLW8112的直流测量原理及校准方法
- win32-字体名称中文名和英文名的对照-c++
- kudu底层存储引擎的数据组织方式
- 根据生日自动计算年龄
- ios 发光字体文字的实现
- 关于组装电脑注意事项
- 二台电脑之间数据库文件进行备份
- Spring Boot 集成Quartz
- 中创专利|中国5G标准必要专利达1.8万项,尊重知识产权,共建知识产权强国
热门文章
- 微信公众号网页开发逻辑梳理
- 方舟手游机服务器修改,方舟生存进化私服怎么设置 方舟手游私服设置教程
- 谷歌浏览器如何在不登录的情况下保存书签
- [lua]紫猫lua教程-命令宝典-L1-01-07. table表
- Python调用有道智云文本翻译API接口实现“智能”伪原创
- word文档怎么转换成jpg格式图片
- 正则表达式中的?表示匹配前面的正则表达式0次或者1次
- python 查找字符第一次出现位置_python 字符串第n次出现的位置 | 学步园
- 笔记本电脑BIOS和硬盘加密密码设置方法
- error LNK1123: failure during conversion to COFF: file invalid or corrupt