useVentWebSocket.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { reactive, unref, computed, ref, Ref, watchEffect, WatchStopHandle } from 'vue';
  2. import { useWebSocket as $useWebSocket } from '@vueuse/core';
  3. import { useGlobSetting } from '/@/hooks/setting';
  4. import { useUserStore } from '/@/store/modules/user';
  5. import { useVentStore } from '/@/store/modules/vent';
  6. import { getToken } from '/@/utils/auth';
  7. const glob = useGlobSetting();
  8. const userStore = useUserStore();
  9. const state = reactive({
  10. server:
  11. glob.domainUrl?.replace('https://', 'wss://').replace('http://', 'ws://') +
  12. '/deviceSocket/' +
  13. unref(userStore.getUserInfo).username +
  14. '?token=' +
  15. getToken(),
  16. sendValue: '',
  17. recordList: [] as { id: number; time: number; res: string }[],
  18. });
  19. const ventStore = useVentStore();
  20. const resultWebSocket = computed(() => {
  21. return ventStore.getResultWebSocket;
  22. });
  23. const data = computed(() => (resultWebSocket.value ? resultWebSocket.value.data : ''));
  24. const status = computed(() => (resultWebSocket.value ? resultWebSocket.value.status : ''));
  25. const stop = <Ref<WatchStopHandle>>ref();
  26. // [perf-base-v1] S-W 6d: 保存 vueuse 返回的真实 close,供 closeWebSocket 真实断开底层 socket
  27. let realClose: (() => void) | null = null;
  28. const startWatchEffect = () => {
  29. // [perf-base-v1] S-W 6d: 先 stop 旧 watcher 再注册,防重复调用时 watcher 叠加
  30. stop.value?.();
  31. stop.value = watchEffect(() => {
  32. if (status.value === 'OPEN' && !data.value) {
  33. try {
  34. resultWebSocket.value.send(state.sendValue);
  35. console.log(222, 'sendValue', state.sendValue, status.value);
  36. } catch (e) {
  37. console.error(e);
  38. }
  39. }
  40. if (data.value && status.value === 'OPEN') {
  41. try {
  42. const res = JSON.parse(data.value);
  43. if (res.cmd === 'monitordata') {
  44. state.recordList = [];
  45. const list: [] = res.msgTxt[0].datalist;
  46. list.forEach((item: any) => {
  47. const resultItem = { ...item };
  48. const readData = item.readData;
  49. for (const key in readData) {
  50. resultItem[key] = readData[key];
  51. }
  52. state.recordList.push(resultItem);
  53. });
  54. }
  55. } catch (error) {
  56. state.recordList.push({
  57. res: data.value,
  58. id: Math.ceil(Math.random() * 1000),
  59. time: new Date().getTime(),
  60. });
  61. }
  62. }
  63. });
  64. };
  65. function connectWebSocket() {
  66. if (!resultWebSocket.value) {
  67. console.log('测试链接。。。。');
  68. const result = $useWebSocket(state.server, {
  69. // [perf-base-v1] S-W 6d: 开启自动重连(保留心跳检测)
  70. autoReconnect: true,
  71. // 心跳检测
  72. heartbeat: true,
  73. //protocols: [token],
  74. });
  75. // [perf-base-v1] S-W 6d: 缓存真实 close(vueuse 显式 close 后 autoReconnect 不再触发)
  76. realClose = () => result.close();
  77. ventStore.setResultWebSocket(result);
  78. startWatchEffect();
  79. }
  80. }
  81. export function initWebSocket(sendValue) {
  82. if (resultWebSocket.value) {
  83. closeWebSocket();
  84. }
  85. state.sendValue = sendValue;
  86. connectWebSocket();
  87. }
  88. export function getRecordList() {
  89. return state.recordList;
  90. }
  91. export function closeWebSocket() {
  92. state.recordList = [];
  93. // [perf-base-v1] S-W 6d: 真实关闭底层 socket 并停掉 watcher(原实现只清 store 引用,socket 仍存活)
  94. try {
  95. realClose?.();
  96. } catch (e) {
  97. console.warn('[VentWebSocket] close 异常(忽略):', e);
  98. }
  99. realClose = null;
  100. stop.value?.();
  101. ventStore.setResultWebSocket(null);
  102. }