Web Console:Monitor、Lab、ECharts 和记录回看的前端边界
解释 RespiraScope 前端为什么采用统一 Console + 多个静态页面,Monitor 如何消费实时数据,Lab 如何服务模拟和滤波调参。
背景问题
RespiraScope 的前端要服务两类人:使用者需要 Monitor 看实时波形、BPM、稳定性和记录片段;开发者需要 Lab 调模拟信号、滤波参数和异常场景。如果把所有内容塞进一个巨大 JS 文件,维护会很困难;如果拆成多个独立站点,启动和访问又会复杂。
当前方案是统一 Web Console:frontend-console 是入口,里面用 tab 切换 Monitor、Lab、Guide 和 API Docs。
设计方案对比
| 方案 | 优点 | 问题 | 项目判断 |
|---|---|---|---|
| 单个巨型页面 | 启动简单 | 代码膨胀,职责混乱 | 不利于维护 |
| 多个独立前端服务 | 页面边界清楚 | 多端口、多入口、用户容易迷路 | 不适合演示工具 |
| Console + tab/iframe | 一个入口,页面可独立维护 | 需要语言同步和运行时配置注入 | 当前采用 |
| React/Vue SPA | 工程能力强 | 构建链路和打包复杂度更高 | 当前静态页面足够 |
项目选择静态页面,是因为前端的核心任务是展示和控制,不需要复杂状态管理框架。ECharts 和原生模块化 JS 已经能支撑当前规模。
当前方案
frontend-console/app.js 负责读取 window.CT_BREATH_RUNTIME_CONFIG,判断哪些 tab 可用,并把语言选择通过 postMessage 发送给 iframe。Monitor 和 Lab 各自维护自己的业务逻辑。
Monitor 被拆成几个模块:
| 模块 | 职责 |
|---|---|
app.js | 全局状态、DOM、语言、模块组装 |
modules/socket.js | 启动接收、连接 Socket.IO、消费实时消息 |
modules/chart.js | ECharts 实时图和记录图 |
modules/record.js | 记录、scan、保存、加载和离线复算 |
modules/status.js | 接收状态、无数据提示和统计信息 |
为什么这样选
Monitor 的前端状态必须同时包含实时数据和记录数据。实时数据保存在 state.raw、state.filtered、state.peaks、state.valleys;记录过程中还要把进入 capture 范围的点追加到 state.activeRecord。这就是为什么前端也有记录逻辑:它需要及时显示用户交互反馈,即使后端接口短暂失败,也能维持本地记录体验。
ECharts 的选择是工程效率。实时波形需要缩放、散点 marker、markArea 区间、dataZoom 和大量点绘制。手写 canvas 可以更轻,但交互和坐标轴成本高;ECharts 对这些场景支持成熟。
Lab 的价值
Lab 不是一个附属页面。它让开发者在不启动真实设备的情况下选择模拟场景、调整 BPM、幅度、噪声、不规则度,再调用 /mock/preview 和 /applyFilter 查看结果。这个流程把参数调试从后端日志里搬到了可视化界面。
Lab 也承担教学价值。用户能直观看到不同场景下 raw、filtered、peak、valley 的变化,从而理解为什么 gaussian_sigma、peak_threshold_ratio 和 auto_peak_detection 会影响结果。
代价和边界
静态前端没有完整构建系统,所以复用和类型检查比 React/Vue 项目弱。项目通过模块拆分和清晰的 moduleContext 控制复杂度,但如果未来 UI 功能继续膨胀,迁移到框架会更合适。
前端本地记录逻辑和后端记录逻辑存在一定重复。这是为了 UI 及时反馈和容错,但也要求双方字段保持兼容。record.js 中大量 normalize 函数就是为了兼容后端返回和本地保存文件。
关键函数表
| 函数或模块 | 作用 | 设计点 |
|---|---|---|
resolveBackendHost() | 根据页面 host 修正后端地址 | 支持局域网访问时不写死 localhost |
createSocketModule() | 连接 Socket.IO 并消费消息 | raw 到达后标记数据已收到 |
chartOption() | 生成 ECharts 配置 | 同时支持实时和回看模式 |
recordMarkArea() | 绘制 record 和 scan 区间 | 让记录范围在波形上可见 |
createRecordModule() | 管理记录状态和文件 | 兼容后端 record 和本地导出 |
previewAndFilter() | Lab 生成预览并离线滤波 | 参数调试闭环 |
postMessage 语言同步 | Console 到 iframe | 多页面保持语言一致 |
读源码建议
先读 frontend-console/app.js,理解统一入口如何加载各页面。再读 frontend-monitor/app.js 的 moduleContext,看模块如何共享状态。随后读 modules/socket.js 和 modules/chart.js,就能看到实时消息如何变成图表。最后读 frontend-lab/app.js,理解模拟和滤波预览如何串起来。