Browse Source
Define 5s Monitor full load polling and per-open DeviceDetail detail-only refresh; DevicesView stays manual.main
1 changed files with 112 additions and 0 deletions
@ -0,0 +1,112 @@ |
|||
# 实时监控 / 设备详情状态轮询 |
|||
|
|||
日期:2026-09-03 |
|||
状态:已确认(待写实现计划) |
|||
范围:仅前端 `laic-frontend` |
|||
|
|||
## 1. 背景 |
|||
|
|||
「实时监控」页当前只在 `onMounted`(以及指令成功后的 `reload`)调用一次 `devices.load()`。左侧设备列表、右侧详情面板、地图 marker 都读同一份 Pinia `devicesStore`;store 不刷新,UI 就不更新。 |
|||
|
|||
直播会话(`useMonitorLive`)与指令进度(`useCommandProgress`)已有各自定时器,但**设备状态本身没有轮询**,与「实时监控」语义不符。 |
|||
|
|||
现有 `devices.load()` 契约: |
|||
|
|||
1. `GET /v1/docks` + `GET /v1/drones`(近全量 pageSize=100) |
|||
2. 再对每条 `GET /v1/docks/:id` / `GET /v1/drones/:id` 取 `online` + `realtime` |
|||
3. 映射 status / environment / alarms / 地图坐标后写入 `docks` / `drones` / `assets` |
|||
|
|||
设备详情页 `DeviceDetailView` 同样只在挂载时 `devices.load()` 一次,无持续刷新。 |
|||
|
|||
## 2. 目标 |
|||
|
|||
1. **实时监控页**停在页面上时,设备列表 / 选中详情 / 地图状态约每 **5 秒**自动更新。 |
|||
2. **设备详情页**只刷新**当前路由打开的那一台**设备详情,约每 **5 秒**一次。 |
|||
3. 离开页面或标签页隐藏时停止轮询;回到前台立即补刷一次再恢复。 |
|||
4. 不改变直播 heartbeat / phase / play-url,也不改变指令进度轮询。 |
|||
|
|||
## 3. 非目标 |
|||
|
|||
- **设备管理列表页(`DevicesView`)不自动刷新**(仍手动刷新按钮)。 |
|||
- 不新增后端批量快照 / WebSocket / SSE。 |
|||
- 不在本轮优化掉 Monitor 的 N+1 详情请求(已知成本,后续可换批量 API)。 |
|||
- 不改 `DevicesView` 分页本地 `tableRecords` 数据源。 |
|||
|
|||
## 4. 方案(页面各自定时器) |
|||
|
|||
采用页面级 `setInterval`,不引入 store 全局轮询器。 |
|||
|
|||
### 4.1 `MonitorView` |
|||
|
|||
1. `onMounted`:保留现有首次 `devices.load()`;成功后启动 `setInterval(() => void pollDevices(), 5000)`。 |
|||
2. `pollDevices`: |
|||
- 若上一轮 `load` 仍 in-flight → **跳过本轮**(防请求堆积)。 |
|||
- 否则 `await devices.load()`。 |
|||
- 单次失败:静默(`console.warn` 即可),**不 toast**,下一轮继续。 |
|||
- `401` 仍走现有 `http` 拦截器(登出 / 跳转)。 |
|||
3. `onUnmounted` / `pagehide`:`clearInterval`,并丢掉 in-flight 回写意图(沿用现有 generation/disposed 习惯,至少保证 timer 清掉)。 |
|||
4. `document.visibilitychange`: |
|||
- `hidden` → 暂停(clearInterval) |
|||
- `visible` → 立即 `pollDevices()` 一次,再重新 `setInterval` |
|||
5. 指令路径现有 `reload()` 继续直接 `devices.load()`;与轮询共享同一 in-flight 闸门更佳(同一 `loading`/`inflight` 标志),避免指令 reload 与定时器重叠打双份。 |
|||
|
|||
### 4.2 `DeviceDetailView` |
|||
|
|||
1. 保留挂载时一次 `devices.load()`(以及非 admin 的 logs/alarms)。 |
|||
2. 另启 **当前 `route.params.id`** 的详情轮询,间隔 5000ms: |
|||
- dock → `GET /v1/docks/:id` |
|||
- drone → `GET /v1/drones/:id` |
|||
3. 响应经 store 新方法合并进**对应一条**记录(见 4.3),驱动本页与若仍挂着的 Monitor 共享状态。 |
|||
4. `watch(() => route.params.id)`:停旧定时器,按新 id 立即拉一次并重启 interval。 |
|||
5. 生命周期 / visibility / in-flight 跳过 / 失败静默:与 Monitor 同规则。 |
|||
6. 离开页:清除定时器。 |
|||
|
|||
### 4.3 `devicesStore` 增量回写 |
|||
|
|||
新增(命名可微调,语义固定): |
|||
|
|||
- `applyDockDetail(id, detail)` |
|||
- `applyDroneDetail(id, detail)` |
|||
|
|||
行为: |
|||
|
|||
1. 找到 `docks` / `drones` 中对应 `id`;找不到则 **no-op**(或可选触发一次全量 `load` 作为 fallback;实现计划里二选一,默认 **no-op + console**,避免详情页单独制造全表风暴)。 |
|||
2. 用与 `load()` 相同的映射规则更新该条:`online`、`realtime`、`status` / `statusClass`、`environment`、`alarms`、`mode`、无人机 `battery` / `_lat` `_lon` `_alt` 等派生字段。 |
|||
3. 同步更新 `assets[id]` 上用于地图的 status / 坐标 / realtime 相关字段,避免 Monitor 与详情不一致。 |
|||
4. **不**重拉列表,**不**重建无关条目。 |
|||
|
|||
`load()` 本身可抽一小段「detail → record 字段」纯函数供全量与增量共用,避免两套映射分叉;若改动面过大,允许增量路径先复制必要映射,但字段语义必须与 `load()` 一致。 |
|||
|
|||
## 5. 错误与并发 |
|||
|
|||
| 场景 | 行为 | |
|||
|------|------| |
|||
| 轮询 HTTP 业务/网络失败 | 静默,保留旧数据,下轮再试 | |
|||
| 401 | 现有拦截器登出 | |
|||
| 上轮未完成 | 跳过本轮 | |
|||
| 页面 hidden | 暂停 timer | |
|||
| 页面 visible | 立即补一次 + 重启 timer | |
|||
| 详情 id 切换 | 取消旧轮询,新 id 立即请求 | |
|||
|
|||
## 6. 验收 |
|||
|
|||
1. 停留在实时监控:约 5s 内列表状态 / 右侧详情(电量、舱门、环境、在线等)/ 地图 marker 会随后端变化更新。 |
|||
2. 打开设备详情 A:网络面板仅见对 A 的详情轮询;切换到 B 后改为 B。 |
|||
3. 设备管理列表页打开时**无**定时 `/docks/:id` `/drones/:id` 轮询(仅用户点击刷新或进入时的请求)。 |
|||
4. 从监控/详情路由离开,或切到其它浏览器标签:轮询停止;切回后先补刷再按 5s 继续。 |
|||
5. 开播、停播、指令进度浮层行为与改前一致。 |
|||
|
|||
## 7. 风险 |
|||
|
|||
- Monitor 每 5s 全量 `load()` 仍是列表 + N 次详情;设备数量上来后 QPS 偏高。本轮按产品选择接受;后续应用批量状态接口替换 `pollDevices` 内部实现,页面契约可不变。 |
|||
- 详情增量映射若与 `load()` 分叉,会出现「详情页字段」与「监控全量刷新后字段」不一致;优先抽共享映射。 |
|||
|
|||
## 8. 实现落点(预告) |
|||
|
|||
| 文件 | 变更 | |
|||
|------|------| |
|||
| `src/stores/modules/devicesStore.js` | 抽映射;新增 `applyDockDetail` / `applyDroneDetail`;可选 `inflight` 或由页面自管 | |
|||
| `src/views/MonitorView/MonitorView.vue` | 5s 轮询 + visibility + 与 `reload` 共用 in-flight | |
|||
| `src/views/DeviceDetailView/DeviceDetailView.vue` | 当前 id 详情轮询 + id watch + visibility | |
|||
|
|||
完成后:实现计划 → 编码 → 构建部署 → 人工看监控与详情是否按 5s 变。 |
|||
Loading…
Reference in new issue