diff --git a/src/store/modules/websocket.ts b/src/store/modules/websocket.ts new file mode 100644 index 0000000..9d5a721 --- /dev/null +++ b/src/store/modules/websocket.ts @@ -0,0 +1,140 @@ +import { ElMessage } from 'element-plus' +import useUserStore from './user' + +const useWebsocketStore = defineStore( + 'websocket', + { + state: () => ({ + wsUrl: `ws://${import.meta.env.VITE_APP_API_BASEURL.split('://')[1]}/websocket/${useUserStore().id}`, + websocket: null, // ws连接 + wsStatus: false, // websocket连接状态 true为连接 + wsPingTimer: null, // 心跳定时器 + wsPingTime: 60000, // 心跳定时时长 + wsReconnectCount: 0, // 重连次数 + wsReconnectTimer: null, // 重连定时器 + wsIsReconnect: true, // 是否重连 + }), + getters: {}, + actions: { + // 连接websocket + initWebSocket() { + if (typeof (WebSocket) === 'undefined') { + ElMessage({ + message: '当前浏览器无法接收实时报警信息,请使用谷歌浏览器、火狐或360浏览器极速模式!', + type: 'warning', + // duration: 0, + }) + this.wsIsReconnect = true + } + else { + // 实例化socket + console.log(`**********socketUrl************${this.wsUrl}`) + this.wsIsReconnect = false + const socket = new WebSocket(this.wsUrl) + this.websocket = socket + // 监听socket打开 + socket.onopen = () => { + console.log('浏览器WebSocket已打开') + this.wsStatus = true + const wsPingTimer = setInterval(() => { + // 发送心跳 + if (this.wsStatus) { + try { + socket.send(JSON.stringify({ + id: useUserStore().id, // 用户id + type: 'heartbeat', + })) + console.log(`ping websocket${new Date()}`) + } + catch (err) { + console.log('心跳发送失败,执行重连', err) + console.log(`正在尝试重新连接${this.wsReconnectCount}${1}次`) + // 调用重新链接 + this.reConnectWebsocket() + this.wsStatus = false + } + } + }, this.wsPingTime) + this.wsPingTimer = wsPingTimer + } + // 监听socket消息接收s + socket.onmessage = (msg) => { + console.log(msg, 'websocket初始') + // 转换为json对象 + const data = JSON.parse(msg.data) + console.log(data, 'websocket 返回消息') + } + // 监听socket错误 + // const that = this + socket.onerror = function () { + ElMessage({ + message: '无法接收实时报警信息,请检查服务器后重新刷新页面', + type: 'error', + // duration: 0, + }) + // 调用重新链接 + // that.reConnectWebsocket() + } + // 监听socket关闭 + socket.onclose = () => { + console.log('WebSocket已关闭') + this.wsStatus = false + if (this.wsPingTimer) { + console.log('停止定时器') + clearInterval(this.wsPingTimer) + this.wsPingTimer = null + } + if (this.wsReconnectTimer) { + clearTimeout(this.wsReconnectTimer) + this.wsReconnectTimer = null + } + if (this.wsIsReconnect && this.wsReconnectCount === 0) { + this.reConnectWebsocket() + } + } + } + }, + // 断开websocket + destroyWebSocket() { + this.wsIsReconnect = false + if (this.websocket) { + this.websocket.close() + } + if (this.wsPingTimer) { + console.log('停止定时器') + clearInterval(this.wsPingTimer) + this.wsPingTimer = null + } + if (this.wsReconnectTimer) { + clearTimeout(this.wsReconnectTimer) + this.wsReconnectTimer = null + } + this.wsStatus = false + }, + // websocket重连 + reConnectWebsocket() { + console.log('重连', this.wsReconnectCount) + // 逐渐延长重连时间 + var time = 3000 + if (this.wsReconnectCount < 20) { + time = 3000 + } + else if (this.wsReconnectCount < 50) { + time = 10000 + } + else if (this.wsReconnectCount < 100) { + time = 450000 + } + else { + return false + } + const wsReconnectTimer = setTimeout(() => { + this.initWebSocket() + }, time) + this.wsReconnectTimer = wsReconnectTimer + this.wsReconnectCount = this.wsReconnectCount + 1 + }, + }, + }, +) +export default useWebsocketStore diff --git a/src/store/modules/websocket.ts b/src/store/modules/websocket.ts new file mode 100644 index 0000000..9d5a721 --- /dev/null +++ b/src/store/modules/websocket.ts @@ -0,0 +1,140 @@ +import { ElMessage } from 'element-plus' +import useUserStore from './user' + +const useWebsocketStore = defineStore( + 'websocket', + { + state: () => ({ + wsUrl: `ws://${import.meta.env.VITE_APP_API_BASEURL.split('://')[1]}/websocket/${useUserStore().id}`, + websocket: null, // ws连接 + wsStatus: false, // websocket连接状态 true为连接 + wsPingTimer: null, // 心跳定时器 + wsPingTime: 60000, // 心跳定时时长 + wsReconnectCount: 0, // 重连次数 + wsReconnectTimer: null, // 重连定时器 + wsIsReconnect: true, // 是否重连 + }), + getters: {}, + actions: { + // 连接websocket + initWebSocket() { + if (typeof (WebSocket) === 'undefined') { + ElMessage({ + message: '当前浏览器无法接收实时报警信息,请使用谷歌浏览器、火狐或360浏览器极速模式!', + type: 'warning', + // duration: 0, + }) + this.wsIsReconnect = true + } + else { + // 实例化socket + console.log(`**********socketUrl************${this.wsUrl}`) + this.wsIsReconnect = false + const socket = new WebSocket(this.wsUrl) + this.websocket = socket + // 监听socket打开 + socket.onopen = () => { + console.log('浏览器WebSocket已打开') + this.wsStatus = true + const wsPingTimer = setInterval(() => { + // 发送心跳 + if (this.wsStatus) { + try { + socket.send(JSON.stringify({ + id: useUserStore().id, // 用户id + type: 'heartbeat', + })) + console.log(`ping websocket${new Date()}`) + } + catch (err) { + console.log('心跳发送失败,执行重连', err) + console.log(`正在尝试重新连接${this.wsReconnectCount}${1}次`) + // 调用重新链接 + this.reConnectWebsocket() + this.wsStatus = false + } + } + }, this.wsPingTime) + this.wsPingTimer = wsPingTimer + } + // 监听socket消息接收s + socket.onmessage = (msg) => { + console.log(msg, 'websocket初始') + // 转换为json对象 + const data = JSON.parse(msg.data) + console.log(data, 'websocket 返回消息') + } + // 监听socket错误 + // const that = this + socket.onerror = function () { + ElMessage({ + message: '无法接收实时报警信息,请检查服务器后重新刷新页面', + type: 'error', + // duration: 0, + }) + // 调用重新链接 + // that.reConnectWebsocket() + } + // 监听socket关闭 + socket.onclose = () => { + console.log('WebSocket已关闭') + this.wsStatus = false + if (this.wsPingTimer) { + console.log('停止定时器') + clearInterval(this.wsPingTimer) + this.wsPingTimer = null + } + if (this.wsReconnectTimer) { + clearTimeout(this.wsReconnectTimer) + this.wsReconnectTimer = null + } + if (this.wsIsReconnect && this.wsReconnectCount === 0) { + this.reConnectWebsocket() + } + } + } + }, + // 断开websocket + destroyWebSocket() { + this.wsIsReconnect = false + if (this.websocket) { + this.websocket.close() + } + if (this.wsPingTimer) { + console.log('停止定时器') + clearInterval(this.wsPingTimer) + this.wsPingTimer = null + } + if (this.wsReconnectTimer) { + clearTimeout(this.wsReconnectTimer) + this.wsReconnectTimer = null + } + this.wsStatus = false + }, + // websocket重连 + reConnectWebsocket() { + console.log('重连', this.wsReconnectCount) + // 逐渐延长重连时间 + var time = 3000 + if (this.wsReconnectCount < 20) { + time = 3000 + } + else if (this.wsReconnectCount < 50) { + time = 10000 + } + else if (this.wsReconnectCount < 100) { + time = 450000 + } + else { + return false + } + const wsReconnectTimer = setTimeout(() => { + this.initWebSocket() + }, time) + this.wsReconnectTimer = wsReconnectTimer + this.wsReconnectCount = this.wsReconnectCount + 1 + }, + }, + }, +) +export default useWebsocketStore diff --git a/src/views/dashboard/index.vue b/src/views/dashboard/index.vue index 988d7d3..1e9238e 100644 --- a/src/views/dashboard/index.vue +++ b/src/views/dashboard/index.vue @@ -5,11 +5,17 @@ -->