From f3f68d45dc3ffed8f46499177d335609e71b20c1 Mon Sep 17 00:00:00 2001 From: fuguobin Date: Fri, 15 Sep 2023 17:37:46 +0800 Subject: [PATCH] =?UTF-8?q?websocket=E5=A2=9E=E5=8A=A0=E5=BF=83=E8=B7=B3?= =?UTF-8?q?=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 1 + .env.production | 3 +- README.md | 6 +- src/types/auto-imports.d.ts | 2 - src/utils/socket.ts | 84 +++++++++++++------ .../monitoring/screen/components/main.vue | 14 ++-- vite.config.ts | 58 +++++++------ 7 files changed, 103 insertions(+), 65 deletions(-) diff --git a/.env.development b/.env.development index e3ebad3..0aabab7 100644 --- a/.env.development +++ b/.env.development @@ -2,4 +2,5 @@ VITE_APP_ENV = 'development' VITE_APP_TITLE = 'vue-vite-project-admin' VITE_APP_PORT = 8089 +VITE_APP_WS_API = 'ws://board.heatiot.cn:8001/prod-api' ## websocket地址 VITE_APP_BASE_API = '/dev-api' ## '/dev-api'线上接口 '/mock'本地模拟数据 diff --git a/.env.production b/.env.production index 0fcf7f0..23cf18a 100644 --- a/.env.production +++ b/.env.production @@ -2,4 +2,5 @@ VITE_APP_ENV = 'production' VITE_APP_TITLE = 'vue-vite-project-admin' VITE_APP_PORT = 8089 -VITE_APP_BASE_API = 'http://board.heatiot.cn:8001/prod-api/' +VITE_APP_WS_API = 'ws://board.heatiot.cn:8001/prod-api' ## websocket地址 +VITE_APP_BASE_API = 'http://board.heatiot.cn:8001/prod-api/' ## 线上接口 diff --git a/README.md b/README.md index 33de8fd..415410c 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ ``` bash # install dependencies -npm install +pnpm install # serve with hot reload at localhost:8080 -npm run dev +pnpm run dev # build for production with minification -npm run build +pnpm run build ``` diff --git a/src/types/auto-imports.d.ts b/src/types/auto-imports.d.ts index 5742656..67e581d 100644 --- a/src/types/auto-imports.d.ts +++ b/src/types/auto-imports.d.ts @@ -2,7 +2,6 @@ export {} declare global { const EffectScope: typeof import('vue')['EffectScope'] - const ElForm: typeof import('element-plus/es')['ElForm'] const ElMessage: typeof import('element-plus/es')['ElMessage'] const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] const ElNotification: typeof import('element-plus/es')['ElNotification'] @@ -273,7 +272,6 @@ import { UnwrapRef } from 'vue' declare module 'vue' { interface ComponentCustomProperties { readonly EffectScope: UnwrapRef - readonly ElForm: UnwrapRef readonly ElMessage: UnwrapRef readonly ElMessageBox: UnwrapRef readonly ElNotification: UnwrapRef diff --git a/src/utils/socket.ts b/src/utils/socket.ts index c6c9470..6731015 100644 --- a/src/utils/socket.ts +++ b/src/utils/socket.ts @@ -2,29 +2,38 @@ * Author: Fu Guobin * Date: 2022/08/02 * Last Modified by: Fu Guobin - * Last Modified time: 2023/08/28 + * Last Modified time: 2023/09/15 * Copyright:Daniel(Fu Guobin) - * Description:websocket函数封装 + * Description:websocket方法封装 */ -import { reactive, toRefs } from 'vue'; -import { tableStore } from '@/store/modules/table'; import mitt from '@/plugins/bus'; -// const tableStoreCounter = tableStore(); class WebSocketService { + url: string; websocket: WebSocket | null; isInitialized: boolean; isConnected: boolean; + heartbeatInterval: number; + reconnectInterval: number; + maxReconnectAttempts: number; + reconnectAttempts: number; data: any; constructor() { + this.url = ''; this.websocket = null; this.isInitialized = false; - this.isConnected = false; + this.isConnected = false; //握手 + this.heartbeatInterval = 30000; // 默认心跳30秒 + this.reconnectInterval = 5000; // 默认重连5秒 + this.maxReconnectAttempts = 5; // 默认尝试重连5次 + this.reconnectAttempts = 0; this.data = null; } initialize(url: string): void { + //初始化 + this.url = url; this.websocket = new WebSocket(url); this.websocket.onopen = this.onOpen.bind(this); this.websocket.onclose = this.onClose.bind(this); @@ -34,24 +43,24 @@ class WebSocketService { } onOpen(): void { - this.isConnected = true; - // 进行握手操作,如果需要的话 - } - - onClose(): void { - this.isConnected = false; - // 关闭WebSocket连接的处理逻辑 + this.isConnected = true; // 进行握手操作,如果需要的话 + this.reconnectAttempts = 0; // 重置重连次数 + this.startHeartbeat(); } - onError(error: Event): void { - console.error('WebSocket error:', error); - // 错误处理的逻辑 + onSend(data: any): void { + //发送消息处理 + console.log('websocketSend:', JSON.stringify(data)); + if (this.isConnected) { + this.websocket?.send(JSON.stringify(data)); + } } onMessage(event: MessageEvent): void { + //获取消息处理 if (event.data != '连接成功') { const response = JSON.parse(event.data); - console.log("response:",response); + console.log('response:', response); this.data = response; // 处理返回的数据 if (response.code === 'datareal') { @@ -61,19 +70,40 @@ class WebSocketService { console.log('waring'); mitt.emit('waringMessage', response); } - // const oldData = tableStoreCounter.tableDataStore; - // const index = oldData.findIndex((obj) => obj.id === response.id); - // if (index !== -1) { - // oldData.splice(index, 1, response); - // } - // tableStoreCounter.tableDataAction(oldData); } } - send(data: any): void { - console.log('websocketSend:', JSON.stringify(data)); - if (this.isConnected) { - this.websocket?.send(JSON.stringify(data)); + onClose(): void { + // 关闭WebSocket连接的处理逻辑 + this.isConnected = false; + this.stopHeartbeat(); + if (this.reconnectAttempts < this.maxReconnectAttempts) { + setTimeout(() => { + this.reconnectAttempts++; + this.initialize(this.url); + }, this.reconnectInterval); + } + } + + onError(error: Event): void { + console.error('WebSocket error:', error); + // 错误处理的逻辑 + } + + startHeartbeat() { + // 发送心跳 + this.heartbeatInterval = setInterval(() => { + if (this.websocket?.readyState === WebSocket.OPEN) { + this.websocket.send('ping'); //心跳消息 + } + }, this.heartbeatInterval); + } + + stopHeartbeat() { + // 停止心跳 + if (this.heartbeatInterval) { + clearInterval(this.heartbeatInterval); + this.heartbeatInterval = 0; } } diff --git a/src/views/monitoring/screen/components/main.vue b/src/views/monitoring/screen/components/main.vue index 0f027f7..1bd11b5 100644 --- a/src/views/monitoring/screen/components/main.vue +++ b/src/views/monitoring/screen/components/main.vue @@ -16,8 +16,8 @@ + :column-config="{ resizable: true, useKey: true }" :row-config="{ useKey: true }" :span-method="mergeRowMethod" + :columns="tableColumn" :data="tableData" @cell-dblclick="cellDBLClickEvent">