fix: 初验针对修改

This commit is contained in:
zxr
2026-09-09 16:43:43 +08:00
parent a6a6198eaa
commit 781d1af337
179 changed files with 8533 additions and 15030 deletions

View File

@@ -22,6 +22,8 @@ export interface MessageRecord {
firstOccurredAt?: string
lastOccurredAt?: string
lastDeliveryId?: number
severity?: string
soundEnabled?: boolean
}
export type MessageListType = MessageRecord[]

View File

@@ -1,35 +0,0 @@
import { request } from '@/api/request'
/** 批次列表 */
export const fetchLoanBatch = (data: { page: number; size: number }) => request.post('/factor/v1/fetch/loan_batch', data)
/** 上报列表 */
export const fetchTransferWatch = (data: { page: number; size: number }) => request.post('/factor/v1/fetch/transfer_watch', data)
/** 回盘列表 */
export const fetchTransferDown = (data: { page: number; size: number }) => request.post('/factor/v1/fetch/transfer_down', data)
/** 放款数据列表 */
export const fetchDataFile = (data: { page: number; size: number }) => request.post('/factor/v1/fetch/data_file', data)
/** 回盘数据列表 */
export const fetchDataReply = (data: { page: number; size: number }) => request.post('/factor/v1/fetch/data_reply', data)
/** 贷款支付数据列表 */
export const fetchLoanPayment = (data: { page: number; size: number; status?: number }) =>
request.post('/factor/v1/fetch/loan_payment', data)
/** 获取日报数据 */
export const fetchOverviewReports = (data: { page: number; size: number }) => request.post('/factor/v1/reports/overview', data)
/** 获取日报数据 */
export const fetchDailyReports = (data: { page: number; size: number }) => request.post('/factor/v1/reports/days', data)
/** 获取周报数据 */
export const fetchWeeklyReports = (data: { page: number; size: number }) => request.post('/factor/v1/reports/weeks', data)
/** 获取月报数据 */
export const fetchMonthlyReports = (data: { page: number; size: number }) => request.post('/factor/v1/reports/months', data)
/** 获取批次详情 */
export const getLoanBatchDetail = (data: { batch_id: number }) => request.post(`/factor/v1/get/batch`, data)

View File

@@ -34,11 +34,3 @@ export const modifyMenu = (data: MenuItem) => request.post('/rbac2/v1/pmn/modify
export const deleteMenu = (data: { id: MenuItem['id'] }) => request.post('/rbac2/v1/pmn/del', data, { needWorkspace: true })
/** 更新菜单排序 */
export const updateMenuOrder = (data: { pmn_id: number; sort_key: number }[]) => request.post('/rbac2/v1/pmn/sort', data)
/** 用户-给指定用户设置权限 */
export const userPmn = (data: { code: string; list: { id: number; pmn_id: number }[] }) =>
request.post('/rbac2/v1/pmn/user_pmn', data, { needWorkspace: true })
/** 用户-给指定用户设置权限 */
export const userSetPmn = (data: { list: { id: number; pmn_id: number }[] }) =>
request.post('/rbac2/v1/pmn/user/set_pmn', data, { needWorkspace: true })

View File

@@ -4,7 +4,9 @@ import { LoginRequest, UserItem } from '../types'
/** 登录 */
export const login = (data: LoginRequest) => request.post('/rbac2/v1/login', data)
/** 登出 */
export const logout = () => request.post('/rbac2/v1/logout')
export const logout = () => request.post('/rbac2/v1/user/logout')
/** 更新在线状态 */
export const heartbeat = () => request.post('/rbac2/v1/user/heartbeat')
/** 获取菜单列表 */
export const getMenuList = () => request.post('/rbac2/v1/user/menu')
/** 创建用户 */
@@ -17,19 +19,14 @@ export const fetchUserList = (data: { page: number; size: number; keyword?: stri
export const modifyUser = (data: UserItem) => request.post('/rbac2/v1/user/modify', data)
/** 删除用户 */
export const deleteUser = (data: { id: UserItem['id'] }) => request.post('/rbac2/v1/user/del', data)
/** 获取所有权限【树形】 */
export const getUserPmnTree = (data: { id: UserItem['id']; workspace: string }) => request.post('/rbac2/v1/user/pmn_tree', data)
/** 用户-获取所有权限【平面】 */
/** 获取用户通过角色获得的权限 */
export const userPmn = (data: { id: UserItem['id']; workspace: string }) =>
request.post('/rbac2/v1/user/pmn', data, { needWorkspace: true })
/** 用户-给指定用户设置权限 */
export const userSetPmn = (data: { list: { id: number; pmn_id: number }[] }) =>
request.post('/rbac2/v1/user/set_pmn', data, { needWorkspace: true })
/** 用户-给指定用户编辑权限 */
export const userModifyPmn = (data: { id: UserItem['id']; list: number[] }) =>
request.post('/rbac2/v1/user/modify_pmn', data, { needWorkspace: true })
/** 在线用户 */
export const fetchOnlineUsers = (data: { page: number; size: number; keyword?: string }) => request.post('/rbac2/v1/user/online', data)
/** 登录日志 */
export const fetchLoginLogs = (data: { page: number; size: number; keyword?: string; result?: string }) =>
request.post('/rbac2/v1/user/login-logs', data)
/** 重置密码(短信) */
export const resetUserPassword = (data: {

View File

@@ -143,5 +143,38 @@ export interface PolicyOptionsParams {
enabled?: boolean
}
export type ServicePolicyCategory = 'database' | 'middleware' | 'host' | 'security' | 'storage' | 'room_device'
export interface ServicePolicyBindingDetails {
category: ServicePolicyCategory
service_identity: string
source_version: number
policy_ids: number[]
}
export interface AlertBindingSyncStatus {
category: ServicePolicyCategory
service_identity: string
source_version?: number
status: 'none' | 'pending' | 'processing' | 'succeeded' | 'failed'
attempt_count?: number
last_error?: string
last_http_code?: number
last_attempt_at?: string
next_attempt_at?: string
}
/** 获取告警策略下拉选项(不分页),支持 keyword 模糊搜索与 enabled 过滤 */
export const fetchPolicyOptions = (params?: PolicyOptionsParams) => request.get<PolicyOptionItem[]>('/Alert/v1/policy/options', { params })
/** 获取资源当前绑定的告警策略 */
export const fetchServicePolicyBindings = (category: ServicePolicyCategory, serviceIdentity: string) =>
request.get<{ code: number; details?: ServicePolicyBindingDetails; message?: string }>('/Alert/v1/service-policy-bindings', {
params: { category, service_identity: serviceIdentity },
})
/** 获取告警策略绑定同步状态 */
export const fetchAlertBindingSyncStatus = (category: ServicePolicyCategory, serviceIdentity: string) =>
request.get<{ code: number; details?: AlertBindingSyncStatus; message?: string }>('/DC-Control/v1/alert-binding-sync/status', {
params: { category, service_identity: serviceIdentity },
})

View File

@@ -17,6 +17,8 @@ export const fetchAlertRecords = (data: {
resource_category?: string
server_identity?: string
ip?: string
resource_uid?: string
mine?: boolean
}) => {
return request.get('/Alert/v1/record/list', { params: data })
}
@@ -24,13 +26,21 @@ export const fetchAlertRecords = (data: {
/** 获取 告警记录详情 */
export const fetchAlertRecordDetail = (id: number) => request.get(`/Alert/v1/record/get/${id}`)
/** 按统一资源批量获取未恢复告警,供拓扑等视图复用。 */
export const fetchActiveAlertsByResources = (resourceUids: string[], limitPerResource = 5) =>
request.post('/Alert/v1/record/active/by-resources', {
resource_uids: resourceUids,
limit_per_resource: limitPerResource,
})
/** 创建处理记录(执行确认/解决/屏蔽等操作) */
export const createAlertProcess = (data: {
alert_record_id: number
action: string // ack / resolve / silence / comment / assign / escalate / close
comment?: string
assign_to?: string
assign_to_id?: string
assign_to_id?: number
assign_role_id?: number
silence_until?: string
silence_reason?: string
escalate_level?: string
@@ -41,6 +51,9 @@ export const createAlertProcess = (data: {
metadata?: string
}) => request.post('/Alert/v1/process/create', data)
/** 获取“级别—状态—监控对象”告警分类计数。 */
export const fetchAlertTree = (mine = false) => request.get('/Alert/v1/record/tree', { params: { mine } })
/** 获取 告警处理记录列表 */
export const fetchAlertProcessList = (data: {
alert_record_id?: number

View File

@@ -0,0 +1,74 @@
import { request } from '@/api/request'
export interface MessageContentTemplate {
id?: number
code: string
name: string
description?: string
enabled: boolean
subject_template: string
body_template: string
recovery_subject_template: string
recovery_body_template: string
}
export interface NotificationGroup {
id?: number
code: string
name: string
description?: string
enabled: boolean
member_user_ids: number[] | string
}
export interface RoutingScope {
priority: number
resource_category?: string
business_system_id?: number
ip_cidr?: string
device_level?: string
label_matchers?: Record<string, string>
}
export interface ResponsibilityRule extends RoutingScope {
id?: number
code: string
name: string
description?: string
enabled: boolean
owner_user_id: number
subscriber_group_ids: number[] | string
cc_user_ids: number[] | string
}
export interface NotificationPolicy extends RoutingScope {
id?: number
name: string
enabled: boolean
severity_filter: string[] | string
channel_ids: number[] | string
notification_group_ids: number[] | string
cc_user_ids: number[] | string
}
type ListParams = { page?: number; page_size?: number; keyword?: string; enabled?: boolean | string }
export const fetchMessageTemplateList = (params?: ListParams) => request.get('/Alert/v1/message-template/list', { params: params || {} })
export const createMessageTemplate = (data: MessageContentTemplate) => request.post('/Alert/v1/message-template/create', data)
export const updateMessageTemplate = (data: MessageContentTemplate) => request.post('/Alert/v1/message-template/update', data)
export const deleteMessageTemplate = (id: number) => request.delete(`/Alert/v1/message-template/delete/${id}`)
export const fetchNotificationGroupList = (params?: ListParams) => request.get('/Alert/v1/notification-group/list', { params: params || {} })
export const createNotificationGroup = (data: NotificationGroup) => request.post('/Alert/v1/notification-group/create', data)
export const updateNotificationGroup = (data: NotificationGroup) => request.post('/Alert/v1/notification-group/update', data)
export const deleteNotificationGroup = (id: number) => request.delete(`/Alert/v1/notification-group/delete/${id}`)
export const fetchResponsibilityList = (params?: ListParams) => request.get('/Alert/v1/responsibility/list', { params: params || {} })
export const createResponsibility = (data: ResponsibilityRule) => request.post('/Alert/v1/responsibility/create', data)
export const updateResponsibility = (data: ResponsibilityRule) => request.post('/Alert/v1/responsibility/update', data)
export const deleteResponsibility = (id: number) => request.delete(`/Alert/v1/responsibility/delete/${id}`)
export const fetchNotificationPolicyList = (params?: ListParams) => request.get('/Alert/v1/notification-policy/list', { params: params || {} })
export const createNotificationPolicy = (data: NotificationPolicy) => request.post('/Alert/v1/notification-policy/create', data)
export const updateNotificationPolicy = (data: NotificationPolicy) => request.post('/Alert/v1/notification-policy/update', data)
export const deleteNotificationPolicy = (id: number) => request.delete(`/Alert/v1/notification-policy/delete/${id}`)

View File

@@ -44,17 +44,33 @@ export interface AssetListParams {
status?: string
sort?: string
order?: string
category_code?: string
manufacturer_code?: string
datacenter_id?: number
province_id?: number
city_id?: number
room_id?: number
rack_id?: number
department_id?: number
department?: string
business_system_id?: number
device_level?: string
projection_status?: string
}
/** 资产表单数据 */
export interface AssetForm {
id?: number
resource_uid?: string
asset_name: string
asset_code: string
category_id?: number
model?: string
manufacturer?: string
manufacturer_id?: number
manufacturer_code?: string
serial_number?: string
management_ip?: string
device_level?: 'core' | 'important' | 'normal'
source_address?: string
purchase_date?: string
original_value?: number
@@ -62,6 +78,8 @@ export interface AssetForm {
warranty_period?: number
warranty_expiry?: string
department?: string
department_id?: number
business_system_id?: number
user?: string
status?: string
location?: string
@@ -74,48 +92,49 @@ export interface AssetForm {
specifications?: string
description?: string
remarks?: string
attachments?: string
}
/** 获取资产列表(分页) */
export const fetchAssetList = (data?: AssetListParams) => {
return request.post('/Assets/v1/asset/list', data || {})
return request.get('/Assets/v1/devices', { params: data || {} })
}
/** 获取资产列表(不分页,下拉) */
export const fetchAssetAll = (params?: { keyword?: string }) => {
return request.get('/Assets/v1/asset/all', { params })
return request.get('/Assets/v1/devices/options', { params })
}
/** 获取资产详情 */
export const fetchAssetDetail = (id: number) => {
return request.get(`/Assets/v1/asset/detail/${id}`)
export const fetchAssetDetail = (resourceUid: string) => {
return request.get(`/Assets/v1/devices/${encodeURIComponent(resourceUid)}`)
}
/** 创建资产 */
export const createAsset = (data: AssetForm) => {
return request.post('/Assets/v1/asset/create', data)
return request.post('/Assets/v1/devices', data)
}
/** 批量导入资产 */
export const bulkImportAssets = (data: { dry_run?: boolean; items: any[] }) => {
return request.post('/Assets/v1/asset/bulk_import', data)
return request.post('/Assets/v1/devices/bulk-import', data)
}
/** 更新资产 */
export const updateAsset = (data: AssetForm) => {
return request.put('/Assets/v1/asset/update', data)
export const updateAsset = (resourceUid: string, data: AssetForm) => {
return request.put(`/Assets/v1/devices/${encodeURIComponent(resourceUid)}`, data)
}
/** 删除资产 */
export const deleteAsset = (id: number) => {
return request.delete(`/Assets/v1/asset/delete/${id}`)
export const deleteAsset = (resourceUid: string) => {
return request.delete(`/Assets/v1/devices/${encodeURIComponent(resourceUid)}`)
}
/** 导出资产 */
export const exportAssets = (keyword?: string) => {
const params: any = {}
if (keyword) params.keyword = keyword
return request.get('/Assets/v1/asset/export', { params })
return request.get('/Assets/v1/devices/export', { params })
}
/** 获取资产分类列表(下拉) */
@@ -128,24 +147,7 @@ export const fetchSupplierOptions = () => {
return request.get('/Assets/v1/supplier/all')
}
/** 绑定资产和监控资源 */
export const linkAssetResource = (data: {
asset_id: number
resource_uid: string
display_name?: string
business_system_id?: number
health_status?: string
alert_status?: string
}) => {
return request.post('/Assets/v1/asset/resource/link', data)
}
/** 查询资产绑定的监控资源 */
export const fetchAssetResourceBindings = (assetId: number) => {
return request.get(`/Assets/v1/asset/resource/${assetId}`)
}
/** 解除资产和监控资源绑定 */
export const unlinkAssetResource = (assetId: number, resourceUid: string) => {
return request.delete(`/Assets/v1/asset/resource/${assetId}`, { params: { resource_uid: resourceUid } })
/** 获取生产厂商列表(下拉) */
export const fetchManufacturerOptions = (keyword?: string) => {
return request.get('/Assets/v1/manufacturers/options', { params: { keyword } })
}

View File

@@ -1,87 +0,0 @@
import { request } from '@/api/request'
export interface AutomationScript {
id: number
name: string
resource_category: string
command_template: string
approval_level: string
rollback_command?: string
rollback_required: boolean
description?: string
status: string
created_at?: string
updated_at?: string
}
export interface AutomationExecution {
id: number
script_id: number
mode: string
status: string
resource_uid: string
rendered_command: string
incident_id?: number
ticket_id?: number
approval_level: string
approved_by?: string
approved_at?: string
operator?: string
started_at?: string
finished_at?: string
timeout_sec?: number
stdout?: string
stderr?: string
exit_code?: number
error?: string
audit_trail?: string
created_at?: string
updated_at?: string
}
export interface AutomationRunRequest {
resource_uid: string
incident_id?: number
ticket_id?: number
operator?: string
approver?: string
approved?: boolean
mode?: 'execute' | 'rollback'
variables?: Record<string, string>
}
export interface PageResponse<T> {
total: number
page: number
page_size: number
data: T[]
}
export const fetchAutomationScripts = (params?: Record<string, any>) =>
request.get<{ details: PageResponse<AutomationScript> }>('/DC-Control/v1/automation/scripts', { params })
export const createAutomationScript = (data: Partial<AutomationScript>) =>
request.post<{ details: AutomationScript }>('/DC-Control/v1/automation/scripts', data)
export const updateAutomationScript = (id: number, data: Partial<AutomationScript>) =>
request.put(`/DC-Control/v1/automation/scripts/${id}`, data)
export const deleteAutomationScript = (id: number) => request.delete(`/DC-Control/v1/automation/scripts/${id}`)
export const dryRunAutomationScript = (id: number, data: AutomationRunRequest) =>
request.post<{ details: AutomationExecution }>(`/DC-Control/v1/automation/scripts/${id}/dry-run`, data)
export const requestAutomationExecution = (id: number, data: AutomationRunRequest) =>
request.post<{ details: AutomationExecution }>(`/DC-Control/v1/automation/scripts/${id}/executions`, data)
export const executeAutomationScript = (id: number, data: AutomationRunRequest) =>
request.post<{ details: AutomationExecution }>(`/DC-Control/v1/automation/scripts/${id}/execute`, data)
export const rollbackAutomationScript = (id: number, data: AutomationRunRequest) =>
request.post<{ details: AutomationExecution }>(`/DC-Control/v1/automation/scripts/${id}/rollback`, data)
export const fetchAutomationExecutions = (params?: Record<string, any>) =>
request.get<{ details: PageResponse<AutomationExecution> }>('/DC-Control/v1/automation/executions', { params })
export const approveAutomationExecution = (id: number, data: { approver: string; operator?: string }) =>
request.post<{ details: AutomationExecution }>(`/DC-Control/v1/automation/executions/${id}/approve`, data)

View File

@@ -17,8 +17,12 @@ export interface BigScreen {
width: number
height: number
status: number
publish_status: 'draft' | 'published' | 'offline' | string
is_public?: boolean
publish_status: 'draft' | 'published' | string
dataset_code: 'network_topology' | 'it_resource_monitor' | 'business_monitor' | string
built_in_code?: string
is_builtin: boolean
carousel_enabled: boolean
carousel_order: number
creator_name?: string
created_at?: string
updated_at?: string
@@ -45,12 +49,15 @@ export interface BigScreenPublish {
export interface BigScreenCarousel {
id: number
name: string
screen_ids: Record<string, any>
interval_seconds: number
enabled: boolean
}
export interface BigScreenDataset {
code: string
name: string
}
export interface BigScreenSnapshot {
id: number
screen_id: number
@@ -79,7 +86,10 @@ export const createBigScreen = (data: Partial<BigScreen>) =>
export const updateBigScreen = (id: number, data: Partial<BigScreen>) =>
request.put<ApiResponse<BigScreen>>(`/Mgt/v1/screen/${id}`, data)
export const publishBigScreen = (data: { screen_id: number; publish_type: 1 | 2; change_log?: string }) =>
export const beginEditBigScreen = (id: number) =>
request.post<ApiResponse<BigScreen>>(`/Mgt/v1/screen/${id}/begin-edit`)
export const publishBigScreen = (data: { screen_id: number; publish_type: 1; change_log?: string }) =>
request.post<ApiResponse<BigScreenPublish>>('/Mgt/v1/publish', data)
export const fetchBigScreenPublishes = (params: { screen_id: number; page?: number; page_size?: number }) =>
@@ -91,11 +101,17 @@ export const fetchBigScreenGroups = () =>
export const createBigScreenGroup = (data: Partial<BigScreenGroup>) =>
request.post<ApiResponse<BigScreenGroup>>('/Mgt/v1/big-screen/groups', data)
export const fetchBigScreenCarousels = () =>
request.get<ApiResponse<BigScreenCarousel[]>>('/Mgt/v1/big-screen/carousels')
export const fetchBigScreenCarousel = () =>
request.get<ApiResponse<BigScreenCarousel>>('/Mgt/v1/big-screen/carousel')
export const createBigScreenCarousel = (data: Partial<BigScreenCarousel>) =>
request.post<ApiResponse<BigScreenCarousel>>('/Mgt/v1/big-screen/carousels', data)
export const updateBigScreenCarousel = (data: Pick<BigScreenCarousel, 'interval_seconds' | 'enabled'>) =>
request.put<ApiResponse<BigScreenCarousel>>('/Mgt/v1/big-screen/carousel', data)
export const updateBigScreenCarouselItem = (id: number, data: { enabled: boolean; order: number }) =>
request.put<ApiResponse<BigScreen>>(`/Mgt/v1/big-screen/screens/${id}/carousel`, data)
export const fetchBigScreenDatasets = () =>
request.get<ApiResponse<BigScreenDataset[]>>('/Mgt/v1/public/big-screens/datasets')
export const fetchBigScreenSnapshots = (params?: { screen_id?: number }) =>
request.get<ApiResponse<BigScreenSnapshot[]>>('/Mgt/v1/big-screen/snapshots', { params })

View File

@@ -171,6 +171,101 @@ export interface ListResult<T> {
count: number
}
/** HTTP/API 检测步骤请求头 */
export interface BusinessHTTPHeader {
name: string
value: string
}
/** HTTP/API 检测响应变量提取 */
export interface BusinessHTTPExtract {
variable: string
source: 'json' | 'header' | 'cookie'
expression: string
}
/** HTTP/API 检测断言 */
export interface BusinessHTTPAssertion {
kind: 'status' | 'max_response_time_ms' | 'header_equals' | 'body_contains' | 'json_exists' | 'json_equals'
expression?: string
expected?: string
}
/** HTTP/API 检测步骤 */
export interface BusinessHTTPCheckStep {
code: string
name: string
method: 'GET' | 'HEAD' | 'POST'
path: string
headers?: Record<string, string>
body?: string
read_only_confirmed?: boolean
extracts?: BusinessHTTPExtract[]
assertions?: BusinessHTTPAssertion[]
}
export interface BusinessHTTPCheck {
id: number
business_system_id: number
name: string
base_url: string
collector_node_id: number
credential_id?: number
enabled: boolean
interval_seconds: number
timeout_seconds: number
version: number
next_run_at?: string
last_run_at?: string
last_status: string
last_duration_ms: number
last_error?: string
last_trace_id?: string
steps: BusinessHTTPCheckStep[]
collector_node?: { id: number; name: string; code: string; status: string }
credential?: { id: number; name: string; code: string; type: string }
}
export interface BusinessHTTPCheckInput {
name: string
base_url: string
collector_node_id: number
credential_id?: number
enabled: boolean
interval_seconds: number
timeout_seconds: number
steps: BusinessHTTPCheckStep[]
}
export interface BusinessHTTPCheckStepResult {
code: string
name: string
span_id: string
success: boolean
status_code: number
duration_ms: number
message: string
method: string
request_path: string
}
export interface BusinessHTTPCheckRun {
id: number
http_check_id: number
business_system_id: number
collector_node_id: number
task_id: string
trigger_type: string
status: string
started_at?: string
finished_at?: string
duration_ms: number
failed_step_code?: string
message?: string
step_results_json: string
trace_id?: string
}
/** 获取业务系统列表 */
export const fetchBusinessSystems = (params?: BusinessSystemListParams) =>
request.get<{ code?: number; details?: PageResult<BusinessSystemItem>; message?: string }>('/DC-Control/v1/business-systems', { params })
@@ -235,3 +330,27 @@ export const fetchBusinessDocumentLinks = (id: number) =>
/** 新增业务文档链接 */
export const createBusinessDocumentLink = (id: number, data: Partial<BusinessDocumentLink>) =>
request.post<{ code?: number; details?: BusinessDocumentLink; message?: string }>(`/DC-Control/v1/business-systems/${id}/documents`, data)
/** 获取业务系统 HTTP/API 检测 */
export const fetchBusinessHTTPChecks = (id: number) =>
request.get<{ code?: number; details?: ListResult<BusinessHTTPCheck>; message?: string }>(`/DC-Control/v1/business-systems/${id}/http-checks`)
export const createBusinessHTTPCheck = (id: number, data: BusinessHTTPCheckInput) =>
request.post<{ code?: number; details?: BusinessHTTPCheck; message?: string }>(`/DC-Control/v1/business-systems/${id}/http-checks`, data)
export const updateBusinessHTTPCheck = (id: number, checkId: number, data: BusinessHTTPCheckInput) =>
request.put<{ code?: number; details?: BusinessHTTPCheck; message?: string }>(`/DC-Control/v1/business-systems/${id}/http-checks/${checkId}`, data)
export const deleteBusinessHTTPCheck = (id: number, checkId: number) =>
request.delete(`/DC-Control/v1/business-systems/${id}/http-checks/${checkId}`)
export const runBusinessHTTPCheck = (id: number, checkId: number) =>
request.post<{ code?: number; details?: { task_id: string; status: string }; message?: string }>(
`/DC-Control/v1/business-systems/${id}/http-checks/${checkId}/run`
)
export const fetchBusinessHTTPCheckRuns = (id: number, checkId: number, limit = 50) =>
request.get<{ code?: number; details?: ListResult<BusinessHTTPCheckRun>; message?: string }>(
`/DC-Control/v1/business-systems/${id}/http-checks/${checkId}/runs`,
{ params: { limit } }
)

180
src/api/ops/collection.ts Normal file
View File

@@ -0,0 +1,180 @@
import { request } from '@/api/request'
const PREFIX = '/DC-Control/v1/monitoring'
export interface PageResult<T> {
total: number
page: number
page_size: number
data: T[]
}
export type CredentialType = 'snmp_v1' | 'snmp_v2c' | 'snmp_v3' | 'ssh' | 'database' | 'http_api' | 'redfish' | 'ipmi'
export interface CollectionCredential {
id: number
code: string
name: string
type: CredentialType
username?: string
scope?: string
description?: string
enabled: boolean
secret_configured: boolean
created_at?: string
updated_at?: string
}
export interface CredentialInput {
code: string
name: string
type: CredentialType
username?: string
scope?: string
description?: string
enabled?: boolean
secret?: Record<string, string>
}
export interface CollectionTemplate {
id: number
code: string
name: string
manufacturer_code: string
resource_category: string
protocol: string
version: number
model_matchers: string
metric_mappings: string
index_discoveries: string
inventory_mappings: string
read_only_queries: string
alert_rule_codes: string
content_digest: string
description?: string
adapter_verified: boolean
verification_note?: string
verified_at?: string
enabled: boolean
}
export type CollectionTemplateInput = Omit<CollectionTemplate, 'id' | 'version' | 'content_digest' | 'verified_at'>
export interface CollectorNode {
id: number
code: string
name: string
node_type: 'center' | 'regional'
region_code?: string
description?: string
enabled: boolean
status: string
capabilities: string
version?: string
queue_depth: number
last_heartbeat_at?: string
last_error?: string
enrollment_expires_at?: string
}
export interface CollectorNodeInput {
code: string
name: string
node_type: 'center' | 'regional'
region_code?: string
description?: string
capabilities: string
enabled?: boolean
}
export interface CollectionBinding {
id: number
name: string
resource_uid: string
collector_node_id: number
credential_id: number
template_id: number
template_version: number
protocol: string
target: string
port: number
interval_seconds: number
retry_policy: string
enabled: boolean
state: string
last_validation_error?: string
collector_node?: CollectorNode
credential?: CollectionCredential
template?: CollectionTemplate
}
export interface CollectionBindingInput {
name: string
resource_uid: string
collector_node_id: number
credential_id: number
template_id: number
protocol: string
target: string
port: number
interval_seconds: number
retry_policy?: string
enabled?: boolean
}
export interface HostAgentRegistration {
id: number
agent_id: string
resource_uid: string
claimed_resource_uid: string
hostname: string
version: string
status: 'confirmed' | 'pending_confirmation'
last_error: string
last_seen_at: string
}
export const fetchCredentials = (params?: Record<string, unknown>) =>
request.get<{ code: number; details?: PageResult<CollectionCredential>; message?: string }>(`${PREFIX}/credentials`, { params })
export const createCredential = (data: CredentialInput) => request.post(`${PREFIX}/credentials`, data)
export const updateCredential = (id: number, data: CredentialInput) => request.put(`${PREFIX}/credentials/${id}`, data)
export const deleteCredential = (id: number) => request.delete(`${PREFIX}/credentials/${id}`)
export const fetchCollectionTemplates = (params?: Record<string, unknown>) =>
request.get<{ code: number; details?: PageResult<CollectionTemplate>; message?: string }>(`${PREFIX}/templates`, { params })
export const createCollectionTemplate = (data: CollectionTemplateInput) => request.post(`${PREFIX}/templates`, data)
export const updateCollectionTemplate = (id: number, data: CollectionTemplateInput) => request.put(`${PREFIX}/templates/${id}`, data)
export const deleteCollectionTemplate = (id: number) => request.delete(`${PREFIX}/templates/${id}`)
export const exportCollectionTemplate = (id: number) => request.get(`${PREFIX}/templates/${id}/export`)
export const importCollectionTemplate = (data: Record<string, unknown>) => request.post(`${PREFIX}/templates/import`, data)
export const fetchCollectorNodes = (params?: Record<string, unknown>) =>
request.get<{ code: number; details?: PageResult<CollectorNode>; message?: string }>(`${PREFIX}/collector-nodes`, { params })
export const createCollectorNode = (data: CollectorNodeInput) => request.post(`${PREFIX}/collector-nodes`, data)
export const updateCollectorNode = (id: number, data: CollectorNodeInput) => request.put(`${PREFIX}/collector-nodes/${id}`, data)
export const deleteCollectorNode = (id: number) => request.delete(`${PREFIX}/collector-nodes/${id}`)
export const rotateCollectorNodeToken = (id: number) => request.post(`${PREFIX}/collector-nodes/${id}/installation-token`)
export const fetchHostAgentRegistrations = (params?: Record<string, unknown>) =>
request.get<{ code: number; details?: PageResult<HostAgentRegistration>; message?: string }>(`${PREFIX}/host-agents`, { params })
export const confirmHostAgentRegistration = (id: number, resourceUid: string) =>
request.post(`${PREFIX}/host-agents/${id}/confirm`, { resource_uid: resourceUid })
export const fetchCollectionBindings = (params?: Record<string, unknown>) =>
request.get<{ code: number; details?: PageResult<CollectionBinding>; message?: string }>(`${PREFIX}/bindings`, { params })
export const createCollectionBinding = (data: CollectionBindingInput) => request.post(`${PREFIX}/bindings`, data)
export const updateCollectionBinding = (id: number, data: CollectionBindingInput) => request.put(`${PREFIX}/bindings/${id}`, data)
export const deleteCollectionBinding = (id: number) => request.delete(`${PREFIX}/bindings/${id}`)
export const fetchDiscoveryRuns = (params?: Record<string, string | number | boolean | undefined>) =>
request.get(`${PREFIX}/discovery-runs`, { params })
export const collectResourceNow = (resourceUid: string) =>
request.post<{ code: number; details?: { task_ids: string[]; count: number }; message?: string }>(
`${PREFIX}/resources/${encodeURIComponent(resourceUid)}/collect-now`
)

View File

@@ -1,7 +1,7 @@
import { request } from '@/api/request'
/** 数据库类型枚举 */
export type DatabaseType = 'MySQL' | 'PostgreSQL' | 'Redis' | 'MongoDB' | 'DM' | 'KingBase'
export type DatabaseType = 'MySQL' | 'PostgreSQL' | 'Redis' | 'MongoDB' | 'DM' | 'KingBase' | 'Oracle' | 'OracleRAC'
/** 数据库服务状态 */
export type DatabaseStatus = 'online' | 'offline' | 'error'
@@ -13,19 +13,16 @@ export interface DatabaseService {
updated_at: string
deleted_at: string | null
service_identity: string
server_identity: string
name: string
category: string
type: DatabaseType
host: string
port: number
username: string
password: string // 列表接口恒为空字符串,详情接口不返回
database: string
tls_mode: 'require' | 'verify-ca' | 'verify-full'
description: string
enabled: boolean
interval: number
extra: string
tags: string
status: DatabaseStatus
status_code: number
@@ -36,10 +33,9 @@ export interface DatabaseService {
last_offline_time: string | null
continuous_errors: number
uptime: number
collect_on: boolean
collect_interval: number
collect_args: string
collect_last_result: string
product_version: string
adapter_status: 'verified' | 'unverified' | 'blocked'
last_data_time: string | null
}
/** 列表接口返回的分页数据 */
@@ -52,48 +48,32 @@ export interface DatabaseListResponse {
/** 创建数据库服务请求参数 */
export interface CreateDatabaseParams {
service_identity?: string
server_identity?: string
name: string
category: string
type: DatabaseType
host: string
port: number
username?: string
password?: string
database?: string
tls_mode?: 'require' | 'verify-ca' | 'verify-full'
description?: string
enabled?: boolean
interval?: number
extra?: string
tags?: string
collect_on?: boolean
collect_args?: string
collect_interval?: number
collect_last_result?: string
}
/** 更新数据库服务请求参数 */
export interface UpdateDatabaseParams {
service_identity?: string
server_identity?: string
name?: string
category?: string
type?: DatabaseType
host?: string
port?: number
username?: string
password?: string
database?: string
tls_mode?: 'require' | 'verify-ca' | 'verify-full'
description?: string
enabled?: boolean
interval?: number
extra?: string
tags?: string
collect_on?: boolean
collect_args?: string
collect_interval?: number
collect_last_result?: string
}
/** 列表查询参数 */
@@ -107,14 +87,13 @@ export interface DatabaseQueryParams {
/** 指标采集请求参数 */
export interface CollectMetricsParams {
ids: number[]
persist?: boolean
}
/** 指标采集结果项 */
export interface CollectMetricsResultItem {
id: number
service_identity: string
metrics?: Record<string, any>
task_ids?: string[]
error?: string
}
@@ -164,7 +143,7 @@ export const fetchDatabaseDetail = (id: number) => request.get<DatabaseService>(
* 创建数据库服务
* @param data 创建参数
*/
export const createDatabase = (data: CreateDatabaseParams) => request.post<{ message: string; id: number }>('/DC-Control/v1/database', data)
export const createDatabase = (data: CreateDatabaseParams) => request.post<{ message: string; id: number; service_identity: string }>('/DC-Control/v1/database', data)
/**
* 更新数据库服务

View File

@@ -68,6 +68,10 @@ export interface ControlResource {
display_name: string
description?: string
status: string
asset_status?: string
manufacturer_code?: string
management_ip?: string
device_level?: string
business_system_id?: number
owner_user_id?: number
department_id?: number
@@ -86,23 +90,33 @@ export interface ControlResource {
updated_at?: string
}
export interface ControlResourcePayload {
resource_category?: string
service_identity?: string
display_name?: string
description?: string
status?: string
business_system_id?: number | null
owner_user_id?: number | null
department_id?: number | null
asset_id?: number | null
datacenter_id?: number | null
room_id?: number | null
rack_id?: number | null
unit_start?: number | null
unit_end?: number | null
location_ref?: string | null
tags?: string
export interface ControlResourceRuntimeMetric {
name: string
value: number
unit: string
type: string
timestamp: string
}
export interface ControlResourceRuntime {
resource_uid: string
resource_category: string
service_identity: string
display_name: string
status: string
metrics_at?: string
metrics: ControlResourceRuntimeMetric[]
}
export interface ControlResourceOverview {
master: ControlResource
runtime: ControlResourceRuntime | null
context: {
resource_uid: string
alert_query: { resource_uid: string }
log_query: { resource_uid: string }
topology_query: { resource_uid: string }
}
}
export interface ControlResourceType {
@@ -169,6 +183,15 @@ export interface ControlCollectionStatus {
updated_at?: string
}
export interface ControlCollectionSummary {
enabled: number
ok: number
failed: number
unknown: number
overdue: number
as_of: string
}
export interface ResourceListParams {
page?: number
size?: number
@@ -192,17 +215,10 @@ export const fetchControlResourceOptions = (params?: { resource_category?: strin
params,
})
export const createControlResource = (data: ControlResourcePayload) =>
request.post<{ code?: number; details?: ControlResource; message?: string }>('/DC-Control/v1/resources', data)
export const updateControlResource = (id: number, data: ControlResourcePayload) =>
request.put<{ code?: number; details?: ControlResource; message?: string }>(`/DC-Control/v1/resources/${id}`, data)
export const deleteControlResource = (id: number) =>
request.delete<{ code?: number; details?: { message: string }; message?: string }>(`/DC-Control/v1/resources/${id}`)
export const backfillControlResources = () =>
request.post<{ code?: number; details?: { message: string }; message?: string }>('/DC-Control/v1/resources/backfill')
export const fetchControlResourceOverview = (resourceUid: string) =>
request.get<{ code?: number; details?: ControlResourceOverview; message?: string }>(
`/DC-Control/v1/resources/${encodeURIComponent(resourceUid)}/overview`
)
export const fetchControlResourceTypes = (params?: { page?: number; size?: number; keyword?: string }) =>
request.get<{ code?: number; details?: PageResult<ControlResourceType>; message?: string }>('/DC-Control/v1/resource-types', { params })
@@ -245,3 +261,6 @@ export const fetchCollectionStatus = (params?: {
request.get<{ code?: number; details?: PageResult<ControlCollectionStatus>; message?: string }>('/DC-Control/v1/collection/status', {
params,
})
export const fetchCollectionStatusSummary = () =>
request.get<{ code?: number; details?: ControlCollectionSummary; message?: string }>('/DC-Control/v1/collection/status/summary')

View File

@@ -0,0 +1,74 @@
import { request } from '@/api/request'
export interface ImportantInterfaceConfig {
id: number
resource_uid: string
interface_identity: string
purpose: string
expected_peer_resource_uid?: string
expected_peer_interface_identity?: string
enabled: boolean
last_condition: 'unknown' | 'normal' | 'interface_down' | 'neighbor_missing'
last_evaluated_at?: string
last_transition_at?: string
}
export interface UnifiedDeviceInterface {
id: number
resource_uid: string
interface_identity: string
name: string
mac?: string
admin_state: string
oper_state: string
speed_bps: number
in_bytes: number
out_bytes: number
in_errors: number
out_errors: number
last_seen_at: string
important?: ImportantInterfaceConfig
}
export interface DeviceConfigVersion {
id: number
resource_uid: string
task_id: string
template_code: string
template_version: number
collected_at: string
content_hash: string
filename: string
size: number
previous_version_id?: number
}
const resourcePath = (resourceUid: string) => `/DC-Control/v1/monitoring/resources/${encodeURIComponent(resourceUid)}`
export const fetchUnifiedDeviceInterfaces = (resourceUid: string) =>
request.get(`${resourcePath(resourceUid)}/interfaces`)
export const saveImportantInterface = (
resourceUid: string,
interfaceIdentity: string,
data: {
purpose: string
expected_peer_resource_uid?: string
expected_peer_interface_identity?: string
}
) => request.put(`${resourcePath(resourceUid)}/interfaces/${encodeURIComponent(interfaceIdentity)}/importance`, data)
export const removeImportantInterface = (resourceUid: string, interfaceIdentity: string) =>
request.delete(`${resourcePath(resourceUid)}/interfaces/${encodeURIComponent(interfaceIdentity)}/importance`)
export const triggerDeviceConfigBackup = (resourceUid: string) =>
request.post(`${resourcePath(resourceUid)}/config-backups`)
export const fetchDeviceConfigBackups = (resourceUid: string, params?: { page?: number; size?: number }) =>
request.get(`${resourcePath(resourceUid)}/config-backups`, { params })
export const fetchDeviceConfigDiff = (resourceUid: string, baseId: number, targetId: number) =>
request.get(`${resourcePath(resourceUid)}/config-backups/diff`, { params: { base_id: baseId, target_id: targetId } })
export const downloadDeviceConfig = (resourceUid: string, versionId: number) =>
request.get<Blob>(`${resourcePath(resourceUid)}/config-backups/${versionId}/download`, { responseType: 'blob' })

View File

@@ -13,10 +13,12 @@ export interface Floor {
enabled?: boolean
layout_plan?: string
layout_plan_file_id?: string
layout_plan_name?: string
layout_plan_content_type?: string
description?: string
}
export type SaveFloorPayload = Omit<Floor, 'layout_plan'>
export type SaveFloorPayload = Omit<Floor, 'layout_plan' | 'layout_plan_name' | 'layout_plan_content_type'>
interface ApiResponse<T> {
code: number

View File

@@ -2,7 +2,6 @@ import { request } from '@/api/request'
export interface PendingUpload {
file_id: string
object_key: string
upload: {
method: string
url: string
@@ -17,7 +16,7 @@ interface ApiResponse<T> {
details: T
}
/** 初始化楼层布局文件并直传 OSS。 */
/** 初始化楼层布局文件并上传到当前全局存储。 */
export async function uploadFloorLayout(file: File): Promise<PendingUpload> {
const response = await request.post<ApiResponse<PendingUpload>>('/Assets/v1/floor/layout/init', {
filename: file.name,

View File

@@ -41,11 +41,21 @@ export interface CapacityRisk {
metric_code: string
unit: string
current_value: number
threshold: number
status: '资源不足' | '配置合理' | '资源闲置' | '容量风险' | '数据不足'
idle_threshold: number
risk_threshold: number
shortage_threshold: number
slope_per_hour: number
risk_level: string
predicted_at?: string
predicted_value?: number
confidence_low?: number
confidence_high?: number
sample_count: number
data_start?: string
data_end?: string
data_span_hours: number
forecast_hours: number
}
export interface SloDashboardBucket {
@@ -75,7 +85,7 @@ export const fetchAlertNoise = (params?: { hours?: number }) =>
export const fetchRuleSuggestions = (params?: { hours?: number }) =>
request.get<RuleSuggestion[]>('/Alert/v1/governance/suggestions', { params })
export const fetchCapacityRisk = (params?: { resource_uid?: string; metric_code?: string }) =>
export const fetchCapacityRisk = (params?: { resource_uid?: string; metric_type?: string; metric_code?: string }) =>
request.get<CapacityRisk>('/DC-Control/v1/risk/capacity', { params })
export const fetchSloDashboard = () => request.get<SloDashboard>('/Feedback/v1/tickets/slo/dashboard')

View File

@@ -8,12 +8,16 @@ export interface IpScanTask {
description?: string
target_range: string
port_range?: string
config?: string
timeout?: number
concurrency?: number
collector_node_id: number
candidate_credential_ids: string
allowed_protocols: string
default_location: string
default_resource_category: string
auto_onboard: boolean
cron_expr?: string
status?: string
server_id: number
last_scan_time?: string
next_scan_time?: string
last_scan_status?: string
@@ -42,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}`)
/** 触发一次扫描(会创建 scan_run 并调用 Agent);成功体见文档 { message: "scan triggered" } */
/** 触发一次扫描,运行记录进入指定采集节点的等待队列。 */
export const triggerIpScan = (id: number) =>
request.post<{ code: number; details?: { message?: string }; message?: string }>(`/DC-Control/v1/ipscans/${id}/trigger`)

View File

@@ -21,8 +21,12 @@ export interface LogEvent {
normalized_detail: string
device_name: string
resource_type: string
resource_uid: string
resource_id: string
resource_name: string
business_system_id?: number
trace_id?: string
span_id?: string
match_method: string
severity_code: string
trap_oid: string
@@ -38,6 +42,61 @@ export interface LogEntriesParams {
resource_id?: string
dispatch_status?: string
log_event_id?: number
trace_id?: string
resource_uid?: string
business_system_id?: number
}
export interface TraceSummary {
trace_id: string
start_time: string
end_time: string
duration_ms: number
span_count: number
error_count: number
services: string
business_system_id?: number
resource_uid?: string
}
export interface TraceSpan {
id: number
trace_id: string
span_id: string
parent_span_id?: string
service_name: string
operation_name: string
span_kind: string
start_time: string
end_time: string
duration_ms: number
status_code: string
status_message?: string
business_system_id?: number
resource_uid?: string
http_method?: string
http_route?: string
http_status_code?: number
}
export interface TraceListParams {
page?: number
page_size?: number
trace_id?: string
service_name?: string
resource_uid?: string
business_system_id?: number
status?: 'ok' | 'error' | 'unset'
start_time?: string
end_time?: string
}
export interface ServiceDependency {
source_service: string
target_service: string
call_count: number
error_count: number
average_ms: number
}
export interface LogEntriesResult {
@@ -138,6 +197,7 @@ export interface AuditLog {
actor_id: string
actor_name: string
action: string
log_category: 'operation' | 'data'
object_type: string
object_id: string
operation_risk: string
@@ -157,6 +217,7 @@ export interface AuditLogParams {
source_service?: string
actor_id?: string
action?: string
log_category?: 'operation' | 'data'
object_type?: string
object_id?: string
operation_risk?: string
@@ -197,6 +258,18 @@ export function fetchLogEntries(params?: LogEntriesParams) {
return request.get(`${BASE}/entries`, { params })
}
export function fetchTraces(params?: TraceListParams) {
return request.get(`${BASE}/traces`, { params })
}
export function fetchTraceDetail(traceId: string) {
return request.get(`${BASE}/traces/${encodeURIComponent(traceId)}`)
}
export function fetchServiceDependencies(params?: TraceListParams) {
return request.get(`${BASE}/service-dependencies`, { params })
}
export function fetchAlertOutbox(params?: AlertOutboxParams) {
return request.get(`${BASE}/alert-outbox`, { params })
}

View File

@@ -14,9 +14,11 @@ export interface MiddlewareItem {
description: string
enabled: boolean
interval: number
extra: string
tags: string
status_url: string
adapter_mode: 'http_status' | 'json' | 'prometheus' | 'jolokia'
product_version: string
adapter_status: 'verified' | 'unverified' | 'blocked'
last_data_time: string | null
status: string
status_code: number
status_message: string
@@ -26,11 +28,6 @@ export interface MiddlewareItem {
last_offline_time: string | null
continuous_errors: number
uptime: number
agent_config: string
collect_on: boolean
collect_args: string
collect_interval: number
collect_last_result: string
}
/** 中间件列表响应 */
@@ -51,7 +48,6 @@ export interface MiddlewareListParams {
/** 创建中间件请求参数 */
export interface MiddlewareCreateData {
service_identity?: string
server_identity?: string
name: string
category: string
@@ -59,19 +55,13 @@ export interface MiddlewareCreateData {
description?: string
enabled?: boolean
interval?: number
extra?: string
tags?: string
status_url?: string
agent_config?: string
collect_on?: boolean
collect_args?: string
collect_interval?: number
adapter_mode?: 'http_status' | 'json' | 'prometheus' | 'jolokia'
policy_ids?: number[]
}
/** 更新中间件请求参数 */
export interface MiddlewareUpdateData {
service_identity?: string
server_identity?: string
name?: string
category?: string
@@ -79,52 +69,11 @@ export interface MiddlewareUpdateData {
description?: string
enabled?: boolean
interval?: number
extra?: string
tags?: string
status_url?: string
agent_config?: string
collect_on?: boolean
collect_args?: string
collect_interval?: number
collect_last_result?: string
status?: string
status_code?: number
status_message?: string
response_time?: number
last_check_time?: string
last_online_time?: string | null
last_offline_time?: string | null
continuous_errors?: number
uptime?: number
adapter_mode?: 'http_status' | 'json' | 'prometheus' | 'jolokia'
policy_ids?: number[]
}
/** 采集配置更新参数 */
export interface MiddlewareCollectData {
collect_on?: boolean
collect_args?: string
collect_interval?: number
collect_last_result?: string
}
/** 指标上报项 */
export interface MetricItem {
service_identity: string
timestamp: string
[key: string]: any
}
/** 指标上报请求参数 */
export interface MetricsUploadData {
metrics: MetricItem[]
}
/** 指标上报响应 */
export interface MetricsUploadResponse {
message: string
count: number
}
/** 指标项 */
export interface MiddlewareMetric {
metric_name: string
@@ -177,7 +126,7 @@ export const fetchMiddlewareDetail = (id: number) => {
/** 创建中间件服务 */
export const createMiddleware = (data: MiddlewareCreateData) => {
return request.post<{ message: string; id: number }>('/DC-Control/v1/middleware', data)
return request.post<{ message: string; id: number; service_identity: string }>('/DC-Control/v1/middleware', data)
}
/** 更新中间件服务 */
@@ -185,21 +134,11 @@ export const updateMiddleware = (id: number, data: MiddlewareUpdateData) => {
return request.put<{ message: string }>(`/DC-Control/v1/middleware/${id}`, data)
}
/** 部分更新采集配置 */
export const patchMiddlewareCollect = (id: number, data: MiddlewareCollectData) => {
return request.patch<{ message: string }>(`/DC-Control/v1/middleware/${id}/collect`, data)
}
/** 删除中间件服务 */
export const deleteMiddleware = (id: number) => {
return request.delete<{ message: string }>(`/DC-Control/v1/middleware/${id}`)
}
/** 上报中间件服务指标(匿名接口) */
export const uploadMiddlewareMetrics = (data: MetricsUploadData) => {
return request.post<MetricsUploadResponse>('/DC-Control/v1/middleware/metrics/upload', data)
}
/** 查询中间件服务指标元数据 */
export const fetchMiddlewareMetricsMeta = (params: MetricsMetaParams) => {
return request.get<MetricsMetaResponse>('/DC-Control/v1/services/metrics/meta', { params })
@@ -217,13 +156,13 @@ export const MIDDLEWARE_TYPE_MAP: Record<string, string> = {
nginx: 'Nginx',
apache: 'Apache',
tomcat: 'Tomcat',
redis: 'Redis',
kafka: 'Kafka',
activemq: 'ActiveMQ',
rocketmq: 'RocketMQ',
websphere: 'WebSphere',
generic: '通用中间件',
rabbitmq: 'RabbitMQ',
elasticsearch: 'Elasticsearch',
mysql: 'MySQL',
postgresql: 'PostgreSQL',
mongodb: 'MongoDB',
other: '其他',
}

View File

@@ -19,6 +19,7 @@ export interface Topology {
node_count?: number
link_count?: number
enable?: boolean
auto_discovery?: boolean
created_at?: string
updated_at?: string
}
@@ -41,6 +42,12 @@ export interface Link {
description?: string
created_at?: string
updated_at?: string
discovery_source?: string
confirmed?: boolean
source_resource_uid?: string
source_interface_identity?: string
target_resource_uid?: string
target_interface_identity?: string
}
/** 拓扑分组 */
@@ -133,6 +140,9 @@ export const fetchTopologies = (data: { page: number; size: number; keyword?: st
/** 获取拓扑详情 */
export const fetchTopologyDetail = (id: number) => request.get(`/DC-Control/v1/topologies/${id}`)
/** 获取统一资源对应的系统自动拓扑 */
export const fetchAutomaticTopology = () => request.get('/DC-Control/v1/topologies/automatic')
/** 创建拓扑 */
export const createTopology = (data: Partial<Topology>) => request.post('/DC-Control/v1/topologies', data)
@@ -160,6 +170,13 @@ export const fetchImpactAnalysis = (params: { resource_uid: string; topology_id?
export const createNode = (topologyId: number, data: Partial<TopologyNode>) =>
request.post(`/DC-Control/v1/topologies/${topologyId}/nodes`, data)
/** 将已有统一设备引用加入手工拓扑 */
export const addResourceNodes = (topologyId: number, resource_uids: string[]) =>
request.post<{ code: number; details?: { message: string; added: number } }>(
`/DC-Control/v1/topologies/${topologyId}/resource-nodes`,
{ resource_uids }
)
/** 更新节点 */
export const updateNode = (topologyId: number, nodeId: string, data: Partial<TopologyNode>) =>
request.put(`/DC-Control/v1/topologies/${topologyId}/nodes/${nodeId}`, data)
@@ -171,13 +188,6 @@ export const deleteNode = (topologyId: number, nodeId: string) => request.delete
export const updateNodesPositions = (topologyId: number, positions: Array<{ id: string; position: { x: number; y: number } }>) =>
request.put(`/DC-Control/v1/topologies/${topologyId}/nodes/positions`, { positions })
/** 按资产 ID 批量导入节点(后端生成 node_id=asset-{id} 与 ref_type=asset) */
export const batchImportAssetNodes = (topologyId: number, asset_ids: number[]) =>
request.post<{ code: number; details?: { message: string; imported: number } }>(
`/DC-Control/v1/topologies/${topologyId}/nodes/batch-import`,
{ asset_ids }
)
// ==================== 链路管理接口 ====================
/** 获取链路列表 */

View File

@@ -1,32 +1,24 @@
import { request } from '@/api/request'
export type NetworkDeviceProtocol = 'snmp' | 'ssh' | 'telnet'
export type NetworkDeviceSnmpVersion = 'v1' | 'v2c' | 'v3'
export type NetworkDeviceStatus = 'online' | 'offline' | 'error' | 'unknown'
export interface NetworkDeviceService {
id: number
resource_uid: string
asset_id: number
created_at: string
updated_at: string
deleted_at: string | null
service_identity: string
server_identity: string
name: string
category: string
type: string
host: string
port: number
protocol: NetworkDeviceProtocol
community: string
snmp_version: NetworkDeviceSnmpVersion
username: string
vendor: string
model: string
location: string
description: string
enabled: boolean
interval: number
extra: string
tags: string
status: NetworkDeviceStatus
status_code: number
@@ -37,6 +29,40 @@ export interface NetworkDeviceService {
last_offline_time: string | null
continuous_errors: number
uptime: number
product_version: string
adapter_status: 'verified' | 'unverified'
last_data_time: string | null
}
export interface DeviceInterfaceSnapshot {
timestamp: string
service_identity: string
device_host: string
if_index: number
if_name: string
mac_address: string
admin_status: string
oper_status: string
in_octets: number
out_octets: number
in_errors: number
out_errors: number
speed_bps: number
}
export interface WirelessAccessPoint {
id: number
controller_resource_uid: string
ap_identity: string
name: string
mac_address: string
ip_address: string
serial_number: string
model: string
status: string
radio_count: number
client_count: number
last_seen_at: string
}
export interface NetworkDeviceListResponse {
@@ -54,25 +80,18 @@ export interface NetworkDeviceQueryParams {
}
export interface CreateNetworkDeviceParams {
resource_uid: string
asset_id: number
service_identity?: string
server_identity?: string
name: string
category: string
type?: string
host: string
port?: number
protocol?: NetworkDeviceProtocol
community?: string
snmp_version?: NetworkDeviceSnmpVersion
username?: string
password?: string
vendor?: string
model?: string
location?: string
description?: string
enabled?: boolean
interval?: number
extra?: string
tags?: string
}
@@ -89,4 +108,8 @@ export const createNetworkDevice = (data: CreateNetworkDeviceParams) =>
export const updateNetworkDevice = (id: number, data: UpdateNetworkDeviceParams) =>
request.put<{ message: string }>(`/DC-Control/v1/network-device-services/${id}`, data)
export const deleteNetworkDevice = (id: number) => request.delete<{ message: string }>(`/DC-Control/v1/network-device-services/${id}`)
export const fetchNetworkDeviceInterfaces = (id: number) =>
request.get<DeviceInterfaceSnapshot[]>(`/DC-Control/v1/network-device-services/${id}/interfaces`)
export const fetchNetworkDeviceAccessPoints = (id: number) =>
request.get<WirelessAccessPoint[]>(`/DC-Control/v1/network-device-services/${id}/access-points`)

View File

@@ -15,7 +15,8 @@ export const createNoticeChannel = (data: {
name: string
type: string
config: string
message_template?: string
message_template_id: number
in_app_sound_enabled?: boolean
rate_limit?: number
rate_limit_window?: number
severity_filter?: string
@@ -51,7 +52,8 @@ export const updateNoticeChannel = (data: {
name?: string
type?: string
config?: string
message_template?: string
message_template_id?: number
in_app_sound_enabled?: boolean
rate_limit?: number
rate_limit_window?: number
severity_filter?: string

View File

@@ -5,14 +5,6 @@ export interface PCListParams {
page?: number
size?: number
keyword?: string
collect_on?: boolean
}
/** 资源使用率信息 */
export interface ResourceInfo {
value: number // 使用率百分比
total?: string // 总量描述
used?: string // 已用描述
}
/** PC 数据结构 */
@@ -22,6 +14,8 @@ export interface PCItem {
updated_at: string
deleted_at: string | null
pc_identity: string
resource_uid: string
asset_id: number
name: string
host: string
ip_address: string
@@ -32,19 +26,8 @@ export interface PCItem {
server_type: string
tags: string
location: string
remote_access: string
remote_port: number
agent_config: string
status: string
last_check_time: string
collect_on: boolean
collect_args: string
collect_interval: number
collect_last_result: string
// 资源使用率(前端展示用,可能来自采集数据)
cpu_info?: ResourceInfo
memory_info?: ResourceInfo
disk_info?: ResourceInfo
}
/** PC 列表返回数据 */
@@ -57,6 +40,8 @@ export interface PCListResult {
/** PC 创建参数 */
export interface PCCreateParams {
resource_uid: string
asset_id: number
pc_identity?: string
name: string
host: string
@@ -68,21 +53,11 @@ export interface PCCreateParams {
server_type?: string
tags?: string
location?: string
remote_access?: string
remote_port?: number
agent_config?: string
status?: string
last_check_time?: string
collect_on?: boolean
collect_args?: string
collect_interval?: number
collect_last_result?: string
}
/** PC 更新参数 */
export interface PCUpdateParams {
id: number
pc_identity?: string
name?: string
host?: string
ip_address?: string
@@ -93,15 +68,6 @@ export interface PCUpdateParams {
server_type?: string
tags?: string
location?: string
remote_access?: string
remote_port?: number
agent_config?: string
status?: string
last_check_time?: string
collect_on?: boolean
collect_args?: string
collect_interval?: number
collect_last_result?: string
}
/** 获取PC列表(分页) */
@@ -123,8 +89,3 @@ export const createPC = (data: PCCreateParams) => {
export const updatePC = (id: number, data: Omit<PCUpdateParams, 'id'>) => {
return request.put<{ message: string }>(`/DC-Control/v1/pcs/${id}`, data)
}
/** 删除PC */
export const deletePC = (id: number) => {
return request.delete<{ message: string }>(`/DC-Control/v1/pcs/${id}`)
}

View File

@@ -0,0 +1,193 @@
import { isAxiosError } from 'axios'
import { request } from '@/api/request'
export interface RuntimeCheck {
name: string
required: boolean
ready: boolean
message?: string
}
export interface RuntimeWorker {
name: string
running: boolean
queue_depth?: number
last_error?: string
last_error_at?: string
last_succeeded_at?: string
}
export interface RuntimeScheduler {
running: boolean
last_error?: string
}
export interface RuntimeDisk {
path: string
total_bytes: number
used_bytes: number
free_bytes: number
used_percent: number
minimum_free_bytes?: number
level: 'normal' | 'warning' | 'critical'
}
export interface RuntimeStorage {
provider: 'local' | 'aliyun' | string
container: string
writable: boolean
}
export interface NotificationQueue {
pending: number
retry_scheduled: number
uncertain: number
failed: number
backlog: number
oldest_pending?: string
}
export interface PlatformServiceStatus {
key: string
name: string
reachable: boolean
ready: boolean
version: string
checked_at?: string
checks: RuntimeCheck[]
workers: RuntimeWorker[]
scheduler?: RuntimeScheduler
disk?: RuntimeDisk
storage?: RuntimeStorage
notification_queue?: NotificationQueue
error?: string
}
interface ServiceSpec {
key: string
name: string
path: string
}
const services: ServiceSpec[] = [
{ key: 'rbac2', name: '权限中心', path: '/rbac2/v1/runtime/status' },
{ key: 'assets', name: '资产管理', path: '/Assets/v1/runtime/status' },
{ key: 'dc-control', name: '监控控制中心', path: '/DC-Control/v1/runtime/status' },
{ key: 'dc-network', name: '网络采集', path: '/dc-network/v1/runtime/status' },
{ key: 'dc-hardware', name: '硬件采集', path: '/DC-Hardware/v1/runtime/status' },
{ key: 'alert', name: '告警中心', path: '/Alert/v1/runtime/status' },
{ key: 'logs', name: '日志中心', path: '/Logs/v1/runtime/status' },
{ key: 'feedback', name: '工单反馈', path: '/Feedback/v1/runtime/status' },
{ key: 'kb', name: '知识库', path: '/Kb/v1/runtime/status' },
{ key: 'mgt', name: '大屏管理', path: '/Mgt/v1/runtime/status' },
{ key: 'visual', name: '可视化服务', path: '/Visual/v1/runtime/status' },
{ key: 'files', name: '文件服务', path: '/Files/v1/runtime/status' },
]
const asRecord = (value: unknown): Record<string, any> => (value && typeof value === 'object' ? (value as Record<string, any>) : {})
const optionalString = (value: unknown): string | undefined => (typeof value === 'string' && value.length > 0 ? value : undefined)
const normalizeWorker = (value: unknown, fallbackName = ''): RuntimeWorker => {
const record = asRecord(value)
return {
name: optionalString(record.name) || fallbackName,
running: record.running === true,
queue_depth: typeof record.queue_depth === 'number' ? record.queue_depth : undefined,
last_error: optionalString(record.last_error),
last_error_at: optionalString(record.last_error_at),
last_succeeded_at: optionalString(record.last_succeeded_at) || optionalString(record.last_success),
}
}
const normalizeWorkers = (value: unknown): RuntimeWorker[] => {
if (Array.isArray(value)) return value.map((item) => normalizeWorker(item))
const record = asRecord(value)
return Object.entries(record).map(([name, item]) => normalizeWorker(item, name))
}
const normalizeDisk = (value: unknown): RuntimeDisk | undefined => {
const record = asRecord(value)
const level = record.level
if (!['normal', 'warning', 'critical'].includes(level)) return undefined
if (typeof record.path !== 'string') return undefined
const values = [record.total_bytes, record.used_bytes, record.free_bytes, record.used_percent]
if (!values.every((item) => typeof item === 'number' && Number.isFinite(item))) return undefined
return record as RuntimeDisk
}
const normalizeStorage = (value: unknown): RuntimeStorage | undefined => {
const record = asRecord(value)
if (typeof record.provider !== 'string' || typeof record.container !== 'string' || typeof record.writable !== 'boolean') {
return undefined
}
return record as RuntimeStorage
}
const normalizeNotificationQueue = (value: unknown): NotificationQueue | undefined => {
const record = asRecord(value)
const fields = ['pending', 'retry_scheduled', 'uncertain', 'failed', 'backlog'] as const
if (!fields.every((field) => typeof record[field] === 'number' && Number.isFinite(record[field]))) return undefined
return {
pending: record.pending,
retry_scheduled: record.retry_scheduled,
uncertain: record.uncertain,
failed: record.failed,
backlog: record.backlog,
oldest_pending: optionalString(record.oldest_pending),
}
}
const isRuntimePayload = (payload: unknown): boolean => {
const envelope = asRecord(payload)
const readiness = asRecord(envelope.readiness || envelope)
return typeof readiness.ready === 'boolean'
}
const normalizePayload = (spec: ServiceSpec, payload: unknown): PlatformServiceStatus => {
const envelope = asRecord(payload)
const readiness = asRecord(envelope.readiness || envelope)
const workers = envelope.workers && envelope.readiness ? envelope.workers : readiness.workers
return {
key: spec.key,
name: spec.name,
reachable: true,
ready: readiness.ready === true,
version: typeof readiness.version === 'string' ? readiness.version : 'unknown',
checked_at: typeof readiness.checked_at === 'string' ? readiness.checked_at : undefined,
checks: Array.isArray(readiness.checks) ? (readiness.checks as RuntimeCheck[]) : [],
workers: normalizeWorkers(workers),
scheduler: readiness.scheduler ? (readiness.scheduler as RuntimeScheduler) : undefined,
disk: normalizeDisk(envelope.disk || readiness.disk),
storage: normalizeStorage(envelope.storage || readiness.storage),
notification_queue: normalizeNotificationQueue(envelope.notification_queue),
}
}
const fetchServiceStatus = async (spec: ServiceSpec): Promise<PlatformServiceStatus> => {
try {
const payload = await request.get(spec.path)
return normalizePayload(spec, payload)
} catch (error) {
if (isAxiosError(error) && error.response?.data && isRuntimePayload(error.response.data)) {
return normalizePayload(spec, error.response.data)
}
return {
key: spec.key,
name: spec.name,
reachable: false,
ready: false,
version: 'unknown',
checks: [],
workers: [],
error:
isAxiosError(error) && error.response?.status
? `网关返回 ${error.response.status}`
: error instanceof Error
? error.message
: '服务无法连接',
}
}
}
export const fetchPlatformRuntime = (): Promise<PlatformServiceStatus[]> => Promise.all(services.map(fetchServiceStatus))

View File

@@ -9,7 +9,12 @@ export interface UserItem {
username?: string
email?: string
phone?: string
status?: string
status?: number
department_id?: number
position_id?: number
department?: { id: number; name: string }
position?: { id: number; name: string }
roles?: { id: number; name: string }[]
created_at?: string
updated_at?: string
}
@@ -30,3 +35,52 @@ export interface UserListResponse {
export const fetchUserList = async (data: any) => {
return request.post<UserListResponse>('/rbac2/v1/user/list', data, { needWorkspace: true })
}
export interface RoleItem {
id: number
name: string
description?: string
data_scope: 'all' | 'department'
status?: number
users?: UserItem[]
}
export const fetchRoleList = (data: { page?: number; size?: number; keyword?: string; status?: number }) =>
request.post('/rbac2/v1/role/fetch', data, { needWorkspace: true })
export const fetchRoleUsers = (roleId: number) => request.post('/rbac2/v1/role/user', { id: roleId }, { needWorkspace: true })
export interface DepartmentItem {
id: number
name: string
parent_id?: number
leader_id?: number
status?: number
}
export interface PositionItem {
id: number
code: string
name: string
description?: string
status?: number
}
export const fetchDepartmentList = (data: { page?: number; size?: number; keyword?: string }) =>
request.post('/rbac2/v1/dpt/fetch', data, { needWorkspace: true })
export const createDepartment = (data: Partial<DepartmentItem>) => request.post('/rbac2/v1/dpt/create', data, { needWorkspace: true })
export const updateDepartment = (data: Partial<DepartmentItem>) => request.post('/rbac2/v1/dpt/modify', data, { needWorkspace: true })
export const deleteDepartment = (id: number) => request.post('/rbac2/v1/dpt/del', { id }, { needWorkspace: true })
export const fetchPositionList = (data: { page?: number; size?: number; keyword?: string }) =>
request.post('/rbac2/v1/position/fetch', data, { needWorkspace: true })
export const createPosition = (data: Partial<PositionItem>) => request.post('/rbac2/v1/position/create', data, { needWorkspace: true })
export const updatePosition = (data: Partial<PositionItem>) => request.post('/rbac2/v1/position/modify', data, { needWorkspace: true })
export const deletePosition = (id: number) => request.post('/rbac2/v1/position/del', { id }, { needWorkspace: true })
export const createRole = (data: Partial<RoleItem>) => request.post('/rbac2/v1/role/create', data, { needWorkspace: true })
export const updateRole = (data: Partial<RoleItem>) => request.post('/rbac2/v1/role/modify', data, { needWorkspace: true })
export const deleteRole = (id: number) => request.post('/rbac2/v1/role/del', { id }, { needWorkspace: true })
export const fetchRolePermissions = (id: number) => request.post('/rbac2/v1/role/pmn', { id }, { needWorkspace: true })
export const updateRolePermissions = (id: number, list: number[]) =>
request.post('/rbac2/v1/role/modify_pmn', { id, list }, { needWorkspace: true })

View File

@@ -19,6 +19,7 @@ export enum ReportType {
SERVER = 'server',
NETWORK_DEVICE = 'network_device',
OPERATIONS = 'operations',
DESIGNER = 'designer',
EVIDENCE = 'evidence',
}
@@ -48,6 +49,92 @@ export interface ReportRecord {
finished_at?: string
created_at: string
updated_at: string
definition_id?: number
definition_version?: number
period_type?: 'daily' | 'monthly'
}
export interface ReportDatasetField {
code: string
name: string
type: 'string' | 'number' | 'datetime' | 'boolean'
operators: string[]
aggregations: string[]
}
export interface ReportDataset {
code: string
name: string
category: string
description: string
fields: ReportDatasetField[]
temporal: boolean
enabled: boolean
version: number
}
export interface ReportSelectedField {
field: string
aggregation: string
}
export interface ReportFilter {
field: string
operator: string
value: string | number | boolean | Array<string | number | boolean>
}
export interface ReportLayoutBlock {
type: 'table' | 'bar' | 'line' | 'stat'
title: string
x_field?: string
y_fields?: string[]
}
export interface ReportDefinitionInput {
code: string
name: string
description: string
dataset_code: string
fields: ReportSelectedField[]
filters: ReportFilter[]
layout: { blocks: ReportLayoutBlock[] }
row_limit: number
enabled: boolean
}
export interface ReportDefinition extends ReportDefinitionInput {
id: number
version: number
created_at: string
updated_at: string
}
export interface ReportSchedule {
id: number
definition_id: number
period_type: 'daily' | 'monthly'
timezone: string
hour: number
minute: number
enabled: boolean
next_run_at?: string
last_run_at?: string
definition?: ReportDefinition
}
export interface CapacityThreshold {
id: number
resource_category: string
metric_type: string
metric_code: string
display_name: string
idle_threshold: number
risk_threshold: number
shortage_threshold: number
min_samples: number
forecast_hours: number
enabled: boolean
}
export interface ReportListParams {
@@ -242,6 +329,41 @@ export const fetchReportMetricsAvailable = (params: {
export const fetchReportMetricsRegistry = (params: { data_source: string }) =>
request.get<ApiResponse<{ data_source: string; metrics: any[] }>>('/DC-Control/v1/reports/metrics/registry', { params })
export const fetchReportDatasets = () => request.get<ApiResponse<ReportDataset[]>>('/DC-Control/v1/reports/datasets')
export const fetchReportDefinitions = () => request.get<ApiResponse<ReportDefinition[]>>('/DC-Control/v1/reports/definitions')
export const createReportDefinition = (data: ReportDefinitionInput) =>
request.post<ApiResponse<ReportDefinition>>('/DC-Control/v1/reports/definitions', data)
export const updateReportDefinition = (id: number, data: ReportDefinitionInput) =>
request.put<ApiResponse<ReportDefinition>>(`/DC-Control/v1/reports/definitions/${id}`, data)
export const deleteReportDefinition = (id: number) => request.delete(`/DC-Control/v1/reports/definitions/${id}`)
export const generateReportDefinition = (
id: number,
data: { period_type: 'daily' | 'monthly'; start_time: string; end_time: string }
) => request.post<ApiResponse<ReportRecord>>(`/DC-Control/v1/reports/definitions/${id}/generate`, data)
export const fetchReportSchedules = () => request.get<ApiResponse<ReportSchedule[]>>('/DC-Control/v1/reports/schedules')
export const saveReportSchedule = (data: Omit<ReportSchedule, 'id' | 'next_run_at' | 'last_run_at' | 'definition'>) =>
request.post<ApiResponse<ReportSchedule>>('/DC-Control/v1/reports/schedules', data)
export const deleteReportSchedule = (id: number) => request.delete(`/DC-Control/v1/reports/schedules/${id}`)
export const fetchCapacityThresholds = () =>
request.get<ApiResponse<CapacityThreshold[]>>('/DC-Control/v1/reports/capacity-thresholds')
export const createCapacityThreshold = (data: Omit<CapacityThreshold, 'id'>) =>
request.post<ApiResponse<CapacityThreshold>>('/DC-Control/v1/reports/capacity-thresholds', data)
export const updateCapacityThreshold = (id: number, data: Omit<CapacityThreshold, 'id'>) =>
request.put<ApiResponse<CapacityThreshold>>(`/DC-Control/v1/reports/capacity-thresholds/${id}`, data)
export const deleteCapacityThreshold = (id: number) => request.delete(`/DC-Control/v1/reports/capacity-thresholds/${id}`)
/** 查看报表内容 */
export const fetchReportContent = (id: number) => request.get<ApiResponse<Record<string, any>>>(`/DC-Control/v1/reports/${id}/content`)

View File

@@ -7,33 +7,16 @@ export interface RoomDeviceItem {
updated_at: string
deleted_at: string | null
service_identity: string
resource_uid: string
asset_id: number
name: string
description: string
room_id: number
device_code?: string
device_category: string
type?: string
status_url?: string
agent_config: string
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
management_address?: string
enabled: boolean
collect_on: boolean
collect_interval: number
collect_last_result: string
status?: string
status_code?: number
status_message?: string
@@ -66,82 +49,22 @@ export interface RoomDeviceListParams {
/** 机房设备创建数据 */
export interface RoomDeviceCreateData {
resource_uid: string
asset_id: number
service_identity?: string
name: string
description?: string
room_id: number
device_code?: string
device_category: string
agent_config?: string
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
type?: string
management_address?: string
enabled?: boolean
collect_on?: boolean
collect_interval?: number
policy_ids?: number[]
}
/** 机房设备更新数据 */
export interface RoomDeviceUpdateData {
name?: string
description?: string
room_id?: number
device_category?: string
agent_config?: string
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
enabled?: boolean
collect_on?: boolean
collect_interval?: number
policy_ids?: number[]
}
/** 机房设备采集配置数据 */
export interface RoomDeviceCollectData {
collect_method?: 'api' | 'snmp'
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
collect_on?: boolean
collect_interval?: number
}
export type RoomDeviceUpdateData = Partial<RoomDeviceCreateData>
/** 指标数据项 */
export interface MetricItem {
@@ -195,16 +118,6 @@ export const updateRoomDevice = (id: number, data: RoomDeviceUpdateData) => {
return request.put<{ message: string }>(`/DC-Control/v1/room-devices/${id}`, data)
}
/** 删除机房设备 */
export const deleteRoomDevice = (id: number) => {
return request.delete<{ message: string }>(`/DC-Control/v1/room-devices/${id}`)
}
/** 更新采集配置 */
export const patchRoomDeviceCollect = (id: number, data: RoomDeviceCollectData) => {
return request.patch<{ message: string }>(`/DC-Control/v1/room-devices/${id}/collect`, data)
}
/** 查询最新指标 */
export const fetchLatestMetrics = (serviceIdentity: string) => {
return request.get<RoomDeviceMetricsLatestResponse>('/DC-Control/v1/room-devices/metrics/latest', {

View File

@@ -1,43 +1,25 @@
import { request } from '@/api/request'
import type { DeviceInterfaceSnapshot, WirelessAccessPoint } from './network-device'
/** 安全设备服务项 */
export interface SecurityServiceItem {
id: number
resource_uid: string
asset_id: number
created_at: string
updated_at: string
deleted_at: string | null
service_identity: string
oid: string
server_identity: string
name: string
category: string
type: string
host: string
vendor: string
model: string
location: string
description: string
enabled: boolean
interval: number
extra: string
tags: string
status_url: string
agent_config: string
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
collect_on: boolean
collect_args: string
collect_interval: number
collect_last_result: string
status: string
status_code: number
status_message: string
@@ -47,6 +29,9 @@ export interface SecurityServiceItem {
last_offline_time: string | null
continuous_errors: number
uptime: number
product_version: string
adapter_status: 'verified' | 'unverified'
last_data_time: string | null
}
/** 安全设备服务列表数据 */
@@ -67,45 +52,32 @@ export interface SecurityServiceListParams {
/** 创建/更新安全设备服务请求参数 */
export interface SecurityServiceFormData {
resource_uid?: string
asset_id?: number
service_identity?: string
oid?: string
server_identity?: string
name?: string
category?: string
type?: string
host?: string
vendor?: string
model?: string
location?: string
description?: string
enabled?: boolean
interval?: number
extra?: string
tags?: string
status_url?: string
agent_config?: string
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
collect_on?: boolean
collect_args?: string
collect_interval?: number
policy_ids?: number[]
}
/** 安全设备指标项 */
export interface SecurityMetric {
timestamp?: string
service_identity?: string
type?: string
metric_name: string
metric_value: number
metric_unit: string
series_key?: string
labels?: string
}
/** 安全设备最新指标数据 */
@@ -136,11 +108,6 @@ export const updateSecurityService = (id: number, data: Partial<SecurityServiceF
return request.put<{ code: number; message: string; details: { message: string } }>(`/DC-Control/v1/security/${id}`, data)
}
/** 删除安全设备服务 */
export const deleteSecurityService = (id: number) => {
return request.delete<{ code: number; message: string; details: { message: string } }>(`/DC-Control/v1/security/${id}`)
}
/** 获取最新时序指标 */
export const fetchSecurityMetricsLatest = (serviceIdentity: string) => {
return request.get<{ code: number; message: string; details: SecurityMetricsLatestData }>('/DC-Control/v1/security/metrics/latest', {
@@ -148,33 +115,35 @@ export const fetchSecurityMetricsLatest = (serviceIdentity: string) => {
})
}
/** 采集配置补丁参数 */
export interface SecurityServicePatchData {
collect_method?: 'api' | 'snmp'
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
collect_on?: boolean
collect_interval?: number
export interface SecurityMetricsTimeseriesQuery {
start_time?: string
end_time?: string
metric_name?: string
}
/** 采集配置补丁 */
export const patchSecurityServiceCollect = (id: number, data: SecurityServicePatchData) => {
return request.patch<{ code: number; message: string; details: { message: string } }>(`/DC-Control/v1/security/${id}/collect`, data)
export interface SecurityMetricsTimeseriesData {
service_identity: string
start_time: string
end_time: string
count: number
metrics: SecurityMetric[]
}
/** 查询安全设备指标原始时序点 */
export const fetchSecurityMetricsTimeseries = (serviceIdentity: string, params?: SecurityMetricsTimeseriesQuery) => {
const path = encodeURIComponent(serviceIdentity)
return request.get<{ code: number; message: string; details: SecurityMetricsTimeseriesData }>(
`/DC-Control/v1/security/metrics/timeseries/${path}`,
{ params }
)
}
export const fetchSecurityInterfaces = (id: number) =>
request.get<{ code: number; message: string; details: DeviceInterfaceSnapshot[] }>(`/DC-Control/v1/security/${id}/interfaces`)
export const fetchSecurityAccessPoints = (id: number) =>
request.get<{ code: number; message: string; details: WirelessAccessPoint[] }>(`/DC-Control/v1/security/${id}/access-points`)
/** 告警聚合查询参数 */
export interface SecurityMetricsAggregateParams {
service_identity: string
@@ -210,6 +179,12 @@ export const SECURITY_TYPE_MAP: Record<string, string> = {
ids: 'IDS',
ips: 'IPS',
vpn: 'VPN',
threat_awareness: '态势感知',
bastion_host: '堡垒机',
log_audit: '日志审计',
database_audit: '数据库审计',
internet_behavior: '上网行为管理',
security_gap: '网闸',
other: '其他',
}
@@ -220,6 +195,12 @@ export const SECURITY_TYPE_OPTIONS = [
{ label: 'IDS', value: 'ids' },
{ label: 'IPS', value: 'ips' },
{ label: 'VPN', value: 'vpn' },
{ label: '态势感知', value: 'threat_awareness' },
{ label: '堡垒机', value: 'bastion_host' },
{ label: '日志审计', value: 'log_audit' },
{ label: '数据库审计', value: 'database_audit' },
{ label: '上网行为管理', value: 'internet_behavior' },
{ label: '网闸', value: 'security_gap' },
{ label: '其他', value: 'other' },
]

View File

@@ -3,6 +3,7 @@ import { request } from '@/api/request'
/** 服务器类型 */
export interface ServerItem {
id: number
resource_uid: string
created_at: string
updated_at: string
deleted_at: string | null
@@ -18,17 +19,10 @@ export interface ServerItem {
tags: string
location: string
asset_id?: number
remote_access: string
remote_port: number
agent_config: string
monitored_processes: string[]
monitored_ports: number[]
status: string
last_check_time: string
collect_on: boolean
collect_args: string
collect_interval: number
collect_last_result: string
is_ip_scan_server: boolean
ip_scan_port: number
}
/** 服务器列表响应 */
@@ -44,12 +38,11 @@ export interface ServerListParams {
page?: number
size?: number
keyword?: string
collect_on?: boolean
is_ip_scan_server?: boolean
}
/** 创建/更新服务器请求参数 */
export interface ServerFormData {
resource_uid?: string
server_identity?: string
name?: string
host?: string
@@ -62,17 +55,8 @@ export interface ServerFormData {
tags?: string
location?: string
asset_id?: number
remote_access?: string
remote_port?: number
agent_config?: string
status?: string
last_check_time?: string
collect_on?: boolean
collect_args?: string
collect_interval?: number
collect_last_result?: string
is_ip_scan_server?: boolean
ip_scan_port?: number
monitored_processes?: string[]
monitored_ports?: number[]
}
/** 获取服务器列表(分页) */
@@ -95,11 +79,6 @@ export const updateServer = (id: number, data: Partial<ServerFormData>) => {
return request.put<{ message: string }>(`/DC-Control/v1/servers/${id}`, data)
}
/** 删除服务器 */
export const deleteServer = (id: number) => {
return request.delete<{ message: string }>(`/DC-Control/v1/servers/${id}`)
}
/** 主机最新指标摘要(统计卡片,与 dc-control /servers/metrics/summary 一致) */
export interface HostMetricsUseStat {
total_bytes: number
@@ -138,6 +117,33 @@ export interface HostMetricsSummary {
cpu?: HostMetricsCpuCard
}
export interface HostMetricRow {
timestamp: string
server_identity: string
type: string
sub_type: string
metric_name: string
metric_value: number
metric_unit: string
}
export interface HostLatestMetricsPayload {
server_identity: string
timestamp?: string
has_data: boolean
rows: HostMetricRow[]
}
export interface HardwareSnapshotPayload {
has_data: boolean
protocol?: string
collected_at?: string
metrics: Array<{ code: string; value: number; unit: string; labels: Record<string, string> }>
inventory: Array<{ type: string; identity: string; name: string; status: string; attributes: Record<string, string> }>
events: Array<{ code: string; severity: string; summary: string; attributes: Record<string, string> }>
diagnostics: Array<{ code: string; level: string; message: string }>
}
export interface HostNetworkTrafficPoint {
time: string
recv_mbps: number
@@ -162,12 +168,15 @@ export const fetchServerMetricsSummary = (serverIdentity: string) => {
})
}
/** 立即拉取一次主机指标并返回最新统计卡片 */
export const collectServerMetricsNow = (serverIdentity: string) => {
return request.post<{ code: number; details?: HostMetricsSummary; message?: string }>('/DC-Control/v1/servers/metrics/collect', {
server_identity: serverIdentity,
})
}
export const fetchServerLatestMetrics = (serverIdentity: string) =>
request.get<{ code: number; details?: HostLatestMetricsPayload; message?: string }>('/DC-Control/v1/servers/metrics/latest', {
params: { server_identity: serverIdentity },
})
export const fetchServerHardwareSnapshot = (serverIdentity: string) =>
request.get<{ code: number; details?: HardwareSnapshotPayload; message?: string }>('/DC-Control/v1/servers/metrics/hardware', {
params: { server_identity: serverIdentity },
})
/** 近 N 小时网络收/发速率(Mbps,相邻采样字节差分) */
export const fetchServerNetworkTraffic = (serverIdentity: string, hours = 6) => {

View File

@@ -3,41 +3,22 @@ import { request } from '@/api/request'
/** 存储设备服务项 */
export interface StorageItem {
id: number
resource_uid: string
asset_id: number
created_at: string
updated_at: string
deleted_at: string | null
service_identity: string
oid: string
server_identity: string
name: string
category: string
type: string
host: string
vendor: string
model: string
location: string
description: string
enabled: boolean
interval: number
extra: string
tags: string
status_url: string
agent_config: string
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
collect_on: boolean
collect_args: string
collect_interval: number
collect_last_result: string
status: string
status_code: number
status_message: string
@@ -47,6 +28,9 @@ export interface StorageItem {
last_offline_time: string | null
continuous_errors: number
uptime: number
product_version: string
adapter_status: 'verified' | 'unverified'
last_data_time: string | null
}
/** 存储设备列表响应 */
@@ -67,86 +51,53 @@ export interface StorageListParams {
/** 创建存储设备请求参数 */
export interface StorageCreateData {
resource_uid?: string
asset_id?: number
service_identity?: string
name: string
category?: string
type: string
oid?: string
server_identity?: string
host?: string
vendor?: string
model?: string
location?: string
description?: string
enabled?: boolean
interval?: number
extra?: string
tags?: string
status_url?: string
agent_config?: string
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
collect_on?: boolean
collect_args?: string
collect_interval?: number
policy_ids?: number[]
}
/** 更新存储设备请求参数 */
export interface StorageUpdateData {
resource_uid?: string
asset_id?: number
service_identity?: string
oid?: string
server_identity?: string
name?: string
category?: string
type?: string
host?: string
vendor?: string
model?: string
location?: string
description?: string
enabled?: boolean
interval?: number
extra?: string
tags?: string
status_url?: string
agent_config?: string
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
collect_on?: boolean
collect_args?: string
collect_interval?: number
collect_last_result?: string
status?: string
status_code?: number
status_message?: string
response_time?: number
last_check_time?: string
last_online_time?: string | null
last_offline_time?: string | null
continuous_errors?: number
uptime?: number
policy_ids?: number[]
}
export interface StorageComponent {
id: number
resource_uid: string
component_type: string
component_identity: string
name: string
status: string
capacity_bytes: number
used_bytes: number
attributes: string
last_seen_at: string
}
/** 指标项 */
export interface StorageMetricItem {
metric_name: string
@@ -182,10 +133,8 @@ export const updateStorage = (id: number, data: StorageUpdateData) => {
return request.put<{ message: string }>(`/DC-Control/v1/storage/${id}`, data)
}
/** 删除存储设备服务 */
export const deleteStorage = (id: number) => {
return request.delete<{ message: string }>(`/DC-Control/v1/storage/${id}`)
}
export const fetchStorageComponents = (id: number) =>
request.get<StorageComponent[]>(`/DC-Control/v1/storage/${id}/components`)
/** 查询最新一批时序指标 */
export const fetchStorageMetricsLatest = (serviceIdentity: string) => {
@@ -199,27 +148,21 @@ export interface StorageMonitorOptionItem {
service_identity: string
name: string
type: string
server_identity: string
host: string
vendor: string
model: string
status: string
}
/** 监控大屏:汇总 current.host(与后端 storage_monitor 一致) */
export interface StorageMonitorSummaryHost {
has_data: boolean
cpu_usage_percent?: number | null
memory_usage_percent?: number | null
swap_usage_percent?: number | null
disk_root_used_percent?: number | null
disk_root_avail_percent?: number | null
host_server_identity?: string
host_summary_timestamp?: string | null
}
export interface StorageMonitorSummaryCurrent {
service_identity: string
controller_status: string
server_identity: string
host?: StorageMonitorSummaryHost | null
resource_uid: string
status: string
adapter_status: string
product_version: string
last_data_time?: string | null
component_count: number
abnormal_component_count: number
}
export interface StorageMonitorSummaryPayload {
@@ -230,7 +173,7 @@ export interface StorageMonitorSummaryPayload {
current?: StorageMonitorSummaryCurrent | null
}
export const fetchStorageMonitorList = (params?: { keyword?: string; limit?: number }) => {
export const fetchStorageMonitorList = (params?: { keyword?: string }) => {
return request.get<{
code: number
details?: { data: StorageMonitorOptionItem[]; count: number }
@@ -330,30 +273,3 @@ export const fetchStorageMetricsTimeseries = (serviceIdentity: string, params?:
params,
})
}
/** 采集配置补丁 */
export interface StoragePatchData {
collect_method?: 'api' | 'snmp'
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
collect_on?: boolean
collect_interval?: number
}
/** 采集配置补丁更新 */
export const patchStorage = (id: number, data: StoragePatchData) => {
return request.patch<{ message: string }>(`/DC-Control/v1/storage/${id}/collect`, data)
}

View File

@@ -0,0 +1,67 @@
import { request } from '@/api/request'
const BASE = '/Mgt/v1/settings'
export interface DataDictionaryItem {
id?: number
category_code: string
item_code: string
label: string
value: string
sort: number
enabled: boolean
description: string
}
export interface SystemParameter {
id: number
code: string
name: string
value: number
unit: string
minimum: number
maximum: number
description: string
}
export interface CommonPhrase {
id?: number
category_code: string
content: string
sort: number
enabled: boolean
}
export type PublicSystemParameters = Record<string, number>
export const fetchDictionaries = (params?: { category_code?: string; enabled?: boolean }) =>
request.get(`${BASE}/dictionaries`, { params })
export const createDictionary = (data: DataDictionaryItem) => request.post(`${BASE}/dictionaries`, data)
export const updateDictionary = (id: number, data: DataDictionaryItem) => request.put(`${BASE}/dictionaries/${id}`, data)
export const deleteDictionary = (id: number) => request.delete(`${BASE}/dictionaries/${id}`)
export const fetchSystemParameters = () => request.get(`${BASE}/parameters`)
export const fetchPublicSystemParameters = () => request.get<unknown>('/Mgt/v1/settings/parameters/public')
export const updateSystemParameter = (code: string, value: number) => request.put(`${BASE}/parameters/${code}`, { value })
export const fetchCommonPhrases = (params?: { page?: number; page_size?: number; keyword?: string; category_code?: string }) =>
request.get(`${BASE}/phrases`, { params })
export const createCommonPhrase = (data: CommonPhrase) => request.post(`${BASE}/phrases`, data)
export const updateCommonPhrase = (id: number, data: CommonPhrase) => request.put(`${BASE}/phrases/${id}`, data)
export const deleteCommonPhrase = (id: number) => request.delete(`${BASE}/phrases/${id}`)
export function unwrapSystemSettings<T>(response: any): T {
return (response?.details ?? response?.data) as T
}
export async function fetchDictionaryOptions(categoryCode: string): Promise<Array<{ label: string; value: string }>> {
const response = await fetchDictionaries({ category_code: categoryCode, enabled: true })
const rows = unwrapSystemSettings<DataDictionaryItem[]>(response) || []
return rows.map((item) => ({ label: item.label, value: item.value }))
}
export async function fetchEnabledCommonPhrases(categoryCode: string): Promise<CommonPhrase[]> {
const response = await fetchCommonPhrases({ page: 1, page_size: 100, category_code: categoryCode })
const payload = unwrapSystemSettings<{ data?: CommonPhrase[] }>(response) || {}
return (payload.data || []).filter((item) => item.enabled)
}

View File

@@ -33,8 +33,8 @@ export interface ThreeMachineRoomSize {
depth: number
}
/** 设备绑定的监控资源。 */
export interface ThreeMachineRoomBinding {
/** 统一监控资源身份。 */
export interface ThreeMachineRoomResourceIdentity {
resource_uid: string
resource_category?: string
service_identity?: string
@@ -52,7 +52,7 @@ export interface ThreeMachineRoomMetric {
}
/** 设备资源运行数据。 */
export interface ThreeMachineRoomResource extends ThreeMachineRoomBinding {
export interface ThreeMachineRoomResource extends ThreeMachineRoomResourceIdentity {
status?: string
metrics_at?: string
metrics?: ThreeMachineRoomMetric[]
@@ -89,6 +89,7 @@ export interface ThreeMachineRoomUnit {
/** 机柜中的资产设备。 */
export interface ThreeMachineRoomDevice {
asset_id: number
resource_uid: string
asset_code?: string
asset_name?: string
category_id?: number | null
@@ -102,7 +103,6 @@ export interface ThreeMachineRoomDevice {
power_consumption?: number
transform?: ThreeMachineRoomTransform
size?: ThreeMachineRoomSize
bindings?: ThreeMachineRoomBinding[]
}
/** 3D 场景机柜。 */

View File

@@ -84,6 +84,35 @@ export interface TrafficDashboardResponse {
}>
}
export interface NetworkObservation {
id: number
created_at: string
probe_id: string
source_kind: string
sensor_interface?: string
window_start: string
window_end: string
source_ip: string
destination_ip: string
source_port?: number
destination_port?: number
transport: string
application?: string
bytes: number
packets: number
connections: number
latency_ms?: number
http_method?: string
http_host?: string
http_path?: string
http_status_code?: number
tls_version?: string
tls_server_name?: string
tls_cert_subject?: string
tls_cert_issuer?: string
tls_cert_not_after?: string
}
export const fetchTrafficList = (params?: Record<string, any>) =>
request.get<{ code: number; details?: TrafficListResponse; message?: string }>('/DC-Control/v1/traffic', {
params,
@@ -106,3 +135,9 @@ export const fetchRealtimeTraffic = (params?: Record<string, any>) =>
export const fetchTrafficDashboard = (params?: Record<string, any>) =>
request.get<{ code: number; details?: TrafficDashboardResponse; message?: string }>('/DC-Control/v1/traffic/dashboard', { params })
export const fetchNetworkObservations = (params?: Record<string, any>) =>
request.get<{ code: number; details?: { total: number; page: number; page_size: number; data: NetworkObservation[] }; message?: string }>(
'/DC-Control/v1/traffic/network-observations',
{ params }
)

View File

@@ -1,145 +0,0 @@
import { request } from '@/api/request'
export interface UrlDeviceItem {
id: number
created_at: string
updated_at: string
deleted_at: string | null
service_identity: string
name: string
description: string
target_url: string
method: string
enabled: boolean
interval: number
extra: string
tags: string
collect_on: boolean
collect_interval: number
collect_last_result: string
status: string
status_code: number
response_time: number
last_check_time: string
last_online_time: string | null
last_offline_time: string | null
continuous_errors: number
}
export interface UrlDeviceListResponse {
total: number
page: number
page_size: number
data: UrlDeviceItem[]
}
export interface UrlDeviceListParams {
page?: number
size?: number
keyword?: string
enabled?: boolean
}
export interface UrlDeviceCreateData {
service_identity?: string
name: string
description?: string
target_url: string
method?: string
enabled?: boolean
interval?: number
extra?: string
tags?: string
collect_on?: boolean
collect_interval?: number
collect_last_result?: string
}
export interface UrlDeviceUpdateData {
name?: string
description?: string
target_url?: string
method?: string
enabled?: boolean
interval?: number
extra?: string
tags?: string
collect_on?: boolean
collect_interval?: number
collect_last_result?: string
status?: string
status_code?: number
response_time?: number
last_check_time?: string
last_online_time?: string | null
last_offline_time?: string | null
continuous_errors?: number
}
export interface UrlDeviceCollectData {
collect_on?: boolean
collect_interval?: number
collect_last_result?: string
}
export const fetchUrlDeviceList = (params?: UrlDeviceListParams) => {
return request.get<UrlDeviceListResponse>('/DC-Control/v1/url-devices', { params })
}
export const fetchUrlDeviceDetail = (id: number) => {
return request.get<UrlDeviceItem>(`/DC-Control/v1/url-devices/${id}`)
}
export const createUrlDevice = (data: UrlDeviceCreateData) => {
return request.post<{ message: string; id: number }>('/DC-Control/v1/url-devices', data)
}
export const updateUrlDevice = (id: number, data: UrlDeviceUpdateData) => {
return request.put<{ message: string }>(`/DC-Control/v1/url-devices/${id}`, data)
}
export const patchUrlDeviceCollect = (id: number, data: UrlDeviceCollectData) => {
return request.patch<{ message: string }>(`/DC-Control/v1/url-devices/${id}/collect`, data)
}
export const deleteUrlDevice = (id: number) => {
return request.delete<{ message: string }>(`/DC-Control/v1/url-devices/${id}`)
}
export interface UrlDeviceStatsOverview {
total: number
online: number
today_alert_count: number
avg_response_time_ms: number
}
export interface ResponseTimePoint {
hour: string
avg_response_time_ms: number
}
export interface UrlDeviceResponseTimeTrend {
points: ResponseTimePoint[]
}
export interface StatusDistributionItem {
status: string
count: number
}
export interface UrlDeviceStatusDistribution {
total: number
by_status: StatusDistributionItem[]
}
export const fetchUrlDeviceStatsOverview = () => {
return request.get<UrlDeviceStatsOverview>('/DC-Control/v1/url-devices/stats/overview')
}
export const fetchUrlDeviceResponseTimeTrend = () => {
return request.get<UrlDeviceResponseTimeTrend>('/DC-Control/v1/url-devices/stats/response-time-trend')
}
export const fetchUrlDeviceStatusDistribution = () => {
return request.get<UrlDeviceStatusDistribution>('/DC-Control/v1/url-devices/stats/status-distribution')
}

View File

@@ -28,6 +28,12 @@ export interface UserItem {
status?: number
role_id?: number
role_name?: string
department_id?: number
position_id?: number
role_ids?: number[]
department?: { id: number; name: string }
position?: { id: number; name: string }
roles?: { id: number; name: string }[]
created_at?: string
updated_at?: string
}