From a6c89717a6b582b7acf17074d14223ab310beaf3 Mon Sep 17 00:00:00 2001 From: Timi Date: Mon, 13 Apr 2026 14:55:15 +0800 Subject: [PATCH] sync dashboard tab --- .../DockerDashboard/DockerDashboard.vue | 3 +- .../ServerDashboard/ServerDashboard.vue | 26 +++++- src/pages/tabs/DashboardTab.vue | 87 +++++++++++++++---- 3 files changed, 92 insertions(+), 24 deletions(-) diff --git a/src/pages/dashboard/DockerDashboard/DockerDashboard.vue b/src/pages/dashboard/DockerDashboard/DockerDashboard.vue index 999c186..ade7264 100644 --- a/src/pages/dashboard/DockerDashboard/DockerDashboard.vue +++ b/src/pages/dashboard/DockerDashboard/DockerDashboard.vue @@ -58,7 +58,8 @@ async function handleSelectContainer(containerId: string): Promise { await router.push({ name: "DockerContainerDetail", query: { - containerId + containerId, + tab: "docker" } }); } diff --git a/src/pages/dashboard/ServerDashboard/ServerDashboard.vue b/src/pages/dashboard/ServerDashboard/ServerDashboard.vue index 9de45ce..075656b 100644 --- a/src/pages/dashboard/ServerDashboard/ServerDashboard.vue +++ b/src/pages/dashboard/ServerDashboard/ServerDashboard.vue @@ -12,7 +12,13 @@ title="运行时长" :note="Time.duration(Time.now() - snapshotView?.snapshot?.os?.bootAt)" /> - + @@ -46,7 +52,13 @@ - + - + @@ -124,7 +142,7 @@ import SystemAPI from "@/api/SystemAPI"; import type { SystemStatusHistoryPoint, SystemStatusSnapshotView } from "@/types/System"; import type { DashboardHistoryMetric } from "@/store/settingStore"; import { useSettingStore } from "@/store/settingStore"; -import { IOSize, type LabelValue, Text, Time, Toolkit } from "timi-web"; +import { IOSize, type LabelValue, Text, Time } from "timi-web"; import TCellInfo from "@/components/TCellInfo.vue"; import type { ProgressItem } from "@/components/ProgressGroup.vue"; import ProgressGroup from "@/components/ProgressGroup.vue"; diff --git a/src/pages/tabs/DashboardTab.vue b/src/pages/tabs/DashboardTab.vue index 8001d20..0e0da3b 100644 --- a/src/pages/tabs/DashboardTab.vue +++ b/src/pages/tabs/DashboardTab.vue @@ -21,6 +21,11 @@ import ServerDashboard from "@/pages/dashboard/ServerDashboard/ServerDashboard.v import DockerDashboard from "@/pages/dashboard/DockerDashboard/DockerDashboard.vue"; import UPSDashboard from "@/pages/dashboard/UPSDashboard/UPSDashboard.vue"; +const route = useRoute(); +const router = useRouter(); + +// ---------- Tab ---------- + type DashboardTabValue = "server" | "docker" | "ups"; type PanelTransitionName = "panel-slide-next" | "panel-slide-prev"; @@ -30,10 +35,71 @@ const dashboardMap: Record = { ups: UPSDashboard }; const tabOrder: DashboardTabValue[] = ["server", "docker", "ups"]; - +const activeComponent = computed(() => dashboardMap[activeTab.value]); const activeTab = ref("server"); const panelTransitionName = ref("panel-slide-next"); -const activeComponent = computed(() => dashboardMap[activeTab.value]); + +async function onChangeTab(value: string): Promise { + const nextTab = value as DashboardTabValue; + if (nextTab === activeTab.value) { + return; + } + + panelTransitionName.value = resolveTabDirection(nextTab); + activeTab.value = nextTab; + await syncRouteTab(nextTab); +} + +// ---------- Tab 同步路由 ---------- + +type DashboardTabQuery = { + tab?: string; +}; + +watch(() => route.query.tab, () => { + const nextTab = resolveRouteTab(); + if (nextTab === activeTab.value) { + return; + } + panelTransitionName.value = resolveTabDirection(nextTab); + activeTab.value = nextTab; +}, { immediate: true }); + +function resolveRouteTab(): DashboardTabValue { + const queryTab = route.query.tab; + if (queryTab === "server" || queryTab === "docker" || queryTab === "ups") { + return queryTab; + } + return "server"; +} + +function resolveTabDirection(nextTab: DashboardTabValue): PanelTransitionName { + const currentIndex = tabOrder.indexOf(activeTab.value); + const nextIndex = tabOrder.indexOf(nextTab); + if (currentIndex <= -1 || nextIndex <= -1) { + return "panel-slide-next"; + } + return currentIndex < nextIndex ? "panel-slide-next" : "panel-slide-prev"; +} + +async function syncRouteTab(nextTab: DashboardTabValue): Promise { + if (route.query.tab === nextTab) { + return; + } + + const nextQuery: DashboardTabQuery = { + ...(route.query as DashboardTabQuery), + tab: nextTab + }; + await router.replace({ + query: nextQuery + }); +} + +onMounted(() => activeTab.value = resolveRouteTab()); + +// ---------- Tab 高度 ---------- + const tabsWrapRef = ref(); const tabsHeight = ref("0px"); let tabsResizeObs: ResizeObserver | undefined; @@ -51,7 +117,6 @@ onMounted(() => { if (!tabsWrapRef.value) { return; } - tabsResizeObs = new ResizeObserver(() => { updateTabsHeight(); }); @@ -63,22 +128,6 @@ onUnmounted(() => { tabsResizeObs.disconnect(); } }); - -function onChangeTab(value: string): void { - const nextTab = value as DashboardTabValue; - if (nextTab === activeTab.value) { - return; - } - - const currentIndex = tabOrder.indexOf(activeTab.value); - const nextIndex = tabOrder.indexOf(nextTab); - if (currentIndex <= -1 || nextIndex <= -1) { - panelTransitionName.value = "panel-slide-next"; - } else { - panelTransitionName.value = currentIndex < nextIndex ? "panel-slide-next" : "panel-slide-prev"; - } - activeTab.value = nextTab; -}