From e2722801e4f03040a7303d980066589eebd30da9 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sat, 6 Jun 2026 17:56:44 +0800 Subject: [PATCH] feat(dashboard): enhance layout and responsiveness of dashboard components --- src/pages/dashboard.vue | 67 +++++++++++++++++++ src/views/dashboard/AnalyticsCpu.vue | 24 +++++-- .../dashboard/AnalyticsMediaStatistic.vue | 6 -- src/views/dashboard/AnalyticsMemory.vue | 24 +++++-- src/views/dashboard/AnalyticsNetwork.vue | 24 +++++-- src/views/dashboard/AnalyticsScheduler.vue | 15 +++-- src/views/dashboard/AnalyticsSpeed.vue | 13 +++- src/views/dashboard/AnalyticsStorage.vue | 3 - .../dashboard/AnalyticsWeeklyOverview.vue | 24 +++++-- src/views/dashboard/MediaServerLatest.vue | 10 ++- src/views/dashboard/MediaServerLibrary.vue | 5 +- src/views/dashboard/MediaServerPlaying.vue | 5 +- 12 files changed, 180 insertions(+), 40 deletions(-) diff --git a/src/pages/dashboard.vue b/src/pages/dashboard.vue index 065cee84..72adff32 100644 --- a/src/pages/dashboard.vue +++ b/src/pages/dashboard.vue @@ -71,6 +71,7 @@ const dashboardGridPendingContentResize = new Set() let dashboardGridContentObserver: ResizeObserver | null = null let dashboardGridContentResizeFrame: number | null = null +let dashboardGridResizeRefreshFrame: number | null = null // 是否正在手动缩放组件,避免自动测高抢回用户拖动中的高度。 const isDashboardGridResizing = ref(false) @@ -590,6 +591,7 @@ function initializeDashboardGrid() { dashboardGrid.value.on('dragstop', handleDashboardGridDragStop) dashboardGrid.value.on('resizestart', handleDashboardGridResizeStart) + dashboardGrid.value.on('resize', handleDashboardGridResize) dashboardGrid.value.on('resizestop', handleDashboardGridResizeStop) updateDashboardGridEditableState(isLayoutEditing.value) syncDashboardGrid() @@ -724,6 +726,12 @@ function handleDashboardGridResizeStart(_event: Event, element: GridItemHTMLElem isDashboardGridResizing.value = true dashboardGridResizeStartHeights.set(id, element.gridstackNode?.h) + notifyDashboardContentResize() +} + +// 在用户缩放过程中通知图表、虚拟网格等内容重新读取容器尺寸。 +function handleDashboardGridResize() { + notifyDashboardContentResize() } // 保存用户拖动后的位置,并保持未手动调高组件继续按内容自适应。 @@ -740,9 +748,20 @@ function handleDashboardGridResizeStop(_event: Event, element: GridItemHTMLEleme dashboardGridResizeStartHeights.delete(id) isDashboardGridResizing.value = false + notifyDashboardContentResize() compactAndPersistDashboardGrid(heightChanged ? id : false) } +// 合并连续 resize 通知,模拟浏览器窗口变化让组件内部内容自适配新尺寸。 +function notifyDashboardContentResize() { + if (typeof window === 'undefined' || dashboardGridResizeRefreshFrame !== null) return + + dashboardGridResizeRefreshFrame = window.requestAnimationFrame(() => { + dashboardGridResizeRefreshFrame = null + window.dispatchEvent(new Event('resize')) + }) +} + // 将 GridStack 保存结果归一化为本地布局覆盖表。 function persistDashboardGridLayout(manualHeightId: string | false = false) { if (!dashboardGrid.value || isSyncingDashboardGrid.value) return @@ -831,6 +850,10 @@ onBeforeUnmount(() => { cancelAnimationFrame(dashboardGridContentResizeFrame) dashboardGridContentResizeFrame = null } + if (dashboardGridResizeRefreshFrame !== null) { + cancelAnimationFrame(dashboardGridResizeRefreshFrame) + dashboardGridResizeRefreshFrame = null + } dashboardGridPendingContentResize.clear() dashboardGridResizeStartHeights.clear() dashboardGrid.value?.destroy(false) @@ -900,6 +923,17 @@ onBeforeUnmount(() => { margin-block: -6px 0; } +.dashboard-grid :deep(.v-card) { + overflow: hidden; + box-shadow: var(--app-surface-shadow) !important; +} + +@media (hover: hover) { + .dashboard-grid :deep(.v-card:hover) { + box-shadow: var(--app-surface-hover-shadow) !important; + } +} + .dashboard-grid-item.is-manual-height :deep(.v-card) { block-size: 100%; } @@ -928,6 +962,39 @@ onBeforeUnmount(() => { block-size: 100%; } +.dashboard-grid :deep(.dashboard-chart-card), +.dashboard-grid :deep(.dashboard-summary-card), +.dashboard-grid :deep(.dashboard-work-card), +.dashboard-grid :deep(.dashboard-media-card) { + display: flex; + flex-direction: column; + min-block-size: 0; +} + +.dashboard-grid :deep(.dashboard-chart-card .v-card-text), +.dashboard-grid :deep(.dashboard-work-card .v-card-text), +.dashboard-grid :deep(.dashboard-card-grid-wrap) { + flex: 1 1 auto; + min-block-size: 0; +} + +.dashboard-grid:not(.is-editing) .dashboard-grid-item:not(.is-manual-height) :deep(.dashboard-summary-card) { + min-block-size: 160px; +} + +.dashboard-grid:not(.is-editing) .dashboard-grid-item:not(.is-manual-height) :deep(.dashboard-chart-card) { + min-block-size: 256px; +} + +.dashboard-grid:not(.is-editing) .dashboard-grid-item:not(.is-manual-height) :deep(.dashboard-work-card) { + min-block-size: 352px; +} + +.dashboard-grid.is-editing :deep(.v-card-text), +.dashboard-grid-item.is-manual-height :deep(.v-card-text) { + overflow: auto; +} + .dashboard-grid-drag-handle { position: absolute; z-index: 10; diff --git a/src/views/dashboard/AnalyticsCpu.vue b/src/views/dashboard/AnalyticsCpu.vue index 25a9431d..7cabc2c1 100644 --- a/src/views/dashboard/AnalyticsCpu.vue +++ b/src/views/dashboard/AnalyticsCpu.vue @@ -139,8 +139,10 @@ useKeepAliveRefresh(refresh) CPU - - + +
+ +

{{ t('dashboard.current') }}:{{ current }}%

@@ -149,7 +151,21 @@ useKeepAliveRefresh(refresh) diff --git a/src/views/dashboard/AnalyticsMediaStatistic.vue b/src/views/dashboard/AnalyticsMediaStatistic.vue index 04ea3cdb..1a7d8c01 100644 --- a/src/views/dashboard/AnalyticsMediaStatistic.vue +++ b/src/views/dashboard/AnalyticsMediaStatistic.vue @@ -85,9 +85,3 @@ onActivated(() => { - - diff --git a/src/views/dashboard/AnalyticsMemory.vue b/src/views/dashboard/AnalyticsMemory.vue index 961a024b..e9f66efe 100644 --- a/src/views/dashboard/AnalyticsMemory.vue +++ b/src/views/dashboard/AnalyticsMemory.vue @@ -144,8 +144,10 @@ useKeepAliveRefresh(refresh) {{ t('dashboard.memory') }} - - + +
+ +

{{ t('dashboard.current') }}:{{ formatBytes(usedMemory) }}

@@ -154,7 +156,21 @@ useKeepAliveRefresh(refresh) diff --git a/src/views/dashboard/AnalyticsNetwork.vue b/src/views/dashboard/AnalyticsNetwork.vue index f12fc2d1..fd9c178b 100644 --- a/src/views/dashboard/AnalyticsNetwork.vue +++ b/src/views/dashboard/AnalyticsNetwork.vue @@ -177,8 +177,10 @@ useKeepAliveRefresh(refresh) {{ t('dashboard.network') }} - - + +
+ +

{{ t('dashboard.upload') }} diff --git a/src/views/dashboard/AnalyticsScheduler.vue b/src/views/dashboard/AnalyticsScheduler.vue index 5bb1027a..3b2d6992 100644 --- a/src/views/dashboard/AnalyticsScheduler.vue +++ b/src/views/dashboard/AnalyticsScheduler.vue @@ -51,8 +51,8 @@ useDataRefresh( {{ t('dashboard.scheduler') }} - - + + diff --git a/src/views/dashboard/MediaServerLatest.vue b/src/views/dashboard/MediaServerLatest.vue index 67912468..1667079a 100644 --- a/src/views/dashboard/MediaServerLatest.vue +++ b/src/views/dashboard/MediaServerLatest.vue @@ -60,7 +60,7 @@ onActivated(() => {