diff --git a/docs/superpowers/specs/2026-09-03-monitor-device-polling-design.md b/docs/superpowers/specs/2026-09-03-monitor-device-polling-design.md index a1e2d8a..0213ac0 100644 --- a/docs/superpowers/specs/2026-09-03-monitor-device-polling-design.md +++ b/docs/superpowers/specs/2026-09-03-monitor-device-polling-design.md @@ -38,13 +38,13 @@ ### 4.1 `MonitorView` -1. `onMounted`:保留现有首次 `devices.load()`;成功后启动 `setInterval(() => void pollDevices(), 5000)`。 +1. `onMounted`:先做现有首次 `devices.load()`(失败仍 toast 一次,与现状一致);无论首次成败,只要仍挂在本页就启动 `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 清掉)。 +3. `onUnmounted` / `pagehide`:`clearInterval`;用页面级 `disposed`/`generation` 忽略卸载后才返回的轮询结果(避免卸载后无意义的续跑逻辑;store 已被 `load()` 写入可保留,不必回滚)。 4. `document.visibilitychange`: - `hidden` → 暂停(clearInterval) - `visible` → 立即 `pollDevices()` 一次,再重新 `setInterval` @@ -70,7 +70,7 @@ 行为: -1. 找到 `docks` / `drones` 中对应 `id`;找不到则 **no-op**(或可选触发一次全量 `load` 作为 fallback;实现计划里二选一,默认 **no-op + console**,避免详情页单独制造全表风暴)。 +1. 找到 `docks` / `drones` 中对应 `id`;找不到则 **no-op + `console.warn`**(不触发全量 `load`,避免详情页单独制造全表风暴)。 2. 用与 `load()` 相同的映射规则更新该条:`online`、`realtime`、`status` / `statusClass`、`environment`、`alarms`、`mode`、无人机 `battery` / `_lat` `_lon` `_alt` 等派生字段。 3. 同步更新 `assets[id]` 上用于地图的 status / 坐标 / realtime 相关字段,避免 Monitor 与详情不一致。 4. **不**重拉列表,**不**重建无关条目。 @@ -105,7 +105,7 @@ | 文件 | 变更 | |------|------| -| `src/stores/modules/devicesStore.js` | 抽映射;新增 `applyDockDetail` / `applyDroneDetail`;可选 `inflight` 或由页面自管 | +| `src/stores/modules/devicesStore.js` | 抽共享映射;新增 `applyDockDetail` / `applyDroneDetail` | | `src/views/MonitorView/MonitorView.vue` | 5s 轮询 + visibility + 与 `reload` 共用 in-flight | | `src/views/DeviceDetailView/DeviceDetailView.vue` | 当前 id 详情轮询 + id watch + visibility |