whyczyk
2022-06-09 11be4fa888dcbb55bbf43b6caf1f4a4abd16a208
src/components/charts/chinaMap.vue
@@ -1,341 +1,672 @@
<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
      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 * 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/newInfoPanel.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 {
  components: { InfoPanel, newChinaMap },
  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
    },
  },
  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: {
    setOption(opt) {
        // 设置配置项
        this.$options.chart.setOption(opt);
    findParents(node, select) {
      var parent = node.parentNode;
      if (parent === null || parent.className.indexOf(select) != -1) {
        return parent;
      } else {
        return this.findParents(parent, select);
      }
    },
    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%", "50%"], //地图位置
                layoutSize: '100%',
                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
                    },
                    emphasis: {
                        areaColor: '#1A6BF0',
                        label: {
                            color: "#fff"
                        }
                    }
                },
            },
            {
                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
                                    ]
                        }]
                    },
                    )
    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;
            }
        })
    let option = {
            // backgroundColor: '#000f1e',
            geo: {
                map: 'china',
                aspectScale: 0.85,
                layoutCenter: ["50%", "50%"], //地图位置
                layoutSize: '100%',
                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,
                        },
                    },
                ],
          },
        },
        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",
              },
            },
            series: series
    };
        this.setOption(option);
            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() {
      this.$options.chart.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 = res.data;
          if (rs.code == 1) {
            let data = rs.data;
            data.map((item) => {
              if (item.status == 1) {
                this.mapName = item.name;
              }
            });
          }
          if (!this.mapName) {
            this.mapStyle = "百度地图";
          }
          this.mapNameCopy = this.mapName;
          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];
      this.mapInfoY = poit[1];
      this.mapInfoTitle = homeData.stationName;
      this.$nextTick(() => {
        console.log("panelInfo", homeData);
        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"));
      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];
          this.mapInfoY = poit[1];
          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
          // 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 = res.data;
          if (rs.data.length != 0) {
            this.areas = rs.data;
            //this.hdwDialog = true;
            this.showThreeHomeDialog(this.areas);
          } else {
            searchHomeNum({
              // 查询告警落后的信息
              stationId: sId,
            })
              .then((res) => {
                let rs = res.data;
                homeData.nums = rs;
                this.changeChartPanelStatus(homeData);
              })
              .catch((error) => {
                console.log(error);
              });
          }
        })
        .catch((error) => {
          console.log(error);
        });
    },
    initCityChart() {
      searchMap()
        .then((res) => {
          let rs = res.data.data;
          let list = this.mergeMapInfos(rs);
          console.log("list", list);
          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 = res.data;
          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);
          }
        })
        .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.chinaMap);
    window.addEventListener('resize', this.resize);
    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];
        this.mapInfoY = poit[1];
      }, 300);
    });
    this.newPlatform = sessionStorage.getItem("newPlatform");
  },
  destroyed() {
    window.removeEventListener('resize', this.resize);
  }
}
    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;
  transform: translateY(-100%);
  margin-top: -26px;
  margin-left: -120px;
  z-index: 2;
}
</style>
.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>