| | |
| | | } |
| | | })) |
| | | |
| | | // 实时告警只展示后端当前仍开放的异常,关闭区间保留在历史记录中追溯。 |
| | | // 实时告警只展示后端当前仍开放的异常,异常事实由后端状态和消息说明。 |
| | | const currentExceptions = computed(() => (liveState.value?.exceptions || []) |
| | | .filter(item => item.sourceType !== 'COLLECTOR' || !item.status || item.status === 'OPEN')) |
| | | |
| | |
| | | <div class="console-layout"> |
| | | <main> |
| | | <section class="panel step-panel"><header class="panel-heading"><div><i></i><strong>项目参数</strong><span>STEP PARAMETERS</span></div><div class="step-actions"><template v-if="stepEditing"><button class="primary-button compact-button" type="button" @click="addStepMapping"><el-icon><Plus /></el-icon>合并选中</button><button class="primary-button compact-button" type="button" @click="saveSteps"><el-icon><Check /></el-icon>保存</button><button class="secondary-button compact-button" type="button" @click="cancelStepSettings">取消</button></template><button v-else class="primary-button compact-button" type="button" @click="openStepSettings"><el-icon><Setting /></el-icon>工步设置</button></div></header><div class="project-meta"><span>测试项目 <strong>{{ profile.purpose }}</strong></span><span>当前循环 <strong>{{ currentCycleNo || '-' }} / 计划 {{ plannedCycleCount || '-' }}</strong></span><span>当前工步 <strong>{{ currentStepNo || '-' }}</strong></span><span>执行状态 <strong>{{ testStatusLabel }}</strong></span></div><div class="step-table-wrap"><table><thead><tr><th v-if="stepEditing">选择</th><th>工步号</th><th>工步名称</th><th>时间(h:min:s.ms)</th><th>电压(V)</th><th>执行状态</th></tr></thead><tbody><template v-if="stepEditing"><tr v-for="step in actualPlanRows" :key="`edit-${step.cyclePosition}`" :class="{ active: step.executionStatus === '进行中' }"><td><el-checkbox :model-value="selectedPlanSteps.includes(step.cyclePosition)" @change="(checked: string | number | boolean) => togglePlanStep(step.cyclePosition, checked)" /></td><td>{{ step.stepNo }}</td><td><strong>{{ step.stepName }}</strong></td><td>{{ formatDuration(step.durationSeconds) }}</td><td>{{ step.voltageV == null ? '-' : `${Number(step.voltageV).toFixed(4)} V` }}</td><td><span class="step-state" :class="step.executionStatus">{{ step.executionStatus }}</span></td></tr></template><template v-else><tr v-for="(step, index) in planRows" :key="`${index}-${step.no}-${step.name}`" :class="{ active: step.state === '进行中' }"><td>{{ step.no }}</td><td><strong>{{ step.name }}</strong></td><td>{{ step.time }}</td><td>{{ step.voltage }}</td><td><span class="step-state" :class="step.state">{{ step.state }}</span></td></tr></template><tr v-if="!planRows.length && !actualPlanRows.length"><td :colspan="stepEditing ? 6 : 5" class="empty-cell">暂无后端检测柜工步方案</td></tr></tbody></table></div><div v-if="stepEditing && stepDraft.length" class="mapping-list"><div v-for="(item, index) in stepDraft" :key="index" class="mapping-row"><strong>逻辑工步 {{ item.logicalNo }}</strong><span>第 {{ item.startStepNo }} 至 {{ item.endStepNo }} 个工步</span><button class="secondary-button compact-button" type="button" aria-label="解除合并" @click="removeStepMapping(index)"><el-icon><Delete /></el-icon>解除合并</button></div></div></section> |
| | | <section class="panel alarm-panel"><header class="panel-heading"><div><i></i><strong>异常警告</strong><span>ALARM</span></div></header><div v-if="currentExceptions.length" class="alarm-list"><div v-for="(item, index) in currentExceptions" :key="`${item.sourceId || item.sourceType}-${item.channelCode || index}-${index}`"><el-icon><WarningFilled /></el-icon><span><strong>{{ item.sourceType === 'COLLECTOR' ? `采集器${item.collectorName || item.collectorCode || `#${item.sourceId}`}${item.status === 'OPEN' ? '离线' : '断线已恢复'} · ${item.channelCode || '来源'}` : (item.message || '数据来源当前不可观测') }}</strong><small>{{ item.measurementName ? `${item.measurementName}受影响 · ` : '' }}{{ item.status === 'OPEN' ? '缺失区间开放' : (item.message || '当前异常') }} · {{ item.missingFrom || item.openedAt || '-' }}<template v-if="item.missingTo"> 至 {{ item.missingTo }}</template></small></span></div></div><div v-else class="alarm-empty"><el-icon><CircleCheckFilled /></el-icon>暂无异常</div></section> |
| | | <section class="panel alarm-panel"><header class="panel-heading"><div><i></i><strong>异常警告</strong><span>ALARM</span></div></header><div v-if="currentExceptions.length" class="alarm-list"><div v-for="(item, index) in currentExceptions" :key="`${item.sourceId || item.sourceType}-${item.channelCode || index}-${index}`"><el-icon><WarningFilled /></el-icon><span><strong>{{ item.sourceType === 'COLLECTOR' ? `采集器${item.collectorName || item.collectorCode || `#${item.sourceId}`}${item.status === 'OPEN' ? '离线' : '异常已处理'} · ${item.channelCode || '来源'}` : (item.message || '数据来源当前不可观测') }}</strong><small>{{ item.measurementName ? `${item.measurementName}受影响 · ` : '' }}{{ item.message || (item.status === 'OPEN' ? '当前异常' : '异常已处理') }}</small></span></div></div><div v-else class="alarm-empty"><el-icon><CircleCheckFilled /></el-icon>暂无异常</div></section> |
| | | <section class="panel channel-panel"><header class="panel-heading"><div><i></i><strong>通道</strong><span>CHANNEL STATUS</span></div></header><div class="channel-table-wrap"><table><thead><tr><th>电池号</th><th>测试柜</th><th>柜状态</th><th>检测通道</th><th>采集器</th><th>采集器状态</th><th>温度</th><th>正电位</th><th>负电位</th></tr></thead><tbody><tr v-for="item in channels" :key="item.no"><td><strong>{{ item.no }}</strong></td><td>{{ item.cabinet }}</td><td><span class="device-state" :class="item.cabinetState">{{ item.cabinetState }}</span></td><td>{{ item.channel }}</td><td>{{ item.collector }}</td><td><span class="device-state" :class="{ 在线: item.collectorState === '在线', 异常: item.collectorState !== '在线' }">{{ item.collectorState }}</span></td><td>{{ item.temperature }}</td><td>{{ item.positive }}</td><td>{{ item.negative }}</td></tr></tbody></table></div></section> |
| | | </main> |
| | | <aside class="parameter-panel"><header class="panel-heading"><div><i></i><strong>测试参数</strong><span>TEST SETTINGS</span></div></header><dl><div v-for="item in parameters" :key="item[0]"><dt>{{ item[0] }}</dt><dd>{{ item[1] }}</dd></div></dl></aside> |