diff --git a/src/client/admin/api/alert.ts b/src/client/admin/api/alert.ts deleted file mode 100644 index af88d63..0000000 --- a/src/client/admin/api/alert.ts +++ /dev/null @@ -1,89 +0,0 @@ -import axios from 'axios'; -import { DeviceAlert } from "@/share/monitorTypes"; - -// 告警相关响应类型 -interface DeviceAlertDataResponse { - data: DeviceAlert[]; - total: number; - page: number; - pageSize: number; - } - - interface DeviceAlertResponse { - data: DeviceAlert; - message?: string; - } - - interface AlertCreateResponse { - data: DeviceAlert; - message: string; - } - - interface AlertUpdateResponse { - data: DeviceAlert; - message: string; - } - - interface AlertDeleteResponse { - message: string; - } - -// 告警API接口定义 -export const AlertAPI = { - // 获取告警数据 - getAlertData: async (params?: { - page?: number, - limit?: number, - alert_type?: string, - alert_level?: string, - start_time?: string, - end_time?: string - }): Promise => { - try { - const response = await axios.get(`/alerts`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个告警数据 - getAlert: async (id: number): Promise => { - try { - const response = await axios.get(`/alerts/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建告警数据 - createAlert: async (data: Partial): Promise => { - try { - const response = await axios.post(`/alerts`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新告警数据 - updateAlert: async (id: number, data: Partial): Promise => { - try { - const response = await axios.put(`/alerts/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除告警数据 - deleteAlert: async (id: number): Promise => { - try { - const response = await axios.delete(`/alerts/${id}`); - return response.data; - } catch (error) { - throw error; - } - } - }; \ No newline at end of file diff --git a/src/client/admin/api/alert_handle.ts b/src/client/admin/api/alert_handle.ts deleted file mode 100644 index 88b5601..0000000 --- a/src/client/admin/api/alert_handle.ts +++ /dev/null @@ -1,75 +0,0 @@ -import axios from 'axios'; -import { AlertHandleLog } from "@/share/monitorTypes"; - -// 告警处理相关响应类型 -interface AlertHandleDataResponse { - data: AlertHandleLog[]; - total: number; - page: number; - pageSize: number; - } - - interface AlertHandleResponse { - data: AlertHandleLog; - message?: string; - } - -// 告警处理API接口定义 -export const AlertHandleAPI = { - // 获取告警处理数据 - getAlertHandleData: async (params?: { - page?: number, - limit?: number, - alert_id?: number, - handle_type?: string, - start_time?: string, - end_time?: string - }): Promise => { - try { - const response = await axios.get(`/alert-handles`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个告警处理数据 - getAlertHandle: async (id: number): Promise => { - try { - const response = await axios.get(`/alert-handles/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建告警处理数据 - createAlertHandle: async (data: Partial) => { - try { - const response = await axios.post(`/alert-handles`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新告警处理数据 - updateAlertHandle: async (id: number, data: Partial) => { - try { - const response = await axios.put(`/alert-handles/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除告警处理数据 - deleteAlertHandle: async (id: number) => { - try { - const response = await axios.delete(`/alert-handles/${id}`); - return response.data; - } catch (error) { - throw error; - } - } - }; \ No newline at end of file diff --git a/src/client/admin/api/alert_notify_config.ts b/src/client/admin/api/alert_notify_config.ts deleted file mode 100644 index f14fc76..0000000 --- a/src/client/admin/api/alert_notify_config.ts +++ /dev/null @@ -1,63 +0,0 @@ -import axios from 'axios'; -import { AlertNotifyConfig } from "@/share/monitorTypes"; - -// 告警通知配置相关响应类型 -interface AlertNotifyConfigDataResponse { - data: AlertNotifyConfig[]; - total: number; - page: number; - pageSize: number; - } - - interface AlertNotifyConfigResponse { - data: AlertNotifyConfig; - message?: string; - } - -// 告警通知配置API接口定义 -export const AlertNotifyConfigAPI = { - // 获取告警通知配置 - getAlertNotifyConfig: async (params?: { - page?: number, - limit?: number, - device_id?: number, - alert_level?: string - }): Promise => { - try { - const response = await axios.get(`/alert-notify-configs`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建告警通知配置 - createAlertNotifyConfig: async (data: Partial): Promise => { - try { - const response = await axios.post(`/alert-notify-configs`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新告警通知配置 - updateAlertNotifyConfig: async (id: number, data: Partial): Promise => { - try { - const response = await axios.put(`/alert-notify-configs/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除告警通知配置 - deleteAlertNotifyConfig: async (id: number): Promise => { - try { - const response = await axios.delete(`/alert-notify-configs/${id}`); - return response.data; - } catch (error) { - throw error; - } - } - }; \ No newline at end of file diff --git a/src/client/admin/api/auth.ts b/src/client/admin/api/auth.ts deleted file mode 100644 index 275b341..0000000 --- a/src/client/admin/api/auth.ts +++ /dev/null @@ -1,104 +0,0 @@ -import axios from 'axios'; -import type { User } from '../@/share/types'; - -interface AuthLoginResponse { - message: string; - token: string; - refreshToken?: string; - user: User; -} - -interface AuthResponse { - message: string; - [key: string]: any; -} - -interface AuthAPIType { - login: (username: string, password: string, latitude?: number, longitude?: number) => Promise; - register: (username: string, email: string, password: string) => Promise; - logout: () => Promise; - getCurrentUser: () => Promise; - updateUser: (userId: number, userData: Partial) => Promise; - changePassword: (oldPassword: string, newPassword: string) => Promise; - requestPasswordReset: (email: string) => Promise; - resetPassword: (token: string, newPassword: string) => Promise; -} - -export const AuthAPI: AuthAPIType = { - login: async (username: string, password: string, latitude?: number, longitude?: number) => { - try { - const response = await axios.post('/auth/login', { - username, - password, - latitude, - longitude - }); - return response.data; - } catch (error) { - throw error; - } - }, - - register: async (username: string, email: string, password: string) => { - try { - const response = await axios.post('/auth/register', { username, email, password }); - return response.data; - } catch (error) { - throw error; - } - }, - - logout: async () => { - try { - const response = await axios.post('/auth/logout'); - return response.data; - } catch (error) { - throw error; - } - }, - - getCurrentUser: async () => { - try { - const response = await axios.get('/auth/me'); - return response.data; - } catch (error) { - throw error; - } - }, - - updateUser: async (userId: number, userData: Partial) => { - try { - const response = await axios.put(`/auth/users/${userId}`, userData); - return response.data; - } catch (error) { - throw error; - } - }, - - changePassword: async (oldPassword: string, newPassword: string) => { - try { - const response = await axios.post('/auth/change-password', { oldPassword, newPassword }); - return response.data; - } catch (error) { - throw error; - } - }, - - requestPasswordReset: async (email: string) => { - try { - const response = await axios.post('/auth/request-password-reset', { email }); - return response.data; - } catch (error) { - throw error; - } - }, - - resetPassword: async (token: string, newPassword: string) => { - try { - const response = await axios.post('/auth/reset-password', { token, newPassword }); - return response.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/charts.ts b/src/client/admin/api/charts.ts deleted file mode 100644 index 64c185e..0000000 --- a/src/client/admin/api/charts.ts +++ /dev/null @@ -1,66 +0,0 @@ -import axios from 'axios'; - -interface ChartDataResponse { - message: string; - data: T; -} - -interface UserActivityData { - date: string; - count: number; -} - -interface FileUploadsData { - month: string; - count: number; -} - -interface FileTypesData { - type: string; - value: number; -} - -interface DashboardOverviewData { - userCount: number; - fileCount: number; - articleCount: number; - todayLoginCount: number; -} - -export const ChartAPI = { - getUserActivity: async (): Promise> => { - try { - const response = await axios.get('/charts/user-activity'); - return response.data; - } catch (error) { - throw error; - } - }, - - getFileUploads: async (): Promise> => { - try { - const response = await axios.get('/charts/file-uploads'); - return response.data; - } catch (error) { - throw error; - } - }, - - getFileTypes: async (): Promise> => { - try { - const response = await axios.get('/charts/file-types'); - return response.data; - } catch (error) { - throw error; - } - }, - - getDashboardOverview: async (): Promise> => { - try { - const response = await axios.get('/charts/dashboard-overview'); - return response.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/device_alert_rule.ts b/src/client/admin/api/device_alert_rule.ts deleted file mode 100644 index 8013d1b..0000000 --- a/src/client/admin/api/device_alert_rule.ts +++ /dev/null @@ -1,78 +0,0 @@ -import axios from 'axios'; -import { DeviceAlert, DeviceAlertRule } from "@/share/monitorTypes"; - -// 告警相关响应类型 -interface DeviceAlertDataResponse { - data: DeviceAlert[]; - total: number; - page: number; - pageSize: number; - } - - interface DeviceAlertResponse { - data: DeviceAlert; - message?: string; - } - - -interface AlertDeleteResponse { - message: string; - } - -// 设备告警规则API接口定义 -export const DeviceAlertRuleAPI = { - // 获取设备告警规则 - getDeviceAlertRules: async (params?: { - page?: number, - limit?: number, - device_id?: number, - rule_type?: string - }): Promise => { - try { - const response = await axios.get(`/device-alert-rules`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个设备告警规则 - getDeviceAlertRule: async (id: number): Promise => { - try { - const response = await axios.get(`/device-alert-rules/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建设备告警规则 - createDeviceAlertRule: async (data: Partial): Promise => { - try { - const response = await axios.post(`/device-alert-rules`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新设备告警规则 - updateDeviceAlertRule: async (id: number, data: Partial): Promise => { - try { - const response = await axios.put(`/device-alert-rules/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除设备告警规则 - deleteDeviceAlertRule: async (id: number): Promise => { - try { - const response = await axios.delete(`/device-alert-rules/${id}`); - return response.data; - } catch (error) { - throw error; - } - } - }; \ No newline at end of file diff --git a/src/client/admin/api/device_instance.ts b/src/client/admin/api/device_instance.ts deleted file mode 100644 index ad098cd..0000000 --- a/src/client/admin/api/device_instance.ts +++ /dev/null @@ -1,93 +0,0 @@ -import axios from "axios"; -import { DeviceInstance, DeviceType, ZichanInfo } from "@/share/monitorTypes"; - -// 设备实例API接口定义 -interface DeviceInstancesResponse { - data: DeviceInstance[]; - pagination: { - total: number; - current: number; - pageSize: number; - totalPages: number; - }; -} - -interface DeviceInstanceResponse { - data: DeviceInstance; - asset_info?: ZichanInfo; - type_info?: DeviceType; - message?: string; -} - -interface DeviceInstanceCreateResponse { - message: string; - data: DeviceInstance; -} - -interface DeviceInstanceUpdateResponse { - message: string; - data: DeviceInstance; -} - -interface DeviceInstanceDeleteResponse { - message: string; - id: number; -} - -export const DeviceInstanceAPI = { - // 获取设备实例列表 - getDeviceInstances: async (params?: { - page?: number, - limit?: number, - type_id?: number, - protocol?: string, - status?: number - }): Promise => { - try { - const response = await axios.get('/device/instances', { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个设备实例信息 - getDeviceInstance: async (id: number): Promise => { - try { - const response = await axios.get(`/device/instances/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建设备实例 - createDeviceInstance: async (data: Partial): Promise => { - try { - const response = await axios.post('/device/instances', data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新设备实例 - updateDeviceInstance: async (id: number, data: Partial): Promise => { - try { - const response = await axios.put(`/device/instances/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除设备实例 - deleteDeviceInstance: async (id: number): Promise => { - try { - const response = await axios.delete(`/device/instances/${id}`); - return response.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/device_type.ts b/src/client/admin/api/device_type.ts deleted file mode 100644 index 9882291..0000000 --- a/src/client/admin/api/device_type.ts +++ /dev/null @@ -1,101 +0,0 @@ -import axios from "axios"; -import { DeviceType } from "@/share/monitorTypes"; - -// 设备类型API接口定义 -interface DeviceTypeResponse { - data: DeviceType[]; - pagination: { - total: number; - current: number; - pageSize: number; - totalPages: number; - }; -} - -interface DeviceTypeDetailResponse { - data: DeviceType; - message?: string; -} - -interface DeviceTypeCreateResponse { - message: string; - data: DeviceType; -} - -interface DeviceTypeUpdateResponse { - message: string; - data: DeviceType; -} - -interface DeviceTypeDeleteResponse { - message: string; - id: number; -} - -export const DeviceTypeAPI = { - // 获取设备类型列表 - getDeviceTypes: async (params?: { - page?: number, - pageSize?: number, - code?: string, - name?: string, - is_enabled?: boolean - }): Promise => { - try { - const response = await axios.get('/device/types', { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个设备类型信息 - getDeviceType: async (id: number): Promise => { - try { - const response = await axios.get(`/device/types/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建设备类型 - createDeviceType: async (data: Partial): Promise => { - try { - const response = await axios.post('/device/types', data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新设备类型 - updateDeviceType: async (id: number, data: Partial): Promise => { - try { - const response = await axios.put(`/device/types/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除设备类型 - deleteDeviceType: async (id: number): Promise => { - try { - const response = await axios.delete(`/device/types/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取设备类型图标 - getTypeIcons: async (): Promise<{data: Record, success: boolean}> => { - try { - const response = await axios.get('/device/types/icons'); - return response.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/files.ts b/src/client/admin/api/files.ts deleted file mode 100644 index 49696a7..0000000 --- a/src/client/admin/api/files.ts +++ /dev/null @@ -1,159 +0,0 @@ -import axios from 'axios'; -import type { FileLibrary, FileCategory } from '../@/share/types'; -import type { MinioUploadPolicy, OSSUploadPolicy } from '@d8d-appcontainer/types'; - -interface FileUploadPolicyResponse { - message: string; - data: MinioUploadPolicy | OSSUploadPolicy; -} - -interface FileListResponse { - message: string; - data: { - list: FileLibrary[]; - pagination: { - current: number; - pageSize: number; - total: number; - }; - }; -} - -interface FileSaveResponse { - message: string; - data: FileLibrary; -} - -interface FileInfoResponse { - message: string; - data: FileLibrary; -} - -interface FileDeleteResponse { - message: string; -} - -interface FileCategoryListResponse { - data: FileCategory[]; - total: number; - page: number; - pageSize: number; -} - -interface FileCategoryCreateResponse { - message: string; - data: FileCategory; -} - -interface FileCategoryUpdateResponse { - message: string; - data: FileCategory; -} - -interface FileCategoryDeleteResponse { - message: string; -} - -export const FileAPI = { - getUploadPolicy: async (filename: string, prefix: string = 'uploads/', maxSize: number = 10 * 1024 * 1024): Promise => { - try { - const response = await axios.get('/upload/policy', { - params: { filename, prefix, maxSize } - }); - return response.data; - } catch (error) { - throw error; - } - }, - - saveFileInfo: async (fileData: Partial): Promise => { - try { - const response = await axios.post('/upload/save', fileData); - return response.data; - } catch (error) { - throw error; - } - }, - - getFileList: async (params?: { - page?: number, - pageSize?: number, - category_id?: number, - fileType?: string, - keyword?: string - }): Promise => { - try { - const response = await axios.get('/upload/list', { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - getFileInfo: async (id: number): Promise => { - try { - const response = await axios.get(`/upload/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - updateDownloadCount: async (id: number): Promise => { - try { - const response = await axios.post(`/upload/${id}/download`); - return response.data; - } catch (error) { - throw error; - } - }, - - deleteFile: async (id: number): Promise => { - try { - const response = await axios.delete(`/upload/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - getCategories: async (params?: { - page?: number, - pageSize?: number, - search?: string - }): Promise => { - try { - const response = await axios.get('/file-categories', { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - createCategory: async (data: Partial): Promise => { - try { - const response = await axios.post('/file-categories', data); - return response.data; - } catch (error) { - throw error; - } - }, - - updateCategory: async (id: number, data: Partial): Promise => { - try { - const response = await axios.put(`/file-categories/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - deleteCategory: async (id: number): Promise => { - try { - const response = await axios.delete(`/file-categories/${id}`); - return response.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/index.ts b/src/client/admin/api/index.ts deleted file mode 100644 index 889398b..0000000 --- a/src/client/admin/api/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import axios from 'axios'; - -// 基础配置 -export const API_BASE_URL = '/api'; -// 全局axios配置 -// axios.defaults.baseURL = API_BASE_URL; - -// 获取OSS完整URL -export const getOssUrl = (path: string): string => { - // 获取全局配置中的OSS_HOST,如果不存在使用默认值 - const ossHost = (window.CONFIG?.OSS_BASE_URL) || ''; - // 确保path不以/开头 - const ossPath = path.startsWith('/') ? path.substring(1) : path; - return `${ossHost}/${ossPath}`; -}; - -export * from './auth'; -export * from './users'; -export * from './files'; -export * from './theme'; -export * from './charts'; -export * from './messages'; -export * from './sys'; -export * from './know_info'; -export * from './maps'; -export * from './zichan' -export * from './zichan_category' -export * from './zichan_area' -export * from './zichan_transfer' -export * from './device_instance' -export * from './device_type' -export * from './rack' -export * from './rack_server' -export * from './rack_server_type' -export * from './monitor' -export * from './alert' -export * from './alert_handle' -export * from './alert_notify_config' -export * from './device_alert_rule' -export * from './monitor_charts' -export * from './work_orders' \ No newline at end of file diff --git a/src/client/admin/api/inspections.ts b/src/client/admin/api/inspections.ts deleted file mode 100644 index 8f6fa32..0000000 --- a/src/client/admin/api/inspections.ts +++ /dev/null @@ -1,301 +0,0 @@ -import axios from 'axios'; - -// 检查模板类型 -export interface InspectionTemplate { - id: number; - name: string; - description?: string; - items: InspectionItem[]; - createdAt: string; - updatedAt: string; -} - -export interface InspectionItem { - id: number; - name: string; - description?: string; - required: boolean; -} - -// 检查任务类型 -export interface InspectionTask { - id: number; - templateId: number; - name: string; - taskNo: string; - description?: string; - status: 'pending' | 'in_progress' | 'completed' | 'failed'; - startTime?: string; - endTime?: string; - createdAt: string; - updatedAt: string; - schedule_type?: 'manual' | 'scheduled' | 'yearly'; - cronExpression?: string; - intervalDays?: number; - deviceTypes?: string[]; - run_immediately?: boolean; - progress?: number; - checked_count?: number; - issues_found?: number; -} - -// 检查结果类型 -export interface InspectionResult { - id: number; - taskId: number; - itemId: number; - status: 'passed' | 'failed' | 'skipped'; - notes?: string; - createdAt: string; -} - -// 报告接收者类型 -export interface ReportReceiver { - id: number; - name: string; - email: string; - createdAt: string; -} - -// API响应类型 -export interface ListResponse { - data: T[]; - total: number; - page: number; - pageSize: number; -} - -export interface SingleResponse { - data: T; - message?: string; -} - -export interface CreateResponse { - data: T; - message: string; -} - -export interface UpdateResponse { - data: T; - message: string; -} - -export interface DeleteResponse { - message: string; -} - -// 检查API接口定义 -export const InspectionsAPI = { - // 模板相关API - getTemplates: async (params?: { - page?: number; - limit?: number; - name?: string; - }): Promise> => { - try { - const response = await axios.get('/inspections/templates', { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - createTemplate: async (data: Omit): Promise> => { - try { - const response = await axios.post('/inspections/templates', data); - return response.data; - } catch (error) { - throw error; - } - }, - - updateTemplate: async (id: number, data: Partial): Promise> => { - try { - const response = await axios.put(`/inspections/templates/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - createAutoInspectionTask: async (data: { - taskNo: string; - cronExpression?: string; - intervalDays?: number; - deviceTypes?: string[]; - reportReceivers?: string[]; - }): Promise> => { - try { - const response = await axios.post('/inspections/auto-tasks', data); - return response.data; - } catch (error) { - throw error; - } - }, - - deleteTemplate: async (id: number): Promise => { - try { - const response = await axios.delete(`/inspections/templates/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 任务相关API - getTasks: async (params?: { - page?: number; - limit?: number; - status?: string; - templateId?: number; - }): Promise> => { - try { - const response = await axios.get('/inspections/tasks', { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - createTask: async (data: Omit): Promise> => { - try { - const response = await axios.post('/inspections/tasks', data); - return response.data; - } catch (error) { - throw error; - } - }, - - createAutoTask: async (data: { - name: string; - intervalDays: number; - deviceTypes?: string[]; - }): Promise> => { - try { - const response = await axios.post('/inspections/tasks/auto', data); - return response.data; - } catch (error) { - throw error; - } - }, - - runManualTask: async (data: { - deviceTypes?: string[]; - }): Promise> => { - try { - const response = await axios.post('/inspections/tasks/manual', data); - return response.data; - } catch (error) { - throw error; - } - }, - - runTask: async (id: number): Promise> => { - try { - const response = await axios.post(`/inspections/tasks/${id}/run`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 结果相关API - getResults: async (params?: { - page?: number; - limit?: number; - taskId?: number; - status?: string; - }): Promise> => { - try { - const response = await axios.get('/inspections/results', { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - exportReport: async (id: number): Promise => { - try { - const response = await axios.get(`/inspections/results/${id}/export`, { - responseType: 'blob' - }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 接收者相关API - getReceivers: async (params?: { - page?: number; - limit?: number; - }): Promise> => { - try { - const response = await axios.get('/inspections/receivers', { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - addReceiver: async (data: Omit): Promise> => { - try { - const response = await axios.post('/inspections/receivers', data); - return response.data; - } catch (error) { - throw error; - } - }, - - removeReceiver: async (id: number): Promise => { - try { - const response = await axios.delete(`/inspections/receivers/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 新年巡检专用API - createNewYearTask: async (data: { - id: string; - time: string; - deviceType: string; - status: string; - issuesFound: number; - receiverId: string; - }): Promise> => { - try { - const response = await axios.post('/inspections/tasks/new-year', data); - return response.data; - } catch (error) { - throw error; - } - }, - - updateProgress: async (id: number, data: { - progress: number; - checkedCount: number; - issuesFound: number; - }): Promise> => { - try { - const response = await axios.put(`/inspections/tasks/${id}/progress`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - completeInspection: async (id: number, results: { - itemId: number; - status: 'passed' | 'failed' | 'skipped'; - notes?: string; - }[]): Promise> => { - try { - const response = await axios.post(`/inspections/tasks/${id}/complete`, { results }); - return response.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/know_info.ts b/src/client/admin/api/know_info.ts deleted file mode 100644 index 0c6320e..0000000 --- a/src/client/admin/api/know_info.ts +++ /dev/null @@ -1,92 +0,0 @@ -import axios from 'axios'; -import type { KnowInfo } from '../@/share/types'; - -export interface KnowInfoListResponse { - data: KnowInfo[]; - pagination: { - current: number; - pageSize: number; - total: number; - totalPages: number; - }; -} - -interface KnowInfoResponse { - data: KnowInfo; - message?: string; -} - -interface KnowInfoCreateResponse { - message: string; - data: KnowInfo; -} - -interface KnowInfoUpdateResponse { - message: string; - data: KnowInfo; -} - -interface KnowInfoDeleteResponse { - message: string; - id: number; -} - - -// 知识库API -export const KnowInfoAPI = { - // 获取知识库列表 - getKnowInfos: async (params?: { - page?: number; - pageSize?: number; - title?: string; - category?: string; - tags?: string; - }): Promise => { - try { - const response = await axios.get('/know-infos', { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个知识详情 - getKnowInfo: async (id: number): Promise => { - try { - const response = await axios.get(`/know-infos/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建知识 - createKnowInfo: async (data: Partial): Promise => { - try { - const response = await axios.post('/know-infos', data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新知识 - updateKnowInfo: async (id: number, data: Partial): Promise => { - try { - const response = await axios.put(`/know-infos/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除知识 - deleteKnowInfo: async (id: number): Promise => { - try { - const response = await axios.delete(`/know-infos/${id}`); - return response.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/maps.ts b/src/client/admin/api/maps.ts deleted file mode 100644 index b5584a5..0000000 --- a/src/client/admin/api/maps.ts +++ /dev/null @@ -1,62 +0,0 @@ -import axios from 'axios'; -import type { - LoginLocation, LoginLocationDetail, -} from '../@/share/types'; - - -// 地图相关API的接口类型定义 -export interface LoginLocationResponse { - message: string; - data: LoginLocation[]; -} - -export interface LoginLocationDetailResponse { - message: string; - data: LoginLocationDetail; -} - -export interface LoginLocationUpdateResponse { - message: string; - data: LoginLocationDetail; -} - -// 地图相关API -export const MapAPI = { - // 获取地图标记点数据 - getMarkers: async (params?: { - startTime?: string; - endTime?: string; - userId?: number - }): Promise => { - try { - const response = await axios.get(`/map/markers`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取登录位置详情 - getLocationDetail: async (locationId: number): Promise => { - try { - const response = await axios.get(`/map/location/${locationId}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新登录位置信息 - updateLocation: async (locationId: number, data: { - longitude: number; - latitude: number; - location_name?: string; - }): Promise => { - try { - const response = await axios.put(`/map/location/${locationId}`, data); - return response.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/messages.ts b/src/client/admin/api/messages.ts deleted file mode 100644 index 9fa4d7b..0000000 --- a/src/client/admin/api/messages.ts +++ /dev/null @@ -1,79 +0,0 @@ -import axios from 'axios'; -import type { UserMessage, Message } from '../@/share/types'; - -interface MessagesResponse { - data: UserMessage[]; - pagination: { - total: number; - current: number; - pageSize: number; - totalPages: number; - }; -} - -interface MessageResponse { - data: Message; - message?: string; -} - -interface MessageCountResponse { - count: number; -} - -export const MessageAPI = { - getMessages: async (params?: { - page?: number, - pageSize?: number, - type?: string, - status?: string, - search?: string - }): Promise => { - try { - const response = await axios.get('/messages', { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - sendMessage: async (data: { - title: string, - content: string, - type: string, - receiver_ids: number[] - }): Promise => { - try { - const response = await axios.post('/messages', data); - return response.data; - } catch (error) { - throw error; - } - }, - - getUnreadCount: async (): Promise => { - try { - const response = await axios.get('/messages/count/unread'); - return response.data; - } catch (error) { - throw error; - } - }, - - markAsRead: async (id: number): Promise => { - try { - const response = await axios.post(`/messages/${id}/read`); - return response.data; - } catch (error) { - throw error; - } - }, - - deleteMessage: async (id: number): Promise => { - try { - const response = await axios.delete(`/messages/${id}`); - return response.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/modbus_rtu_device.ts b/src/client/admin/api/modbus_rtu_device.ts deleted file mode 100644 index 9f7f35b..0000000 --- a/src/client/admin/api/modbus_rtu_device.ts +++ /dev/null @@ -1,47 +0,0 @@ -import axios from 'axios'; - -export interface DeviceMonitorData { - id: number; - device_id: number; - device_name: string; - protocol: string; - address: string; - metric_type: string; - metric_value: number; - unit?: string; - status: string; - collect_time: Date; -} - -export const ModbusRtuDeviceAPI = { - // 获取Modbus RTU设备监控数据 - getMonitorData: async (params: { - page?: number; - pageSize?: number; - device_id?: number; - device_name?: string; - protocol?: string; - address?: string; - metric_type?: string; - status?: string; - }) => { - const response = await axios.get('/modbus-rtu-device/monitor-data', { params }); - return { - data: response.data.data || [], - total: response.data.total || 0, - }; - }, - - // 测试Modbus RTU设备连接 - testConnection: async (data: { - protocol: string; - address: string; - baud_rate: number; - data_bits: number; - stop_bits: number; - parity: string; - }) => { - const response = await axios.post('/modbus-rtu-device/test-connection', data); - return response.data; - }, -}; \ No newline at end of file diff --git a/src/client/admin/api/monitor.ts b/src/client/admin/api/monitor.ts deleted file mode 100644 index 7145352..0000000 --- a/src/client/admin/api/monitor.ts +++ /dev/null @@ -1,179 +0,0 @@ -import axios from 'axios'; -import { DeviceMapStats, DeviceMonitorData, DeviceStatus, DeviceTreeNode, DeviceTreeStats, MapViewDevice } from "@/share/monitorTypes"; - -interface DeviceMonitorDataResponse { - data: DeviceMonitorData[]; - total: number; - page: number; - pageSize: number; - } - - interface DeviceMonitorResponse { - data: DeviceMonitorData; - message?: string; - } - - interface MonitorCreateResponse { - data: DeviceMonitorData; - message: string; - } - - interface MonitorUpdateResponse { - data: DeviceMonitorData; - message: string; - } - - interface MonitorDeleteResponse { - message: string; - } - -// 监控API接口定义 -export const MonitorAPI = { - // 获取监控数据 - getMonitorData: async (params?: { - page?: number, - limit?: number, - device_id?: number, - device_type?: string, - start_time?: string, - end_time?: string - }): Promise => { - try { - const response = await axios.get(`/monitor/data`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取设备树数据 - getDeviceTree: async (params?: { - status?: string, - keyword?: string - }): Promise<{ data: DeviceTreeNode[] }> => { - try { - const response = await axios.get(`/monitor/devices/tree`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取设备树统计数据 - getDeviceTreeStats: async (): Promise<{ data: DeviceTreeStats }> => { - try { - const response = await axios.get(`/monitor/devices/tree/statistics`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取设备地图数据 - getDeviceMapData: async (params?: { - type_code?: string, - device_status?: DeviceStatus, - keyword?: string, - device_id?: number - }): Promise<{ data: MapViewDevice[], stats: DeviceMapStats }> => { - try { - const response = await axios.get(`/monitor/devices/map`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个监控数据 - getMonitor: async (id: number): Promise => { - try { - const response = await axios.get(`/monitor/data/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建监控数据 - createMonitor: async (data: Partial): Promise => { - try { - const response = await axios.post(`/monitor/data`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新监控数据 - updateMonitor: async (id: number, data: Partial): Promise => { - try { - const response = await axios.put(`/monitor/data/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除监控数据 - deleteMonitor: async (id: number): Promise => { - try { - const response = await axios.delete(`/monitor/data/${id}`); - return response.data; - } catch (error) { - throw error; - } - } - }; - - // 获取烟雾/水浸传感器状态 - export async function getDeviceStatus(params: { - device_id: number; - device_type: 'smoke' | 'water'; - }): Promise<{ - status: 0 | 1; - timestamp: string; - }> { - try { - const response = await axios.get(`/monitor/devices/smoke-water/status`, { params }); - return response.data; - } catch (error) { - throw error; - } - } - - // 获取烟雾/水浸传感器历史数据 - export async function getDeviceHistory(params: { - device_id: number; - device_type: 'smoke' | 'water'; - start_time: string; - end_time: string; - interval?: number; - }): Promise<{ - data: Array<{ - timestamp: string; - status: 0 | 1; - }>; - }> { - try { - const response = await axios.get(`/monitor/devices/smoke-water/history`, { params }); - return response.data; - } catch (error) { - throw error; - } - } - - // 获取最新温湿度数据 - export async function getLatestTemperatureHumidity(params: { - device_id?: number; - } = {}): Promise<{ - temperature: number; - humidity: number; - timestamp: string; - }> { - try { - const response = await axios.get(`/monitor/data/latest-temperature-humidity`, { params }); - return response.data; - } catch (error) { - throw error; - } - } \ No newline at end of file diff --git a/src/client/admin/api/monitor_charts.ts b/src/client/admin/api/monitor_charts.ts deleted file mode 100644 index 4b9107d..0000000 --- a/src/client/admin/api/monitor_charts.ts +++ /dev/null @@ -1,69 +0,0 @@ -import axios from 'axios'; -import { AlarmChartData, CategoryChartData, CategoryChartDataWithPercent, OnlineRateChartData, StateChartData, StateChartDataWithPercent } from "@/share/monitorTypes"; - -export const MonitorChartsAPI = { - // 资产分类数据查询 - fetchCategoryData: async (): Promise => { - const res = await axios.get(`/big/zichan_category_chart`); - - // 预先计算百分比 - const data = res.data; - const total = data.reduce((sum: number, item: CategoryChartData) => sum + item['设备数'], 0); - - // 为每个数据项添加百分比字段 - return data.map(item => ({ - ...item, - 百分比: total > 0 ? (item['设备数'] / total * 100).toFixed(1) : '0' - })); - }, - - // 在线率变化数据查询 - fetchOnlineRateData: async (params?: { - created_at_gte?: string; - created_at_lte?: string; - dimension?: string; - }): Promise => { - // 可选参数 - // const params = { - // created_at_gte: dayjs().subtract(7, 'day').format('YYYY-MM-DD HH:mm:ss'), - // created_at_lte: dayjs().format('YYYY-MM-DD HH:mm:ss'), - // dimension: 'day' - // }; - - const res = await axios.get(`/big/zichan_online_rate_chart`, { params }); - return res.data; - }, - - // 资产流转状态数据查询 - fetchStateData: async (): Promise => { - const res = await axios.get(`/big/zichan_state_chart`); - - // 预先计算百分比 - const data = res.data; - const total = data.reduce((sum: number, item: StateChartData) => sum + item['设备数'], 0); - - // 为每个数据项添加百分比字段 - return data.map(item => ({ - ...item, - 百分比: total > 0 ? (item['设备数'] / total * 100).toFixed(1) : '0' - })); - }, - - // 告警数据变化查询 - fetchAlarmData: async (params?: { - created_at_gte?: string; - created_at_lte?: string; - dimension?: string; - }): Promise => { - // 可选参数 - // const params = { - // created_at_gte: dayjs().startOf('day').format('YYYY-MM-DD HH:mm:ss'), - // created_at_lte: dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss'), - // dimension: 'hour' - // }; - - - const res = await axios.get(`/big/zichan_alarm_chart`, { params }); - return res.data; - } - }; \ No newline at end of file diff --git a/src/client/admin/api/rack.ts b/src/client/admin/api/rack.ts deleted file mode 100644 index 73633e0..0000000 --- a/src/client/admin/api/rack.ts +++ /dev/null @@ -1,60 +0,0 @@ -import axios from 'axios'; -import { RackInfo } from "@/share/monitorTypes"; -// 机柜管理API接口定义 -export const RackAPI = { - // 获取机柜列表 - getRackList: async (params?: { - page?: number, - limit?: number, - rack_name?: string, - rack_code?: string, - area?: string - }) => { - try { - const response = await axios.get(`/racks`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个机柜信息 - getRack: async (id: number) => { - try { - const response = await axios.get(`/racks/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建机柜 - createRack: async (data: Partial) => { - try { - const response = await axios.post(`/racks`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新机柜 - updateRack: async (id: number, data: Partial) => { - try { - const response = await axios.put(`/racks/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除机柜 - deleteRack: async (id: number) => { - try { - const response = await axios.delete(`/racks/${id}`); - return response.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/rack_server.ts b/src/client/admin/api/rack_server.ts deleted file mode 100644 index da94483..0000000 --- a/src/client/admin/api/rack_server.ts +++ /dev/null @@ -1,60 +0,0 @@ -import axios from 'axios'; -import { RackServer } from "@/share/monitorTypes"; -// 机柜服务器API接口定义 -export const RackServerAPI = { - // 获取机柜服务器列表 - getRackServerList: async (params?: { - page?: number, - limit?: number, - rack_id?: number, - asset_id?: number, - server_type?: string - }) => { - try { - const response = await axios.get(`/rack-servers`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个机柜服务器信息 - getRackServer: async (id: number) => { - try { - const response = await axios.get(`/rack-servers/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建机柜服务器 - createRackServer: async (data: Partial) => { - try { - const response = await axios.post(`/rack-servers`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新机柜服务器 - updateRackServer: async (id: number, data: Partial) => { - try { - const response = await axios.put(`/rack-servers/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除机柜服务器 - deleteRackServer: async (id: number) => { - try { - const response = await axios.delete(`/rack-servers/${id}`); - return response.data; - } catch (error) { - throw error; - } - } - }; \ No newline at end of file diff --git a/src/client/admin/api/rack_server_type.ts b/src/client/admin/api/rack_server_type.ts deleted file mode 100644 index e5fc415..0000000 --- a/src/client/admin/api/rack_server_type.ts +++ /dev/null @@ -1,69 +0,0 @@ -import axios from 'axios'; -import { RackServerType } from "@/share/monitorTypes"; - -// 机柜服务器类型API响应类型 -interface RackServerTypeResponse { - data: RackServerType[]; - pagination: { - total: number; - current: number; - pageSize: number; - }; - } -// 机柜服务器类型API接口定义 -export const RackServerTypeAPI = { - // 获取机柜服务器类型列表 - getRackServerTypeList: async (params?: { - page?: number, - limit?: number, - name?: string, - code?: string - }): Promise => { - try { - const response = await axios.get(`/rack-server-types`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个机柜服务器类型信息 - getRackServerType: async (id: number) => { - try { - const response = await axios.get(`/rack-server-types/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建机柜服务器类型 - createRackServerType: async (data: Partial) => { - try { - const response = await axios.post(`/rack-server-types`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新机柜服务器类型 - updateRackServerType: async (id: number, data: Partial) => { - try { - const response = await axios.put(`/rack-server-types/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除机柜服务器类型 - deleteRackServerType: async (id: number) => { - try { - const response = await axios.delete(`/rack-server-types/${id}`); - return response.data; - } catch (error) { - throw error; - } - } - }; \ No newline at end of file diff --git a/src/client/admin/api/sms.ts b/src/client/admin/api/sms.ts deleted file mode 100644 index c5ce2a3..0000000 --- a/src/client/admin/api/sms.ts +++ /dev/null @@ -1,25 +0,0 @@ -import axios from 'axios' - -export const smsApi = { - checkLogin: () => axios.get('/sms/check-login'), - login: (data: { username: string; password: string }) => - axios.post('/sms/login', data), - send: (data: { phone: string; content: string; taskId?: string }) => - axios.post('/sms/send', data), - getStatus: () => axios.get('/sms/status'), - getList: () => axios.get('/sms/list') -} - -export type SmsStatus = { - signalStrength: number - carrier: string - mode: string -} - -export type SmsItem = { - id: string - phone: string - content: string - status: string - createdAt: string -} \ No newline at end of file diff --git a/src/client/admin/api/sys.ts b/src/client/admin/api/sys.ts deleted file mode 100644 index 9f70dd6..0000000 --- a/src/client/admin/api/sys.ts +++ /dev/null @@ -1,47 +0,0 @@ -import axios from 'axios'; - -import type { - SystemSetting, SystemSettingGroupData, -} from '../@/share/types'; - -export const SystemAPI = { - // 获取所有系统设置 - getSettings: async (): Promise => { - try { - const response = await axios.get('/settings'); - return response.data.data; - } catch (error) { - throw error; - } - }, - - // 获取指定分组的系统设置 - getSettingsByGroup: async (group: string): Promise => { - try { - const response = await axios.get(`/settings/group/${group}`); - return response.data.data; - } catch (error) { - throw error; - } - }, - - // 更新系统设置 - updateSettings: async (settings: Partial[]): Promise => { - try { - const response = await axios.put('/settings', settings); - return response.data.data; - } catch (error) { - throw error; - } - }, - - // 重置系统设置 - resetSettings: async (): Promise => { - try { - const response = await axios.post('/settings/reset'); - return response.data.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/theme.ts b/src/client/admin/api/theme.ts deleted file mode 100644 index b2fc8a5..0000000 --- a/src/client/admin/api/theme.ts +++ /dev/null @@ -1,36 +0,0 @@ -import axios from 'axios'; -import type { ThemeSettings } from '@/share/types'; - -export interface ThemeSettingsResponse { - message: string; - data: ThemeSettings; -} - -export const ThemeAPI = { - getThemeSettings: async (): Promise => { - try { - const response = await axios.get('/theme'); - return response.data.data; - } catch (error) { - throw error; - } - }, - - updateThemeSettings: async (themeData: Partial): Promise => { - try { - const response = await axios.put('/theme', themeData); - return response.data.data; - } catch (error) { - throw error; - } - }, - - resetThemeSettings: async (): Promise => { - try { - const response = await axios.post('/theme/reset'); - return response.data.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/users.ts b/src/client/admin/api/users.ts deleted file mode 100644 index f0aa3b5..0000000 --- a/src/client/admin/api/users.ts +++ /dev/null @@ -1,79 +0,0 @@ -import axios from 'axios'; -import type { User } from '../@/share/types'; - -interface UsersResponse { - data: User[]; - pagination: { - total: number; - current: number; - pageSize: number; - totalPages: number; - }; -} - -interface UserResponse { - data: User; - message?: string; -} - -interface UserCreateResponse { - message: string; - data: User; -} - -interface UserUpdateResponse { - message: string; - data: User; -} - -interface UserDeleteResponse { - message: string; - id: number; -} - -export const UserAPI = { - getUsers: async (params?: { page?: number, limit?: number, search?: string }): Promise => { - try { - const response = await axios.get('/users', { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - getUser: async (userId: number): Promise => { - try { - const response = await axios.get(`/users/${userId}`); - return response.data; - } catch (error) { - throw error; - } - }, - - createUser: async (userData: Partial): Promise => { - try { - const response = await axios.post('/users', userData); - return response.data; - } catch (error) { - throw error; - } - }, - - updateUser: async (userId: number, userData: Partial): Promise => { - try { - const response = await axios.put(`/users/${userId}`, userData); - return response.data; - } catch (error) { - throw error; - } - }, - - deleteUser: async (userId: number): Promise => { - try { - const response = await axios.delete(`/users/${userId}`); - return response.data; - } catch (error) { - throw error; - } - } -}; \ No newline at end of file diff --git a/src/client/admin/api/work_orders.ts b/src/client/admin/api/work_orders.ts deleted file mode 100644 index 738bc57..0000000 --- a/src/client/admin/api/work_orders.ts +++ /dev/null @@ -1,308 +0,0 @@ -import axios from 'axios'; -import { WorkOrder, WorkOrderSettings, WorkOrderStatus, WorkOrderPriority } from '@/share/monitorTypes' - -// 分类数据缓存 -let categoriesCache: string[] | null = null; -let cacheExpireTime = 0; -const CACHE_EXPIRE_DURATION = 5 * 60 * 1000; // 5分钟缓存 - -interface WorkOrderListParams { - page?: number; - pageSize?: number; - status?: WorkOrderStatus; - priority?: WorkOrderPriority; - device_id?: number; - creator_id?: number; -} - -interface WorkOrderListResponse { - data: WorkOrder[]; - pagination: { - total: number; - current: number; - pageSize: number; - totalPages: number; - }; -} - -interface WorkOrderDetailResponse { - data: WorkOrder; - message?: string; -} - -interface WorkOrderCreateResponse { - message: string; - data: WorkOrder; -} - -interface WorkOrderUpdateResponse { - message: string; - data: WorkOrder; -} - -interface WorkOrderStatusChangeResponse { - message: string; - status: string; - history_id?: string; -} - -interface WorkOrderDeadlineResponse { - data: { - deadline: string; - remaining_hours: number; - is_overdue: boolean; - }; -} - -interface WorkOrderHistoryItem { - id: string; - status_from: string; - status_to: string; - operator: string; - comment?: string; - created_at: string; -} - -interface WorkOrderHistoryResponse { - data: WorkOrderHistoryItem[]; - pagination: { - total: number; - current: number; - pageSize: number; - }; -} - -interface WorkOrderAssignResponse { - message: string; - assignee: string; -} - -interface WorkOrderSettingsResponse { - data: WorkOrderSettings; - message?: string; -} - -interface WorkOrderCategoryResponse { - data: string[]; - message?: string; -} - -interface WorkOrderAttachmentResponse { - message: string; - data: { - id: string; - url: string; - name: string; - }; -} - -interface WorkOrderCommentResponse { - message: string; - data: { - id: string; - content: string; - created_at: string; - author: string; - }[]; -} - -export const WorkOrderAPI = { - getList: async (params?: WorkOrderListParams): Promise => { - try { - const response = await axios.get('/work-orders', { params }); - return response.data; - } catch (error) { - if (axios.isAxiosError(error)) { - const errorMessage = error.response?.data?.message || error.message; - throw new Error(`获取工单列表失败: ${errorMessage}`); - } - throw new Error('获取工单列表失败: 未知错误'); - } - }, - - create: async (data: { - title: string; - device_id?: number; - problem_desc: string; - problem_type: string; - priority: WorkOrderPriority; - deadline?: Date; - attachments?: Array<{ - id: string; - url: string; - name: string; - }>; - }): Promise => { - try { - const response = await axios.post('/work-orders', data); - return response.data; - } catch (error) { - throw error; - } - }, - - getDetail: async (id: string): Promise => { - try { - const response = await axios.get(`/work-orders/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - update: async (id: string, data: { - status?: WorkOrderStatus; - priority?: WorkOrderPriority; - feedback?: string; - assignee_id?: number; - deadline?: Date; - }): Promise => { - try { - const response = await axios.put(`/work-orders/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - changeStatus: async (id: string, status: string, operator: string, comment?: string): Promise => { - try { - const response = await axios.post(`/work-orders/${id}/status`, { - status, - operator, - comment - }); - return response.data; - } catch (error) { - throw error; - } - }, - - getDeadline: async (id: string): Promise => { - try { - const response = await axios.get(`/work-orders/${id}/deadline`); - return response.data; - } catch (error) { - throw error; - } - }, - - getHistory: async (id: string, page = 1, pageSize = 10): Promise => { - try { - const response = await axios.get(`/work-orders/${id}/history`, { - params: { page, pageSize } - }); - return response.data; - } catch (error) { - throw error; - } - }, - - getStatusHistory: async (id: string): Promise => { - try { - const response = await axios.get(`/work-orders/${id}/status-history`); - return response.data; - } catch (error) { - throw error; - } - }, - - assign: async (id: string, assignee: string): Promise => { - try { - const response = await axios.post(`/work-orders/${id}/assign`, { assignee }); - return response.data; - } catch (error) { - throw error; - } - }, - - getSettings: async (): Promise => { - try { - const response = await axios.get('/work-orders/settings'); - return response.data; - } catch (error) { - throw error; - } - }, - - updateSettings: async (data: WorkOrderSettings): Promise => { - try { - const response = await axios.post('/work-orders/settings', data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 新增分类相关API - getCategories: async (): Promise => { - // 检查缓存是否有效 - if (categoriesCache && Date.now() < cacheExpireTime) { - return { data: categoriesCache }; - } - - try { - const response = await axios.get('/work-orders/categories'); - categoriesCache = response.data.data; - cacheExpireTime = Date.now() + CACHE_EXPIRE_DURATION; - return response.data; - } catch (error) { - if (axios.isAxiosError(error)) { - const errorMessage = error.response?.data?.message || error.message; - throw new Error(`获取分类失败: ${errorMessage}`); - } - throw new Error('获取分类失败: 未知错误'); - } - }, - - // 新增附件相关API - uploadAttachment: async (id: string, file: File): Promise => { - try { - const formData = new FormData(); - formData.append('file', file); - const response = await axios.post(`/work-orders/${id}/attachments`, formData, { - headers: { - 'Content-Type': 'multipart/form-data' - } - }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 新增评论相关API - getComments: async (id: string): Promise => { - try { - const response = await axios.get(`/work-orders/${id}/comments`); - return response.data; - } catch (error) { - throw error; - } - }, - - addComment: async (id: string, content: string): Promise => { - try { - const response = await axios.post(`/work-orders/${id}/comments`, { content }); - return response.data; - } catch (error) { - throw error; - } - }, - - exportList: async (params?: WorkOrderListParams): Promise => { - try { - const response = await axios.get('/work-orders/export', { - params, - responseType: 'blob' - }); - return response.data; - } catch (error) { - if (axios.isAxiosError(error)) { - const errorMessage = error.response?.data?.message || error.message; - throw new Error(`导出工单失败: ${errorMessage}`); - } - throw new Error('导出工单失败: 未知错误'); - } - }, -}; \ No newline at end of file diff --git a/src/client/admin/api/yangantubiao.png b/src/client/admin/api/yangantubiao.png deleted file mode 100644 index ed79dcb..0000000 Binary files a/src/client/admin/api/yangantubiao.png and /dev/null differ diff --git a/src/client/admin/api/zichan.ts b/src/client/admin/api/zichan.ts deleted file mode 100644 index 5af80f4..0000000 --- a/src/client/admin/api/zichan.ts +++ /dev/null @@ -1,61 +0,0 @@ -import axios from "axios"; -import { DeviceCategory, DeviceStatus, ZichanInfo } from "@/share/monitorTypes"; - -// 资产管理API -export const ZichanAPI = { - // 获取资产列表 - getZichanList: async (params?: { - page?: number, - limit?: number, - asset_name?: string, - device_category?: DeviceCategory, - device_status?: DeviceStatus - }) => { - try { - const response = await axios.get(`/zichan`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个资产 - getZichan: async (id: number) => { - try { - const response = await axios.get(`/zichan/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建资产 - createZichan: async (data: Partial) => { - try { - const response = await axios.post(`/zichan`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新资产 - updateZichan: async (id: number, data: Partial) => { - try { - const response = await axios.put(`/zichan/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除资产 - deleteZichan: async (id: number) => { - try { - const response = await axios.delete(`/zichan/${id}`); - return response.data; - } catch (error) { - throw error; - } - } - }; \ No newline at end of file diff --git a/src/client/admin/api/zichan_area.ts b/src/client/admin/api/zichan_area.ts deleted file mode 100644 index a294878..0000000 --- a/src/client/admin/api/zichan_area.ts +++ /dev/null @@ -1,60 +0,0 @@ -import axios from "axios"; -import { ZichanArea } from "@/share/monitorTypes"; - -// 资产归属区域API接口定义 -export const ZichanAreaAPI = { - // 获取资产归属区域列表 - getZichanAreaList: async (params?: { - page?: number, - limit?: number, - name?: string, - code?: string - }) => { - try { - const response = await axios.get(`/zichan-areas`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个资产归属区域信息 - getZichanArea: async (id: number) => { - try { - const response = await axios.get(`/zichan-areas/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建资产归属区域 - createZichanArea: async (data: Partial) => { - try { - const response = await axios.post(`/zichan-areas`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新资产归属区域 - updateZichanArea: async (id: number, data: Partial) => { - try { - const response = await axios.put(`/zichan-areas/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除资产归属区域 - deleteZichanArea: async (id: number) => { - try { - const response = await axios.delete(`/zichan-areas/${id}`); - return response.data; - } catch (error) { - throw error; - } - } - }; \ No newline at end of file diff --git a/src/client/admin/api/zichan_category.ts b/src/client/admin/api/zichan_category.ts deleted file mode 100644 index b012d63..0000000 --- a/src/client/admin/api/zichan_category.ts +++ /dev/null @@ -1,60 +0,0 @@ -import axios from "axios"; -import { ZichanCategory } from "@/share/monitorTypes"; - -// 资产分类API接口定义 -export const ZichanCategoryAPI = { - // 获取资产分类列表 - getZichanCategoryList: async (params?: { - page?: number, - limit?: number, - name?: string, - code?: string - }) => { - try { - const response = await axios.get(`/zichan-categories`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取单个资产分类信息 - getZichanCategory: async (id: number) => { - try { - const response = await axios.get(`/zichan-categories/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建资产分类 - createZichanCategory: async (data: Partial) => { - try { - const response = await axios.post(`/zichan-categories`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新资产分类 - updateZichanCategory: async (id: number, data: Partial) => { - try { - const response = await axios.put(`/zichan-categories/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除资产分类 - deleteZichanCategory: async (id: number) => { - try { - const response = await axios.delete(`/zichan-categories/${id}`); - return response.data; - } catch (error) { - throw error; - } - } - }; \ No newline at end of file diff --git a/src/client/admin/api/zichan_transfer.ts b/src/client/admin/api/zichan_transfer.ts deleted file mode 100644 index 2bcb74e..0000000 --- a/src/client/admin/api/zichan_transfer.ts +++ /dev/null @@ -1,54 +0,0 @@ -import axios from "axios"; -import { AssetTransferType, ZichanTransLog } from "@/share/monitorTypes"; -// 资产流转API接口定义 -export const ZichanTransferAPI = { - // 获取资产流转记录列表 - getTransferList: async (params?: { page?: number, limit?: number, asset_id?: number, asset_transfer?: AssetTransferType }) => { - try { - const response = await axios.get(`/zichan-transfer`, { params }); - return response.data; - } catch (error) { - throw error; - } - }, - - // 获取资产流转记录详情 - getTransfer: async (id: number) => { - try { - const response = await axios.get(`/zichan-transfer/${id}`); - return response.data; - } catch (error) { - throw error; - } - }, - - // 创建资产流转记录 - createTransfer: async (data: Partial) => { - try { - const response = await axios.post(`/zichan-transfer`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 更新资产流转记录 - updateTransfer: async (id: number, data: Partial) => { - try { - const response = await axios.put(`/zichan-transfer/${id}`, data); - return response.data; - } catch (error) { - throw error; - } - }, - - // 删除资产流转记录 - deleteTransfer: async (id: number) => { - try { - const response = await axios.delete(`/zichan-transfer/${id}`); - return response.data; - } catch (error) { - throw error; - } - } - }; \ No newline at end of file diff --git a/src/client/big/api.ts b/src/client/big/api.ts deleted file mode 100644 index 441aaa9..0000000 --- a/src/client/big/api.ts +++ /dev/null @@ -1,381 +0,0 @@ -import axios from 'axios'; -import * as THREE from 'three'; -import { - AlarmDeviceData, - CategoryChartData, - CategoryChartDataWithPercent, - OnlineRateChartData, - StateChartData, - StateChartDataWithPercent, - AlarmChartData, - DeviceWithAssetInfo, -} from '@/share/monitorTypes'; - - -// API请求参数类型定义 -interface OnlineRateChartParams { - created_at?: { - $gte: string; - $lte: string; - }; - dimension?: { - $eq: 'hour' | 'day' | 'month'; - }; - pagination?: { - page: number; - pageSize: number; - }; -} - -interface AlarmChartParams { - created_at?: { - $gte: string; - $lte: string; - }; - dimension?: { - $eq: 'hour' | 'day' | 'month'; - }; -} - -interface DeviceInstancesParams { - is_deleted?: number; -} - -interface RackQueryParams { - is_deleted?: number; -} - -interface RackServerQueryParams { - rack_id?: number; - is_deleted?: number; -} - -interface RackServerTypeParams { - is_enabled?: number; - is_deleted?: number; - page?: number; - pageSize?: number; -} - -// 机柜数据 -interface RackData { - id: number; - rack_name: string; - rack_code: string; - capacity: number; - position_x: number; - position_y: number; - position_z: number; - area?: string; - room?: string; - remark?: string; - is_disabled: number; - is_deleted: number; - created_at: string; - updated_at: string; -} - -// 机柜服务器数据 -interface RackServerData { - id: number; - rack_id: number; - asset_id: number; - start_position: number; - size: number; - server_type?: string; - remark?: string; - is_disabled: number; - is_deleted: number; - created_at: string; - updated_at: string; - // 关联字段 asset - asset_name: string; - device_category: number; - ip_address?: string; - device_status: number; - network_status: number; - packet_loss: number; - cpu?: string; - memory?: string; - disk?: string; - // 关联字段 rack - rack_name: string; - rack_code: string; -} - -// 设备类型图标数据 -interface DeviceIconData { - id: number; - category_id: number; - icon: string; - icon_name?: string; - icon_type: string; - sort: number; - is_default: number; - is_disabled: number; - is_deleted: number; - created_at: string; - updated_at: string; - category?: { - name: string; - }; -} - -// 机柜服务器类型数据 -interface RackServerType { - /** 主键ID */ - id: number; - - /** 类型名称 */ - name: string; - - /** 类型编码 */ - code: string; - - /** 类型图片 */ - image_url?: string; - - /** 类型描述 */ - description?: string; - - /** 是否启用 (0否 1是) */ - is_enabled?: number; - - /** 是否被删除 (0否 1是) */ - is_deleted?: number; - - /** 创建时间 */ - created_at: string; - - /** 更新时间 */ - updated_at: string; -} - -// 服务器基本信息接口 -export interface ServerData { - id: number; - slot: number; - u: number; - type: number; - name: string; - ip: string; - cpu: string; - memory: string; - disk: string; - deviceStatus: number; - networkStatus: number; - packetLoss: number; -} - -// 设备状态和监控数据接口 -export interface DeviceStatusInfo { - status: 'online' | 'offline' | 'warning'; - usage: { - cpu: number; - memory: number; - disk: number; - }; -} - -// 机柜配置接口 -export interface RackConfig { - position: THREE.Vector3; - serverCount: number; - id: number; - name: string; - servers: ServerData[]; -} - -// 服务器图标接口 -export interface ServerIconConfig { - textureUrl: string | null; - color: number; -} - -export interface ServerIconConfigs { - [key: number]: ServerIconConfig; -} - - - - -const API_BASE_URL = '/api'; -// 从全局配置中获取OSS_HOST,如果不存在则使用默认值 -const OSS_BASE_URL = window.CONFIG?.OSS_BASE_URL || ''; - - -// 计算风险等级 -const calculateRiskLevel = (onlineRate: number): { level: string; color: string } => { - if (onlineRate >= 95) { - return { level: '健康', color: '#52c41a' }; // 绿色 - } else if (onlineRate >= 80) { - return { level: '风险低', color: '#faad14' }; // 黄色 - } else if (onlineRate >= 70) { - return { level: '风险中', color: '#faad14' }; // 黄色 - } else { - return { level: '高风险', color: '#f5222d' }; // 红色 - } -}; - -// 统一将查询函数提取到顶部 -export const queryFns = { - // 资产分类数据查询 - fetchCategoryData: async (): Promise => { - const res = await axios.get(`${API_BASE_URL}/big/zichan_category_chart`); - - // 预先计算百分比 - const data = res.data; - const total = data.reduce((sum: number, item: CategoryChartData) => sum + item['设备数'], 0); - - // 为每个数据项添加百分比字段 - return data.map(item => ({ - ...item, - 百分比: total > 0 ? (item['设备数'] / total * 100).toFixed(1) : '0' - })); - }, - - // 在线率变化数据查询 - fetchOnlineRateData: async (): Promise => { - // 直接使用扁平化参数 - const params = { - // created_at_gte: dayjs().subtract(7, 'day').format('YYYY-MM-DD HH:mm:ss'), - // created_at_lte: dayjs().format('YYYY-MM-DD HH:mm:ss'), - // dimension: 'day', - // page: 1, - // pageSize: 1000 - }; - - const res = await axios.get(`${API_BASE_URL}/big/zichan_online_rate_chart`, { params }); - return res.data; - }, - - // 资产流转状态数据查询 - fetchStateData: async (): Promise => { - const res = await axios.get(`${API_BASE_URL}/big/zichan_state_chart`); - - // 预先计算百分比 - const data = res.data; - const total = data.reduce((sum: number, item: StateChartData) => sum + item['设备数'], 0); - - // 为每个数据项添加百分比字段 - return data.map(item => ({ - ...item, - 百分比: total > 0 ? (item['设备数'] / total * 100).toFixed(1) : '0' - })); - }, - - // 告警数据变化查询 - fetchAlarmData: async (): Promise => { - // 直接使用扁平化参数 - const params = { - // created_at_gte: dayjs().startOf('day').format('YYYY-MM-DD HH:mm:ss'), - // created_at_lte: dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss'), - // dimension: 'hour' - }; - - const res = await axios.get(`${API_BASE_URL}/big/zichan_alarm_chart`, { params }); - return res.data; - }, - - // 获取设备数据 - fetchDeviceMetrics: async () => { - const params = { - is_deleted: 0 - }; - const response = await axios.get(`${API_BASE_URL}/big/device-instances`, { params }); - - const devices = response.data; - const totalDevices = devices.length; - const onlineDevices = devices.filter(device => device.device_status === 1).length; - const offlineDevices = totalDevices - onlineDevices; - const onlineRate = totalDevices ? ((onlineDevices / totalDevices) * 100) : 0; - const riskLevel = calculateRiskLevel(onlineRate); - - return { - totalDevices, - onlineDevices, - offlineDevices, - onlineRate: onlineRate.toFixed(2), - riskLevel - }; - }, - - // 获取告警设备数据 - fetchTopAlarmDevices: async (): Promise => { - const response = await axios.get(`${API_BASE_URL}/big/zichan_alarm_device`); - return response.data; - }, - - // 获取机柜配置数据 - fetchRackConfigs: async (): Promise => { - const params: RackQueryParams = { - is_deleted: 0 - } - // 1. 获取机柜数据 - const rackResponse = await axios.get(`${API_BASE_URL}/big/rack`, { params }); - - const racks = rackResponse.data; - - // 2. 获取所有机柜的服务器数据 - const serverPromises = racks.map(async (rack: RackData) => { - const params: RackServerQueryParams = { - rack_id: rack.id, - is_deleted: 0 - } - const serverResponse = await axios.get(`${API_BASE_URL}/big/rack-server`, { params }); - - // 3. 获取每个服务器对应的基本信息 - let servers: ServerData[] = []; - try { - servers = serverResponse.data.map((server: RackServerData) => ({ - id: server.id, - slot: server.start_position, - u: server.size, - type: server.device_category, - name: server.asset_name || '', - ip: server.ip_address || '', - cpu: server.cpu || '', - memory: server.memory || '', - disk: server.disk || '', - deviceStatus: server.device_status || 0, - networkStatus: server.network_status || 0, - packetLoss: server.packet_loss || 0 - })); - } catch (error) { - console.error("error", error); - } - - // 返回包含服务器数据的机柜配置 - return { - position: new THREE.Vector3(Number(rack.position_x) || 0, Number(rack.position_y) || 0, Number(rack.position_z) || 0), - serverCount: rack.capacity || 42, - id: rack.id, - name: rack.rack_name, - servers - }; - }); - - // 等待所有数据获取完成 - return Promise.all(serverPromises); - }, - - // 获取服务器类型图标配置 - fetchDeviceIcons: async (): Promise => { - const params: RackServerTypeParams = { - is_enabled: 1, - is_deleted: 0, - page: 1, - pageSize: 100 - } - const response = await axios.get(`${API_BASE_URL}/big/rack/server/type/image`, { params }); - - const ossHost = OSS_BASE_URL; - return response.data.reduce((acc: ServerIconConfigs, type: RackServerType) => { - acc[type.id] = { - textureUrl: type.image_url ? `${ossHost}/${type.image_url}` : null, - color: 0x444444 - }; - return acc; - }, {}); - } -} diff --git a/src/client/big/client.tsx b/src/client/big/client.tsx deleted file mode 100644 index 2fdb46a..0000000 --- a/src/client/big/client.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import { createRoot } from 'react-dom/client'; -import { DataCenterApp } from './components/DataCenter'; - -// 渲染应用 -const root = createRoot(document.getElementById('root') as HTMLElement); -root.render( - -); \ No newline at end of file diff --git a/src/client/big/components/AlarmDeviceTable.tsx b/src/client/big/components/AlarmDeviceTable.tsx deleted file mode 100644 index fb84656..0000000 --- a/src/client/big/components/AlarmDeviceTable.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from 'react'; -import { useQuery } from '@tanstack/react-query'; -import { AlarmDeviceData } from '@/share/monitorTypes'; -import { bigClient } from '../../api'; - -export function AlarmDeviceTable() { - const { data = [], isLoading } = useQuery({ - queryKey: ['topAlarmDevices'], - queryFn: async () => { - const res = await bigClient['zichan-alarm-device'].$get({ - query:{ limit: 100 } - }); - if (res.status !== 200) throw new Error('Failed to fetch alarm devices'); - return await res.json(); - }, - refetchInterval: 30000 - }); - - if (isLoading) { - return ( -
- 加载中... -
- ); - } - - return ( -
- {/* 表头 */} -
-
排名
-
告警次数
-
点位名称
-
- - {/* 表格内容 */} -
- {data.map((item: AlarmDeviceData) => ( -
-
{item.rank}
-
{item.alarmCount}
- - {item.deviceName} - -
- ))} - - {data.length === 0 && ( -
- 暂无数据 -
- )} -
-
- ); -} \ No newline at end of file diff --git a/src/client/big/components/CustomCard.tsx b/src/client/big/components/CustomCard.tsx deleted file mode 100644 index 843cd1d..0000000 --- a/src/client/big/components/CustomCard.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import React, { ReactNode } from 'react'; - -interface CustomCardProps { - title?: string; - children: ReactNode; - className?: string; - bodyStyle?: React.CSSProperties; - onClick?: () => void; -} - -export function CustomCard({ title, children, className = '', bodyStyle = {}, onClick }: CustomCardProps) { - return ( -
- {title && ( -
- {title} -
- )} -
- {children} -
-
- ); -} \ No newline at end of file diff --git a/src/client/big/components/DataCenter.tsx b/src/client/big/components/DataCenter.tsx deleted file mode 100644 index caebae7..0000000 --- a/src/client/big/components/DataCenter.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import React, { useState, useCallback } from 'react'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { FullscreenOutlined, FullscreenExitOutlined } from '@ant-design/icons'; -import { PageTitle } from './PageTitle'; -import { MetricCards } from './MetricCards'; -import { CustomCard } from './CustomCard'; -import { ServerMonitorCharts } from './ServerMonitorCharts'; -import { AlarmDeviceTable } from './AlarmDeviceTable'; -import { ThreeJSRoom } from './three/ThreeJSRoom'; - -const queryClient = new QueryClient(); - -export function DataCenter() { - const [isFullscreen, setIsFullscreen] = useState(false); - - const toggleFullscreen = useCallback(() => { - if (!document.fullscreenElement) { - document.documentElement.requestFullscreen(); - setIsFullscreen(true); - } else { - document.exitFullscreen().then(() => { - setIsFullscreen(false); - window.location.reload(); - }); - } - }, []); - - return ( -
- {/* 顶部标题区域 */} -
- - - {/* 全屏切换按钮 */} - -
- - {/* 主要内容区域 */} -
- {/* 顶部指标卡片 */} -
- -
- -
- {/* 左侧图表区域 */} -
-
- {/* 饼图 */} - -
- -
-
- - {/* 柱状图 */} - -
- -
-
- - {/* 饼图2 */} - -
- -
-
-
-
- - {/* 右侧区域 */} -
- {/* 中间3D机房区域 */} - -
- -
-
- - {/* 底部区域分为两列 */} -
- {/* 左侧告警曲线图 */} - -
- -
-
- - {/* 右侧告警设备表格 */} - -
- -
-
-
-
-
-
-
- ); -} - -export function DataCenterApp() { - return ( - - - - ); -} \ No newline at end of file diff --git a/src/client/big/components/MetricCards.tsx b/src/client/big/components/MetricCards.tsx deleted file mode 100644 index d11eadc..0000000 --- a/src/client/big/components/MetricCards.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import React from 'react'; -import { useQuery } from '@tanstack/react-query'; -import { Card } from 'antd'; -import { bigClient } from '../../api'; -import { calculateRiskLevel, handleNavigate } from './utils'; - -export function MetricCards() { - const { data: metrics = { - totalDevices: 0, - onlineDevices: 0, - offlineDevices: 0, - onlineRate: "0.00", - riskLevel: { level: '健康', color: '#52c41a' } - }, isLoading } = useQuery({ - queryKey: ['deviceMetrics'], - queryFn: async () => { - const res = await bigClient['device-instances'].$get({ - query: { is_deleted: 0 } - }); - if (res.status !== 200) throw new Error('Failed to fetch device metrics'); - - const data = await res.json(); - const devices = data.data; - const totalDevices = devices.length; - const onlineDevices = devices.filter((device: any) => device.device_status === 1).length; - const offlineDevices = totalDevices - onlineDevices; - const onlineRate = totalDevices ? ((onlineDevices / totalDevices) * 100) : 0; - const riskLevel = calculateRiskLevel(onlineRate); - - return { - totalDevices, - onlineDevices, - offlineDevices, - onlineRate: onlineRate.toFixed(2), - riskLevel - }; - }, - refetchInterval: 30000, - refetchIntervalInBackground: true - }); - - const metricConfigs = [ - { - title: "设备数", - value: metrics.totalDevices, - link: "/admin/alarm/manage" - }, - { - title: "正常数", - value: metrics.onlineDevices, - link: "/admin/alarm/manage" - }, - { - title: "在线率", - value: `${metrics.onlineRate}%`, - link: "/admin/device/rate" - }, - { - title: "异常数", - value: metrics.offlineDevices, - link: "/admin/alert/manage" - }, - { - title: "风险等级", - value: metrics.riskLevel.level, - color: metrics.riskLevel.color, - link: undefined - } - ]; - - return ( - <> - {metricConfigs.map((metric, index) => ( -
metric.link && handleNavigate(metric.link)} - className={metric.link ? "cursor-pointer" : undefined} - > - - {metric.title} - - {isLoading ? "-" : metric.value} - - -
- ))} - - ); -} \ No newline at end of file diff --git a/src/client/big/components/PageTitle.tsx b/src/client/big/components/PageTitle.tsx deleted file mode 100644 index 72ba72c..0000000 --- a/src/client/big/components/PageTitle.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { getGlobalConfig } from '@/client/admin/utils'; -import React from 'react'; - -export function PageTitle() { - return ( -
- {/* 背景图片 */} -
- title background -
-
- ); -} \ No newline at end of file diff --git a/src/client/big/components/ServerMonitorCharts.tsx b/src/client/big/components/ServerMonitorCharts.tsx deleted file mode 100644 index 509e53d..0000000 --- a/src/client/big/components/ServerMonitorCharts.tsx +++ /dev/null @@ -1,289 +0,0 @@ -import React from 'react'; -import { useQuery } from '@tanstack/react-query'; -import { Pie, Column, Line } from '@ant-design/plots'; -import { bigClient } from '../../api'; - -interface ServerMonitorChartsProps { - type?: 'pie' | 'column' | 'line' | 'pie2'; -} - -export function ServerMonitorCharts({ type = 'pie' }: ServerMonitorChartsProps) { - // 资产分类数据 - const { data: categoryData } = useQuery({ - queryKey: ['zichanCategory'], - queryFn: async () => { - const res = await bigClient.charts['zichan-category'].$get({ query:{} }); - if (res.status !== 200) throw new Error('Failed to fetch category data'); - const data = await res.json(); - const total = data.reduce((sum: number, item: any) => sum + item['设备数'], 0); - return data.map((item: any) => ({ - ...item, - 百分比: total > 0 ? (item['设备数'] / total * 100).toFixed(1) : '0' - })); - }, - enabled: type === 'pie' - }); - - // 在线率变化数据 - const { data: onlineRateData } = useQuery({ - queryKey: ['zichanOnlineRate'], - queryFn: async () => { - const res = await bigClient.charts['zichan-online-rate'].$get({ query:{} }); - if (res.status !== 200) throw new Error('Failed to fetch online rate data'); - return await res.json(); - }, - enabled: type === 'column' - }); - - // 资产流转状态数据 - const { data: stateData } = useQuery({ - queryKey: ['zichanState'], - queryFn: async () => { - const res = await bigClient.charts['zichan-state'].$get({ query:{} }); - if (res.status !== 200) throw new Error('Failed to fetch state data'); - const data = await res.json(); - const total = data.reduce((sum: number, item: any) => sum + item['设备数'], 0); - return data.map((item: any) => ({ - ...item, - 百分比: total > 0 ? (item['设备数'] / total * 100).toFixed(1) : '0' - })); - }, - enabled: type === 'pie2' - }); - - // 告警数据变化 - const { data: alarmData } = useQuery({ - queryKey: ['pingAlarm'], - queryFn: async () => { - const res = await bigClient.charts['zichan-alarm'].$get({ query:{} }); - if (res.status !== 200) throw new Error('Failed to fetch alarm data'); - return await res.json(); - }, - enabled: type === 'line' - }); - - const renderChart = () => { - switch (type) { - case 'pie': - return ( - { - // 只有占比超过5%的项才显示标签 - if (percent < 0.05) return null; - return `${设备分类}\n(${设备数})`; - }, - style: { - fill: '#fff', - fontSize: 12, - fontWeight: 500, - }, - transform: [{ type: 'overlapDodgeY' }], - }} - theme={{ - colors10: ['#36cfc9', '#ff4d4f', '#ffa940', '#73d13d', '#4096ff'], - }} - legend={false} - autoFit={true} - interaction={{ - tooltip: { - render: (_: any, { items, title }: { items: any[], title: string }) => { - if (!items || items.length === 0) return ''; - - // 获取当前选中项的数据 - const item = items[0]; - - // 根据value找到对应的完整数据项 - const fullData = categoryData?.find(d => d['设备数'] === item.value); - if (!fullData) return ''; - - return `
-
-
- ${fullData['设备分类']} -
-

数量: ${item.value}

-

占比: ${fullData['百分比']}%

-
`; - } - } - }} - /> - ); - case 'column': - return ( - { - let content = items['time_interval']; - content += `\n(${(items['total_devices'])})`; - return content; - }, - }} - xAxis={{ - label: { - style: { - fill: '#fff', - }, - }, - }} - yAxis={{ - label: { - style: { - fill: '#fff', - }, - }, - }} - autoFit={true} - interaction={{ - tooltip:false - }} - /> - ); - case 'line': - return ( - { - const value = items['total_devices']; - - // if (value === 0) return null; - - // const maxValue = Math.max(...(alarmData || []).map(item => item.total_devices)); - - // if (value < maxValue * 0.3 && alarmData && alarmData.length > 8) return null; - - return `${items['time_interval']}\n(${value})`; - }, - transform: [{ type: 'overlapDodgeY' }], - }} - xAxis={{ - label: { - style: { - fill: '#fff', - }, - autoHide: true, - autoRotate: true, - }, - }} - yAxis={{ - label: { - style: { - fill: '#fff', - }, - }, - }} - autoFit={true} - interaction={{ - tooltip: { - render: (_: any, { items, title }: { items: any[], title: string }) => { - if (!items || items.length === 0) return ''; - - // 获取当前选中项的数据 - const item = items[0]; - - // 根据value找到对应的完整数据项 - const fullData = alarmData?.find(d => d.total_devices === item.value); - if (!fullData) return ''; - - return `
-
-
- ${fullData.time_interval} -
-

数量: ${item.value}

-
`; - } - } - }} - /> - ); - case 'pie2': - return ( - { - // 只有占比超过5%的项才显示标签 - if (percent < 0.05) return null; - return `${资产流转}\n(${设备数})`; - }, - style: { - fill: '#fff', - fontSize: 12, - fontWeight: 500, - }, - transform: [{ type: 'overlapDodgeY' }], - }} - theme={{ - colors10: ['#36cfc9', '#ff4d4f', '#ffa940', '#73d13d', '#4096ff'], - }} - legend={{ - color: { - itemLabelFill: '#fff', - } - }} - autoFit={true} - interaction={{ - tooltip: { - render: (_: any, { items, title }: { items: any[], title: string }) => { - if (!items || items.length === 0) return ''; - - // 获取当前选中项的数据 - const item = items[0]; - - // 根据value找到对应的完整数据项 - const fullData = stateData?.find(d => d['设备数'] === item.value); - if (!fullData) return ''; - - return `
-
-
- ${fullData['资产流转']} -
-

数量: ${item.value}

-

占比: ${fullData['百分比']}%

-
`; - } - } - }} - /> - ); - } - }; - - return ( -
- {renderChart()} -
- ); -} \ No newline at end of file diff --git a/src/client/big/components/three/ServerTooltip.tsx b/src/client/big/components/three/ServerTooltip.tsx deleted file mode 100644 index c5505ae..0000000 --- a/src/client/big/components/three/ServerTooltip.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React from 'react'; -import type { ServerStatus } from './types'; -import { UI_STYLES } from './constants'; - -interface ServerTooltipProps { - status: ServerStatus; -} - - -export const ServerTooltip: React.FC = ({ status }) => { - return ( - -
-
- - - - - 资产信息 -
-
-
名称: {status.name}
-
IP地址: {status.ip}
-
- -
- - - - - - 网络状态 -
-
-
- 状态: -
- {status.networkStatus === 1 ? '在线' : '离线'} - -
-
-
丢包率: {status.packetLoss}%
-
- -
- - - - - - - 配置信息 -
-
-
CPU: {status.cpu || '-'}
-
内存: {status.memory || '-'}
-
硬盘: {status.disk || '-'}
-
-
- ); -}; \ No newline at end of file diff --git a/src/client/big/components/three/ThreeJSRoom.tsx b/src/client/big/components/three/ThreeJSRoom.tsx deleted file mode 100644 index e79cc71..0000000 --- a/src/client/big/components/three/ThreeJSRoom.tsx +++ /dev/null @@ -1,220 +0,0 @@ -import React, { useRef, useEffect } from 'react'; -import { useQuery } from '@tanstack/react-query'; -import * as THREE from 'three'; -import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; -import { ServerTooltip } from './ServerTooltip'; -import { useServerHover } from './utils'; -import { createFloor, ServerRack } from './models'; -import { COLORS } from './constants'; -import { bigClient } from '@/client/api'; -import { getGlobalConfig } from '@/client/admin/utils'; -import type { RackConfig, ServerData, ServerIconConfigs } from './types'; - -export function ThreeJSRoom() { - const containerRef = useRef(null); - const tooltipRef = useRef(null); - const racksRef = useRef([]); - const sceneRef = useRef<{ - scene: THREE.Scene; - camera: THREE.PerspectiveCamera; - renderer: THREE.WebGLRenderer; - controls: typeof OrbitControls; - cleanup: () => void; - } | null>(null); - - // 获取服务器类型图标 - const { data: rackServerTypes } = useQuery({ - queryKey: ['rackServerTypes'], - queryFn: async () => { - const res = await bigClient['rack-server-types'].$get({query:{}}); - if (res.status !== 200) throw new Error('Failed to fetch device icons'); - const data = await res.json(); - return data.data.reduce((acc: ServerIconConfigs, type) => { - acc[type.id] = { - textureUrl: type.imageUrl ? `${getGlobalConfig('OSS_BASE_URL')}/${type.imageUrl}` : null, - color: 0x444444 - }; - return acc; - }, {}); - } - }); - - // 获取机柜配置,添加自动刷新 - const { data: rackConfigs } = useQuery({ - queryKey: ['rackConfigs'], - queryFn: async () => { - const res = await bigClient['racks'].$get({query:{}}); - if (res.status !== 200) throw new Error('Failed to fetch rack configs'); - const racks = await res.json(); - - const serverPromises = racks.data.map(async (rack) => { - const serverResponse = await bigClient['rack-servers'].$get({ - query:{ - rackId: rack.id, - } - }); - - let servers:ServerData[] = []; - try { - if (serverResponse.status !== 200) throw new Error('Failed to fetch rack servers configs'); - const serverData = await serverResponse.json(); - servers = serverData.data.map((server) => ({ - id: server.id, - slot: server.startPosition, - u: server.size, - type: server.serverType || 0, - name: server.deviceInfo.zichanInfo?.assetName || '', - ip: server.deviceInfo.address || '', - cpu: server.deviceInfo.zichanInfo?.cpu || '', - memory: server.deviceInfo.zichanInfo?.memory || '', - disk: server.deviceInfo.zichanInfo?.disk || '', - deviceStatus: server.deviceInfo.zichanInfo?.deviceStatus || 0, - networkStatus: server.deviceInfo.zichanInfo?.networkStatus || 0, - packetLoss: server.deviceInfo.zichanInfo?.packetLoss || 0 - })); - } catch (error) { - console.error("error", error); - } - - return { - position: new THREE.Vector3(Number(rack.positionX) || 0, Number(rack.positionY) || 0, Number(rack.positionZ) || 0), - serverCount: rack.capacity || 42, - id: rack.id, - name: rack.rackName || '', - servers - }; - }); - - return Promise.all(serverPromises); - }, - refetchInterval: 30000, - refetchIntervalInBackground: true - }); - - // 初始化3D场景 - useEffect(() => { - if (!containerRef.current) return; - - // 初始化场景 - const scene = new THREE.Scene(); - scene.background = new THREE.Color(COLORS.BACKGROUND); - - const camera = new THREE.PerspectiveCamera( - 22, - containerRef.current.clientWidth / containerRef.current.clientHeight, - 0.1, - 1000 - ); - - const renderer = new THREE.WebGLRenderer({ antialias: true }); - renderer.setSize(containerRef.current.clientWidth, containerRef.current.clientHeight); - containerRef.current.appendChild(renderer.domElement); - - const controls = new OrbitControls(camera, renderer.domElement); - controls.enableDamping = true; - controls.maxPolarAngle = Math.PI / 2; - controls.minDistance = 6; - controls.maxDistance = 10; - controls.enablePan = false; - controls.target.set(0, 1, 0); - controls.enabled = false; - - // 添加地板 - const floor = createFloor(); - floor.position.y = -0.01; - scene.add(floor); - - // 设置场景光照 - const ambientLight = new THREE.AmbientLight(COLORS.LIGHTS.AMBIENT, 0.6); - scene.add(ambientLight); - - const directionalLight = new THREE.DirectionalLight(COLORS.LIGHTS.DIRECT, 0.8); - directionalLight.position.set(5, 5, 5); - scene.add(directionalLight); - - const spotLight = new THREE.SpotLight(COLORS.LIGHTS.SPOT, 0.8); - spotLight.position.set(0, 5, 0); - spotLight.angle = Math.PI / 4; - spotLight.penumbra = 0.1; - scene.add(spotLight); - - camera.position.set(0, 1, 1); - camera.lookAt(0, 1, 0); - - const { handleMouseMove, cleanup } = useServerHover({ - scene, - camera, - containerRef: containerRef as React.RefObject, - tooltipRef: tooltipRef as React.RefObject - }); - - containerRef.current.addEventListener('mousemove', handleMouseMove); - - // 动画循环 - const animate = () => { - requestAnimationFrame(animate); - controls.update(); - renderer.render(scene, camera); - }; - - animate(); - - // 保存场景引用 - sceneRef.current = { - scene, - camera, - renderer, - controls: controls as unknown as typeof OrbitControls, - cleanup: () => { - cleanup(); - if (containerRef.current) { - containerRef.current.removeEventListener('mousemove', handleMouseMove); - containerRef.current.removeChild(renderer.domElement); - } - } - }; - - // 使用 ResizeObserver 监听容器大小变化 - const resizeObserver = new ResizeObserver(() => { - if (!containerRef.current || !sceneRef.current) return; - const { camera, renderer } = sceneRef.current; - camera.aspect = containerRef.current.clientWidth / containerRef.current.clientHeight; - camera.updateProjectionMatrix(); - renderer.setSize(containerRef.current.clientWidth, containerRef.current.clientHeight); - }); - - resizeObserver.observe(containerRef.current); - - // 清理 - return () => { - resizeObserver.disconnect(); - sceneRef.current?.cleanup(); - }; - }, []); - - // 更新机柜数据 - useEffect(() => { - if (!sceneRef.current || !rackConfigs || !rackServerTypes) return; - - // 清除现有机柜 - racksRef.current.forEach(rack => { - rack.servers.forEach(server => { - sceneRef.current!.scene.remove(server); - }); - sceneRef.current!.scene.remove(rack.rack); - }); - racksRef.current = []; - - // 创建新机柜 - racksRef.current = rackConfigs.map(config => { - return new ServerRack(sceneRef.current!.scene, config, rackServerTypes); - }); - }, [rackConfigs, rackServerTypes]); - - return ( -
-
-
-
- ); -} \ No newline at end of file diff --git a/src/client/big/components/three/constants.ts b/src/client/big/components/three/constants.ts deleted file mode 100644 index 5915f04..0000000 --- a/src/client/big/components/three/constants.ts +++ /dev/null @@ -1,55 +0,0 @@ -// 颜色常量定义 -export const COLORS = { - // 背景色(调亮为 #002952) - BACKGROUND: 0x002952, - - // 地板颜色(相应调亮) - FLOOR: 0x1D5491, // 调亮地板颜色 - FLOOR_GRID: 0x2E66A3, // 相应调亮网格线条 - - // 机柜颜色 - RACK: { - FRAME: 0x2E5483, // 机柜框架颜色(调亮) - FRONT: 0x2E5483, // 机柜前面板 - SIDE: 0x274D70, // 机柜侧面板(稍暗) - }, - - // 服务器颜色 - SERVER: { - DEFAULT: 0x2E4D75, // 服务器默认颜色(调亮) - FRONT: 0x355882, // 服务器前面板(调亮) - STATUS: { - ONLINE: 0x00FF00, // 在线状态指示灯(绿色) - WARNING: 0xFFFF00, // 警告状态指示灯(黄色) - OFFLINE: 0xFF0000 // 离线状态指示灯(红色) - }, - HOVER: { - COLOR: 0x00DDFF, // 悬停发光颜色(青色) - INTENSITY: 0.05 // 悬停发光强度 - } - }, - - // 灯光颜色 - LIGHTS: { - AMBIENT: 0xCCE0FF, // 环境光(偏蓝色冷光) - DIRECT: 0xFFFFFF, // 直射光(白光) - SPOT: 0x00DDFF, // 聚光灯(青色) - } -} as const; - -// UI样式常量 -export const UI_STYLES = { - TOOLTIP: { - BACKGROUND: '#001529', - BORDER: '#00dff9', - BORDER_INNER: '#15243A', - SHADOW: '0 0 10px rgba(0,223,249,0.3)', - TEXT: '#ffffff', - PADDING: '12px 16px', - BORDER_RADIUS: '4px', - FONT_SIZE: '14px' - } -} as const; - -// 定义1U的高度(米) -export const U_HEIGHT = 0.04445; // 1U = 44.45mm = 0.04445m \ No newline at end of file diff --git a/src/client/big/components/three/models.ts b/src/client/big/components/three/models.ts deleted file mode 100644 index 35581e6..0000000 --- a/src/client/big/components/three/models.ts +++ /dev/null @@ -1,180 +0,0 @@ -import * as THREE from 'three'; -import { COLORS, U_HEIGHT } from './constants'; -import type { ServerData, ServerIconConfig, RackConfig, ServerIconConfigs, ServerStatus } from './types'; -import { getServerStatus } from './utils'; - -// 创建机柜模型 - 修改机柜的原点为底部中心 -export function createRack(position: THREE.Vector3): THREE.Mesh { - // 创建机柜的六个面 - const rackGeometry = new THREE.BoxGeometry(0.6, 2, 1); - - // 创建两种材质: - // 1. 通用材质 - 用于除前面外的所有面,双面渲染 - const commonMaterial = new THREE.MeshPhongMaterial({ - color: COLORS.RACK.SIDE, - side: THREE.DoubleSide, - opacity: 0.9, - }); - - // 2. 前面材质 - 半透明 - const frontMaterial = new THREE.MeshPhongMaterial({ - color: COLORS.RACK.FRONT, - transparent: true, - opacity: 0.1, - }); - - // 创建材质数组,按照几何体的面的顺序设置材质 - // BoxGeometry的面顺序:右、左、上、下、前、后 - const materials = [ - commonMaterial, // 右面 - commonMaterial, // 左面 - commonMaterial, // 上面 - commonMaterial, // 下面 - frontMaterial, // 前面 - commonMaterial, // 后面 - ]; - - const rack = new THREE.Mesh(rackGeometry, materials); - rack.position.copy(position); - rackGeometry.translate(0, 1, 0); - return rack; -} - -// 创建服务器模型 -export function createServer( - position: THREE.Vector3, - serverData: ServerData, - serverIconConfig: ServerIconConfig -): { server: THREE.Mesh } { - const config = serverIconConfig; - const U = serverData.u; - - const serverGeometry = new THREE.BoxGeometry( - 0.483, // 19英寸 ≈ 0.483米 - U * U_HEIGHT, // 将U数转换为实际高度 - 0.8 // 深度保持0.8米 - ); - - serverGeometry.translate(0, U * U_HEIGHT/2, 0); - - // 创建基础材质(用于侧面、顶面、底面和后面) - const baseMaterial = new THREE.MeshPhongMaterial({ - color: config.color, - shininess: 30, - }); - - // 创建前面的材质(用于贴图) - const frontMaterial = new THREE.MeshPhongMaterial({ - color: config.color, - shininess: 30, - map: null, - }); - - // 创建材质数组 - const materials = [ - baseMaterial, // 右面 - baseMaterial, // 左面 - baseMaterial, // 上面 - baseMaterial, // 下面 - frontMaterial, // 前面 - baseMaterial, // 后面 - ]; - - const server = new THREE.Mesh(serverGeometry, materials); - server.position.copy(position); - - // 加载贴图(如果有) - if (config.textureUrl) { - const textureLoader = new THREE.TextureLoader(); - textureLoader.load(config.textureUrl, (texture) => { - texture.minFilter = THREE.LinearFilter; - texture.magFilter = THREE.LinearFilter; - texture.anisotropy = 16; - - texture.repeat.set(1, 1); - texture.offset.set(0, 0); - - frontMaterial.map = texture; - frontMaterial.needsUpdate = true; - }); - } - - return { server }; -} - -// 添加创建地板的函数 -export function createFloor(): THREE.Mesh { - const floorGeometry = new THREE.PlaneGeometry(10, 10); - const floorMaterial = new THREE.MeshPhongMaterial({ - color: COLORS.FLOOR, - side: THREE.DoubleSide - }); - - // 添加网格纹理 - const gridHelper = new THREE.GridHelper(10, 20, COLORS.FLOOR_GRID, COLORS.FLOOR_GRID); - gridHelper.rotation.x = Math.PI / 2; - - const floor = new THREE.Mesh(floorGeometry, floorMaterial); - floor.rotation.x = -Math.PI / 2; - floor.add(gridHelper); - - return floor; -} - -// 机柜类 -export class ServerRack { - rack: THREE.Mesh; - servers: THREE.Mesh[] = []; - statusLights: THREE.PointLight[] = []; - - constructor(scene: THREE.Scene, rackConfig: RackConfig, serverIconConfigs: ServerIconConfigs) { - // 创建机柜 - this.rack = createRack(rackConfig.position); - scene.add(this.rack); - - const bottomSpace = 0.04445; // 底部预留空间1U - const slotHeight = 0.04445; // 每个槽位高度1U - - // 使用配置中的服务器数据创建服务器 - rackConfig.servers.forEach((serverData: ServerData) => { - // 从底部开始计算高度 - const currentHeight = bottomSpace + (slotHeight * (serverData.slot - 1)); - - const serverPosition = new THREE.Vector3( - rackConfig.position.x, - rackConfig.position.y + currentHeight, - rackConfig.position.z - ); - - const serverIconConfig = serverIconConfigs[serverData.type]; - const { server } = createServer( - serverPosition, - serverData, - serverIconConfig - ); - - server.userData.type = 'server'; - server.userData.status = getServerStatus(serverData); - - this.servers.push(server); - scene.add(server); - }); - } - - // 更新服务器状态 - updateServerStatus(serverId: string, status: ServerStatus) { - const server = this.servers.find(s => s.userData.id === serverId); - if (server) { - server.userData.status = status; - const index = this.servers.indexOf(server); - if (index !== -1) { - const light = this.statusLights[index]; - light.color.setHex( - status.status === 'online' ? COLORS.SERVER.STATUS.ONLINE : - status.status === 'warning' ? COLORS.SERVER.STATUS.WARNING : - COLORS.SERVER.STATUS.OFFLINE - ); - } - } - } -} \ No newline at end of file diff --git a/src/client/big/components/three/types.ts b/src/client/big/components/three/types.ts deleted file mode 100644 index 98d0901..0000000 --- a/src/client/big/components/three/types.ts +++ /dev/null @@ -1,46 +0,0 @@ -export interface ServerData { - id: number; - slot: number; - u: number; - type: number; - name: string; - ip: string; - cpu: string; - memory: string; - disk: string; - deviceStatus: number; - networkStatus: number; - packetLoss: number; -} - -export interface ServerIconConfig { - textureUrl: string | null; - color: number; -} - -export interface ServerIconConfigs { - [key: number]: ServerIconConfig; -} - -import * as THREE from 'three'; - -// 机柜配置接口 -export interface RackConfig { - position: THREE.Vector3; - serverCount: number; - id: number; - name: string; - servers: ServerData[]; -} - - -export interface DeviceStatusInfo { - status: 'online' | 'offline' | 'warning'; - usage: { - cpu: number; - memory: number; - disk: number; - }; -} - -export interface ServerStatus extends ServerData, DeviceStatusInfo {} \ No newline at end of file diff --git a/src/client/big/components/three/utils.tsx b/src/client/big/components/three/utils.tsx deleted file mode 100644 index 1f8d00a..0000000 --- a/src/client/big/components/three/utils.tsx +++ /dev/null @@ -1,174 +0,0 @@ -import * as THREE from 'three'; -import { createRoot } from 'react-dom/client'; -import type { ServerData, ServerIconConfig, DeviceStatusInfo, ServerStatus } from './types'; -import { COLORS, UI_STYLES } from './constants'; -import { ServerTooltip } from './ServerTooltip'; - -export function useServerHover({ scene, camera, containerRef, tooltipRef }: { - scene: THREE.Scene; - camera: THREE.Camera; - containerRef: React.RefObject; - tooltipRef: React.RefObject; -}) { - const HOVER_COLOR = new THREE.Color(COLORS.SERVER.HOVER.COLOR); - const HOVER_INTENSITY = COLORS.SERVER.HOVER.INTENSITY; - let INTERSECTED: THREE.Mesh | null = null; - const raycaster = new THREE.Raycaster(); - const mouse = new THREE.Vector2(); - - const setMaterialEmissive = (materials: THREE.Material | THREE.Material[], color: THREE.Color, intensity: number) => { - if (Array.isArray(materials)) { - materials.forEach(material => { - if (material instanceof THREE.MeshPhongMaterial) { - material.emissive.copy(color); - material.emissiveIntensity = intensity; - material.needsUpdate = true; - } - }); - } else if (materials instanceof THREE.MeshPhongMaterial) { - materials.emissive.copy(color); - materials.emissiveIntensity = intensity; - materials.needsUpdate = true; - } - }; - - const resetMaterialEmissive = (materials: THREE.Material | THREE.Material[]) => { - if (Array.isArray(materials)) { - materials.forEach(material => { - if (material instanceof THREE.MeshPhongMaterial) { - material.emissive.setHex(0x000000); - material.emissiveIntensity = 0.2; - material.needsUpdate = true; - } - }); - } else if (materials instanceof THREE.MeshPhongMaterial) { - materials.emissive.setHex(0x000000); - materials.emissiveIntensity = 0.2; - materials.needsUpdate = true; - } - }; - - const handleMouseMove = (event: MouseEvent) => { - const rect = containerRef.current?.getBoundingClientRect(); - if (!rect) return; - - mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; - mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; - - raycaster.setFromCamera(mouse, camera); - const intersects = raycaster.intersectObjects(scene.children, true); - - if (intersects.length > 0) { - const found = intersects.find(item => - item.object instanceof THREE.Mesh && - item.object.userData.type === 'server' - ); - - if (found) { - const serverMesh = found.object as THREE.Mesh; - - if (INTERSECTED !== serverMesh) { - if (INTERSECTED) { - resetMaterialEmissive(INTERSECTED.material); - } - - INTERSECTED = serverMesh; - setMaterialEmissive(INTERSECTED.material, HOVER_COLOR, HOVER_INTENSITY); - - updateTooltip(event, INTERSECTED.userData.status); - } - } else { - resetHoverState(); - } - } else { - resetHoverState(); - } - }; - - const resetIntersected = () => { - if (INTERSECTED) { - resetMaterialEmissive(INTERSECTED.material); - } - }; - - const resetHoverState = () => { - resetIntersected(); - INTERSECTED = null; - if (tooltipRef.current) { - tooltipRef.current.style.display = 'none'; - } - }; - - let root: ReturnType | null = null; - - const updateTooltip = (event: MouseEvent, serverStatus: ServerStatus) => { - if (!tooltipRef.current) return; - - const containerRect = containerRef.current?.getBoundingClientRect(); - if (!containerRect) return; - - const tooltipX = event.clientX - containerRect.left; - const tooltipY = event.clientY - containerRect.top; - - const tooltipRect = tooltipRef.current.getBoundingClientRect(); - const tooltipWidth = tooltipRect.width; - const tooltipHeight = tooltipRect.height; - - const finalX = Math.min( - tooltipX + 10, - containerRect.width - tooltipWidth - 10 - ); - const finalY = Math.min( - tooltipY + 10, - containerRect.height - tooltipHeight - 10 - ); - - tooltipRef.current.style.left = `${finalX}px`; - tooltipRef.current.style.top = `${finalY}px`; - tooltipRef.current.style.display = 'block'; - - if (!root) { - root = createRoot(tooltipRef.current); - } - root.render(); - }; - - const cleanup = () => { - resetHoverState(); - if (root) { - root.unmount(); - root = null; - } - }; - - return { - handleMouseMove, - cleanup - }; -} - -// 将服务器状态根据设备状态转换为对应的status格式 -export const getServerStatus = (serverData: ServerData): ServerStatus => { - // 转换网络状态为UI显示状态 - let status: 'online' | 'offline' | 'warning' = 'offline'; - - // 根据设备状态判断显示状态 - if (serverData.deviceStatus === 0) { // 正常 - status = 'online'; - } else if (serverData.deviceStatus === 2) { // 故障 - status = 'warning'; - } else { // 其他情况(维护中、下线) - status = 'offline'; - } - - // 随机生成资源使用率用于展示 - return { - ...serverData, - status, - usage: { - cpu: Math.floor(Math.random() * 100), - memory: Math.floor(Math.random() * 100), - disk: Math.floor(Math.random() * 100) - } - }; -}; \ No newline at end of file diff --git a/src/client/big/components/utils.ts b/src/client/big/components/utils.ts deleted file mode 100644 index c076eee..0000000 --- a/src/client/big/components/utils.ts +++ /dev/null @@ -1,28 +0,0 @@ -export const pushStateAndTrigger = (url: string, target: string) => { - window.history.pushState({}, '', url); - window.dispatchEvent(new Event('popstate')); -} - -// 统一的链接处理函数 -export const handleNavigate = (url: string) => { - // 判断是否在iframe中 - const isInIframe = window.self !== window.top; - if (isInIframe) { - pushStateAndTrigger(url, 'top'); - } else { - window.open(url, '_blank'); - } -}; - -// 计算风险等级 -export const calculateRiskLevel = (onlineRate: number): { level: string; color: string } => { - if (onlineRate >= 95) { - return { level: '健康', color: '#52c41a' }; // 绿色 - } else if (onlineRate >= 80) { - return { level: '风险低', color: '#faad14' }; // 黄色 - } else if (onlineRate >= 70) { - return { level: '风险中', color: '#faad14' }; // 黄色 - } else { - return { level: '高风险', color: '#f5222d' }; // 红色 - } -}; \ No newline at end of file diff --git a/src/client/big/components_three.tsx b/src/client/big/components_three.tsx deleted file mode 100644 index 626eff6..0000000 --- a/src/client/big/components_three.tsx +++ /dev/null @@ -1,691 +0,0 @@ -import React, { useRef, useEffect } from 'react'; -import { useQuery } from '@tanstack/react-query'; - -import * as THREE from 'three'; -import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; - - -import type { ServerData, ServerIconConfig, RackConfig, ServerIconConfigs,DeviceStatusInfo } from './api.js'; -import { bigClient } from '../api.js'; -import { getGlobalConfig } from '../admin/utils.js'; - -interface UseServerHoverProps { - scene: THREE.Scene; - camera: THREE.Camera; - containerRef: React.RefObject; - tooltipRef: React.RefObject; -} - -// 合并服务器基本信息和状态信息 -interface ServerStatus extends ServerData, DeviceStatusInfo {} - - - -// 颜色常量定义 -const COLORS = { - // 背景色(调亮为 #002952) - BACKGROUND: 0x002952, - - // 地板颜色(相应调亮) - FLOOR: 0x1D5491, // 调亮地板颜色 - FLOOR_GRID: 0x2E66A3, // 相应调亮网格线条 - - // 机柜颜色 - RACK: { - FRAME: 0x2E5483, // 机柜框架颜色(调亮) - FRONT: 0x2E5483, // 机柜前面板 - SIDE: 0x274D70, // 机柜侧面板(稍暗) - }, - - // 服务器颜色 - SERVER: { - DEFAULT: 0x2E4D75, // 服务器默认颜色(调亮) - FRONT: 0x355882, // 服务器前面板(调亮) - STATUS: { - ONLINE: 0x00FF00, // 在线状态指示灯(绿色) - WARNING: 0xFFFF00, // 警告状态指示灯(黄色) - OFFLINE: 0xFF0000 // 离线状态指示灯(红色) - }, - HOVER: { - COLOR: 0x00DDFF, // 悬停发光颜色(青色) - INTENSITY: 0.05 // 悬停发光强度 - } - }, - - // 灯光颜色 - LIGHTS: { - AMBIENT: 0xCCE0FF, // 环境光(偏蓝色冷光) - DIRECT: 0xFFFFFF, // 直射光(白光) - SPOT: 0x00DDFF, // 聚光灯(青色) - } -} as const; - -// UI样式常量 -const UI_STYLES = { - TOOLTIP: { - BACKGROUND: '#001529', - BORDER: '#00dff9', - BORDER_INNER: '#15243A', - SHADOW: '0 0 10px rgba(0,223,249,0.3)', - TEXT: '#ffffff', - PADDING: '12px 16px', - BORDER_RADIUS: '4px', - FONT_SIZE: '14px' - } -} as const; - -// 定义1U的高度(米) -const U_HEIGHT = 0.04445; // 1U = 44.45mm = 0.04445m - - -function useServerHover({ scene, camera, containerRef, tooltipRef }: UseServerHoverProps) { - const HOVER_COLOR = new THREE.Color(COLORS.SERVER.HOVER.COLOR); - const HOVER_INTENSITY = COLORS.SERVER.HOVER.INTENSITY; - let INTERSECTED: THREE.Mesh | null = null; - const raycaster = new THREE.Raycaster(); - const mouse = new THREE.Vector2(); - - const setMaterialEmissive = (materials: THREE.Material | THREE.Material[], color: THREE.Color, intensity: number) => { - if (Array.isArray(materials)) { - materials.forEach(material => { - if (material instanceof THREE.MeshPhongMaterial) { - material.emissive.copy(color); - material.emissiveIntensity = intensity; - material.needsUpdate = true; - } - }); - } else if (materials instanceof THREE.MeshPhongMaterial) { - materials.emissive.copy(color); - materials.emissiveIntensity = intensity; - materials.needsUpdate = true; - } - }; - - const resetMaterialEmissive = (materials: THREE.Material | THREE.Material[]) => { - if (Array.isArray(materials)) { - materials.forEach(material => { - if (material instanceof THREE.MeshPhongMaterial) { - material.emissive.setHex(0x000000); - material.emissiveIntensity = 0.2; - material.needsUpdate = true; - } - }); - } else if (materials instanceof THREE.MeshPhongMaterial) { - materials.emissive.setHex(0x000000); - materials.emissiveIntensity = 0.2; - materials.needsUpdate = true; - } - }; - - const handleMouseMove = (event: MouseEvent) => { - const rect = containerRef.current?.getBoundingClientRect(); - if (!rect) return; - - mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; - mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; - - raycaster.setFromCamera(mouse, camera); - const intersects = raycaster.intersectObjects(scene.children, true); - - if (intersects.length > 0) { - const found = intersects.find(item => - item.object instanceof THREE.Mesh && - item.object.userData.type === 'server' - ); - - if (found) { - const serverMesh = found.object as THREE.Mesh; - - if (INTERSECTED !== serverMesh) { - if (INTERSECTED) { - resetMaterialEmissive(INTERSECTED.material); - } - - INTERSECTED = serverMesh; - setMaterialEmissive(INTERSECTED.material, HOVER_COLOR, HOVER_INTENSITY); - - updateTooltip(event, INTERSECTED.userData.status); - } - } else { - resetHoverState(); - } - } else { - resetHoverState(); - } - }; - - const resetIntersected = () => { - if (INTERSECTED) { - resetMaterialEmissive(INTERSECTED.material); - } - }; - - const resetHoverState = () => { - resetIntersected(); - INTERSECTED = null; - if (tooltipRef.current) { - tooltipRef.current.style.display = 'none'; - } - }; - - const updateTooltip = (event: MouseEvent, serverStatus: ServerStatus) => { - if (tooltipRef.current) { - const containerRect = containerRef.current?.getBoundingClientRect(); - if (!containerRect) return; - - const tooltipX = event.clientX - containerRect.left; - const tooltipY = event.clientY - containerRect.top; - - const tooltipRect = tooltipRef.current.getBoundingClientRect(); - const tooltipWidth = tooltipRect.width; - const tooltipHeight = tooltipRect.height; - - const finalX = Math.min( - tooltipX + 10, - containerRect.width - tooltipWidth - 10 - ); - const finalY = Math.min( - tooltipY + 10, - containerRect.height - tooltipHeight - 10 - ); - - tooltipRef.current.style.left = `${finalX}px`; - tooltipRef.current.style.top = `${finalY}px`; - tooltipRef.current.innerHTML = ` -
-
- - - - - 资产信息 -
-
-
名称: ${serverStatus.name}
-
IP地址: ${serverStatus.ip}
-
- -
- - - - - - 网络状态 -
-
-
- 状态: -
- ${serverStatus.networkStatus === 1 ? '在线' : '离线'} - -
-
-
丢包率: ${serverStatus.packetLoss}%
-
- -
- - - - - - - 配置信息 -
-
-
CPU: ${serverStatus.cpu || '-'}
-
内存: ${serverStatus.memory || '-'}
-
硬盘: ${serverStatus.disk || '-'}
-
-
- `; - tooltipRef.current.style.display = 'block'; - } - }; - - const cleanup = () => { - resetHoverState(); - }; - - return { - handleMouseMove, - cleanup - }; -} - -// 创建机柜模型 - 修改机柜的原点为底部中心 -function createRack(position: THREE.Vector3): THREE.Mesh { - // 创建机柜的六个面 - const rackGeometry = new THREE.BoxGeometry(0.6, 2, 1); - - // 创建两种材质: - // 1. 通用材质 - 用于除前面外的所有面,双面渲染 - const commonMaterial = new THREE.MeshPhongMaterial({ - color: COLORS.RACK.SIDE, - side: THREE.DoubleSide, // 双面渲染 - opacity: 0.9, - }); - - // 2. 前面材质 - 半透明 - const frontMaterial = new THREE.MeshPhongMaterial({ - color: COLORS.RACK.FRONT, - transparent: true, - opacity: 0.1, // 前面设置为更透明 - }); - - // 创建材质数组,按照几何体的面的顺序设置材质 - // BoxGeometry的面顺序:右、左、上、下、前、后 - const materials = [ - commonMaterial, // 右面 - 双面渲染 - commonMaterial, // 左面 - 双面渲染 - commonMaterial, // 上面 - 双面渲染 - commonMaterial, // 下面 - 双面渲染 - frontMaterial, // 前面 - 半透明 - commonMaterial, // 后面 - 双面渲染 - ]; - - const rack = new THREE.Mesh(rackGeometry, materials); - rack.position.copy(position); - rackGeometry.translate(0, 1, 0); - return rack; -} - -// 创建服务器模型 -function createServer( - position: THREE.Vector3, - serverData: ServerData, - serverIconConfig: ServerIconConfig -): { server: THREE.Mesh } { - const config = serverIconConfig; - const U = serverData.u; - - const serverGeometry = new THREE.BoxGeometry( - 0.483, // 19英寸 ≈ 0.483米 - U * U_HEIGHT, // 将U数转换为实际高度 - 0.8 // 深度保持0.8米 - ); - - serverGeometry.translate(0, U * U_HEIGHT/2, 0); - - // 创建基础材质(用于侧面、顶面、底面和后面) - const baseMaterial = new THREE.MeshPhongMaterial({ - color: config.color, - shininess: 30, // 降低反光度 - }); - - // 创建前面的材质(用于贴图) - const frontMaterial = new THREE.MeshPhongMaterial({ - color: config.color, - shininess: 30, - map: null, // 初始化时设为null,等待贴图加载 - }); - - // 创建材质数组 - const materials = [ - baseMaterial, // 右面 - baseMaterial, // 左面 - baseMaterial, // 上面 - baseMaterial, // 下面 - frontMaterial, // 前面 - 用于贴图 - baseMaterial, // 后面 - ]; - - const server = new THREE.Mesh(serverGeometry, materials); - server.position.copy(position); - - // 加载贴图(如果有) - if (config.textureUrl) { - const textureLoader = new THREE.TextureLoader(); - textureLoader.load(config.textureUrl, (texture) => { - // 设置贴图属性以提高清晰度 - texture.minFilter = THREE.LinearFilter; - texture.magFilter = THREE.LinearFilter; - texture.anisotropy = 16; // 增加各向异性过滤 - - // 调整贴图的重复和偏移 - texture.repeat.set(1, 1); - texture.offset.set(0, 0); - - // 更新材质 - frontMaterial.map = texture; - frontMaterial.needsUpdate = true; - }); - } - - return { server }; -} - -// 添加创建地板的函数 -function createFloor(): THREE.Mesh { - const floorGeometry = new THREE.PlaneGeometry(10, 10); - const floorMaterial = new THREE.MeshPhongMaterial({ - color: COLORS.FLOOR, - side: THREE.DoubleSide - }); - - // 添加网格纹理 - const gridHelper = new THREE.GridHelper(10, 20, COLORS.FLOOR_GRID, COLORS.FLOOR_GRID); - gridHelper.rotation.x = Math.PI / 2; - - const floor = new THREE.Mesh(floorGeometry, floorMaterial); - floor.rotation.x = -Math.PI / 2; - floor.add(gridHelper); - - return floor; -} - -class ServerRack { - rack: THREE.Mesh; - servers: THREE.Mesh[] = []; - statusLights: THREE.PointLight[] = []; - - constructor(scene: THREE.Scene, rackConfig: RackConfig, serverIconConfigs: ServerIconConfigs) { - // 创建机柜 - this.rack = createRack(rackConfig.position); - scene.add(this.rack); - - const bottomSpace = 0.04445; // 底部预留空间1U - const slotHeight = 0.04445; // 每个槽位高度1U - - // 使用配置中的服务器数据创建服务器 - rackConfig.servers.forEach((serverData: ServerData) => { - // 从底部开始计算高度 - const currentHeight = bottomSpace + (slotHeight * (serverData.slot - 1)); - - const serverPosition = new THREE.Vector3( - rackConfig.position.x, - rackConfig.position.y + currentHeight, - rackConfig.position.z - ); - - const serverIconConfig = serverIconConfigs[serverData.type]; - // console.log(serverIconConfig, serverIconConfigs); - // console.log(serverData); - // console.log(serverPosition); - const { server } = createServer( - serverPosition, - serverData, - serverIconConfig - ); - - server.userData.type = 'server'; - server.userData.status = getServerStatus(serverData); - - this.servers.push(server); - - scene.add(server); - }); - } - - // 更新服务器状态 - updateServerStatus(serverId: string, status: ServerStatus) { - const server = this.servers.find(s => s.userData.id === serverId); - if (server) { - server.userData.status = status; - const index = this.servers.indexOf(server); - if (index !== -1) { - const light = this.statusLights[index]; - light.color.setHex( - status.status === 'online' ? COLORS.SERVER.STATUS.ONLINE : - status.status === 'warning' ? COLORS.SERVER.STATUS.WARNING : - COLORS.SERVER.STATUS.OFFLINE - ); - } - } - } -} - -// 将服务器状态根据设备状态转换为对应的status格式 -const getServerStatus = (serverData: ServerData): ServerStatus => { - // 转换网络状态为UI显示状态 - let status: 'online' | 'offline' | 'warning' = 'offline'; - - // 根据设备状态判断显示状态 - if (serverData.deviceStatus === 0) { // 正常 - status = 'online'; - } else if (serverData.deviceStatus === 2) { // 故障 - status = 'warning'; - } else { // 其他情况(维护中、下线) - status = 'offline'; - } - - // 随机生成资源使用率用于展示 - return { - ...serverData, - status, - usage: { - cpu: Math.floor(Math.random() * 100), - memory: Math.floor(Math.random() * 100), - disk: Math.floor(Math.random() * 100) - } - }; -}; - -export function ThreeJSRoom() { - const containerRef = useRef(null); - const tooltipRef = useRef(null); - const racksRef = useRef([]); - const sceneRef = useRef<{ - scene: THREE.Scene; - camera: THREE.PerspectiveCamera; - renderer: THREE.WebGLRenderer; - controls: typeof OrbitControls; - cleanup: () => void; - } | null>(null); - - // 获取服务器类型图标 - const { data: rackServerTypes } = useQuery({ - queryKey: ['rackServerTypes'], - queryFn: async () => { - const res = await bigClient['rack-server-types'].$get({query:{}}); - if (res.status !== 200) throw new Error('Failed to fetch device icons'); - const data = await res.json(); - return data.data.reduce((acc: ServerIconConfigs, type) => { - acc[type.id] = { - textureUrl: type.imageUrl ? `${getGlobalConfig('OSS_BASE_URL')}/${type.imageUrl}` : null, - color: 0x444444 - }; - return acc; - }, {}); - } - }); - - // 获取机柜配置,添加自动刷新 - const { data: rackConfigs } = useQuery({ - queryKey: ['rackConfigs'], - queryFn: async () => { - const res = await bigClient['racks'].$get({query:{}}); - if (res.status !== 200) throw new Error('Failed to fetch rack configs'); - const racks = await res.json(); - // 2. 获取所有机柜的服务器数据 - const serverPromises = racks.data.map(async (rack) => { - const serverResponse = await bigClient['rack-servers'].$get({ - query:{ - rackId: rack.id, - } - }) - - // 3. 获取每个服务器对应的基本信息 - let servers: ServerData[] = []; - try { - if (serverResponse.status !== 200) throw new Error('Failed to fetch rack servers configs'); - const serverData = await serverResponse.json(); - servers = serverData.data.map((server) => ({ - id: server.id, - slot: server.startPosition, - u: server.size, - type: server.serverType || 0, - name: server.deviceInfo.zichanInfo?.assetName || '', - ip: server.deviceInfo.address || '', - cpu: server.deviceInfo.zichanInfo?.cpu || '', - memory: server.deviceInfo.zichanInfo?.memory || '', - disk: server.deviceInfo.zichanInfo?.disk || '', - deviceStatus: server.deviceInfo.zichanInfo?.deviceStatus || 0, - networkStatus: server.deviceInfo.zichanInfo?.networkStatus || 0, - packetLoss: server.deviceInfo.zichanInfo?.packetLoss || 0 - })); - } catch (error) { - console.error("error", error); - } - - // 返回包含服务器数据的机柜配置 - return { - position: new THREE.Vector3(Number(rack.positionX) || 0, Number(rack.positionY) || 0, Number(rack.positionZ) || 0), - serverCount: rack.capacity || 42, - id: rack.id, - name: rack.rackName || '', - servers - }; - }); - - // 等待所有数据获取完成 - return Promise.all(serverPromises); - }, - refetchInterval: 30000, - refetchIntervalInBackground: true - }); - - // 初始化3D场景 - useEffect(() => { - if (!containerRef.current) return; - - // 初始化场景 - const scene = new THREE.Scene(); - scene.background = new THREE.Color(COLORS.BACKGROUND); - - const camera = new THREE.PerspectiveCamera( - 22, - containerRef.current.clientWidth / containerRef.current.clientHeight, - 0.1, - 1000 - ); - - const renderer = new THREE.WebGLRenderer({ antialias: true }); - renderer.setSize(containerRef.current.clientWidth, containerRef.current.clientHeight); - containerRef.current.appendChild(renderer.domElement); - - const controls = new OrbitControls(camera, renderer.domElement); - controls.enableDamping = true; - controls.maxPolarAngle = Math.PI / 2; - controls.minDistance = 6; - controls.maxDistance = 10; - controls.enablePan = false; - controls.target.set(0, 1, 0); - controls.enabled = false; - - // 添加地板 - const floor = createFloor(); - floor.position.y = -0.01; - scene.add(floor); - - // 设置场景光照 - const ambientLight = new THREE.AmbientLight(COLORS.LIGHTS.AMBIENT, 0.6); - scene.add(ambientLight); - - const directionalLight = new THREE.DirectionalLight(COLORS.LIGHTS.DIRECT, 0.8); - directionalLight.position.set(5, 5, 5); - scene.add(directionalLight); - - const spotLight = new THREE.SpotLight(COLORS.LIGHTS.SPOT, 0.8); - spotLight.position.set(0, 5, 0); - spotLight.angle = Math.PI / 4; - spotLight.penumbra = 0.1; - scene.add(spotLight); - - camera.position.set(0, 1, 1); - camera.lookAt(0, 1, 0); - - const { handleMouseMove, cleanup } = useServerHover({ - scene, - camera, - containerRef: containerRef as React.RefObject, - tooltipRef: tooltipRef as React.RefObject - }); - - containerRef.current.addEventListener('mousemove', handleMouseMove); - - // 动画循环 - const animate = () => { - requestAnimationFrame(animate); - controls.update(); - renderer.render(scene, camera); - }; - - animate(); - - // 保存场景引用 - sceneRef.current = { - scene, - camera, - renderer, - controls: controls as unknown as typeof OrbitControls, - cleanup: () => { - cleanup(); - if (containerRef.current) { - containerRef.current.removeEventListener('mousemove', handleMouseMove); - containerRef.current.removeChild(renderer.domElement); - } - } - }; - - // 使用 ResizeObserver 监听容器大小变化 - const resizeObserver = new ResizeObserver(() => { - if (!containerRef.current || !sceneRef.current) return; - // console.log('resizeObserver', containerRef.current.clientWidth, containerRef.current.clientHeight); - const { camera, renderer } = sceneRef.current; - camera.aspect = containerRef.current.clientWidth / containerRef.current.clientHeight; - camera.updateProjectionMatrix(); - renderer.setSize(containerRef.current.clientWidth, containerRef.current.clientHeight); - }); - - resizeObserver.observe(containerRef.current); - - // 清理 - return () => { - resizeObserver.disconnect(); - sceneRef.current?.cleanup(); - }; - }, []); - - // 更新机柜数据 - useEffect(() => { - if (!sceneRef.current || !rackConfigs || !rackServerTypes) return; - - // 清除现有机柜 - racksRef.current.forEach(rack => { - rack.servers.forEach(server => { - sceneRef.current!.scene.remove(server); - }); - sceneRef.current!.scene.remove(rack.rack); - }); - racksRef.current = []; - - - // 创建新机柜 - racksRef.current = rackConfigs.map(config => { - return new ServerRack(sceneRef.current!.scene, config, rackServerTypes); - }); - - }, [rackConfigs, rackServerTypes]); - - return ( -
-
-
-
- {/* 工具提示内容由useServerHover处理 */} -
-
-
- ); -} \ No newline at end of file diff --git a/src/client/big/title-bg.png b/src/client/big/title-bg.png deleted file mode 100644 index fcac9b3..0000000 Binary files a/src/client/big/title-bg.png and /dev/null differ diff --git a/src/server/api.ts b/src/server/api.ts index dcaf045..d02e0b6 100644 --- a/src/server/api.ts +++ b/src/server/api.ts @@ -1,35 +1,11 @@ import { OpenAPIHono } from '@hono/zod-openapi' import { errorHandler } from './utils/errorHandler' -import base from './api/base' import usersRouter from './api/users/index' -import zichanRoute from './api/zichan/index' -import zichanCategoryRouter from './api/zichan-category' -import zichanAreaRouter from './api/zichan-area/index' import { initConfigRouter, initStatusRouter } from './api/init' -import alertNotifyConfigsRoute from './api/alert-notify-configs/index' import authRoute from './api/auth/index' -import themeSettingsRoute from './api/theme-settings/index' -import deviceTypesRoute from './api/device-types/index' -import alertRulesRoute from '@/server/api/alert-rules/index' -import deviceInstancesRoute from '@/server/api/device-instances' -import rackRoute from '@/server/api/rack' -import rackServerTypeRoute from '@/server/api/rack-server-type' -import rackServerRoute from '@/server/api/rack-server/index' -import zichanTransferRoute from '@/server/api/zichan-transfer/index' -import monitorDataRoute from '@/server/api/monitor-data/index' -import alertRoute from '@/server/api/alerts/index' -import alertsHandlesRoute from '@/server/api/alerts/handles/index' -import monitorMapRoute from '@/server/api/monitor-map/index' -import knowInfoRoute from '@/server/api/know-info/index' -import monitorTaskRoute from '@/server/api/monitor-task/index' -import filesRoute from '@/server/api/files/index' -import fileCategoryRoute from '@/server/api/file-category/index' -import bigRoute from '@/server/api/big/index' import { AuthContext } from './types/context' import { AppDataSource } from './data-source' import { authMiddleware } from './middleware/auth.middleware' -import { MonitorService } from './modules/monitor/monitor.service' -import { MonitorSchedulerService } from './modules/monitor/monitor-scheduler.service' const api = new OpenAPIHono() @@ -46,15 +22,6 @@ api.use('/api/v1/*', async (c, next) => { api.use('/api/v1/*', async (c, next) => { if(!AppDataSource.isInitialized) { await AppDataSource.initialize(); - - // 初始化监控任务调度器 - try { - const monitorService = new MonitorService(AppDataSource); - const scheduler = new MonitorSchedulerService(AppDataSource, monitorService); - await scheduler.init(); - } catch (error) { - console.error('监控任务调度器初始化失败:', error); - } } await next(); }) @@ -82,24 +49,10 @@ if(!import.meta.env.PROD){ }) } -// Register routes -const routes = api - .route('/api/v1/init', initConfigRouter) - .route('/api/v1/init', initStatusRouter) - .route('/api/v1/base', base) + const userRoutes = api.route('/api/v1/users', usersRouter) -const zichanRoutes = api - .route('/api/v1/zichan', zichanRoute.getRoute) - .route('/api/v1/zichan', zichanRoute.getByIdRoute) - .route('/api/v1/zichan', zichanRoute.postRoute) - .route('/api/v1/zichan', zichanRoute.putByIdRoute) - .route('/api/v1/zichan', zichanRoute.deleteByIdRoute) - -const zichanCategoryRoutes = api.route('/api/v1/zichan-category', zichanCategoryRouter) - -const zichanAreaRoutes = api.route('/api/v1/zichan-area', zichanAreaRouter) const authRoutes = api .route('/api/v1/auth', authRoute.loginRoute.passwordRoute) diff --git a/src/server/api/init.ts b/src/server/api/init.ts deleted file mode 100644 index a71bfbd..0000000 --- a/src/server/api/init.ts +++ /dev/null @@ -1,192 +0,0 @@ -import { OpenAPIHono, createRoute, z } from '@hono/zod-openapi'; -import { ErrorSchema } from '../utils/errorHandler'; -import { AppDataSource } from '../data-source'; -import { UserEntity as User } from '../modules/users/user.entity'; -import { Role } from '../modules/users/role.entity'; -import * as bcrypt from 'bcrypt'; -import { generateJwtSecret } from '../utils/env-init'; -import { writeFileSync } from 'fs'; - -const initRouter = new OpenAPIHono(); - -// Zod 验证模式 -const DatabaseConfigSchema = z.object({ - host: z.string(), - port: z.number(), - username: z.string(), - password: z.string(), - database: z.string() -}); - -const AdminUserSchema = z.object({ - username: z.string().min(3), - password: z.string().min(8) -}); - -const InitConfigSchema = z.object({ - dbConfig: DatabaseConfigSchema, - adminUser: AdminUserSchema -}); - -// 检查初始化状态路由 -const statusRoute = createRoute({ - method: 'get', - path: '/status', - responses: { - 200: { - content: { - 'application/json': { - schema: z.object({ - initialized: z.boolean() - }) - } - }, - description: '返回系统初始化状态' - }, - 500: { - description: '初始化状态检查失败', - content: { - 'application/json': { - schema: ErrorSchema - } - } - } - } -}); - -const initStatusRouter = initRouter.openapi(statusRoute, async (c) => { - try { - const isInitialized = await checkInitialization(); - return c.json({ initialized: isInitialized }, 200); - } catch (error) { - return c.json({ - code: 500, - message: '初始化状态检查失败' - }, 500); - } -}); - -// 提交配置路由 -const configRoute = createRoute({ - method: 'post', - path: '/config', - request: { - body: { - content: { - 'application/json': { - schema: InitConfigSchema - } - } - } - }, - responses: { - 200: { - description: '系统初始化成功', - content: { - 'application/json': { - schema: z.object({ - success: z.boolean(), - jwtSecret: z.string().optional() - }) - } - } - }, - 400: { - description: '初始化失败', - content: { - 'application/json': { - schema: ErrorSchema - } - } - }, - 500: { - description: '服务器内部错误', - content: { - 'application/json': { - schema: ErrorSchema - } - } - } - } -}); - -const initConfigRouter = initRouter.openapi(configRoute, async (c) => { - const { dbConfig, adminUser } = c.req.valid('json'); - - if (await checkInitialization()) { - return c.json({ - code: 400, - message: '系统已初始化' - }, 400); - } - - try { - await validateDatabase(dbConfig); - await generateEnvFile(dbConfig); - const jwtSecret = generateJwtSecret(); - await createAdminUser(adminUser); - - return c.json({ - success: true, - jwtSecret - }, 200); - } catch (error) { - return c.json({ - code: 400, - message: error instanceof Error ? error.message : '未知错误' - }, 400); - } -}); - -export { initStatusRouter, initConfigRouter }; - - -async function checkInitialization(): Promise { - // 检查数据库是否已初始化 - return AppDataSource.isInitialized; -} - -async function validateDatabase(config: any) { - // 使用TypeORM验证数据库连接 - const testDataSource = AppDataSource.setOptions(config); - await testDataSource.initialize(); - await testDataSource.destroy(); -} - -async function generateEnvFile(config: any) { - const envContent = `DB_HOST=${config.host} -DB_PORT=${config.port} -DB_USERNAME=${config.username} -DB_PASSWORD=${config.password} -DB_DATABASE=${config.database} -`; - writeFileSync('.env', envContent); -} - -async function createAdminUser(userData: any) { - const userRepo = AppDataSource.getRepository(User); - const roleRepo = AppDataSource.getRepository(Role); - - // 检查是否已存在管理员 - const existingAdmin = await userRepo.findOne({ where: { username: userData.username } }); - if (existingAdmin) { - throw new Error('管理员用户已存在'); - } - - // 创建管理员角色 - let adminRole = await roleRepo.findOne({ where: { name: 'admin' } }); - if (!adminRole) { - adminRole = roleRepo.create({ name: 'admin', permissions: ['*'] }); - await roleRepo.save(adminRole); - } - - // 创建管理员用户 - const hashedPassword = await bcrypt.hash(userData.password, 10); - const adminUser = userRepo.create({ - username: userData.username, - password: hashedPassword, - roles: [adminRole] - }); - - await userRepo.save(adminUser); -} \ No newline at end of file diff --git a/src/server/api/migration.ts b/src/server/api/migration.ts deleted file mode 100644 index dcdccdd..0000000 --- a/src/server/api/migration.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { createRoute, OpenAPIHono } from '@hono/zod-openapi' -import { z } from 'zod' -import { AppDataSource } from '../data-source' -import { HTTPException } from 'hono/http-exception'; -import { authMiddleware } from '../middleware/auth.middleware'; -import { AuthContext } from '../types/context'; - -interface Migration { - name: string; - timestamp: number; -} - -const app = new OpenAPIHono() - -const MigrationResponseSchema = z.object({ - success: z.boolean(), - message: z.string(), - migrations: z.array(z.string()).optional() -}) - -const runMigrationRoute = createRoute({ - method: 'post', - path: '/migrations/run', - middleware: authMiddleware, - responses: { - 200: { - content: { - 'application/json': { - schema: MigrationResponseSchema - } - }, - description: 'Migrations executed successfully' - }, - 500: { - description: 'Migration failed' - } - } -}) - -const revertMigrationRoute = createRoute({ - method: 'post', - path: '/migrations/revert', - middleware: authMiddleware, - responses: { - 200: { - content: { - 'application/json': { - schema: MigrationResponseSchema - } - }, - description: 'Migration reverted successfully' - }, - 500: { - description: 'Revert failed' - } - } -}) - -app.openapi(runMigrationRoute, async (c) => { - try { - const migrations = await AppDataSource.runMigrations() - return c.json({ - success: true, - message: 'Migrations executed successfully', - migrations: migrations.map((m: Migration) => m.name) - }) - } catch (error) { - throw error - } -}) - -app.openapi(revertMigrationRoute, async (c) => { - try { - await AppDataSource.undoLastMigration() - const migrations = await AppDataSource.showMigrations() - return c.json({ - success: true, - message: 'Migration reverted successfully', - migrations: migrations - }) - } catch (error) { - throw error - } -}) - - - -export default app -export type AppType = typeof app \ No newline at end of file diff --git a/src/server/renderer.tsx b/src/server/renderer.tsx index ca67c78..c4a78ab 100644 --- a/src/server/renderer.tsx +++ b/src/server/renderer.tsx @@ -6,7 +6,6 @@ import process from 'node:process' // 全局配置常量 const GLOBAL_CONFIG: GlobalConfig = { OSS_BASE_URL: process.env.OSS_BASE_URL || 'https://oss.d8d.fun', - // API_BASE_URL: '/api', APP_NAME: process.env.APP_NAME || '多八多Aider', } diff --git a/src/share/monitorTypes.ts b/src/share/monitorTypes.ts deleted file mode 100644 index fadb894..0000000 --- a/src/share/monitorTypes.ts +++ /dev/null @@ -1,1754 +0,0 @@ -import { AuditStatus, DeleteStatus, EnableStatus } from './types' - -// 启用/禁用状态枚举 -export enum DisabledStatus { - DISABLED = 1, // 禁用 - ENABLED = 0 // 启用 -} - -// 备件标识枚举 是否备件 (0否 1是) -export enum IsSpare { - NO = 0, - YES = 1 -} - -// 设备通信协议类型枚举 -export enum DeviceProtocolType { - SNMP = 'SNMP', // 简单网络管理协议(网络设备管理) - HTTP = 'HTTP', // 超文本传输协议(Web服务) - MODBUS = 'MODBUS', // Modbus协议(工业自动化标准通信协议) - MQTT = 'MQTT', // 消息队列遥测传输(物联网消息协议) - SOCKET = 'SOCKET', // Socket通信(基础网络通信) - OPC = 'OPC', // OPC统一架构(工业设备互操作性标准) - RS485 = 'RS485', // RS485串行通信(工业现场总线) - TCP = 'TCP' // TCP网络协议(可靠的网络传输协议) -} - -// 设备通信协议类型中文映射 -export const DeviceProtocolTypeNameMap: Record = { - [DeviceProtocolType.SNMP]: 'SNMP', - [DeviceProtocolType.HTTP]: 'HTTP', - [DeviceProtocolType.MODBUS]: 'MODBUS', - [DeviceProtocolType.MQTT]: 'MQTT', - [DeviceProtocolType.SOCKET]: 'SOCKET', - [DeviceProtocolType.OPC]: 'OPC', - [DeviceProtocolType.RS485]: 'RS485', - [DeviceProtocolType.TCP]: 'TCP' -}; - -// 任务类型枚举 -export enum TaskType { - TEMPERATURE = 'temperature', - HUMIDITY = 'humidity', - SMOKE = 'smoke', - WATER = 'water', - NETWORK = 'network' -} - -// 统一的监控指标类型枚举 -export enum MetricType { - TEMPERATURE = 'temperature', - HUMIDITY = 'humidity', - VOLTAGE = 'voltage', - CPU_USAGE = 'cpu_usage', - MEMORY_USAGE = 'memory_usage', - DISK_USAGE = 'disk_usage', - SMOKE = 'smoke', - WATER = 'water', - NETWORK_TRAFFIC = 'network_traffic', - PING_TIME = 'ping_time', - PACKET_LOSS = 'packet_loss', - SNMP_RESPONSE_TIME = 'snmp_response_time', - SNMP_ERRORS = 'snmp_errors', - HTTP_RESPONSE_TIME = 'http_response_time', - HTTP_STATUS = 'http_status', - TCP_CONNECTION_TIME = 'tcp_connection_time', - CONNECTION_STATUS = 'connection_status' -} - -// 监控类型中文映射 -export const MetricTypeNameMap: Record = { - [MetricType.TEMPERATURE]: '温度', - [MetricType.HUMIDITY]: '湿度', - [MetricType.VOLTAGE]: '电压', - [MetricType.CPU_USAGE]: 'CPU使用率', - [MetricType.MEMORY_USAGE]: '内存使用率', - [MetricType.DISK_USAGE]: '磁盘使用率', - [MetricType.NETWORK_TRAFFIC]: '网络流量', - [MetricType.PING_TIME]: 'Ping时间', - [MetricType.PACKET_LOSS]: '丢包率', - [MetricType.SNMP_RESPONSE_TIME]: 'SNMP响应时间', - [MetricType.SNMP_ERRORS]: 'SNMP错误数', - [MetricType.HTTP_RESPONSE_TIME]: 'HTTP响应时间', - [MetricType.HTTP_STATUS]: 'HTTP状态码', - [MetricType.TCP_CONNECTION_TIME]: 'TCP连接时间', - [MetricType.CONNECTION_STATUS]: '连接状态', - [MetricType.WATER]: '水浸', - [MetricType.SMOKE]: '烟感', -}; - -// 处理类型枚举 -export enum HandleType { - CONFIRM = 'confirm', - RESOLVE = 'resolve', - IGNORE = 'ignore' -} - -// 处理类型中文映射 -export const HandleTypeNameMap: Record = { - [HandleType.CONFIRM]: '确认', - [HandleType.RESOLVE]: '解决', - [HandleType.IGNORE]: '忽略' -}; - -// 问题类型枚举 -export enum ProblemType { - DEVICE = 'device', - NETWORK = 'network', - POWER = 'power', - CONSTRUCTION = 'construction', - OTHER = 'other' -} - -// 问题类型中文映射 -export const ProblemTypeNameMap: Record = { - [ProblemType.DEVICE]: '设备故障', - [ProblemType.NETWORK]: '网络故障', - [ProblemType.POWER]: '电源故障', - [ProblemType.CONSTRUCTION]: '施工影响', - [ProblemType.OTHER]: '其他原因' -}; - -// 通知类型枚举 -export enum NotifyType { - SMS = 'sms', - EMAIL = 'email', - WECHAT = 'wechat' -} - -// 通知类型中文映射 -export const NotifyTypeNameMap: Record = { - [NotifyType.SMS]: '短信', - [NotifyType.EMAIL]: '邮件', - [NotifyType.WECHAT]: '微信' -}; - -// 告警等级枚举 -export enum AlertLevel { - MINOR = 0, // 次要 - NORMAL = 1, // 一般 - IMPORTANT = 2, // 重要 - URGENT = 3 // 紧急 -} - -// 告警等级中文映射 -export const AlertLevelNameMap: Record = { - [AlertLevel.MINOR]: '次要', - [AlertLevel.NORMAL]: '一般', - [AlertLevel.IMPORTANT]: '重要', - [AlertLevel.URGENT]: '紧急' -}; - -// 告警等级颜色映射 -export const AlertLevelColorMap: Record = { - [AlertLevel.MINOR]: 'blue', - [AlertLevel.NORMAL]: 'orange', - [AlertLevel.IMPORTANT]: 'red', - [AlertLevel.URGENT]: 'purple' -}; - -// // 设备查询状态枚举 -export enum DeviceQueryStatus { - ALL = 'all', - NORMAL = 'normal', - ERROR = 'error', - OFFLINE = 'offline' -} - -// 设备状态枚举(资产管理) -export enum DeviceStatus { - NORMAL = 0, // 正常 - MAINTAIN = 1, // 维护中 - FAULT = 2, // 故障 - OFFLINE = 3 // 下线 -} - -// 设备分类枚举 -export enum DeviceCategory { - SERVER = 1, // 服务器 - NETWORK = 2, // 网络设备 - STORAGE = 3, // 存储设备 - SECURITY = 4, // 安全设备 - OTHER = 5 // 其他设备 -} - -// 区域枚举 -export enum AreaType { - AREA_A = 1, // A区 - AREA_B = 2, // B区 - AREA_C = 3, // C区 - AREA_OTHER = 4 // 其他区域 -} - -// 资产状态枚举 -export enum AssetStatus { - IN_USE = 0, // 使用中 - IDLE = 1, // 闲置 - REPAIR = 2, // 维修中 - SCRAPPED = 3 // 已报废 -} - -// 网络状态枚举 -export enum NetworkStatus { - CONNECTED = 0, // 已连接 - DISCONNECTED = 1, // 已断开 - UNSTABLE = 2 // 不稳定 -} - -// 丢包状态枚举 -export enum PacketLossStatus { - NORMAL = 0, // 正常 - HIGH = 1 // 丢包 -} - -// 设备状态中文映射(资产管理) -export const DeviceStatusNameMap: Record = { - [DeviceStatus.NORMAL]: '正常', - [DeviceStatus.MAINTAIN]: '维护中', - [DeviceStatus.FAULT]: '故障', - [DeviceStatus.OFFLINE]: '下线' -}; - -// 设备状态颜色映射(资产管理) -export const DeviceStatusColorMap: Record = { - [DeviceStatus.NORMAL]: 'green', - [DeviceStatus.MAINTAIN]: 'blue', - [DeviceStatus.FAULT]: 'red', - [DeviceStatus.OFFLINE]: 'gray' -}; - -// 设备分类中文映射 -export const DeviceCategoryNameMap: Record = { - [DeviceCategory.SERVER]: '服务器', - [DeviceCategory.NETWORK]: '网络设备', - [DeviceCategory.STORAGE]: '存储设备', - [DeviceCategory.SECURITY]: '安全设备', - [DeviceCategory.OTHER]: '其他设备' -}; - -// 告警状态枚举 -export enum AlertStatus { - PENDING = 'pending', - HANDLING = 'handling', - RESOLVED = 'resolved', - IGNORED = 'ignored' -} - -// 告警状态中文映射 -export const AlertStatusNameMap: Record = { - [AlertStatus.PENDING]: '待处理', - [AlertStatus.HANDLING]: '处理中', - [AlertStatus.RESOLVED]: '已解决', - [AlertStatus.IGNORED]: '已忽略' -}; - -// 告警状态颜色映射 -export const AlertStatusColorMap: Record = { - [AlertStatus.PENDING]: 'red', - [AlertStatus.HANDLING]: 'blue', - [AlertStatus.RESOLVED]: 'green', - [AlertStatus.IGNORED]: 'gray' -}; - -// 设备在线状态枚举 -export enum OnlineStatus { - ONLINE = 'online', - OFFLINE = 'offline' -} - -// 设备在线状态中文映射 -export const OnlineStatusNameMap: Record = { - [OnlineStatus.ONLINE]: '在线', - [OnlineStatus.OFFLINE]: '离线' -}; - -// 设备在线状态颜色映射 -export const OnlineStatusColorMap: Record = { - [OnlineStatus.ONLINE]: 'green', - [OnlineStatus.OFFLINE]: 'red' -}; - -// 工单状态枚举 -export enum WorkOrderStatus { - PENDING = '待受理', // 待受理 - PROCESSING = '处理中', // 处理中 - REASSIGNED = '已改派', // 已改派 - COMPLETED = '已完成', // 已完成 - CLOSED = '已关闭' // 已关闭 -} - -// 工单状态中文映射 -export const WorkOrderStatusNameMap: Record = { - [WorkOrderStatus.PENDING]: '待受理', - [WorkOrderStatus.PROCESSING]: '处理中', - [WorkOrderStatus.REASSIGNED]: '已改派', - [WorkOrderStatus.COMPLETED]: '已完成', - [WorkOrderStatus.CLOSED]: '已关闭' -}; - -// 工单状态颜色映射 -export const WorkOrderStatusColorMap: Record = { - [WorkOrderStatus.PENDING]: 'orange', - [WorkOrderStatus.PROCESSING]: 'blue', - [WorkOrderStatus.REASSIGNED]: 'purple', - [WorkOrderStatus.COMPLETED]: 'green', - [WorkOrderStatus.CLOSED]: 'gray' -}; - -// 工单优先级枚举 -export enum WorkOrderPriority { - NORMAL = 0, // 普通 - IMPORTANT = 1, // 重要 - URGENT = 2 // 紧急 -} - -// 工单优先级中文映射 -export const WorkOrderPriorityNameMap: Record = { - [WorkOrderPriority.NORMAL]: '普通', - [WorkOrderPriority.IMPORTANT]: '重要', - [WorkOrderPriority.URGENT]: '紧急' -}; - -// 工单优先级颜色映射 -export const WorkOrderPriorityColorMap: Record = { - [WorkOrderPriority.NORMAL]: 'green', - [WorkOrderPriority.IMPORTANT]: 'orange', - [WorkOrderPriority.URGENT]: 'red' -}; - -// 工单操作类型枚举 -export enum WorkOrderAction { - CREATE = 'create', - ACCEPT = 'accept', - HANDLE = 'handle', - AUDIT = 'audit', - CLOSE = 'close' -} - -// 工单操作类型中文映射 -export const WorkOrderActionNameMap: Record = { - [WorkOrderAction.CREATE]: '创建', - [WorkOrderAction.ACCEPT]: '接受', - [WorkOrderAction.HANDLE]: '处理', - [WorkOrderAction.AUDIT]: '审核', - [WorkOrderAction.CLOSE]: '关闭' -}; - -// 服务器类型枚举 -export enum ServerType { - STANDARD = 'standard', - NETWORK = 'network', - STORAGE = 'storage', - SPECIAL = 'special' -} - -// 服务器类型中文映射 -export const ServerTypeNameMap: Record = { - [ServerType.STANDARD]: '标准服务器', - [ServerType.NETWORK]: '网络设备', - [ServerType.STORAGE]: '存储设备', - [ServerType.SPECIAL]: '特殊设备' -}; - - - -// 图表类型映射 -export const AlertTypeMap = { - temperature: { text: '温度异常', color: 'orange' }, - humidity: { text: '湿度异常', color: 'blue' }, - offline: { text: '设备离线', color: 'red' } -} as const; - -// 工单状态映射 -export const StatusMap = { - unread: { text: '未读', color: 'red' }, - read: { text: '已读', color: 'blue' }, - processed: { text: '已处理', color: 'green' } -} as const; - - -// 定义JSON数据结构接口 - -// 附件类型定义 -export interface Attachment { - /** 附件ID */ - id: string; - - /** 附件名称 */ - name: string; - - /** 附件访问地址 */ - url: string; - - /** 附件类型(如image/jpeg, application/pdf等) */ - type: string; - - /** 附件大小(字节) */ - size: number; - - /** 上传时间 */ - upload_time: string; -} - -// 通知项配置类型定义 -interface NotifyItem { - /** 通知项ID */ - id: string; - - /** 通知项类型 */ - type: string; - - /** 是否启用 */ - enabled: boolean; - - /** 通知配置参数 */ - config: Record; -} - -// 监控配置类型定义 -export interface MonitorConfig { - /** 监控间隔(秒) */ - interval: number; - - /** 监控指标列表 */ - metrics: Array<{ - /** 指标名称 */ - name: string; - - /** 指标类型 */ - type: string; - - /** 是否启用 */ - enabled: boolean; - - /** 阈值设置 */ - threshold?: { - /** 最小阈值 */ - min?: number; - - /** 最大阈值 */ - max?: number; - }; - }>; - - /** 通知设置 */ - notification: { - /** 是否启用通知 */ - enabled: boolean; - - /** 通知渠道列表 */ - channels: string[]; - }; -} - -// 告警规则类型定义 -export interface AlertRuleConfig { - /** 规则列表 */ - rules: Array<{ - /** 监控指标 */ - metric: string; - - /** 触发条件(如>、<、=等) */ - condition: string; - - /** 阈值 */ - threshold: number; - - /** 持续时间(秒) */ - duration: number; - - /** 告警等级 */ - level: AlertLevel; - }>; - - /** 动作列表 */ - actions: Array<{ - /** 动作类型 */ - type: string; - - /** 动作目标 */ - target: string; - - /** 通知模板 */ - template?: string; - }>; -} - -// 数据格式配置类型定义 -export interface DataSchema { - /** 版本号 */ - version: string; - - /** 属性定义 */ - properties: Record; - - /** 必填字段列表 */ - required: string[]; -} - -// 图标配置类型定义 -export interface IconConfig { - /** 图标尺寸 */ - size: { - /** 宽度 */ - width: number; - - /** 高度 */ - height: number; - }; - - /** 支持的文件格式 */ - format: string[]; - - /** 最大文件大小(KB) */ - maxSize: number; -} - -// 告警等级配置类型定义 -export interface AlertLevelConfig { - /** 等级定义 */ - levels: Record; - - /** 默认等级 */ - default: string; -} - -// 监控项配置类型定义 -export interface MonitorItemConfig { - /** 监控项列表 */ - items: Array<{ - /** 监控项名称 */ - name: string; - - /** 描述 */ - description: string; - - /** 监控项类型 */ - type: string; - - /** 单位 */ - unit: string; - - /** 默认是否启用 */ - defaultEnabled: boolean; - - /** 默认阈值 */ - defaultThresholds?: { - /** 最小阈值 */ - min?: number; - - /** 最大阈值 */ - max?: number; - }; - }>; -} - -// 常用语列表类型定义 -export interface CommonPhrase { - /** 常用语ID */ - id: string; - - /** 分类 */ - category: string; - - /** 内容 */ - content: string; - - /** 标签列表 */ - tags: string[]; -} - -// SLA配置类型定义 -export interface SLAConfig { - /** 响应时间(分钟) */ - responseTime: number; - - /** 解决时间(分钟) */ - resolveTime: number; - - /** 工作时间 */ - workingHours: { - /** 开始时间(HH:mm) */ - start: string; - - /** 结束时间(HH:mm) */ - end: string; - - /** 工作日(0-6,0代表周日) */ - workDays: number[]; - }; - - /** 升级规则 */ - escalationRules: Array<{ - /** 超时时间(分钟) */ - timeout: number; - - /** 动作 */ - action: string; - - /** 目标(如用户ID、角色等) */ - target: string[]; - }>; -} - -// 流程配置类型定义 -export interface WorkflowConfig { - /** 流程步骤 */ - steps: Array<{ - /** 步骤名称 */ - name: string; - - /** 允许操作的角色 */ - roles: string[]; - - /** 可执行的动作 */ - actions: string[]; - - /** 下一步可能的步骤 */ - nextSteps: string[]; - - /** 自动超时时间(分钟) */ - autoTimeout?: number; - }>; - - /** 初始步骤 */ - initialStep: string; -} - -// 告警处理记录表 -export interface AlertHandleLog { - /** 主键ID */ - id: number; - - /** 关联的告警ID */ - alert_id: number; - - /** 处理人ID */ - handler_id: number; - - /** 处理类型 */ - handle_type: HandleType; - - /** 问题类型 */ - problem_type: ProblemType; - - /** 处理结果 */ - handle_result?: string; - - /** 附件列表 */ - attachments?: Attachment[]; - - /** 是否禁用通知 (0否 1是) */ - notify_disabled?: number; - - /** 禁用的通知项配置 */ - notify_items?: NotifyItem[]; - - /** 处理时间 */ - handle_time: Date; - - /** 是否删除 (0否 1是) */ - is_deleted?: DeleteStatus; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 告警通知配置表 -export interface AlertNotifyConfig { - /** 主键ID */ - id: number; - - /** 关联的设备ID */ - device_id: number; - - /** 告警等级 */ - alert_level: AlertLevel; - - /** 通知类型 */ - notify_type: NotifyType; - - /** 通知模板 */ - notify_template?: string; - - /** 通知用户ID列表 */ - notify_users?: number[]; - - /** 短信通知手机号(当notify_type为SMS时使用) */ - phone_number?: string; - - /** 是否启用 (0否 1是) */ - is_enabled?: EnableStatus; - - /** 是否删除 (0否 1是) */ - is_deleted?: DeleteStatus; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 设备告警规则表 -export interface DeviceAlertRule { - /** 主键ID */ - id: number; - - /** 关联的设备ID */ - device_id: number; - - /** 监控指标类型 */ - metric_type: string; - - /** 最小阈值 */ - min_value?: number; - - /** 最大阈值 */ - max_value?: number; - - /** 持续时间(秒) */ - duration_seconds?: number; - - /** 告警等级 */ - alert_level: AlertLevel; - - /** 告警消息模板 */ - alert_message?: string; - - /** 是否启用 (0否 1是) */ - is_enabled?: EnableStatus; - - /** 是否删除 (0否 1是) */ - is_deleted?: DeleteStatus; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 设备告警记录表 -export interface DeviceAlert { - /** 主键ID */ - id: number; - - /** 关联的设备ID */ - device_id: number; - - /** 设备名称 */ - device_name: string; - - /** 监控指标类型 */ - metric_type: string; - - /** 触发值 */ - metric_value: number; - - /** 告警等级 */ - alert_level: AlertLevel; - - /** 告警消息 */ - alert_message: string; - - /** 状态 */ - status: AlertStatus; - - /** 是否删除 (0否 1是) */ - is_deleted?: DeleteStatus; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 设备分类图标表 -export interface DeviceCategoryIcon { - /** 主键ID */ - id: number; - - /** 关联的设备分类ID */ - category_id: number; - - /** 分类图标 */ - icon?: string; - - /** 图标名称 */ - icon_name?: string; - - /** 图标类型(svg/url等) */ - icon_type?: string; - - /** 排序 */ - sort?: number; - - /** 是否为默认图标 (0否 1是) */ - is_default?: number; - - /** 是否禁用 (0否 1是) */ - is_disabled?: number; - - /** 是否被删除 (0否 1是) */ - is_deleted?: number; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - - -// 设备实例表 -export interface DeviceInstance { - /** 关联资产ID */ - id: number; - - /** 设备类型ID */ - type_id: number; - - /** 通信协议(SNMP/HTTP/RS485/TCP等) */ - protocol: DeviceProtocolType; - - /** 通信地址 */ - address: string; - - /** 状态地址 */ - status_address?: string; - - /** 连接配置 */ - connection_config?: string; - - /** 采集间隔(秒) */ - collect_interval?: number; - - /** 最后采集时间 */ - last_collect_time?: Date; - - /** 备注 */ - remark?: string; - - /** 是否启用 (0否 1是) */ - is_enabled?: number; - - /** 是否删除 (0否 1是) */ - is_deleted?: number; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; - - /** 资产名称(来自zichan_info表) */ - asset_name?: string; - - /** 设备分类(来自zichan_info表) */ - device_category?: DeviceCategory; - - /** 归属区域(来自zichan_info表) */ - area?: AreaType; - - /** 供应商(来自zichan_info表) */ - supplier?: string; - - /** 设备状态(来自zichan_info表) */ - device_status?: DeviceStatus; -} - -// 设备监控数据表 -export interface DeviceMonitorData { - /** 主键ID */ - id: number; - - /** 关联的设备ID */ - device_id: number; - - /** 监控指标类型(temperature/humidity/smoke/water等) */ - metric_type: string; - - /** 监控值 */ - metric_value: number; - - /** 单位 */ - unit?: string; - - /** 状态 */ - status?: DeviceStatus; - - /** 采集时间 */ - collect_time: Date; - - /** 是否删除 (0否 1是) */ - is_deleted?: DeleteStatus; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 设备类型表 -export interface DeviceType { - /** 主键ID */ - id: number; - - /** 类型名称 */ - name: string; - - /** 类型编码 */ - code: string; - - /** 设备类型图片URL */ - image_url?: string; - - /** 类型描述 */ - description?: string; - - /** 是否启用 (0否 1是) */ - is_enabled?: number; - - /** 是否删除 (0否 1是) */ - is_deleted?: number; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 操作日志表 -export interface OperationLog { - /** 主键ID */ - id: number; - - /** 操作人ID */ - operator_id: number; - - /** 操作类型 */ - operation_type: string; - - /** 操作内容 */ - operation_content?: string; - - /** 操作结果 */ - operation_result?: string; - - /** 操作IP */ - ip_address?: string; - - /** 是否删除 (0否 1是) */ - is_deleted?: number; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 机柜信息表 -export interface RackInfo { - /** 主键ID */ - id: number; - - /** 机柜名称 */ - rack_name?: string; - - /** 机柜编号 */ - rack_code?: string; - - /** 机柜可容纳设备数量,默认42U */ - capacity?: number; - - /** 机柜X轴位置坐标 */ - position_x?: number; - - /** 机柜Y轴位置坐标 */ - position_y?: number; - - /** 机柜Z轴位置坐标 */ - position_z?: number; - - /** 机柜所在区域 */ - area?: string; - - /** 机柜所在机房 */ - room?: string; - - /** 备注信息 */ - remark?: string; - - /** 是否禁用 (0否 1是) */ - is_disabled?: EnableStatus; - - /** 是否被删除 (0否 1是) */ - is_deleted?: DeleteStatus; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 机柜服务器表 -export interface RackServer { - /** 主键ID */ - id: number; - - /** 关联的机柜ID */ - rack_id: number; - - /** 关联的资产ID */ - asset_id: number; - - /** 设备安装的起始U位 */ - start_position: number; - - /** 设备占用U数 */ - size?: number; - - /** 服务器类型 */ - server_type?: number; - - /** 备注信息 */ - remark?: string; - - /** 是否禁用 (0否 1是) */ - is_disabled?: EnableStatus; - - /** 是否被删除 (0否 1是) */ - is_deleted?: DeleteStatus; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 机柜服务器类型表 -export interface RackServerType { - /** 主键ID */ - id: number; - - /** 类型名称 */ - name: string; - - /** 类型编码 */ - code: string; - - /** 类型图片 */ - image_url?: string; - - /** 类型描述 */ - description?: string; - - /** 是否启用 (0否 1是) */ - is_enabled?: EnableStatus; - - /** 是否被删除 (0否 1是) */ - is_deleted?: DeleteStatus; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// // 工单表 -// export interface WorkOrder { -// /** 主键ID */ -// id: number; - -// /** 工单标题 */ -// title: string; - -// /** 关联设备ID */ -// device_id?: number; - -// /** 关联告警ID */ -// alert_id?: number; - -// /** 工单模板ID */ -// template_id?: number; - -// /** 工单内容 */ -// content?: string; - -// /** 工单状态 */ -// status: WorkOrderStatus; - -// /** 优先级 */ -// priority: WorkOrderPriority; - -// /** 创建人ID */ -// creator_id: number; - -// /** 处理人ID */ -// handler_id?: number; - -// /** 审核人ID */ -// auditor_id?: number; - -// /** 截止时间 */ -// deadline?: Date; - -// /** 处理结果 */ -// handle_result?: string; - -// /** 审核结果 */ -// audit_result?: string; - -// /** 是否删除 (0否 1是) */ -// is_deleted?: number; - -// /** 创建时间 */ -// created_at: Date; - -// /** 更新时间 */ -// updated_at: Date; -// } - -// // 工单处理记录表 -// export interface WorkOrderLog { -// /** 主键ID */ -// id: number; - -// /** 工单ID */ -// work_order_id: number; - -// /** 操作人ID */ -// operator_id: number; - -// /** 操作类型 */ -// action: WorkOrderAction; - -// /** 处理内容 */ -// content?: string; - -// /** 是否删除 (0否 1是) */ -// is_deleted?: number; - -// /** 创建时间 */ -// created_at: Date; - -// /** 更新时间 */ -// updated_at: Date; -// } - -// // 工单模板表 -// export interface WorkOrderTemplate { -// /** 主键ID */ -// id: number; - -// /** 模板名称 */ -// name: string; - -// /** 模板内容 */ -// content?: string; - -// /** 是否需要审核 (0否 1是) */ -// need_audit: number; - -// /** 默认处理人 */ -// default_handler_id?: number; - -// /** 默认完成时限(小时) */ -// default_deadline_hours?: number; - -// /** 常用语列表 */ -// common_phrases?: CommonPhrase[]; - -// /** SLA配置 */ -// sla_config?: SLAConfig; - -// /** 流程配置 */ -// workflow_config?: WorkflowConfig; - -// /** 是否启用 (0否 1是) */ -// is_enabled?: number; - -// /** 是否删除 (0否 1是) */ -// is_deleted?: number; - -// /** 创建时间 */ -// created_at: Date; - -// /** 更新时间 */ -// updated_at: Date; -// } - -// 资产信息表 -export interface ZichanInfo { - /** 主键ID */ - id: number; - - /** 资产名称 */ - asset_name?: string; - - /** 设备分类 */ - device_category?: DeviceCategory; - - /** 归属区域 */ - area?: AreaType; - - /** 供应商 */ - supplier?: string; - - /** 使用地址 */ - use_address?: string; - - /** 运行情况 */ - operation_status?: string; - - /** 是否审核 (0否 1是) */ - is_audited?: number; - - /** 审核状态 */ - audit_status?: AuditStatus; - - /** 资产状态 */ - asset_status?: AssetStatus; - - /** 入库数量 */ - stock_quantity?: number; - - /** 质保时间 */ - warranty_time?: Date; - - /** 品牌 */ - brand?: string; - - /** IP地址 */ - ip_address?: string; - - /** 设备状态 */ - device_status?: DeviceStatus; - - /** 网络状态 */ - network_status?: NetworkStatus; - - /** 丢包率 */ - packet_loss?: number; - - /** 图片 */ - images?: string; - - /** 是否备件 (0否 1是) */ - is_spare?: number; - - /** 是否被禁用 (0否 1是) */ - is_disabled?: number; - - /** 是否被删除 (0否 1是) */ - is_deleted?: number; - - /** 资产位置经度 */ - longitude?: number; - - /** 资产位置纬度 */ - latitude?: number; - - /** CPU信息 */ - cpu?: string; - - /** 内存信息 */ - memory?: string; - - /** 硬盘信息 */ - disk?: string; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 资产分类表 -export interface ZichanCategory { - /** 主键ID */ - id: number; - - /** 分类名称 */ - name: string; - - /** 分类编码 */ - code: string; - - /** 分类图片 */ - image_url?: string; - - /** 分类描述 */ - description?: string; - - /** 是否启用 (0否 1是) */ - is_enabled?: EnableStatus; - - /** 是否被删除 (0否 1是) */ - is_deleted?: DeleteStatus; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 资产归属区域 -export interface ZichanArea { - /** 主键ID */ - id: number; - - /** 区域名称 */ - name: string; - - /** 区域编码 */ - code: string; - - /** 区域图片 */ - image_url?: string; - - /** 区域描述 */ - description?: string; - - /** 是否启用 (0否 1是) */ - is_enabled?: EnableStatus; - - /** 是否被删除 (0否 1是) */ - is_deleted?: DeleteStatus; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; -} - -// 资产流转记录表 -export interface ZichanTransLog { - /** 主键ID */ - id: number; - - /** 资产流转 */ - asset_transfer?: AssetTransferType; - - /** 资产ID */ - asset_id?: number; - - /** 人员 */ - person?: string; - - /** 部门 */ - department?: string; - - /** 电话 */ - phone?: string; - - /** 流转事由 */ - transfer_reason?: string; - - /** 流转时间 */ - transfer_time?: Date | string; - - /** 是否被禁用 (0否 1是) */ - is_disabled?: number; - - /** 是否被删除 (0否 1是) */ - is_deleted?: number; - - /** 创建时间 */ - created_at: Date; - - /** 更新时间 */ - updated_at: Date; - - /** 关联的资产信息(查询时后端关联返回) */ - asset_info?: ZichanInfo; -} - -// 文件库接口 -export interface FileLibrary { - /** 主键ID */ - id: number; - - /** 文件名称 */ - file_name: string; - - /** 原始文件名 */ - original_filename?: string; - - /** 文件路径 */ - file_path: string; - - /** 文件类型 */ - file_type: string; - - /** 文件大小(字节) */ - file_size: number; - - /** 上传用户ID */ - uploader_id?: number; - - /** 上传者名称 */ - uploader_name?: string; - - /** 文件分类 */ - category_id?: number; - - /** 文件标签 */ - tags?: string; - - /** 文件描述 */ - description?: string; - - /** 下载次数 */ - download_count: number; - - /** 是否禁用 (0否 1是) */ - is_disabled?: EnableStatus; - - /** 是否被删除 (0否 1是) */ - is_deleted?: DeleteStatus; - - /** 创建时间 */ - created_at: string; - - /** 更新时间 */ - updated_at: string; -} - -// 文件分类接口 -export interface FileCategory { - id: number; - name: string; - code: string; - description?: string; - is_deleted?: DeleteStatus; - created_at: string; - updated_at: string; -} - -// 资产流转类型枚举 -export enum AssetTransferType { - STOCK = 0, // 在库 - BORROW = 1, // 借用 - RETURN = 2, // 归还 - LOST = 3, // 遗失 - MAINTAIN = 4 // 维护保养 -} - -// 资产流转类型名称映射 -export const AssetTransferTypeNameMap: Record = { - [AssetTransferType.STOCK]: '在库', - [AssetTransferType.BORROW]: '借用', - [AssetTransferType.RETURN]: '归还', - [AssetTransferType.LOST]: '遗失', - [AssetTransferType.MAINTAIN]: '维护保养' -}; - -// 资产流转类型颜色映射 -export const AssetTransferTypeColorMap: Record = { - [AssetTransferType.STOCK]: 'green', - [AssetTransferType.BORROW]: 'blue', - [AssetTransferType.RETURN]: 'cyan', - [AssetTransferType.LOST]: 'red', - [AssetTransferType.MAINTAIN]: 'orange' -}; - -// 添加图表类型定义(从大屏移植) -export interface CategoryChartData { - 设备分类: string; - 设备数: number; -} - -export interface CategoryChartDataWithPercent extends CategoryChartData { - 百分比: string; -} - -export interface OnlineRateChartData { - time_interval: string; - online_devices: number; - total_devices: number; -} - -export interface StateChartData { - 资产流转: string; - 设备数: number; -} - -export interface StateChartDataWithPercent extends StateChartData { - 百分比: string; -} - -export interface AlarmChartData { - time_interval: string; - total_devices: number; -} - -export interface AlarmDeviceData { - deviceName: string; - alarmCount: number; - rank: number; -} - -// 设备与资产信息结合的接口 -export interface DeviceWithAssetInfo { - id: number; - asset_name?: string; - device_category?: number; - ip_address?: string; - device_status?: DeviceStatus; - network_status?: NetworkStatus; - packet_loss?: PacketLossStatus; - cpu?: string; - memory?: string; - disk?: string; - is_deleted?: number; -} - -// 地图标记数据接口 - 基础定义 -export interface MarkerData { - longitude: number; - latitude: number; - isOnline?: string; - asset_name?: string; - type_image_url?: string; -} - -// 设备地图监控视图设备接口 -export interface MapViewDevice extends MarkerData { - id: number; - name?: string; - type_code: string; - device_category?: DeviceCategory; - device_status?: DeviceStatus; - description?: string; - address?: string; - protocol?: DeviceProtocolType; - last_update_time?: string; - area_code?: string; - area_name?: string; - image_url?: string; -} - -// 设备地图筛选条件 -export interface DeviceMapFilter { - type_code?: string; - device_category?: DeviceCategory[]; - device_status?: DeviceStatus; - area_code?: string[]; - keyword?: string; - device_id?: number; -} - -// 设备地图统计数据接口 -export interface DeviceMapStats { - total: number; - online: number; - offline: number; - error: number; - normal?: number; - fault?: number; - categoryStats?: { - category: DeviceCategory; - count: number; - name: string; - }[]; -} - -// 设备树统计数据类型 -export type DeviceTreeStats = Record; - -// 设备地图响应数据接口 -export interface DeviceMapDataResponse { - data: MapViewDevice[]; - stats: DeviceMapStats; - total?: number; - page?: number; - pageSize?: number; -} - -// 设备地图统计响应接口 -export interface DeviceMapStatsResponse { - data: DeviceMapStats; -} - -// 设备树节点类型枚举 -export enum DeviceTreeNodeType { - CATEGORY = 'category', - DEVICE = 'device' -} - -// 设备树节点状态枚举 -export enum DeviceTreeNodeStatus { - NORMAL = 'normal', - ERROR = 'error', - OFFLINE = 'offline', - WARNING = 'warning' -} - -// 设备树节点接口 -export interface DeviceTreeNode { - key: string; - title: string; - type: DeviceTreeNodeType; - status?: DeviceTreeNodeStatus; - icon?: string | null; - isLeaf?: boolean; - children?: DeviceTreeNode[]; -} - -export interface DeadlineInfo { - /** 进度百分比 */ - progress: number; - /** 剩余时间 */ - remainingTime: string; - /** 是否超时 */ - isOverdue: boolean; - /** 进度颜色 */ - color: string; - /** 进度文本 */ - text: string; -} - -export interface WorkOrderStatusHistory { - /** 状态 */ - status: WorkOrderStatus; - /** 操作人 */ - operator: string; - /** 操作时间 */ - operateTime: string; - /** 备注 */ - remark?: string; -} - -export interface WorkOrder { - /** 工单ID */ - id: string; - - /** 工单编号 */ - order_no: string; - - /** 工单标题 */ - title: string; - - /** 关联设备ID */ - device_id?: string; - - /** 设备名称 */ - device_name: string; - - /** 问题描述 */ - problem_desc: string; - - /** 问题分类 */ - problem_type: string; - - /** 故障等级 */ - priority: WorkOrderPriority; - - /** 工单状态 */ - status: WorkOrderStatus; - - /** 创建人ID */ - creator_id: string; - - /** 创建人姓名 */ - creator_name: string; - - /** 截止日期 */ - deadline: string; - - /** 创建时间 */ - created_at: string; - - /** 更新时间 */ - updated_at: string; - - /** 结果反馈 */ - feedback?: string; - - /** 附件列表 */ - attachments?: Array<{ - id: string; - name: string; - url: string; - size: number; - type: string; - }>; - - /** 当前处理人ID */ - assignee_id?: string; - - /** 当前处理人姓名 */ - assignee_name?: string; - - /** 状态历史记录 */ - statusHistory?: Array<{ - status: string; - timestamp: string; - operator: string; - }>; -} - -export interface WorkOrderSettings { - statusOptions: string[]; - priorityOptions: string[]; -} \ No newline at end of file