fastbee/yack-web/docs/data-center-history-chart-solution.md

166 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 数据中心 · 历史记录 · 曲线趋势图改造方案
## 1. 背景与问题
### 1.1 业务场景
路径:**数据中心 → 历史记录**([`history.vue`](../src/views/dataCenter/history.vue))。
页面含三个 Tab:**设备**、**网关设备**、**场景**,各自有「曲线趋势图」或网关下的计算量 / 多设备对比 / 单子设备折线图。
### 1.2 原始痛点
| 问题 | 说明 |
|------|------|
| 多曲线「压成直线」 | 多物模型量级差异大(如位移 168、角度 3、电压 12),共用单 Y 轴时范围被拉大,小幅波动在图上不可见。 |
| 多 Y 轴布局异常 | 为每条曲线建隐藏 Y 轴时,ECharts 会为多轴计算偏移,曲线一多时绘图区被挤到一侧。 |
| 图例占用空间 | 网关多设备对比图例项极多,默认换行占满高度,挤压 grid。 |
| X 轴可读性 | 时间点密集时标签重叠。 |
| 垂直空间不足 | 固定 480px 高度时,几十条归一化曲线仍显拥挤。 |
---
## 2. 总体思路
1. **独立 Y 轴模式**:不再使用「每 series 一个 Y 轴」,改为 **按每条曲线自身 min-max 归一化到 [-100, 100]**,**共用一条数值 Y 轴**,避免多轴布局副作用;**Tooltip 始终展示原始值**。
2. **共享 Y 轴模式**:保留原逻辑,单 Y 轴 + `scale: true`,便于对比绝对量级。
3. **归一化坐标展示**:独立模式下 Y 轴可见,刻度约 -100%~100%,并附说明性网格线。
4. **网关图**:图例与 grid 与设备 Tab 对齐策略;X 轴旋转 + 对齐刻度;必要时配合底部留白与 dataZoom。
5. **动态高度**:按 **series 数量** 增加图表容器高度(有上下限),并在 DOM 更新后 `resize`。
---
## 3. 功能开关
- **数据字段**:`independentYAxis`(默认 `true`)。
- **UI**:设备 / 网关 / 场景三个图表卡片头部 **「独立Y轴 | 共享Y轴」** 开关。
- **切换行为**:`handleYAxisModeChange` 在 `$nextTick` 内按当前 Tab 与已有数据调用对应 `draw*Line`,无需重新请求接口。
---
## 4. 核心实现
### 4.1 归一化(独立模式)
**方法**:`applyIndependentScale(series)`
- 对每条 `series.data` 中可解析为数字的点,取该 series 全体有效点的 `min`、`max`。
- 映射公式:`value = ((num - min) / (max - min)) * 200 - 100`,落在 **[-100, 100]**。
- **常量序列**(`max === min`):映射为 **0**(中间水平线)。
- 每个数据点存为 `{ value, _original }`,`_original` 为归一化前的原始值(兼容负数与非数字展示)。
**返回的 Y 轴配置**(单轴):
- `min: -100`, `max: 100`
- `axisLine` / `axisTick` 显示
- `axisLabel.formatter`: 显示为 `xx%`(表示相对本曲线量程的位置,非物理单位)
- `splitLine`:虚线网格,便于读趋势
### 4.2 Tooltip
**方法**:`independentScaleTooltip()`
- `trigger: 'axis'`
- `formatter`:时间轴标签 + 各 series **原始值**(从 `p.data._original` 读取)
### 4.3 共享模式
- `yAxis`: `{ type: 'value', scale: true }`
- `tooltip`: `{ trigger: 'axis' }`(默认)
### 4.4 涉及的绘图方法
| 方法 | Tab / 场景 |
|------|------------|
| `drawDevLine` | 设备 |
| `drawGwCalcLine` | 网关 · 计算量 |
| `drawGwSingleLine` | 网关 · 单子设备 |
| `drawSubCompareLine` | 网关 · 多设备同一变量对比 |
| `drawSceneLine` | 场景 |
以上方法在 `independentYAxis === true` 时均走 `applyIndependentScale` + `independentScaleTooltip`。
### 4.5 网关图布局要点
- `legend`: `align: 'right'`, `left: '3%'`, `top: '3%'`(与多行图例协调)
- `grid.top: '30%'`,为图例留出区域,避免与曲线重叠
- `xAxis`: `boundaryGap: true`, `axisTick.alignWithLabel: true`, `axisLabel.rotate: 30`
- `dataZoom`: `inside` + 滑块,便于时间范围缩放
- `toolbox`: 数据视图、还原、保存图片(与设备 Tab 能力对齐)
### 4.6 动态图表高度
**数据字段**(像素):
- `devChartHeight`, `gwCalcChartHeight`, `gwSingleChartHeight`, `subCompareChartHeight`, `sceneChartHeight`(默认 480)
**方法**:`calcChartHeight(seriesCount)`
```text
height = clamp(480, seriesCount * 14 + 360, 1200)
```
即:最少 480px,随曲线数量增加,**最多 1200px**。
**模板**:各图表容器使用 `:style="{ height: xxxChartHeight + 'px', ... }"`。
**绘制流程**:
1. 先算好 `series` 与 `series.length`,赋值对应 `xxxChartHeight`
2. `this.$nextTick(() => { init/clear → setOption → chart.resize() })`
保证先根据新高度更新 DOM,再初始化/重绘 ECharts。
---
## 5. 数据流(简图)
```mermaid
flowchart LR
subgraph input [数据]
API[历史接口]
end
subgraph mode [模式]
IND[独立Y轴]
SHR[共享Y轴]
end
subgraph render [渲染]
NORM[逐条 min-max 到 -100~100]
ONEAXIS[单 Y 轴]
TT[Tooltip 原始值]
end
API --> IND
API --> SHR
IND --> NORM --> ONEAXIS
ONEAXIS --> TT
SHR --> ONEAXIS
```
---
## 6. 使用说明(给产品/测试)
1. **独立 Y 轴(推荐多曲线看趋势)**:纵轴为各曲线**自身量程内的相对位置**(-100%~100%),对比不同物理量时看形状;**真实数值以 Tooltip 与下方表格为准**。
2. **共享 Y 轴**:纵轴为**真实数值**,适合量级接近、需比大小的变量;量级差很大时仍可能出现「看起来像直线」。
3. **曲线很多时**:图会自动变高(上限约 1200px),页面可纵向滚动查看全图。
---
## 7. 相关文件
| 文件 | 说明 |
|------|------|
| [`yack-web/src/views/dataCenter/history.vue`](../src/views/dataCenter/history.vue) | 全部图表逻辑、开关、高度、归一化 |
| [`yack-web/src/api/data/center.js`](../src/api/data/center.js) | 历史数据接口(未因本方案变更协议) |
---
## 8. 版本与维护建议
- 若需调整「多高算够」,改 `calcChartHeight` 中的系数 `14`、基础 `360`、上下限 `480`/`1200` 即可。
- 若产品要求 Y 轴显示「归一化」文案而非 `%`,可在 `applyIndependentScale` 返回的 `axisLabel` 中改为固定文案或 `name`/`nameLocation`。
- 新增同类折线图时,复用:`applyIndependentScale` / `independentScaleTooltip` / `calcChartHeight` + `$nextTick` + `resize` 模式。
---
*文档对应实现:历史记录页曲线趋势图(多 Tab、独立/共享 Y 轴、归一化 -100~100、动态高度)。*