list.vue 6.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. <template>
  2. <div class="alarm-page">
  3. <el-card shadow="never" class="alarm-filter-card"><el-form :model="filters" inline class="alarm-filters" @submit.prevent="search">
  4. <el-form-item label="报警单号"><el-input v-model="filters.alarmNo" clearable placeholder="请输入报警单号" @keyup.enter="search" /></el-form-item>
  5. <el-form-item label="设备搜索"><el-input v-model="filters.keyword" clearable placeholder="请输入设备编码/名称" @keyup.enter="search" /></el-form-item>
  6. <el-form-item label="报警等级"><el-select v-model="filters.alarmLevel" clearable placeholder="全部等级"><el-option v-for="v in options.alarmLevels" :key="v.value" :label="v.label" :value="v.value" /></el-select></el-form-item>
  7. <el-form-item label="监测状态"><el-select v-model="filters.alarmStatus" clearable placeholder="全部状态"><el-option v-for="v in options.monitorStatuses" :key="v.value" :label="v.label" :value="v.value" /></el-select></el-form-item>
  8. <el-form-item label="报警时间"><el-date-picker v-model="dates" type="daterange" value-format="YYYY-MM-DD" start-placeholder="开始日期" end-placeholder="结束日期" range-separator="至" /></el-form-item>
  9. <el-form-item><el-button type="primary" :icon="Search" @click="search">查询</el-button><el-button :icon="Refresh" @click="reset">重置</el-button></el-form-item>
  10. </el-form></el-card>
  11. <el-card shadow="never"><div class="alarm-toolbar"><h3>报警事件</h3><span class="muted">共 {{ total }} 条</span></div>
  12. <el-alert v-if="error" :title="error" type="error" show-icon :closable="false" class="load-error"><el-button link @click="load">重新加载</el-button></el-alert>
  13. <el-table v-loading="loading" :data="rows" border stripe row-key="id" :header-cell-style="{ background: '#f5f7fa', color: '#606266' }" :default-sort="{ prop: 'createTime', order: 'descending' }" @sort-change="sort">
  14. <el-table-column prop="alarmNo" label="报警单号" width="210" show-overflow-tooltip><template #default="{ row }">{{ row.alarmNo || '—' }}</template></el-table-column>
  15. <el-table-column prop="deviceCode" label="设备编码" width="200" show-overflow-tooltip />
  16. <el-table-column prop="deviceName" label="设备名称" min-width="155" show-overflow-tooltip />
  17. <el-table-column prop="equipmentLocation" label="安装位置" min-width="200" show-overflow-tooltip />
  18. <el-table-column label="报警描述" min-width="270"><template #default="{ row }"><div>{{ alarmDescription(row) }}</div><div v-if="hasActualValue(row)" class="muted">实际值:{{ valueText(row.actualValue, row.warningUnit) }};阈值:{{ thresholdText(row) }}</div></template></el-table-column>
  19. <el-table-column label="报警等级" width="105" align="center"><template #default="{ row }"><el-tag :type="levelTone(row.alarmLevel)">{{ row.alarmLevelName }}</el-tag></template></el-table-column>
  20. <el-table-column prop="createTime" label="报警时间" width="180" sortable="custom" />
  21. <el-table-column label="监测状态" width="100" align="center"><template #default="{ row }"><el-tag :type="row.alarmStatus === 0 ? 'danger' : 'success'">{{ row.monitorStatusName }}</el-tag></template></el-table-column>
  22. <el-table-column prop="auditStatusName" label="审核结果" width="105" align="center">
  23. <template #default="{ row }"><el-tag effect="light" :type="auditStatusTone(row.auditStatus)">{{ row.auditStatusName || '未知' }}</el-tag></template>
  24. </el-table-column>
  25. <el-table-column prop="orderStatusName" label="处置状态" width="100" align="center">
  26. <template #default="{ row }"><el-tag effect="light" :type="row.workOrderId != null && row.orderStatus != null ? orderStatusType(row.orderStatus) : 'info'">{{ row.orderStatusName || '未转工单' }}</el-tag></template>
  27. </el-table-column>
  28. <el-table-column prop="receiveUserName" label="责任人" width="100"><template #default="{ row }">{{ row.receiveUserName || '未分配' }}</template></el-table-column>
  29. <el-table-column label="操作" width="80" fixed="right" align="center"><template #default="{ row }"><el-button link type="primary" @click="detailRef.open(row.id)">详情</el-button></template></el-table-column>
  30. <template #empty><el-empty :description="error ? '数据加载失败' : '暂无匹配报警'" /></template>
  31. </el-table>
  32. <pagination v-show="total > 0" v-model:page="pageNum" v-model:limit="pageSize" :total="total" @pagination="load" />
  33. </el-card><AlarmDetail ref="detailRef" />
  34. </div>
  35. </template>
  36. <script setup name="AlarmEventList">
  37. import { ref, reactive, watch, onBeforeUnmount } from 'vue'
  38. import { Search, Refresh } from '@element-plus/icons-vue'
  39. import { getAlarms, getAlarmOptions } from '@/api/alarm'
  40. import { alarmDescription, hasActualValue, valueText, thresholdText } from './utils/alarmReviewModel'
  41. import { auditStatusTone, levelTone, rangeParams } from './utils/alarmOperationsModel'
  42. import { orderStatusType } from '../pipeNetwork/ops/workOrder/workOrderDict'
  43. import { useAlarmScope } from './utils/useAlarmScope'
  44. import AlarmDetail from './AlarmDetail.vue'
  45. import './styles/alarmOperations.scss'
  46. const { scope, scopeKey, route } = useAlarmScope()
  47. const empty = () => ({ alarmNo: '', keyword: '', alarmLevel: undefined, alarmStatus: undefined })
  48. const filters = reactive(empty()), dates = ref([]), options = ref({}), rows = ref([]), total = ref(0)
  49. const pageNum = ref(1), pageSize = ref(10), ascending = ref(false), loading = ref(false), error = ref(''), detailRef = ref()
  50. let generation = 0
  51. async function load() {
  52. const token = ++generation; loading.value = true; error.value = ''
  53. try {
  54. const result = await getAlarms({ ...filters, ...rangeParams(dates.value), ...scope.value, pageNum: pageNum.value, pageSize: pageSize.value, ascending: ascending.value })
  55. if (token === generation) { rows.value = result.data.records || []; total.value = result.data.total || 0 }
  56. } catch (e) { if (token === generation) { rows.value = []; total.value = 0; error.value = e.message || '加载失败' } }
  57. finally { if (token === generation) loading.value = false }
  58. }
  59. function search() { pageNum.value = 1; return load() }
  60. function reset() { Object.assign(filters, empty()); dates.value = []; search() }
  61. function sort({ order }) { ascending.value = order === 'ascending'; search() }
  62. watch(scopeKey, async () => {
  63. ++generation; rows.value = []; total.value = 0; loading.value = false
  64. Object.assign(filters, empty()); dates.value = []; options.value = {}
  65. const key = scopeKey.value
  66. try { const result = await getAlarmOptions({ ...scope.value }); if (key === scopeKey.value) options.value = result.data || {} } catch (e) { error.value = e.message }
  67. if (key !== scopeKey.value) return
  68. await search()
  69. if (route.query.alarmId) detailRef.value?.open(route.query.alarmId)
  70. }, { immediate: true })
  71. onBeforeUnmount(() => { ++generation })
  72. watch(() => route.query.alarmId, id => { if (id) detailRef.value?.open(id) })
  73. </script>