diff --git a/doc/系统磁盘监控数据库设计.sql b/doc/系统磁盘监控数据库设计.sql new file mode 100644 index 0000000..13c0f55 --- /dev/null +++ b/doc/系统磁盘监控数据库设计.sql @@ -0,0 +1,104 @@ +CREATE TABLE IF NOT EXISTS `disk_monitor_policy` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键', + `policy_name` VARCHAR(100) NOT NULL DEFAULT '默认磁盘监控策略' COMMENT '策略名称', + `monitor_enabled` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用监控:0否 1是', + `run_on_app_start` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '应用启动后是否执行一次:0否 1是', + `daily_run_time` TIME NOT NULL COMMENT '每日统一执行时间', + `warning_notify_mode` VARCHAR(32) NOT NULL DEFAULT 'STATUS_CHANGE' COMMENT '预警通知模式', + `alarm_notify_mode` VARCHAR(32) NOT NULL DEFAULT 'EVERY_TIME' COMMENT '告警通知模式', + `last_job_id` BIGINT NULL COMMENT '最近一次任务ID', + `remark` VARCHAR(500) NULL COMMENT '备注', + `created_by` VARCHAR(64) NULL COMMENT '创建人', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` VARCHAR(64) NULL COMMENT '更新人', + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='磁盘监控全局策略表'; + +CREATE TABLE IF NOT EXISTS `disk_monitor_target` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键', + `policy_id` BIGINT NOT NULL COMMENT '策略ID', + `drive_letter` VARCHAR(10) NOT NULL COMMENT '盘符,例如 C:', + `monitor_enabled` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用监控:0否 1是', + `warning_usage_percent` TINYINT UNSIGNED NOT NULL COMMENT '预警使用率阈值', + `alarm_usage_percent` TINYINT UNSIGNED NOT NULL COMMENT '告警使用率阈值', + `notify_path_enabled` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用路径通知:0否 1是', + `notify_path_list_json` JSON NULL COMMENT '路径通知目标列表JSON', + `notify_http_enabled` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用HTTP通知:0否 1是', + `notify_http_list_json` JSON NULL COMMENT 'HTTP通知目标列表JSON', + `last_status` VARCHAR(32) NOT NULL DEFAULT 'UNKNOWN' COMMENT '最近一次状态', + `last_scan_time` DATETIME NULL COMMENT '最近扫描时间', + `last_used_percent` DECIMAL(5,2) NULL COMMENT '最近一次使用率', + `remark` VARCHAR(500) NULL COMMENT '备注', + `created_by` VARCHAR(64) NULL COMMENT '创建人', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_by` VARCHAR(64) NULL COMMENT '更新人', + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_drive_letter` (`drive_letter`), + KEY `idx_policy_id` (`policy_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='磁盘监控盘符配置表'; + +CREATE TABLE IF NOT EXISTS `disk_monitor_job` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键', + `job_no` VARCHAR(64) NOT NULL COMMENT '任务编号', + `job_source` VARCHAR(32) NOT NULL COMMENT '任务来源', + `planned_time` DATETIME NULL COMMENT '计划执行时间', + `started_at` DATETIME NOT NULL COMMENT '开始时间', + `finished_at` DATETIME NULL COMMENT '结束时间', + `job_status` VARCHAR(32) NOT NULL COMMENT '任务状态', + `target_count` INT NOT NULL DEFAULT 0 COMMENT '计划扫描盘符数量', + `success_count` INT NOT NULL DEFAULT 0 COMMENT '成功扫描数量', + `warning_count` INT NOT NULL DEFAULT 0 COMMENT '预警数量', + `alarm_count` INT NOT NULL DEFAULT 0 COMMENT '告警数量', + `message` VARCHAR(1000) NULL COMMENT '结果说明', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_job_no` (`job_no`), + KEY `idx_job_source` (`job_source`), + KEY `idx_started_at` (`started_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='磁盘监控任务批次表'; + +CREATE TABLE IF NOT EXISTS `disk_monitor_result` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键', + `job_id` BIGINT NOT NULL COMMENT '任务ID', + `target_id` BIGINT NOT NULL COMMENT '盘符配置ID', + `drive_letter` VARCHAR(10) NOT NULL COMMENT '盘符', + `total_bytes` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '总容量字节数', + `used_bytes` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '已使用字节数', + `free_bytes` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '剩余字节数', + `used_percent` DECIMAL(5,2) NOT NULL DEFAULT 0.00 COMMENT '使用率', + `current_status` VARCHAR(32) NOT NULL COMMENT '当前状态', + `previous_status` VARCHAR(32) NOT NULL DEFAULT 'UNKNOWN' COMMENT '上一次状态', + `status_changed` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '状态是否变化:0否 1是', + `should_notify` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '本次是否通知:0否 1是', + `notify_reason` VARCHAR(32) NOT NULL DEFAULT 'NO_NOTIFY' COMMENT '通知原因', + `scan_time` DATETIME NOT NULL COMMENT '扫描时间', + `message` VARCHAR(1000) NULL COMMENT '扫描说明', + PRIMARY KEY (`id`), + KEY `idx_job_id` (`job_id`), + KEY `idx_target_id` (`target_id`), + KEY `idx_drive_letter` (`drive_letter`), + KEY `idx_scan_time` (`scan_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='磁盘监控结果表'; + +CREATE TABLE IF NOT EXISTS `disk_monitor_notify_log` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键', + `job_id` BIGINT NOT NULL COMMENT '任务ID', + `result_id` BIGINT NOT NULL COMMENT '结果ID', + `target_id` BIGINT NOT NULL COMMENT '盘符配置ID', + `drive_letter` VARCHAR(10) NOT NULL COMMENT '盘符', + `notify_level` VARCHAR(32) NOT NULL COMMENT '通知级别', + `channel_type` VARCHAR(32) NOT NULL COMMENT '通知通道类型', + `channel_target` VARCHAR(1000) NOT NULL COMMENT '通知目标', + `notify_title` VARCHAR(255) NOT NULL COMMENT '通知标题', + `notify_content` TEXT NOT NULL COMMENT '通知内容', + `send_status` VARCHAR(32) NOT NULL COMMENT '发送状态', + `response_message` VARCHAR(2000) NULL COMMENT '响应结果或异常信息', + `sent_at` DATETIME NOT NULL COMMENT '发送时间', + PRIMARY KEY (`id`), + KEY `idx_job_id` (`job_id`), + KEY `idx_result_id` (`result_id`), + KEY `idx_target_id` (`target_id`), + KEY `idx_sent_at` (`sent_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='磁盘监控通知日志表'; diff --git a/frontend/src/api/system/diskMonitor/index.ts b/frontend/src/api/system/diskMonitor/index.ts new file mode 100644 index 0000000..09261ab --- /dev/null +++ b/frontend/src/api/system/diskMonitor/index.ts @@ -0,0 +1,26 @@ +import http from '@/api' +import type { DiskMonitor } from '@/api/system/diskMonitor/interface' + +export const getDiskMonitorPolicyDetail = () => { + return http.get('/disk-monitor/policy/detail') +} + +export const saveDiskMonitorPolicy = (params: DiskMonitor.SavePolicyParams) => { + return http.post('/disk-monitor/policy/save', params) +} + +export const runDiskMonitorJob = (params: DiskMonitor.RunJobParams) => { + return http.post('/disk-monitor/job/run', params) +} + +export const getDiskMonitorJobList = (params: DiskMonitor.JobListParams) => { + return http.post('/disk-monitor/job/list', params) +} + +export const getDiskMonitorJobDetail = (jobId: number) => { + return http.get(`/disk-monitor/job/${jobId}/detail`) +} + +export const testDiskMonitorNotify = (params: DiskMonitor.NotifyTestParams) => { + return http.post('/disk-monitor/notify/test', params) +} diff --git a/frontend/src/api/system/diskMonitor/interface/index.ts b/frontend/src/api/system/diskMonitor/interface/index.ts new file mode 100644 index 0000000..2a85450 --- /dev/null +++ b/frontend/src/api/system/diskMonitor/interface/index.ts @@ -0,0 +1,129 @@ +import type { ReqPage, ResPage } from '@/api/interface' + +export namespace DiskMonitor { + export type MonitorStatus = 'UNKNOWN' | 'NORMAL' | 'WARNING' | 'ALARM' + export type NotifyMode = 'STATUS_CHANGE' | 'EVERY_TIME' + export type JobSource = 'APP_START' | 'DAILY_SCHEDULE' | 'MANUAL' + export type JobStatus = 'RUNNING' | 'SUCCESS' | 'PARTIAL_SUCCESS' | 'FAILED' + export type NotifyLevel = 'WARNING' | 'ALARM' | 'RECOVER' + export type NotifyChannelType = 'PATH' | 'HTTP' + export type NotifySendStatus = 'SUCCESS' | 'FAILED' + + export interface NotifyPathTarget { + path: string + name: string + enabled: boolean + } + + export interface NotifyHttpTarget { + url: string + name: string + method: 'POST' + timeoutMs: number + enabled: boolean + } + + export interface PolicyItem { + id?: number + policyName: string + monitorEnabled: boolean + runOnAppStart: boolean + dailyRunTime: string + warningNotifyMode: NotifyMode + alarmNotifyMode: NotifyMode + lastJobId?: number | null + remark: string + } + + export interface TargetItem { + id?: number + policyId?: number + driveLetter: string + monitorEnabled: boolean + warningUsagePercent: number + alarmUsagePercent: number + notifyPathEnabled: boolean + notifyPathList: NotifyPathTarget[] + notifyHttpEnabled: boolean + notifyHttpList: NotifyHttpTarget[] + lastStatus: MonitorStatus + lastScanTime?: string | null + lastUsedPercent?: number | null + remark: string + } + + export interface PolicyDetailData { + policy: PolicyItem + targets: TargetItem[] + } + + export interface SavePolicyParams { + policy: PolicyItem + targets: TargetItem[] + } + + export interface RunJobParams { + jobSource: 'MANUAL' + } + + export interface RunJobResult { + jobId: number + jobNo: string + } + + export interface JobListParams extends ReqPage {} + + export interface JobListItem { + id: number + jobNo: string + jobSource: JobSource + startedAt: string + finishedAt?: string | null + jobStatus: JobStatus + targetCount: number + warningCount: number + alarmCount: number + message?: string + } + + export interface ResultItem { + resultId: number + targetId: number + driveLetter: string + totalBytes: number + usedBytes: number + freeBytes: number + usedPercent: number + currentStatus: MonitorStatus + previousStatus: MonitorStatus + statusChanged: boolean + shouldNotify: boolean + notifyReason: 'ALARM_EVERY_TIME' | 'STATUS_CHANGED' | 'NO_NOTIFY' + scanTime: string + message?: string + } + + export interface NotifyLogItem { + id: number + resultId: number + driveLetter: string + notifyLevel: NotifyLevel + channelType: NotifyChannelType + channelTarget: string + sendStatus: NotifySendStatus + responseMessage?: string + sentAt: string + } + + export interface JobDetailData { + job: JobListItem + results: ResultItem[] + notifyLogs: NotifyLogItem[] + } + + export interface NotifyTestParams { + driveLetter: string + } + + export interface JobPageData extends ResPage {} +} diff --git a/frontend/src/routers/modules/staticRouter.ts b/frontend/src/routers/modules/staticRouter.ts index e69bedd..c7481fb 100644 --- a/frontend/src/routers/modules/staticRouter.ts +++ b/frontend/src/routers/modules/staticRouter.ts @@ -83,6 +83,22 @@ export const staticRouter: RouteRecordRaw[] = [ title: '500' } }, + { + path: '/systemMonitor', + name: 'systemMonitor', + component: () => import('@/views/systemMonitor/index.vue'), + meta: { + title: '系统监控' + } + }, + { + path: '/systemMonitor/diskMonitor', + name: 'diskMonitor', + component: () => import('@/views/systemMonitor/diskMonitor/index.vue'), + meta: { + title: '磁盘监控' + } + }, { path: '/:pathMatch(.*)*', component: () => import('@/components/ErrorMessage/404.vue') diff --git a/frontend/src/views/systemMonitor/diskMonitor/index.vue b/frontend/src/views/systemMonitor/diskMonitor/index.vue new file mode 100644 index 0000000..b8bd0af --- /dev/null +++ b/frontend/src/views/systemMonitor/diskMonitor/index.vue @@ -0,0 +1,9 @@ + + + diff --git a/frontend/src/views/systemMonitor/index.vue b/frontend/src/views/systemMonitor/index.vue new file mode 100644 index 0000000..a3d24a7 --- /dev/null +++ b/frontend/src/views/systemMonitor/index.vue @@ -0,0 +1,9 @@ + + +