# Disk Monitor Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 在当前仓库内完成磁盘监控页面、前端 API 契约、数据库 SQL 交付文件和手工验证入口,为后端接入完整磁盘监控能力提供可直接联调的前端实现基础。 **Architecture:** 以前端单页容器 `frontend/src/views/systemMonitor/diskMonitor/index.vue` 负责编排状态、加载配置、保存配置、触发手动执行和展示历史结果;页面拆分为摘要卡片、全局策略表单、盘符编辑器、通知编辑器、任务历史与详情抽屉。后端按已确认的规格提供 `/disk-monitor/**` 接口,本仓库额外产出一份 `doc/系统磁盘监控数据库设计.sql` 作为数据库交付物。该计划不在当前仓库内实现真实磁盘扫描、定时器和通知发送逻辑,只实现页面、契约和 SQL 文件。 **Tech Stack:** Vue 3 ` ``` - [ ] **Step 3: Create the global policy form component** Create `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorPolicyForm.vue` with: ```vue ``` - [ ] **Step 4: Replace the placeholder page with container state and data loading** Replace `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\index.vue` with a container that imports the new API and components, keeping the back navigation and adding concise Chinese comments on the main business flow: ```vue ``` Expected: 页面不再显示占位摘要和占位面板,而是渲染摘要卡片和全局策略卡片,并能在挂载时请求配置与最近任务。 - [ ] **Step 5: Run the first full type-check after replacing the placeholder** Run: ```powershell cd D:\Work\SourceCode\CN_Tool_client\frontend npm run type-check ``` Expected: 允许失败原因为“盘符编辑组件和任务列表组件尚未创建”,不允许出现 `form.ts`、`DiskMonitorSummary.vue`、`DiskMonitorPolicyForm.vue` 的类型错误。 - [ ] **Step 6: Commit the page state skeleton** Run: ```powershell git add D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\utils\form.ts D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorSummary.vue D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorPolicyForm.vue D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\index.vue git commit -m "feat: scaffold disk monitor page state" ``` ## Task 3: Build The Target Editor And Notification Editors **Files:** - Create: `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\NotificationPathEditor.vue` - Create: `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\NotificationHttpEditor.vue` - Create: `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorTargetDialog.vue` - Create: `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorTargetTable.vue` - Modify: `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\index.vue` - [ ] **Step 1: Create the path notification array editor** Create `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\NotificationPathEditor.vue` with: ```vue ``` Expected: 组件支持新增、删除、编辑路径通知目标,不自行维护状态。 - [ ] **Step 2: Create the HTTP notification array editor** Create `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\NotificationHttpEditor.vue` with: ```vue ``` - [ ] **Step 3: Create the target edit dialog** Create `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorTargetDialog.vue` with a dialog shell that hosts the two editor components: ```vue ``` Expected: 弹窗内至少包含盘符、启用开关、预警阈值、告警阈值、路径通知开关与编辑器、HTTP 通知开关与编辑器、备注。 - [ ] **Step 4: Create the target table with add/edit/delete events** Create `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorTargetTable.vue` with: ```vue ``` Expected: 表格列至少显示盘符、是否监控、预警使用率、告警使用率、当前状态、最近扫描时间、最近使用率、操作按钮。 - [ ] **Step 5: Wire target CRUD into the page container** Update `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\index.vue` to add: ```ts import { createEmptyTarget, validateTarget } from './utils/form' import DiskMonitorTargetTable from './components/DiskMonitorTargetTable.vue' import DiskMonitorTargetDialog from './components/DiskMonitorTargetDialog.vue' const targetDialogVisible = ref(false) const editingTargetIndex = ref(-1) const editingTarget = ref(createEmptyTarget()) const openAddTarget = () => { editingTargetIndex.value = -1 editingTarget.value = createEmptyTarget() targetDialogVisible.value = true } const openEditTarget = (row: DiskMonitor.TargetItem, index: number) => { editingTargetIndex.value = index editingTarget.value = JSON.parse(JSON.stringify(row)) targetDialogVisible.value = true } const confirmTarget = () => { const duplicatePool = targetList.value .filter((_, index) => index !== editingTargetIndex.value) .map(item => item.driveLetter) const error = validateTarget(editingTarget.value, duplicatePool) if (error) { ElMessage.warning(error) return } if (editingTargetIndex.value === -1) { targetList.value = [...targetList.value, JSON.parse(JSON.stringify(editingTarget.value))] } else { targetList.value = targetList.value.map((item, index) => index === editingTargetIndex.value ? JSON.parse(JSON.stringify(editingTarget.value)) : item ) } targetDialogVisible.value = false } const removeTarget = (index: number) => { targetList.value = targetList.value.filter((_, rowIndex) => rowIndex !== index) } ``` Expected: 页面可以新增、编辑、删除多个盘符,并能在保存前阻止重复盘符和非法阈值。 - [ ] **Step 6: Run lint and type-check after target editor wiring** Run: ```powershell cd D:\Work\SourceCode\CN_Tool_client\frontend npm run lint -- src/views/systemMonitor/diskMonitor/index.vue src/views/systemMonitor/diskMonitor/components/NotificationPathEditor.vue src/views/systemMonitor/diskMonitor/components/NotificationHttpEditor.vue src/views/systemMonitor/diskMonitor/components/DiskMonitorTargetDialog.vue src/views/systemMonitor/diskMonitor/components/DiskMonitorTargetTable.vue npm run type-check ``` Expected: 两个命令退出 `0`;不允许出现盘符编辑器和通知编辑器的 props/emits 类型错误。 - [ ] **Step 7: Commit the target editor slice** Run: ```powershell git add D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\NotificationPathEditor.vue D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\NotificationHttpEditor.vue D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorTargetDialog.vue D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorTargetTable.vue D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\index.vue git commit -m "feat: add disk monitor target editors" ``` ## Task 4: Add Manual Run, Job History, And Job Detail Views **Files:** - Create: `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorJobTable.vue` - Create: `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorJobDetailDrawer.vue` - Modify: `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\index.vue` - [ ] **Step 1: Create the recent job table component** Create `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorJobTable.vue` with: ```vue ``` Expected: 表格列至少包含任务编号、来源、开始时间、结束时间、状态、预警数量、告警数量和“查看详情”按钮。 - [ ] **Step 2: Create the job detail drawer** Create `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorJobDetailDrawer.vue` with: ```vue ``` Expected: 抽屉中分两块表格展示 `results` 与 `notifyLogs`,字段名与规格文档一致。 - [ ] **Step 3: Wire manual run and history loading into the page** Update `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\index.vue` with: ```ts import { getDiskMonitorJobDetail } from '@/api/system/diskMonitor' import DiskMonitorJobTable from './components/DiskMonitorJobTable.vue' import DiskMonitorJobDetailDrawer from './components/DiskMonitorJobDetailDrawer.vue' const jobList = ref([]) const jobDetailVisible = ref(false) const jobDetail = ref(null) const detailLoading = ref(false) const loadJobList = async () => { loading.jobs = true try { const resp = await getDiskMonitorJobList({ pageNum: 1, pageSize: 10 }) jobList.value = resp.data.records || [] latestJob.value = jobList.value[0] || null } finally { loading.jobs = false } } const openJobDetail = async (row: DiskMonitor.JobListItem) => { detailLoading.value = true jobDetailVisible.value = true try { const resp = await getDiskMonitorJobDetail(row.id) jobDetail.value = resp.data } finally { detailLoading.value = false } } ``` Expected: 手动执行完任务后可以刷新最近任务列表,并且可点开详情查看每个盘符结果与通知日志。 - [ ] **Step 4: Keep the page refresh flow single-sourced** Update `loadPageData` in `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\index.vue` so it only loads config + recent任务列表 once: ```ts const loadPageData = async () => { loading.init = true try { const policyResp = await getDiskMonitorPolicyDetail() policyForm.value = policyResp.data.policy targetList.value = policyResp.data.targets || [] await loadJobList() } finally { loading.init = false } } ``` Expected: 保存配置、手动执行、页面初始化都复用同一套刷新入口,不出现多处重复请求逻辑。 - [ ] **Step 5: Run the full frontend verification commands** Run: ```powershell cd D:\Work\SourceCode\CN_Tool_client\frontend npm run lint npm run type-check ``` Expected: 两个命令都退出 `0`。 - [ ] **Step 6: Commit the job history UI** Run: ```powershell git add D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorJobTable.vue D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\DiskMonitorJobDetailDrawer.vue D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\index.vue git commit -m "feat: add disk monitor job views" ``` ## Task 5: Perform Manual Verification On The Hash Route **Files:** - Verify only: `D:\Work\SourceCode\CN_Tool_client\frontend\src\routers\modules\staticRouter.ts` - Verify only: `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\index.vue` - Verify only: `D:\Work\SourceCode\CN_Tool_client\frontend\src\views\systemMonitor\diskMonitor\components\*.vue` - Verify only: `D:\Work\SourceCode\CN_Tool_client\doc\系统磁盘监控数据库设计.sql` - [ ] **Step 1: Start the frontend dev server** Run: ```powershell cd D:\Work\SourceCode\CN_Tool_client\frontend npm run dev ``` Expected: Vite 启动成功;当前开发环境使用 `hash` 路由,因此目标页面地址为 `/#/systemMonitor/diskMonitor`。 - [ ] **Step 2: Verify configuration load and save behavior** Manual checklist: ```text 1. 访问 /#/systemMonitor/diskMonitor,能看到摘要区、全局策略区、盘符列表区、最近任务区。 2. 修改“启用监控”“启动即监控”“每日执行时间”后点击“保存配置”,页面给出成功提示。 3. 新增两个盘符,例如 C: 与 D:,分别配置不同的预警/告警阈值。 4. 为其中一个盘符新增本地目录通知和 HTTP 通知目标,保存后刷新页面,配置仍正确回显。 5. 尝试录入重复盘符或告警阈值小于预警阈值,页面必须阻止提交并给出提示。 ``` Expected: 五项都成立。 - [ ] **Step 3: Verify manual run and job detail behavior** Manual checklist: ```text 1. 点击“立即执行监控”,页面提示任务已启动。 2. 最近任务列表出现一条新的 MANUAL 任务。 3. 打开任务详情抽屉,能看到盘符结果表和通知日志表。 4. 若后端暂未接通,页面应以接口错误提示结束,不得卡死或出现未捕获异常。 ``` Expected: 四项都成立。 - [ ] **Step 4: Verify the SQL artifact matches the approved spec** Run: ```powershell Get-Content -Raw D:\Work\SourceCode\CN_Tool_client\doc\系统磁盘监控数据库设计.sql Get-Content -Raw D:\Work\SourceCode\CN_Tool_client\docs\superpowers\specs\2026-04-22-disk-monitor-design.md ``` Expected: SQL 文件包含同样的五张表和字段命名:`disk_monitor_policy`、`disk_monitor_target`、`disk_monitor_job`、`disk_monitor_result`、`disk_monitor_notify_log`。 - [ ] **Step 5: Record final verification status** Run: ```powershell cd D:\Work\SourceCode\CN_Tool_client\frontend npm run lint npm run type-check git status --short ``` Expected: `lint` 和 `type-check` 退出 `0`;`git status --short` 只显示本功能相关改动和仓库原有未处理改动,不出现意外文件。 ## Self-Review - Spec coverage: 计划覆盖了静态路由兜底、前端 API 契约、数据库 SQL 文件、摘要区、全局策略区、盘符与通知编辑、手动执行、最近任务、详情抽屉和验证步骤,与已批准规格一致。 - Placeholder scan: 没有 `TODO`、`TBD`、`后续再说` 类占位语;每个任务都给了明确文件路径、代码骨架、命令和预期结果。 - Type consistency: 计划统一使用 `DiskMonitor.PolicyItem`、`DiskMonitor.TargetItem`、`DiskMonitor.JobListItem`、`DiskMonitor.JobDetailData`、`createDefaultPolicy`、`createEmptyTarget`、`validatePolicy`、`validateTarget` 等命名,没有前后不一致的接口名。