# 运维监控看板 — 现状核查与验证计划

## 背景

本轮会话目标：在 `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<OpsMonitorDto> → JSON → JSONP 包装
  │
  ↓ 返回浏览器
  │
displayOpsMonitorTable(data)
  │  ├─ 4张汇总卡片（今日应换单数/完成数/24H成功数/完成率）
  │  └─ 13列历史数据表格（完成率≥80%绿色/＜50%红色）
```

---

## 五、不影响其他模块的保证

1. **Tab 按钮**：独立 `<li>` 元素追加到导航栏末尾，不修改现有 Tab
2. **Tab 面板**：独立 `<div class="tab-pane">` 追加，不修改现有面板
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(); -- 验证用
```

---

**计划状态**：代码实现已全部完成，无新增修改项，仅需确认文件完整性。
