微信小程序接入騰訊雲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:'',//房源id
type:'',//房源類型
height:'',
complete:0,//默認爲有歷史記錄可以拉取
is_lock:true//發送消息鎖
},
/**
* 生命週期函數--監聽頁面加載
*/
onLoad: function (options) {
var that = this;
that.setData({
height: wx.getSystemInfoSync().windowHeight
})
if(options){
if(options.id){//設置會話列表傳參過來的爲好友id
that.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.fromAccount
for (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.fromAccount
for (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
})
})
}
}
}
發送消息就到這裏了,歷史記錄下章講