From 98d50099c44367aff79cd781369911d567447d05 Mon Sep 17 00:00:00 2001 From: fanluyan <754122931@qq.com> Date: Thu, 4 Jul 2024 11:25:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0websocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- socket/index.js | 138 ++++++++++++++++++++++++++++++++++++++++++++++++ src/App.vue | 21 ++++++++ src/main.js | 4 ++ 3 files changed, 163 insertions(+) create mode 100644 socket/index.js diff --git a/socket/index.js b/socket/index.js new file mode 100644 index 0000000..554453a --- /dev/null +++ b/socket/index.js @@ -0,0 +1,138 @@ +import { Notification } from "element-ui"; + +let hasShownNotification = false; +// WebSocket连接实例 +let socket = null; + +// 是否正在尝试重连 +let lockReconnect = false; + +// 心跳间隔,20秒 +const timeout = 20 * 1000; + +// 心跳定时器 +let timeoutObj = null; + +// 服务器无响应超时定时器 +let serverTimeoutObj = null; + +// 重连定时器 +let reconnectTimeout = null; + +// 初始化WebSocket连接 +const initWebSocket = () => { + if ("WebSocket" in window) { + const protocol = window.location.protocol === "https:" ? "wss://" : "ws://"; + const wsPath = "/api/xymanager/websocket"; + const wshost = + window.location.hostname === "localhost" + ? "61.169.135.146:40085" + : window.location.host; + const wsUrl = protocol + wshost + wsPath; + + socket = new WebSocket(wsUrl); + + socket.onerror = webSocketOnError; + socket.onmessage = webSocketOnMessage; + socket.onclose = closeWebsocket; + socket.onopen = openWebsocket; + } else { + // 浏览器不支持WebSocket + console.error("您的浏览器不支持WebSocket"); + // 这里可以添加更友好的提示方式,如使用Element UI的Notification + } +}; + +// 打开WebSocket连接时执行 +const openWebsocket = () => { + console.log("WebSocket链接成功"); + startHeartbeat(); +}; + +// 启动心跳 +const startHeartbeat = () => { + timeoutObj = setTimeout(() => { + if (socket.readyState === WebSocket.OPEN) { + socket.send("1"); // 发送心跳消息 + console.log("发送心跳消息以保持WebSocket连接活跃"); + + // 如果需要,可以在这里添加检测服务器响应的逻辑 + // 例如,设置一个服务器响应超时检测 + + // 递归调用以继续发送心跳 + startHeartbeat(); + } else { + // 如果WebSocket已经关闭,则不再发送心跳 + console.log("WebSocket连接已关闭,停止发送心跳"); + clearTimeout(timeoutObj); // 清除定时器 + } + }, timeout); +}; + +// WebSocket错误处理 +const webSocketOnError = (e) => { + console.error("WebSocket发生错误:", e); + // 这里通常不需要立即重连,因为onclose会处理重连逻辑 +}; + +// 处理接收到的消息 +const webSocketOnMessage = (e) => { + // 自定义事件,将接收到的数据派发给其他监听器 + window.dispatchEvent( + new CustomEvent("onmessageWS", { detail: { data: e.data } }) + ); + // 收到消息后重置心跳定时器 + resetHeartbeat(); +}; + +// WebSocket关闭处理 +const closeWebsocket = (e) => { + console.log("WebSocket连接已关闭:", e); + // if (!hasShownNotification) { + // Notification({ + // title: "告警", + // message: "WebSocket连接已关闭", + // position: "bottom-right", + // type: "warning", + // duration: 2000, + // }); + // hasShownNotification = true; // 更新状态,防止再次显示 + // } + + // 清除所有定时器 + clearTimeout(timeoutObj); + clearTimeout(serverTimeoutObj); + // 设置重连定时器 + reconnectTimeout = setTimeout(() => { + initWebSocket(); + }, 60 * 1000); // 60秒后重连 +}; + +// 重置心跳定时器 +const resetHeartbeat = () => { + clearTimeout(timeoutObj); + clearTimeout(serverTimeoutObj); + startHeartbeat(); +}; + +// 发送消息到WebSocket服务器 +const sendWebsocket = (data) => { + if (socket && socket.readyState === WebSocket.OPEN) { + socket.send(data); + } else { + console.error("WebSocket未连接,无法发送消息"); + } +}; + +// 关闭WebSocket连接(通常不需要在前端主动调用,除非有特定需求) +const close = () => { + if (socket) { + socket.close(); + } +}; + +// 导出相关函数,以便在其他地方使用 +export default { initWebSocket, sendWebsocket, close }; + +// 注意:关于离开页面不断开WebSocket连接的需求,这通常取决于浏览器的行为。 +// 在一些情况下,浏览器会在页面卸载时自动关闭WebSocket连接。 diff --git a/src/App.vue b/src/App.vue index cc9b0ae..e52f581 100644 --- a/src/App.vue +++ b/src/App.vue @@ -9,6 +9,11 @@ import { mapActions } from "vuex"; export default { name: "App", + async mounted() { + this.initWebSocket(); + window.addEventListener("onmessageWS", this.getSocketData); + }, + methods: { ...mapActions("cache", ["addCache", "removeCache"]), // 收集缓存(通过监听) @@ -46,6 +51,19 @@ export default { this.cmpNames[name] = file; } }, + async initWebSocket() { + this.$websocket.initWebSocket(); + }, + getSocketData(res) { + console.log(res); + this.$notify({ + title: "告警", + message: res.detail.data, + position: "bottom-right", + type: "warning", + duration: 0, + }); + }, }, watch: { "$route.path": { @@ -55,6 +73,9 @@ export default { }, }, }, + destroyed() { + this.$websocket.close(); + }, }; diff --git a/src/main.js b/src/main.js index 6b58739..4da5711 100644 --- a/src/main.js +++ b/src/main.js @@ -15,6 +15,10 @@ Vue.use(ElementUI, { import * as echarts from "echarts"; Vue.prototype.$echarts = echarts; +//websocket +import websocket from "../socket/index"; +Vue.prototype.$websocket = websocket; + //字体自适应 import "./utils/rem";