| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- import { ref, reactive } from 'vue'
- import { useWebSocket } from '@vueuse/core'
- type EventHandler = (data: any) => void
- export function useSocketBus(deviceCode: string) {
- const url = `${import.meta.env.VITE_BASE_URL}/ws/${deviceCode}`
- // const url = `ws://192.168.188.149:8080/ws/${deviceCode}`
- // 响应式状态
- const status = ref<'CONNECTING' | 'OPEN' | 'CLOSED'>('CLOSED')
- const messages = ref<any[]>([])
- // 事件总线
- const events: Record<string, EventHandler[]> = reactive({})
- // 创建 WebSocket
- const { ws, open, close, send } = useWebSocket(url, {
- immediate: false,
- autoReconnect: {
- retries: 5,
- delay: 1000
- },
- onConnected(_ws) {
- console.log('✅ WebSocket 已连接')
- status.value = 'OPEN'
- },
- onDisconnected() {
- console.log('🔌 WebSocket 已断开')
- status.value = 'CLOSED'
- },
- onMessage(_ws, event) {
- try {
- const msg = JSON.parse(event.data)
- messages.value.push(msg)
- if (msg.event && events[msg.event]) {
- events[msg.event].forEach((cb) => cb(msg.data))
- }
- anyHandlers.forEach((cb) => cb(msg))
- } catch (err) {
- console.warn('非 JSON 消息:', event.data)
- }
- }
- })
- const anyHandlers: EventHandler[] = reactive([])
- // 注册所有事件回调
- function onAny(cb: EventHandler) {
- anyHandlers.push(cb)
- }
- // 注册事件
- function on(eventName: string, cb: EventHandler) {
- if (!events[eventName]) events[eventName] = []
- events[eventName].push(cb)
- }
- // 注销事件
- function off(eventName: string, cb?: EventHandler) {
- if (!cb) {
- events[eventName] = []
- } else {
- events[eventName] = (events[eventName] || []).filter((fn) => fn !== cb)
- }
- }
- // 发送带事件名的消息
- function sendEvent(eventName: string, data: any) {
- if (ws.value?.readyState === WebSocket.OPEN) {
- send(JSON.stringify({ event: eventName, data }))
- } else {
- console.warn('⚠️ WebSocket 未连接')
- }
- }
- return { ws, status, messages, on, off, sendEvent, open, close, onAny }
- }
- export const formatIotValue = (val: any) => {
- if (val === null || val === undefined) return { value: '0', isText: true }
- const strVal = String(val)
- if (!/\d/.test(strVal)) {
- return { value: strVal, isText: true }
- }
- const match = strVal.match(/^(-?\d+(?:\.\d+)?)(.*)$/)
- if (match) {
- return {
- value: match[1],
- suffix: match[2] || '',
- isText: false
- }
- }
- return { value: strVal, isText: true }
- }
- export interface HeaderItem {
- label: string
- key: string
- judgment?: boolean
- }
- export interface Dimensions {
- identifier: string
- name: string
- value: string | number
- color: string
- bgHover: string
- bgActive: string
- response?: boolean
- suffix?: string
- isText?: boolean
- minValue?: number
- maxValue?: number
- id?: number
- }
|