uniapp中使用websocket实现实时聊天功能

直接贴代码

文档: https://uniapp.dcloud.io/api/request/websocket

//scroll-view组件的scroll-top属性:设置竖向滚动条位置。只要scroll-top大于滚动区域最大高度,即可滚动到底部
<scroll-view scroll-y="true" :scroll-top="commentScrollCount" class="comment-scroll-body">
      。。。。。。
</scroll-view>



data(){
      return{
          commentList:[],  //获取的评论列表
          commentValue:'',  //用户评论内容
          isSocketOpen:false,  //socket是否打开
          pingpangTimes:null,  //socket心跳计时器
      }
}

onLoad(option) {	
	this.chatInit()  //socket相关操作				
},

beforeDestroy() {
	clearInterval(this.pingpangTimes)  //清除socket心跳定时器
	uni.closeSocket()  //关闭socket
},
methods:{
//链接socket以进行直播实时评论发送获取等相关操作
	chatInit(){
		uni.request({
			url: `${this.$baseUrl}/api-live/checkLiveStatus?lid=${this.lid}&initial=1`,  //此接口返回socket请求地址
			method: 'GET',
			success: res => {
				if(res.data.code==200){
					let socketlink=''
					if(this.userToken){  //已登录,携带token
						socketlink=`${res.data.msg}?token=${this.userToken}`
					}else{  //未登录
						socketlink=res.data.msg
					}
					this.commentList=[]  //创建新的socket连接前先清除之前的实时聊天记录
					uni.closeSocket()  //创建新的socket连接前确保旧的已关闭
					//创建一个socket连接
					uni.connectSocket({
						url:encodeURI(socketlink),  //这里建议使用encodeURI编码,以解决ios上可能出现的连接兼容问题(猜测socketlink里存在中文、空格、特殊字符或link字符串过长时可能会在ios上出现连接问题)
					})
					//监听socket打开
					uni.onSocketOpen(()=>{
						this.isSocketOpen=true
						console.log('WebSocket连接已打开!');
					})
					//监听socket关闭
					uni.onSocketClose(()=>{
						this.isSocketOpen=false
						console.log('WebSocket连接已关闭!');
					})
					//监听socket错误
					uni.onSocketError(()=>{
						this.isSocketOpen=false
						console.log('WebSocket连接打开失败');
					})
					//监听socket消息
					uni.onSocketMessage((res)=>{
						return this.getComment(res)
					})

					//先确保清除了之前的心跳定时器
					clearInterval(this.pingpangTimes)
					//每过一段时间发送一次心跳,发送Ping,服务器会反馈pong,防止断连
					this.pingpangTimes=setInterval(()=>{
						uni.sendSocketMessage({
							data: "ping",
							success:()=>{},
							fail:()=>{
								this.isSocketOpen=false
							}
						});
					},60000)
				}
			},
		});
	},

    //监听socket消息
    getComment(res){
      let infos=JSON.parse(res.data)  //socket信息是字符串,需要先转成json形式再去解析内容
      //后端规定cadmin为0--用户发言,为1--管理员发言,为2--系统提示,为3--需登录,为5--心跳信息
      if(typeof(infos.cadmin)=="undefined"){  //infos.cadmin不存在说明返回的是数组,说明是第一次获取的之前的所有聊天记录
        this.commentList=this.commentList.concat(infos)
        //设置定时器,到时间后滚动到最底部。使用scroll-view组件的scroll-top属性。只要scroll-top的值大于滚动区域的最大高度即可实现滚动到最底部
        let scrolltimes=setTimeout(()=>{  
          this.commentScrollCount=this.commentList.length*200
          clearTimeout(scrolltimes)
        },600)

      //后续每次更新一条有效的新聊天(心跳信息pong不是有效聊天),就会触发这个
      }else if(infos.cadmin==0||infos.cadmin==1||infos.cadmin==2){
        this.commentList=this.commentList.concat(infos)
        let scrolltimes=setTimeout(()=>{
          this.commentScrollCount=this.commentList.length*200
          clearTimeout(scrolltimes)
        },150)
      }else if(infos.cadmin==3){  //未登录
        this.loginPopRemind="您尚未登录或您的登录已过期,请重新登录后发言"
        uni.removeStorageSync('kusername')
        uni.removeStorageSync('kuserid')
        uni.removeStorageSync('kuserimg')
        uni.removeStorageSync('kusertoken')
        this.$refs.noLoginPopup.open()
      }
    }
			
	//发表评论
	sendComment(val){
		if(val==""){
			uni.showToast({title: '说点什么吧 ~',icon:'none'})
		}else if(val.length>300){
			uni.showToast({title: `评论字数请勿超过300个字符,当前 ${val.length}`,icon:'none'})
		}else{
			if(this.userToken){  //已登录
				if(this.isSocketOpen){  //socket连接正常
					this.commentValue=val
					let theValue={
						"ccontent":this.commentValue
					}
					let transedValue=JSON.stringify(theValue)   //后端规定的评论数据格式:json转字符串
						uni.sendSocketMessage({
							data: transedValue,
							success:()=>{
								this.commentValue=""
								uni.showToast({title: '发送成功',icon:'none'})
							},
							fail:()=>{
								uni.showToast({title: '发送失败,请稍后再试或重新进入此页面尝试',icon:'none'})
							}
						});
				}else{  //socket已断开
					uni.showToast({title: '聊天断开啦,请重新进入此页面尝试 ~',icon:'none'})
				}
			}else{  //未登录
				this.$refs.needLoginPopup.open()
			}
		}
	},
}
posted @ 2020-08-12 17:32  huihuihero  阅读(13260)  评论(3编辑  收藏  举报