Newer
Older
cockpit_hxrq_front / src / views / maps / mapOverview.vue
StephanieGitHub on 22 Apr 2021 20 KB MOD:对接实际数据
<!--
 * @Description: 综合业务
 * @Author: 王晓颖
 * @Date: 2021-04-08
 -->
<template>
  <layout-map>
    <!--地图-->
    <Map :url="configUrl" @onload="onMapload" />
    <!--下方图层选择按钮-->
    <div class="map-btn-group">
      <select-button :select="areaNeedSupplyShow" name="区域供需情况" icon="icon-supply" @click="showAreaSupplyNeed(areaNeedSupplyShow)"/>
      <select-button :select="factoryStorageShow" name="液化工厂储量" icon="icon-liquidFactory" @click="showFactoryStorage(factoryStorageShow)"/>
      <select-button :select="stationStorageShow" name="加气站储量" icon="icon-gasStation" @click="showStationStorage(stationStorageShow)"/>
      <select-button :select="factoryShow" name="液化工厂加气站分布" icon="icon-position" @click="showPosition(factoryShow)"/>
    </div>
    <!--PNG,LNG选择按钮-->
    <div v-show="areaNeedSupplyShow" class="select-btns-gas">
      <button1 :selected="type=='all'" @click.native="changeType('all')">全部</button1>
      <button1 :selected="type=='png'" @click.native="changeType('png')">PNG</button1>
      <button1 :selected="type=='lng'" @click.native="changeType('lng')">LNG</button1>
    </div>
    <!--遮罩-->
  </layout-map>
</template>

<script>
import Map from '@/components/Map/MarsMap.vue'
import 'mars3d-echarts'
import axios from 'axios'
import SelectButton from '@/components/SelectTool/components/selectButton'
import LayoutMap from '@/layout/layoutMap'
import { getAreaSupply } from '@/api/needSupply'
import { getIndex } from '@/utils/mathUtils'
import Button1 from '@/components/Button/button1'

export default {
  name: 'StorageTopic',
  components: {
    Button1,
    LayoutMap,
    Map,
    SelectButton
  },
  filters: {
    liquidNameFilter(val) {
      return val + '液化工厂'
    },
    gasNameFilter(val) {
      return val + '加气站'
    }
  },
  data() {
    return {
      map: null, // 地图
      configUrl: 'static/config/config.json',
      underground: null, // ?
      index: null, // 供需放大倍数
      storageIndex: null, // 储量放大倍数
      type: 'all', // 全部,LNG,PNG
      colorList: ['#d75111', '#d75111', '#d75111', '#fcaf17', '#fcaf17', '#fcaf17', '#4fffc3', '#4fffc3', '#4fffc3', '#39c53d', '#39c53d'], // 柱子颜色
      areaNeedSupplyShow: true, // 区域供需显示
      factoryShow: false, // 显示液化工厂
      // gasStationShow: false, // 显示加气站
      factoryStorageShow: false, // 液化工厂储量
      stationStorageShow: false, // 加气站储量
      liquidFactoryData: {
        name: '全部',
        value: 196
      },
      gasStationData: {
        name: '全部',
        value: 196
      }, // 统计版展示数据
      cities: [], // 各城市供需数据
      citiesPositions: {
        '太原市': { 'x': 112.549248, 'y': 37.857014 },
        '大同市': { 'x': 113.295258, 'y': 40.090309 },
        '阳泉市': { 'x': 113.583282, 'y': 37.861187 },
        '晋中市': { 'x': 113.290072, 'y': 37.388188 },
        '长治市': { 'x': 113.113556, 'y': 36.191113 },
        '晋城市': { 'x': 112.851273, 'y': 35.497555 },
        '临汾市': { 'x': 111.517975, 'y': 36.084148 },
        '运城市': { 'x': 111.00396, 'y': 35.022778 },
        '朔州市': { 'x': 112.433388, 'y': 39.331261 },
        '忻州市': { 'x': 112.733536, 'y': 38.41769 },
        '吕梁市': { 'x': 111.134338, 'y': 37.524364 }
      },
      filteredData: [], // 过滤后的供需数据,过滤png,lng
      liquidFactory: [], // 液化工厂数据
      gasStation: [], // 加气站
      areaNeedSupplyLayer: null, // 区域供需数据
      factoryStorageLayer: null, // 液化工厂分布图层
      stationStorageLayer: null, // 加气站存储层
      factoryModelLayer: null, // 液化工厂模型层
      stationModelLayer: null, // 加气站模型层
      factoryLineLayer: null, // 飞线层
      graphicLayer: null, // 管理站模型图层
      timer: null, // 定时器, 刷新数据的
      tooltipTimer: null, // 定时器,弹出tooltip的
      clock: 120 // 间隔时间
    }
  },
  watch: {
    // type变更则更新供需图层
    type(val) {
      if (this.areaNeedSupplyLayer) {
        this.map.removeLayer(this.areaNeedSupplyLayer, true)
      }
      this.addNeedSupply()
    }
  },
  created() {
    // 获取液化工厂数据
    this.fetchFactoryData()
  },
  destroyed() {
    clearInterval(this.timer)
  },
  methods: {
    // 地图构造完成回调
    onMapload(map) {
      // 以下为演示代码
      this.map = map
      // 背景透明
      // this.map._viewer.scene.backgroundColor = new this.Cesium.Color(0.0, 0.0, 0.0, 0.0)
      // this.map._viewer.scene.globe.baseColor.alpha = 0
      this.addNeedSupply()
      this.refreshData()
    },
    // 获取供应需求数据
    addNeedSupply() {
      const { mars3d, colorList } = this
      const graphicLayer = new mars3d.layer.GraphicLayer()
      if (this.areaNeedSupplyLayer) {
        this.map.removeLayer(this.areaNeedSupplyLayer)
      }
      this.areaNeedSupplyLayer = graphicLayer
      this.map.addLayer(graphicLayer)
      // 获取数据
      getAreaSupply().then(res => {
        if (res.status === 200) {
          const data = res.data.map(item => {
            return {
              name: item['WD09_05'],
              pngSupply: item['DL03'] / 10000.0,
              pngNeed: item['DL03'] / 10000.0,
              lngSupply: item['DL02'] / 10000.0,
              lngNeed: item['DL02'] / 10000.0,
              supply: (item['DL03'] + item['DL02']) / 10000.0,
              need: (item['DL03'] + item['DL02']) / 10000.0
            }
          })
          this.cities = data
          this.filteredData = this.filterData()
          if (this.index == null) {
            this.index = getIndex(this.filteredData.map(item => item.supply))
          }
          for (const item of this.filteredData) {
            const need = item.need
            const supply = item.supply
            const position = [this.citiesPositions[item.name].x, this.citiesPositions[item.name].y]
            const html = `${item['name']}<br/>
                        <span style="color:#FFB861">实时供给:${supply.toFixed(2)}万m³</span>`
            const color = colorList[Math.floor((supply / need) * 10)]
            this.addWall(graphicLayer, position, supply * this.index, need * this.index, color, html, 4000)
          }
          // 开启定时循环弹窗
          const graphics = this.areaNeedSupplyLayer.graphics.filter(item => item.name === 'supply')
          this.timerTooltip(this.areaNeedSupplyLayer, graphics, graphics.length, 0)
        }
      })
    },
    // 定时弹窗
    timerTooltip(layer, graphics, length, i) {
      this.tooltipTimer = setTimeout(() => {
        if (i === length) {
          this.timerTooltip(layer, graphics, length, 0)
        } else {
          graphics[i].openTooltip()
          this.timerTooltip(layer, graphics, length, i + 1)
        }
      }, 10000)
    },
    // 过滤数据
    filterData() {
      const { type } = this
      if (type === 'all') {
        return this.cities
      } else if (type === 'lng') {
        return this.cities.map(item => {
          return { name: item.name, need: item.lngNeed, supply: item.lngSupply }
        })
      } else if (type === 'png') {
        return this.cities.map(item => {
          return { name: item.name, need: item.pngNeed, supply: item.pngSupply }
        })
      }
    },
    // 获取液化工厂和加气站数据
    fetchFactoryData() {
      axios.get('static/config/liquidFactory.json').then((res) => {
        res = res.data
        if (res.code === 200) {
          // 获取液化工厂数据
          this.liquidFactory = res.data[0].data
          this.liquidFactoryData.value = res.data[0].total
          // 加气站数据
          this.gasStation = res.data[1].data
          this.gasStationData.value = res.data[1].total

          if (this.storageIndex == null) {
            this.storageIndex = getIndex(this.liquidFactory.map(item => item.liquid_level))
            console.log('storageIndex', this.storageIndex)
          }
        }
      })
    },
    // 液化工厂储量效果图
    addFactoryStorage() {
      if (this.liquidFactory.length > 0) {
        // 添加点位
        this.addFeatures(this.liquidFactory, 'liquidFactory')
      } else {
        this.fetchFactoryData()
      }
    },
    // 显示加气站储量
    addStationStorage() {
      if (this.gasStation.length > 0) {
        this.addFeatures(this.gasStation, 'gasStation')
      } else {
        this.fetchFactoryData()
      }
    },
    // 液化工厂三维模型
    addFactoryModel() {
      const { mars3d } = this
      const factoryModelLayer = new mars3d.layer.ModelLayer({
        name: '液化工厂',
        url: './static/gltf/output/yehuagongchang.gltf',
        style: {
          scale: 3,
          heading: 0,
          minimumPixelSize: 30,
          clampToGround: true
        },
        positions: this.liquidFactory.map(item => {
          return { lng: parseFloat(item.value[0]), lat: parseFloat(item.value[1]), alt: 0 }
        })
      })
      this.factoryModelLayer = factoryModelLayer
      this.map.addLayer(factoryModelLayer)
    },
    // 加气站三维模型
    addStationModel() {
      const { mars3d } = this
      const stationModelLayer = new mars3d.layer.ModelLayer({
        name: '加气站',
        url: './static/gltf/output/jiaqizhan.gltf',
        style: {
          scale: 3,
          heading: 0,
          minimumPixelSize: 30,
          clampToGround: true
        },
        positions: this.gasStation.map(item => {
          return { lng: parseFloat(item.value[0]), lat: parseFloat(item.value[1]), alt: 0 }
        })
      })
      this.stationModelLayer = stationModelLayer
      this.map.addLayer(stationModelLayer)
    },
    // 液化工厂和加气站位置飞线
    addFactoryPosition() {
      if (this.liquidFactory.length <= 0) {
        return
      }
      this.addFactoryModel() // 添加液化工厂三维模型
      // this.addStationModel() // 添加加气站三维模型
      const lineColor = ['#f6fb05', '#f6fb05', '#00fcff']
      // 城市点位图标
      const symbol1 = 'image://static/images/map/symbol2.png'
      const symbol2 = 'image://static/images/map/symbol1.png'
      // 线上的动态运动点图标
      var pointSymbol = 'image://static/images/map/linePoint1.png'
      // 工厂加symbol
      const factorys = this.liquidFactory.map(item => {
        return { ...item, symbol: symbol1 }
      })
      // 加气站加symbol
      const stations = this.gasStation.map(item => {
        return { ...item, symbol: symbol2 }
      })
      // 遍历获取关联关系
      const lineArr = []
      for (const station of stations) {
        if (station.belong && station.value[0] !== '0') {
          for (const factory of factorys) {
            if (station.belong === factory.name && factory.value[0] !== '0') {
              lineArr.push([
                { coord: [parseFloat(factory.value[0]), parseFloat(factory.value[1])] },
                { coord: [parseFloat(station.value[0]), parseFloat(station.value[1])] }
              ])
              break
            }
          }
        }
      }
      const curveness = 0.5
      var seriesZero = [
        {
          type: 'effectScatter',
          layout: 'none',
          coordinateSystem: 'GLMap',
          symbolSize: [20, 20],
          symbolOffset: [0, -10],
          zlevel: 3,
          circular: {
            rotateLabel: true
          },
          itemStyle: {
            normal: {
              shadowColor: 'none'
            }
          },
          data: factorys
        }
      ]
      var seriesThree = [
        {
          name: '',
          type: 'lines',
          coordinateSystem: 'GLMap',
          zlevel: 1,
          blendMode: 'lighter',
          effect: {
            show: true,
            smooth: false,
            trailLength: 0,
            symbol: pointSymbol,
            symbolSize: [10, 30],
            period: 4
          },
          lineStyle: {
            width: 2,
            color: lineColor[0],
            curveness: curveness
          },
          data: lineArr
        }
      ]
      var seriesData = [...seriesZero, ...seriesThree]
      const option = {
        animation: false,
        GLMap: {},
        series: seriesData
      }
      var echartsLayer = new this.mars3d.layer.EchartsLayer(option)
      this.factoryLineLayer = echartsLayer
      this.map.addLayer(echartsLayer)
    },
    // 添加点位储量柱状图
    addFeatures(arr, type) {
      const { mars3d, colorList } = this
      if (type === 'liquidFactory') {
        const factoryStorageLayer = new mars3d.layer.GraphicLayer()
        this.factoryStorageLayer = factoryStorageLayer
        this.map.addLayer(factoryStorageLayer)
        for (const item of arr) {
          const realData = item.liquid_level
          const totalData = item.contain
          const position = [parseFloat(item.value[0]), parseFloat(item.value[1])]
          const html = `${item['name']}<br/>
                        <span style="color:#63AEFF">库容:${realData} 吨</span><br/>
                        <span style="color:#FFB861">储量:${totalData} 吨</span><br/>
                        <span style="color:#FFB861">液位值:${realData} 米</span>`
          const color = colorList[Math.floor(realData / totalData * 10)]
          this.addColumn(factoryStorageLayer, position, realData * this.storageIndex, totalData * this.storageIndex, color, html, 6000)
        }
      } else if (type === 'gasStation') {
        const stationStorageLayer = new mars3d.layer.GraphicLayer()
        this.stationStorageLayer = stationStorageLayer
        this.map.addLayer(stationStorageLayer)
        for (const item of arr) {
          const realData = item.liquid_level
          const totalData = item.contain
          const position = [parseFloat(item.value[0]), parseFloat(item.value[1])]
          const color = colorList[Math.floor(realData / totalData * 10)]
          const html = `${item['name']}<br/>
                        <span style="color:#63AEFF">库容:${realData} 吨</span><br/>
                        <span style="color:#FFB861">储量:${totalData} 吨</span><br/>
                        <span style="color:#FFB861">液位值:${realData} 米</span>`
          this.addColumn(stationStorageLayer, position, realData * this.storageIndex, totalData * this.storageIndex, color, html, 2000, false)
        }
      }
    },
    // 添加墙
    addWall(graphicLayer, position, supply, need, color, html, radius) {
      const { mars3d, Cesium } = this
      // 下方实际数据
      var positions1 = mars3d.PolyUtil.getEllipseOuterPositions({
        position: Cesium.Cartesian3.fromDegrees(position[0], position[1], 0),
        radius: radius, // 半径
        count: 50 // 共返回(count*4)个点
      })
      var positions2 = mars3d.PolyUtil.getEllipseOuterPositions({
        position: Cesium.Cartesian3.fromDegrees(position[0] - 0.1, position[1], 0),
        radius: radius, // 半径
        count: 50 // 共返回(count*4)个点
      })
      // 供应
      var graphic1 = new mars3d.graphic.WallPrimitive({
        name: 'supply',
        positions: positions1,
        style: {
          diffHeight: supply,
          closure: true,
          material: mars3d.MaterialUtil.createMaterial(mars3d.MaterialType.LineFlow, {
            image: 'static/images/map/fence.png',
            color: '#fffb33',
            speed: 10,
            axisY: true
          })
        }
      })
      // // 需求
      // var graphic2 = new mars3d.graphic.WallPrimitive({
      //   name: 'need',
      //   positions: positions2,
      //   style: {
      //     diffHeight: need,
      //     closure: true,
      //     material: mars3d.MaterialUtil.createMaterial(mars3d.MaterialType.LineFlow, {
      //       image: 'static/images/map/fence.png',
      //       color: '#46e7ff',
      //       speed: 10,
      //       axisY: true
      //     })
      //   }
      // })
      graphic1.bindTooltip(html)
      // graphic2.bindTooltip(html)
      graphicLayer.addGraphic(graphic1)
      // graphicLayer.addGraphic(graphic2)
    },
    // 添加柱子
    addColumn(graphicLayer, position, realData, totalData, color = '#63AEFF', html, radius, showColumn2 = true) {
      const { mars3d, Cesium } = this
      // 下方实际数据
      const p = Cesium.Cartesian3.fromDegrees(position[0], position[1], Math.floor(realData / 2))
      const height = realData
      var graphic1 = new mars3d.graphic.CylinderEntity({
        position: p,
        style: {
          length: height,
          topRadius: radius,
          bottomRadius: radius,
          opacity: 1,
          color: color
        }
      })
      graphic1.bindTooltip(html)
      graphicLayer.addGraphic(graphic1)
      // 上方空缺白色,表示未空余容量
      if (showColumn2) {
        const p2 = Cesium.Cartesian3.fromDegrees(position[0], position[1], Math.floor(realData + (totalData - realData) / 2))
        const height2 = totalData - realData
        var graphic2 = new this.mars3d.graphic.CylinderEntity({
          position: p2,
          style: {
            length: height2,
            topRadius: radius,
            bottomRadius: radius,
            opacity: 0.3,
            color: '#edf4ff'
          }
        })
        graphicLayer.addGraphic(graphic2)
        graphic2.bindTooltip(html)
      }
    },
    // 添加文字
    addText(graphicLayer, data, position, height) {
      const { mars3d, Cesium } = this
      var primitive = new mars3d.graphic.LabelPrimitive({
        position: Cesium.Cartesian3.fromDegrees(position[0], position[1], height),
        style: {
          text: data,
          font_size: 18,
          font_family: '楷体',
          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
          fillColor: Cesium.Color.fromCssColorString('#00ff00'),
          outlineColor: Cesium.Color.BLACK,
          outlineWidth: 1,
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          pixelOffset: new Cesium.Cartesian2(0, -20)
        }
      })
      graphicLayer.addGraphic(primitive)
    },
    // 选框发生变化
    selectChange({ area, dept }) {
      area = area === '全部' ? '' : area
      this.boardData.name = area
    },
    // 显示区域供需情况
    showAreaSupplyNeed(show) {
      // 现在正在显示
      if (show) { // 移除
        this.areaNeedSupplyShow = false
        this.map.removeLayer(this.areaNeedSupplyLayer, true)
        this.areaNeedSupplyLayer = null
        clearTimeout(this.tooltipTimer)
        this.tooltipTimer = null
      } else {
        this.areaNeedSupplyShow = true
        this.type = 'all'
        this.addNeedSupply()
      }
    },
    // 显示工厂
    showFactoryStorage(show) {
      // 现在正在显示
      if (show) { // 移除
        this.factoryStorageShow = false
        this.map.removeLayer(this.factoryStorageLayer, true)
      } else {
        this.factoryStorageShow = true
        this.addFactoryStorage()
      }
    },
    // 显示加气站
    showStationStorage(show) {
      // 现在正在显示
      if (show) { // 移除
        this.stationStorageShow = false
        this.map.removeLayer(this.stationStorageLayer, true)
      } else {
        this.stationStorageShow = true
        this.addStationStorage()
      }
    },
    // 显示液化工厂位置
    showPosition(show) {
      if (show) { // 移除
        this.factoryShow = false
        this.map.removeLayer(this.factoryModelLayer, true)
        // this.map.removeLayer(this.stationModelLayer, true)
        this.map.removeLayer(this.factoryLineLayer, true)
      } else {
        this.factoryShow = true
        this.addFactoryPosition()
      }
    },
    // 点击全部/png/lng更改类型
    changeType(type) {
      console.log('clickChange')
      this.type = type
    },
    // 打开轮询,定时刷新数据
    refreshData() {
      this.timer = setInterval(() => {
        console.log('refreshData')
        this.fetchFactoryData()// 刷新液化工厂和加气站数据
        if (this.areaNeedSupplyLayer) { // 如果供需图层不为空,刷新工薪数据
          this.addNeedSupply()
        }
      }, this.clock * 1000)
    }
  }
}
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
  .label-container{
    position: absolute;
    top: 140px;
    left:31rem;
    z-index:100;
    .label-div{
      color: white;
      padding:1.5rem 2.5rem 1rem 2.5rem;
      background-image: url("../../assets/button_images/board-box1.png");
      background-size: 100% 100%;
      margin-bottom: 20px;
      .label{
        margin-bottom: 1rem;
        font-size:1rem;
      }
      .value{
        font-family: DS-DigitalBold;
        font-size:2rem;
      }
    }
  }
  .map-btn-group{
    position: absolute;
    bottom:3rem;
    left:50%;
    transform: translateX(-50%);
    display: flex;
    justify-content: center;
  }
  .select-btns-gas{
    position:absolute;
    top:150px;
    left:50%;
    transform: translateX(-50%);
    display: flex;
    justify-content: center;
  }
</style>