U:调整页面

This commit is contained in:
jimmy committed 2025-08-09 14:49:48 +08:00
1 parent 588a518d90
commit 34cd3db09a
2 files changed
+42 -189

No files matched your search

Binary file not shown.
@@ -104,81 +104,6 @@
</div> </div>
</div> </div>
<!-- 协议分布饼图 -->
<div class="chart-card">
<div class="chart-header">
<h3 class="chart-title">协议分布</h3>
</div>
<div class="chart-body">
<div class="pie-chart">
<div class="pie-center">
<svg viewBox="0 0 100 100" class="pie-svg">
<circle
cx="50"
cy="50"
r="40"
fill="none"
stroke="var(--accent-primary)"
stroke-width="20"
stroke-dasharray="75 125"
transform="rotate(-90 50 50)"
/>
<circle
cx="50"
cy="50"
r="40"
fill="none"
stroke="var(--accent-secondary)"
stroke-width="20"
stroke-dasharray="50 125"
stroke-dashoffset="-75"
transform="rotate(-90 50 50)"
/>
<circle
cx="50"
cy="50"
r="40"
fill="none"
stroke="var(--accent-warning)"
stroke-width="20"
stroke-dasharray="35 125"
stroke-dashoffset="-125"
transform="rotate(-90 50 50)"
/>
<circle
cx="50"
cy="50"
r="40"
fill="none"
stroke="var(--accent-error)"
stroke-width="20"
stroke-dasharray="40 125"
stroke-dashoffset="-160"
transform="rotate(-90 50 50)"
/>
</svg>
</div>
<div class="pie-legend">
<div class="legend-item">
<span class="legend-dot" style="background: var(--accent-primary)"></span>
<span>HTTPS (37.5%)</span>
</div>
<div class="legend-item">
<span class="legend-dot" style="background: var(--accent-secondary)"></span>
<span>HTTP (25%)</span>
</div>
<div class="legend-item">
<span class="legend-dot" style="background: var(--accent-warning)"></span>
<span>DNS (17.5%)</span>
</div>
<div class="legend-item">
<span class="legend-dot" style="background: var(--accent-error)"></span>
<span>其他 (20%)</span>
</div>
</div>
</div>
</div>
</div>
<!-- Top应用流量图表 --> <!-- Top应用流量图表 -->
<div class="chart-card"> <div class="chart-card">
@@ -194,9 +119,9 @@
</div> </div>
</div> </div>
<!-- 底部软件流量分析区域 --> <!-- 软件流量分析区域 -->
<div class="bottom-analysis-area"> <div class="software-analysis-area">
<div class="traffic-ranking-panel"> <div class="software-ranking-panel">
<div class="panel-header"> <div class="panel-header">
<h3 class="panel-title">软件流量TOP榜</h3> <h3 class="panel-title">软件流量TOP榜</h3>
<div class="panel-controls"> <div class="panel-controls">
@@ -216,48 +141,22 @@
<SoftwareRankingList <SoftwareRankingList
:data="softwareRankingData" :data="softwareRankingData"
:time-range="selectedRankingRange" :time-range="selectedRankingRange"
:selected-software="selectedSoftware" @select-software="showSoftwareDetail"
@select-software="onSelectSoftware"
/> />
</div> </div>
</div> </div>
<div class="software-detail-panel">
<div class="panel-header">
<h3 class="panel-title">
{{ selectedSoftware?.displayName || '选择软件查看详情' }}
</h3>
</div>
<div class="detail-content">
<div v-if="selectedSoftware" class="software-details">
<!-- 软件基本信息 -->
<div class="detail-section">
<h4 class="section-title">软件信息</h4>
<SoftwareInfoCard :software-info="selectedSoftwareInfo" />
</div>
<!-- 网络连接关系图 -->
<div class="detail-section">
<h4 class="section-title">网络连接</h4>
<NetworkRelationChart
:data="networkRelationData"
:software="selectedSoftware"
/>
</div>
<!-- 端口统计 -->
<div class="detail-section">
<h4 class="section-title">端口统计</h4>
<PortStatsTable :data="portStatsData" />
</div>
</div>
<div v-else class="empty-state">
<n-icon :component="ServerOutline" size="48" />
<p>请从左侧列表选择软件查看详情</p>
</div>
</div>
</div>
</div> </div>
<!-- 软件详情弹窗 -->
<SoftwareDetailModal
v-model:show="showDetailModal"
:software="selectedSoftware"
:software-info="selectedSoftwareInfo"
:network-relation-data="networkRelationData"
:port-stats-data="portStatsData"
:protocol-data="protocolData"
:time-range="selectedRankingRange"
/>
</div> </div>
</div> </div>
</template> </template>
@@ -278,9 +177,7 @@ import {
import TrafficTrendChart from './components/TrafficTrendChart.vue' import TrafficTrendChart from './components/TrafficTrendChart.vue'
import TopAppsChart from './components/TopAppsChart.vue' import TopAppsChart from './components/TopAppsChart.vue'
import SoftwareRankingList from './components/SoftwareRankingList.vue' import SoftwareRankingList from './components/SoftwareRankingList.vue'
import SoftwareInfoCard from './components/SoftwareInfoCard.vue' import SoftwareDetailModal from './components/SoftwareDetailModal.vue'
import NetworkRelationChart from './components/NetworkRelationChart.vue'
import PortStatsTable from './components/PortStatsTable.vue'
// 时间范围选项 // 时间范围选项
const timeRanges = ref([ const timeRanges = ref([
@@ -305,8 +202,9 @@ const selectedInterface = ref('all')
const rankingTimeRanges = ref(['1小时', '1天', '7天', '30天']) const rankingTimeRanges = ref(['1小时', '1天', '7天', '30天'])
const selectedRankingRange = ref('1天') const selectedRankingRange = ref('1天')
// 选中的软件 // 选中的软件和弹窗状态
const selectedSoftware = ref<any>(null) const selectedSoftware = ref<any>(null)
const showDetailModal = ref(false)
// Mock数据 // Mock数据
const trafficTrendData = ref([ const trafficTrendData = ref([
@@ -380,9 +278,21 @@ const portStatsData = computed(() => {
] ]
}) })
// 协议分布数据(移到弹窗中使用)
const protocolData = computed(() => {
if (!selectedSoftware.value) return []
return [
{ protocol: 'HTTPS', bytes: 1610612736, percentage: 37.5, color: '#3b82f6' },
{ protocol: 'HTTP', bytes: 1073741824, percentage: 25.0, color: '#10b981' },
{ protocol: 'DNS', bytes: 751619276, percentage: 17.5, color: '#f59e0b' },
{ protocol: '其他', bytes: 858993459, percentage: 20.0, color: '#ef4444' }
]
})
// 事件处理 // 事件处理
const onSelectSoftware = (software: any) => { const showSoftwareDetail = (software: any) => {
selectedSoftware.value = software selectedSoftware.value = software
showDetailModal.value = true
} }
const refreshData = () => { const refreshData = () => {
@@ -400,10 +310,7 @@ watch(selectedInterface, () => {
}) })
onMounted(() => { onMounted(() => {
// 初始化时选择第一个软件 // 页面初始化,不再默认选择软件
if (softwareRankingData.value.length > 0) {
selectedSoftware.value = softwareRankingData.value[0]
}
}) })
</script> </script>
@@ -550,7 +457,7 @@ onMounted(() => {
/* 图表网格 */ /* 图表网格 */
.charts-grid { .charts-grid {
display: grid; display: grid;
grid-template-columns: 2fr 1fr 1fr; grid-template-columns: 2fr 1fr;
gap: 16px; gap: 16px;
margin-bottom: 24px; margin-bottom: 24px;
} }
@@ -709,22 +616,18 @@ onMounted(() => {
text-align: right; text-align: right;
} }
/* 底部分析区域 */ /* 软件分析区域 */
.bottom-analysis-area { .software-analysis-area {
display: grid;
grid-template-columns: 400px 1fr;
gap: 20px;
margin-top: 24px; margin-top: 24px;
} }
.traffic-ranking-panel, .software-ranking-panel {
.software-detail-panel {
background: var(--bg-card); background: var(--bg-card);
backdrop-filter: var(--backdrop-blur); backdrop-filter: var(--backdrop-blur);
border: 1px solid var(--border-primary); border: 1px solid var(--border-primary);
border-radius: 12px; border-radius: 12px;
overflow: hidden; overflow: hidden;
height: 600px; height: 500px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
@@ -750,74 +653,24 @@ onMounted(() => {
gap: 8px; gap: 8px;
} }
.ranking-content, .ranking-content {
.detail-content {
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;
} }
.software-details {
padding: 20px;
display: flex;
flex-direction: column;
gap: 24px;
height: 100%;
overflow-y: auto;
}
.detail-section {
flex-shrink: 0;
}
.section-title {
font-size: 14px;
font-weight: 600;
color: var(--text-secondary);
margin: 0 0 12px 0;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
color: var(--text-muted);
gap: 16px;
}
.empty-state p {
margin: 0;
font-size: 14px;
}
/* 响应式 */ /* 响应式 */
@media (max-width: 1400px) {
.bottom-analysis-area {
grid-template-columns: 350px 1fr;
}
}
@media (max-width: 1200px) { @media (max-width: 1200px) {
.charts-grid { .charts-grid {
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr;
} }
.chart-card.large { .chart-card.large {
grid-column: span 2; grid-column: span 1;
} }
.bottom-analysis-area { .software-ranking-panel {
grid-template-columns: 1fr; height: 450px;
gap: 16px;
}
.traffic-ranking-panel,
.software-detail-panel {
height: 500px;
} }
} }