Commit 6665bfb8 by licheng

docs: 整理更新注释

parent 46a07fd2
<!-- 最初版本的波形图验证,推送的数据一直追加,服务端使用本目录下的lineChart1Server.js -->
<template> <template>
<el-card class="mb-20px" shadow="hover"> <el-card class="mb-20px" shadow="hover">
<el-skeleton :loading="loading" :rows="4" animated> <el-skeleton :loading="loading" :rows="4" animated>
......
const WebSocket = require("ws");
// 创建 WebSocket 服务器,监听 8080 端口
const wss = new WebSocket.Server({ port: 8080 });
console.log("WebSocket 服务器已启动,监听 ws://localhost:8080");
// 当有客户端连接时
wss.on("connection", (ws) => {
console.log("新客户端已连接");
const data = createData()
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(data));
}
// 设置定时器发送数据
const intervalId = setInterval(() => {
const data = createData(1000, 1)
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(data));
}
}, 2000);
// 当客户端断开连接时
ws.on("close", () => {
console.log("客户端已断开连接");
clearInterval(intervalId); // 清除定时器
});
});
function formatDate(date, format) {
const pad = (num) => num.toString().padStart(2, '0');
return format
.replace('HH', pad(date.getHours()))
.replace('mm', pad(date.getMinutes()))
.replace('ss', pad(date.getSeconds()));
}
// 生成模拟波形数据
function createData(
count = 40000,
dataCount = 1,
minValue = 50,
maxValue = 250
) {
const result = []
const now = new Date()
// 生成时间点(从当前时间往前递减)
const timeStamps = []
for (let i = count - 1; i >= 0; i--) {
const time = new Date(now.getTime() - i * 1000)
timeStamps.push(time)
}
// 初始化各数据项的值和方向
const dataValues = {}
const dataDirections = {}
for (let i = 1; i <= dataCount; i++) {
const key = `data${i}`
dataValues[key] = minValue + Math.random() * (maxValue - minValue) // 初始随机值
dataDirections[key] = Math.random() > 0.5 ? 1 : -1 // 随机初始方向
}
for (let i = 0; i < count; i++) {
const item = { name: formatDate(timeStamps[i], 'HH:mm:ss') }
// 为每个数据项生成波形数据
for (let j = 1; j <= dataCount; j++) {
const key = `data${j}`
const change = 10 + Math.random() * 30 // 变化幅度10~40(可调整)
// 随机决定是否改变方向(更自然的波动)
if (Math.random() < 0.2) {
// 20%概率改变方向
dataDirections[key] *= -1
}
dataValues[key] += dataDirections[key] * change
// 限制在合理范围内(但不强制反转)
dataValues[key] = Math.max(
minValue * 0.9, // 允许稍微低于最小值(避免卡边界)
Math.min(maxValue * 1.1, dataValues[key]) // 允许稍微高于最大值
)
item[key] = Math.round(dataValues[key])
}
result.push(item)
}
return result
}
\ No newline at end of file
<!-- 波形图和瀑布图组合,服务端使用 java 版本的websocket -->
<template>
<el-card class="mb-20px relative" shadow="hover">
<div class="absolute right-2 top-2 text-xs text-gray-500 z-10">
数据: {{ lineInfo.size }} 条 | FPS: {{ lineInfo.fps }}
</div>
<el-skeleton :loading="loading" :rows="4" animated>
<Echart :height="350" :options="lineOptionsData" />
</el-skeleton>
</el-card>
<el-card class="mb-20px px-[40px] relative" shadow="hover">
<div class="absolute right-2 top-2 text-xs text-gray-500 z-10">
大小: {{ waterfallInfo.size }} | FPS: {{ waterfallInfo.fps }}
</div>
<el-skeleton :loading="loading" :rows="4" animated>
<div class="flex justify-center font-700 text-[18px] mb-2">瀑布图</div>
<img id="waterfall" :src="waterfallImg" alt="waterfall" class="w-full h-[200px]" />
</el-skeleton>
</el-card>
</template>
<script lang="ts" setup>
import { set } from 'lodash-es'
import { EChartsOption } from 'echarts'
import 'echarts/lib/component/dataZoom'
import { lineOptions } from './echarts-data'
defineOptions({ name: 'Home2' })
const { t } = useI18n()
const loading = ref(true)
const lineOptionsData = reactive<EChartsOption>(lineOptions) as EChartsOption
let data: any[] = [] // 波形图数据
const waterfallImg = ref('') // 瀑布图图片
// 左上角显示用的数据
const lineInfo = ref({ size: 0, fps: 0 })
const waterfallInfo = ref({ size: '0 KB', fps: 0 })
// FPS 统计
let lineFrameCount = 0
let waterfallFrameCount = 0
setInterval(() => {
lineInfo.value.fps = lineFrameCount
waterfallInfo.value.fps = waterfallFrameCount
lineFrameCount = 0
waterfallFrameCount = 0
}, 1000)
// 初始数据
const getLineData = async () => {
set(
lineOptionsData,
'xAxis.data',
data.map((v) => t(v.name))
)
set(lineOptionsData, 'series', [
{
name: 'data1',
smooth: false,
type: 'line',
showSymbol: false,
progressive: 1000,
progressiveThreshold: 5000,
lineStyle: {
width: 1
},
sampling: 'lttb',
animation: false,
animationDuration: 1000,
animationEasing: 'linear',
data: data.map((v) => v.data1)
}
])
}
const connect = () => {
const socket = new WebSocket('ws://localhost:8025/ws/combined')
// const socket = new WebSocket('ws://localhost:8080')
socket.addEventListener('open', () => {
console.log('WebSocket 连接成功')
})
socket.addEventListener('message', (event) => {
const parsed = JSON.parse(event.data)
const newData = parsed.lineData
// 更新瀑布图
waterfallImg.value = `data:image/png;base64,${parsed.waterfallImg}`
// ---- 更新波形图信息 ----
lineInfo.value.size = newData.length
lineFrameCount++
// ---- 更新瀑布图信息 (计算 base64 大小) ----
const base64Str = parsed.waterfallImg
const strLen = base64Str.length
const fileSizeKB = (strLen * 3 / 4 / 1024).toFixed(2)
waterfallInfo.value.size = `${fileSizeKB} KB`
waterfallFrameCount++
// 更新图表数据
const newXAxisData = newData.map((item) => item.frequency)
set(lineOptionsData, 'xAxis.data', newXAxisData)
set(lineOptionsData, 'series', [
{
name: 'data1',
smooth: false,
type: 'line',
progressive: 1000,
progressiveThreshold: 5000,
showSymbol: false,
lineStyle: {
width: 0.5
},
sampling: 'lttb',
animation: false,
animationDuration: 1000,
animationEasing: 'linear',
data: [...newData.map((item) => item.value)]
}
])
})
}
const getAllApi = async () => {
await getLineData()
loading.value = false
connect()
}
getAllApi()
</script>
<style lang="scss" scoped></style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment