From f135e7f6fcfacefc4d7a3a046cc1a1703d655605 Mon Sep 17 00:00:00 2001 From: qian Date: Sun, 17 May 2026 08:37:28 +0800 Subject: [PATCH] =?UTF-8?q?improve(ui):=E4=BC=98=E5=8C=96=E5=AE=9E?= =?UTF-8?q?=E6=97=B6=E7=9B=91=E6=8E=A7=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/admin/src/views/DashboardPage.vue | 14 + web/admin/src/views/ai/ChannelDetailPage.vue | 11 + web/admin/src/views/monitor/MonitorPage.vue | 33 +- .../src/views/monitor/RealtimeMonitorPage.vue | 452 +++++++++--------- 4 files changed, 290 insertions(+), 220 deletions(-) diff --git a/web/admin/src/views/DashboardPage.vue b/web/admin/src/views/DashboardPage.vue index d975e3d..4500c7f 100644 --- a/web/admin/src/views/DashboardPage.vue +++ b/web/admin/src/views/DashboardPage.vue @@ -332,9 +332,21 @@ const resizeObserver = new ResizeObserver(() => { modelChart?.resize() }) +let resizeTimer: ReturnType | null = null + +function onWindowResize() { + if (resizeTimer) clearTimeout(resizeTimer) + resizeTimer = setTimeout(() => { + trendChart?.resize() + tenantTrendChart?.resize() + modelChart?.resize() + }, 200) +} + // === Lifecycle === onMounted(() => { fetchAll() + window.addEventListener('resize', onWindowResize) nextTick(() => { const trendEl = document.getElementById('trend-chart') const tenantEl = document.getElementById('tenant-trend-chart') @@ -346,6 +358,8 @@ onMounted(() => { }) onBeforeUnmount(() => { + window.removeEventListener('resize', onWindowResize) + if (resizeTimer) clearTimeout(resizeTimer) resizeObserver.disconnect() if (trendChart) { trendChart.dispose(); trendChart = null } if (tenantTrendChart) { tenantTrendChart.dispose(); tenantTrendChart = null } diff --git a/web/admin/src/views/ai/ChannelDetailPage.vue b/web/admin/src/views/ai/ChannelDetailPage.vue index 2f2d3e5..345a650 100644 --- a/web/admin/src/views/ai/ChannelDetailPage.vue +++ b/web/admin/src/views/ai/ChannelDetailPage.vue @@ -272,6 +272,14 @@ const trendLoading = ref(false) const trendData = ref([]) const trendHours = ref(24) let trendChart: echarts.ECharts | null = null +let resizeTimer: ReturnType | null = null + +function onWindowResize() { + if (resizeTimer) clearTimeout(resizeTimer) + resizeTimer = setTimeout(() => { + trendChart?.resize() + }, 200) +} async function fetchHealthTrend() { trendLoading.value = true @@ -328,6 +336,8 @@ function handleTrendHoursChange(val: string | number | boolean) { } onBeforeUnmount(() => { + window.removeEventListener('resize', onWindowResize) + if (resizeTimer) clearTimeout(resizeTimer) if (trendChart) { trendChart.dispose(); trendChart = null } }) @@ -379,6 +389,7 @@ async function handleClone(done: () => void) { onMounted(() => { fetchDetail() + window.addEventListener('resize', onWindowResize) }) function formatJson(str: string): string { diff --git a/web/admin/src/views/monitor/MonitorPage.vue b/web/admin/src/views/monitor/MonitorPage.vue index ee695ed..8c316d1 100644 --- a/web/admin/src/views/monitor/MonitorPage.vue +++ b/web/admin/src/views/monitor/MonitorPage.vue @@ -1,5 +1,5 @@ @@ -237,7 +260,7 @@ onMounted(() => { - + @@ -250,7 +273,7 @@ onMounted(() => { - + @@ -264,7 +287,7 @@ onMounted(() => { {{ num(dashboardData.api?.qps).toFixed(2) }} - + @@ -274,7 +297,7 @@ onMounted(() => { {{ num(dashboardData.api?.tpm).toFixed(0) }} - + diff --git a/web/admin/src/views/monitor/RealtimeMonitorPage.vue b/web/admin/src/views/monitor/RealtimeMonitorPage.vue index b9032ea..9772566 100644 --- a/web/admin/src/views/monitor/RealtimeMonitorPage.vue +++ b/web/admin/src/views/monitor/RealtimeMonitorPage.vue @@ -7,6 +7,7 @@ import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/compon import VChart from 'vue-echarts' import PageHeader from '@/components/PageHeader.vue' import request from '@/utils/request' +import { IconThunderbolt, IconSwap, IconClockCircle, IconCode, IconBarChart, IconLayers, IconApps, IconUserGroup, IconFire } from '@arco-design/web-vue/es/icon' use([CanvasRenderer, LineChart, BarChart, GridComponent, TooltipComponent, LegendComponent]) @@ -41,7 +42,6 @@ function formatTime(ts: string) { function updateCharts() { const history = data.value.history || [] const bwHistory = data.value.bandwidth_history || [] - const go = data.value.go_runtime || {} concurrencyOption.value = { tooltip: { trigger: 'axis' }, @@ -86,6 +86,7 @@ function updateCharts() { } // GC pause bar chart + const go = data.value.go_runtime || {} const gcPauses = (go.gc?.recent_pause_ms || []).slice().reverse() gcPauseOption.value = { tooltip: { trigger: 'axis', valueFormatter: (v: number) => v?.toFixed(2) + ' ms' }, @@ -134,7 +135,17 @@ const rt = computed(() => data.value.runtime || {}) const goRt = computed(() => data.value.go_runtime || {}) const mem = computed(() => goRt.value.memory || {}) const gc = computed(() => goRt.value.gc || {}) -const build = computed(() => goRt.value.build || {}) + +const heapUsagePercent = computed(() => { + const inuse = mem.value.heap_inuse_mb + const sys = mem.value.heap_sys_mb + if (!sys) return 0 + return Math.min(100, (inuse / sys) * 100) +}) + +const concurrencyChart = ref() +const bandwidthChart = ref() +const gcPauseChart = ref() const activeRequests = computed(() => { const reqs: any[] = data.value.active_requests || [] @@ -155,20 +166,23 @@ const byChannel = computed(() => { return entries.map(([k, v]) => ({ channel: k, count: v as number, pct: ((v as number) / max) * 100 })) }) -// Heap usage percentage for progress bar -const heapUsagePercent = computed(() => { - const inuse = mem.value.heap_inuse_mb - const sys = mem.value.heap_sys_mb - if (!sys) return 0 - return Math.min(100, (inuse / sys) * 100) -}) - let pollTimer: ReturnType | null = null +let resizeTimer: ReturnType | null = null + +function onWindowResize() { + if (resizeTimer) clearTimeout(resizeTimer) + resizeTimer = setTimeout(() => { + concurrencyChart.value?.resize?.() + bandwidthChart.value?.resize?.() + gcPauseChart.value?.resize?.() + }, 200) +} onMounted(() => { fetchRealtime() pollTimer = setInterval(fetchRealtime, 10000) elapsedTimer = setInterval(() => { now.value = Date.now() }, 1000) + window.addEventListener('resize', onWindowResize) }) onUnmounted(() => { @@ -180,114 +194,101 @@ onUnmounted(() => { clearInterval(elapsedTimer) elapsedTimer = null } + window.removeEventListener('resize', onWindowResize) + if (resizeTimer) clearTimeout(resizeTimer) })