Newer
Older
smartwell_front / src / views / home / temporary / components / map.vue
liyaguang on 31 Mar 11 KB 防外力破坏监测
<!--
  Description: 闸井监测-地图
  Author: 李亚光
  Date: 2023-07-08
 -->
 <script lang="ts" setup name="WellMap">
 import detailInfo from './detailInfoDialog.vue'
 import AMap from '@/components/map/index.vue'

 const $props = defineProps({
   height: {
     type: Number,
     default: 0,
   },
   // 点位数据
   data: {
     type: Array,
     default: () => ([]),
   },
   // 管线数据
   pipe: {
     type: Array,
     default: () => ([]),
   },
 })
 const $emits = defineEmits(['clickMarker'])
 // 地图实例
 const mapRef = ref()
 const publicPath = window.location.href.split('#')[0]
 // 展示图例数据
 const legendShowData = ref(['管网哨兵', '燃气智能监测终端'])
 const resetLegend = () => {
   legendShowData.value = ['管网哨兵', '燃气智能监测终端']

 }
 // 地图图例数据
 const legendData = ref([
   {
     name: '管网哨兵',
     url: `${publicPath}/image/pipeline/underground-normal.png`,
     value: '管网哨兵',
   },
   {
     name: '燃气智能监测终端',
     url: `${publicPath}/image/pipeline/ranqi-normal.png`,
     value: '燃气智能监测终端',
   },
 ])
 // 控制图例
 const clickLegend = (type: string) => {
   if (legendShowData.value.includes(type)) {
     legendShowData.value = legendShowData.value.filter((item: string) => item !== type)
   }
   else {
     legendShowData.value.push(type)
   }
   resetDraw()
 }
 // 初次加载标识
 const pageIsFirst = ref(true)
 // 绘制标记点
 const drawMarker = () => {
   const style = [
    {
       url: `${publicPath}/image/pipeline/underground-normal.png`, // 图标地址
      //  anchor: new mapRef.value.AMap.Pixel(-13, -13), // 图标显示位置偏移量,基准点为图标左上角
      //  size: new mapRef.value.AMap.Size(26, 26), // 图标的尺寸
       zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前
     },
     {
       url: `${publicPath}/image/pipeline/underground-error.png`, // 图标地址
      //  anchor: new mapRef.value.AMap.Pixel(-13, -13), // 图标显示位置偏移量,基准点为图标左上角
      //  size: new mapRef.value.AMap.Size(26, 26), // 图标的尺寸
       zIndex: 100, // 每种样式图标的叠加顺序,数字越大越靠前
     },
     {
       url: `${publicPath}/image/pipeline/underground-no.png`, // 图标地址
      //  anchor: new mapRef.value.AMap.Pixel(-13, -13), // 图标显示位置偏移量,基准点为图标左上角
      //  size: new mapRef.value.AMap.Size(26, 26), // 图标的尺寸
       zIndex: 100, // 每种样式图标的叠加顺序,数字越大越靠前
     },
    //  {
    //    url: `${publicPath}/image/pipeline/underground-offline.png`, // 图标地址
    //    anchor: new mapRef.value.AMap.Pixel(-13, -13), // 图标显示位置偏移量,基准点为图标左上角
    //    size: new mapRef.value.AMap.Size(26, 26), // 图标的尺寸
    //    zIndex: 98, // 每种样式图标的叠加顺序,数字越大越靠前
    //  },


    //  {
    //    url: `${publicPath}/image/pipeline/ranqi-no.png`, // 图标地址
    //    anchor: new mapRef.value.AMap.Pixel(-13, -13), // 图标显示位置偏移量,基准点为图标左上角
    //    size: new mapRef.value.AMap.Size(26, 26), // 图标的尺寸
    //    zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前
    //  },
     {
       url: `${publicPath}/image/pipeline/ranqi-normal.png`, // 图标地址
      //  anchor: new mapRef.value.AMap.Pixel(-13, -13), // 图标显示位置偏移量,基准点为图标左上角
      //  size: new mapRef.value.AMap.Size(26, 26), // 图标的尺寸
       zIndex: 101, // 每种样式图标的叠加顺序,数字越大越靠前
     },
     {
       url: `${publicPath}/image/pipeline/ranqi-error.png`, // 图标地址
      //  anchor: new mapRef.value.AMap.Pixel(-13, -13), // 图标显示位置偏移量,基准点为图标左上角
      //  size: new mapRef.value.AMap.Size(26, 26), // 图标的尺寸
       zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前
     },
     {
       url: `${publicPath}/image/pipeline/ranqi-no.png`, // 图标地址
      //  anchor: new mapRef.value.AMap.Pixel(-13, -13), // 图标显示位置偏移量,基准点为图标左上角
      //  size: new mapRef.value.AMap.Size(26, 26), // 图标的尺寸
       zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前
     },
     // {
     //   url: `${publicPath}/image/pipeline/station-offline.png`, // 图标地址
     //   anchor: new mapRef.value.AMap.Pixel(4, 4), // 图标显示位置偏移量,基准点为图标左上角
     //   size: new mapRef.value.AMap.Size(20, 20), // 图标的尺寸
     //   zIndex: 99, // 每种样式图标的叠加顺序,数字越大越靠前
     // },
   ]
  //  0 未监控  1 正常 2 异常 3 离线
   const styleDict = {
    //  '管网哨兵-0': 0,
     '管网哨兵-1': 0,
     '管网哨兵-2': 1,
     '管网哨兵-3': 2,

    //  '燃气智能监测终端-0': 4,
     '燃气智能监测终端-1': 3,
     '燃气智能监测终端-2': 4,
     '燃气智能监测终端-3': 5,
   } as { [key: string]: number }
   const data = $props.data.filter((item: any) => item.lng && item.lat && item.deviceTypeName && item.status).map((item: any) => ({
     lnglat: [item.lng, item.lat],
     name: item.deviceTypeName.includes('管网哨兵') ?  '管网哨兵' : item.deviceTypeName.includes('燃气智能监测终端') ?  '燃气智能监测终端':  item.deviceTypeName,
     id: item.deviceCode,
     row: item,
   })).map((item) => ({
     ...item,
     style: styleDict[`${item.name}-${item.row.status}`] || 0,
   }))
   .filter((item: any) => legendShowData.value.includes(item.name))
   mapRef.value.addMassMarks({
     path: data,
     zIndex: 111,
     zooms: [3, 20],
     style,
   })
   if (pageIsFirst.value) {
     mapRef.value.map.setCenter([116.397428, 39.90923])
     mapRef.value.map.setZoom(10.5)
   }
   // else {
   //   mapRef.value.map.setFitView()
   // }

 }
 // 绘制线
 const drawLine = () => {
   const data = $props.pipe.filter((item: any) => item.endLat && item.endLng && item.startLng && item.startLat && item.pipeCode)
   // console.log(data, '准备绘制线')
   data.forEach((item: any) => {
     mapRef.value.addPolyline({
       path: [[item.startLng, item.startLat], [item.endLng, item.endLat]],
       style: {
         strokeColor: '#E80D0D',
         strokeWeight: 2,
         strokeStyle: 'solid',
         zIndex: 95,
       },
     })
   })
 }
 // 点标记弹窗
 const detail = ref()
 const detailRef = ref()
 const massMarksClick = (data: any) => {
   $emits('clickMarker', data.event.data.row)
   mapRef.value.map.setZoom(10.5)
   // 定义弹窗
   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), // 偏移
   })
   // 打开信息窗口
   detail.value.open(data.map, data.event.data.lnglat)
   // 初始化信息窗口
   detailRef.value.initDialog({
     overlay: data.event.target,
     infoWindow: detail.value,
     info: data.event.data,
     map: mapRef.value.map,
   })
   setTimeout(() => {
     const center = JSON.parse(JSON.stringify(data.event.data.lnglat))
     center[1] = Number(center[1]) + 0.0045
     mapRef.value.map.setCenter(center)
   })
   // 关联的管线高亮
   const line = $props.pipe.filter((item: any) => item.pipeCode === data.event.data.row.pipeCode)
   if (line.length) {
     if (!mapRef.value.lineAllList.length) {
       return
     }
     const link = mapRef.value.lineAllList.filter((item: any) => line.filter((citem: any) => [[citem.startLng, citem.startLat], [citem.endLng, citem.endLat]].join() === item.$x.join()).length)
     if (link.length) {
       link.forEach((element: any) => {
         element.setOptions({
           strokeColor: '#34A0E8',
           strokeWeight: 4,
         })
       })
     }
   }
 }

 // 打开信息窗体
 const openInfoDetail = (data: any) => {
   mapRef.value.map.setZoom(10.5)
   // 定义弹窗
   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), // 偏移
   })
   // 打开信息窗口
   setTimeout(() => {
     detail.value.open(mapRef.value.map, data.lnglat)
     // 初始化信息窗口
     detailRef.value.initDialog({
       infoWindow: detail.value,
       info: data,
       map: mapRef.value.map,
     })
     const center = JSON.parse(JSON.stringify(data.lnglat))
     center[1] = Number(center[1]) + 0.0045
     mapRef.value.map.setCenter(center)
   })
 }
 // 重置标记点
 function resetDraw() {
   mapRef.value.removeMassMarks()
   if (detailRef.value) {
     detailRef.value.close()
   }
   if ($props.data) {
     // 清空标记点重新绘制
     drawMarker()
   }
 }
 // 重置线
 function resetDrawLine() {
   mapRef.value.removePolyline()
   if (detailRef.value) {
     detailRef.value.close()
   }
   if ($props.pipe) {
     // 清空闲重新绘制
     drawLine()
   }
 }

 // 地图绘制完毕
 const completeMap = () => {
   // 绘制海量点
   resetDraw()
   clickLegend('智能警示桩')
   setTimeout(() => {
     clickLegend('智能警示桩')
   })
   // 绘制线
   resetDrawLine()
   setTimeout(() => {
     pageIsFirst.value = false
   }, 2000)
 }
 defineExpose({ openInfoDetail, drawMarker, resetDraw, drawLine, resetDrawLine, mapRef, resetLegend })
 </script>

 <template>
   <div :style="`height: ${$props.height}px`" class="map-container">
     <!-- 设备信息窗体 -->
     <detail-info ref="detailRef" />
     <!-- 地图 -->
     <a-map ref="mapRef" :show-pieple-layer="true" @complete="completeMap" @massMarksClick="massMarksClick" />
     <!-- 图例 -->
     <div class="legend">
       <div v-for="item in legendData" :key="item.value" class="legend-item" @click="clickLegend(item.value)">
         <img v-show="legendShowData.includes(item.value)" class="img" :src="item.url">
         <!-- <span v-show="!legendShowData.includes(item.value)" class="img" /> -->
         <img v-show="!legendShowData.includes(item.value)" class="img transparent" :src="item.url">
         <span style="margin-left: 5px;">{{ item.name }}</span>
       </div>
     </div>
   </div>
 </template>

 <style lang="scss" scoped>
 .map-container {
   width: 100%;
   position: relative;
 }

 .legend {
   background: rgb(255 255 255 / 80%);
   position: absolute;
   z-index: 1;
   left: 15px;
   bottom: 10px;
   padding: 0 10px;
   border-radius: 3px;
   color: #000;

   .legend-item {
     margin: 10px 0;
     // font-weight: 700;
     display: flex;
     align-items: center;

     .img {
       width: 24px;
       height: 24px;
     }
     .transparent{
       opacity: 0.25;
     }

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