直接貼代碼
文檔: 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=null
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:socketlink,
success: res=>{}
})
//監聽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)=>{
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()
}
})
//先確保清除了之前的心跳定時器
clearInterval(this.pingpangTimes)
//每過一段時間發送一次心跳,發送Ping,服務器會反饋pong,這樣操作以保持socket一直是連接狀態,防止斷開連接,心跳停止
this.pingpangTimes=setInterval(()=>{
uni.sendSocketMessage({
data: "ping",
success:()=>{},
fail:()=>{
this.isSocketOpen=false
}
});
},60000)
}
},
});
},
//發表評論
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()
}
}
},
}