webSocket
"@vueuse/core": "10.9.0"
webSocket.ts: import { useWebSocket, WebSocketStatus } from '@vueuse/core' import { getAccessToken } from '@/utils/auth' import * as localConfig from '@/localConfig.js' interface WebSocketOptions { autoReconnect?: boolean // 是否自动重连,可设置重试次数 // 是否启用心跳机制,可设置间隔时间 heartbeat?: { interval?: number pongTimeout?: number } onMessage?: (data: string) => void // 自定义消息处理回调函数 onConnected?: () => void // 连接成功时的回调函数 onDisconnected?: () => void // 断开连接时的回调函数 } // 消息处理 interface MessageHandler { (content: any): void } class WebSocketUtil { private serverAddress: string private ws: ReturnType<typeof useWebSocket> private messageHandlers: Map<string, MessageHandler[]> = new Map() // 存储不同类型消息的处理器映射表 private defaultOptions: WebSocketOptions = { autoReconnect: true, heartbeat: { interval: 10000, pongTimeout: 5000 } } /** * 构造函数初始化 WebSocket 连接 * @param url - 可选的 WebSocket 地址 * @param options - 配置选项 */ constructor(url: string, options: WebSocketOptions) { const finalOptions = { ...this.defaultOptions, ...options } this.serverAddress = this.buildWebSocketUrl(url) const wsUrl = this.serverAddress + '?token=' + getAccessToken() this.ws = useWebSocket(wsUrl, { autoReconnect: finalOptions.autoReconnect, heartbeat: finalOptions.heartbeat, onConnected: finalOptions.onConnected, onDisconnected: finalOptions.onDisconnected }) // 监听消息并分发到注册的处理器 this.setupMessageListener(finalOptions.onMessage) } /** * 构建 WebSocket URL * @param url - 用户传入的 URL(如果有的话) * @returns 完整的 WebSocket 连接地址 */ private buildWebSocketUrl(url?: string): string { if (url && url.startsWith('ws')) { return url } return localConfig.default.socket_url } /** * 设置消息监听器 * @param onMessage - 自定义消息处理函数 */ private setupMessageListener(onMessage?: (data: string) => void) { watchEffect(() => { if (!this.ws.data.value) return // 如果有自定义消息处理则先调用 if (onMessage) { onMessage(this.ws.data.value as string) return } // 默认消息处理逻辑 this.handleDefaultMessage(this.ws.data.value as string) }) } /** * 默认消息处理逻辑 * @param data - 接收到的消息数据 */ private handleDefaultMessage(data: string) { try { // 心跳消息 if (data === 'pong') { return } // 解析消息 const jsonMessage = JSON.parse(data) const type = jsonMessage.type // 找到对应类型的处理器 const handlers = this.messageHandlers.get(type) if (handlers) { handlers.forEach((handler) => handler(jsonMessage.content)) } } catch (error) { console.error('处理 WebSocket 消息异常:', error) } } /** * 注册特定类型的消息处理器 * @param type - 消息类型 * @param handler - 处理该类型消息的函数 */ onMessageType(type: string, handler: MessageHandler) { if (!this.messageHandlers.has(type)) { this.messageHandlers.set(type, []) } this.messageHandlers.get(type)!.push(handler) } /** * 发送消息 * @param type - 消息类型 * @param content - 消息内容 */ send(type: string, content: any) { const message = JSON.stringify({ type, content: typeof content === 'string' ? content : JSON.stringify(content) }) this.ws.send(message) } /** * 发送文本消息 * @param text - 要发送的文本内容 * @param toUserId - 目标用户的 ID(可选) */ sendMessage(text: string, toUserId?: string) { const content = { text, toUserId } this.send('message-send', content) } /** * 获取连接状态 * @returns 当前 WebSocket 连接状态 */ getStatus(): WebSocketStatus { return this.ws.status.value } /** * 判断是否已连接 * @returns 如果当前处于 OPEN 状态返回 true,否则返回 false */ isOpen(): boolean { return this.ws.status.value === 'OPEN' } /** * 打开连接 */ connect() { this.ws.open() } /** * 关闭连接 */ disconnect() { this.ws.close() } /** * 获取原始 WebSocket 对象(用于特殊需求) * @returns 原始的 WebSocket 对象 */ getRawWebSocket() { return this.ws } } // 添加全局实例映射表,用于存储已创建的 WebSocketUtil 实例 const webSocketInstanceMap = new Map<string, WebSocketUtil>() /** * 创建 WebSocket 实例的工厂函数 * @param url - WebSocket 地址 * @param options - 配置选项 * @returns 新创建的 WebSocketUtil 实例 */ export function createWebSocketUtil(url: string, options: WebSocketOptions = {}) { // 构建 WebSocket URL 作为唯一标识符 // const wsUrl = new WebSocketUtil(url, {}) console.log('wsUrl-192-', url) // 检查是否已存在相同 URL 的实例 if (webSocketInstanceMap.has(url)) { console.log('196-已存在相同 URL 的实例-') // 如果已存在,则直接返回已创建的实例 return webSocketInstanceMap.get(url)! } else { console.log('200-不存在相同 URL 的实例-') // 如果不存在,则创建新实例并存储 const newInstance = new WebSocketUtil(url, options) webSocketInstanceMap.set(url, newInstance) return newInstance } } export default WebSocketUtil 使用: import { createWebSocketUtil } from '@/utils/webSocket' const webSocketInstance = ref() const connectWebSocket = () => { // WebSocket 工具实例 webSocketInstance.value = createWebSocketUtil('') // 注册消息处理器 webSocketInstance.value.onMessageType('Notice_Push', (data) => { console.log('收到消息', data) ElNotification({ message: '收到消息:' + data, type: 'success', duration: 2000 }) // 处理消息 getList() }) } onMounted(() => { connectWebSocket() })
websocket更新el-table表格数据
//--------------------------------------websocket let didizhi = 'ws://10.10.160.191:8081/ws' let webljFn = (didizhi) => { let socket = new WebSocket(didizhi) //监听连接成功事件 socket.onopen = function(){ console.log('1.客户端连接上了服务器'); // socket.send('3.你好') } // 定义指标映射配置 const indicatorConfig = { 'FDFH': { index: 0, name: '机组发电负荷' }, 'JHFDFH': { index: 1, name: '计划发电负荷' }, 'FHL': { index: 2, name: '机组负荷率' }, 'GDMH': { index: 3, name: '供电煤耗' }, 'CYDL': { index: 4, name: '厂用电率' }, 'SO2PFND': { index: 5, name: 'SO2排放浓度' }, 'NOXPFND': { index: 6, name: 'NOX排放浓度' }, 'YCPFND': { index: 7, name: '烟尘排放浓度' }, 'JZYXZT': { index: 8, name: '机组运行状态' }, } // 定义机组映射 const unitConfig = { '1号机组': 'machine_1', '2号机组': 'machine_2' } //监听接收到的消息 socket.onmessage = async (event) => { if(event.data){ try { let item = JSON.parse(event.data) if(item.plantCode === 'CF') { // console.log(item) const machineKey = unitConfig[item.unitName]//'1号机组' const indicator = indicatorConfig[item.indicatorCode]//{ index: 0, name: '机组发电负荷(MW)' } if(machineKey && indicator) { // 更新数据 let result = Number(item.indicatorValue).toFixed(2) if(result == 0){ result = 0 } if(indicator.index != 8){ jizuData[indicator.index][machineKey] = result }else{ //机组运行状态 if(item.indicatorCode == 'JZYXZT'){ if(machineKey == 'machine_1'){ //1号机组 if(item.indicatorValue == '停运中'){ jizuList.value[0].status = '冷态' }else{ jizuList.value[0].status = '热态' } }else if(machineKey == 'machine_2'){ //2号机组 if(item.indicatorValue == '停运中'){ jizuList.value[1].status = '冷态' }else{ jizuList.value[1].status = '热态' } } } } /* if(indicator.index == 0){ //当前是发电负荷,发电负荷为负数或0,其他值都为0 if(Number(item.indicatorValue) <= 0){ jizuData[0][machineKey] = 0; jizuData[1][machineKey] = 0; jizuData[2][machineKey] = 0; jizuData[3][machineKey] = 0; jizuData[4][machineKey] = 0; jizuData[5][machineKey] = 0; jizuData[6][machineKey] = 0; jizuData[7][machineKey] = 0; }else{ //给发电负荷赋值 jizuData[0][machineKey] = Number(item.indicatorValue).toFixed(2) } }else{ //当前不是发电负荷,先判断发电负荷是否为0,如果为0,全部值都为0, if(jizuData[0][machineKey] == 0){ jizuData[0][machineKey] = 0; jizuData[1][machineKey] = 0; jizuData[2][machineKey] = 0; jizuData[3][machineKey] = 0; jizuData[4][machineKey] = 0; jizuData[5][machineKey] = 0; jizuData[6][machineKey] = 0; jizuData[7][machineKey] = 0; }else{ //发电负荷不为0再赋值 jizuData[indicator.index][machineKey] = Number(item.indicatorValue).toFixed(2) } } */ //机组负荷曲线---------------------------------------------------------- /* let obj = {} if(item.indicatorCode == 'FDFH'){ obj['发电负荷值'] = jizuData[0][machineKey]//本次发电负荷 obj['时间'] = dayjs(item.time).format("YYYY-MM-DD HH:mm")//本次时间 }else if(item.indicatorCode == 'JHFDFH'){ obj['计划发电负荷'] = jizuData[1][machineKey]//本次计划发电负荷 obj['时间'] = dayjs(item.time).format("YYYY-MM-DD HH:mm")//本次时间 } // console.log(obj) //四个折线初始化数组1440,值为0 //获取时间在一天数组中的索引位置,和值 //用索引在对应折线数组中找位置,将0替换为值 let jzjishuanFn = (jzVal) => { let timeMap = {}; // 提取时分部分作为键 const timeKey = jzVal['时间'].split(' ')[1]; // console.log(timeKey) let str = jzVal['发电负荷值'] // timeMap[timeKey] = parseFloat(str).toString(); // return jizuxData.map(timeStr => timeMap[timeStr] || 0); //索引,值 return [jizuxData.indexOf(timeKey),parseFloat(str).toString()] } let jzjhjishuanFn = (jzVal) => { let timeMap = {}; // 提取时分部分作为键 const timeKey = jzVal['时间'].split(' ')[1]; let str = jzVal['计划发电负荷'] // timeMap[timeKey] = parseFloat(str).toString(); // return jizuxData.map(timeStr => timeMap[timeStr] || 0); return [jizuxData.indexOf(timeKey),parseFloat(str).toString()] } if(machineKey == 'machine_1'){ if(item.indicatorCode == 'FDFH'){//1机组 console.log(obj) let resultJz1 = jzjishuanFn(obj) console.log(resultJz1) seriesJZFHQX[0].data[resultJz1[0]] = resultJz1[1] }else if(item.indicatorCode == 'JHFDFH'){//1机组计划 let resultJzJh1 = jzjhjishuanFn(obj) seriesJZFHQX[1].data[resultJzJh1[0]] = resultJzJh1[1] } }else if(machineKey == 'machine_2'){ if(item.indicatorCode == 'FDFH'){//2机组 let resultJz2 = jzjishuanFn(obj) seriesJZFHQX[2].data[resultJz2[0]] = resultJz2[1] }else if(item.indicatorCode == 'JHFDFH'){//2机组计划 let resultJzJh2 = jzjhjishuanFn(obj) seriesJZFHQX[3].data[resultJzJh2[0]] = resultJzJh2[1] } } let option = { xAxis: [{ data: jizuxData, }], series: seriesJZFHQX }; // console.log(seriesJZFHQX) */ // 触发响应式更新 await nextTick() jizuTableData.value = [...jizuData] // 更新图表 // loadChart.value!.update(option); // console.log(`更新 ${item.unitName} - ${indicator.name}:`, item.indicatorValue) } } } catch (error) { console.error('处理消息出错:', error) } } } //处理错误 socket.onerror = function(error) { console.error('WebSocket error:', error); }; //关闭事件 socket.onclose = function(event) { console.log('Connection closed:', event.code, event.reason); setTimeout(function() { console.log('重试连接') webljFn(didizhi) // socket = new WebSocket(didizhi); // 重新创建连接 }, 3000); // 3秒后重试连接 }; } webljFn(didizhi) //--------------------------------------websocket

浙公网安备 33010602011771号