diff --git a/frontend/src/views/systemMonitor/diskMonitor/components/DiskMonitorTargetDialog.vue b/frontend/src/views/systemMonitor/diskMonitor/components/DiskMonitorTargetDialog.vue new file mode 100644 index 0000000..877fecf --- /dev/null +++ b/frontend/src/views/systemMonitor/diskMonitor/components/DiskMonitorTargetDialog.vue @@ -0,0 +1,141 @@ + + + + + patchTarget({ driveLetter: String(value).trim().toUpperCase() })" + /> + + + patchTarget({ monitorEnabled: Boolean(value) })" + /> + + + + % + + + + % + + + patchTarget({ notifyPathEnabled: Boolean(value) })" + /> + + + patchTarget({ notifyPathList: value })" + /> + + + patchTarget({ notifyHttpEnabled: Boolean(value) })" + /> + + + patchTarget({ notifyHttpList: value })" + /> + + + patchTarget({ remark: String(value) })" + /> + + + + + + + + + + + diff --git a/frontend/src/views/systemMonitor/diskMonitor/components/DiskMonitorTargetTable.vue b/frontend/src/views/systemMonitor/diskMonitor/components/DiskMonitorTargetTable.vue new file mode 100644 index 0000000..c5658ba --- /dev/null +++ b/frontend/src/views/systemMonitor/diskMonitor/components/DiskMonitorTargetTable.vue @@ -0,0 +1,127 @@ + + + + + 监控目标 + 维护需要监控的盘符与通知目标 + + 新增目标 + + + + + + + {{ row.monitorEnabled ? '是' : '否' }} + + + + + {{ row.warningUsagePercent }}% + + + + + {{ row.alarmUsagePercent }}% + + + + + + {{ getStatusLabel(row.lastStatus) }} + + + + + + {{ formatScanTime(row.lastScanTime) }} + + + + + {{ formatUsedPercent(row.lastUsedPercent) }} + + + + + 编辑 + 删除 + + + + + + + + + diff --git a/frontend/src/views/systemMonitor/diskMonitor/components/NotificationHttpEditor.vue b/frontend/src/views/systemMonitor/diskMonitor/components/NotificationHttpEditor.vue new file mode 100644 index 0000000..07f6eff --- /dev/null +++ b/frontend/src/views/systemMonitor/diskMonitor/components/NotificationHttpEditor.vue @@ -0,0 +1,133 @@ + + + + HTTP 通知目标 + 新增 HTTP 目标 + + 暂无 HTTP 通知目标 + + + patchRow(index, 'name', String(value))" + /> + patchRow(index, 'url', String(value))" + /> + patchRow(index, 'method', value as DiskMonitor.NotifyHttpTarget['method'])" + > + + + + patchRow(index, 'enabled', Boolean(value))" + /> + 删除 + + + + + + + + diff --git a/frontend/src/views/systemMonitor/diskMonitor/components/NotificationPathEditor.vue b/frontend/src/views/systemMonitor/diskMonitor/components/NotificationPathEditor.vue new file mode 100644 index 0000000..269f7e0 --- /dev/null +++ b/frontend/src/views/systemMonitor/diskMonitor/components/NotificationPathEditor.vue @@ -0,0 +1,116 @@ + + + + 路径通知目标 + 新增路径 + + 暂无路径通知目标 + + + patchRow(index, 'name', String(value))" + /> + patchRow(index, 'path', String(value))" + /> + patchRow(index, 'enabled', Boolean(value))" + /> + 删除 + + + + + + + + diff --git a/frontend/src/views/systemMonitor/diskMonitor/index.vue b/frontend/src/views/systemMonitor/diskMonitor/index.vue index f6cc6a1..8bccb31 100644 --- a/frontend/src/views/systemMonitor/diskMonitor/index.vue +++ b/frontend/src/views/systemMonitor/diskMonitor/index.vue @@ -18,6 +18,15 @@ @save="handleSave" @run="handleRun" /> + + + + @@ -34,7 +43,9 @@ import { import type { DiskMonitor } from '@/api/system/diskMonitor/interface' import DiskMonitorPolicyForm from './components/DiskMonitorPolicyForm.vue' import DiskMonitorSummary from './components/DiskMonitorSummary.vue' -import { createDefaultPolicy, validatePolicy } from './utils/form' +import DiskMonitorTargetDialog from './components/DiskMonitorTargetDialog.vue' +import DiskMonitorTargetTable from './components/DiskMonitorTargetTable.vue' +import { createDefaultPolicy, createEmptyTarget, validatePolicy, validateTarget } from './utils/form' defineOptions({ name: 'DiskMonitorPage' @@ -44,6 +55,9 @@ const router = useRouter() const policyForm = ref(createDefaultPolicy()) const targetList = ref([]) +const targetDialogVisible = ref(false) +const editingTargetIndex = ref(-1) +const editingTarget = ref(createEmptyTarget()) const latestJob = ref(null) const loading = reactive({ init: false, @@ -57,6 +71,53 @@ const handleBack = async () => { await router.push('/systemMonitor') } +const cloneTarget = (target: DiskMonitor.TargetItem): DiskMonitor.TargetItem => ({ + ...target, + notifyPathList: target.notifyPathList.map(item => ({ ...item })), + notifyHttpList: target.notifyHttpList.map(item => ({ ...item })) +}) + +const openAddTarget = () => { + editingTargetIndex.value = -1 + editingTarget.value = createEmptyTarget() + targetDialogVisible.value = true +} + +const openEditTarget = (row: DiskMonitor.TargetItem, index: number) => { + editingTargetIndex.value = index + // 编辑时克隆当前行,避免未确认前直接污染列表数据 + editingTarget.value = cloneTarget(row) + targetDialogVisible.value = true +} + +const confirmTarget = () => { + // 提交前统一规范盘符并做去重、阈值关系校验 + const normalizedDriveLetter = editingTarget.value.driveLetter.trim().toUpperCase() + const payload: DiskMonitor.TargetItem = { + ...editingTarget.value, + driveLetter: normalizedDriveLetter + } + const exists = targetList.value + .filter((_, index) => index !== editingTargetIndex.value) + .map(item => item.driveLetter.trim().toUpperCase()) + const errorMessage = validateTarget(payload, exists) + if (errorMessage) { + ElMessage.warning(errorMessage) + return + } + + if (editingTargetIndex.value >= 0) { + targetList.value.splice(editingTargetIndex.value, 1, payload) + } else { + targetList.value.push(payload) + } + targetDialogVisible.value = false +} + +const removeTarget = (index: number) => { + targetList.value.splice(index, 1) +} + const loadPolicyDetail = async () => { const response = await getDiskMonitorPolicyDetail() const detail = response.data
维护需要监控的盘符与通知目标