- 登录成功后建立WebSocket链接,使用心跳机制保持连接状态
- 后端根据用户权限选择关闭或保持连接状态
- 收到消息时创建一个notify并以id作为key值保存到通知对象中
- notify自动消失前点击详情按钮视为消息已读
- 5秒后自动消失视为未读,关闭事件中设置未读数量加1,删除对象中相应notify实例
具体实现如下:
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions, mapMutations } = createNamespacedHelpers(
'message'
)
export default {
data() {
return {
notifyObj: {},
}
},
// 监听消息对象
watch: {
notice: {
handler(newValue) {
if (newValue.createTime) {
this.openNotify(newValue)
const dateTime = moment().format('YYYY-MM-DD HH:mm:ss')
this.$iNotify({
title: `消息提示`,
body: newValue.messageContent + '\r\n' + dateTime,
account: newValue.account,
type: newValue.type,
uniqueid: newValue.uniqueid
})
}
}
},
deep: true,
immediate: true
},
// 弹出新消息通知
openNotify(mess) {
const h = this.$createElement
const notify = this.$notify({
duration: 3000,
customClass: 'message-notify',
onClose: () => {
this.closeNotify(mess)
},
message: h(
'div',
{
class: ['notice-con']
},
[
h(
'p',
{
class: ['notice-title']
},
[
h('span', {
class: ['el-icon-warning', 'notice-icon']
}),
'消息提示'
]
),
h(
'p',
{
class: ['notice-text']
},
mess.messageContent
),
h(
'el-button',
{
class: ['fr'],
attrs: {
type: 'primary',
size: 'mini'
},
on: {
click: () => {
mess.isRead = 1
this.toDetail(mess)
}
}
},
'督导'
)
]
)
})
this.notifyObj[mess.id] = notify
},
// 关闭消息弹窗
closeNotify(mess) {
delete this.notifyObj[mess.id]
if (!mess.isRead) {
this.messageCount++
}
if (this.show) {
this.$refs.messagePop.list.unshift(mess)
}
},
}
notify的onClose 在5秒自动关闭和手动关闭的情况下都会触发,但要区分两种情况,需要在弹窗内部的click事件中为对象添加标识,这是使用的isRead, 1表示手动点的关闭,0表示5秒后自动关闭,this.notifyObj用来存储notify实例,关闭时通过id进行删除对应实例
import store from '@/store/'
import * as types from '@/store/types'
import { Message } from 'element-ui'
import { socketUrl, id } from './config'
class Ws {
constructor(options = {}) {
this.account = options.account
this.token = options.token
this.url = `${socketUrl}/message/${this.account}/${id}`
this.timer = null
this.closeTimer = null
this.time = 30 * 1000
this.isHeart = false
this.ws = null
this.isMyClose = false
this.create()
}
create() {
this.ws = new WebSocket(this.url)
this.ws.onclose = this.onclose
this.ws.onerror = this.onerror
this.ws.onopen = this.onopen
this.ws.onmessage = this.onmessage
}
close = () => {
this.isMyClose = true
this.ws.close()
}
send = (obj = {}) => {
this.ws.send(JSON.stringify(obj))
}
heartCheck = () => {
clearTimeout(this.timer)
this.timer = setInterval(() => {
if (this.isHeart) {
this.send({ type: 1, data: { heartCheck: true } })
this.isHeart = false
} else {
this.create()
}
}, this.time)
}
onclose = (e) => {
if (e.code === 3000 || e.code === 3001) {
console.log(e, '没有消息提醒权限')
clearInterval(this.timer)
} else if (!this.isMyClose) {
clearTimeout(this.closeTimer)
this.closeTimer = setTimeout(() => {
this.create()
}, 5 * 1000)
} else {
clearInterval(this.timer)
if (e.reason) {
Message.error(e.reason)
}
}
}
onerror = () => {}
onopen = () => {
this.isHeart = true
this.send({ type: 0, data: this.token })
this.heartCheck()
}
onmessage = (e) => {
const data = e.data
try {
const obj = JSON.parse(data)
if (obj.heartCheck) {
this.isHeart = true
return
}
// 接收消息
store.commit(`message/${types.SET_NOTICE}`, obj)
} catch (error) {
this.isHeart = true
console.log(error)
}
}
}
export default Ws
import Ws from '@/utils/WebsocketMessage'
import * as types from '@/store/types'
// import { } from '@/api/message'
import store from '../index'
const state = {
ws: null,
notice: {}
}
const mutations = {
[types.SET_WEBSCOKET_MESSAGE](state, ws) {
state.ws = ws
},
[types.CLOST_WEBSCOKET_MESSAGE](state) {
state.ws = null
state.notice = {}
},
[types.SET_NOTICE](state, data) {
state.notice = { ...data }
}
}
const actions = {
// 设置websocket
[types.SET_WEBSCOKET_MESSAGE]({ commit }) {
const ws = new Ws({
account: store.state.user.detail.account,
id: store.state.user.detail.id,
token: store.state.user.token
})
commit(types.SET_WEBSCOKET_MESSAGE, ws)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
本文介绍了如何在Vue项目中利用ElementUI实现消息通知功能,并结合WebSocket保持实时通信。登录成功后,建立WebSocket连接并采用心跳机制维持连接状态。根据用户权限决定关闭或保持连接。当收到消息时,创建notify并存储,用户点击详情视为已读,否则5秒后自动关闭视为未读。在notify的onClose事件中,通过isRead字段区分手动与自动关闭,并更新未读消息计数。
1287

被折叠的 条评论
为什么被折叠?



