index.vue 7.04 KB
<template>
  <div ref="vChartRef"></div>
</template>

<script setup lang="ts">
import { ref, PropType, toRefs, watch } from 'vue'
import AMapLoader from '@amap/amap-jsapi-loader'
import { CreateComponentType } from '@/packages/index.d'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { MarkerEnum, ThemeEnum } from './config'
import { isArray } from '@/utils'
import djh from './images/djh.png'
import online from './images/online1.png'
import lx1 from './images/lx1.png'
import { getDeviceActiveTime } from '@/api/external/common/index'
import dayjs from 'dayjs'

const props = defineProps({
  chartConfig: {
    type: Object as PropType<CreateComponentType>,
    required: true
  }
})

let {
  amapKey,
  amapStyleKey,
  amapLon,
  amapLat,
  amapZindex,
  mapMarkerType,
  lang,
  amapStyleKeyCustom,
  features,
  viewMode,
  pitch,
  skyColor,
  marker
} = toRefs(props.chartConfig.option.mapOptions)

let mapIns: any = null
let markers: any = []
let AMapIns: any = null
const vChartRef = ref<HTMLElement>()

const initMap = (newData: any) => {
  // 初始化
  AMapLoader.load({
    key: amapKey.value, //api服务key--另外需要在public中使用安全密钥!!!
    version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 需要使用的的插件列表
  })
    .then(AMap => {
      AMapIns = AMap
      mapIns = new AMap.Map(vChartRef.value, {
        resizeEnable: true,
        zoom: amapZindex.value, // 地图显示的缩放级别
        center: [amapLon.value, amapLat.value],
        lang: lang.value,
        features: features.value,
        pitch: pitch.value, // 地图俯仰角度,有效范围 0 度- 83 度
        skyColor: skyColor.value,
        viewMode: viewMode.value, // 地图模式
        willReadFrequently: true
      })
      dataHandle(props.chartConfig.option.dataset)
      let satellite = new AMap.TileLayer.Satellite()
      let roadNet = new AMap.TileLayer.RoadNet()
      if (newData.amapStyleKey === ThemeEnum.WEIXIN) {
        mapIns.add([satellite, roadNet])
      } else {
        mapIns.remove([satellite, roadNet])
        mapIns.setMapStyle(
          `amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}`
        )
      }
      //点击地图任意地方关闭infoWindow窗体
      mapIns.on('click', () => {
        mapIns.clearInfoWindow()
      })
    })
    .catch(e => {
      console.error(e)
    })
}

const createInfoWindow = async (extraInfo: any) => {
  try {
    const { name, alias, organizationDTO, deviceState, deviceProfile, deviceInfo, tbDeviceId } = extraInfo
    const res = await getDeviceActiveTime(tbDeviceId)
    let { lastUpdateTs } = res[0]
    lastUpdateTs = dayjs(lastUpdateTs).format('YYYY-MM-DD HH:mm:ss')
    return `
        <div style="width:15vw;height:18vh;background-color:white;">
         <div style="margin:0px 10px">
          <div style="display:flex;justify-content:space-between; margin:20px 0px;">
            <div style="font-size:16px;font-weight:bold">${alias || name}</div>
            ${
              deviceState === 'INACTIVE'
                ? `<div style="display:flex;align-items:center;"><img style="width:15px;height:15px" src="${djh}" class="mr-1">待激活</div>`
                : deviceState === 'ONLINE'
                ? `<div style="display:flex;align-items:center; ">
                <img style="width:15px;height:15px"  src="${online}"  class="mr-1">在线</div>`
                : `<div style="display:flex;align-items:center;"><img style="width:15px;height:15px" src="${lx1}" class="mr-1">离线</div>`
            }
          </div>
          <div>所属组织:${organizationDTO.name}</div>
          <div style="margin-top:6px;">接入协议:${deviceProfile.transportType}</div>
          <div style="margin-top:6px;">
            设备位置:${!deviceInfo.address ? '该设备暂无地理位置' : deviceInfo.address}
          </div>
          <div style="margin-top:6px;">
            ${deviceState === 'ONLINE' ? '在线' : deviceState === 'INACTIVE' ? '创建' : '离线'}时间:${lastUpdateTs}
            </div>
            </div>
          </div>
          `
  } catch (e) {
    console.error(e)
  }
}

const dataHandle = (newData: any) => {
  if (!mapIns && !AMapIns) {
    initMap(props.chartConfig.option)
    return
  }
  if (isArray(newData.markers)) {
    // 先清除旧标记
    mapIns.remove(markers)
    markers = []
    // 记录新标记
    if (mapMarkerType.value === MarkerEnum.MARKER) {
      newData.markers.forEach((markerItem: any) => {
        const markerInstance = new AMapIns.Marker({
          position: [markerItem.position[0], markerItem.position[1]],
          offset: new AMapIns.Pixel(-13, -30)
        })
        // markers.push(markerInstance) 原作者这种方式添加,地图标注获取不到当前点击对象
        // markerInstance.setMap(mapIns)
        markerInstance.setExtData({
          extraInfo: markerItem.extraInfo
        })
        mapIns.add(markerInstance)
        markerInstance.setLabel({
          content: markerItem.extraInfo.alias || markerItem.extraInfo.name
        })
        markerInstance.on('click', async (e: any) => {
          const { extraInfo } = e.target.getExtData()
          let infoWindow = new AMapIns.InfoWindow({
            content: await createInfoWindow(extraInfo),
            offset: new AMapIns.Pixel(0, -50)
          })
          infoWindow.open(mapIns, e.target.getPosition())
        })
      })
    } else if (mapMarkerType.value === MarkerEnum.CIRCLE_MARKER) {
      newData.markers.forEach((markerItem: any) => {
        const markerInstance = new AMapIns.CircleMarker({
          center: [
            !markerItem.position[0] ? 0 : markerItem.position[0],
            !markerItem.position[1] ? 0 : markerItem.position[1]
          ],
          radius: markerItem.value,
          ...marker.value,
        })
        // markers.push(markerInstance) //原作者这种方式添加,地图标注获取不到当前点击对象
        // markerInstance.setMap(mapIns)
        markerInstance.setExtData({
          extraInfo: markerItem.extraInfo
        })
        mapIns.add(markerInstance)
        markerInstance.on('click', async (e: any) => {
          console.log(e)
          const { extraInfo } = e.target.getExtData()
          let infoWindow = new AMapIns.InfoWindow({
            content: await createInfoWindow(extraInfo),
            offset: new AMapIns.Pixel(0, -50)
          })
          infoWindow.open(mapIns, e.target.getPosition())
        })
      })
    }
  }
}

const stopWatch = watch(
  () => props.chartConfig.option.mapOptions,
  option => {
    initMap(option)
  },
  {
    immediate: true,
    deep: true
  }
)

watch(
  () => props.chartConfig.option.dataset,
  newData => {
    try {
      dataHandle(newData)
    } catch (error) {
      console.log(error)
    }
  },
  {
    deep: false
  }
)

// 预览
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
  stopWatch()
  dataHandle(newData)
})
</script>