采集从仪表盘组件挪进模块级单例(web/telemetry.ts),流量曲线和每路 吞吐的历史跨页面留存——跟着组件走的话切一次页面就清零一次。每路吞吐 从 /connections 快照按连接逐条求差再按 inboundName 聚合:先求和再求差 会在连接关闭时算出负数。 图表换 ECharts(按需注册):手写 SVG 折线做不出平滑曲线和时间轴, 颜色在运行时从 CSS 变量取,跟随主题切换重取。 路由列表每行带走势、速率和可选的公网 IP 检测,点击跳路由页并选中 那一路(外壳传 focus 给 RouterPage 消费)。
53 lines
1.4 KiB
Vue
53 lines
1.4 KiB
Vue
<script setup lang="ts">
|
|
/**
|
|
* ECharts 的最小封装:初始化、跟随 option 更新、跟随容器尺寸缩放、卸载时销毁。
|
|
*
|
|
* 按需注册而不是整包引入:仪表盘只用折线和环形图。调用方传新的 option 对象
|
|
* 触发更新(computed 每次重算都是新引用),这里不做深比较。
|
|
*/
|
|
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
import * as echarts from 'echarts/core'
|
|
import { LineChart, PieChart } from 'echarts/charts'
|
|
import { GridComponent, TooltipComponent } from 'echarts/components'
|
|
import { CanvasRenderer } from 'echarts/renderers'
|
|
import type { EChartsCoreOption } from 'echarts/core'
|
|
|
|
echarts.use([LineChart, PieChart, GridComponent, TooltipComponent, CanvasRenderer])
|
|
|
|
const props = defineProps<{ option: EChartsCoreOption }>()
|
|
|
|
const el = ref<HTMLElement | null>(null)
|
|
let chart: echarts.EChartsType | null = null
|
|
let observer: ResizeObserver | null = null
|
|
|
|
onMounted(() => {
|
|
if (!el.value) return
|
|
chart = echarts.init(el.value)
|
|
chart.setOption(props.option)
|
|
observer = new ResizeObserver(() => chart?.resize())
|
|
observer.observe(el.value)
|
|
})
|
|
|
|
watch(
|
|
() => props.option,
|
|
(option) => chart?.setOption(option),
|
|
)
|
|
|
|
onBeforeUnmount(() => {
|
|
observer?.disconnect()
|
|
chart?.dispose()
|
|
chart = null
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div ref="el" class="echart"></div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.echart {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
</style>
|