仪表盘重做:ECharts 曲线、常驻遥测、路由行直达详情

采集从仪表盘组件挪进模块级单例(web/telemetry.ts),流量曲线和每路
吞吐的历史跨页面留存——跟着组件走的话切一次页面就清零一次。每路吞吐
从 /connections 快照按连接逐条求差再按 inboundName 聚合:先求和再求差
会在连接关闭时算出负数。

图表换 ECharts(按需注册):手写 SVG 折线做不出平滑曲线和时间轴,
颜色在运行时从 CSS 变量取,跟随主题切换重取。

路由列表每行带走势、速率和可选的公网 IP 检测,点击跳路由页并选中
那一路(外壳传 focus 给 RouterPage 消费)。
This commit is contained in:
2026-08-11 22:26:36 +08:00
parent ce181e9ae5
commit eec5b791c8
15 changed files with 1385 additions and 376 deletions
File diff suppressed because it is too large Load Diff
+19 -2
View File
@@ -34,10 +34,15 @@ import InboundDetail from './InboundDetail.vue'
import InboundForm from './InboundForm.vue'
import IconAdd from '~icons/ri/add-line'
const props = defineProps<{ data: ConfigObject; revision: string }>()
const props = defineProps<{
data: ConfigObject
revision: string
/** 外部(仪表盘的路由行)指名要选中的一路。消费后通过 focus-done 请外壳清掉 */
focus?: string | null
}>()
/** 配置文件变了,需要重读整份配置。运行时的变化不走这里。 */
const emit = defineEmits<{ saved: [] }>()
const emit = defineEmits<{ saved: []; 'focus-done': [] }>()
const inbounds = computed(() => collectInbounds(props.data))
const subscriptions = computed(() => userProviders(props.data))
@@ -83,6 +88,18 @@ watch(
{ immediate: true },
)
// 带着指名跳进来时选中那一路。immediate 是因为组件随页签切换重建,
// watch 挂上时 focus 早就是最终值了,不 immediate 就永远等不到变化
watch(
() => props.focus,
(id) => {
if (!id) return
if (inbounds.value.some((i) => i.id === id)) selectedId.value = id
emit('focus-done')
},
{ immediate: true },
)
const selected = computed(() => inbounds.value.find((i) => i.id === selectedId.value) ?? null)
const takenNames = computed(() => inbounds.value.map((i) => i.name))