uniapp使用腾讯im 无ui集成方案写法

页面显示
在这里插入图片描述
在这里插入图片描述

1.无ui集成方案

1.1 首先下来依赖
//初始化
npm init
// IM Web SDK
// 从v2.11.2起,SDK 支持了 WebSocket,推荐接入;v2.10.2及以下版本,使用 HTTP
npm install tim-js-sdk --save
// 发送图片、文件等消息需要腾讯云即时通信 IM 上传插件
npm install tim-upload-plugin --save
// 拦截或替换敏感词需要本地审核插件
npm install tim-profanity-filter-plugin --save
1.2 创建tim.js
import TIM from 'tim-js-sdk/tim-js-friendship.js'
import TIMUploadPlugin from 'tim-upload-plugin';
import TIMProfanityFilterPlugin from 'tim-profanity-filter-plugin';

// import COS from "cos-js-sdk-v5";


​ const options = {
​ SDKAppID: 1600024346
​ // 接入时需要将0替换为您的即时通信应用的 SDKAppID
​ };
​ // 创建 SDK 实例,TIM.create() 方法对于同一个 SDKAppID 只会返回同一份实例
​ const tim = TIM.create(options); // SDK 实例通常用 tim 表示
​ // tim.setLogLevel(0);
​ const TIMData = TIM
​ // 注册腾讯云即时通信 IM 上传插件
​ tim.registerPlugin({
​ ‘tim-upload-plugin’: TIMUploadPlugin
​ });

// 注册腾讯云即时通信 IM 本地审核插件
tim.registerPlugin({
	'tim-profanity-filter-plugin': TIMProfanityFilterPlugin
});

// 注册 COS SDK 插件
// tim.registerPlugin({'cos-js-sdk': COS});



​ /* eslint-disable require-jsdoc */
​ function genTestUserSig(userID) {
​ const SDKAPPID = 1600024346;
​ const EXPIRETIME = 604800;
​ const SECRETKEY = ‘a03e633a7f9e49784a8f1b1d87ebc4d930be70544e13822bdd8f9a0af40acc1’;

const generator = new LibGenerateTestUserSig(SDKAPPID, SECRETKEY, EXPIRETIME);
const userSig = generator.genTestUserSig(userID);

	return {
		sdkAppId: SDKAPPID,
		userSig: userSig
	};
}

export default {
	tim,
	TIMData,
	genTestUserSig
}
1.3 在main.js导入
import tim from './utils/tim.js'
import TIM from 'tim-js-sdk/tim-js-friendship.js'

Vue.prototype.tim = tim.tim //tim sdk 引入后生成的tim服务
Vue.prototype.$TIM = TIM //tim 的状态/事件 常量
2.1 在登录接口存储用户信息
//用户信息
		user() {
			this.$helper.apiPost(this.$api.tab.user).then(ret => {
				if (ret.data.code == 200) {
					this.info = ret.data.data
					//根据返回的userID 以及 userSig 登录tim
					uni.setStorageSync('uid', ret.data.data.username)
					//这里我叫后端返回了一个userSing
					uni.setStorageSync('uid_sig', ret.data.data.user_sig)
					console.log(this.info, '122332211');
					this.tim.login({
						userID: this.info.username,
						userSig: this.info.user_sig
					}).then((imResponse) => {
						this.$helper.showToast('登录成功')
						setTimeout(() => {
							uni.switchTab({
								url: '/pages/tab/home'
							})
						}, 500)
					})
				}
			})
		},
2.2 进入首页
 data() {
		return {
			userID: uni.getStorageSync('uid'),
			userSig: uni.getStorageSync('uid_sig'),
		};
	},
 onLoad() {
		this.cosImLogin()
	},
 methods: {
	 cosImLogin() {
		console.log(this.userID, 'this.userID');
		console.log(this.userSig, 'this.userSig');
		if (!this.userID.length || !this.userSig.length) return
			this.tim.login({
				userID: this.userID,
				userSig: this.userSig
			}).then((res) => {
				this.loginTUICallKit()
			}).catch((err) => {
				console.log("报错", err)
			})
		},
	 loginTUICallKit() {
			const options = {
				SDKAppID: 1600024346, // 请替换为步骤一取到的 SDKAppID
				userID: this.userID, // 请替换为您的 UserID
				userSig: this.userSig, // 您可以在控制台中计算一个 UserSig 并填在这个位置
			};
			this.$TUICallKit.login(options, (res) => {
				if (res.code === 0) {
					console.log('login success');
					this.$TUICallKit.enableFloatWindow(true); // 开启小浮窗
				} else {
					console.log(`login failed, error message = ${res.msg}`);
				  }
				});
			},
		}
2.3 我的好友列表
export default {
	data() {
		return {
			friends: []
		};
	},

	onLoad() {
		this.friendList();
	},
	methods: {
		openConversation(name, userID) {
		// userID:电话号码  username:昵称 
		//跳转到聊天页面(聊天页面自定义头部所以要携带昵称)
		this.$helper.toPage('/pages/active/chat?name=' + name + '&userID=' + userID);
	 },
	    //我的好友
		async friendList() {
			let res = await this.$helper.apiPost(this.$api.user.friend_list);
			this.friends = res.data.data;
			console.log(this.friends);
		}
	}
};
3.1 聊天页面

3.1.1 对话内容

3.1.1 对话内容
<view class="msg-content-list">
   <mescroll-uni ref="mescrollRef" :fixed="false" :down="downOption" @init="mescrollInit" @down="downCallback"	@up="upCallback">
	 <view>
		<view class="msg-content-item" v-for="(item, index) in msgList">
		  <view class="time-slot" v-if="item.isShowTime || index == 0">
			{{getShowTimePipe(item.time) || ''}}
		  </view>
  <!-- 个人开始 -->
	      <view>
		<view class="content-from msg" v-if="item.flow == 'in'">
		<image class="msg-image left-head" :src="item.avatar" />
  <!-- 每条消息内容 -- left -->
		<view class="content-my-left-box">
  <!-- 展示文本 -->
		<view class="content-my-left-text" v-if="item.type == 'TIMTextElem'">
		   <rich-text :nodes="nodesFliter(item.payload.text)"></rich-text>
		</view>
  <!-- 展示图片 -->
	<image class="content-my-left-img" :style="`height:${item.payload.imageInfoArray[1].height}px; width: ${item.payload.imageInfoArray[1].width}px;`" :src="item.payload.imageInfoArray[1].imageUrl" mode="widthFix" v-else-if="item.type == 'TIMImageElem'" @click="onPreviewImg(item.payload.imageInfoArray[1].imageUrl)"></image>
  <!-- 展示视频 -->
	<MyVideo class="content-my-video" v-else-if="item.type == 'TIMVideoFileElem'" :videoUrl="item.payload.remoteVideoUrl" />
	</view>
<!-- 每条消息内容 -- left -->
	</view>
	<view class="content-my msg" v-else-if="item.flow == 'out'">
<!-- 每条消息内容 -- right -->
	<view class="content-my-right-box">
<!-- 展示文本 -->
	<view class="content-my-right-text" v-if="item.type == 'TIMTextElem'">
		rich-text :nodes="nodesFliter(item.payload.text)"></rich-text>
	</view>
<!-- 展示图片 -->
<image class="content-my-right-img"	:style="`height: ${item.payload.imageInfoArray[1].height*2}rpx; width: ${item.payload.imageInfoArray[1].width*2}rpx;`":src="item.payload.imageInfoArray[1].imageUrl" mode="widthFix" v-else-if="item.type == 'TIMImageElem'" @click="onPreviewImg(item.payload.imageInfoArray[1].imageUrl)"></image>
<!-- 展示视频 -->
<MyVideo class="content-my-video" v-else-if="item.type == 'TIMVideoFileElem'" :videoUrl="item.payload.remoteVideoUrl" />
</view>
<!-- 每条消息内容 -- right -->
	      <image class="msg-image right-head" :src="item.avatar " />
        </view>
      </view>
<!-- 个人结束 -->
					</view>
				</view>
			</mescroll-uni>
		</view>
3.2 底部输入框
3.2 底部输入框

<view class="bottom fixed" @click="getBottomHeight()" :style="{bottom: changeBottomVal}">
	<view class="flex-center-between">
		<image @click="imgBtn" src="/static/images/home/1086.png" mode=""></image>
		// @keyboardheightchange 监听键盘高度
			<input :adjust-position="false" @keyboardheightchange="keyboardheightchange" class="save-inp" v-model="msgText" :focus="focus" type="text" @confirm="sendBtn">
		<view class="send" @click="sendBtn">发送</view>
	 </view>
	</view>

3.1.2 js代码

3.1.2 js代码

	data() {
			return {
				top: uni.getStorageSync('safeArea').top,
				name: '',
				bottomImg: false,
				username: '',
				changeBottomVal: '',//键盘高度
				bottomHeight: '', //底部高度
				msgList: [], // 会话消息列表		
				msgText: '', // 文字消息
				message: {}, // 发送消息对象
				timUserInfo: {}, // 会话对象用户信息
				msgUserData: {}, // 会话对象信息
				focus: false,
				downOption: {
					auto: false,
					textInOffset: '拉取历史记录',
					textOutOffset: '',
					textLoading: '拉取中...'
				},
			};
		},
		onShow() {
			this.getTimeSlot()
			// 获取会话数据
			this.getListMsg()

		},
		onLoad(e) {

			this.tim.on(this.$TIM.EVENT.MESSAGE_RECEIVED, (event) => {

				if (event.data[0].type == "TIMSoundElem") {
					this.getListMsg()
					this.getTimeSlot()
				} else {
					let arr = event.data.filter((res) => res.conversationID == (this.isGroup ? `GROUP${this.msgData.groupID}` :
						`C2C${this.msgUserData.userID}`))
					this.msgList.push(...arr)
					this.getTimeSlot()
					// 获取底部高度
					this.getBottomHeight(false)
				}
			})

			this.name = e.name;
			this.username = e.username;
			this.msgUserData = e

			// 已读会话
			this.inRead()
			// 获取底部高度
			this.getBottomHeight(false)
		},
		methods: {
		//键盘高度
			keyboardheightchange(e) {
				this.changeBottomVal = e.detail.height + 'px'
			},
			getBottomHeight() {
				this.$nextTick(() => {
					const query = uni.createSelectorQuery().in(this);
					query.select('.bottom').boundingClientRect(data => {
						this.bottomHeight = data.height

						console.log(data.height, 'data.height');
					}).exec();
					this.$nextTick(() => {
						uni.pageScrollTo({
							scrollTop: 9999,
							duration: 100
						})
					})
				})
			},

			// 预览图片
			onPreviewImg(image) {
				uni.previewImage({
					urls: [image],
					fail: function(err) {}
				})
			},
			imgBtn() {
				this.bottomImg = !this.bottomImg
			},
			// 发送拍摄或者上传视频
			sendMsgVideo() {
				uni.chooseVideo({
					success: (res) => {
						this.message = this.tim.createVideoMessage({
							to: this.msgUserData.userID,
							conversationType: 'C2C',
							payload: {
								file: res
							},
							onProgress: (event) => {}
						});
						this.tim.sendMessage(this.message).then((res) => {
							this.msgList.push(res.data.message)
							// 获取底部高度
							this.getBottomHeight(false)
						})
					}
				})
			},
			// 发送拍摄或者上传图片
			sendMsgImage() {
				uni.chooseImage({
					count: 1,
					mediaType: ['image'], // 图片
					sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
					success: (res) => {
						this.message = this.tim.createImageMessage({
							to: this.msgUserData.userID,
							conversationType: 'C2C',
							payload: {
								file: res
							},
							onProgress: function(event) {}
						});
						this.tim.sendMessage(this.message).then((res) => {
							this.msgList.push(res.data.message)
							// 获取底部高度
							this.getBottomHeight(false)
						})
					}
				});
			},
			// 判断是否有十分钟的时间间隔
			getTimeSlot() {
				setTimeout(() => {
					this.msgList.forEach((res, index) => {
						let i = this.msgList.length - (index + 2) <= 0 ? 0 : this.msgList.length - (index + 2)
						let j = this.msgList.length - (index + 1) <= 0 ? 0 : this.msgList.length - (index + 1)
						let time1 = this.$time.getNowDate(this.msgList[i].time * 1000)
						let time2 = this.$time.getNowDate(this.msgList[j].time * 1000)
						if (this.$time.GetDateDiff(time2, time1, 'minute') <= -5) {
							this.$set(this.msgList[j], 'isShowTime', true)
						}
					})
				}, 300)
			},
			// 获取会话列表
			getListMsg(isDown = false) {
				// 用于拉取历史聊天数据
				let parmas = {
					conversationID: `C2C${this.msgUserData.userID}`,
					nextReqMessageID: this.nextReqMessageID
				}
				// 用于拉取目前聊天数据
				let data = {
					conversationID: `C2C${this.msgUserData.userID}`,
				}
				this.tim.getMessageList(isDown ? parmas : data).then((res) => {

					this.nextReqMessageID = res.data.nextReqMessageID
					console.log(res, '11122111221');
					if (!this.nextReqMessageID.length || this.nextReqMessageID == '-1') this.mescroll.lockDownScroll(true)
					if (isDown) {
						this.msgList = res.data.messageList.concat(this.msgList)
						this.mescroll.endDownScroll()
					} else {
						this.msgList = res.data.messageList
					}

				});
				this.timeOut = setTimeout(() => {
					uni.hideLoading()
					if (!isDown) {
						uni.pageScrollTo({
							scrollTop: 9999,
							duration: 100
						})
					}
					this.$forceUpdate()
				}, 800)
			},
			inRead() {
				// 将某会话下所有未读消息已读上报
				this.tim.setMessageRead({
					conversationID: `C2C${this.msgUserData.userID}`
				})
			},
			//聊天的节点加上外层的div
			nodesFliter(str) {
				let nodeStr = '<div style="display: flex; align-items: center;word-wrap:break-word; width: auto;">' + str +
					'</div>'
				return nodeStr
			},
			getShowTimePipe(time) {
				return this.$time.showTimePipe(time * 1000)
			},
			// 发送文本
			sendMsgText() {
				this.msgText = this.msgText.trim()
				console.log(this.msgText, '111111');
				if (this.msgText.length == '') {
					uni.showToast({
						title: "发送消息不能为空",
						icon: "none"
					})
					return
				}
				// 1. 创建消息实例,接口返回的实例可以上屏
				this.message = this.tim.createTextMessage({
					to: this.msgUserData.userID,
					conversationType: 'C2C',
					payload: {
						text: this.msgText
					},
				});
				this.tim.sendMessage(this.message).then((res) => {
					this.msgList.push(res.data.message)
					this.focus = true
					this.msgText = ""
					// 获取底部高度
					this.getBottomHeight(false)
				})
			},
			sendBtn() {
				this.sendMsgText()
			}
		}
4.1 消息列表
4.1.1 html
<view>
	<view v-for="(item, index) in list" :key="index" @click="goToMessage(item.userProfile.nick,item.userProfile.userID,index)">
				<view class="pop flex-center-between">
					<view class="name flex">
						<image :src="item.userProfile.avatar" mode=""></image>
						<view class="tian">
							<view>{{item.userProfile.nick}}</view>
							<span>
								<rich-text :nodes="nodesFliter(item.lastMessage.messageForShow)"></rich-text>
							</span>
						</view>
					</view>
					//未读消息
				<view class="red" v-if="item.unreadCount">{{item.unreadCount}}</view>
			</view>
		<view class="line"></view>
	</view>
</view>
4.2.2 js
export default {
		data() {
			return {
				top: uni.getStorageSync('safeArea').top,
				list: [],
				isTips: true
			};

		},
		onLoad() {
			this.getList()
		},
		onShow() {
			this.getList()
		},
		methods: {
			//聊天的节点加上外层的div
			nodesFliter(str) {
				let nodeStr = '<div style="align-items: center;word-wrap:break-word;">' + str + '</div>'
				return nodeStr
			},
			goToMessage(name, userID, index) {
				this.$helper.toPage('/pages/active/chat?name=' + name + '&userID=' + userID );
				// this.list[index].unreadCount = 0
			},
			getList() {
				// 获取全量的会话列表
				this.tim.getConversationList().then((res) => {

					this.list = res.data.conversationList
					// console.log(this.list, '1111');
					console.log(this.list, '1111');
					this.list = this.list.filter((res) => res.type != "@TIM#SYSTEM")

					this.getFriend()
				})
			},
			getFriend() {
				this.tim.getFriendApplicationList().then(res => {
					this.friendNum = res.data.unreadCount
				})
			},
		}
	};
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值