|
|
|
@ -19,13 +19,13 @@ |
|
|
|
</div> |
|
|
|
</header> |
|
|
|
|
|
|
|
<div class="full-detail-tabs"> |
|
|
|
<button :class="{ active: activeTab === 'overview' }" @click="activeTab = 'overview'">概览</button> |
|
|
|
<button :class="{ active: activeTab === 'state' }" @click="activeTab = 'state'">设备状态</button> |
|
|
|
<button :class="{ active: activeTab === 'alarms' }" @click="activeTab = 'alarms'">告警记录<b v-if="alarmRecords.length">{{ alarmRecords.length }}</b></button> |
|
|
|
<button :class="{ active: activeTab === 'logs' }" @click="activeTab = 'logs'">操作记录</button> |
|
|
|
<button :class="{ active: activeTab === 'diagnostics' }" @click="activeTab = 'diagnostics'">运维诊断</button> |
|
|
|
</div> |
|
|
|
<t-tabs v-model="activeTab" class="device-detail-tabs"> |
|
|
|
<t-tab-panel value="overview" label="概览" :destroy-on-hide="false" /> |
|
|
|
<t-tab-panel value="state" label="设备状态" :destroy-on-hide="false" /> |
|
|
|
<t-tab-panel value="alarms" :label="alarmsTabLabel" :destroy-on-hide="false" /> |
|
|
|
<t-tab-panel value="logs" label="操作记录" :destroy-on-hide="false" /> |
|
|
|
<t-tab-panel value="diagnostics" label="运维诊断" :destroy-on-hide="false" /> |
|
|
|
</t-tabs> |
|
|
|
|
|
|
|
<div v-if="activeTab === 'overview'" class="full-detail-content"> |
|
|
|
<template v-if="!isDrone"> |
|
|
|
@ -218,20 +218,19 @@ |
|
|
|
<div><h2>告警记录</h2><span>当前设备</span></div> |
|
|
|
<t-select v-model="alarmStatusFilter" :options="alarmStatusOptions" placeholder="全部告警状态" style="width: 160px" /> |
|
|
|
</div> |
|
|
|
<table class="record-table"> |
|
|
|
<thead><tr><th>告警时间</th><th>告警编码</th><th>告警内容</th><th>级别</th><th>状态</th><th>恢复时间</th></tr></thead> |
|
|
|
<tbody> |
|
|
|
<tr v-for="item in filteredAlarms" :key="item.id"> |
|
|
|
<td>{{ item.triggeredAt }}</td> |
|
|
|
<td>{{ item.code }}</td> |
|
|
|
<td>{{ item.message }}</td> |
|
|
|
<td><i class="severity" :class="item.levelClass">{{ item.levelName }}</i></td> |
|
|
|
<td><span class="table-status" :class="item.statusClass"><i></i>{{ item.statusName }}</span></td> |
|
|
|
<td>{{ item.resolvedAt }}</td> |
|
|
|
</tr> |
|
|
|
</tbody> |
|
|
|
</table> |
|
|
|
<div v-if="!filteredAlarms.length" class="table-empty">暂无告警记录</div> |
|
|
|
<t-table |
|
|
|
row-key="id" |
|
|
|
:data="filteredAlarms" |
|
|
|
:columns="alarmColumns" |
|
|
|
empty="暂无告警记录" |
|
|
|
> |
|
|
|
<template #level="{ row }"> |
|
|
|
<i class="severity" :class="row.levelClass">{{ row.levelName }}</i> |
|
|
|
</template> |
|
|
|
<template #status="{ row }"> |
|
|
|
<span class="table-status" :class="row.statusClass"><i></i>{{ row.statusName }}</span> |
|
|
|
</template> |
|
|
|
</t-table> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div v-else-if="activeTab === 'logs'" class="full-detail-content"> |
|
|
|
@ -239,19 +238,16 @@ |
|
|
|
<div><h2>操作记录</h2><span>远程控制与配置变更</span></div> |
|
|
|
<t-button variant="outline" @click="loadLogs">刷新</t-button> |
|
|
|
</div> |
|
|
|
<table class="record-table"> |
|
|
|
<thead><tr><th>操作时间</th><th>操作类型</th><th>操作内容</th><th>执行结果</th><th>目标设备</th></tr></thead> |
|
|
|
<tbody> |
|
|
|
<tr v-for="log in logs" :key="log.id"> |
|
|
|
<td>{{ log.createdAt }}</td> |
|
|
|
<td>{{ log.category }}</td> |
|
|
|
<td>{{ log.commandName }}</td> |
|
|
|
<td><span :class="log.resultClass">{{ log.result }}</span></td> |
|
|
|
<td>{{ log.droneSn }}</td> |
|
|
|
</tr> |
|
|
|
</tbody> |
|
|
|
</table> |
|
|
|
<div v-if="!logs.length" class="table-empty">暂无设备操作记录</div> |
|
|
|
<t-table |
|
|
|
row-key="id" |
|
|
|
:data="logs" |
|
|
|
:columns="logColumns" |
|
|
|
empty="暂无设备操作记录" |
|
|
|
> |
|
|
|
<template #result="{ row }"> |
|
|
|
<span :class="row.resultClass">{{ row.result }}</span> |
|
|
|
</template> |
|
|
|
</t-table> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div v-else class="full-detail-content"> |
|
|
|
@ -339,6 +335,25 @@ const alarmStatusOptions = [ |
|
|
|
] |
|
|
|
const editDockVisible = ref(false) |
|
|
|
|
|
|
|
const alarmsTabLabel = computed(() => (alarmRecords.value.length ? `告警记录 ${alarmRecords.value.length}` : '告警记录')) |
|
|
|
|
|
|
|
const alarmColumns = [ |
|
|
|
{ colKey: 'triggeredAt', title: '告警时间', width: '18%' }, |
|
|
|
{ colKey: 'code', title: '告警编码', width: '14%' }, |
|
|
|
{ colKey: 'message', title: '告警内容', width: '28%' }, |
|
|
|
{ colKey: 'level', title: '级别', width: '10%' }, |
|
|
|
{ colKey: 'status', title: '状态', width: '12%' }, |
|
|
|
{ colKey: 'resolvedAt', title: '恢复时间', width: '18%' } |
|
|
|
] |
|
|
|
|
|
|
|
const logColumns = [ |
|
|
|
{ colKey: 'createdAt', title: '操作时间', width: '20%' }, |
|
|
|
{ colKey: 'category', title: '操作类型', width: '14%' }, |
|
|
|
{ colKey: 'commandName', title: '操作内容', width: '26%' }, |
|
|
|
{ colKey: 'result', title: '执行结果', width: '16%' }, |
|
|
|
{ colKey: 'droneSn', title: '目标设备', width: '24%' } |
|
|
|
] |
|
|
|
|
|
|
|
const record = computed(() => devices.record(route.params.id)) |
|
|
|
const asset = computed(() => devices.asset(route.params.id)) |
|
|
|
const isDrone = computed(() => record.value?.kind === 'drone') |
|
|
|
@ -598,3 +613,15 @@ function goMonitor() { |
|
|
|
router.push({ name: 'monitor', query: { deviceId: route.params.id } }) |
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
|
<style scoped> |
|
|
|
.device-detail-tabs :deep(.t-tabs__nav-container) { |
|
|
|
padding: 0 24px; |
|
|
|
} |
|
|
|
.device-detail-tabs :deep(.t-tabs__nav-wrap) { |
|
|
|
margin-left: 0; |
|
|
|
} |
|
|
|
.full-detail-content :deep(.t-table) { |
|
|
|
background: transparent; |
|
|
|
} |
|
|
|
</style> |
|
|
|
|