Browse Source

fix: 解决socket断开没有重新监听推送的问题

master
guoapeng 1 week ago
parent
commit
f33a54d401
  1. 2
      src/apis/system.ts
  2. 81
      src/app.vue
  3. 2
      src/assets/images/wifi-unconn.svg
  4. 3
      src/layouts/default.vue
  5. 35
      src/libs/socket.ts

2
src/apis/system.ts

@ -20,6 +20,7 @@ export async function sendCmd(resParams: System.SendCmdParams) {
return res.rely return res.rely
} }
else { else {
console.log(res)
throw new Error(res.message) throw new Error(res.message)
} }
} }
@ -40,6 +41,7 @@ export async function syncSendCmd(resParams: System.SendCmdParams) {
export async function subscribeEvent(fromFn: string | '*', callback: (response: Socket.WebSocketResponse) => void) { export async function subscribeEvent(fromFn: string | '*', callback: (response: Socket.WebSocketResponse) => void) {
wsClient.socket.addEventListener('message', (event) => { wsClient.socket.addEventListener('message', (event) => {
const data = JSON.parse(event.data) const data = JSON.parse(event.data)
// console.log(data)
if (data.messageType === 'Report' && data.fromFn === fromFn) { if (data.messageType === 'Report' && data.fromFn === fromFn) {
callback && callback(data) callback && callback(data)
} }

81
src/app.vue

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { isConnected } from 'libs/socket'
import { delToken } from 'libs/token' import { delToken } from 'libs/token'
import { useDebugStore } from 'stores/debugStore' import { useDebugStore } from 'stores/debugStore'
import { useDeviceStore } from 'stores/deviceStore' import { useDeviceStore } from 'stores/deviceStore'
@ -7,7 +8,7 @@ import { useHomeStore } from 'stores/homeStore'
import { useLiquidStore } from 'stores/liquidStore' import { useLiquidStore } from 'stores/liquidStore'
import { useSealStore } from 'stores/sealStore' import { useSealStore } from 'stores/sealStore'
import { useSystemStore } from 'stores/systemStore' import { useSystemStore } from 'stores/systemStore'
import { onBeforeMount, onUnmounted, ref } from 'vue'
import { onBeforeMount, onUnmounted, ref, watch } from 'vue'
import { sendCmd, subscribeEvent } from '@/apis/system' import { sendCmd, subscribeEvent } from '@/apis/system'
@ -40,39 +41,51 @@ onBeforeMount(async () => {
await systemStore.getSystemTime() // await systemStore.getSystemTime() //
await initDeviceInfo() await initDeviceInfo()
}) })
// store
subscribeEvent('stateUpdate', (data) => {
if (data.fromClass === 'AirLeakDetectTest') {
//
sealStore.updateSealInfo(data.rely)
}
else if (data.fromClass === 'AddLiquidService') {
//
liquidStore.updateAddLiquidWorkState(data.rely)
}
else if (data.fromClass === 'DrainLiquidService') {
//
liquidStore.updateDrainLiquidWorkState(data.rely)
}
else if (data.fromClass === 'DisinfectionCtrlServiceExt') {
//
homeStore.updateHomeDisinfectionState(data.rely)
}
else if (data.fromClass === 'H2O2SensorMgr') {
// console.log(data.rely)
//
homeStore.updateHomeData(data.rely)
}
else if (data.fromClass === 'AppCore') {
//
deviceStateStore.setDeviceState(data.rely)
systemStore.insertLogs(data.rely.appEvents)
}
else if (data.fromClass === 'TestPageCtrlService') {
//
debugStore.updateDebugPageState(data.rely)
}
})
watch(
() => isConnected.value,
(newVal) => {
console.log(newVal)
if (newVal) {
// store
subscribeEvent('stateUpdate', (data) => {
if (data.fromClass === 'AirLeakDetectTest') {
//
sealStore.updateSealInfo(data.rely)
}
else if (data.fromClass === 'AddLiquidService') {
//
liquidStore.updateAddLiquidWorkState(data.rely)
}
else if (data.fromClass === 'DrainLiquidService') {
//
liquidStore.updateDrainLiquidWorkState(data.rely)
}
else if (data.fromClass === 'DisinfectionCtrlServiceExt') {
//
homeStore.updateHomeDisinfectionState(data.rely)
}
else if (data.fromClass === 'H2O2SensorMgr') {
// console.log(data.rely)
//
homeStore.updateHomeData(data.rely)
}
else if (data.fromClass === 'AppCore') {
//
deviceStateStore.setDeviceState(data.rely)
systemStore.insertLogs(data.rely.appEvents)
}
else if (data.fromClass === 'TestPageCtrlService') {
//
debugStore.updateDebugPageState(data.rely)
}
})
}
},
{
immediate: true,
},
)
/** /**
* @function 启动初始化进度条 * @function 启动初始化进度条

2
src/assets/images/wifi-unconn.svg

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="42" height="32" viewBox="0 0 42 32"><g><path d="M37.9313,13.4957L41.7381,9.3913C30.2499,-3.13043,11.5561,-3.13043,0,9.3913L3.80673,13.4957C13.2556,3.26957,28.5505,3.26957,37.9313,13.4957ZM26.7853,18.9216C27.873,17.252,29.4365,15.8607,31.2039,14.9564C23.9303,9.73897,14.0736,10.6433,7.61573,17.5998L11.4225,21.7042C15.5691,17.1824,21.755,16.2781,26.7853,18.9216ZM37.9991,25.461L41.5339,29.0784C42.1457,29.7045,42.1457,30.748,41.4659,31.2349C40.9221,31.7915,40.1063,31.861,39.4945,31.4436L39.2906,31.2349L35.7558,27.6175L32.221,31.2349C31.6092,31.861,30.5895,31.861,29.9777,31.2349C29.4339,30.6784,29.3659,29.8436,29.7738,29.2175L29.9777,29.0088L33.5125,25.3915L29.9777,21.7741C29.3659,21.148,29.3659,20.1045,29.9777,19.4784C30.5215,18.9219,31.3373,18.8523,31.9491,19.2697L32.153,19.4784L35.7558,23.2349L39.2906,19.6175C39.9024,18.9915,40.9221,18.9915,41.5339,19.6175C42.0777,20.1741,42.1457,21.0088,41.7378,21.6349L41.5339,21.8436L37.9991,25.461ZM25.0157,25.0435L25.0157,24.5565C21.9567,22.5391,17.878,22.9565,15.2269,25.8087L20.937,32L25.2876,27.2696C25.0836,26.5739,25.0157,25.8087,25.0157,25.0435Z" fill-rule="evenodd" fill="#2892F3" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" version="1.1" width="42" height="32" viewBox="0 0 42 32"><g><path d="M37.9313,13.4957L41.7381,9.3913C30.2499,-3.13043,11.5561,-3.13043,0,9.3913L3.80673,13.4957C13.2556,3.26957,28.5505,3.26957,37.9313,13.4957ZM26.7853,18.9216C27.873,17.252,29.4365,15.8607,31.2039,14.9564C23.9303,9.73897,14.0736,10.6433,7.61573,17.5998L11.4225,21.7042C15.5691,17.1824,21.755,16.2781,26.7853,18.9216ZM37.9991,25.461L41.5339,29.0784C42.1457,29.7045,42.1457,30.748,41.4659,31.2349C40.9221,31.7915,40.1063,31.861,39.4945,31.4436L39.2906,31.2349L35.7558,27.6175L32.221,31.2349C31.6092,31.861,30.5895,31.861,29.9777,31.2349C29.4339,30.6784,29.3659,29.8436,29.7738,29.2175L29.9777,29.0088L33.5125,25.3915L29.9777,21.7741C29.3659,21.148,29.3659,20.1045,29.9777,19.4784C30.5215,18.9219,31.3373,18.8523,31.9491,19.2697L32.153,19.4784L35.7558,23.2349L39.2906,19.6175C39.9024,18.9915,40.9221,18.9915,41.5339,19.6175C42.0777,20.1741,42.1457,21.0088,41.7378,21.6349L41.5339,21.8436L37.9991,25.461ZM25.0157,25.0435L25.0157,24.5565C21.9567,22.5391,17.878,22.9565,15.2269,25.8087L20.937,32L25.2876,27.2696C25.0836,26.5739,25.0157,25.8087,25.0157,25.0435Z" fill-rule="evenodd" fill="#F56C6C" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>

3
src/layouts/default.vue

@ -5,6 +5,7 @@ import WifiUnconnSvg from 'assets/images/wifi-unconn.svg'
import NetReconnection from 'components/system/NetReconnection.vue' import NetReconnection from 'components/system/NetReconnection.vue'
import { ElMessageBox } from 'element-plus' import { ElMessageBox } from 'element-plus'
import { useActivateDebug } from 'hooks/useActivateDebug' import { useActivateDebug } from 'hooks/useActivateDebug'
import { isConnected } from 'libs/socket'
import { delToken } from 'libs/token' import { delToken } from 'libs/token'
import { formatDateTime } from 'libs/utils' import { formatDateTime } from 'libs/utils'
import { authRoutes } from 'router/routes' import { authRoutes } from 'router/routes'
@ -258,7 +259,7 @@ const handleCloseAll = async () => {
</div> </div>
<div class="user"> <div class="user">
<span v-if="deviceType === deviceStore.deviceTypeMap.LargeSpaceDM_B"> <span v-if="deviceType === deviceStore.deviceTypeMap.LargeSpaceDM_B">
<img v-if="websocketConnected" width="20" :src="WifiConnSvg" alt="">
<img v-if="isConnected" width="20" :src="WifiConnSvg" alt="">
<img v-else :src="WifiUnconnSvg" width="20" alt=""> <img v-else :src="WifiUnconnSvg" width="20" alt="">
</span> </span>
<el-select v-model="languageType" class="select-language" :disabled="false" @change="toggleLanguage"> <el-select v-model="languageType" class="select-language" :disabled="false" @change="toggleLanguage">

35
src/libs/socket.ts

@ -3,6 +3,7 @@ import { ref, watch } from 'vue'
import { FtMessageBox } from './messageBox' import { FtMessageBox } from './messageBox'
export const isConnected = ref(false)
// WebSocket客户端类 // WebSocket客户端类
export class WebSocketClient { export class WebSocketClient {
public socket: WebSocket public socket: WebSocket
@ -25,15 +26,36 @@ export class WebSocketClient {
// 创建WebSocket实例 // 创建WebSocket实例
private createWebSocket() { private createWebSocket() {
const socket = new WebSocket(this.url) const socket = new WebSocket(this.url)
let hearBeat_timer: any = null
const heartbeat = () => {
if (hearBeat_timer) {
clearInterval(hearBeat_timer)
}
hearBeat_timer = setInterval(() => {
heartSend()
}, 5000)
}
const heartSend = () => {
// 开启状态直接发送
if (socket.readyState === socket.OPEN) {
socket.send(JSON.stringify({ type: 'ping' }))
}
else {
clearInterval(hearBeat_timer)
}
}
heartbeat()
socket.onopen = () => { socket.onopen = () => {
this.isConnecting = false this.isConnecting = false
this.isConnected.value = true this.isConnected.value = true
isConnected.value = true
this.connectionError.value = null this.connectionError.value = null
this.connectCount = 0 this.connectCount = 0
clearInterval(this.intervalVal) clearInterval(this.intervalVal)
} }
socket.onclose = (event) => { socket.onclose = (event) => {
this.isConnected.value = false this.isConnected.value = false
isConnected.value = false
this.connectionError.value = `连接关闭: ${event.code} ${event.reason}` this.connectionError.value = `连接关闭: ${event.code} ${event.reason}`
// 非正常关闭时尝试重连 // 非正常关闭时尝试重连
if (event.code !== 1000) { if (event.code !== 1000) {
@ -42,6 +64,7 @@ export class WebSocketClient {
} }
socket.onerror = (error) => { socket.onerror = (error) => {
this.isConnected.value = false this.isConnected.value = false
isConnected.value = false
this.connectionError.value = `连接错误: ${(error as any).message || '未知错误'}` this.connectionError.value = `连接错误: ${(error as any).message || '未知错误'}`
this.scheduleReconnect() this.scheduleReconnect()
} }
@ -73,13 +96,13 @@ export class WebSocketClient {
request: Socket.WebSocketRequest, request: Socket.WebSocketRequest,
): Promise<Socket.WebSocketResponse & { rely: T }> { ): Promise<Socket.WebSocketResponse & { rely: T }> {
// 等待连接建立 // 等待连接建立
if (!this.isConnected.value) {
if (!isConnected.value) {
await new Promise<void>((resolve) => { await new Promise<void>((resolve) => {
if (this.isConnected.value) {
if (isConnected.value) {
resolve() resolve()
} }
else { else {
const watcher = watch(this.isConnected, (connected) => {
const watcher = watch(isConnected, (connected) => {
if (connected) { if (connected) {
watcher() // 停止监听 watcher() // 停止监听
resolve() resolve()
@ -89,7 +112,8 @@ export class WebSocketClient {
}) })
return this.sendRequest(request) return this.sendRequest(request)
} }
else { // 连接建立后发送请求
else {
// 连接建立后发送请求
return this.sendRequest(request) return this.sendRequest(request)
} }
} }
@ -99,7 +123,7 @@ export class WebSocketClient {
request: Socket.WebSocketRequest, request: Socket.WebSocketRequest,
): Promise<Socket.WebSocketResponse & { rely: T }> { ): Promise<Socket.WebSocketResponse & { rely: T }> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (this.isConnected.value) {
if (isConnected.value) {
this.socket.send(JSON.stringify(request)) this.socket.send(JSON.stringify(request))
this.responseHandlers.set(request.messageId, (response) => { this.responseHandlers.set(request.messageId, (response) => {
if (response.ackcode === 0) { if (response.ackcode === 0) {
@ -124,6 +148,7 @@ export class WebSocketClient {
else { else {
if (!this.isConnecting) { if (!this.isConnecting) {
this.reconnect() this.reconnect()
reject(new Error(`ws未连接`))
} }
} }
}) })

Loading…
Cancel
Save