| | |
| | | const testStatusLabel = ref('待测试') |
| | | let closeLiveStream: (() => void) | null = null |
| | | let reconnectTimer: number | null = null |
| | | let stopPending = false |
| | | const runtimeAttach = ref(false) |
| | | const receptionState = ref<ReceptionState>('未开始接收') |
| | | const realtimeRecords = ref<PersistedTestRecord[]>([]) |
| | |
| | | } |
| | | |
| | | function applyLiveState(next: TestLiveState) { |
| | | if (stopPending && next.receptionStatus !== 'ENDED') return |
| | | liveState.value = next |
| | | liveConnection.value = next.sources.some(source => Boolean(source.latestSnapshot?.observedAt) |
| | | || Boolean(source.latestSnapshot?.measurements?.length)) ? '已连接' : '空数据' |
| | |
| | | } |
| | | else if (event === 'test-status' && data && typeof data === 'object' && 'testStatus' in data && liveState.value) |
| | | applyLiveState({ ...liveState.value, testStatus: (data as { testStatus: TestLiveState['testStatus'] }).testStatus }) |
| | | else if (event === 'exception' && Array.isArray(data) && liveState.value) { |
| | | else if (event === 'exception' && Array.isArray(data) && liveState.value && !stopPending) { |
| | | const current = (data as TestLiveState['exceptions']).filter(item => !item.status || item.status === 'OPEN') |
| | | liveState.value = { ...liveState.value, exceptions: current } |
| | | // 来源异常和测试预警由下方告警面板展示,不能把正常暂停/完成误报成连接错误。 |
| | |
| | | |
| | | // 实时告警只展示后端当前仍开放的异常,异常事实由后端状态和消息说明。 |
| | | const currentExceptions = computed(() => (liveState.value?.exceptions || []) |
| | | .filter(item => item.sourceType !== 'COLLECTOR' || !item.status || item.status === 'OPEN')) |
| | | .filter(item => receptionState.value === '接收中' |
| | | && (item.sourceType !== 'COLLECTOR' || !item.status || item.status === 'OPEN'))) |
| | | |
| | | function openStepSettings() { stepDraft.value = stepSettings.value.map(item => ({ ...item })); selectedPlanSteps.value = []; stepEditing.value = true } |
| | | function togglePlanStep(position: number, checked: string | number | boolean) { const next = new Set(selectedPlanSteps.value); checked ? next.add(position) : next.delete(position); selectedPlanSteps.value = [...next].sort((a, b) => a - b) } |
| | |
| | | if (state.value === '检测完成') return |
| | | try { |
| | | await ElMessageBox.confirm('停止测试后将不可恢复,系统会停止请求本测试的数据,但不会向设备发送停止命令,是否继续?', '确认停止测试', { confirmButtonText: '停止测试', cancelButtonText: '取消', type: 'warning', confirmButtonClass: 'danger-confirm' }) |
| | | backendDetail.value = await endTestReception(testId.value) |
| | | const previousState = state.value |
| | | const previousReceptionState = receptionState.value |
| | | const previousLiveState = liveState.value |
| | | // 停止是不可恢复动作,先更新本地视图,避免等待后端配置重载和采样事务提交。 |
| | | stopPending = true |
| | | state.value = '检测完成' |
| | | receptionState.value = '已结束接收' |
| | | liveError.value = '' |
| | | testStatusLabel.value = ({ WAITING: '待测试', RUNNING: '检测中', PAUSED: '暂停', RUNNING_ABNORMAL: '检测中', COMPLETION_PENDING: '检测完成', COMPLETED: '检测完成', TERMINATED: '检测完成' } as Record<string, string>)[backendDetail.value.testStatus || 'COMPLETED'] || '检测完成' |
| | | testStatusLabel.value = '检测完成' |
| | | if (liveState.value) |
| | | liveState.value = { ...liveState.value, testStatus: 'COMPLETED', receptionStatus: 'ENDED', exceptions: [] } |
| | | try { |
| | | backendDetail.value = await endTestReception(testId.value) |
| | | stopPending = false |
| | | } catch (error) { |
| | | stopPending = false |
| | | state.value = previousState |
| | | receptionState.value = previousReceptionState |
| | | liveState.value = previousLiveState |
| | | throw error |
| | | } |
| | | ElMessage.success('测试已停止,系统不再请求数据') |
| | | } catch (error) { |
| | | if (error === 'cancel' || error === 'close') return |