直接贴代码
<div class="chat-content">
<div class="comment-list" id="comment-list">
<div class="every-comment" v-for="(item,index) in commentList" :key="index">
<div class="every-comment-user" v-if="item.type==0">...</div> <!-- 普通发言 -->
<div class="every-comment-admin" v-if="item.type==1">...</div> <!-- 管理员发言 -->
<div class="every-comment-welcome" v-if="item.type==2">...</div> <!-- 欢迎xx进入直播间 -->
<div class="every-comment-system" v-if="item.type==3">...</div> <!-- 系统消息 -->
<div class="every-comment-nologin" v-if="item.type==4">...</div> <!-- 未登录提示 -->
<div class="every-comment-banned" v-if="item.type==5">...</div> <!-- 禁言通知 -->
</div>
</div>
</div>
<script>
export default {
data() {
return {
commentValue: "", //评论内容
commentList: [], //聊天列表
liveSocket: null, //socket实例
isSocketOpen: false, //socket是否打开
pingpangTimer: null, //socket心跳计数器
};
},
deactivated(){
clearInterval(this.pingpangTimer)
this.liveSocket?.close()
},
beforeDestroy(){
clearInterval(this.pingpangTimer)
this.liveSocket?.close()
},
created(){
this.$eventBus.$on("liveInfo",(data)=>{
this.liveInfo=data
if(this.liveInfo?.wsUrl){ //socket链接由后端提供
this.chatInit() //初始化聊天
}
})
},
methods: {
//初始化socket
chatInit(){
let socketlink=null
if(this.userInfo.tokenValue){
socketlink=`${this.liveInfo.wsUrl}?token=${this.userInfo.tokenValue}`
}else{
socketlink=this.liveInfo.wsUrl
}
this.commentList=[] //创建新的socket连接前先清除之前的实时聊天记录
this.liveSocket?.close() //创建新的socket连接前确保旧的已关闭
//创建一个socket实例
this.liveSocket = new WebSocket(socketlink)
//监听socket打开
this.liveSocket.onopen = () => {
this.isSocketOpen = true
console.log('WebSocket连接已打开!');
}
//监听socket关闭
this.liveSocket.onclose = () => {
this.isSocketOpen = false
console.log('WebSocket连接已关闭!');
}
//监听socket错误
this.liveSocket.onerror = () => {
this.isSocketOpen = false
console.log('WebSocket连接打开失败');
}
//监听socket消息,不是调用形式,getComment后面不要加()
this.liveSocket.onmessage = this.getComment
//先确保清除了之前的心跳定时器
clearInterval(this.pingpangTimer)
//每过一段时间发送一次心跳,发送Ping,服务器会反馈pong,防止断连
this.pingpangTimer = setInterval(() => {
this.liveSocket.send("ping");
},60000)
},
//监听socket消息
getComment(res){
let infos=JSON.parse(res.data)
console.log(infos)
// type类型:0-普通发言;1-管理员发言;2-欢迎提示;3-系统消息;4-未登录;5-禁言通知;6-ping;7-错误提示;8-初始会返回的整个聊天数据列表
const allowType=[0,1,2,3,4,5] //这些类型的数据将允许被推入聊天数据列表
if(infos.type==8){
this.commentList=this.commentList.concat(infos.list) //需要取infos下的list,数据结构和后端商定
let scrolltimer=setTimeout(()=>{ //自动滚动到底部
document.getElementById('comment-list').scrollTop=this.commentList.length*300 //偷懒了,较佛系的办法-_-,假定平均每条评论所占区域高度300。。。
clearTimeout(scrolltimer)
},600)
}else if(allowType.includes(infos.type)){ //后续每更新一条有效的新数据时触发(标准参考上面allowType)
this.commentList=this.commentList.concat(infos) //返回单个的聊天数据对象
let scrolltimer=setTimeout(()=>{
document.getElementById('comment-list').scrollTop=this.commentList.length*300
clearTimeout(scrolltimer)
},150)
if(infos.type==4){ //未登录,清除用户信息和token
//do something
}
//......
}else if(infos.type==7){ //出现错误
//do something
}
},
//发表评论
sendComment(){
if(this.commentValue==""){
this.$message.info("说点什么吧 ~")
}else if(this.commentValue.length>300){
this.$message.info(`评论字数请勿超过200个字符,当前 ${this.commentValue.length}`)
}else{
if(this.userInfo.tokenValue){ //已登录
if(this.isSocketOpen){ //socket连接正常
// 如果后端规定了评论数据格式,则按照后端的传,注意socket.send需要传字符串,其他类型需要转下
// let theValue={
// "ccontent":this.commentValue
// }
// let transedValue=JSON.stringify(theValue)
// this.liveSocket.send(transedValue);
this.liveSocket.send(this.commentValue) //如果后端没规定,直接传评论内容即可
this.commentValue=""
}else{ //socket已断开
this.$message.info('聊天断开啦,请重新进入此页面尝试 ~')
}
}else{ //未登录
this.$message.info("您尚未登录,请登录后再试")
}
}
},
}
}
</script>
<style scoped lang="less">
.chat-content{
width: 300px;
height: 600px;
.comment-list{
width: 100%;
height: 100%;
padding: 20px 20px;
box-sizing: border-box;
overflow-y: auto;
.every-comment{
margin-bottom: 20px;
.every-comment-user{
......
}
.every-comment-admin{
......
}
......
}
}
}
</style>
相关api