import { reactive, unref, computed, ref, Ref, watchEffect, WatchStopHandle } from 'vue'; import { useWebSocket as $useWebSocket } from '@vueuse/core'; import { useGlobSetting } from '/@/hooks/setting'; import { useUserStore } from '/@/store/modules/user'; import { useVentStore } from '/@/store/modules/vent'; import { getToken } from '/@/utils/auth'; const glob = useGlobSetting(); const userStore = useUserStore(); const state = reactive({ server: glob.domainUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/deviceSocket/' + unref(userStore.getUserInfo).username + '?token=' + getToken(), sendValue: '', recordList: [] as { id: number; time: number; res: string }[], }); const ventStore = useVentStore(); const resultWebSocket = computed(() => { return ventStore.getResultWebSocket; }); const data = computed(() => (resultWebSocket.value ? resultWebSocket.value.data : '')); const status = computed(() => (resultWebSocket.value ? resultWebSocket.value.status : '')); const stop = >ref(); // [perf-base-v1] S-W 6d: 保存 vueuse 返回的真实 close,供 closeWebSocket 真实断开底层 socket let realClose: (() => void) | null = null; const startWatchEffect = () => { // [perf-base-v1] S-W 6d: 先 stop 旧 watcher 再注册,防重复调用时 watcher 叠加 stop.value?.(); stop.value = watchEffect(() => { if (status.value === 'OPEN' && !data.value) { try { resultWebSocket.value.send(state.sendValue); console.log(222, 'sendValue', state.sendValue, status.value); } catch (e) { console.error(e); } } if (data.value && status.value === 'OPEN') { try { const res = JSON.parse(data.value); if (res.cmd === 'monitordata') { state.recordList = []; const list: [] = res.msgTxt[0].datalist; list.forEach((item: any) => { const resultItem = { ...item }; const readData = item.readData; for (const key in readData) { resultItem[key] = readData[key]; } state.recordList.push(resultItem); }); } } catch (error) { state.recordList.push({ res: data.value, id: Math.ceil(Math.random() * 1000), time: new Date().getTime(), }); } } }); }; function connectWebSocket() { if (!resultWebSocket.value) { console.log('测试链接。。。。'); const result = $useWebSocket(state.server, { // [perf-base-v1] S-W 6d: 开启自动重连(保留心跳检测) autoReconnect: true, // 心跳检测 heartbeat: true, //protocols: [token], }); // [perf-base-v1] S-W 6d: 缓存真实 close(vueuse 显式 close 后 autoReconnect 不再触发) realClose = () => result.close(); ventStore.setResultWebSocket(result); startWatchEffect(); } } export function initWebSocket(sendValue) { if (resultWebSocket.value) { closeWebSocket(); } state.sendValue = sendValue; connectWebSocket(); } export function getRecordList() { return state.recordList; } export function closeWebSocket() { state.recordList = []; // [perf-base-v1] S-W 6d: 真实关闭底层 socket 并停掉 watcher(原实现只清 store 引用,socket 仍存活) try { realClose?.(); } catch (e) { console.warn('[VentWebSocket] close 异常(忽略):', e); } realClose = null; stop.value?.(); ventStore.setResultWebSocket(null); }