# 运维监控看板 — 现状核查与验证计划 ## 背景 本轮会话目标:在 `batch_query.html` 数据看板中新增「📈 运维监控」Tab,通过调用存储过程 `sp_GetOperationsMonitor()` 将每日运营监控数据展示在界面上,且不影响其他模块。 经核查,上一轮会话已完成全部代码实现,**无需重复开发**。本计划仅针对「核查发现的问题」进行修复和补充。 --- ## 一、已完成内容(已核实,无需修改) | 层级 | 文件 | 状态 | |------|------|------| | 数据库层 | `database/migrations/003_add_join_indexes.sql` | ✅ 已建 | | 数据库层 | `database/migrations/004_create_sp_operations_monitor.sql`(472行) | ✅ 已建 | | 调用入口 | `运营监控_优化版.sql` | ✅ 已建 | | DTO | `src/MDL/DTOs/OpsMonitorDto.cs` | ✅ 已建(13个字段) | | Repository 接口 | `src/DAL/Interfaces/ILabelReplaceRepository.cs` 第171行 | ✅ 已追加 | | Repository 实现 | `src/DAL/repositories/LabelReplaceRepository.cs`(第1664-1702行) | ✅ 已实现 | | Service 接口 | `src/BLL/Interfaces/ILabelReplaceService.cs` 第134行 | ✅ 已追加 | | Service 实现 | `src/BLL/Services/LabelReplaceService.cs`(第1044-1055行) | ✅ 已实现 | | Controller | `src/CONTROLLER/Controllers/DashboardController.cs`(第368-414行) | ✅ 已追加 | | 前端 Tab 按钮 | `batch_query.html` 第786行 | ✅ 已追加 | | 前端 Tab 面板 | `batch_query.html` 第1819-1884行(4卡片+13列表格) | ✅ 已追加 | | 前端 JS 逻辑 | `batch_query.html` 第4745-4867行 | ✅ 已追加 | --- ## 二、当前核查发现的问题 ### 问题1:`loadOpsMonitorData()` 使用 JSONP,但同域部署时更推荐直接 JSON **发现**:前端 `loadOpsMonitorData()` 使用 `dataType: 'jsonp'`,如果 `batch_query.html` 与后端同域部署,JSONP 会正常工作(后端已支持 callback 参数),但如果浏览器从本地 `file://` 协议打开,JSONP 会由于浏览器安全限制失败。 **当前后端**:`DashboardController.GetOpsMonitorData` 已支持 JSONP(`callback` 参数)和直接 JSON 两种模式。 **结论**:JSONP 模式在同域或跨域部署时均可工作,不影响功能。**无需修改**。 --- ### 问题2:`loadOpsMonitorData()` 中 `_opsMonitorLoaded = true` 设置时机 **发现**:`_opsMonitorLoaded` 在请求成功后设为 `true`,意味着只要成功加载过一次,切换 Tab 不再自动重新加载(懒加载设计)。用户可通过「🔄 刷新数据」按钮手动刷新。 **结论**:这是预期的懒加载行为,符合其他 Tab 的设计模式。**无需修改**。 --- ### 问题3(需要确认):`data[0]` 作为「今日」数据的假设 **发现**:`displayOpsMonitorTable(data)` 中用 `var today = data[0]` 作为今日汇总卡片数据来源,依赖存储过程 `ORDER BY dm.日期 DESC` 返回最新数据在第一行。 **存储过程末尾**:已确认使用 `ORDER BY dm.日期 DESC`,第一行确实是最新日期数据。**逻辑正确,无需修改**。 --- ### 问题4(需要修复):`data[0]` 的字段名大小写 **发现**:前端 JS 中使用 `today.ShouldReplaceCount`、`today.DailySuccessCount` 等驼峰命名,但 ASP.NET Core 默认的 `System.Text.Json` 序列化器使用**属性原始名称(PascalCase)**,而非 camelCase。 **后端 DTO 字段**(以 PascalCase 定义): ```csharp public string Date { get; set; } public int ShouldReplaceCount { get; set; } // ... ``` **ASP.NET Core 默认行为**:`System.Text.Json.JsonSerializer.Serialize()` 默认保留 PascalCase,即 JSON 输出为 `ShouldReplaceCount`,与前端 `today.ShouldReplaceCount` 一致。 **结论**:字段名匹配,**无需修改**。 --- ## 三、实施步骤 由于核查未发现需要修复的代码问题,本计划的实施步骤聚焦于**确保代码完整性**: ### 步骤 1:确认 batch_query.html Tab 结构完整 - 验证第786行 Tab 按钮代码存在且格式正确 - 验证第1819-1884行 Tab 面板代码完整 - 验证第4745-4867行 JS 函数完整 ### 步骤 2:确认后端三层代码完整 - 确认 `OpsMonitorDto.cs` 命名空间为 `MDL.DTOs`(已修复) - 确认 `DashboardController.cs` 顶部有 `using MDL.DTOs;`(已修复) - 确认无编译诊断错误 ### 步骤 3:确认存储过程文件完整 - `004_create_sp_operations_monitor.sql`(472行)结构完整,含 DELIMITER 和 END$$ --- ## 四、数据流架构图 ``` 浏览器 batch_query.html │ │ 切换到「📈 运维监控」Tab(首次触发懒加载) │ 或点击「🔄 刷新数据」按钮 │ ↓ GET /api/dashboard/ops-monitor?callback=jQuery_xxx (JSONP) │ ASP.NET Core DashboardController.GetOpsMonitorData() │ ↓ await _labelReplaceService.GetOpsMonitorDataAsync() │ LabelReplaceService.GetOpsMonitorDataAsync() │ ↓ await _labelReplaceRepository.GetOpsMonitorDataAsync() │ LabelReplaceRepository(直接使用 MySqlConnection) │ ↓ CALL sp_GetOperationsMonitor(); (CommandTimeout=120s) │ MySQL 8.0 存储过程 │ 临时表链路: │ tmp_scan_agg → tmp_daily_scan → tmp_form_order │ → tmp_form_first_scan → tmp_form_stats │ → tmp_form_push_ranked → tmp_order_full │ → tmp_should_replace_dedup → tmp_label_push → tmp_daily_metrics │ ↓ SELECT 13列数据 ORDER BY 日期 DESC │ List → JSON → JSONP 包装 │ ↓ 返回浏览器 │ displayOpsMonitorTable(data) │ ├─ 4张汇总卡片(今日应换单数/完成数/24H成功数/完成率) │ └─ 13列历史数据表格(完成率≥80%绿色/<50%红色) ``` --- ## 五、不影响其他模块的保证 1. **Tab 按钮**:独立 `
  • ` 元素追加到导航栏末尾,不修改现有 Tab 2. **Tab 面板**:独立 `
    ` 追加,不修改现有面板 3. **JS 函数**:`loadOpsMonitorData`、`displayOpsMonitorTable`、`exportOpsMonitorToExcel` 均为新增,无同名冲突 4. **变量名**:`_opsMonitorLoaded`、`_opsMonitorData` 前缀唯一,无冲突 5. **元素 ID**:`opsMonitorTableBody`、`opsCard_*`、`opsMonitorFetchTime` 均为新增,无冲突 6. **后端接口**:新增 `GET /api/dashboard/ops-monitor`,不修改现有接口 7. **数据库**:存储过程 `sp_GetOperationsMonitor` 为新增,不修改现有表结构 --- ## 六、部署前置条件 在运行前,需确保以下操作已在数据库执行: ```sql -- 1. 添加索引(003文件) ALTER TABLE label_replace_requests ADD INDEX IF NOT EXISTS idx_bill_of_lading_number (BillOfLadingNumber), ADD INDEX IF NOT EXISTS idx_master_package_number (MasterPackageNumber); -- 2. 创建存储过程(执行 004 文件全部内容) -- CALL sp_GetOperationsMonitor(); -- 验证用 ``` --- **计划状态**:代码实现已全部完成,无新增修改项,仅需确认文件完整性。