refactor(ui): merge instances page into network dashboard
- Remove the redundant Instances page; its network detail and server connection sections now live in DashboardView below selectable instance cards - Redirect legacy /instances and /general routes to / - Add per-page subtitles to the header instead of a fixed caption - Widen content container to 1700px for large screens - Highlight online device count in green on the stats cards
This commit is contained in:
@@ -79,7 +79,7 @@ onBeforeUnmount(() => window.removeEventListener("keydown", handleKeydown));
|
||||
|
||||
<div class="min-w-0">
|
||||
<h1 class="truncate text-lg font-bold text-slate-900 dark:text-white">{{ pageMeta.label }}</h1>
|
||||
<p class="hidden text-xs text-slate-400 sm:block">VNT 虚拟局域网管理</p>
|
||||
<p class="hidden text-xs text-slate-400 sm:block">{{ pageMeta.subtitle || "VNT 虚拟局域网管理" }}</p>
|
||||
</div>
|
||||
|
||||
<div class="ml-auto flex items-center gap-2">
|
||||
@@ -103,7 +103,7 @@ onBeforeUnmount(() => window.removeEventListener("keydown", handleKeydown));
|
||||
</header>
|
||||
|
||||
<main class="custom-scrollbar min-h-0 flex-1 overflow-x-hidden overflow-y-auto">
|
||||
<div class="mx-auto w-full max-w-7xl px-4 py-5 sm:px-5 lg:px-7 lg:py-6">
|
||||
<div class="mx-auto w-full max-w-[1700px] px-4 py-5 sm:px-5 lg:px-7 lg:py-6">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="fade" mode="out-in"><component :is="Component" /></transition>
|
||||
</router-view>
|
||||
|
||||
@@ -3,43 +3,43 @@ export const navItems = [
|
||||
to: "/",
|
||||
label: "网络总览",
|
||||
shortLabel: "总览",
|
||||
subtitle: "组网状态与实例管理",
|
||||
icon: "M4 4h6v6H4V4Zm10 0h6v6h-6V4ZM4 14h6v6H4v-6Zm10 0h6v6h-6v-6Z",
|
||||
},
|
||||
{
|
||||
to: "/instances",
|
||||
label: "运行实例",
|
||||
shortLabel: "实例",
|
||||
icon: "M4 18V8m5 10V4m6 14v-7m5 7V6",
|
||||
},
|
||||
{
|
||||
to: "/peers",
|
||||
label: "在线设备",
|
||||
shortLabel: "设备",
|
||||
subtitle: "查看网络中的对端设备",
|
||||
icon: "M15 19a6 6 0 0 0-12 0m18 0a5 5 0 0 0-5-5m-7-3a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm8 0a3 3 0 1 0 0-6",
|
||||
},
|
||||
{
|
||||
to: "/routes",
|
||||
label: "路由表",
|
||||
shortLabel: "路由",
|
||||
subtitle: "虚拟网络路由信息",
|
||||
icon: "M6 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4Zm12 12a2 2 0 1 0 0-4 2 2 0 0 0 0 4ZM8 6h6a4 4 0 0 1 4 4v2m-3-3 3 3 3-3M16 18h-6a4 4 0 0 1-4-4v-2",
|
||||
},
|
||||
{
|
||||
to: "/config",
|
||||
label: "组网配置",
|
||||
shortLabel: "配置",
|
||||
icon: "M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Zm7.4-.5a1.7 1.7 0 0 0 .3 1.9l.1.1-2.8 2.8-.1-.1a1.7 1.7 0 0 0-1.9-.3A1.7 1.7 0 0 0 14 21v.2h-4V21a1.7 1.7 0 0 0-1-1.6 1.7 1.7 0 0 0-1.9.3l-.1.1L4.2 17l.1-.1a1.7 1.7 0 0 0 .3-1.9A1.7 1.7 0 0 0 3 14h-.2v-4H3a1.7 1.7 0 0 0 1.6-1 1.7 1.7 0 0 0-.3-1.9L4.2 7 7 4.2l.1.1A1.7 1.7 0 0 0 9 4.6 1.7 1.7 0 0 0 10 3v-.2h4V3a1.7 1.7 0 0 0 1 1.6 1.7 1.7 0 0 0 1.9-.3l.1-.1L19.8 7l-.1.1a1.7 1.7 0 0 0-.3 1.9 1.7 1.7 0 0 0 1.6 1h.2v4H21a1.7 1.7 0 0 0-1.6 1Z",
|
||||
subtitle: "管理组网配置文件",
|
||||
icon: "M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Zm7.4-.5a1.7 1.7 0 0 0 .3 1.9l.1.1-2.8 2.8-.1-.1a1.7 1.7 0 0 0-1.9-.3A1.7 1.7 0 0 0 14 21v.2h-4V21a1.7 1.7 0 0 0-1-1.6 1.7 1.7 0 0 0-1.9.3l-.1.1L4.2 17l.1-.1a1.7 1.7 0 0 0 .3-1.9A1.7 1.7 0 0 0 3 14h-.2v-4H3a1.7 1.7 0 0 0 1.6-1 1.7 1.7 0 0 0-.3-1.9L4.2 7 7 4.2l.1.1A1.7 1.7 0 0 0 9 4.6 1.7 1.7 0 0 0 10 3v-.2h4V3a1.7 1.7 0 0 0 1 1.6 1.7 1.7 0 0 0 1.9-.3l.1-.1L19.8 7l-.1.1a1.7 1.7 0 0 0-.3 1.9 1.7 1.7 0 0 0 1.6 1h.2v4H21a1.7 1.7 0 0 0-1.6-1Z",
|
||||
},
|
||||
{
|
||||
to: "/web-access",
|
||||
label: "Web 访问",
|
||||
shortLabel: "Web",
|
||||
subtitle: "远程访问设置",
|
||||
desktopOnly: true,
|
||||
icon: "M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Zm0 0c2.2-2.5 3.3-5.5 3.3-9S14.2 5.5 12 3m0 18c-2.2-2.5-3.3-5.5-3.3-9S9.8 5.5 12 3M3.5 9h17m-17 6h17",
|
||||
icon: "M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Zm0 0c-2.2-2.5 3.3-5.5 3.3-9S14.2 5.5 12 3m0 18c-2.2-2.5-3.3-5.5-3.3-9S9.8 5.5 12 3M3.5 9h17m-17 6h17",
|
||||
},
|
||||
{
|
||||
to: "/about",
|
||||
label: "关于",
|
||||
shortLabel: "关于",
|
||||
subtitle: "版本与更新",
|
||||
icon: "M12 17v-6m0-4h.01M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { createRouter, createWebHashHistory } from "vue-router";
|
||||
import DashboardView from "../views/DashboardView.vue";
|
||||
import InstancesView from "../views/InstancesView.vue";
|
||||
import ConfigView from "../views/ConfigView.vue";
|
||||
import PeersView from "../views/PeersView.vue";
|
||||
import RoutesView from "../views/RoutesView.vue";
|
||||
@@ -9,9 +8,9 @@ import AboutView from "../views/AboutView.vue";
|
||||
|
||||
const routes = [
|
||||
{ path: "/", component: DashboardView },
|
||||
{ path: "/instances", component: InstancesView },
|
||||
// 兼容旧路由
|
||||
{ path: "/general", redirect: "/instances" },
|
||||
// 兼容旧路由:实例管理已并入网络总览
|
||||
{ path: "/instances", redirect: "/" },
|
||||
{ path: "/general", redirect: "/" },
|
||||
{ path: "/config", component: ConfigView },
|
||||
{ path: "/peers", component: PeersView },
|
||||
{ path: "/routes", component: RoutesView },
|
||||
|
||||
@@ -60,7 +60,10 @@ const statusSummary = computed(() => {
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="text-xs font-medium muted">在线设备</div>
|
||||
<div class="mt-2 text-2xl font-bold tabular-nums text-slate-900 dark:text-white">
|
||||
<div
|
||||
class="mt-2 text-2xl font-bold tabular-nums"
|
||||
:class="onlineDevices > 0 ? 'text-green-600 dark:text-green-400' : 'text-slate-900 dark:text-white'"
|
||||
>
|
||||
{{ onlineDevices }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -81,23 +84,144 @@ const statusSummary = computed(() => {
|
||||
<!-- 启动组网 -->
|
||||
<StartPanel />
|
||||
|
||||
<!-- 实例概览 -->
|
||||
<!-- 实例列表 -->
|
||||
<div>
|
||||
<div class="mb-3 flex items-center justify-between">
|
||||
<h2 class="text-base font-bold text-slate-900 dark:text-white">实例概览</h2>
|
||||
<router-link
|
||||
to="/instances"
|
||||
class="text-sm font-medium text-indigo-600 hover:text-indigo-500 dark:text-indigo-400"
|
||||
>查看详情 →</router-link
|
||||
>
|
||||
<h2 class="text-base font-bold text-slate-900 dark:text-white">组网实例</h2>
|
||||
<span v-if="app.instanceList.length > 0" class="text-xs muted">点击卡片查看详情</span>
|
||||
</div>
|
||||
<EmptyState
|
||||
v-if="app.instanceList.length === 0"
|
||||
:text="app.configList.length === 0 ? '暂无配置,请先新建配置' : '暂无运行中的组网,请在上方选择配置启动'"
|
||||
/>
|
||||
<TransitionGroup v-else name="card-list" tag="div" class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<InstanceCard v-for="inst in app.instanceList" :key="inst.file_name" :inst="inst" />
|
||||
<InstanceCard v-for="inst in app.instanceList" :key="inst.file_name" :inst="inst" selectable />
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
|
||||
<!-- 选中实例详情 -->
|
||||
<template v-if="app.selectedInstance && app.selectedInfo">
|
||||
<div class="card">
|
||||
<h2 class="mb-4 text-lg font-bold text-slate-900 dark:text-white">
|
||||
网络详情
|
||||
<span class="ml-2 text-sm font-medium text-indigo-600 dark:text-indigo-400">{{
|
||||
app.selectedConfigName
|
||||
}}</span>
|
||||
</h2>
|
||||
<div class="grid grid-cols-1 gap-4 text-sm md:grid-cols-2">
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">虚拟 IP / 掩码</span>
|
||||
<span class="font-mono tabular-nums text-slate-900 dark:text-white"
|
||||
>{{ app.selectedInfo.ip || "-" }} / {{ app.selectedInfo.prefix_len || "-" }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">网关</span>
|
||||
<span class="font-mono text-slate-900 dark:text-white">{{ app.selectedInfo.gateway || "-" }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">网络编号</span>
|
||||
<span class="font-mono text-slate-900 dark:text-white">{{ app.selectedInfo.network_code || "-" }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">MTU</span>
|
||||
<span class="font-mono tabular-nums text-slate-900 dark:text-white">{{ app.selectedInfo.mtu || "" }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">NAT 类型</span>
|
||||
<span class="font-mono text-indigo-600 dark:text-indigo-400">{{
|
||||
app.selectedInfo.nat_type || "Unknown"
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">Public IPv6</span>
|
||||
<span
|
||||
class="max-w-[200px] truncate font-mono text-slate-900 dark:text-white"
|
||||
:title="app.selectedInfo.public_ipv6"
|
||||
>{{ app.selectedInfo.public_ipv6 || "-" }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">设备名称</span>
|
||||
<span class="text-slate-900 dark:text-white">{{ app.selectedInfo.name || "-" }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">设备 ID</span>
|
||||
<span
|
||||
class="max-w-[200px] truncate font-mono text-xs text-slate-500 dark:text-slate-400"
|
||||
:title="app.selectedInfo.device_id"
|
||||
>{{ app.selectedInfo.device_id || "-" }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 grid grid-cols-2 gap-3 md:grid-cols-4">
|
||||
<div
|
||||
v-for="feat in [
|
||||
{ key: 'encrypt', label: '加密' },
|
||||
{ key: 'compress', label: '压缩' },
|
||||
{ key: 'fec', label: 'FEC纠错' },
|
||||
{ key: 'rtx', label: 'QUIC传输' },
|
||||
]"
|
||||
:key="feat.key"
|
||||
class="flex items-center gap-2 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50"
|
||||
>
|
||||
<span
|
||||
class="h-2 w-2 rounded-full"
|
||||
:class="app.selectedInfo[feat.key] ? 'bg-green-500' : 'bg-slate-300 dark:bg-slate-600'"
|
||||
></span>
|
||||
<span class="text-sm text-slate-600 dark:text-slate-300">{{ feat.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<span class="mb-2 block text-sm muted">Public IPv4s</span>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span
|
||||
v-for="pip in app.selectedInfo.public_ipv4s"
|
||||
:key="pip"
|
||||
class="rounded border border-slate-200 bg-slate-50 px-2 py-1 font-mono text-xs tabular-nums text-green-700 dark:border-slate-600 dark:bg-slate-800 dark:text-green-300"
|
||||
>{{ pip }}</span
|
||||
>
|
||||
<span
|
||||
v-if="!app.selectedInfo.public_ipv4s || app.selectedInfo.public_ipv4s.length === 0"
|
||||
class="text-xs text-slate-400"
|
||||
>无</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card p-0 overflow-hidden">
|
||||
<div class="border-b border-slate-200 px-6 py-4 dark:border-slate-700">
|
||||
<h2 class="text-lg font-bold text-slate-900 dark:text-white">服务器连接列表</h2>
|
||||
</div>
|
||||
<div class="custom-scrollbar max-h-[400px] overflow-x-auto">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>地址</th>
|
||||
<th>状态</th>
|
||||
<th>延迟</th>
|
||||
<th>版本</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(server, idx) in app.selectedInfo.server_info" :key="idx">
|
||||
<td class="font-mono">{{ server.server }}</td>
|
||||
<td>
|
||||
<span :class="server.connected ? 'badge-green' : 'badge-red'">
|
||||
{{ server.connected ? "已连接" : "未连接" }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="tabular-nums">{{ server.server_rtt ? server.server_rtt + " ms" : "-" }}</td>
|
||||
<td>{{ server.server_version || "-" }}</td>
|
||||
</tr>
|
||||
<tr v-if="!app.selectedInfo.server_info || app.selectedInfo.server_info.length === 0">
|
||||
<td colspan="4" class="text-center text-slate-400">暂无数据</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
<script setup>
|
||||
import { useAppStore } from "../stores/app";
|
||||
import StartPanel from "../components/StartPanel.vue";
|
||||
import InstanceCard from "../components/InstanceCard.vue";
|
||||
import EmptyState from "../components/EmptyState.vue";
|
||||
|
||||
const app = useAppStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-6">
|
||||
<!-- 页面标题 -->
|
||||
<div>
|
||||
<h1 class="page-title">实例</h1>
|
||||
<p class="page-subtitle">管理组网实例,点击卡片查看详情</p>
|
||||
</div>
|
||||
|
||||
<!-- 启动组网 -->
|
||||
<StartPanel />
|
||||
|
||||
<!-- 组网实例 -->
|
||||
<EmptyState v-if="app.instanceList.length === 0" text="暂无运行中的组网,请在上方选择配置启动" />
|
||||
<TransitionGroup v-else name="card-list" tag="div" class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<InstanceCard v-for="inst in app.instanceList" :key="inst.file_name" :inst="inst" selectable />
|
||||
</TransitionGroup>
|
||||
|
||||
<!-- 选中实例详情 -->
|
||||
<template v-if="app.selectedInstance && app.selectedInfo">
|
||||
<div class="card">
|
||||
<h2 class="mb-4 text-lg font-bold text-slate-900 dark:text-white">
|
||||
网络详情
|
||||
<span class="ml-2 text-sm font-medium text-indigo-600 dark:text-indigo-400">{{
|
||||
app.selectedConfigName
|
||||
}}</span>
|
||||
</h2>
|
||||
<div class="grid grid-cols-1 gap-4 text-sm md:grid-cols-2">
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">虚拟 IP / 掩码</span>
|
||||
<span class="font-mono tabular-nums text-slate-900 dark:text-white"
|
||||
>{{ app.selectedInfo.ip || "-" }} / {{ app.selectedInfo.prefix_len || "-" }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">网关</span>
|
||||
<span class="font-mono text-slate-900 dark:text-white">{{ app.selectedInfo.gateway || "-" }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">网络编号</span>
|
||||
<span class="font-mono text-slate-900 dark:text-white">{{ app.selectedInfo.network_code || "-" }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">MTU</span>
|
||||
<span class="font-mono tabular-nums text-slate-900 dark:text-white">{{ app.selectedInfo.mtu || "" }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">NAT 类型</span>
|
||||
<span class="font-mono text-indigo-600 dark:text-indigo-400">{{
|
||||
app.selectedInfo.nat_type || "Unknown"
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">Public IPv6</span>
|
||||
<span
|
||||
class="max-w-[200px] truncate font-mono text-slate-900 dark:text-white"
|
||||
:title="app.selectedInfo.public_ipv6"
|
||||
>{{ app.selectedInfo.public_ipv6 || "-" }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">设备名称</span>
|
||||
<span class="text-slate-900 dark:text-white">{{ app.selectedInfo.name || "-" }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between border-b border-slate-100 pb-2 dark:border-slate-700">
|
||||
<span class="muted">设备 ID</span>
|
||||
<span
|
||||
class="max-w-[200px] truncate font-mono text-xs text-slate-500 dark:text-slate-400"
|
||||
:title="app.selectedInfo.device_id"
|
||||
>{{ app.selectedInfo.device_id || "-" }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 grid grid-cols-2 gap-3 md:grid-cols-4">
|
||||
<div
|
||||
v-for="feat in [
|
||||
{ key: 'encrypt', label: '加密' },
|
||||
{ key: 'compress', label: '压缩' },
|
||||
{ key: 'fec', label: 'FEC纠错' },
|
||||
{ key: 'rtx', label: 'QUIC传输' },
|
||||
]"
|
||||
:key="feat.key"
|
||||
class="flex items-center gap-2 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50"
|
||||
>
|
||||
<span
|
||||
class="h-2 w-2 rounded-full"
|
||||
:class="app.selectedInfo[feat.key] ? 'bg-green-500' : 'bg-slate-300 dark:bg-slate-600'"
|
||||
></span>
|
||||
<span class="text-sm text-slate-600 dark:text-slate-300">{{ feat.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<span class="mb-2 block text-sm muted">Public IPv4s</span>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span
|
||||
v-for="pip in app.selectedInfo.public_ipv4s"
|
||||
:key="pip"
|
||||
class="rounded border border-slate-200 bg-slate-50 px-2 py-1 font-mono text-xs tabular-nums text-green-700 dark:border-slate-600 dark:bg-slate-800 dark:text-green-300"
|
||||
>{{ pip }}</span
|
||||
>
|
||||
<span
|
||||
v-if="!app.selectedInfo.public_ipv4s || app.selectedInfo.public_ipv4s.length === 0"
|
||||
class="text-xs text-slate-400"
|
||||
>无</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card p-0 overflow-hidden">
|
||||
<div class="border-b border-slate-200 px-6 py-4 dark:border-slate-700">
|
||||
<h2 class="text-lg font-bold text-slate-900 dark:text-white">服务器连接列表</h2>
|
||||
</div>
|
||||
<div class="custom-scrollbar max-h-[400px] overflow-x-auto">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>地址</th>
|
||||
<th>状态</th>
|
||||
<th>延迟</th>
|
||||
<th>版本</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(server, idx) in app.selectedInfo.server_info" :key="idx">
|
||||
<td class="font-mono">{{ server.server }}</td>
|
||||
<td>
|
||||
<span :class="server.connected ? 'badge-green' : 'badge-red'">
|
||||
{{ server.connected ? "已连接" : "未连接" }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="tabular-nums">{{ server.server_rtt ? server.server_rtt + " ms" : "-" }}</td>
|
||||
<td>{{ server.server_version || "-" }}</td>
|
||||
</tr>
|
||||
<tr v-if="!app.selectedInfo.server_info || app.selectedInfo.server_info.length === 0">
|
||||
<td colspan="4" class="text-center text-slate-400">暂无数据</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user