From 1a1a3a9129d5bfa59e8c3e00bc18bd968e31403d Mon Sep 17 00:00:00 2001 From: zwq Date: Fri, 10 Oct 2025 14:41:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/dataBoard/components/LeftBottom.vue | 4 +- src/views/base/dataBoard/index.vue | 376 ++++++++++-------- 2 files changed, 211 insertions(+), 169 deletions(-) diff --git a/src/views/base/dataBoard/components/LeftBottom.vue b/src/views/base/dataBoard/components/LeftBottom.vue index e87564f3..b737414d 100644 --- a/src/views/base/dataBoard/components/LeftBottom.vue +++ b/src/views/base/dataBoard/components/LeftBottom.vue @@ -37,7 +37,9 @@ export default { this.outputData.push(item.outputNum) this.goodRateData.push(item.goodRate) }) + this.$nextTick(()=>{ this.initChart(); + }) } }, data() { @@ -281,4 +283,4 @@ export default { .qhd-chart-tooltip * { color: #fff !important; } - \ No newline at end of file + diff --git a/src/views/base/dataBoard/index.vue b/src/views/base/dataBoard/index.vue index 3b979572..82776338 100644 --- a/src/views/base/dataBoard/index.vue +++ b/src/views/base/dataBoard/index.vue @@ -1,17 +1,20 @@ @@ -28,212 +31,249 @@ import RightBottom from './components/RightBottom.vue'; import { debounce } from '@/utils/debounce'; import screenfull from 'screenfull'; import { getAccessToken } from '@/utils/auth'; -import store from "@/store"; +import store from '@/store'; export default { name: 'DataBoard', - components: { DataBoardHeader,LeftTop,LeftBottom,CenterTop,CenterBottomL,CenterBottomR,RightTop,RightBottom }, + components: { + DataBoardHeader, + LeftTop, + LeftBottom, + CenterTop, + CenterBottomL, + CenterBottomR, + RightTop, + RightBottom, + }, props: {}, data() { return { isFullScreen: false, scaleNum: 0.8, - dataObj:{}, - sseReader: null, // 保存流读取器 - abortController: null, // 用于中止 fetch 请求 - retryCount: 0, // 当前重试次数 - isDestroyed: false // 标记组件是否已销毁 + dataObj: {}, + sseReader: null, // 保存流读取器 + abortController: null, // 用于中止 fetch 请求 + retryCount: 0, // 当前重试次数 + isDestroyed: false, // 标记组件是否已销毁 }; }, created() { - this.init() - }, + this.init(); + }, mounted() { - this.boxReset = debounce(() => { - this.resetSize() - }, 300) - this.boxReset() - window.addEventListener('resize', () => { - this.boxReset() - }) - this.getData() + this.boxReset = debounce(() => { + this.resetSize(); + }, 300); + this.boxReset(); + window.addEventListener('resize', () => { + this.boxReset(); + }); + this.getData(); }, beforeDestroy() { - this.closeSSE(); - }, - destroyed() { - window.removeEventListener('resize', this.boxReset); - }, + this.closeSSE(); + }, + destroyed() { + window.removeEventListener('resize', this.boxReset); + }, computed: { sidebarOpened() { - return this.$store.state.app.sidebar.opened - } + return this.$store.state.app.sidebar.opened; + }, }, watch: { sidebarOpened(newVal, oldVal) { - this.boxReset() - } + this.boxReset(); + }, }, methods: { async getData() { let _this = this; if (_this.isDestroyed) return; - const url = process.env.VUE_APP_BASE_API+'/admin-api/monitoring/message/subscribe/'+store.getters.userId+'-'+Date.now(); - const token = getAccessToken() + const url = + process.env.VUE_APP_BASE_API + + '/admin-api/monitoring/message/subscribe/' + + store.getters.userId + + '-' + + Date.now(); + const token = getAccessToken(); const headers = new Headers({ - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'text/event-stream' - }); + Authorization: `Bearer ${token}`, + 'Content-Type': 'text/event-stream', + }); try { - // 创建中止控制器 - this.abortController = new AbortController(); - // 发起 fetch 请求(替换为你的接口地址) - const response = await fetch(url, { - method: 'GET', - headers: headers, - signal: _this.abortController.signal // 绑定中止信号 - }); + // 创建中止控制器 + this.abortController = new AbortController(); + // 发起 fetch 请求(替换为你的接口地址) + const response = await fetch(url, { + method: 'GET', + headers: headers, + signal: _this.abortController.signal, // 绑定中止信号 + }); - // 获取流读取器 - _this.sseReader = response.body.getReader(); - const decoder = new TextDecoder(); + // 获取流读取器 + _this.sseReader = response.body.getReader(); + const decoder = new TextDecoder(); + let buffer = ''; + let receivedBytes = 0; - // 持续读取流数据 - while (true) { - const { done, value } = await _this.sseReader.read(); - if (done) { - console.log('SSE 连接正常关闭'); - _this.handleReconnect(); // 触发重连 - break; - } - // 处理 SSE 事件数据 - const data = decoder.decode(value); - console.log('收到消息:', data); - if (_this.isValidData(data)){ - _this.upDateMsg(data); + // 持续读取流数据 + while (true) { + const { done, value } = await _this.sseReader.read(); + if (done) { + console.log('SSE 连接正常关闭'); + _this.handleReconnect(); // 触发重连 + break; } - } - } catch (error) { - // 主动中止的请求不报错 - if (error.name === 'AbortError') return; - console.error('SSE 连接异常:', error); - _this.handleReconnect(); // 触发重连 - } + // const data = decoder.decode(value); + // console.log('收到消息:', data); + + receivedBytes += value.length; + console.log( + `收到数据块: ${value.length} 字节, 累计: ${receivedBytes} 字节` + ); + const chunk = decoder.decode(value, { stream: true }); + buffer += chunk; + + // 处理完整的消息 + const messages = buffer.split('\n\n'); // SSE 消息以双换行分隔 + buffer = messages.pop() || ''; // 保留最后一个不完整的消息 + + for (const message of messages) { + if (_this.isValidData(message)) { + // console.log('完整 SSE 消息:', message); + _this.upDateMsg(message); + } + } + + // 处理 SSE 事件数据 + // const data = decoder.decode(value); + // console.log('收到消息:', data); + // if (_this.isValidData(data)){ + // _this.upDateMsg(data); + // } + } + } catch (error) { + // 主动中止的请求不报错 + if (error.name === 'AbortError') return; + console.error('SSE 连接异常:', error); + _this.handleReconnect(); // 触发重连 + } }, closeSSE() { - this.isDestroyed = true; // 标记销毁 - if (this.abortController) { - this.abortController.abort(); // 中止 fetch 请求 - } - if (this.sseReader) { - this.sseReader.cancel(); // 关闭流读取器 - this.sseReader = null; - } - console.log('SSE 连接已强制关闭'); - }, + this.isDestroyed = true; // 标记销毁 + if (this.abortController) { + this.abortController.abort(); // 中止 fetch 请求 + } + if (this.sseReader) { + this.sseReader.cancel(); // 关闭流读取器 + this.sseReader = null; + } + console.log('SSE 连接已强制关闭'); + }, handleReconnect() { - if (this.isDestroyed) return; - // 指数退避策略(最大重试 5 次) - const maxRetries = 5; - if (this.retryCount < maxRetries) { - const delay = Math.pow(2, this.retryCount) * 1000; - setTimeout(() => { - this.retryCount++; - this.initSSE(); - }, delay); - } else { - console.error('SSE 重连次数已达上限'); - } - }, - isValidData (data) { - return data.trim().startsWith('data:{') && !data.includes('heartbeat'); + if (this.isDestroyed) return; + // 指数退避策略(最大重试 5 次) + const maxRetries = 5; + if (this.retryCount < maxRetries) { + const delay = Math.pow(2, this.retryCount) * 1000; + setTimeout(() => { + this.retryCount++; + this.initSSE(); + }, delay); + } else { + console.error('SSE 重连次数已达上限'); + } + }, + isValidData(data) { + return data.trim().startsWith('data:{') && !data.includes('heartbeat'); }, upDateMsg(data) { - const jsonStr = data.replace(/^data:/, '').trim(); - console.log('jsonStr', jsonStr); + const jsonStr = data.replace(/^data:/, '').trim(); + console.log('jsonStr', jsonStr); try { const dataObj = JSON.parse(jsonStr); - this.dataObj = dataObj - console.log('dataObj',this.dataObj) + this.dataObj = dataObj; + console.log('dataObj', this.dataObj); } catch (e) { console.error('JSON 解析失败:', e); } }, change() { - this.isFullScreen = screenfull.isFullscreen - }, + this.isFullScreen = screenfull.isFullscreen; + }, init() { - if (!screenfull.isEnabled) { - this.$message({ - message: 'you browser can not work', - type: 'warning' - }) - return false - } - screenfull.on('change', this.change) - }, - destroy() { - if (!screenfull.isEnabled) { - this.$message({ - message: 'you browser can not work', - type: 'warning' - }) - return false - } - screenfull.off('change', this.change) - }, + if (!screenfull.isEnabled) { + this.$message({ + message: 'you browser can not work', + type: 'warning', + }); + return false; + } + screenfull.on('change', this.change); + }, + destroy() { + if (!screenfull.isEnabled) { + this.$message({ + message: 'you browser can not work', + type: 'warning', + }); + return false; + } + screenfull.off('change', this.change); + }, // 全屏 - screenfullChange() { - if (!screenfull.isEnabled) { - this.$message({ - message: 'you browser can not work', - type: 'warning' - }) - return false - } - screenfull.toggle(this.$refs.dataBoardBoxB) - }, + screenfullChange() { + if (!screenfull.isEnabled) { + this.$message({ + message: 'you browser can not work', + type: 'warning', + }); + return false; + } + screenfull.toggle(this.$refs.dataBoardBoxB); + }, resetSize() { - const dataBoardBox = document.getElementById('dataBoardBox') - const rw = parseFloat(window.innerWidth) - const rh = parseFloat(window.innerHeight) - const bw = parseFloat(dataBoardBox.style.width) - const bh = parseFloat(dataBoardBox.style.height) - let wx = 0 - let hy = 0 - if (screenfull.isFullscreen) { - wx = rw / bw - hy = rh / bh - } else { - if (this.$store.state.app.sidebar.opened) { - wx = (rw - 283) / bw - } else { - wx = (rw - 88) / bw - } - hy = (rh - 150) / bh - } - this.scaleNum = wx < hy ? wx : hy - }, + const dataBoardBox = document.getElementById('dataBoardBox'); + const rw = parseFloat(window.innerWidth); + const rh = parseFloat(window.innerHeight); + const bw = parseFloat(dataBoardBox.style.width); + const bh = parseFloat(dataBoardBox.style.height); + let wx = 0; + let hy = 0; + if (screenfull.isFullscreen) { + wx = rw / bw; + hy = rh / bh; + } else { + if (this.$store.state.app.sidebar.opened) { + wx = (rw - 283) / bw; + } else { + wx = (rw - 88) / bw; + } + hy = (rh - 150) / bh; + } + this.scaleNum = wx < hy ? wx : hy; + }, }, };