Newer
Older
smartwell_front / src / views / home / alarm / current / components / detail.vue
liyaguang on 27 Apr 12 KB 视频轮询逻辑修改
<!--
  Description: 当前报警管理-详情
  Author: 李亚光
  Date: 2023-09-11
 -->
<script lang="ts" setup name="currentAlarmDetail">
import dayjs from 'dayjs'
import { ElMessage } from 'element-plus'
import { alarmProcessNode, detailAlarm } from '@/api/home/alarm/current'
import { getAlarmDetail } from '@/api/home/alarm/history'
import { toHumpObject } from '@/utils/String'
import { getAlarmLevelListPage, getAlarmTypeListPage } from '@/api/home/rule/alarm'
import { getDateDiff } from '@/utils/dayjs'
import showPosition from '@/views/home/device/device/components/showPosition.vue'
import { getDeviceListPage } from '@/api/home/device/device'
import monitorDataDialog from './monitorDataDialog.vue'
import gasDataDialog from './gasDataDialog.vue'
import { alarmValue } from '@/views/home/alarm/current/components/dict'
import { encrypt, decrypt, isEncrypt } from '@/utils/security1'
const $router = useRouter()
const $route = useRoute()
// 页面详情数据
const detailInfo = ref<{ [key: string]: string }>({})
// 描述列表数据
const descriptionsList = ref([
  {
    text: '报警编号',
    value: 'id',
    align: 'center',
  },
  {
    text: '报警类别',
    value: 'alarmCategory',
    align: 'center',
  },
  {
    text: '报警类型',
    value: 'alarmTypeName',
    align: 'center',
  },
  {
    text: '报警原因',
    value: 'alarmReason',
    align: 'center',
  },
  {
    text: '报警等级',
    value: 'alarmLevelName',
    align: 'center',
  },
  {
    text: '报警时间',
    value: 'ts',
    align: 'center',
  },
  {
    text: '设备类型',
    value: 'devTypeName',
    align: 'center',
  },
  {
    text: '设备编号',
    value: 'devcode',
    align: 'center',
  },
  {
    text: '位置',
    value: 'address',
    align: 'center',
  },
  {
    text: '详细地址',
    value: 'position',
    align: 'center',
  },
  {
    text: '管理单位',
    value: 'deptName',
    align: 'center',
  },
  {
    text: '负责人',
    value: 'personName',
    align: 'center',
  },
  // {
  //   text: '是否误报',
  //   value: 'realAlarmName',
  //   align: 'center',
  // },
  {
    text: '解除时间',
    value: 'cancelTime',
    align: 'center',
  },
  {
    text: '处置时长',
    value: 'duration',
    align: 'center',
  },
  // {
  //   text: '',
  //   value: '',
  //   align: '',
  // },
])
if ($route.query.type === 'history') {
  descriptionsList.value = descriptionsList.value.filter((item) => item.text !== '是否误报' && item.text)
}
// 报警动态
const alarmDynamics = ref<any[]>([])
const showDeviceTips = ref(false) // 展示设备编号提示
const deviceTips = ref({
  typeName: '',
  manufactureName: ''
})
// 页面loading
const loading = ref(false)
const loadingDynamics = ref(false)
// 获取报警详情数据
const fetchDetail = async () => {
  showDeviceTips.value = false
  loading.value = true
  const res1 = await getAlarmLevelListPage({ offset: 1, limit: 9999 })
  const res2 = await getAlarmTypeListPage({ offset: 1, limit: 9999 });
  ($route.query.type === 'history' ? getAlarmDetail : detailAlarm)($route.query.id as string).then((res) => {
    detailInfo.value = toHumpObject(res.data)
    detailInfo.value.cancelDuration = (detailInfo.value.cancelDuration || '').replace(/0天/g, '')
    // detailInfo.value.address = detailInfo.value.address.replace(/\s*/g,'')
    detailInfo.value.realAlarmName = detailInfo.value.realAlarm === '0' ? '是' : '否'
    detailInfo.value.alarmTypeName = res2.data.rows.filter((item: any) => item.id === detailInfo.value.alarmTypeId)[0]?.alarmType || ''
    detailInfo.value.alarmLevelName = res1.data.rows.filter((item: any) => item.id === detailInfo.value.alarmLevel)[0]?.alarmLevel || ''
    detailInfo.value.duration = detailInfo.value.ts && detailInfo.value.cancelTime ? getDateDiff(detailInfo.value.ts, detailInfo.value.cancelTime) : ''
    loading.value = false
    // 处理报警原因
    if (detailInfo.value.alarmCategory.includes('浓度') || detailInfo.value.alarmTypeName.includes('浓度')) {
      detailInfo.value.alarmReason = `${detailInfo.value.alarmValue}${detailInfo.value.watchObject === '2' ? 'PPM.M' : '%LEL'}`
    }
    else {
      detailInfo.value.alarmReason = (alarmValue[detailInfo.value.alarmValue] || '其他')
    }
    if (!detailInfo.value.alarmCategory.includes('浓度') && !detailInfo.value.alarmTypeName.includes('浓度')) {
      descriptionsList.value = descriptionsList.value.filter(item => item.text !== '详细地址')
      descriptionsList.value.push({
        text: '',
        value: ''
      })
    }
    // 查询设备类型和厂商
    getDeviceListPage({ offset: 1, limit: 1, devCode: detailInfo.value.devcode }).then(res => {
      if (res.data.rows.length) {
        showDeviceTips.value = true
        deviceTips.value = {
          typeName: res.data.rows[0].deviceName || detailInfo.value.devTypeName,
          manufactureName: res.data.rows[0].manufactureName
        }
      }
    })
  }).catch(() => {
    loading.value = false
  })

  // 获取报警动态
  loadingDynamics.value = true
  const info = JSON.parse($route.query.row as string)
  alarmProcessNode($route.query.id as string).then((res) => {
    alarmDynamics.value = res.data.map((item: any) => ({ ...toHumpObject(item) }))
    alarmDynamics.value.unshift({
      approvalTime: info.ts, // 报警生成时间
      process_name: '',
      approvalPerson: '报警生成',
      dept_name: '',
    })
    alarmDynamics.value = alarmDynamics.value.map((item: any) => ({
      ...item,
      approvalPerson: isEncrypt(item.approvalPerson) ? decrypt(item.approvalPerson) : item.approvalPerson,
    }))
    alarmDynamics.value.forEach((item: any) => {
      if (item.descn) {
        if (item.process_name === '挂起') {
          item.descn = `挂起时长:${item.descn.split('|')[0] || ''}${item.descn.split('|')[0] ? '小时' : ''} ;
            挂起原因:${item.descn.split('|')[1] || ''};`
        }
        else {
          item.descn = `内容:${item.descn}`
        }
      }
    })
    loadingDynamics.value = false
  }).catch(() => {
    loadingDynamics.value = false
  })
}
// 点击经纬度展示地图
const mapRef = ref()
const { proxy } = getCurrentInstance() as any
const showMap = (data: any, skip: boolean) => {
  if (!detailInfo.value.alarmCategory.includes('浓度') && !detailInfo.value.alarmTypeName.includes('浓度') && data.text === '位置' && !skip) {
    return
  }
  // console.log(data, 'data')
  if (data.text === '设备编号') {
    // JSON.parse($route.query.row as string).devcode
    if (!detailInfo.value.devcode || !detailInfo.value.devTypeName) {
      ElMessage.warning('缺少设备关键信息')
      return
    }
    if (!proxy.hasPerm('/device/manage')) {
      ElMessage.warning('没有对应权限菜单')
      return
    }
    $router.push({
      name: 'DeviceManageDetail',
      params: {
        type: 'detail',
      },
      query: {
        row: JSON.stringify({
          devcode: detailInfo.value.devcode,
          deviceType: detailInfo.value.devTypeName,
          deviceTypeName: detailInfo.value.devTypeName,
          devTypeName: detailInfo.value.devTypeName,
        }),
      },
    })
    return
  }
  if (data.text === '位置') {
    if (detailInfo.value.watchObject && detailInfo.value.devcode && detailInfo.value.ledgerId) {
      const watchObject = {
        1: 'WellMonitorDetail',
        2: 'StationMonitorDetail',
        3: 'PipelineMonitorDetail',
      } as { [key: string]: string }
      // 判断是否有菜单权限
      const watchObjectAuth = {
        1: '/well',
        2: '/station/monitor',
        3: '/pipeline',
      } as { [key: string]: string }
      if (!proxy.hasPerm(watchObjectAuth[detailInfo.value.watchObject])) {
        ElMessage.warning('没有对应权限菜单')
        return
      }
      $router.push({
        name: watchObject[detailInfo.value.watchObject],
        query: {
          id: detailInfo.value.ledgerId,
          deviceCode: detailInfo.value.devcode,
          typeName: detailInfo.value.devTypeName,
          row: JSON.stringify({
            id: detailInfo.value.ledgerId,
            typeName: detailInfo.value.devTypeName,
            deviceCode: detailInfo.value.devcode,
          }),
        },
      })
      // $router
    }
    return
  }
  if (data.text !== '详细地址' || !detailInfo.value[data.value]) {
    return
  }
  if (!detailInfo.value.lngGaode || !detailInfo.value.latGaode) {
    ElMessage.warning('该数据缺少坐标信息')
    return
  }
  mapRef.value.initDialog([detailInfo.value.lngGaode, detailInfo.value.latGaode])
}
// 查看数据 -- 浓度类
const dataRef = ref()
const gasRef = ref()
const viewData = () => {
  const timerange = [detailInfo.value.alarmTime || '', detailInfo.value.cancelTime || dayjs().format('YYYY-MM-DD HH:mm:ss')]
  if (detailInfo.value.devTypeName.includes('燃气智能监测终端')) {
    dataRef.value.initDialog(detailInfo.value, timerange)
  }
  else {
    gasRef.value.initDialog(detailInfo.value, timerange)
  }
}

onMounted(() => {
  fetchDetail()
})
</script>

<template>
  <!-- 布局 -->
  <app-container v-loading="loading" class="container">
    <!-- 查看数据 -->
    <monitor-data-dialog ref="dataRef" />
    <gas-data-dialog ref="gasRef" />
    <!-- <detail-page :title="`${$route.path.includes('current') ? '当前' : '历史'}报警详情`">
      <template #btns>
        <el-button type="info" @click="$router.back()">
          关闭
        </el-button>
      </template>
</detail-page> -->
    <detail-block-com>
      <el-descriptions :column="2" border>
        <el-descriptions-item v-for="item in descriptionsList" :key="item.text" :align="item.align">
          <template #label>
            <span class="label">
              {{ item.text }}
            </span>
          </template>
          <span
            :class="`${item.text === '详细地址' ? 'pointer link' : item.text === '位置' || item.text === '设备编号' ? 'pointer link' : ''}`"
            @click="showMap(item, false)">
            <el-tooltip v-if="showDeviceTips && item.text === '设备编号'" class="box-item" effect="dark"
              :content="`${deviceTips.typeName}(${deviceTips.manufactureName})`" placement="top">
              {{ detailInfo[item.value] || '' }}
            </el-tooltip>
            <template v-else>
              <template
                v-if="item.text === '位置' && !detailInfo.alarmCategory?.includes('浓度') && !detailInfo.alarmTypeName?.includes('浓度')">
                <el-popconfirm confirm-button-text="地图点位" cancel-button-text="安装位置" icon-color="#626AEF"
                  title="选择查看内容?" @confirm="showMap({...item, text: '详细地址'}, true)" @cancel="showMap({...item, text: '位置'}, true)" width="180">
                  <template #reference>
                    {{ detailInfo[item.value] || '' }}
                  </template>
                </el-popconfirm>
              </template>
              <template v-else>
                {{ detailInfo[item.value] || '' }}
                <!-- 报警原因 --查看数据(浓度类报警)按钮 -->
                <el-button v-if="item.text === '报警原因' && detailInfo.alarmCategory?.includes('浓度')" type="primary"
                  size="small" @click="viewData">查看数据</el-button>
              </template>
            </template>
          </span>
        </el-descriptions-item>
        <el-descriptions-item v-loading="loadingDynamics" align="left" label-align="center">
          <template #label>
            <span class="label">
              报警动态
            </span>
          </template>
          <div style="padding: 25px;">
            <el-timeline>
              <el-timeline-item v-for="(item, index) in alarmDynamics" :key="index" :timestamp="item.approvalTime"
                type="primary">
                <div>{{ `${item.approvalPerson}${item.dept_name ? '(' : ''}${item.dept_name}${item.dept_name ? ')' :
                  ''}${item.process_name}` }}</div>
                <div v-if="item.descn">{{ item.descn }}</div>
              </el-timeline-item>
            </el-timeline>
          </div>
        </el-descriptions-item>
      </el-descriptions>
      <show-position ref="mapRef" />
    </detail-block-com>
  </app-container>
</template>

<style lang="scss" scoped>
::v-deep(.el-descriptions__label) {
  width: 15%;
}

::v-deep(.el-descriptions__content) {
  width: 35%;
}

.pointer {
  &:hover {
    cursor: pointer;
  }
}

.link {
  color: #0d76d4;

  &:hover {
    text-decoration: underline;
  }
}

.bottom {
  --el-descriptions-table-border-top: none;

  ::v-deep(.el-descriptions) {
    --el-descriptions-table-border-top: none;
  }
}

::v-deep(.el-popconfirm__action) {
  .el-popconfirm__action{
    background-color: #0d76d4;
  }
}
</style>