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

6.3 KiB
Raw Blame History

数据中心 · 历史记录 · 曲线趋势图改造方案

1. 背景与问题

1.1 业务场景

路径:数据中心 → 历史记录(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)

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. 数据流(简图)

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 全部图表逻辑、开关、高度、归一化
yack-web/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、动态高度)。