From 9b22196eb091c256f7961b4a0537935ec27b316b Mon Sep 17 00:00:00 2001 From: zxr <271055687@qq.com> Date: Mon, 21 Sep 2026 10:46:12 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=AA=8C=E6=94=B6=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/ops/ipScan.ts | 2 +- src/api/ops/network-screen.ts | 140 +- .../pages/dc/security/components/Detail.vue | 24 +- src/views/ops/pages/monitor/network/index.vue | 1536 +++++++++++++++-- src/views/ops/pages/monitor/storage/index.vue | 508 ++++-- .../ops/pages/netarch/ip-scan-tasks/index.vue | 18 +- 6 files changed, 1920 insertions(+), 308 deletions(-) diff --git a/src/api/ops/ipScan.ts b/src/api/ops/ipScan.ts index c5dac21..7001037 100644 --- a/src/api/ops/ipScan.ts +++ b/src/api/ops/ipScan.ts @@ -46,7 +46,7 @@ export const fetchIpScanList = (params?: { page?: number; size?: number; keyword export const fetchIpScanDetail = (id: number) => request.get<{ code: number; details?: IpScanTask; message?: string }>(`/DC-Control/v1/ipscans/${id}`) -/** 触发一次扫描,运行记录进入指定采集节点的等待队列。 */ +/** 触发一次扫描,由独立网络扫描服务执行。 */ export const triggerIpScan = (id: number) => request.post<{ code: number; details?: { message?: string }; message?: string }>(`/DC-Control/v1/ipscans/${id}/trigger`) diff --git a/src/api/ops/network-screen.ts b/src/api/ops/network-screen.ts index 7d72e84..31c3c7e 100644 --- a/src/api/ops/network-screen.ts +++ b/src/api/ops/network-screen.ts @@ -1,21 +1,116 @@ import { request } from '@/api/request' +import type { NetworkDeviceService } from '@/api/ops/network-device' -export const fetchNetworkScreenOverview = () => request.get('/DC-Control/v1/network-screen/overview') +export interface NetworkScreenResponse { + code?: number + details?: T + message?: string + timeseq?: number +} -export const fetchNetworkScreenHealthMatrix = (params?: { window?: string }) => - request.get('/DC-Control/v1/network-screen/health-matrix', { params }) +export interface NetworkScreenOverview { + total_devices: number + online_devices: number + abnormal_devices: number + avg_response_time_ms: number + updated_at: string +} -export const fetchNetworkScreenFreshnessDistribution = () => request.get('/DC-Control/v1/network-screen/freshness-distribution') +export interface NetworkHealthMatrixItem { + error_bucket: string + latency_bucket: string + count: number +} -export const fetchNetworkScreenProtocolDistribution = () => request.get('/DC-Control/v1/network-screen/protocol-distribution') +export interface NetworkFreshnessItem { + bucket_label: string + count: number +} -export const fetchNetworkScreenResourceOverview = (params?: { window?: string }) => - request.get('/DC-Control/v1/network-screen/resource-overview', { params }) +export interface NetworkProtocolItem { + protocol: string + snmp_version: string + count: number +} -export const fetchNetworkScreenAlertsStream = (params?: { limit?: number; window?: string }) => - request.get('/DC-Control/v1/network-screen/alerts-stream', { params }) +export interface NetworkDistributionItem { + name: string + count: number +} -export const fetchNetworkScreenDevices = (params?: { +export interface NetworkInterfaceSummary { + latest_timestamp: string + total: number + up: number + down: number +} + +export interface NetworkArpSummary { + latest_timestamp: string + total: number + unique_ip_count: number +} + +export interface NetworkRouteSummary { + latest_timestamp: string + total: number + protocol_share: NetworkDistributionItem[] +} + +export interface NetworkFibSummary { + latest_timestamp: string + total: number + vendor_share: NetworkDistributionItem[] +} + +export interface NetworkResourceOverview { + interface_summary: NetworkInterfaceSummary + arp_summary: NetworkArpSummary + route_summary: NetworkRouteSummary + fib_summary: NetworkFibSummary + meta: { count: number } +} + +export interface NetworkContinuousErrorItem { + id: number + name: string + host: string + status: string + continuous_errors: number + last_check_time: string + status_message: string +} + +export interface NetworkOfflineItem { + id: number + name: string + host: string + last_offline_time: string | null +} + +export interface NetworkStatusHotspotItem { + status_message: string + count: number +} + +export interface NetworkAlertsStream { + top_continuous_errors: NetworkContinuousErrorItem[] + recent_offline: NetworkOfflineItem[] + status_message_hotspots: NetworkStatusHotspotItem[] +} + +export interface NetworkScreenDevice extends NetworkDeviceService { + protocol: string +} + +export interface NetworkDevicePage { + total: number + page: number + size: number + data: NetworkScreenDevice[] +} + +export interface NetworkDeviceQuery { page?: number size?: number keyword?: string @@ -23,4 +118,27 @@ export const fetchNetworkScreenDevices = (params?: { enabled?: boolean protocol?: string vendor?: string -}) => request.get('/DC-Control/v1/network-screen/devices', { params }) +} + +export const fetchNetworkScreenOverview = () => + request.get>('/DC-Control/v1/network-screen/overview') + +export const fetchNetworkScreenHealthMatrix = (params?: { window?: string }) => + request.get>('/DC-Control/v1/network-screen/health-matrix', { + params, + }) + +export const fetchNetworkScreenFreshnessDistribution = () => + request.get>('/DC-Control/v1/network-screen/freshness-distribution') + +export const fetchNetworkScreenProtocolDistribution = () => + request.get>('/DC-Control/v1/network-screen/protocol-distribution') + +export const fetchNetworkScreenResourceOverview = (params?: { window?: string }) => + request.get>('/DC-Control/v1/network-screen/resource-overview', { params }) + +export const fetchNetworkScreenAlertsStream = (params?: { limit?: number; window?: string }) => + request.get>('/DC-Control/v1/network-screen/alerts-stream', { params }) + +export const fetchNetworkScreenDevices = (params?: NetworkDeviceQuery) => + request.get>('/DC-Control/v1/network-screen/devices', { params }) diff --git a/src/views/ops/pages/dc/security/components/Detail.vue b/src/views/ops/pages/dc/security/components/Detail.vue index 68aedab..2dddad1 100644 --- a/src/views/ops/pages/dc/security/components/Detail.vue +++ b/src/views/ops/pages/dc/security/components/Detail.vue @@ -84,7 +84,7 @@ -
{{ item.metric_name }}
+
{{ metricDisplayName(item.metric_name) }}
{{ metricSeriesLabel(item) }}
{{ item.metric_value }} {{ item.metric_unit || '' }}
@@ -117,6 +117,7 @@ import { Message } from '@arco-design/web-vue' import { IconEdit, IconDelete, IconDashboard } from '@arco-design/web-vue/es/icon' import Chart from '@/components/chart/index.vue' import ImportantInterfacesPanel from '../../components/ImportantInterfacesPanel.vue' +import { fetchControlMetricDefinitionOptions } from '@/api/ops/dcControl' import { SECURITY_TYPE_MAP, STATUS_MAP, @@ -139,6 +140,7 @@ defineEmits(['edit', 'delete']) const metricsVisible = ref(false) const metricsLoading = ref(false) const metricsData = ref(null) +const metricDefinitionNames = ref>({}) const selectedMetric = ref('') const trendLoading = ref(false) const trendRows = ref([]) @@ -152,7 +154,7 @@ const accessPointColumns = [ const metricOptions = computed(() => { const names = new Set((metricsData.value?.metrics || []).map((item) => item.metric_name)) - return [...names].sort().map((value) => ({ label: value, value })) + return [...names].sort().map((value) => ({ label: metricDisplayName(value), value })) }) const trendChartOptions = computed(() => { @@ -191,6 +193,7 @@ watch( async (id) => { accessPoints.value = [] metricsData.value = null + metricDefinitionNames.value = {} selectedMetric.value = '' trendRows.value = [] if (!id) return @@ -219,8 +222,17 @@ const handleViewMetrics = async () => { metricsVisible.value = true metricsLoading.value = true try { - const response: any = await fetchSecurityMetricsLatest(props.record.resource_uid) - metricsData.value = response?.details || null + const [definitionsResponse, metricsResponse] = await Promise.all([ + fetchControlMetricDefinitionOptions({ resource_category: 'security', data_source: 'dc-security' }), + fetchSecurityMetricsLatest(props.record.resource_uid), + ]) + if (definitionsResponse.code !== undefined && definitionsResponse.code !== 0) { + throw new Error(definitionsResponse.message || '获取安全设备指标定义失败') + } + metricDefinitionNames.value = Object.fromEntries( + (definitionsResponse.details?.list || []).map((item) => [item.metric_code, item.metric_name]) + ) + metricsData.value = metricsResponse.details || null selectedMetric.value = metricOptions.value[0]?.value || '' if (selectedMetric.value) await loadTrend() } catch (error) { @@ -273,9 +285,11 @@ const metricSeriesLabel = (metric: SecurityMetric) => { const trendSeriesName = (seriesKey: string, metric?: SecurityMetric) => { const label = metric ? metricSeriesLabel(metric) : '' if (label) return label - return seriesKey === 'default' ? selectedMetric.value : seriesKey.slice(0, 8) + return seriesKey === 'default' ? metricDisplayName(selectedMetric.value) : seriesKey.slice(0, 8) } +const metricDisplayName = (metricName: string) => metricDefinitionNames.value[metricName] + const formatTime = (time?: string | null) => { if (!time) return '-' if (time.startsWith('0001-01-01')) return '-' diff --git a/src/views/ops/pages/monitor/network/index.vue b/src/views/ops/pages/monitor/network/index.vue index c563b7f..d8a095f 100644 --- a/src/views/ops/pages/monitor/network/index.vue +++ b/src/views/ops/pages/monitor/network/index.vue @@ -1,118 +1,391 @@