Newer
Older
carbon-metering-front / src / components / map / index.vue
liyaguang on 3 Aug 2023 16 KB feat(*): 添加用热节点
<!--
  Description: 高德地图
  Author: 李亚光
  Date: 2023-04-21
 -->
<script lang="ts" setup name="GuadMap">
import AMapLoader from '@amap/amap-jsapi-loader'
import infoDetail from './infoWindow.vue'
import infoDetail2 from './infoWindow2.vue'
import infoDetailHot from './infoWindowHot.vue'
import { HotNodeList, branchList, electNodeList, guangfuList } from './mock.js'
import { getDictByCode } from '@/api/system/dict'
import { electricityBranch, electricityNode, getAreaPosition, getDeviceListPage, getElectricityListAll, getMonitorStationList } from '@/api/api/index'
const publicPath = import.meta.env.BASE_URL
// 设置安全密钥
window._AMapSecurityConfig = {
  securityJsCode: '56bf9671d4b3517d294caec4751889a1', // 后期需替换
}
const electricityList = ref()
// 地图实例
const map = ref()
//  用来画区域的
const polygon = ref()
//  画图工具实例
const mouseTool = ref()
// 区域数组
const pathArr = ref([
  [111.737806, 40.83386],
  [111.736806, 40.83686],
  [111.739906, 40.83686],
  [111.739906, 40.83386],
])
// 电网节点数组
const markerArr = ref([
])
// 光伏数组
const markerArr1 = ref([
])
// 用热坐标数组
const markerArrHot = ref()
const markerArrHotInfo = ref()
// 信息窗体
const infoWindow = ref()
const infoWindow2 = ref()
const infoWindowHot = ref()
const windowInfoRef = ref()
const windowInfoRef2 = ref()
const windowInfoHotRef = ref()
const markerArrInfo = ref()
const markerArrInfo1 = ref()
// 折现节点坐标
const lineArr = ref([])
// 地图点击事件
const clickHandler = function (e) {
  const location = [e.lnglat.getLng(), e.lnglat.getLat()]
  if (event.button === 2) {
    console.log('当前点击坐标为:   ', location)
  }
}
// 地图实例对象
const AMap1 = ref()
// 图层实例
const layer = ref()
const flag = ref(false)
// 切换图层
const changeLayerGrop = () => {
  if (flag.value) {
    map.value.addLayer(layer.value)
  }
  else {
    map.value.removeLayer(layer.value)
  }
  flag.value = !flag.value
}
// 初始化地图
const initMap = async () => {
  await AMapLoader.load({
    key: '40849e82b4e33f5255b17372520c954d', // 后期需替换
    version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    plugins: ['AMap.Scale', 'AMap.MouseTool', 'AMap.ToolBar'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
  }).then((AMap) => {
    AMap1.value = AMap
    // 初始化地图
    map.value = new AMap.Map('map', {
      viewMode: '3D', //  是否为3D地图模式
      zoom: 18, // 初始化地图级别
      center: [111.73142, 40.830627],
      resizeEnable: true,
    })
    // 图层实例
    layer.value = new AMap.TileLayer.Satellite()
    map.value.addLayer(layer.value)
    // 地图绑定右击事件
    map.value.on('mousedown', clickHandler)
  })
    .catch((e) => {
      console.log(e)
    })
}
// 绘制用电监测相关
const useElectricity = () => {
  const AMap = AMap1.value
  // 电网支路标记点绘制
  for (let i = 0; i < markerArr.value.length; i++) {
    const icon = new AMap.Icon({
      size: new AMap.Size(36, 36), // 图标尺寸
      image: `${publicPath}img/icon1.png`, // Icon的图像
      imageSize: new AMap.Size(24, 30), // 根据所设置的大小拉伸或压缩图片
      imageOffset: new AMap.Pixel(0, 0), // 图像相对展示区域的偏移量,适于雪碧图等
    })
    const marker = new AMap.Marker({
      zooms: [16, 20], // 缩放
      position: markerArr.value[i], // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
      map: map.value,
      icon,
      offset: new AMap.Pixel(0, -20),
    })
    // 支路点详细信息// 信息窗体
    infoWindow.value = new AMap.InfoWindow({
      isCustom: true, // 自定义信息窗体
      content: windowInfoRef.value.$el, // 窗体内容(vue组件)
      offset: new AMap.Pixel(9, -5), // 偏移
    })
    marker.on('click', (e) => {
      // 打开信息窗口
      infoWindow.value.open(map.value, e.lnglat)
      // 初始化信息窗口
      windowInfoRef.value.initialize({
        overlay: e.target,
        infoWindow: infoWindow.value,
        info: markerArrInfo.value[i],
      })
    })
    // 标记点文本标记
    marker.setLabel({
      offset: new AMap.Pixel(-10, -2), // 设置文本标注偏移量
      content: `<div>${markerArrInfo.value[i].nodeName}</div>`, // 设置文本标注内容
      direction: 'right', // 设置文本标注方位
    })
    map.value.add([marker])
  }
  // // 光伏标记点及光伏绘制
  for (let i = 0; i < markerArr1.value.length; i++) {
    const icon = new AMap.Icon({
      size: new AMap.Size(36, 36), // 图标尺寸
      image: `${publicPath}img/icon2.png`, // Icon的图像
      imageSize: new AMap.Size(24, 30), // 根据所设置的大小拉伸或压缩图片
      imageOffset: new AMap.Pixel(0, 0), // 图像相对展示区域的偏移量,适于雪碧图等
    })
    const marker = new AMap.Marker({
      zooms: [16, 20],
      position: markerArr1.value[i], // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
      map: map.value,
      icon,
      offset: new AMap.Pixel(-20, -20),
    })
    // 信息窗体
    infoWindow2.value = new AMap.InfoWindow({
      isCustom: true, // 自定义信息窗体
      content: windowInfoRef2.value.$el, // 窗体内容(vue组件)
      offset: new AMap.Pixel(9, -5), // 偏移
    })
    marker.on('click', (e) => {
      // 打开信息窗口
      infoWindow2.value.open(map.value, e.lnglat)
      // 初始化信息窗口
      windowInfoRef2.value.initialize({
        overlay: e.target,
        infoWindow: infoWindow2.value,
        info: markerArrInfo1.value[i],
      })
    })
    // 标记点的文本
    marker.setLabel({
      zooms: [16, 20],
      offset: new AMap.Pixel(-10, -2), // 设置文本标注偏移量
      content: `<div>${markerArrInfo1.value[i].stationName}</div>`, // 设置文本标注内容
      direction: 'right', // 设置文本标注方位
    })
    map.value.add([marker])
    // 绘制电网和节点连线
    const path = markerArrInfo1.value.map((item) => {
      return [[Number(item.lng), Number(item.lat)], [Number(item.nodeLng), Number(item.nodeLat)]]
    })
    const polyline = new AMap.Polyline({
      path,
      strokeColor: '#03A382',
      strokeStyle: 'dashed',
      strokeDasharray: [10, 3],
      lineJoin: 'round',
      lineCap: 'round',
      zIndex: 50,
      zooms: [16, 20],
    })
    polyline.setMap(map.value)
    map.value.add(polyline)
  }
  // 电网支路折线绘制
  for (let i = 0; i < lineArr.value.length; i++) {
    const path = lineArr.value[i].branchNodeInfos
    var polyline = new AMap.Polyline({
      path,
      isOutline: true,
      strokeColor: '#008d68',
      // strokeOpacity: 1,
      strokeWeight: 3,
      // 折线样式还支持 'dashed'
      // strokeStyle是dashed时有效
      strokeDasharray: [10, 3],
      lineJoin: 'round',
      // lineCap: 'square',
      lineCap: 'round',
      zIndex: 50,
      zooms: [16, 20],
    })
    polyline.setMap(map.value)
    map.value.add(polyline)
  }
  // for (let i = 0; i < lineArr.value.length; i++) {
  //   // console.log(lineArr.value[i])
  //   const path = lineArr.value.map(item => item.branchNodeInfos)
  //   const line = path.map(item => (
  //     item.map((child) => {
  //       return ([[child.flng, child.flat], [child.tlng, child.tlat], child.status2])
  //     })
  //   ))
  //   line.forEach((item) => {
  //     item.forEach((child) => {
  //       const path = [child[0], child[1]]
  //       const polyline = new AMap.Polyline({
  //         path,
  //         // isOutline: true,
  //         strokeColor: child[2] === 1 ? '#008d68' : '#000',
  //         // strokeOpacity: 1,
  //         strokeWeight: 3,
  //         // 折线样式还支持 'dashed'
  //         strokeStyle: child[2] !== 1 ? 'dashed' : 'dashed ',
  //         // strokeStyle是dashed时有效
  //         strokeDasharray: [10, 3],
  //         lineJoin: 'round',
  //         showDir: child[2] === 1,
  //         // lineCap: 'square',
  //         lineCap: 'round',
  //         zIndex: 50,
  //         zooms: [16, 20],

  //       })
  //       // 离线支路连接添加开关图标
  //       if (child[2] === 0) {
  //         const data = [(Number(child[0][0]) + Number(child[1][0])) / 2, (Number(child[0][1]) + Number(child[1][1])) / 2]
  //         const icon = new AMap.Icon({
  //           size: new AMap.Size(36, 36), // 图标尺寸
  //           image: `${publicPath}img/icon3.png`, // Icon的图像
  //           imageSize: new AMap.Size(24, 30), // 根据所设置的大小拉伸或压缩图片
  //           imageOffset: new AMap.Pixel(0, 0), // 图像相对展示区域的偏移量,适于雪碧图等
  //         })
  //         const marker = new AMap.Marker({
  //           zooms: [16, 20],
  //           position: data, // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
  //           map: map.value,
  //           icon,
  //           offset: new AMap.Pixel(-20, -20),
  //         })
  //         map.value.add([marker])
  //       }
  //       polyline.setMap(map.value)
  //       map.value.add(polyline)
  //     })
  //   })
  // 添加支路折线文本
  // 创建纯文本标记
  // const textArr = path.map(item => (
  //   item.map((child) => {
  //     return ([[(Number(child.flng) + Number(child.tlng)) / 2, (Number(child.flat) + Number(child.tlat)) / 2], child.flowRate])
  //   })
  // ))
  // textArr.forEach((item) => {
  //   // console.log(item, 'item')
  //   item.forEach((child) => {
  //     const icon = new AMap.Icon({
  //       size: new AMap.Size(36, 36), // 图标尺寸
  //       // image: '', // Icon的图像
  //       imageSize: new AMap.Size(24, 30), // 根据所设置的大小拉伸或压缩图片
  //       imageOffset: new AMap.Pixel(0, 0), // 图像相对展示区域的偏移量,适于雪碧图等
  //     })
  //     // const content = '<div>111</div>'
  //     const marker = new AMap.Marker({
  //       position: child[0], // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
  //       map: map.value,
  //       content: '<span></span>',
  //       offset: new AMap.Pixel(-20, -20),
  //     })
  //     marker.setLabel({
  //       offset: new AMap.Pixel(-10, -2), // 设置文本标注偏移量
  //       content: `<div>${`${child[1]}kgCO2/h`}</div>`, // 设置文本标注内容
  //       direction: 'right', // 设置文本标注方位
  //     })
  //     map.value.add([marker])
  //   })
  // })
  // }
}
// 绘制用热监测相关
const useHot = () => {
  for (let i = 0; i < markerArrHot.value.length; i++) {
    const AMap = AMap1.value
    const icon = new AMap.Icon({
      size: new AMap.Size(36, 36), // 图标尺寸
      image: `${publicPath}img/icon4.png`, // Icon的图像
      imageSize: new AMap.Size(24, 30), // 根据所设置的大小拉伸或压缩图片
      imageOffset: new AMap.Pixel(0, 0), // 图像相对展示区域的偏移量,适于雪碧图等
    })
    const marker = new AMap.Marker({
      zooms: [16, 20], // 缩放
      position: markerArrHot.value[i], // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
      map: map.value,
      icon,
      offset: new AMap.Pixel(3, -30),
    })
    // 支路点详细信息// 信息窗体
    infoWindowHot.value = new AMap.InfoWindow({
      isCustom: true, // 自定义信息窗体
      content: windowInfoHotRef.value.$el, // 窗体内容(vue组件)
      offset: new AMap.Pixel(9, -5), // 偏移
    })
    marker.on('click', (e) => {
      // 打开信息窗口
      infoWindowHot.value.open(map.value, e.lnglat)
      // 初始化信息窗口
      windowInfoHotRef.value.initialize({
        overlay: e.target,
        infoWindow: infoWindowHot.value,
        info: markerArrHotInfo.value[i],
      })
    })
    // 标记点文本标记
    marker.setLabel({
      offset: new AMap.Pixel(-10, -2), // 设置文本标注偏移量
      content: `<div>${markerArrHotInfo.value[i].deviceName}</div>`, // 设置文本标注内容
      direction: 'right', // 设置文本标注方位
    })
    map.value.add([marker])
  }
}
onMounted(async () => {
  // 获取电网列表
  try {
    const list = await getElectricityListAll()
    // 电网列表
    console.log(list.data, '电网列表')
    electricityList.value = list.data
    // 查询节点列表(标记点)
    if (electricityList.value.length) {
      const res = await electricityNode(electricityList.value[0].id)
      // markerArr.value = res.data.map(item => ([Number(item.lng), Number(item.lat)]))
      // markerArrInfo.value = res.data
      markerArr.value = electNodeList.map(item => ([Number(item.lng), Number(item.lat)]))
      markerArrInfo.value = electNodeList
      console.log(res.data, '电网标记点')
      // 获取支路信息(折线)
      // const res1 = await electricityBranch(electricityList.value[0].id)
      lineArr.value = branchList
      // console.log(res1.data, '折线记点')
    }
    // 获取光伏列表
    const list1 = guangfuList
    // console.log(list1, '广福街店')
    markerArr1.value = list1.map(item => ([Number(item.lng), Number(item.lat)]))
    markerArrInfo1.value = list1
    // 初始化地图
    await initMap()
    useElectricity()
  }
  catch (error) {
    initMap()
  }
  // 获取用热数据
  getDeviceListPage({
    offset: 1,
    limit: 999,
    ptn: '',
    deviceType: '2',
  }).then((res) => {
    markerArrHotInfo.value = HotNodeList
    markerArrHot.value = HotNodeList.map(item => ([Number(item.lng), Number(item.lat)]))
    // markerArrHotInfo.value = res.data.rows
    // markerArrHot.value = res.data.rows.map(item => ([Number(item.lng), Number(item.lat)]))
  })
  // getElectricityListAll().then((res) => {
  //   // 电网列表
  //   electricityList.value = res.data
  //   // 默认选中第一个查询节点
  //   if (electricityList.value.length) {
  //     electricityNode(electricityList.value[0].id).then((res) => {
  //       markerArr.value = res.data.map(item => ([Number(item.lng), Number(item.lat)]))
  //       markerArrInfo.value = res.data
  //       // 获取支路
  //       electricityBranch(electricityList.value[0].id).then(res => {
  //         lineArr.value = res.data
  //         // console.log(res.data)
  //         initMap()
  //       })
  //     })
  //   }
  // })
})
const area = ref('')
const areaList = ref([])
// 获取分区列表
const fetchAreaList = () => {
  getDictByCode('ptn_type').then((res) => {
    areaList.value = res.data
  })
}
fetchAreaList()
const areaMarkerList = ref()
const polygons = ref()
// 绘制区域
const drawArea = (markerList: any, color: string) => {
  const polygon = new AMap1.value.Polygon({
    path: markerList,
    fillColor: color,
    strokeOpacity: 1,
    fillOpacity: 0.5,
    strokeColor: '#2b8cba',
    strokeWeight: 1,
    strokeStyle: 'dashed',
    strokeDasharray: [5, 5],
  })
  polygons.value = polygon
  map.value.add(polygon)
}
// 删除绘制
const clearDraw = () => {
  if (polygons.value) {
    map.value.remove(polygons.value)
    area.value = ''
  }
}
// 监听分区变化
watch(() => area.value, (newVal) => {
  if (polygons.value) {
    map.value.remove(polygons.value)
  }
  if (!newVal) {
    return
  }
  getAreaPosition(newVal).then((res) => {
    const color = {
      1: '#2b8cbe',
      2: '#ccebc5',
      3: '#7bccc4',
    }
    areaMarkerList.value = res.data
    if (res.data.length) {
      areaMarkerList.value.push(res.data[0])
      const data = areaMarkerList.value.map(item => ([Number(item.lng), Number(item.lat)]))
      drawArea(data, color[newVal])
    }
  })
})
// 用电检测/用热监测 默认用电
const flagType = ref(true)
// 切换用电检测/用热监测
const changeFlagType = () => {
  map.value.clearMap()
  map.value.setCenter([111.73142, 40.830627])
  // 区域框展示
  area.value = ''
  if (flagType.value) {
    useHot()
  }
  else {
    useElectricity()
  }
  flagType.value = !flagType.value
}
defineExpose({ changeLayerGrop, changeFlagType, flag })
</script>

<template>
  <div id="map" />
  <info-detail ref="windowInfoRef" />
  <info-detail2 ref="windowInfoRef2" />
  <info-detail-hot ref="windowInfoHotRef" />
  <!-- <div class="btns">
    <el-radio-group v-model="area">
      <el-radio-button v-for="item in areaList" :key="item.id" :label="item.value" @dblclick="clearDraw">
        {{ item.name }}
      </el-radio-button>
    </el-radio-group>
  </div> -->
</template>

<style scoped>
#map {
  overflow: hidden;
  width: 100%;
  height: 100%;
  margin: 0;
  font-family: "微软雅黑";
}

.btns {
  position: absolute;
  left: 10px;
  bottom: 10px;
}
</style>

<style>
/* 隐藏高德logo  */
.amap-logo {
  display: none !important;
}

/* 隐藏高德版权  */
.amap-copyright {
  display: none !important;
}

.amap-marker-label {
  border: 0;
  background-color: transparent;
}
</style>