Newer
Older
robot_dog_patrol_front / src / views / home / dashboard / components / eventMap.vue
<!--
  Description: 综合大屏-布控地图
  Author: 李亚光
  Date: 2024-07-18
 -->
<script lang="ts" setup>
import allAlarmStatus from '../fullScreen-components/allAlarmStatus.vue'
import deptAlarmCount from '../fullScreen-components/deptAlarmCount.vue'
import currentAlarm from '../fullScreen-components/currentAlarm.vue'
import deviceOnlineMonitor from '../fullScreen-components/deviceOnlineMonitor.vue'
import deviceAlarmTrend from '../fullScreen-components/deviceAlarmTrend.vue'
import alarmCount from '../fullScreen-components/alarmCount.vue'
import detailInfo from './alarmDialog.vue'
import { img } from './imgData'
import { getAlarmLevelListPage } from '@/api/home/rule/alarm'
import { getCurrentAlarmListPage } from '@/api/home/alarm/current'
import AMap from '@/components/map/index.vue'
// 地图实例
const mapRef = ref()

// 图例展示
const legend = ref<string[]>([])
const legendData = ref<any[]>([])
// 双击多边形(行政区或九五示范区)掉起弹窗
const detail = ref()
const detailRef = ref()

// 绘点标记
const drawMarker = (data: any, style: any, type: string) => {
  mapRef.value.addMassMarks({
    path: data,
    zIndex: 111,
    zooms: [0, 100],
    style,
  })
  // 判断图例设置(没有显示的直接就隐藏)
  if (!legend.value.includes(type)) {
    mapRef.value.massMarksAllList.forEach((line: any) => {
      line.hide()
    })
  }
}
// 阀门,调压站等点标记点击
const massMarksClick = (data: any) => {
  // 定义弹窗
  detail.value = new mapRef.value.AMap.InfoWindow({
    closeWhenClickMap: true, // 是否在鼠标点击地图后关闭信息窗体
    autoMove: true, // 是否自动调整窗体到视野内
    isCustom: true, // 自定义信息窗体
    content: detailRef.value.$el, // 窗体内容(vue组件)
    offset: new mapRef.value.AMap.Pixel(9, -5), // 偏移
  })
  // 打开信息窗口
  console.log(data.event.data.lnglat, 'data.event.data.lnglat')
  detail.value.open(data.map, data.event.data.lnglat)
  // 初始化信息窗口
  detailRef.value.initDialog({
    overlay: data.event.target,
    infoWindow: detail.value,
    info: data.event.data,
  })
}

// 点击图例,显示隐藏对应的点或线
const clickLegend = (data: { name: string; type: string }) => {
  if (legend.value.includes(data.name)) {
    //  隐藏
    legend.value = legend.value.filter((citem: string) => citem !== data.name)
    mapRef.value.massMarksAllList.filter((item: any) => item.getData().some((citem: any) => citem.type === data.name)).forEach((marker: any) => {
      marker.hide()
    })
  }
  else {
    // 显示
    legend.value.push(data.name)
    mapRef.value.massMarksAllList.filter((item: any) => item.getData().some((citem: any) => citem.type === data.name)).forEach((marker: any) => {
      marker.show()
    })
  }
}

// 获取报警等级
const publicPath = window.location.href.split('#')[0]
async function fetchAlarmLevel() {
  legendData.value = []
  const res = await getAlarmLevelListPage({ offset: 1, limit: 9999 })
  const colorObj = {
    一级: '#f56c6c',
    二级: '#ee9611',
    三级: '#ffd700',
    其他: '#8dc6ea',
  } as { [key: string]: string }
  const imgObj = {
    一级: `${publicPath}/image/other/one-icon.png`,
    二级: `${publicPath}/image/other/two-icon.png`,
    三级: `${publicPath}/image/other/three-icon.png`,
    其他: `${publicPath}/image/other/other-icon.png`,
  } as { [key: string]: string }
  legendData.value = []
  legend.value = []
  res.data.rows.forEach((element: any) => {
    legend.value.push(element.alarmLevel)
    const obj = {
      name: element.alarmLevel,
      // img: img.alarm,
      type: 'marker',
      color: '',
      img: '',
    }
    for (const i in colorObj) {
      if (element.alarmLevel.includes(i)) {
        obj.color = colorObj[i]
        obj.img = imgObj[i]
      }
    }
    if (!obj.color) {
      obj.color = colorObj['其他']
      obj.img = `${publicPath}/image/other/other-icon.png`
    }
    legendData.value.push(obj)
  })
  console.log(legendData.value, 'legendData.value')
}
// 获取报警
const alarmList = ref<any[]>([])

const fetchAlarm = () => {
  getCurrentAlarmListPage({ offset: 1, limit: 9999 }).then((res) => {
    alarmList.value = res.data.rows
    const style = [
      {
        url: `${publicPath}/image/other/one.png`,
        anchor: new mapRef.value.AMap.Pixel(4, 4),
        size: new mapRef.value.AMap.Size(18, 18),
        zIndex: 99,
        type: '一级',
      },
      {
        url: `${publicPath}/image/other/two.png`,
        anchor: new mapRef.value.AMap.Pixel(4, 4),
        size: new mapRef.value.AMap.Size(18, 18),
        zIndex: 99,
        type: '二级',
      },
      {
        url: `${publicPath}/image/other/three.png`,
        anchor: new mapRef.value.AMap.Pixel(4, 4),
        size: new mapRef.value.AMap.Size(18, 18),
        zIndex: 99,
        type: '三级',
      },
      {
        url: `${publicPath}/image/other/other.png`,
        anchor: new mapRef.value.AMap.Pixel(4, 4),
        size: new mapRef.value.AMap.Size(18, 18),
        zIndex: 99,
        type: '其他',
      },
    ]
    legendData.value.forEach((item: any) => {
      drawMarker(
        alarmList.value.filter((citem: any) => citem.alarmLevelName === item.name && citem.lngGaode && citem.latGaode).map((citem: any) => ({
          lnglat: [citem.lngGaode, citem.latGaode],
          name: citem.alarmContent,
          style: style.findIndex(citem => item.name.includes(citem.type)) === -1 ? 3 : style.findIndex(citem => item.name.includes(citem.type)),
          type: citem.alarmLevelName,
          id: citem.id,
        })), style, item.name,
      )
    })
    mapRef.value.map.setCenter([alarmList.value[0].lngGaode, alarmList.value[0].latGaode])
    mapRef.value.map.setZoom(11)
  })
}
// 获取报警
// 地图挂载完毕执行
const drawBj = async () => {
  await fetchAlarmLevel()
  fetchAlarm()
}
</script>

<template>
  <div class="full-container">
    <!-- 左侧 -->
    <div class="left-container">
      <!-- 总体报警情况 -->
      <all-alarm-status type=" " />
      <!-- 各分公司报警统计  -->
      <dept-alarm-count type=" " style="margin-top: 20px;" />
      <!-- 当前报警 -->
      <current-alarm style="margin-top: 20px;" />
    </div>
    <!-- 右侧 -->
    <div class="right-container">
      <!-- 设备在线监控 -->
      <device-online-monitor />
      <!-- 设备报警趋势 -->
      <device-alarm-trend style="margin-top: 20px;" />
      <!-- 累计报警统计 -->
      <alarm-count style="margin-top: 20px;" />
    </div>
    <!-- 设备信息窗体 -->
    <detail-info ref="detailRef" />
    <!-- 地图 -->
    <a-map
      ref="mapRef" layer="dark" :zoom="14" :center="[116.397428, 39.90923]" @complete="drawBj"
      @massMarksClick="massMarksClick"
    />
    <!-- 图例 -->
    <div v-if="legendData.length" class="amap-legend2">
      <div v-for="(item) in legendData" :key="item.name" class="legend-item">
        <div class="icon" :class="legend.includes(item.name) ? '' : 'none'">
          <img :src="item.img">
        </div>
        <div class="value" @click="clickLegend({ name: item.name, type: item.type })">
          {{ item.name }}
        </div>
      </div>
    </div>
  </div>
</template>

<styele lang="scss" scoped>
.show-count {
  position: absolute;
  z-index: 9;
  left: 400px;
  top: 100px;
  width: 240px;
}

.show-change {
  position: absolute;
  top: 100px;
  right: 400px;
  z-index: 9;
  // background-color: #ddd;

  .change {
    padding: 10px 20px;
    text-align: center;
    background: url("@/assets/fullscren/data-bg.png") no-repeat center center / cover;
    border: 1px solid #249eff;
    color: #fff;

    &:hover {
      cursor: pointer;
    }
  }
}

.left-container {
  position: absolute;
  z-index: 9;
  top: 100px;
  left: 15px;
  background-color: rgba($color: #0B0B0F, $alpha: 0.8);
}

.right-container {
  position: absolute;
  z-index: 9;
  top: 100px;
  right: 15px;
  // background-color: #0b0b0f;
  background-color: rgba($color: #0B0B0F, $alpha: 0.8);
}

.amap-legend1 {
  /* background: url("@/assets/images/dashboard/legend.png") no-repeat center center / cover; */
  position: absolute;
  z-index: 9;
  bottom: 10px;
  left: 400px;
  /* background: rgb(68 66 66 / 80%); */
  background-color: rgba($color: #0B0B0F, $alpha: 0.8);
  border: 2px solid #249eff;
  color: #fff;
  padding: 10px;

  .legend-item {
    display: flex;
    margin: 5px;
    flex-wrap: wrap;
    color: #a7ceec;

    img {
      height: 16px;
      width: 16px;
    }

    .value {
      margin-left: 5px;
      height: 16px;
      line-height: 16px;

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

.amap-legend2 {
  /* background: url("@/assets/images/dashboard/legend.png") no-repeat center center / cover; */
  position: absolute;
  z-index: 9;
  bottom: 10px;
  right: 400px;
  background-color: rgba($color: #0B0B0F, $alpha: 0.8);

  border: 2px solid #249eff;
  color: #fff;
  padding: 10px;

  .legend-item {
    display: flex;
    margin: 5px;
    flex-wrap: wrap;
    color: #a7ceec;

    // .icon {
    //   height: 20px;
    //   width: 20px;
    //   border-radius: 50%;
    //   opacity: 0.8;
    // }
    img {
      height: 16px;
      width: 16px;
    }

    .value {
      margin-left: 5px;
      height: 20px;
      line-height: 20px;

      &:hover {
        cursor: pointer;
      }
    }
  }
}
</styele>

<style>
.full-container {
  width: 100%;
  height: 100vh;
}

.none {
  opacity: 0 !important;
}

.close {
  width: 150px;
  height: 70px;
  position: fixed;
  top: 0;
  right: 0;

  /* background-color: antiquewhite; */
  &:hover {
    .icon {
      display: block;
    }
  }

  .icon {
    display: none;
    width: 50px;
    height: 50px;
    background: rgb(145 144 144 / 60%);
    border-radius: 50%;
    line-height: 50px;
    text-align: center;
    font-size: 18px;
    font-weight: 700;
    color: #ccc;
    margin: 10px auto;

    &:hover {
      cursor: pointer;
    }
  }
}
</style>