add ServerPartitionsDetail.vue

This commit is contained in:
Timi
2026-04-12 20:57:10 +08:00
parent 611830f393
commit ed2d2ef233
4 changed files with 140 additions and 2 deletions

View File

@@ -82,7 +82,7 @@ defineSlots<{
.value { .value {
flex: 1 1 auto; flex: 1 1 auto;
min-width: 0; min-width: 0;
font-size: .8rem; font-size: 14px;
text-align: right; text-align: right;
} }
} }

View File

@@ -65,7 +65,7 @@
: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 /> <t-cell title="更多" arrow @click="router.push('/server/partitions-detail')" />
</t-cell-group> </t-cell-group>
</template> </template>
<t-empty v-else description="暂无系统状态数据" /> <t-empty v-else description="暂无系统状态数据" />

View File

@@ -0,0 +1,124 @@
<template>
<div class="server-partitions-detail">
<div v-if="isLoading && partitions.length < 1" class="loading-wrap">
<t-loading text="加载磁盘详情..." />
</div>
<template v-else-if="partitions.length">
<t-cell-group
v-for="item in partitions"
:key="item.uuid"
:title="resolvePartitionTitle(item)"
theme="card"
>
<t-cell title="磁盘名称" :note="Text.display(item.diskName)" />
<t-cell-info label="磁盘型号" :value="Text.display(item.diskModel)" />
<t-cell-info label="磁盘序列号" :value="Text.display(item.diskSerial)" />
<t-cell title="分区 ID" :note="Text.display(item.partitionId)" />
<t-cell title="分区名称" :note="Text.display(item.partitionName)" />
<t-cell title="分区类型" :note="Text.display(item.partitionType)" />
<t-cell-info label="UUID" :value="Text.display(item.uuid)" />
<t-cell title="总容量" :note="IOSize.format(item.total)" />
<t-cell title="已使用" :note="IOSize.format(item.used)" />
<t-cell title="可用容量" :note="IOSize.format(resolveAvailableBytes(item))" />
<t-cell title="使用率" :note="Text.unit(resolveUsageRate(item) * 100, '%')" />
<t-cell
v-if="typeof item.transferTimeMs === 'number'"
title="传输耗时"
:note="Text.unit(item.transferTimeMs, '毫秒')"
/>
<t-cell v-if="item.healthStatus" title="健康状态" :note="item.healthStatus" />
</t-cell-group>
</template>
<t-empty v-else description="暂无磁盘详情数据" />
</div>
</template>
<script setup lang="ts">
import { Toast } from "tdesign-mobile-vue";
import { getSystemStatus, resolveSystemRequestErrorMessage } from "@/api/SystemAPI";
import type { SystemStatusSnapshot, SystemStatusSnapshotView } from "@/types/System";
import { IOSize, Text } from "timi-web";
type Partition = NonNullable<SystemStatusSnapshot["storagePartitions"]>[number];
defineOptions({
name: "ServerPartitionsDetail"
});
const isLoading = ref(false);
const snapshotView = ref<SystemStatusSnapshotView | null>(null);
const refreshIntervalMs = 3000;
let refreshTimer: ReturnType<typeof setInterval> | null = null;
const partitions = computed<Partition[]>(() => {
const list = snapshotView.value?.snapshot?.storagePartitions || [];
return list.slice().sort((left, right) => {
return (right.used / Math.max(right.total, 1)) - (left.used / Math.max(left.total, 1));
});
});
onMounted(() => {
void refreshDetail();
refreshTimer = setInterval(() => {
void refreshDetail();
}, refreshIntervalMs);
});
onUnmounted(() => {
if (!refreshTimer) {
return;
}
clearInterval(refreshTimer);
refreshTimer = null;
});
function resolvePartitionTitle(item: Partition): string {
const mountPoint = Text.display(item.mountPoint);
const partitionName = Text.display(item.partitionName);
if (partitionName !== "-") {
return `${mountPoint} (${partitionName})`;
}
return mountPoint;
}
function resolveUsageRate(item: Partition): number {
if (item.total < 1) {
return 0;
}
return item.used / item.total;
}
function resolveAvailableBytes(item: Partition): number {
return Math.max(item.total - item.used, 0);
}
async function refreshDetail(): Promise<void> {
if (isLoading.value) {
return;
}
isLoading.value = true;
try {
snapshotView.value = await getSystemStatus("storage");
} catch (error) {
Toast({
theme: "error",
message: resolveSystemRequestErrorMessage(error)
});
} finally {
isLoading.value = false;
}
}
</script>
<style scoped lang="less">
.server-partitions-detail {
padding: var(--app-nav-offset) 0 1rem 0;
.loading-wrap {
display: flex;
min-height: 4rem;
align-items: center;
justify-content: center;
}
}
</style>

View File

@@ -12,6 +12,7 @@ import DashboardSetting from "@/pages/setting/DashboardSetting.vue";
import ThemeSetting from "@/pages/setting/ThemeSetting.vue"; import ThemeSetting from "@/pages/setting/ThemeSetting.vue";
import ServerDetail from "@/pages/dashboard/ServerDashboard/ServerDetail.vue"; import ServerDetail from "@/pages/dashboard/ServerDashboard/ServerDetail.vue";
import ServerPerformanceDetail from "@/pages/dashboard/ServerDashboard/ServerPerformanceDetail.vue"; import ServerPerformanceDetail from "@/pages/dashboard/ServerDashboard/ServerPerformanceDetail.vue";
import ServerPartitionsDetail from "@/pages/dashboard/ServerDashboard/ServerPartitionsDetail.vue";
const router = createRouter({ const router = createRouter({
history: createWebHistory("/"), history: createWebHistory("/"),
@@ -95,6 +96,19 @@ const router = createRouter({
}, },
component: ServerPerformanceDetail component: ServerPerformanceDetail
}, },
{
path: "/server/partitions-detail",
name: "ServerPartitionsDetail",
meta: {
depth: 3,
navBarVisible: true,
navBarCanBack: true,
navBarTitle: "磁盘详情",
tabBarVisible: false,
bodyBackground: "#F4F4F4"
},
component: ServerPartitionsDetail
},
{ {
path: "/settings/connect", path: "/settings/connect",
name: "ConnectSetting", name: "ConnectSetting",