first commit

This commit is contained in:
nnbcccscdscdsc
2026-03-31 20:41:08 +08:00
commit 771829d99d
44 changed files with 7663 additions and 0 deletions

View File

@@ -0,0 +1,151 @@
<script setup lang="ts">
import { computed } from 'vue'
import type { NetworkTelemetry } from '@/types'
const props = defineProps<{
network: NetworkTelemetry | null
}>()
const updatedAt = computed(() => {
if (!props.network?.updated_at) {
return '暂无'
}
return new Date(props.network.updated_at).toLocaleString('zh-CN', { hour12: false })
})
</script>
<template>
<section class="panel network-panel">
<div class="panel-head">
<div>
<p class="eyebrow">Network</p>
<h2>链路状态</h2>
</div>
<span class="badge">{{ network?.peer_status ?? 'loading' }}</span>
</div>
<div class="stats">
<div class="stat-card">
<span>延迟</span>
<strong>{{ network?.latency_ms ?? '--' }} ms</strong>
</div>
<div class="stat-card">
<span>抖动</span>
<strong>{{ network?.jitter_ms ?? '--' }} ms</strong>
</div>
<div class="stat-card">
<span>丢包率</span>
<strong>{{ network?.packet_loss_pct ?? '--' }} %</strong>
</div>
<div class="stat-card">
<span>信号强度</span>
<strong>{{ network?.signal_dbm ?? '--' }} dBm</strong>
</div>
<div class="stat-card">
<span>发送速率</span>
<strong>{{ network?.tx_kbps ?? '--' }} kbps</strong>
</div>
<div class="stat-card">
<span>接收速率</span>
<strong>{{ network?.rx_kbps ?? '--' }} kbps</strong>
</div>
</div>
<div class="summary">
<p><strong>来源</strong>{{ network?.transport ?? '暂无' }} / {{ network?.source_mode ?? '暂无' }}</p>
<p><strong>刷新</strong>{{ updatedAt }}</p>
</div>
</section>
</template>
<style scoped>
.network-panel {
display: grid;
gap: 16px;
}
.panel-head {
display: flex;
justify-content: space-between;
gap: 12px;
align-items: start;
}
.eyebrow {
margin: 0 0 4px;
color: #4dd4ac;
text-transform: uppercase;
letter-spacing: 0.12em;
font-size: 12px;
font-weight: 700;
}
h2 {
margin: 0;
font-size: 24px;
}
.badge {
padding: 8px 12px;
border-radius: 999px;
background: rgba(40, 199, 111, 0.16);
color: #63e6a9;
font-size: 12px;
font-weight: 700;
text-transform: uppercase;
}
.stats {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
}
.stat-card {
padding: 14px;
border-radius: 16px;
background: rgba(7, 14, 26, 0.78);
border: 1px solid rgba(133, 147, 169, 0.2);
}
.stat-card span {
display: block;
margin-bottom: 8px;
color: #8d99b3;
font-size: 12px;
}
.stat-card strong {
font-size: 22px;
}
.summary {
padding: 14px;
border-radius: 16px;
background: rgba(7, 14, 26, 0.78);
border: 1px solid rgba(133, 147, 169, 0.2);
color: #d5dbee;
}
.summary p {
margin: 0;
}
.summary p + p {
margin-top: 8px;
}
@media (max-width: 960px) {
.stats {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 640px) {
.stats {
grid-template-columns: 1fr;
}
}
</style>