| | |
| | | const testStatusLabel = ref('待测试') |
| | | let closeLiveStream: (() => void) | null = null |
| | | let reconnectTimer: number | null = null |
| | | let reconnectAttempt = 0 |
| | | let disposed = false |
| | | let stopPending = false |
| | | const runtimeAttach = ref(false) |
| | |
| | | liveConnection.value = next.sources.some(source => Boolean(source.latestSnapshot?.observedAt) |
| | | || Boolean(source.latestSnapshot?.measurements?.length)) ? '已连接' : '空数据' |
| | | liveError.value = '' |
| | | // 这一帧成功送达,重连退避回到起点。 |
| | | reconnectAttempt = 0 |
| | | const nextState = ({ WAITING: '待测试', RUNNING: '检测中', PAUSED: '暂停', COMPLETED: '检测完成', |
| | | // 历史数据仅兼容展示,不参与新生命周期流转。 |
| | | RUNNING_ABNORMAL: '检测中', COMPLETION_PENDING: '检测完成', TERMINATED: '检测完成' } as Record<string, ConsoleState | undefined>)[next.testStatus] || '待测试' |
| | |
| | | else receptionState.value = '接收中' |
| | | } |
| | | |
| | | /** |
| | | * 断线后重连:间隔按 2s、4s… 翻倍到 30s 封顶,收到快照即重置。 |
| | | * |
| | | * 固定 2 秒重连在"这个测试已经不存在"时会一直空转——测试被删除后(ADR-0047 允许物理删除), |
| | | * 每次重连都会让服务端记一条错误日志,几秒一条地刷屏。退避不影响恢复能力(后端重启后最迟 30 秒接回), |
| | | * 只是不再把持续失败刷成一屏日志。 |
| | | */ |
| | | function scheduleLiveReconnect() { |
| | | if (disposed || reconnectTimer !== null) return |
| | | const delay = Math.min(2000 * 2 ** reconnectAttempt, 30000) |
| | | reconnectAttempt += 1 |
| | | reconnectTimer = window.setTimeout(async () => { |
| | | reconnectTimer = null |
| | | if (!backendDetail.value) { await loadConsole(); return } |
| | | try { applyLiveState(await getTestLiveState(testId.value)); if (!disposed) connectLiveStream() } |
| | | catch (error) { handleLiveError(error instanceof Error ? error : new Error('实时状态加载失败')) } |
| | | }, 2000) |
| | | }, delay) |
| | | } |
| | | |
| | | function connectLiveStream() { |