Newer
Older
smart-metering-front / src / store / modules / websocket.ts
import { ElMessage } from 'element-plus'
import useUserStore from './user'

const useWebsocketStore = defineStore(
  'websocket',
  {
    state: () => ({
      // wsUrl: `ws://${import.meta.env.VITE_APP_API_BASEURL.split('://')[1]}/websocket/`,
      // wsUrl: 'ws://192.168.2.96:8085/websocket/',
      // wsUrl: 'ws://192.168.2.96:8088/websocket/', // 内网
      wsUrl: 'ws://222.187.140.114:8896/websocket/', // 外网

      websocket: null, // ws连接
      wsStatus: false, // websocket连接状态 true为连接
      wsPingTimer: null, // 心跳定时器
      wsPingTime: 60000, // 心跳定时时长
      wsReconnectCount: 0, // 重连次数
      wsReconnectTimer: null, // 重连定时器
      wsIsReconnect: true, // 是否重连
      messageList: [],
    }),
    getters: {},
    actions: {
      // 连接websocket
      initWebSocket() {
        if (typeof (WebSocket) === 'undefined') {
          ElMessage({
            message: '当前浏览器无法接收实时报警信息,请使用谷歌浏览器、火狐或360浏览器极速模式!',
            type: 'warning',
            // duration: 0,
          })
          this.wsIsReconnect = true
        }
        else {
          // 实例化socket
          console.log(`**********socketUrl************${this.wsUrl}-----${useUserStore().id}`)
          const socketUrl = this.wsUrl + useUserStore().id
          this.wsIsReconnect = false
          const socket = new WebSocket(socketUrl)
          this.websocket = socket
          // 监听socket打开
          socket.onopen = () => {
            console.log('浏览器WebSocket已打开')
            this.wsStatus = true
            const wsPingTimer = setInterval(() => {
              // 发送心跳
              if (this.wsStatus) {
                try {
                  socket.send(JSON.stringify({
                    id: useUserStore().id, // 用户id
                    type: 'heartbeat',
                  }))
                  console.log(`ping websocket${new Date()}`)
                }
                catch (err) {
                  console.log('心跳发送失败,执行重连', err)
                  console.log(`正在尝试重新连接${this.wsReconnectCount}${1}次`)
                  // 调用重新链接
                  this.reConnectWebsocket()
                  this.wsStatus = false
                }
              }
            }, this.wsPingTime)
            this.wsPingTimer = wsPingTimer
          }
          // 监听socket消息接收s
          socket.onmessage = (msg) => {
            console.log(msg, 'websocket初始')
            // 转换为json对象
            const data = JSON.parse(msg.data)
            console.log(data, 'websocket 返回消息')
            this.messageList.push(data)
          }
          // 监听socket错误
          socket.onerror = function () {
            ElMessage({
              message: '发生错误,请检查服务器后重新刷新页面',
              type: 'error',
              // duration: 0,
            })
          }
          // 监听socket关闭
          socket.onclose = () => {
            console.log('WebSocket已关闭')
            this.wsStatus = false
            if (this.wsPingTimer) {
              console.log('停止定时器')
              clearInterval(this.wsPingTimer)
              this.wsPingTimer = null
            }
            if (this.wsReconnectTimer) {
              clearTimeout(this.wsReconnectTimer)
              this.wsReconnectTimer = null
            }
            if (this.wsIsReconnect && this.wsReconnectCount === 0) {
              this.reConnectWebsocket()
            }
          }
        }
      },
      // 断开websocket
      destroyWebSocket() {
        this.wsIsReconnect = false
        if (this.websocket) {
          this.websocket.close()
        }
        if (this.wsPingTimer) {
          clearInterval(this.wsPingTimer)
          this.wsPingTimer = null
        }
        if (this.wsReconnectTimer) {
          clearTimeout(this.wsReconnectTimer)
          this.wsReconnectTimer = null
        }
        this.wsStatus = false
      },
      // websocket重连
      reConnectWebsocket() {
        console.log('重连', this.wsReconnectCount)
        // 逐渐延长重连时间
        var time = 3000
        if (this.wsReconnectCount < 20) {
          time = 3000
        }
        else if (this.wsReconnectCount < 50) {
          time = 10000
        }
        else if (this.wsReconnectCount < 100) {
          time = 450000
        }
        else {
          return false
        }
        const wsReconnectTimer = setTimeout(() => {
          this.initWebSocket()
        }, time)
        this.wsReconnectTimer = wsReconnectTimer
        this.wsReconnectCount = this.wsReconnectCount + 1
      },
      // 清空消息列表
      resetMessageList() {
        this.messageList = []
      },
      // 清空指定消息
      clearAppointMessage(message: any) {
        this.messageList = this.messageList.filter(item => item.id !== message.id)
      },
    },
  },
)
export default useWebsocketStore