因为融云含ui的聊天室并不适用于uniapp,所以uniapp中所有东西就需要自己来实现,好在融云给的接口还是很全的,因为项目的差异性我只介绍聊天室的代码(因为没做任何优化,可能代码可读性并不强,而且只实现了发送文字信息的功能,分享出来只是方便自己看,接不通可以私信我)
在开始聊天之前需要先连接融云的im(main.js中)
//引入融云SDK
const RongIMib = require('./common/libs/RongIMLib-3.0.7.1-dev.js')
const RongIMLib = require('./common/libs/RongEmoji-2.2.9.js')
//初始化融云SDK
let im = RongIMib.init({
appkey: ""//申请的key
})
Vue.prototype.$Im = im
//挂载融云到Vue原型
Vue.prototype.$RongIMib = RongIMib
Vue.prototype.$RongIMLib=RongIMLib
可以在首页打印下判断是否连接成功
我是在首页连接的融云,连接的话只一次就可以,可以在登录成功后连接,我感觉在登录成功后连接更好(刚开始就连接就好,不用监听,在会话列表里已经监听过了) 注意:连接融云需要token,这时候需要读后端的接口拿到
rongyunInit() {
//初始化融云
// let _that = this;
//设置监听
// let conversationList = []; //当前存在的会话列表
// _that.$Im.watch({
// //对会话列表进行监听
// conversation: event => {
// console.log(event);
// let updatedConversationList = event.updatedConversationList; //更新的会话列表
// console.log('upload:', updatedConversationList);
// let sendOut = {
// content: event.updatedConversationList[0].latestMessage.content.content,
// sentTime: event.updatedConversationList[0].latestMessage.sentTime
// };
// uni.setStorageSync('sendOut', sendOut);
// if (event.updatedConversationList[0].latestMessage.messageDirection == 2) {
// this.chat.push({
// type: event.updatedConversationList[0].latestMessage.messageDirection,
// time: event.updatedConversationList[0].latestMessage.sentTime,
// msg: event.updatedConversationList[0].latestMessage.content.content,
// avatar: uni.getStorageSync('user_info').avatar
// });
// }
// },
// status: function(event) {
// let status = event.status;
// console.log('status num:', status);
// }
// });
/**
* 3.连接融云
* 1) 需要先调用服务端接口,获取Token 然后进行连接
*/
//进行连接
this.$Im
.connect({
token: uni.getStorageSync('rong_token')
})
.then(user => {
console.log('success id: ', user.id);
})
.catch(error => {
console.log('error: ', error.code, error.msg);
});
},
聊天室代码.js文件
export default {
name: 'index',
data() {
return {
chat: [],
sentText: '',
doctorInfo: '',
height: '0rpx',
scrollTop: 0,
count: 7,
uuid: '',
avatar: '',
list: [],
style: {
pageHeight: 0,
contentViewHeight: 0,
footViewHeight: 90,
mitemHeight: 0
},
};
},
onLoad(options) {
this.uuid = options.uuid
this.avatar = options.avatar
this.rongyunInit();
this.getlist(new Date())
const res = uni.getSystemInfoSync(); //获取手机可使用窗口高度 api为获取系统信息同步接口
this.style.pageHeight = res.windowHeight;
this.style.contentViewHeight = res.windowHeight - uni.getSystemInfoSync().screenWidth / 750 * (100); //像素 因为给出的是像素高度 然后我们用的是upx 所以换算一下
},
onShow() {
this.chat = []
this.clear()
},
methods: {
read(uuid, time) {
let conversation = this.$Im.Conversation.get({
targetId: this.uuid,
type: this.$RongIMib.CONVERSATION_TYPE.PRIVATE
});
let messageUId = uuid; // 消息唯一 Id, message 中的 messageUid
let lastMessageSendTime = time; // 最后一条消息的发送时间
let type = '1'; // 备用,默认赋值 1 即可
// 以上 3 个属性在会话的最后一条消息中可以获得
conversation.send({
messageType: 'RC:ReadNtf',
content: {
messageUId: messageUId,
lastMessageSendTime: lastMessageSendTime,
type: type
}
}).then((message) => {
console.log('发送已读通知消息成功', message);
});
},
scrolltoupper() {
this.$u.throttle(this.getlist(this.chat[0].time, 1), 500)
},
// 清空未读数
clear() {
this.$Im.Conversation.getTotalUnreadCount().then(function(totalUnreadCount) {
console.log('获取未读总数成功', totalUnreadCount);
});
let conversation = this.$Im.Conversation.get({
targetId: this.uuid,
type: this.$RongIMib.CONVERSATION_TYPE.PRIVATE
});
conversation.read().then(()=> {
console.log('清除未读数成功'); // im.watch conversation 将被触发
});
},
scrollToBottom() {
let that = this;
let query = uni.createSelectorQuery();
query.selectAll('.m-item').boundingClientRect();
query.select('#scrollview').boundingClientRect();
query.exec((res) => {
console.log(res)
that.style.mitemHeight = 0;
res[0].forEach((rect) => that.style.mitemHeight = that.style.mitemHeight + rect.height + 40) //获取所有内部子元素的高度
// 因为vue的虚拟DOM 每次生成的新消息都是之前的,所以采用异步setTimeout 主要就是添加了这定时器
setTimeout(() => {
if (that.style.mitemHeight > (that.style.contentViewHeight - 100)) { //判断子元素高度是否大于显示高度
console.log(3333)
that.scrollTop = that.style.mitemHeight - that.style.contentViewHeight //用子元素的高度减去显示的高度就获益获得序言滚动的高度
}
}, 100)
})
},
// #ifdef APP-PLUS
hgit() {
this.height = '50rpx'
},
// #endif
// #ifdef H5
hgit() {
this.height = '500rpx'
},
// #endif
blur() {
this.height = '0rpx'
},
rongyunInit() {
//初始化融云
let _that = this;
//设置监听
let conversationList = []; //当前存在的会话列表
_that.$Im.watch({
//对会话列表进行监听
conversation: (event) => {
let updatedConversationList = event.updatedConversationList; //更新的会话列表
console.log('upload用户端:', updatedConversationList);
let sendOut = {
content: event.updatedConversationList[0].latestMessage.content.content,
sentTime: event.updatedConversationList[0].latestMessage.sentTime
}
uni.setStorageSync('sendOut', sendOut)
if (event.updatedConversationList[0].latestMessage.messageDirection == 2) {
console.log('执行了')
this.chat.push({
type: event.updatedConversationList[0].latestMessage.messageDirection,
time: event.updatedConversationList[0].latestMessage.sentTime,
msg: event.updatedConversationList[0].latestMessage.content.content,
avatar: uni.getStorageSync('user_info').avatar
})
}
},
status: function(event) {
let status = event.status;
console.log('status num:', status);
}
});
/**
* 3.连接融云
* 1) 需要先调用服务端接口,获取Token 然后进行连接
*/
//进行连接
// this.$Im
// .connect({
// token: uni.getStorageSync('rong_token')
// })
// .then(user => {
// console.log('success id: ', user.id);
// })
// .catch(error => {
// console.log('error: ', error.code, error.msg);
// });
},
// 获取历史信息
getlist(time, status) {
console.log(time, status)
let conversation = this.$Im.Conversation.get({
targetId: this.uuid,
type: this.$RongIMib.CONVERSATION_TYPE.PRIVATE
});
let option = {
timestrap: +time,
count: this.count
};
conversation.getMessages(option).then((result) => {
this.list = result.list; // 历史消息列表
let hasMore = result.hasMore; // 是否还有历史消息可以获取
console.log('获取历史消息成功', this.list, hasMore);
// this.read(this.list.length.messageUId, this.list.length.sentTime)
this.read(this.list[this.list.length-1].messageUId, this.list[this.list.length-1].sentTime)
// data == 1下拉加载
if (status == 1) {
let a = []
this.list.forEach(item => {
if (item.messageDirection == 1) {
a.push({
type: item.messageDirection,
time: item.sentTime,
msg: item.content.content,
avatar: uni.getStorageSync('user_info').avatar
})
} else {
a.push({
type: item.messageDirection,
time: item.sentTime,
msg: item.content.content,
avatar: this.avatar
})
}
})
console.log(2342342,a)
this.chat.unshift(...a)
console.log(this.chat)
}else{
this.list.forEach(item => {
if (item.messageDirection == 1) {
this.chat.push({
type: item.messageDirection,
time: item.sentTime,
msg: item.content.content,
avatar: uni.getStorageSync('user_info').avatar
})
} else {
this.chat.push({
type: item.messageDirection,
time: item.sentTime,
msg: item.content.content,
avatar: this.avatar
})
}
})
}
console.log(this.chat)
});
},
//融云发送消息方法
sendMessage(type, content) {
//4.连接融云成功后进行发送消息
this.conversation = this.$Im.Conversation.get({
targetId: this.uuid,
type: this.$RongIMib.CONVERSATION_TYPE.PRIVATE
});
this.conversation.send({
messageType: this.$RongIMib.MESSAGE_TYPE[type],
content
}).then((msg) => {
this.scrollToBottom(); //创建后调用回到底部方法
console.log('发送消息成功', msg);
this.chat.push({
type: msg.messageDirection,
time: msg.sentTime,
msg: msg.content.content,
avatar: uni.getStorageSync('user_info').avatar
})
this.sentText = []
}).catch(err => {
console.log('消息发送失败', err)
})
},
}
};
.vue文件
<template>
<view class="mh100p pd20 pb100" :style="{height: 100+'%'}">
<share title="即时通讯" />
<scroll-view id="scrollview" @scrolltoupper='scrolltoupper' class="chat-window pb100" scroll-y="true" :style="{ height: style.contentViewHeight + 'px' }" :scroll-with-animation="true" :scroll-top="scrollTop">
<view class="my20 m-item" v-for="(item, index) in chat" :key="index">
<view class="cl999 ftr26 mb20 u-text-center">{{ item.time | date('yyyy.mm.dd hh:MM:ss') }}</view>
<view class="yc" :class="item.type == 1 ? 'rever' : ''">
<u-avatar mode="square" :src="item.avatar"></u-avatar>
<view class="chat-box">{{ item.msg }}</view>
</view>
</view>
</scroll-view>
<view class="fix-wrap bgfff px30 py20 pb50" :style="{ bottom: height }">
<u-search
placeholder="请输入发送内容"
search-icon="edit-pen"
action-text="发送"
v-model="sentText"
@focus="hgit"
@blur="blur"
@custom="sendMessage('TEXT', { content: sentText })"
@search="sendMessage('TEXT', { content: sentText })"
></u-search>
</view>
</view>
</template>
<script>
import index from './index.js';
export default index;
</script>
<style lang="scss" scope>
@import './index.scss';
</style>
.css文件(用的ui库是uview)
.chat-box {
padding: 20upx;
margin: 0 16upx;
background-color: #ffffff;
border-radius: 12upx;
}
.rever {
flex-direction: row-reverse;
.chat-box {
background-color: #f8e271;
}
}
.fix-wrap {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100upx;
}
/deep/ .u-input__input {
background-color: #f4f4f4;
border-radius: 20upx;
padding: 0 20upx;
}
即时通讯接起来还是挺麻烦的,走一遍之后就还好,该有的api都有所提供,因为我是直接拿的项目里的,可能并不适用于你们