whyczyk
2022-03-02 733823ffa701f749c7154cacf60a26951891f2ca
src/components/charts/chinaMap.vue
@@ -1,351 +1,643 @@
<template>
  <div class="echarts-wrapper">
    <div class="echarts-content" ref="chinaMap" id="chinaMap">
   <new-china-map v-if="newPlatform==1"></new-china-map>
   <div class="echarts-wrapper" @dblclick="dblclick" v-else>
      <div class="echarts-content" ref="chart" id="cityChart">
    </div>
  </div>
      </div>
      <div class="infoPanel" v-show="isShowInfoPanel" :style="{ left: mapInfoX + 'px', top: mapInfoY + 'px' }">
         <h4 class="infoPanel-Title">
            {{ mapInfoTitle }}
            <div class="closeBtn" @click.self="isShowInfoPanel=false"></div>
         </h4>
         <div class="infoPanel-center">
            <info-panel :infos="panelInfo"></info-panel>
         </div>
      </div>
   </div>
</template>
<script>
import * as echarts from 'echarts';
import {
   searchMap,
   searchMapHomeState,
   getAllMapOutlineAction,
   searchByDevId,
   searchHomeNum,
} from "../../assets/js/api";
import HomeNormal from '@/assets/images/home.png'
let mapHomeImage = new Image();
mapHomeImage.src = HomeNormal;
// 正常的图标
import HomeNormalImage from '@/assets/images/home-normal.png';
let homeNormalImage = new Image();
homeNormalImage.src = HomeNormalImage;
// 充电的图标
import HomeChargeImage from '@/assets/images/home-charge.png';
let homeChargeImage = new Image();
homeChargeImage.src = HomeChargeImage;
// 告警图标
import HomeWarnImage from '@/assets/images/home-warn.png';
let homeWarnImage = new Image();
homeWarnImage.src = HomeWarnImage;
// 放电图标
import HomeDischargeImage from '@/assets/images/home-discharge.png';
import InfoPanel from '../indexPanel/InfoPanel.vue';
import newChinaMap from './newChinaMap.vue';
let homeDischargeImage = new Image();
homeDischargeImage.src = HomeDischargeImage;
let chartData = []; //chart数据
let abnormalArr = []; //异常数组
let tempData = []; //站点数组
let chart, chartLng, chartLat;
export default {
  name: "chinaMap",
  chart: "",
  props: {
    id: {
      require: true,
      type: String,
      default: "",
    },
    name: {
      type: String,
      default: ""
    },
    top: {
      type: Number,
      default: 15,
    },
    bottom: {
      type: Number,
      default: 60
    },
    space: {
      type: Number,
      default: 4
    },
  },
  data() {
    return {
   components: { InfoPanel, newChinaMap },
   name: "chinaMap",
   chart: "",
   chartData: "",
   data() {
      return {
         newPlatform: 0,
         parentsStyle: {},
         isAllScreen: false,
         timers: null,
         mapName: 'zhongguo',
         mapInfoX: null,
         mapInfoY: null,
         mapInfoTitle: "",
         isShowInfoPanel: false,
         panelInfo: {
            num: 369,
            StationId: "42070471",
            StationName: "贵州省-贵阳市-观山湖区-观山湖区护理学院-设备1",
            StationName3: "观山湖区护理学院",
            Address: "湖北省武汉市武昌区",
            longitude: 114.37285909,
            latitude: 30.56442241,
            information: "",
            FBSDeviceId: 910000111,
            nums: {
               code: 0,
               sum: 0,
               newsum: 0
            }
         },
      }
   },
   methods: {
      findParents(node, select) {
         var parent = node.parentNode;
         if (parent === null || parent.className.indexOf(select) != -1) {
            return parent;
         } else {
            return this.findParents(parent, select);
         }
      },
      dblclick(e) {
         this.isAllScreen = !this.isAllScreen
         let parents = this.findParents(e.currentTarget, 'vdr')
         if (this.isAllScreen) {
            this.parentsStyle = JSON.parse(JSON.stringify(parents.style));
            parents.style.transform = 'none';
            parents.style.width = '100%';
            parents.style.height = '100%';
            parents.style.position = 'fixed';
            parents.style.left = 0;
            parents.style.right = 0;
            parents.style.bottom = 0;
            parents.style.top = 0;
            parents.style.zIndex = 99999;
         } else {
            parents.style.transform = this.parentsStyle.transform;
            parents.style.width = this.parentsStyle.width;
            parents.style.height = this.parentsStyle.height;
            parents.style.position = this.parentsStyle.position;
            parents.style.left = 'initial';
            parents.style.right = 'initial';
            parents.style.bottom = 'initial';
            parents.style.top = 'initial';
            parents.style.zIndex = 'auto';
         }
         this.$options.chart.resize();
      },
      setOption(opt) {
         this.$options.chart.setOption(opt);
      },
      setData(sendData) {
         if (sendData) {
            this.$options.chartData = sendData;
            this.organizeData(sendData)
         } else {
            // 初始化页面
            this.$nextTick(() => {
               if (sessionStorage.getItem('newPlatform') != 1) {
                  this.getAllMapOutlineAction();
               }
            })
         }
      },
      organizeData(data) {
         let geoJson = require(`../../../public/mapJson/${this.mapName}.json`);
         echarts.registerMap('map', geoJson);
         // 整体配置项
         let option = {
            tooltip: {
               trigger: 'item',
               formatter: function (params) {
                  if (params.componentSubType == "map") {
                     return ''
                  } else if (params.componentSubType == "scatter") {
                     return params.name;
                  }
               }
            },
            visualMap: {
               show: false,
               min: 0,
               max: 500,
               left: 'left',
               top: 'bottom',
               text: ['高', '低'], // 文本,默认为数值文本
               calculable: true,
               seriesIndex: [1],
               inRange: {}
            },
            geo: {
               map: "map",
               layoutCenter: ["55%", "50%"],
               layoutSize: "100%",
               label: {
                  normal: {
                     show: true,
                     textStyle: {
                        color: '#fff'
                     }
                  },
                  emphasis: {
                     textStyle: {
                        color: '#fff'
                     }
                  }
               },
               roam: true, //是否允许缩放
               mapLocation: {
                  width: "110%",
                  height: "97%"
               },
               itemStyle: {
                  normal: {
                     borderColor: 'rgba(147, 235, 248, 1)',
                     borderWidth: 1,
                     areaColor: {
                        type: 'radial',
                        x: 0.5,
                        y: 0.5,
                        r: 0.8,
                        colorStops: [{
                           offset: 0,
                           color: 'rgba(147, 235, 248, 0)' // 0% 处的颜色
                        }, {
                           offset: 1,
                           color: 'rgba(147, 235, 248, .2)' // 100% 处的颜色
                        }],
                        globalCoord: false // 缺省为 false
                     },
                     shadowColor: 'rgba(128, 217, 248, 1)',
                     shadowOffsetX: -2,
                     shadowOffsetY: 2,
                     shadowBlur: 10
                  },
                  emphasis: {
                     areaColor: '#1ecee5',
                     borderWidth: 0,
                     label: {
                        show: false
                     }
                  }
               }
            },
            series: this.getSeries(data)
         };
         // 设置配置项
         this.setOption(option);
      },
      resize() {
         setTimeout(() => {
            this.$options.chart.resize();
            if (JSON.stringify(this.$options.chartData) != '{}') {
               this.setData(this.$options.chartData);
            }
         }, 300)
      },
      getSeries(opt) {
         // 未配置series
         if (!opt || !opt.series) {
            return [];
         }
         // 设置配置项
         let series = opt.series
         // 返回
         return series;
      },
      getAllMapOutlineAction() {
         //查询激活轮廓图
         getAllMapOutlineAction().then((res) => {
            let rs = JSON.parse(res.data.result);
            if (rs.code == 1) {
               let data = rs.data;
               data.map((item) => {
                  if (item.status == 1) {
                     this.mapName = item.name;
                  }
               });
            }
            this.$nextTick(() => {
               this.initPage();
            });
         })
            .catch((err) => {
               console.log(err);
            });
      },
      changeChartPanelStatus(homeData) {
         //panel面板状态改变
         this.isShowInfoPanel = true;
         let poit = this.convertMain(homeData.longitude, homeData.latitude);
         this.mapInfoX = poit[0] - 120;
         this.mapInfoY = poit[1] - 190;
         this.mapInfoTitle = homeData.StationName;
         this.$nextTick(() => {
            this.panelInfo = homeData
            // this.$refs.infoPanel.setInfo(homeData); //传值子组件
         });
      },
      convertMain(Lng, lat) {
         //根据经纬度计算定位
         // let getModel = chart.getModel().getSeries()[1];
         let seriesModel = chart.getModel().getSeriesByIndex(0);
         let coordSys = seriesModel.coordinateSystem;
         let point = coordSys.dataToPoint([Lng, lat]);
         return point;
      },
      startSearchMapHomeState() {
         this.timers = setInterval(() => {
            this.searchChartHomeState()
         }, 60 * 1000)
      },
      initPage() {
         // 初始化地图
         this.initCityChart();
         chart = echarts.init(document.getElementById('cityChart'));
    }
  },
  methods: {
    setOption(opt) {
            // 设置配置项
            this.$options.chart.setOption(opt);
    },
    setData(data) {
        console.log(data);
    let geoJson = require(`../../../public/mapJson/zhongguo.json`);
        echarts.registerMap('china', geoJson);
    let newarr = [
            {
                name: "武汉",//武汉
                value: [113.41, 31.22, 100],
                color:"#f44336",
                curveness:'-1',
                linesColor:"#fff",
                arrowColor:"#000"
            },
            {
                name: "佛山",//佛山
                value: [113.122717, 23.028762],
                color:"#4AFD88",
                curveness:'-0.2',
                linesColor:"#4AFD88",
                arrowColor:"#4AFD88"
            },
            {
                name: "福州",//福州
                value: [118.28, 26.08],
                color:"#fff100",
                curveness:'-0.2',
                linesColor:"#FFF100",
                arrowColor:"#FFF100"
            },
            {
                name: "长春",//长春
                value: [125.35, 43.88],
                color:"#ECA0BA",
                curveness:'-0.2',
                linesColor:"#00FEFF",
                arrowColor:"#F8A036",
                borderColor:"#F8A036"
            },
            {
                name: "天津",//天津
                value: [117.04, 39.33],
                color:"#4AFD88",
                curveness:'0.2',
                linesColor:"#4AFD88",
                arrowColor:"#4AFD88"
            },
            {
                name: "太原",//太原
                value: [112.30, 37.99],
                color:"#fff100",
                curveness:'0.2',
                linesColor:"#FFF100",
                arrowColor:"#FFF100"
            },
            {
            name: "银川",//银川
                value: [106.26667, 37.46667],
                color:"#4AFD88",
                curveness:'0.2',
                linesColor:"#4AFD88",
                arrowColor:"#1A6BF0"
            },
        ];
    let LableData = [];
    let series = [
            // 常规地图
            {
                type: 'map',
                mapType: 'china',
                aspectScale: 0.85,
                layoutCenter: ["50%", "65%"], //地图位置
                layoutSize: '130%',
                zoom: 1, //当前视角的缩放比例
                // roam: true, //是否开启平游或缩放
                scaleLimit: { //滚轮缩放的极限控制
                    min: 1,
                    max: 2
                },
                // 默认选中的数据
                data:[
                        {name:'广东',selected:true},
                        {name:'湖北',selected:true},
                        {name:'山西',selected:true},
                        {name:'吉林',selected:true},
                        {name:'福建',selected:true},
                        {name:'宁夏',selected:true},
                    ],
                itemStyle: {
                    normal: {
                        areaColor: '#00B2E0',
                        borderColor: '#021651',
                        borderWidth: 1
         chart.on("georoam", (params) => {
            clearInterval(this.timers)
            if (!this.isShowInfoPanel) {
               return;
            }
            this.isShowInfoPanel = false;
            this.timers = setTimeout(() => {
               this.isShowInfoPanel = true;
               let poit = this.convertMain(chartLng, chartLat);
               this.mapInfoX = poit[0] - 120;
               this.mapInfoY = poit[1] - 190;
               var option = chart.getOption(); //获得option对象
               if (params.zoom != null && params.zoom != undefined) {
                  //捕捉到缩放时
                  option.series[0].zoom = option.geo[0].zoom; //下层geo的缩放等级跟着上层的geo一起改变
                  option.series[0].center = option.geo[0].center; //下层的geo的中心位置随着上层geo一起改变
               } else {
                  //捕捉到拖曳时
                  option.series[0].center = option.geo[0].center; //下层的geo的中心位置着上层geo一起改变
               }
               chart.setOption(option); //设置option
                    },
                    emphasis: {
                        areaColor: '#1A6BF0',
                        label: {
                            color: "#fff"
                        }
               // this.startSearchMapHomeState();
            }, 300);
         });
         chart.off("click"); //防止chart点击触发多次
         chart.on("click", (params) => {
            //点击跳转实时数据
            if (params.seriesType == "scatter") {
               chartLng = params.data.longitude;
               chartLat = params.data.latitude;
               this.showChartPanel(
                  params.data.StationId,
                  params.data.FBSDeviceId,
                  params.data
               );
            }
         });
      },
      // 查询告警落后的信息
      showChartPanel(sId, dev_id, homeData) {
         // 检测是否存在3D机房
         searchByDevId({
            deviceId: dev_id,
         })
            .then((res) => {
               let rs = JSON.parse(res.data.result);
               if (rs.data.length != 0) {
                  this.areas = rs.data;
                  //this.hdwDialog = true;
                  this.showThreeHomeDialog(this.areas);
               } else {
                  searchHomeNum({
                     // 查询告警落后的信息
                     StationId: sId,
                     FBSDeviceId: dev_id,
                  })
                     .then((res) => {
                        let rs = JSON.parse(res.data.result);
                        homeData.nums = rs;
                        this.changeChartPanelStatus(homeData);
                     })
                     .catch((error) => {
                        console.log(error);
                     });
               }
            })
            .catch((error) => {
               console.log(error);
            });
      },
      initCityChart() {
         searchMap().then((res) => {
            let rs = JSON.parse(res.data.result);
            let list = this.mergeMapInfos(rs);
            if (list != undefined && list.length > 0) {
               list.map((item) => {
                  item.name = item.StationName;
                  item.value = [];
                  item.value.push(item.longitude);
                  item.value.push(item.latitude);
                  tempData.push(item)
               })
               this.searchChartHomeState()
               this.startSearchMapHomeState();
            } else {
               this.initChart([], []);
            }
         }).catch((err) => {
            console.log(err)
         })
      },
      searchChartHomeState() {
         searchMapHomeState().then((res) => {
            let rsState = JSON.parse(res.data.result);
            let arr = [];
            abnormalArr = [];
            if (rsState.code === 1) {
               let data = rsState.data;
               data.map((item) => {
                  let infos = tempData.filter((jtem) => {
                     return jtem.StationId == item.StationId
                  })
                    }
                },
                  if (infos.length > 0) {
                     let info = JSON.parse(JSON.stringify(infos[0]));
                     switch (item.num) {
                        case 1: // 落后
                           info.img = HomeDischargeImage;
                           info.color = '#ff6a6a';
                           abnormalArr.push(info);
                           break;
                        case 2: // 告警
                           info.img = HomeWarnImage;
                           info.color = '#d4ac6e';
                           abnormalArr.push(info);
                           break;
                        case 3:
                           info.img = HomeChargeImage;
                           info.color = '#4ba1fa';
                           abnormalArr.push(info);
                           break;
                        default:
                           info.img = HomeNormalImage;
                           break;
                     }
                     arr.push(info)
                  }
               })
               let arrId = [];
               for (let item of arr) {
                  if (arrId.indexOf(item['StationId']) == -1) {
                     arrId.push(item['StationId']);
                     chartData.push(item);
                  }
               }
               this.initChart(chartData, abnormalArr);
            },
            {
                type: 'lines',
                zlevel: 3,
                symbol: 'circle',
                symbolSize: [5, 5],
                color: '#ff8003',
                opacity: 1,
                label: {
                    show: true,
                    padding: [10, 20],
                    color: '#fff',
                    backgroundColor: "#1a3961",
                    borderColor: '#aee9fb',
                    borderWidth: 1,
                    borderRadius: 6,
                    formatter(params) {
                        console.log(params)
                        let arr = [params.name, "上行:" + params.value[1] + "G/s", "下行:" + params.value[0] + "G/s"];
                        return arr.join("\n")
                    },
                    textStyle: {
                        align: 'left',
                        lineHeight: 20,
                    }
                },
                lineStyle: {
                    type: 'solid',
                    color: '#fff',
                    width: 0.5,
                    opacity: 1,
                },
                data: LableData,
            },
        ];
        newarr.forEach(item=>{
            series.push( // 区域散点图
            {
                type: 'effectScatter',
                coordinateSystem: 'geo',
                zlevel: 12,
                symbolSize: 10,
                rippleEffect: { //坐标点动画
                    period: 3,
                    scale: 5,
                    brushType: 'fill'
                },
                label: {
                    normal: {
                        show: true,
                        position: 'right',
                        formatter: '{b}',
                        color: '#fff',
                        fontWeight: "bold",
                        fontSize: 13
                    }
                },
                data: [
                        {
                            name: item.name,
                            value: item.value
                        }
                    ],
                itemStyle: { //坐标点颜色
                    normal: {
                        show: true,
                        color: item.color,
                        borderColor:item.borderColor?item.borderColor:'none',
                        shadowBlur: 1,
                        shadowColor: '#fff'
                    },
                    emphasis: {
                        areaColor: '#f00'
                    }
                },
            });
            if(item.name !="武汉"){
                series.push(
                    // 线 和 点
                    {
                        name: item.name,
                        type: 'lines',
                        zlevel: 2,
                        effect: {
                            show: true,
                            period: 5,//流动速度 越小越快
                            trailLength: 0.7,
                            color: item.arrowColor, //流动点颜色
                            symbol: 'arrow',
                            symbolSize: 6
                        },
                        lineStyle: {
                            normal: {
                                color: item.linesColor,//线的颜色
                                width: 1.5,
                                opacity: 0.8,
                                curveness: item.curveness
                            }
                        },
                        data: [{
                            fromName: "武汉",
                            toName: item.name,
                            coords:[
                                        [ 113.41, 31.22 ],
                                        item.value
                                    ]
                        }]
                    },
                    )
            }
        })
    let option = {
            // backgroundColor: '#000f1e',
            geo: {
                map: 'china',
                aspectScale: 0.85,
                layoutCenter: ["50%", "65%"], //地图位置
                layoutSize: '130%',
                itemStyle: {
                    normal: {
                        shadowColor: '#276fce',
                        shadowOffsetX: 0,
                        shadowOffsetY: 15,
                        opacity: 0.5,
                    },
                    emphasis: {
                        areaColor: '#276fce',
                    }
                },
                regions: [
                    {
                        name: '南海诸岛',
                        itemStyle: {
                            areaColor: 'rgba(0, 10, 52, 1)',
                            borderColor: 'rgba(0, 10, 52, 1)',
                            normal: {
                                opacity: 0,
                                label: {
                                    show: false,
                                    color: "#009cc9",
                                }
                            },
                        },
                        label: {
                            show: false,
                            color: '#FFFFFF',
                            fontSize: 12,
                        },
                    },
                ],
            },
            series: series
    };
        this.$nextTick(function(){
            this.setOption(option);
        })
    },
    resize() {
        let self = this;
        setTimeout(() => {
            self.$options.chart.resize();
            self.setData(null);
        }, 300)
    //   this.$options.chart.resize();
    }
  },
  mounted() {
      this.$nextTick(function(){
          // 基于准备好的dom,初始化echarts实例
            this.$options.chart = echarts.init(this.$refs.chinaMap);
            window.addEventListener('resize', this.resize);
      })
  },
  destroyed() {
    window.removeEventListener('resize', this.resize);
  }
            }
         }).catch((err) => {
            console.log(err)
         })
      },
      initChart(chartData, abnormalArr) { //初始化chart图
         let option = {};
         if (abnormalArr.length > 0) {
            option = {
               series: [{ //图片
                  name: '图片',
                  type: 'scatter',
                  coordinateSystem: 'geo',
                  symbol: function (value, params) {
                     return 'image://' + params.data.img
                  },
                  symbolSize: [26, 26],
                  label: {
                     normal: {
                        show: false,
                     }
                  },
                  data: chartData,
                  showEffectOn: 'render',
                  rippleEffect: {
                     brushType: 'stroke'
                  },
                  hoverAnimation: true,
                  zlevel: 2
               }, { //波纹点
                  type: 'effectScatter',
                  coordinateSystem: 'geo',
                  showEffectOn: 'render',
                  zlevel: 1,
                  rippleEffect: {
                     period: 4,
                     scale: 4,
                     brushType: 'fill'
                  },
                  hoverAnimation: false,
                  label: {
                     normal: {
                        show: false
                     },
                  },
                  itemStyle: {
                     normal: {
                        color: function (value) {
                           return value.data.color
                        },
                        shadowBlur: 8,
                        shadowColor: function (value) {
                           return value.data.color
                        },
                     }
                  },
                  symbolSize: [15, 15],
                  data: abnormalArr
               }]
            };
         } else {
            option = {
               series: [{ //图片
                  name: '图片',
                  type: 'scatter',
                  coordinateSystem: 'geo',
                  symbol: function (value, params) {
                     return 'image://' + params.data.img
                  },
                  symbolSize: [26, 26],
                  label: {
                     normal: {
                        show: false,
                     }
                  },
                  data: chartData,
                  showEffectOn: 'render',
                  rippleEffect: {
                     brushType: 'stroke'
                  },
                  hoverAnimation: true,
                  zlevel: 2
               }]
            };
         }
         this.setData(option);
         window.addEventListener('resize', this.resize);
      },
      mergeMapInfos(list) {
         var mergeData = [];
         // 遍历list
         for (var i = 0; i < list.length; i++) {
            var _list = list[i];
            var isIn = this.checkMapInfoIsIn(_list, mergeData);
            if (isIn == -1) {
               mergeData.push(_list);
            }
         }
         // 返回合并值
         return mergeData;
      },
      checkMapInfoIsIn(mapInfo, mergeData) {
         var rs = -1;
         // 遍历mergeData
         for (var i = 0; i < mergeData.length; i++) {
            var _mergeData = mergeData[i];
            // 经纬度相同
            if (mapInfo.latitude == _mergeData.latitude && mapInfo.longitude == _mergeData.longitude) {
               rs = i;
            }
         }
         return rs;
      },
      showThreeHomeDialog(areas) {
         window.parent.parent.postMessage(
            {
               cmd: "showDialog",
               params: {
                  dialog: "hdwDialog",
                  pageInfo: areas,
               },
            },
            "*"
         );
      },
      outClear() {
         window.removeEventListener('resize', this.resize);
         clearInterval(this.timers)
         this.timers = null
      }
   },
   mounted() {
      // 基于准备好的dom,初始化echarts实例
      this.$options.chart = echarts.init(this.$refs.chart);
      // 监听chartMap的面板
      window.addEventListener("resize", () => {
         if (!this.isShowInfoPanel || !this.mapName) {
            return;
         }
         this.isShowInfoPanel = false;
         setTimeout(() => {
            this.isShowInfoPanel = true;
            let poit = this.convertMain(chartLng, chartLat);
            this.mapInfoX = poit[0] - 120;
            this.mapInfoY = poit[1] - 190;
         }, 300);
      });
      this.newPlatform = sessionStorage.getItem('newPlatform')
   },
   destroyed() {
      window.removeEventListener('resize', this.resize);
      clearInterval(this.timers)
   },
}
</script>
<style scoped>
.infoPanel {
   position: absolute;
   background-color: #ffffff;
   color: rgb(0, 0, 0);
   border: 1px solid #999;
   z-index: 99;
}
.infoPanel .infoPanel-Title {
   border-bottom: 1px solid #ccc;
   height: 31px;
   line-height: 30px;
   background-color: #f9f9f9;
   overflow: hidden;
   height: 30px;
   padding: 0 5px;
   font-size: 12px;
   position: relative;
}
.infoPanel .infoPanel-Title .closeBtn {
   background: url("../../assets/images/iw_close1d3.gif") 0 0 no-repeat;
   background-size: 100% 100%;
   position: absolute;
   top: 9px;
   right: 12px;
   width: 10px;
   height: 10px;
   user-select: none;
   overflow: hidden;
   cursor: pointer;
   line-height: 9999px;
   z-index: 10000;
}
.infoPanel .infoPanel-center {
   padding: 3px 5px;
   overflow-x: auto;
   overflow-y: hidden;
}
.infoPanel::after {
   content: "";
   display: block;
   z-index: 5;
   position: absolute;
   bottom: -31px;
   width: 58px;
   height: 31px;
   left: 125px;
   background: url("../../assets/images/iw_tail.png") 0 0 no-repeat;
   background-size: 100% 100%;
}
</style>