微信小程序接入腾讯云IM即时通讯(聊天窗口)
1.效果图:
- 2.功能点 :
1.布局要分左右两边布局,如果是自己为发送消息方,都在右边,对方发送的消息在左边。
2.腾讯云返回的是时间戳,需要转换一下时间,腾讯云是没有返回头像的,需要单独获取并且设置自己跟对方的头像。
3.发送的消息分为自定义消息跟普通文本消息,带房源图片 跟价格和小区名称的是自定义的消息,从房源详情进入聊天就自动发送,普通文本消息则在底部栏发送。
4.获取聊天的历史记录,下拉上翻历史记录,这里没有做本地缓存,是做了每次进入都拉取一次聊天的历史记录的操作。
WXML代码
<scroll-view class='chat' id="chat" style="height:{{height}}px;" scroll-y style='padding-bottom:49px;' ><block wx:for="{{myMessages}}" wx:key="{{index}}"><view class='chat-time' wx:if="{{item.time != ''}}">{{item.msgTime}}</view><view class="chat-item flex-wrap {{item.isSelfSend ? 'house' : ''}}" wx:if='{{item.type != ""}}' bindtap='linkDetail' data-id="{{item.id}}" data-type="{{item.type}}"><view class='avatar'><image style="width:40px;height:40px;border-radius:50%;" mode= "scaleToFill" src="{{item.avatar}}"></image></view><view class='content ' style="width:520rpx;"><image class='img' style="width:100%;height:120px;" mode= "scaleToFill" src="{{item.img == '' ? houseDefault : item.img}}"></image><view class='info'><view class='info-name'>{{item.name}}</view><view class='info-title'>{{item.msgContent}}</view><view class='flex-wrap'><view class='flex-item3'><view class='info-price'>{{item.price}}</view></view><view class='flex-item'><view class='info-type'>{{item.type}}</view></view></view></view></view></view><view class="chat-item flex-wrap {{item.isSelfSend ? 's' : ''}}" wx:if='{{item.type == ""}}'><view class='avatar'><image style="width:40px;height:40px;border-radius:50%;" mode= "scaleToFill" src="{{item.avatar}}"></image></view><view class='content '>{{item.msgContent}}</view></view></block>
</scroll-view><view class='footer-h'></view>
<view class='chat-footer flex-wrap'><view class='flex-item ' bindtap='send1'> <text class="iconfont icon-yuyin" style='vertical-align: 0;padding-right:0; '></text></view><view class='flex-item5'><input class='input' bindinput="bindKeyInput" value="{{inputValue}}" placeholder="对ta发送消息"/></view><view class='flex-item2 send' bindtap='bindConfirm'>发送</view>
</view>
WXSS代码
.flex-wrap.s ,.house{flex-direction:row-reverse;}
.h49{width: 100%;height: 49px;
}
.chat-item.flex-wrap.s{margin: 20px 10px 20px 0px;}
.chat-item.flex-wrap{line-height: 20px;height: auto;margin: 20px 0px 20px 10px;}
.chat-footer{position: fixed;bottom: 0;left: 0;width: 100%;height: 49px;background: #ffffff;
}
.send{width: 100%;height: 49px;line-height: 49px;text-align: center;background: #69BEFF;color: #ffffff;font-size: 16px;
}
.icon-yuyin::before{font-size: 70rpx;color: #7F8389;display: block;height: 49px;line-height: 49px;text-align: center;
}
.input{height: 49px;line-height: 49px;font-size: 13px;
}
.avatar{width: 40px;height: 40px;background: #69BEFF;border-radius:50%;text-align: center;line-height: 40px;color: #ffffff;
}
.chat-item.flex-wrap .content{background: #ffffff;margin-left: 10px;padding:12px;border-radius:10px; width: auto;max-width: 480rpx;font-size: 15px;text-align: justify;
}
.chat-item.flex-wrap.house{margin-right: 10px;
}.chat-item.flex-wrap.s .content{margin-right: 10px;background: #69BEFF;color: #ffffff;
}
.chat-item.flex-wrap.house .content{margin-right: 10px;padding: 0;width: 520rpx;}
.content .img{border-top-left-radius: 10px;border-top-right-radius: 10px;
}
.chat-time{width: 80px;height: 21px;line-height: 21px;background: #CECECE;color: #ffffff;font-size: 12px;margin: 20px auto 0px;text-align: center;border-radius:5px;}
.content .info{padding:0 20rpx 20rpx;
}
.info-price{color: #E93D26;font-size: 14px;
}
.info-title{color: #999999;font-size: 12px;
}
.info-type{width: 50px;height: 18px;line-height: 18px;color: #ffffff;font-size: 12px;background: #CECECE;text-align: center;border-radius: 2px;}
.footer-h{height: 49px;width: 100%;
}
js代码
var webim = require('../../utils/webim.js');
var webimhandler = require('../../utils/webim_handler.js');
const app = getApp()
Page({/*** 页面的初始数据*/data: {noData: app.data.imageUrl + '/no-msg.png',houseDefault: app.data.imageUrl + '/msg-default.png',inputValue:'',//发送的文字消息内容myMessages: [],//消息selToID:0,scrollTop: 0,houseId:'',//房源idtype:'',//房源类型height:'',complete:0,//默认为有历史记录可以拉取is_lock:true//发送消息锁},/*** 生命周期函数--监听页面加载*/onLoad: function (options) {var that = this;that.setData({height: wx.getSystemInfoSync().windowHeight})if(options){if(options.id){//设置会话列表传参过来的为好友idthat.setData({selToID: options.id})wx.setNavigationBarTitle({title: options.name})}else if (!options.dockingname){//非经纪人角色,私聊账号为推荐经纪人账号that.setData({selToID: app.data.userInfo.agent_member_id.toString(),houseId: options.houseid,type:options.type})wx.setNavigationBarTitle({title: '置业顾问' + app.data.userInfo.agent_name})//拉取所需要自定义的消息数据发送that.createhousemsg();}else{that.setData({selToID: options.agent_member_id ,houseId: options.houseid,type: options.type})wx.setNavigationBarTitle({title: '盘方顾问' + options.dockingname})//拉取所需要自定义的消息数据发送that.createhousemsg();}}},onShow:function () {var that = this; wx.setStorageSync('msgKey', '')wx.setStorageSync('lastMsgTime', '')webimhandler.init({accountMode: app.data.Config.accountMode, accountType: app.data.Config.accountType, sdkAppID: app.data.Config.sdkappid, selType: webim.SESSION_TYPE.C2C//私聊, agent_member_id: app.data.userInfo.id, id: that.data.selToID , name: app.data.userInfo.agent_name, icon: app.data.userInfo.agent_pic,that: that});if (webim.checkLogin()) {webimhandler.getC2CHistoryMsgs();} else {webimhandler.sdkLogin(that,app, this.data.selToID,()=> {//获取聊天历史记录webimhandler.getC2CHistoryMsgs();});}},//创建自定义房源消息体createhousemsg:function(){var that = this;var param = {app_token: app.data.userInfo.app_token,id: that.data.houseId,type: that.data.type}app.request('get', 'createhousemsg', that, param,(data) => {//这里的data.array.MsgContent为获取到需要发送的消息体字段webimhandler.sendCustomMsg(data.array.MsgContent, (data)=>{var myMessages = that.setDatas(data)that.setData({myMessages: myMessages,})setTimeout(function () {that.pageScrollToBottom()}, 100)})}, () => {setTimeout(function () {login.login(app)}, 500)}, () => {wx.navigateBack({delta: 1})return;})},//获取普通文本消息bindKeyInput:function(e){var that = this;that.setData({inputValue:e.detail.value})},// 发送普通文本消息bindConfirm: function(e) {var that = this;if(that.data.is_lock){that.setData({is_lock:false})if (that.data.inputValue.length == 0) {wx.showToast({title: '消息不能为空!',icon:'none'})that.setData({is_lock: true})return;}var content = that.data.inputValue;if (!content.replace(/^\s*|\s*$/g, '')) return;webimhandler.onSendMsg(content)}},// 清除输入框clearInput:function(e){this.setData({inputValue:''})},/*** 下拉上翻历史记录*/onPullDownRefresh: function () {if (this.data.complete == 0){wx.showLoading({title: '加载历史记录中...',})var that = this;webimhandler.getPrePageC2CHistoryMsgs()wx.stopPullDownRefresh();}else{wx.showToast({title: '没有更多历史记录了',icon:'none'})}},// 滚动最底部pageScrollToBottom: function () {wx.createSelectorQuery().select('#chat').boundingClientRect(function (rect) {// 使页面滚动到底部wx.pageScrollTo({scrollTop: rect.bottom})}).exec()},// 跳转房源详情linkDetail:function(e){switch (e.currentTarget.dataset.type){case '新房':wx.navigateTo({url: '../newHouseDetail/newHouseDetail?id=' + e.currentTarget.dataset.id,})break;case '二手房':wx.navigateTo({url: '../useroomDetail/useroomDetail?id=' + e.currentTarget.dataset.id,})break;case '租房':wx.navigateTo({url: '../rentroomDetail/rentroomDetail?id=' + e.currentTarget.dataset.id,})break;case '小区':wx.navigateTo({url: '../unitDetail/unitDetail?id=' + e.currentTarget.dataset.id,})break;}},setDatas: function (data){var that = this;var myMessages = data.map((item, index) => {switch (item.type) {case 1:item.type = '二手房'break;case 2:item.type = '租房'break;case 3:item.type = '小区'break;case 4:item.type = '新房'break;}if (item.img == '') {item.img = that.data.houseDefault}return item;})return myMessages;}})
发送自定义消息
//发送消息(自定义消息)
function sendCustomMsg(msgs,callback) {var data = msgs.Data;//数据var desc = msgs.Desc;//描述var ext = msgs.Ext;//拓展字段var msgLen = webim.Tool.getStrBytes(data);if (msgs.length < 1) {alert("发送的消息不能为空!");return;}var maxLen, errInfo;if (selType == webim.SESSION_TYPE.C2C) {maxLen = webim.MSG_MAX_LENGTH.C2C;errInfo = "消息长度超出限制(最多" + Math.round(maxLen / 3) + "汉字)";} else {maxLen = webim.MSG_MAX_LENGTH.GROUP;errInfo = "消息长度超出限制(最多" + Math.round(maxLen / 3) + "汉字)";}if (msgLen > maxLen) {alert(errInfo);return;}if (!selSess) {selSess = new webim.Session(selType, id, name, icon, Math.round(new Date().getTime() / 1000));}var msg = new webim.Msg(selSess, true, -1, -1, -1, id, 0, name);var custom_obj = new webim.Msg.Elem.Custom(data, desc, ext);msg.addCustom(custom_obj);msg.sending = 1;// //调用发送消息接口webim.sendMsg(msg, function (resp) {if (selType == webim.SESSION_TYPE.C2C) {// 处理消息handlderMsg(msg,false);// 获取头像getMyAvatar(id, agent_member_id,function(){callback(currentMsgsArray)});}that.msginformagent(id, msgs)webim.Log.info("发消息成功");}, function (err) {webim.Log.info("发消息失败");});
}// 解析消息(普通文本消息,自定义消息)
function convertMsg(msg, prepend) {var that = this;var elems, elem, type, content, isSelfSend, ifromAccount;elems = msg.getElems();isSelfSend = msg.getIsSend(); //消息是否为自己发的 true是自己发送,ifromAccount = msg.fromAccountfor (var i in elems) {var currentMsg = {}; elem = elems[i];type = elem.getType();content = elem.getContent();switch (type) {case webim.MSG_ELEMENT_TYPE.TEXT://文本消息var msgContent = convertTextMsgToHtml(content);var msgTime = msg.getTime();//得到当前消息发送的时间//解析时间convertTime(msgTime, function (data) {currentMsg.id = ifromAccount;//房源标题 currentMsg.msgContent = msgContent;//当前消息的内容currentMsg.img = '';currentMsg.msgTime = data;currentMsg.name = ''currentMsg.price = '';currentMsg.isSelfSend = isSelfSend;currentMsg.ifromAccount = ifromAccount;currentMsg.type = '';if (prepend){historyMsgsArray.push(currentMsg)}else{currentMsgsArray.push(currentMsg);}})break;case webim.MSG_ELEMENT_TYPE.CUSTOM://自定义消息var msgContent = convertCustomMsgToHtml(content);var msgTime = msg.getTime();//得到当前消息发送的时间if (msgContent.data == ''){}else{msgContent = JSON.parse(msgContent.data)}convertTime(msgTime, function (data) {currentMsg.id = msgContent.id//房源标题currentMsg.img = msgContent.img//房源图片currentMsg.msgTime = data;//消息时间 currentMsg.name = msgContent.name //楼盘名称currentMsg.price = msgContent.price //价格currentMsg.type = msgContent.type //类型(1二手房,2租房,3小区,4新房)currentMsg.isSelfSend = isSelfSend;//默认右边currentMsg.ifromAccount = ifromAccount;if (prepend){historyMsgsArray.push(currentMsg)}else{currentMsgsArray.push(currentMsg);}})break;}}}// 解析自定义消息
function convertCustomMsgToHtml(content) {var data = content.getData();var desc = content.getDesc();var ext = content.getExt();var content = {data:data,desc: desc,ext: ext}return content;
}
发送普通文本消息
//发送消息(普通消息)
function onSendMsg(msg) {//获取消息内容var msgtosend = msg;var msgLen = webim.Tool.getStrBytes(msg);// 创建会话对象if (!selSess) {selSess = new webim.Session(selType, id, name, icon, Math.round(new Date().getTime() / 1000));}var isSend = true;//是否为自己发送var seq = -1;//消息序列,-1表示sdk自动生成,用于去重var random = Math.round(Math.random() * 4294967296);//消息随机数,用于去重var msgTime = Math.round(new Date().getTime() / 1000);//消息时间戳var subType = webim.C2C_MSG_SUB_TYPE.COMMON;//消息子类型c2c消息时,参考c2c消息子类型对象:webim.C2C_MSG_SUB_TYPE //loginInfo.identifier消息发送者账号,loginInfo.identifierNick消息发送者昵称var msg = new webim.Msg(selSess, isSend, seq, random, msgTime, id, subType, name );//解析文本和表情var expr = /\[[^[\]]{1,3}\]/mg;var emotions = msgtosend.match(expr);if (!emotions || emotions.length < 1) {var text_obj = new webim.Msg.Elem.Text(msgtosend);msg.addText(text_obj);} else {//有表情}webim.sendMsg(msg, function (resp) {if (selType == webim.SESSION_TYPE.C2C) {//私聊时,在聊天窗口手动添加一条发的消息handlderMsg(msg,false);// 设置双方头像getMyAvatar(id, agent_member_id, function () {that.clearInput();var myMessages = that.setDatas(currentMsgsArray);that.setData({myMessages: myMessages,is_lock: true})// setTimeout(function () {that.pageScrollToBottom()// }, 100)});that.msginformagent(id, msgtosend) webim.Log.info("发消息成功");}}, function (err) {webim.Log.error("发消息失败:" + err.ErrorInfo);});
}//解析文本消息元素
function convertTextMsgToHtml(content) {return content.getText();
}
统一处理文本消息,自定义消息
// 解析消息(普通文本消息,自定义消息)
function convertMsg(msg, prepend) {var that = this;var elems, elem, type, content, isSelfSend, ifromAccount;elems = msg.getElems();isSelfSend = msg.getIsSend(); //消息是否为自己发的 true是自己发送,ifromAccount = msg.fromAccountfor (var i in elems) {var currentMsg = {}; elem = elems[i];type = elem.getType();content = elem.getContent();switch (type) {case webim.MSG_ELEMENT_TYPE.TEXT://文本消息var msgContent = convertTextMsgToHtml(content);var msgTime = msg.getTime();//得到当前消息发送的时间//解析时间convertTime(msgTime, function (data) {currentMsg.id = ifromAccount;//房源标题 currentMsg.msgContent = msgContent;//当前消息的内容currentMsg.img = '';currentMsg.msgTime = data;currentMsg.name = ''currentMsg.price = '';currentMsg.isSelfSend = isSelfSend;currentMsg.ifromAccount = ifromAccount;currentMsg.type = '';if (prepend){historyMsgsArray.push(currentMsg)}else{currentMsgsArray.push(currentMsg);}})break;case webim.MSG_ELEMENT_TYPE.CUSTOM://自定义消息var msgContent = convertCustomMsgToHtml(content);var msgTime = msg.getTime();//得到当前消息发送的时间if (msgContent.data == ''){}else{msgContent = JSON.parse(msgContent.data)}convertTime(msgTime, function (data) {currentMsg.id = msgContent.id//房源标题currentMsg.img = msgContent.img//房源图片currentMsg.msgTime = data;//消息时间 currentMsg.name = msgContent.name //楼盘名称currentMsg.price = msgContent.price //价格currentMsg.type = msgContent.type //类型(1二手房,2租房,3小区,4新房)currentMsg.isSelfSend = isSelfSend;//默认右边currentMsg.ifromAccount = ifromAccount;if (prepend){historyMsgsArray.push(currentMsg)}else{currentMsgsArray.push(currentMsg);}})break;}}}
发送消息成功之后,就需要监听新消息,更新消息的未读数了
//监听新消息(私聊(包括普通消息、全员推送消息),普通群(非直播聊天室)消息)事件
//newMsgList 为新消息数组,结构为[Msg]
function onMsgNotify(newMsgList) {var newMsg;//获取所有聊天会话for (var j in newMsgList) {//遍历新消息newMsg = newMsgList[j];if (newMsg.getSession().id() == id) {//为当前聊天对象的消息selSess = newMsg.getSession();handlderMsg(newMsg, false);currentMsgsArray = currentMsgsArray.map((item, index) => {if (!item.isSelfSend) {item.avatar = myAvatar} else {item.avatar = friendAvatar}return item;})var myMessages = that.setDatas(currentMsgsArray);that.setData({myMessages: myMessages,})setTimeout(function () {if (that.data.is_chat){that.pageScrollToBottom()}}, 100)}}getUnread()}//更新消息未读数
function getUnread(){var sess= {};var sessMap = webim.MsgStore.sessMap();if (that.data.contactList) {// 更新消息的未读数for (var i in sessMap) {sess = sessMap[i];var contactList = that.data.contactList.map((item, index) => {if (item.To_Account == sess.id()) {item.UnreadMsgCount = sess.unread()}return item;})that.setData({contactList: contactList})// 获取最新的会话消息webim.getRecentContactList({'Count': 10 //最近的会话数 ,最大为 100}, function (resp) {var MsgShow = resp.SessionItem.filter((item, index) => {if (item.To_Account == sess.id()) return item;})var contactList = that.data.contactList.map((item, index) => {if (item.To_Account == sess.id()) {// 获取最新消息if (MsgShow[0].MsgShow == '[其他]'){MsgShow[0].MsgShow = '[房源信息]'}item.MsgShow = MsgShow[0].MsgShow}return item;})that.setData({contactList: contactList})})}}
}
发送消息就到这里了,历史记录下章讲