sync dashboard tab

This commit is contained in:
Timi
2026-04-13 14:55:15 +08:00
parent df6c6b78c9
commit a6c89717a6
3 changed files with 92 additions and 24 deletions

View File

@@ -58,7 +58,8 @@ async function handleSelectContainer(containerId: string): Promise<void> {
await router.push({ await router.push({
name: "DockerContainerDetail", name: "DockerContainerDetail",
query: { query: {
containerId containerId,
tab: "docker"
} }
}); });
} }

View File

@@ -12,7 +12,13 @@
title="运行时长" title="运行时长"
:note="Time.duration(Time.now() - snapshotView?.snapshot?.os?.bootAt)" :note="Time.duration(Time.now() - snapshotView?.snapshot?.os?.bootAt)"
/> />
<t-cell title="更多" arrow @click="router.push('/server/system-detail')" /> <t-cell title="更多" arrow @click="router.push({
path: '/server/system-detail',
query: {
tab: 'server'
}
})"
/>
</t-cell-group> </t-cell-group>
<t-cell-group class="section performance" title="资源" theme="card"> <t-cell-group class="section performance" title="资源" theme="card">
<t-cell-info label="CPU" :value="Text.display(snapshotView?.snapshot?.cpu?.model)"> <t-cell-info label="CPU" :value="Text.display(snapshotView?.snapshot?.cpu?.model)">
@@ -46,7 +52,13 @@
<t-icon name="arrow-down" /> <t-icon name="arrow-down" />
</template> </template>
</t-cell> </t-cell>
<t-cell title="更多" arrow @click="router.push('/server/performance-detail')" /> <t-cell title="更多" arrow @click="router.push({
path: '/server/performance-detail',
query: {
tab: 'server'
}
})"
/>
</t-cell-group> </t-cell-group>
<t-cell-group class="section disk" title="磁盘" theme="card"> <t-cell-group class="section disk" title="磁盘" theme="card">
<t-cell-info <t-cell-info
@@ -66,7 +78,13 @@
:note="Text.unit(item.used / item.total * 100, '%')" :note="Text.unit(item.used / item.total * 100, '%')"
/> />
</t-cell-info> </t-cell-info>
<t-cell title="更多" arrow @click="router.push('/server/partitions-detail')" /> <t-cell title="更多" arrow @click="router.push({
path: '/server/partitions-detail',
query: {
tab: 'server'
}
})"
/>
</t-cell-group> </t-cell-group>
</template> </template>
<t-empty v-else description="暂无系统状态数据" /> <t-empty v-else description="暂无系统状态数据" />
@@ -124,7 +142,7 @@ import SystemAPI from "@/api/SystemAPI";
import type { SystemStatusHistoryPoint, SystemStatusSnapshotView } from "@/types/System"; import type { SystemStatusHistoryPoint, SystemStatusSnapshotView } from "@/types/System";
import type { DashboardHistoryMetric } from "@/store/settingStore"; import type { DashboardHistoryMetric } from "@/store/settingStore";
import { useSettingStore } 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 TCellInfo from "@/components/TCellInfo.vue";
import type { ProgressItem } from "@/components/ProgressGroup.vue"; import type { ProgressItem } from "@/components/ProgressGroup.vue";
import ProgressGroup from "@/components/ProgressGroup.vue"; import ProgressGroup from "@/components/ProgressGroup.vue";

View File

@@ -21,6 +21,11 @@ import ServerDashboard from "@/pages/dashboard/ServerDashboard/ServerDashboard.v
import DockerDashboard from "@/pages/dashboard/DockerDashboard/DockerDashboard.vue"; import DockerDashboard from "@/pages/dashboard/DockerDashboard/DockerDashboard.vue";
import UPSDashboard from "@/pages/dashboard/UPSDashboard/UPSDashboard.vue"; import UPSDashboard from "@/pages/dashboard/UPSDashboard/UPSDashboard.vue";
const route = useRoute();
const router = useRouter();
// ---------- Tab ----------
type DashboardTabValue = "server" | "docker" | "ups"; type DashboardTabValue = "server" | "docker" | "ups";
type PanelTransitionName = "panel-slide-next" | "panel-slide-prev"; type PanelTransitionName = "panel-slide-next" | "panel-slide-prev";
@@ -30,10 +35,71 @@ const dashboardMap: Record<DashboardTabValue, Component> = {
ups: UPSDashboard ups: UPSDashboard
}; };
const tabOrder: DashboardTabValue[] = ["server", "docker", "ups"]; const tabOrder: DashboardTabValue[] = ["server", "docker", "ups"];
const activeComponent = computed(() => dashboardMap[activeTab.value]);
const activeTab = ref<DashboardTabValue>("server"); const activeTab = ref<DashboardTabValue>("server");
const panelTransitionName = ref<PanelTransitionName>("panel-slide-next"); const panelTransitionName = ref<PanelTransitionName>("panel-slide-next");
const activeComponent = computed(() => dashboardMap[activeTab.value]);
async function onChangeTab(value: string): Promise<void> {
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<void> {
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<HTMLElement>(); const tabsWrapRef = ref<HTMLElement>();
const tabsHeight = ref("0px"); const tabsHeight = ref("0px");
let tabsResizeObs: ResizeObserver | undefined; let tabsResizeObs: ResizeObserver | undefined;
@@ -51,7 +117,6 @@ onMounted(() => {
if (!tabsWrapRef.value) { if (!tabsWrapRef.value) {
return; return;
} }
tabsResizeObs = new ResizeObserver(() => { tabsResizeObs = new ResizeObserver(() => {
updateTabsHeight(); updateTabsHeight();
}); });
@@ -63,22 +128,6 @@ onUnmounted(() => {
tabsResizeObs.disconnect(); 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;
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">