赞
踩
页面显示
//初始化
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
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
}
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 的状态/事件 常量
//用户信息 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) }) } }) },
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}`); } }); }, }
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.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 底部输入框
<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.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 }) }, } };
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。