diff --git a/src/api/ops/room-device.ts b/src/api/ops/room-device.ts index c14329b..2c337b1 100644 --- a/src/api/ops/room-device.ts +++ b/src/api/ops/room-device.ts @@ -18,7 +18,15 @@ export interface RoomDeviceItem { collect_method: 'api' | 'snmp' snmp_target: string snmp_port: number + snmp_version: 'v2c' | 'v3' snmp_community: string + snmp_v3_security_level: string + snmp_v3_security_name: string + snmp_v3_auth_protocol: string + snmp_v3_auth_password: string + snmp_v3_priv_protocol: string + snmp_v3_priv_password: string + snmp_v3_context_name: string snmp_timeout_ms: number snmp_retries: number snmp_oids: string @@ -67,7 +75,15 @@ export interface RoomDeviceCreateData { collect_method?: 'api' | 'snmp' snmp_target?: string snmp_port?: number + snmp_version?: 'v2c' | 'v3' snmp_community?: string + snmp_v3_security_level?: string + snmp_v3_security_name?: string + snmp_v3_auth_protocol?: string + snmp_v3_auth_password?: string + snmp_v3_priv_protocol?: string + snmp_v3_priv_password?: string + snmp_v3_context_name?: string snmp_timeout_ms?: number snmp_retries?: number snmp_oids?: string @@ -87,7 +103,15 @@ export interface RoomDeviceUpdateData { collect_method?: 'api' | 'snmp' snmp_target?: string snmp_port?: number + snmp_version?: 'v2c' | 'v3' snmp_community?: string + snmp_v3_security_level?: string + snmp_v3_security_name?: string + snmp_v3_auth_protocol?: string + snmp_v3_auth_password?: string + snmp_v3_priv_protocol?: string + snmp_v3_priv_password?: string + snmp_v3_context_name?: string snmp_timeout_ms?: number snmp_retries?: number snmp_oids?: string @@ -103,7 +127,15 @@ export interface RoomDeviceCollectData { agent_config?: string snmp_target?: string snmp_port?: number + snmp_version?: 'v2c' | 'v3' snmp_community?: string + snmp_v3_security_level?: string + snmp_v3_security_name?: string + snmp_v3_auth_protocol?: string + snmp_v3_auth_password?: string + snmp_v3_priv_protocol?: string + snmp_v3_priv_password?: string + snmp_v3_context_name?: string snmp_timeout_ms?: number snmp_retries?: number snmp_oids?: string diff --git a/src/api/ops/security.ts b/src/api/ops/security.ts index 01f9395..acd620f 100644 --- a/src/api/ops/security.ts +++ b/src/api/ops/security.ts @@ -22,7 +22,15 @@ export interface SecurityServiceItem { collect_method: 'api' | 'snmp' snmp_target: string snmp_port: number + snmp_version: 'v2c' | 'v3' snmp_community: string + snmp_v3_security_level: string + snmp_v3_security_name: string + snmp_v3_auth_protocol: string + snmp_v3_auth_password: string + snmp_v3_priv_protocol: string + snmp_v3_priv_password: string + snmp_v3_context_name: string snmp_timeout_ms: number snmp_retries: number snmp_oids: string @@ -75,7 +83,15 @@ export interface SecurityServiceFormData { collect_method?: 'api' | 'snmp' snmp_target?: string snmp_port?: number + snmp_version?: 'v2c' | 'v3' snmp_community?: string + snmp_v3_security_level?: string + snmp_v3_security_name?: string + snmp_v3_auth_protocol?: string + snmp_v3_auth_password?: string + snmp_v3_priv_protocol?: string + snmp_v3_priv_password?: string + snmp_v3_context_name?: string snmp_timeout_ms?: number snmp_retries?: number snmp_oids?: string @@ -138,7 +154,15 @@ export interface SecurityServicePatchData { agent_config?: string snmp_target?: string snmp_port?: number + snmp_version?: 'v2c' | 'v3' snmp_community?: string + snmp_v3_security_level?: string + snmp_v3_security_name?: string + snmp_v3_auth_protocol?: string + snmp_v3_auth_password?: string + snmp_v3_priv_protocol?: string + snmp_v3_priv_password?: string + snmp_v3_context_name?: string snmp_timeout_ms?: number snmp_retries?: number snmp_oids?: string diff --git a/src/api/ops/storage.ts b/src/api/ops/storage.ts index 1f12395..cf68088 100644 --- a/src/api/ops/storage.ts +++ b/src/api/ops/storage.ts @@ -22,7 +22,15 @@ export interface StorageItem { collect_method: 'api' | 'snmp' snmp_target: string snmp_port: number + snmp_version: 'v2c' | 'v3' snmp_community: string + snmp_v3_security_level: string + snmp_v3_security_name: string + snmp_v3_auth_protocol: string + snmp_v3_auth_password: string + snmp_v3_priv_protocol: string + snmp_v3_priv_password: string + snmp_v3_context_name: string snmp_timeout_ms: number snmp_retries: number snmp_oids: string @@ -75,7 +83,15 @@ export interface StorageCreateData { collect_method?: 'api' | 'snmp' snmp_target?: string snmp_port?: number + snmp_version?: 'v2c' | 'v3' snmp_community?: string + snmp_v3_security_level?: string + snmp_v3_security_name?: string + snmp_v3_auth_protocol?: string + snmp_v3_auth_password?: string + snmp_v3_priv_protocol?: string + snmp_v3_priv_password?: string + snmp_v3_context_name?: string snmp_timeout_ms?: number snmp_retries?: number snmp_oids?: string @@ -103,7 +119,15 @@ export interface StorageUpdateData { collect_method?: 'api' | 'snmp' snmp_target?: string snmp_port?: number + snmp_version?: 'v2c' | 'v3' snmp_community?: string + snmp_v3_security_level?: string + snmp_v3_security_name?: string + snmp_v3_auth_protocol?: string + snmp_v3_auth_password?: string + snmp_v3_priv_protocol?: string + snmp_v3_priv_password?: string + snmp_v3_context_name?: string snmp_timeout_ms?: number snmp_retries?: number snmp_oids?: string @@ -316,7 +340,15 @@ export interface StoragePatchData { agent_config?: string snmp_target?: string snmp_port?: number + snmp_version?: 'v2c' | 'v3' snmp_community?: string + snmp_v3_security_level?: string + snmp_v3_security_name?: string + snmp_v3_auth_protocol?: string + snmp_v3_auth_password?: string + snmp_v3_priv_protocol?: string + snmp_v3_priv_password?: string + snmp_v3_context_name?: string snmp_timeout_ms?: number snmp_retries?: number snmp_oids?: string diff --git a/src/api/ops/traffic-runtime.ts b/src/api/ops/traffic-runtime.ts new file mode 100644 index 0000000..284fb5e --- /dev/null +++ b/src/api/ops/traffic-runtime.ts @@ -0,0 +1,21 @@ +import { request } from '@/api/request' + +export interface TrafficRuntimeStatus { + status?: 'running' | 'stopped' | string + message?: string +} + +export const fetchTrafficRuntimeStatus = () => + request.get<{ code: number; details?: TrafficRuntimeStatus; message?: string }>( + '/dc-network/v1/api/traffic/status', + ) + +export const startTrafficRuntime = () => + request.post<{ code: number; details?: TrafficRuntimeStatus; message?: string }>( + '/dc-network/v1/api/traffic/start', + ) + +export const stopTrafficRuntime = () => + request.post<{ code: number; details?: TrafficRuntimeStatus; message?: string }>( + '/dc-network/v1/api/traffic/stop', + ) diff --git a/src/api/ops/traffic.ts b/src/api/ops/traffic.ts new file mode 100644 index 0000000..6a241ad --- /dev/null +++ b/src/api/ops/traffic.ts @@ -0,0 +1,120 @@ +import { request } from '@/api/request' + +export interface TrafficListItem { + id: number + topology_id: number + link_id: number + node_id: string + time_granularity: string + time_point: string + in_bytes: number + out_bytes: number + total_bytes: number + in_packets: number + out_packets: number + total_packets: number + connections: number + avg_latency: number + packet_loss: number + bandwidth: number + bandwidth_peak: number + protocol_stats?: string + top_sources?: string +} + +export interface TrafficListResponse { + total: number + page: number + page_size: number + data: TrafficListItem[] +} + +export interface TrafficSummary { + total_in_bytes: number + total_out_bytes: number + total_bytes: number + avg_bandwidth: number + peak_bandwidth: number + total_connections: number + avg_packet_loss: number +} + +export interface TrafficTrendPoint { + time: string + in_bytes: number + out_bytes: number + total_bytes: number +} + +export interface TrafficTopItem { + node_id: string + total_in_bytes: number + total_out_bytes: number + total_bytes: number + total_packets: number +} + +export interface TrafficDashboardResponse { + direction: { + inbound_percent: number + outbound_percent: number + } + protocols: Array<{ + name: string + percent: number + }> + top_applications: Array<{ + name: string + in_bytes: number + out_bytes: number + total_bytes: number + share_percent: number + sessions: number + port: string + }> + top_sources: Array<{ + ip: string + name: string + total_bytes: number + total_packets: number + }> + bandwidth: Array<{ + name: string + percent: number + }> +} + +export const fetchTrafficList = (params?: Record) => + request.get<{ code: number; details?: TrafficListResponse; message?: string }>('/DC-Control/v1/traffic', { + params, + }) + +export const fetchTrafficSummary = (params?: Record) => + request.get<{ code: number; details?: TrafficSummary; message?: string }>( + '/DC-Control/v1/traffic/summary', + { params }, + ) + +export const fetchTrafficTrend = (params?: Record) => + request.get<{ code: number; details?: { data?: TrafficTrendPoint[] }; message?: string }>( + '/DC-Control/v1/traffic/trend', + { params }, + ) + +export const fetchTopTraffic = (params?: Record) => + request.get<{ code: number; details?: { data?: TrafficTopItem[] }; message?: string }>( + '/DC-Control/v1/traffic/top', + { params }, + ) + +export const fetchRealtimeTraffic = (params?: Record) => + request.get<{ code: number; details?: { bandwidth?: number; connections?: number }; message?: string }>( + '/DC-Control/v1/traffic/realtime', + { params }, + ) + +export const fetchTrafficDashboard = (params?: Record) => + request.get<{ code: number; details?: TrafficDashboardResponse; message?: string }>( + '/DC-Control/v1/traffic/dashboard', + { params }, + ) diff --git a/src/views/ops/pages/dc/database/components/DetailDialog.vue b/src/views/ops/pages/dc/database/components/DetailDialog.vue index 62c19e0..112c141 100644 --- a/src/views/ops/pages/dc/database/components/DetailDialog.vue +++ b/src/views/ops/pages/dc/database/components/DetailDialog.vue @@ -1,139 +1,123 @@ \ No newline at end of file diff --git a/src/views/ops/pages/dc/database/index.vue b/src/views/ops/pages/dc/database/index.vue index 71008b9..1201973 100644 --- a/src/views/ops/pages/dc/database/index.vue +++ b/src/views/ops/pages/dc/database/index.vue @@ -103,20 +103,32 @@ @@ -132,6 +144,9 @@ @@ -149,6 +164,7 @@ import { Message, Modal } from '@arco-design/web-vue' import { IconPlus, IconSync, + IconDown, IconEye, IconEdit, IconDelete, @@ -360,6 +376,7 @@ const handleAdd = () => { // 查看详情 const handleDetail = (record: DatabaseService) => { + currentRecord.value = record currentRecordId.value = record.id detailDialogVisible.value = true } @@ -375,6 +392,22 @@ const handleCollect = () => { collectDialogVisible.value = true } +const handleDetailEdit = (record: DatabaseService) => { + detailDialogVisible.value = false + currentRecord.value = record + formDialogVisible.value = true +} + +const handleDetailDelete = (record: DatabaseService) => { + detailDialogVisible.value = false + handleDelete(record) +} + +const handleDetailCollect = () => { + detailDialogVisible.value = false + collectDialogVisible.value = true +} + // 表单提交成功 const handleFormSuccess = () => { fetchList() diff --git a/src/views/ops/pages/dc/device-collect/components/Detail.vue b/src/views/ops/pages/dc/device-collect/components/Detail.vue index 111a10c..6479756 100644 --- a/src/views/ops/pages/dc/device-collect/components/Detail.vue +++ b/src/views/ops/pages/dc/device-collect/components/Detail.vue @@ -1,6 +1,6 @@ @@ -61,7 +139,18 @@ const form = ref({ collect_interval: 60, agent_config: '', snmp_target: '', + snmp_port: 161, + snmp_version: 'v2c' as 'v2c' | 'v3', snmp_community: '', + snmp_v3_security_level: 'noAuthNoPriv', + snmp_v3_security_name: '', + snmp_v3_auth_protocol: 'SHA', + snmp_v3_auth_password: '', + snmp_v3_priv_protocol: 'AES', + snmp_v3_priv_password: '', + snmp_v3_context_name: '', + snmp_timeout_ms: 3000, + snmp_retries: 1, }) watch( @@ -73,7 +162,18 @@ watch( form.value.collect_interval = props.record.collect_interval || 60 form.value.agent_config = props.record.agent_config || '' form.value.snmp_target = props.record.snmp_target || '' + form.value.snmp_port = props.record.snmp_port || 161 + form.value.snmp_version = props.record.snmp_version || 'v2c' form.value.snmp_community = props.record.snmp_community || '' + form.value.snmp_v3_security_level = props.record.snmp_v3_security_level || 'noAuthNoPriv' + form.value.snmp_v3_security_name = props.record.snmp_v3_security_name || '' + form.value.snmp_v3_auth_protocol = props.record.snmp_v3_auth_protocol || 'SHA' + form.value.snmp_v3_auth_password = '' + form.value.snmp_v3_priv_protocol = props.record.snmp_v3_priv_protocol || 'AES' + form.value.snmp_v3_priv_password = '' + form.value.snmp_v3_context_name = props.record.snmp_v3_context_name || '' + form.value.snmp_timeout_ms = props.record.snmp_timeout_ms || 3000 + form.value.snmp_retries = props.record.snmp_retries ?? 1 } } ) @@ -81,13 +181,51 @@ watch( const handleSubmit = async () => { loading.value = true try { + if (form.value.collect_method === 'api' && !form.value.agent_config?.trim()) { + Message.warning('API 模式下请填写采集地址') + return + } + if (form.value.collect_method === 'snmp') { + if (!form.value.snmp_target?.trim()) { + Message.warning('SNMP 模式下请填写目标地址') + return + } + if (form.value.snmp_version === 'v3') { + if (!form.value.snmp_v3_security_name?.trim()) { + Message.warning('SNMP v3 请填写 Security Name') + return + } + if (form.value.snmp_v3_security_level !== 'noAuthNoPriv' && !form.value.snmp_v3_auth_password?.trim()) { + Message.warning('SNMP v3 认证级别请填写 Auth 密码') + return + } + if (form.value.snmp_v3_security_level === 'authPriv' && !form.value.snmp_v3_priv_password?.trim()) { + Message.warning('SNMP v3 authPriv 请填写 Priv 密码') + return + } + } else if (!form.value.snmp_community?.trim()) { + Message.warning('SNMP v2c 模式下请填写 community') + return + } + } const data: RoomDeviceCollectData = { collect_method: form.value.collect_method, collect_on: form.value.collect_on, collect_interval: form.value.collect_interval, agent_config: form.value.collect_method === 'api' ? form.value.agent_config : undefined, snmp_target: form.value.collect_method === 'snmp' ? form.value.snmp_target : undefined, + snmp_port: form.value.collect_method === 'snmp' ? form.value.snmp_port : undefined, + snmp_version: form.value.collect_method === 'snmp' ? form.value.snmp_version : undefined, snmp_community: form.value.collect_method === 'snmp' ? form.value.snmp_community : undefined, + snmp_v3_security_level: form.value.collect_method === 'snmp' ? form.value.snmp_v3_security_level : undefined, + snmp_v3_security_name: form.value.collect_method === 'snmp' ? form.value.snmp_v3_security_name : undefined, + snmp_v3_auth_protocol: form.value.collect_method === 'snmp' ? form.value.snmp_v3_auth_protocol : undefined, + snmp_v3_auth_password: form.value.collect_method === 'snmp' ? form.value.snmp_v3_auth_password : undefined, + snmp_v3_priv_protocol: form.value.collect_method === 'snmp' ? form.value.snmp_v3_priv_protocol : undefined, + snmp_v3_priv_password: form.value.collect_method === 'snmp' ? form.value.snmp_v3_priv_password : undefined, + snmp_v3_context_name: form.value.collect_method === 'snmp' ? form.value.snmp_v3_context_name : undefined, + snmp_timeout_ms: form.value.collect_method === 'snmp' ? form.value.snmp_timeout_ms : undefined, + snmp_retries: form.value.collect_method === 'snmp' ? form.value.snmp_retries : undefined, } await patchRoomDeviceCollect(props.record.id, data) diff --git a/src/views/ops/pages/dc/device-collect/index.vue b/src/views/ops/pages/dc/device-collect/index.vue index 806f993..056e5f3 100644 --- a/src/views/ops/pages/dc/device-collect/index.vue +++ b/src/views/ops/pages/dc/device-collect/index.vue @@ -1,4 +1,4 @@ -