# 计划执行：检测项趋势图表显示问题修复

## 文档信息

- 创建时间：2026-07-22
- 关联问题文档：`Docs/需求文档/服务监测/PRD_问题处理_检测项趋势图表显示问题.md`
- 预计改动文件：1 个
- 预计新增文件：0 个

---

## 执行步骤

### Step 1：前端 — 折线图无数值数据时显示友好提示

**文件**：`skill/code/web/templates/service_monitor/statistics.html`

**位置**：`fetchItemTrend` 函数，数据加载后

**改动**：在渲染折线图之前，检查数据点中是否有数值数据。如果全部无数值，显示提示信息代替空白图表。

**具体逻辑**：

```javascript
// 在 fetchItemTrend 函数中，获取 data_points 后：
const numericCount = data.data_points.filter(p => p.value_num !== null).length;
const totalCount = data.data_points.length;

// 情况1：无数据点
if (totalCount === 0) {
    chartTrendLine.setOption({
        title: { text: '该检测项暂无数据', left: 'center', top: 'center',
                 textStyle: { color: '#9ca3af', fontSize: 14 } }
    }, true);
    chartTrendPie.setOption({
        title: { text: '暂无数据', left: 'center', top: 'center',
                 textStyle: { color: '#9ca3af', fontSize: 14 } }
    }, true);
    return;
}

// 情况2：有数据点但无数值（状态类/文本类）
if (numericCount === 0) {
    chartTrendLine.setOption({
        title: {
            text: '该检测项为状态/文本类型',
            subtext: '无法绘制数值趋势图，请查看右侧状态分布',
            left: 'center', top: 'center',
            textStyle: { color: '#6b7280', fontSize: 14 },
            subtextStyle: { color: '#9ca3af', fontSize: 12 }
        }
    }, true);
    // 饼图正常渲染（只有状态分布）
    // ... existing pie chart code ...
    return;
}

// 情况3：有数值数据，正常渲染折线图
// ... existing line chart code ...
```

---

### Step 2：前端 — 模块选择器中标注无趋势项

**文件**：`skill/code/web/templates/service_monitor/statistics.html`

**位置**：`onModuleChange` 函数

**改动**：在检测项选择器中，对无趋势分析能力的项添加标记（如 "(状态)" 后缀），让用户一目了然。

**实现方式**：在 `get_item_keys_for_target` API 返回中增加 `has_numeric` 标记，前端根据标记添加后缀。

---

### Step 3：后端 — item-keys API 增加 has_numeric 标记

**文件**：`skill/code/web/service_monitor/services/statistics_service.py`

**位置**：`get_item_keys_for_target` 函数

**改动**：在收集检测项时，同时检查该项是否有过数值数据，增加 `has_numeric` 字段。

```python
# 在 items_map 中增加 has_numeric 字段
items_map[key] = {
    "key": key,
    "name": item.get("name", key),
    "has_numeric": False,  # 默认 False
}

# 遍历报告时，检查该项是否有数值数据
for item in module.get("items", []):
    key = item.get("key", "")
    value_raw = item.get("value", "")
    value_num, _ = _extract_numeric(value_raw)
    if value_num is not None:
        items_map[key]["has_numeric"] = True
```

---

### Step 4：前端 — 检测项选择器标注

**文件**：`skill/code/web/templates/service_monitor/statistics.html`

**位置**：`onModuleChange` 函数

**改动**：根据 `has_numeric` 字段在选项中添加后缀标记。

```javascript
group.items.forEach(item => {
    const opt = document.createElement('option');
    opt.value = item.key;
    opt.textContent = item.name + (item.has_numeric ? '' : ' (状态)');
    itemSel.appendChild(opt);
});
```

---

### Step 5：本地测试

```bash
cd skill/code && python -m pytest -v
```

---

### Step 6：部署验证

```bash
! cd deploy && SSH_PASSWORD='***' python upload_to_server.py
```

**验证**：
1. 选择 `CPU_USAGE` 等数值项，折线图正常
2. 选择 `CPU_STATUS` 等状态项，显示友好提示 + 饼图正常
3. 检测项选择器中，状态项标注 "(状态)"
4. 控制台无 JS 错误

---

## 验收清单

| 检查项 | 状态 |
|--------|------|
| 折线图无数值时显示友好提示 | ⬜ |
| 状态类检测项饼图正常显示 | ⬜ |
| item-keys API 返回 has_numeric 字段 | ⬜ |
| 检测项选择器标注 "(状态)" 后缀 | ⬜ |
| 本地测试通过 | ⬜ |
| 部署验证通过 | ⬜ |

---

## 执行记录

| 步骤 | 状态 | 时间 | 备注 |
|------|------|------|------|
| Step 1: 折线图友好提示 | 待执行 | - | - |
| Step 2: 后端 has_numeric 标记 | 待执行 | - | - |
| Step 3: 前端选择器标注 | 待执行 | - | - |
| Step 4: 本地测试 | 待执行 | - | - |
| Step 5: 部署验证 | 待执行 | - | - |
