<!-- 
    电子地图    
    -编辑页面
 -->
<template>
  <div>
    <div id="earthContainer" ref="earthContainer" style="width: 100%; height: 100%; top: 300px"></div>
    <div class="earthUI_header" v-if="PropsEarthHeaderShow">
      <header>
        <p>{{ earthTitle }}</p>
        <p>{{ realTime }}</p>
      </header>
    </div>
    <div>
      <a-radio-group default-value="satellite" button-style="solid" size="small" @change="radioChange" class="radioBtn" v-show="radioBtnShow">
        <a-radio-button value="satellite"> 卫星影像</a-radio-button>
        <a-radio-button value="vector"> 矢量地图</a-radio-button>
      </a-radio-group>
      <a-spin size="large" tip="地图切换中，请稍候..." :spinning="earthChangeSpin" class="earthChangeSpin"></a-spin>
    </div>

    <!-- 预警列表 -->
    <!-- <WarnInfoList /> -->

    <!-- 电线杆弹窗 -->
    <div id="cameraModal" class="cameraModal" v-show="cameraModalShow" ref="cameraModal">
      <a-spin size="large" :spinning="spinning" class="spinning"></a-spin>
      <a-button @click="roamPathSet()">视频融合</a-button>
    </div>
    <!-- 视频融合 -->
    <VideoFusionWin
      v-if="VideoFusionWinShow"
      :cameraList="cameraList"
      :monitorPosition="monitorPosition"
      :updateModel="toItemObj.updateModel"
      :isUpdate="toItemObj.isUpdate"
      :userSave="toItemObj.userSave"
    ></VideoFusionWin>
    <!-- 地标弹窗 -->
    <!-- <div id="poiModal" class="poiModal" v-show="poiModalShow" ref="poiModal">
      <div class="poiModal-content">
        <div class="poiModal-header"></div>
        <div class="poiModal-body"></div>
      </div>
    </div>-->

    <!-- 警示弹窗 -->
    <video-split-screen />

    <!-- 警示音频 -->
    <audio ref="audio" loop>
      <source src="@/assets/earthMap/audio/notify.mp3" />
    </audio>

    <!-- 云台控制弹窗 -->
    <video-window
      :id="videoWindowProps.id"
      :visible.sync="videoWindowProps.visible"
      :title="videoWindowProps.title"
      :videoUrl="videoWindowProps.videoUrl"
      :cameraIp="videoWindowProps.cameraIp"
      :cameraUser="videoWindowProps.cameraUser"
      :cameraPwd="videoWindowProps.cameraPwd"
      :isAlarm="videoWindowProps.isAlarm"
      :playRecord="videoWindowProps.playRecord"
      :warnTime="videoWindowProps.warnTime"
      :warnEvent="videoWindowProps.warnEvent"
    />

    <!-- 左侧操作栏 -->
    <Toolbar v-if="toolbarShow" :setLabelStatus="setLabelStatus" :all="this.all"></Toolbar>
    <!-- 左下角显隐控件 -->
    <ShowHideControl v-if="toolbarShow"></ShowHideControl>
    <AddModelWin
      v-if="addModelWinShow"
      :setLabelStatus="setLabelStatus"
      :czmObject="czmObject"
      :node="node"
      :type="type"
      :lineId="lineId"
      :areaCode="areaCode"
      :areaByNodeId="areaByNodeIdModel"
      :setIconByRef="setIconByRef"
      :el="el"
      :eidtId="eidtId"
    ></AddModelWin>
    <AddRoamVideo v-if="addRoamVideoShow"></AddRoamVideo>
    <!-- AIS信息显示窗口 -->
    <AISInfoWindow v-if="AISInfoWindowShow" :ship_guid="ship_guid" :title="windowTitle"></AISInfoWindow>
    <!-- 跟踪船只窗口 -->
    <TailAfterWindow v-if="TailAfterWindowShow"></TailAfterWindow>
  </div>
</template>

<script lang="ts">
  import { Options, Vue } from 'vue-class-component';
  import sceneTree from '@/assets/earthMap/resjson/sc.json';
  import { defHttp } from '/@/utils/http/axios';
  import earthUtils from '@/utils/earthMap/earth';
  import _ from 'lodash';
  import $ from 'jquery';
  import { useUserStore } from '/@/store/modules/user';
  import { useEarthMapStore } from '/@/store/modules/earthMap';
  import Toolbar from '@/components/earthMap/Toolbar.vue';
  import ShowHideControl from '/@/components/earthMap/ShowHideControl.vue';
  import AddModelWin from '@/components/earthMap/toolbar/AddModelWin.vue';
  import AddRoamVideo from '@/components/earthMap/toolbar/AddRoamVideo.vue';
  import VideoSplitScreen from '@/components/earthMap/VideoSplitScreen.vue';
  import VideoWindow from '@/components/earthMap/VideoWindow.vue';
  import WarnInfoList from '@/components/earthMap/WarnInfoList.vue';
  import AISInfoDetail from '@/components/earthMap/AISInfoDetail.vue';
  import AISInfoWindow from '@/components/earthMap/AISInfoWindow.vue';

  import TailAfterWindow from '@/components/earthMap/TailAfterWindow.vue';
  import { getRealTime } from '@/utils/date';
  import $mitt from '@/utils/earthMap/mitt';
  import guid from '@/utils/earthMap/guid';
  import HandleNodeType from '@/utils/earthMap/handleNodeType';
  import { handleNodeType } from '@/utils/earthMap/handleNodeType';
  import { getRandomArr, getHeigthByLonLat } from '@/utils/earthMap/earth';
  import redFlag from '@/assets/earthMap/redFlag.png';
  import { addModel, addPin, addViewShedRadar, addShipTrack } from '@/utils/earthMap/earthObj';
  import { drawAISShipsList, drawMixShipsList, drawRadarShipsList } from '@/utils/earthMap/shipDraw';
  import hidePng from '@/assets/earthMap/hide.png';
  import alarmImg from '@/assets/earthMap/alarm.gif';
  import VideoFusionWin from './components/VideoFusionWin.vue';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { CircleScan } from '@/utils/earthMap/radarEntity';
  import { radianToDegreeInLngLatHeight } from '@/utils/earthMap/earth';
  import listenMouseHandlerSence from '@/utils/earthMap/listenMouseHandlerSence';
  import listenMouseHandler from '@/utils/earthMap/listenMouseHandler';
  import getLineInfo from '@/utils/earthMap/getLineInfo';
  import getCameraInfo from '@/utils/earthMap/getCameraInfo';
  import getLabelInfo from '@/utils/earthMap/getLabelInfo';
  import { setLabelStatus, setAllLabelStatus } from '@/utils/earthMap/setLabelStatus';
  import keyControlInit from '@/utils/earthMap/keyControlInit';
  import createRealTimeObj from '@/utils/earthMap/createRealTimeObj';
  import sceneTreePopContextMenu from '@/utils/earthMap/sceneTreePopContextMenu';
  import { drawInit } from '@/utils/earthMap/earthDraw';
  import { cloneModel, cloneShamNode } from '@/utils/earthMap/clone';
  import {
    initWebSocket,
    websocketonopen,
    websocketonerror,
    loreadAlarmInfo,
    websocketclose,
    websocketonmessage,
    websocketdosend,
    websock,
  } from '@/utils/earthMap/websocket';
  import setIconByRef from '@/utils/earthMap/setIconByRef';

  import dwPng from '@/assets/images/rotationXYZ.png';
  import rotationXYZ from '@/assets/images/rotationXYZ.png';
  import circleDot2 from '@/assets/earthMap/circleDot2.png';
  import circleDot1 from '@/assets/earthMap/circleDot1.png';
  import circleDot3 from '@/assets/earthMap/circleDot3.png';
  import { nextTick } from 'vue';

  const { createMessage } = useMessage();
  function setClassEl(setClassEl1, setClassEl2, checked) {
    if (checked) {
      setClassChecked(setClassEl1, setClassEl2);
    } else {
      setClassNoChecked(setClassEl1, setClassEl2);
    }
  }

  function setClassChecked(setClassEl1, setClassEl2) {
    // node.checkStatus = 'checked'
    // node.disabled = ''
    //***设置样式为选中 */
    setClassEl1.className = 'xbsj-checkbox-wrapper xbsj-checkbox-wrapper-checked xbsj-checkbox-default';
    setClassEl2.className = 'xbsj-checkbox xbsj-checkbox-checked';
  }

  function setClassNoChecked(setClassEl1, setClassEl2) {
    // node.checkStatus = ''
    // node.disabled = 'disabled'
    // 设置为非选中
    setClassEl1.className = 'xbsj-checkbox-wrapper xbsj-checkbox-wrapper-disabled xbsj-checkbox-default';
    setClassEl2.className = 'xbsj-checkbox xbsj-checkbox-disabled';
  }

  function classMutationObserver(el, el1, checkedStauts, id) {
    // 观察器的配置（需要观察什么变动） 属性，子节点or后代节点
    const config = { attributes: true, childList: false, subtree: false };
    const callback1 = function (mutationsList, observer) {
      const checked = checkedStauts.get(id);
      const oldClassName = el.className;
      const trueClassName = 'xbsj-checkbox-wrapper xbsj-checkbox-wrapper-checked xbsj-checkbox-default';
      const noClassName = 'xbsj-checkbox-wrapper xbsj-checkbox-wrapper-disabled xbsj-checkbox-default';
      if (checked) {
        if (oldClassName == trueClassName) {
          return;
        } else {
          setClassChecked(el, el1);
        }
      } else {
        if (oldClassName == noClassName) {
          return;
        } else {
          setClassNoChecked(el, el1);
        }
      }
    };
    // 创建一个观察器实例并传入回调函数
    const observer1 = new MutationObserver(callback1);
    // 以上述配置开始观察目标节点
    observer1.observe(el, config);
  }

  function disabledMutationObserver(el) {
    const config = { attributes: true, childList: false, subtree: false };
    const callback1 = function (mutationsList, observer) {
      const el1 = mutationsList[0];
      if (el1.attributeName == 'disabled') {
        el.removeAttribute('disabled');
      }
    };
    const observe1 = new MutationObserver(callback1);
    // 以上述配置开始观察目标节点
    observe1.observe(el, config);
  }

  @Options({
    components: {
      Toolbar,
      ShowHideControl,
      VideoSplitScreen,
      VideoWindow,
      WarnInfoList,
      AddModelWin,
      AddRoamVideo,
      VideoFusionWin,
      AISInfoDetail,
      AISInfoWindow,
      TailAfterWindow,
    },
    props: {
      //全部显示
      all: {
        type: Boolean,
        default: false,
      },
      //头部显示
      earthHeaderShow: {
        type: Boolean,
        default: false,
      },
      //图层显示
      sceneTreeShow: {
        type: Boolean,
        default: false,
      },
      //状态栏
      statusBarShow: {
        type: Boolean,
        default: true,
      },
      //主工具栏
      mainBar: {
        type: Boolean,
        default: false,
      },
      //监听事件
      listenMouseHandlerOpen: {
        type: Boolean,
        default: false,
      },
      //监听mitt
      listenMittHandlerOpen: {
        type: Boolean,
        default: false,
      },
      //地图路线资源
      createBBHLineOpen: {
        type: Boolean,
        default: false,
      },
      //加载区域
      getLineInfoShow: {
        type: Boolean,
        default: false,
      },
      //加载站点
      getCameraInfoShow: {
        type: Boolean,
        default: false,
      },
      //加载微波和雷达
      getLabelInfoShow: {
        type: Boolean,
        default: false,
      },
      //加载绘图
      drawInitShow: {
        type: Boolean,
        default: false,
      },
      //加载重点监控区域
      keyControlInitShow: {
        type: Boolean,
        default: false,
      },
      //后台场景管理点击
      enablePointer: {
        type: Boolean,
        default: false,
      },
      //后台场景管理点击事件监听
      listenMouseHandlerSenceOpen: {
        type: Boolean,
        default: false,
      },
      //后台区域管理事件
      msMapLineHandler: {
        type: Object,
        default: null,
      },
      //后台监控点位管理事件
      msCameraSiteHandle: {
        type: Object,
        default: null,
      },
    },
  })
  export default class EarthComp extends Vue {
    /**
     * 资源创建
     */
    userStore = useUserStore();
    store = useEarthMapStore();
    setLabelStatus: any = setLabelStatus;
    setIconByRef: any = setIconByRef;
    earthTitle = '态势监控一张图';
    realTime = '……';
    // 注意：Earth和Cesium的相关变量放在vue中，必须使用下划线作为前缀！
    // _earth = undefined;
    // _viewer = undefined;
    _pin = undefined;
    _handler = undefined;
    //  sceneTree= require('@/assets/earthMap/resjson/sc.json'),
    //   sceneTree= new URL(`@/assets/earthMap/resjson/sc.json`, import.meta.url).href,
    sceneTree: any = sceneTree;
    // areaB= require('@/assets/earthMap/resjson/area_b.json'),
    url: any = {
      queryLabelList: 'military/msMapLabel/queryLabelAndDeviceList',
      queryLineList: 'military/msMapLine/list',
      queryCameraInfo: 'military/camera/site/getCameraInfoForEarth',
      queryAllModelInfo: 'military/msModelPosition/queryAllModelInfo',
      queryPatrolRouteInfo: 'military/msPatrolLine/getLineDetail',
      queryBayoneByParam: 'military/msBayonetStatistics/getBayoneByParam',
      queryAisInfo: 'military/checkpoint/msAisInfo/list',
      keepAlive: 'military/mapInfo/keepAlive',
      //雷达扫描列表
      radarList: '/military/RadarConfig/list',
      // 删除模型
      // 传感器
      deleteSensor: '/military/msModelPosition/deleteByEventSerialNum',
      // 站点
      deleteSite: '/military/camera/site/delete',
      // 标志点
      deleteMapLabel: '/military/msMapLabel/delete',
      updateMapLine: '/military/msMapLine/edit',
      deleteMapLine: '/military/msMapLine/delete',
      saveMapLine: '/military/msMapLine/add',
      // 编辑 模型
      // 传感器
      updateSensor: '/military/msModelPosition/editByEventSerialNum',
      // 站点
      updateSite: '/military/camera/site/edit',

      // 标志点
      updateMapLabel: '/military/msMapLabel/edit',

      // 模型 保存
      // 传感器
      SaveSensorModel: '/military/msModelPosition/add',
      // 站点
      saveCameraSiteModel: '/military/camera/site/add',
      // 标志点
      saveMapLabel: '/military/msMapLabel/addMapLabel',

      // 通过 线路名称 查询 线路
      queryMapLine: '/military/msMapLine/queryByName',
      querySiteById: '/military/camera/site/queryById',
      // 查询设备列表
      queryDeviceInfoList: '/military/msDeviceInfo/list',
      setDefenseArea: '/military/netty/microwaveDetector/defenceArea',
      perimeterRegionList: '/third/api/perimeterRegionList',
      perimeterControl: '/third/api/perimeterControl',
      // 雷达重新发送报警信息
      sendRadarAlarmByWebSocket: '/military/warn/sendRadarAlarmByWebSocket',
    };
    // cameraData: any = {};
    cameraModalShow = false;
    poiModalShow = false;
    radioBtnShow = true;
    glmId: any = [];
    spinning = false;
    earthChangeSpin = false;
    // websock: any = [];
    timer: any = null; // 保活定时器
    timer2: any = null; // 时间定时器
    // 报警清除-定时器
    alarmTrackClearTimer: any = null;
    videoWindowProps: any = {
      visible: false,
      isAlarm: false,
      id: '',
      title: '',
      videoUrl: '',
      cameraIp: '',
      cameraUser: '',
      cameraPwd: '',
      playRecord: false,
      warnTime: null,
      warnEvent: {
        happenTime: '',
        happenLoc: '',
        warnNum: 0,
        warnLevel: 0,
        warnType: 0,
        warnContent: '',
      },
    };
    // 图层管理- 模型 ref 旧值
    sceneTreeOldRefValue = '';
    sceneInfo: any = null;
    // 区域节点By Ref划分
    // nodeConfigByRef = new Map();
    // nodeCheckedByRef = new Map();
    // areaByNodeId = new Map();
    // statusByNodeId = new Map();
    // imgByRef = new Map();
    // radarAlarmDataMap = new Map();
    wbUnifiedResponse = false;
    // hostDeviceMapById = new Map();
    // alarmInfoMap = new Map();
    toolbarShow = false;

    //addModelWin
    addModelWinShow = false;
    czmObject: any = null;
    node: any = null;
    type = '';
    lineId = '';
    areaCode = '';
    areaByNodeIdModel = '';
    el: any = null;
    eidtId: any = null;
    //addroamVideo
    addRoamVideoShow = false;

    // 控制窗口显示
    VideoFusionWinShow = false;
    //传到子组件的值
    toItemObj: any = {
      updateModel: {},
      isUpdate: true,
      userSave: {},
    };
    // 节点值
    domKey: any = '';
    // 监控相机列表
    cameraList: any = [];
    // 监控相机位置
    monitorPosition: any = [];

    //处理props  由于从父组件传来props，为作区分其他变量，则采用首字母大写命名
    PropsEarthHeaderShow = this.earthHeaderShow;
    PropsSceneTreeShow = this.sceneTreeShow;
    PropsListenMouseHandlerOpen = this.listenMouseHandlerOpen;
    PropsListenMittHandlerOpen = this.listenMittHandlerOpen;
    PropsCreateBBHLineOpen = this.createBBHLineOpen;
    PropsGetLineInfoShow = this.getLineInfoShow;
    PropsGetCameraInfoShow = this.getCameraInfoShow;
    PropsGetLabelInfoShow = this.getLabelInfoShow;
    PropsDrawInitShow = this.drawInitShow;
    PropsKeyControlInitShow = this.keyControlInitShow;
    ///////////////////////////////////////////////////////////////////////////
    // AIS信息窗口显隐状态
    AISInfoWindowShow = false;
    // 跟踪窗口显隐状态
    TailAfterWindowShow = false;
    // 船只场景id
    ship_guid = '';
    //新增船只是否显示轨迹（雷达）
    isShowRadarTrack = true;
    //新增船只是否显示轨迹（AIS）
    isShowAISTrack = true;
    //新增船只是否显示轨迹（融合）
    isShowMixTrack = true;
    // 新增船只是否显示模型（雷达）
    isShowRadarShip = true;
    // 新增船只是否显示模型（AIS）
    isShowAISShip = true;
    // 新增船只是否显示模型（融合）
    isShowMixShip = true;
    // 信息框的标题
    windowTitle = '';
    // 添加地图上的鼠标监听事件
    // pin: any = undefined;
    // viewer: any = undefined;
    // // 鼠标样式
    // cursorCss = "grab";
    // position: any = null;
    // rotation: any = null;
    // fov: any = null;
    mounted() {
      let that = this;
      //随机数
      window.guid = guid;
      //创建地球资源
      this.createEarth();
      //获取实时日期时间
      this.getRealTime();
      //初始化websocket
      //  this.initWebSocket('domianURL')
      //阻止浏览器右键事件
      document.oncontextmenu = function (e) {
        return false;
      };

      {
        //将回调延迟到下次 DOM 更新循环之后执行（针对由jq动态增加的元素绑定事件）
        this.$nextTick(() => {
          {
            //监控点击事件
            $('.cameraModal').on('click', '.openIframe', function (e: any) {
              // web插件播放视频流
              let videoWindowProps = that.videoWindowProps;
              videoWindowProps.id = $(this).attr('id');
              videoWindowProps.title = $(this).text();
              videoWindowProps.videoUrl = $(this).attr('videoUrl');
              videoWindowProps.cameraIp = $(this).attr('cameraIP');
              videoWindowProps.cameraUser = $(this).attr('cameraUser');
              videoWindowProps.cameraPwd = $(this).attr('cameraPsd');
              videoWindowProps.isAlarm = false;
              videoWindowProps.visible = true;
              videoWindowProps.playRecord = false;
            });
          }
          // 轮询
          {
            //一个小时调用一次空接口，保持系统session不过期
            this.timer = setInterval(() => {
              this.keepAlive();
            }, 60 * 60 * 1000);

            this.alarmTrackClearTimer = setInterval(() => {
              this.radarAlarmTimeOutCheck();
            }, 6 * 1000);
          }
        });
      }
    }

    // 打开视频融合
    roamPathSet() {
      // 打开视频融合
      this.VideoFusionWinShow = true;
      // 关闭相机列表
      this.cameraModalShow = false;
    }

    // 后台区域管理事件
    areaHandler() {
      // 取消双击旋转事件
      window.$viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(window.Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
      this.$nextTick(() => {
        $mitt.emit('msMapLineHandler', this.msMapLineHandler);
      });
    }

    // 后台监控点位管理事件
    cameraSiteHandler() {
      // 取消双击旋转事件
      window.$viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(window.Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
      this.$nextTick(() => {
        $mitt.emit('msCameraSiteHandle', this.msCameraSiteHandle);
      });
    }

    // 控制子元素的显示或者隐藏
    showOrHideChild(clickNode, earthUI, parentChecked) {
      const childs = clickNode.children;
      if (childs && childs.length > 0) {
        for (const child of childs) {
          const ref = child.ref;
          const inputEl: any = document.getElementById(ref);
          if (inputEl) {
            inputEl.checked = parentChecked;
            const event = new Event('change');
            inputEl.dispatchEvent(event);
          } else {
            if (ref.startsWith('node_')) {
              const readyNode = earthUI.earth.sceneTree.$refs[ref.split('_')[1]];
              if (readyNode && readyNode.czmObject) {
                readyNode.czmObject.show = parentChecked;
              }
            } else if (ref.startsWith('nodeSecondary_')) {
              const readyNode = earthUI.earth.sceneTree.$refs[ref.split('_')[1]];
              if (readyNode && readyNode.czmObject) {
                readyNode.czmObject.show = parentChecked;
                let guid = readyNode.czmObject.pinXbsjGuid;
                let pin = window.$earth.getObject(guid);
                pin.show = !pin.show;
              }
            } else {
              if (child && child.czmObject) {
                child.czmObject.show = parentChecked;
              }
            }
            this.store.nodeCheckedByRef.set(ref, parentChecked);
            this.showOrHideChild(child, earthUI, parentChecked);
          }
        }
      }
    }

    // 告警模型显示/隐藏
    showAlarmPin(show) {
      this.store.alarmInfoMap.forEach((item, _index) => {
        item.pin.show = show;
        item.pin._div.hidden = !show;
        item.scanline.show = !show;
      });
    }

    cameraPositionChange = _.debounce(
      (that) => {
        let height = window.$earth.camera.position[2];
        if (height < 100) {
          // 相机高度小于1000米,告警显示扫描线
          that.showAlarmPin(false);
        } else if (height >= 100) {
          // 相机高度大于1000米,告警显示图标
          that.showAlarmPin(true);
        }
      },
      500,
      { maxWait: 1000 }
    );

    createEarth() {
      let that = this;
      //使用store存储XbsjEarthUI
      this.store.xbsjEarthUI = XbsjEarthUI;
      //处理props
      if (this.all) {
        this.PropsEarthHeaderShow = true;
        this.PropsSceneTreeShow = true;
        this.PropsListenMouseHandlerOpen = true;
        this.PropsListenMittHandlerOpen = true;
        this.PropsCreateBBHLineOpen = true;
        this.PropsGetLineInfoShow = true;
        this.PropsGetCameraInfoShow = true;
        this.PropsGetLabelInfoShow = true;
        this.PropsDrawInitShow = true;
        this.PropsKeyControlInitShow = true;
      }
      //创建地球
      XbsjEarthUI.create('earthContainer').then(async (earthUI: any) => {
        // 设置全局变量，可调试
        window.$uia = earthUI;
        window.$earth = earthUI.earth;
        window.$viewer = earthUI.earth.czm.viewer;
        earthUI.controls.mainBar.show = false; //隐藏主工具栏
        earthUI.controls.statusBar.show = true; //状态栏
        //图层管理
        let sceneTree = earthUI.tools.sceneTree;
        // 显示图层管理
        sceneTree.show = this.PropsSceneTreeShow;
        // 设置图层管理 ref 输入框的 回车 事件
        // ref 输入框的
        let sceneTreeInput = sceneTree._comp.$el.getElementsByClassName('xbsj-model-content-box')[0].children[1];
        // 地图右键菜单和ref输入框控制
        this.$nextTick(() => {
          // 删除ref 的 输入框
          sceneTreeInput.remove();
          // ----右键菜单样式控制--start
          // 选择需要观察变动的节点
          const targetNode = document.getElementsByClassName('menu-box')[0];
          // 观察器的配置（需要观察什么变动） 属性，子节点or后代节点
          const config = { attributes: true, childList: false, subtree: false };
          // 当观察到变动时执行的回调函数
          const callback = function (mutationsList, observer) {
            // 右键会弹出菜单的样式 此时可以活的菜单这个元素
            const el = mutationsList[0].target;
            // 菜单的展示属性
            const elDisplay = el.style.display;
            // 如果菜单的展示属性本来就是none 则什么也不做
            if (elDisplay == 'none') {
              return;
            }
            // 获取到菜单项的集合
            const childList = el.children[0].children;
            // 菜单长度
            const liSize = childList.length;
            // 当菜单为none时 不显示
            if (liSize == 0) {
              el.style.display = 'none';
            } else {
              // 长度大于零 但第一个元素是 添加文件夹时也不显示
              const text = childList[0].textContent;
              if ('添加文件夹 ' == text) {
                el.style.display = 'none';
              }
            }
          };
          // 创建一个观察器实例并传入回调函数
          const observer = new MutationObserver(callback);
          // 以上述配置开始观察目标节点
          observer.observe(targetNode, config);
          // -----右键菜单控制----end
        });
        let XE = window.XE;
        // ref 的 输入框
        // 设置 回车 事件
        sceneTreeInput.onkeydown = function (e) {
          if (e.code === 'Enter') {
            // 回车事件
            that.changeRef(earthUI.earth.sceneTree.currentSelectedNode, sceneTree._comp.$data.refvalue, that.sceneTreeOldRefValue);
          }
        };
        // 设置失去焦点事件
        sceneTreeInput.onblur = function () {
          that.changeRef(earthUI.earth.sceneTree.currentSelectedNode, sceneTree._comp.$data.refvalue, that.sceneTreeOldRefValue);
        };
        // 修改图层管理中，右键菜单的显示
        sceneTree._comp.popContextMenu = ({ item, vueObject }) => {
          sceneTreePopContextMenu({ item, vueObject }, earthUI, this);
        };
        earthUI.tools.featureProperty.disabled = true; //禁用对象属性面板

        window.$earth = earthUI.earth;
        window.$earth.interaction.picking.enabled = true; // 全局打开点击事件权限
        window.$earth.czm.viewer.scene.globe.depthTestAgainstTerrain = true; //开启深度检测
        window.$earth.terrainEffect.subSurfaceEnabled = false; //开启地表透明模式

        // this._viewer = earthUI.earth.czm.viewer;
        window.$viewer.scene.fxaa = true; //图像改善
        window.$viewer.scene.globe.baseColor = window.Cesium.Color.BLACK;

        //加载场景资源
        //   console.log("this.sceneTree",this.sceneTree);
        // console.log("window._CONFIG['earthMapURL']",window._CONFIG['earthMapURL']);
        // console.log("window._CONFIG['satellite']",window._CONFIG['satellite']);

        this.sceneTree.children[0].czmObject.xbsjImageryProvider.TileMapServiceImageryProvider.url =
          window._CONFIG['earthMapURL'] + window._CONFIG['satellite'];
        this.sceneTree.children[1].czmObject.xbsjImageryProvider.TileMapServiceImageryProvider.url =
          window._CONFIG['earthMapURL'] + window._CONFIG['vector'];
        this.sceneTree.children[2].czmObject.xbsjTerrainProvider.XbsjCesiumTerrainProvider.url =
          window._CONFIG['earthMapURL'] + window._CONFIG['terrain'];

        window.$earth.sceneTree.root = {
          expand: true,
          title: '场景树',
          children: [this.sceneTree],
        };
        // 监控相机数据
        XE.MVVM.watch(window.$earth.camera, 'position', () => {
          this.cameraPositionChange(this);
        });

        // 飞入方法
        await this.fly();
        //创建工具栏
        this.toolbarShow = true;

        //加载地图实时资源（无人机、车辆、人员、巡逻路线等）
        // createRealTimeObj(earthUI)

        //监听鼠标事件
        if (this.PropsListenMouseHandlerOpen) listenMouseHandler(that);
        //监听鼠标事件（场景管理）
        if (this.listenMouseHandlerSenceOpen) listenMouseHandlerSence(this.enablePointer, this);

        //监听mitt
        if (this.PropsListenMittHandlerOpen) this.listenMittHandler();
        //加载地图线路资源
        if (this.PropsCreateBBHLineOpen) await this.createBBHLine();

        //使用后台区域管理事件 绘制区域等操作
        if (this.msMapLineHandler) this.areaHandler();

        //使用后台监控点位管理事件 设置监控杆等操作
        if (this.msCameraSiteHandle) this.cameraSiteHandler();
      });
    }

    //飞入方法
    async fly() {
      if (this.$attrs.onCustomFly) {
        // 如果外部传入了customFly方法则调用外部的
        this.$emit('customFly');
        return;
      }
      let position, rotation, viewDistance, duration;
      const sceneId = this.userStore.userInfo?.sceneId;
      await defHttp
        .get(
          {
            url: '/military/msMapScene/list',
            params: {
              pageNo: 1,
              pageSize: 999,
              sceneId: sceneId + '*',
              column: 'sceneId',
              order: 'asc',
            },
          },
          { isTransformResponse: false }
        )
        .then((response) => {
          console.log('fly', response);
          // 设置岛屿信息为数组
          this.sceneInfo = response.result.records;
          return response.result.records;
        })
        .then((res) => {
          //飞入 所属场景下的位置
          position = [res[0].cameraLon, res[0].cameraLat, res[0].cameraAltitude];
          rotation = [res[0].rotationX, res[0].rotationY, res[0].rotationZ];
          viewDistance = res[0].viewDistance;
          duration = res[0].duration;
          window.$earth.camera.flyTo(position, viewDistance, rotation, duration);
          // 地图复原事件
          window.$flyTo = this.flyTo = () => {
            window.$earth.camera.flyTo(position, viewDistance, rotation, duration);
          };
        });
    }

    setLoginPoint(data) {
      let position = [data.lon, data.lat, 0];
      let rotation = [data.rotationX, data.rotationY, data.rotationZ];
      let viewDistance = data.viewDistance;
      let duration = data.duration ? data.duration : 1;
      const leafConfig = {
        name: '岛屿',
        xbsjType: 'Pin',
        // far: 2500000,
        near: 3000000,
        position: position,
        // imageUrl: require('@/assets/redFlag.png'),
        imageUrl: redFlag,
        pinBuilder: {
          extText: data.sceneName,
          extTextFont: '30px 楷体',
          extTextPixelOffset: [30, -40],
          fillColor: [1, 1, 1, 0.9],
          outlineColor: [0, 0, 0, 0.9],
        },
      };

      const pin = new window.XE.Obj.Pin(window.$earth);
      pin.xbsjFromJSON(leafConfig);
      position[2] = data.altitude;
      //鼠标事件
      pin.onmouseover = () => {
        window.$viewer._container.style.cursor = 'pointer';
      };
      pin.onmouseout = () => {
        window.$viewer._container.style.cursor = 'default';
      };
      pin.onclick = function () {
        window.$earth.camera.flyTo(position, viewDistance, rotation, duration);
      };
    }

    /* 使用async/await 处理异步方法顺序执行。成功的操作放到try里，失败的放在catch里 */
    async createBBHLine() {
      // console.log('MyScene', this.userStore.userInfo?.sceneId);
      let labelItems: any = undefined;
      let type = 1; //**

      let models: any = {
        ref: this.sceneInfo[0].sceneId,
        expand: true,
        title: this.sceneInfo[0].sceneName,
        children: [],
      };
      for (let record of this.sceneInfo) {
        if (record.sceneId == this.userStore.userInfo?.sceneId) {
          continue;
        }
        models.children.push({
          ref: record.sceneId,
          expand: false,
          title: record.sceneName,
          children: [],
        });
      }

      // console.log('models',models);

      // 加载防区
      // console.log("加载防区");
      if (this.PropsGetLineInfoShow) await getLineInfo(models, type);

      // 加载站点
      // console.log("加载站点");
      if (this.PropsGetCameraInfoShow) await getCameraInfo(models, type);

      // 加载雷达和微波
      // console.log("加载雷达和微波");
      if (this.PropsGetLabelInfoShow) labelItems = await getLabelInfo(models, type);

      //加载绘画资源
      if (this.PropsDrawInitShow) await drawInit();

      //加载重点监控区域
      if (this.PropsKeyControlInitShow) await keyControlInit();

      // 监听树的dom节点变化
      // console.log("监听树的dom节点变化");
      this.$nextTick(() => {
        // ----树节点复选框控制--start
        // 容器元素
        const target1 = document.getElementById('earthContainer')?.children[0].children[0].children[4].children[2].children[0].children[0];
        // 配置子元素变动时触发
        const config1 = { attributes: false, childList: true, subtree: false };
        // this的别称
        const that = this;
        // 回调事件
        const callback1 = function (mutationsList, observer) {
          for (const mutation of mutationsList) {
            // 新增元素
            const el = mutation.addedNodes[0];
            // 删除元素时不触发
            if (!el) {
              continue;
            }
            // 样式设置1
            const setClassEl1 = el.children[0].children[1];
            // 样式设置2
            const setClassEl2 = setClassEl1.children[0];

            // 查找input元素
            const inputEl = setClassEl2.querySelector('input');
            // 移除input元素的禁用属性
            inputEl.removeAttribute('disabled');
            const item = el.__vue__.item;
            // item.checkStatus = 'ignored'
            // 从元素中拿到这个元素节点对象
            const nodeObject = item._inner.sn;
            // console.log("nodeObject",nodeObject);

            // 记录ref
            const ref = nodeObject.ref;
            if (ref.startsWith('wbList') || ref.startsWith('ldList')) {
              // 展开菜单图标元素
              const iel = el.children[0].children[0];
              iel.addEventListener('click', function (e) {
                if (iel.className == 'xbsj-icon xbsj-icon-ios-arrow-forward XbsjVritualTreeItemExpandIcon') {
                  console.log('收起菜单');
                  return;
                }
                // 获取展开菜单下的元素并设置图标
                let eventTarget;
                // console.log(nodeObject.children);
                for (let index in nodeObject.children) {
                  if (index === '0') {
                    eventTarget = el.nextElementSibling;
                  } else {
                    eventTarget = eventTarget.nextElementSibling;
                  }
                  const child = nodeObject.children[index];
                  let customProp = JSON.parse(child.czmObject.customProp);
                  if (that.store.hostDeviceMapById.has(customProp.deviceId)) {
                    let device = that.store.hostDeviceMapById.get(customProp.deviceId);
                    // 设置状态
                    setLabelStatus(device, customProp.labelCode, child.ref, 2);
                  }

                  // 设置图标
                  setIconByRef(child.ref, eventTarget);
                }
              });
            }
            if (nodeObject.czmObject && nodeObject.czmObject.xbsjType == 'Pin') {
              setIconByRef(ref, el);
            }
            // ref不为空并且大于0时 设置为input的id属性
            if (ref && ref.length > 0) {
              inputEl.id = ref;
            }
            // 首次展开添加元素默认为true，显示展示的对象
            if (that.store.nodeCheckedByRef.size <= 0) {
              // item.checkStatus = 'checked'
              inputEl.checked = true;
              //***设置样式为选中 */
              setClassChecked(setClassEl1, setClassEl2, item);
              that.store.nodeCheckedByRef.set(ref, true);
            } else {
              // 之后的展开根据ref获取应该显示的状态是选中还是非选中
              let checked = that.store.nodeCheckedByRef.get(ref);
              if (checked == undefined) {
                checked = true;
                if (ref && ref.length > 0 && ref.startsWith('node_')) {
                  // 分割ref
                  const refSplit = ref.split('_');
                  // 取出真实对象
                  const readyNode = window.$uia.earth.sceneTree.$refs[refSplit[1]];
                  if (readyNode && readyNode.czmObject) {
                    checked = readyNode.czmObject.show;
                  }
                } else {
                  if (nodeObject && nodeObject.czmObject) {
                    checked = nodeObject.czmObject.show;
                  }
                }
                inputEl.checked = checked;
                that.store.nodeCheckedByRef.set(ref, checked);
                setClassEl(setClassEl, setClassEl2, checked, item);
              } else {
                setClassEl(setClassEl, setClassEl2, checked, item);
              }
            }
            // 显示隐藏样式监听
            classMutationObserver(setClassEl1, setClassEl2, that.store.nodeCheckedByRef, ref);
            // input disabled属性监听
            disabledMutationObserver(inputEl);
            /**调整触发顺序，阻止默认的input change事件，并绑定自己的change事件 */
            inputEl.addEventListener(
              'change',
              function (e) {
                // 阻止其他同类型事件调用
                e.stopImmediatePropagation();
                // input元素获取
                const el = e.target;
                // 获取ref
                const ref = el.id;
                // 点击元素的earthSdk对象
                const clickNode = window.$uia.earth.sceneTree.$refs[ref];
                // 真实的earthSdk对象
                let readyNode: any = null;
                // 当ref大于0，并且以node_开头时，此为虚假的对象
                if (ref && ref.length > 0 && ref.startsWith('node_')) {
                  // 分割ref
                  const refSplit = ref.split('_');
                  // 取出真实对象
                  readyNode = window.$uia.earth.sceneTree.$refs[refSplit[1]];
                } else if (ref && ref.length > 0 && ref.startsWith('nodeSecondary_')) {
                  // 分割ref
                  const refSplit = ref.split('_');
                  // 取出真实对象
                  readyNode = window.$uia.earth.sceneTree.$refs[refSplit[1]];
                  let guid = readyNode.czmObject.pinXbsjGuid;
                  let pin = window.$earth.getObject(guid);
                  pin.show = !pin.show;
                } else if (ref && ref.length > 0) {
                  // 真实对象就是本身
                  readyNode = clickNode;
                }
                // 控制子节点的状态同步
                that.showOrHideChild(clickNode, window.$uia, el.checked);
                if (readyNode != null) {
                  // 隐藏对象
                  if (!el.checked) {
                    if (readyNode && readyNode.czmObject) {
                      readyNode.czmObject.show = false;
                    }
                    // 设置属性
                    setClassNoChecked(setClassEl1, setClassEl2, item);
                  } else {
                    // 显示对象
                    if (readyNode && readyNode.czmObject) {
                      readyNode.czmObject.show = true;
                    }
                    // 设置属性
                    setClassChecked(setClassEl1, setClassEl2, item);
                  }
                  // 设置属性
                  setClassNoChecked(setClassEl1, setClassEl2, item);
                } else {
                  // 显示对象
                  if (readyNode && readyNode.czmObject) {
                    readyNode.czmObject.show = true;
                  }
                  // 设置属性
                  setClassChecked(setClassEl1, setClassEl2, item);
                }
                // 记录当前节点状态
                that.store.nodeCheckedByRef.set(ref, el.checked);
              },
              true
            );
          }
        };
        // 创建一个观察器实例并传入回调函数
        const observer1 = new MutationObserver(callback1);
        // 以上述配置开始观察目标节点
        observer1.observe(target1, config1);
        // 设置label的鼠标事件
        labelItems.forEach((itemId) => {
          if (window.$earth.sceneTree.$refs[itemId]) {
            window.$earth.sceneTree.$refs[itemId].czmObject.onmouseover = () => {
              window.$viewer._container.style.cursor = 'pointer';
            };
            window.$earth.sceneTree.$refs[itemId].czmObject.onmouseout = () => {
              window.$viewer._container.style.cursor = 'default';
            };
          }
        });
      });
      // 隐藏图层管理 "地图场景" 一栏
      // document.getElementsByClassName('XbsjVritualTreeItem').item(0).style.display = 'none'
      window.$earth.sceneTree.root.children.splice(1, 0, models);
    }

    listenMittHandler() {
      let that = this;
      {
        $mitt.on('winShow', function (e: any) {
          that.VideoFusionWinShow = e;
        });
        //其他页面调用本页面的methods方法
        $mitt.on('listenMouseHandler', function () {
          listenMouseHandler(that);
        });
        $mitt.on('removeHandler', function () {
          that.removeHandler();
        });
        $mitt.on('createBBHLine', function () {
          that.createBBHLine();
        });
        $mitt.on('createRealTimeObj', function () {
          createRealTimeObj();
        });
        $mitt.on('radioChangeBtnShow', function (callback) {
          that.radioChangeBtnShow(callback);
        });
        $mitt.on('loadingStatus', function () {
          that.loadingStatus();
        });
        $mitt.on('clearAlarmModel', (mittData: any) => {
          let { isWarnEvent, eventSerialNum } = mittData;
          // 清除告警模型
          if (isWarnEvent) {
            // 是告警事件 先去后台查询预警事件获取事件编号
            let url = 'military/msWarnEvent/queryWarnEventDetailList';
            let params = {
              eventSerialNum: eventSerialNum,
            };
            defHttp.get({ url, params }, { isTransformResponse: false }).then((res) => {
              if (res.success) {
                // 成功
                let data = res.result;
                for (const warnEventInfo of data) {
                  this.clearAlarmModel(warnEventInfo.eventSerialNum);
                }
              } else {
                // 失败
                console.log('失败');
                createMessage.error(res.message);
              }
            });
          } else {
            // 不是告警事件,直接清除
            this.clearAlarmModel(eventSerialNum);
          }
        });
        // 监听开关轨迹按钮状态
        $mitt.on('trackAllChange', (data: any) => {
          if (data.type == 'radar') {
            this.isShowRadarTrack = data.status;
          } else if (data.type == 'ais') {
            this.isShowAISTrack = data.status;
          } else {
            this.isShowMixTrack = data.status;
          }
        });
        $mitt.on('shipAllChange', (data: any) => {
          if (data.type == 'radar') {
            this.isShowRadarShip = data.status;
          } else if (data.type == 'ais') {
            this.isShowAISShip = data.status;
          } else {
            this.isShowMixShip = data.status;
          }
        });
        // 监听mqtt消息
        $mitt.on('deviceCmd', (message: any) => {
          let data = JSON.parse(message);
          // 绘制雷达船只
          drawRadarShipsList(data, this.isShowRadarTrack, this.isShowRadarShip);
          // 绘制AIS船只
          drawAISShipsList(data, this.isShowAISTrack, this.isShowAISShip);
          // 绘制融合船只
          drawMixShipsList(data, this.isShowMixTrack, this.isShowMixShip);
        });
      }
    }

    removeHandler() {
      this._handler.removeInputAction(window.Cesium.ScreenSpaceEventType.MOUSE_MOVE); //移除鼠标事件
      this._handler.removeInputAction(window.Cesium.ScreenSpaceEventType.LEFT_CLICK); //移除鼠标事件
    }

    radioChange(e) {
      this.loadingStatus();
      if (`${e.target.value}` == 'satellite') {
        window.$earth.sceneTree.$refs.satellite.czmObject.show = true;
        window.$earth.sceneTree.$refs.vector.czmObject.show = false;
      } else if (`${e.target.value}` == 'vector') {
        window.$earth.sceneTree.$refs.vector.czmObject.show = true;
        window.$earth.sceneTree.$refs.satellite.czmObject.show = false;
      }
    }

    radioChangeBtnShow(callback) {
      this.radioBtnShow = !this.radioBtnShow;
      callback(this.radioBtnShow); //回调返回当前状态
    }

    loadingStatus() {
      this.earthChangeSpin = !this.earthChangeSpin; //加载状态
      setTimeout(() => {
        this.earthChangeSpin = !this.earthChangeSpin; //3秒后去除加载状态
      }, 3000);
    }

    keepAlive() {
      defHttp.get({ url: this.url.keepAlive }, { isTransformResponse: false }).then((res) => {});
    }

    closeClient() {
      chrome.call('close');
    }

    /**
     * 保存更改的ref到模型和后台数据中;
     * @param {Object} model 当前模型
     * @param {string} newRef 新的ref
     * @param {string} oldRef 旧的ref
     */
    changeRef = _.debounce(function (model, newRef, oldRef) {
      // 当数值改变时且旧值不等于空时，更新模型的ref
      if (newRef !== oldRef && oldRef !== '') {
        // 修改后台的数据
        handleNodeType(model)
          .sensor(() => {
            defHttp
              .put(
                {
                  url: this.url.updateSensor + `?eventSerialNum=${oldRef}`,
                  params: { eventSerialNum: newRef },
                },
                { isTransformResponse: false }
              )
              // putAction(this.url.updateSensor + `?eventSerialNum=${oldRef}`, {eventSerialNum: newRef})
              .then((res) => {
                if (res.success) {
                  // 设置保存的 ref
                  this.sceneTreeOldRefValue = '';
                  // 更新模型的名称
                  model.title = newRef;
                  createMessage.success('修改成功');
                } else {
                  createMessage.error('修改失败: ' + res.message);
                }
              })
              .catch((err) => {
                createMessage.error('修改失败: ' + err);
              });
          })
          .modelCallback(() => {
            // 传感器标志线不能修改ref，因为 ref 是后台数据库的ID;
            createMessage.warning('无法修改传感器标志线的ref');
          })
          .run();
      }
    }, 150);

    radarAlarmTimeOutCheck() {
      const now = Date.now();
      const timeout = 5 * 60 * 1000;
      // 遍历报警数据
      this.store.alarmInfoMap.forEach((value, key) => {
        // 获取当前时间与报警时间的时间差
        const timeDiff = now - value.timestamp;
        // 如果时间差大于5分钟，则清除报警
        if (timeDiff > timeout) {
          // 清除报警，有雷达告警则清除雷达告警和雷达轨迹
          this.clearAlarmModel(key);
        }
      });
    }
    clearRadarAlarmModel(radarAlarmDataMap, eventNum) {
      if (radarAlarmDataMap.has(eventNum)) {
        let alarmData = radarAlarmDataMap.get(eventNum);
        for (let target of alarmData.target) {
          let pathModel = target.path;
          let groundImageModel = target.groundImage;
          // 销毁模型
          pathModel && pathModel.destroy();
          groundImageModel && groundImageModel.destroy();
        }
        this.store.radarAlarmDataMap.delete(eventNum);
      }
    }
    clearAlarmModel(eventNum) {
      // let alarmInfoMap = this.store.alarmInfoMap;
      // let radarAlarmDataMap = this.store.radarAlarmDataMap;
      if (this.store.alarmInfoMap.has(eventNum)) {
        let alarmData = this.store.alarmInfoMap.get(eventNum);
        // 清除报警
        alarmData.pin && alarmData.pin._div.remove();
        alarmData.pin && alarmData.pin.destroy();
        alarmData.scanline && alarmData.scanline.destroy();
        this.store.alarmInfoMap.delete(eventNum);
      }
      this.clearRadarAlarmModel(this.store.radarAlarmDataMap, eventNum);
    }

    // 获取当前实时时间
    getRealTime() {
      this.timer2 = setInterval(() => {
        this.realTime = getRealTime();
      }, 1000);
    }
    // 资源销毁
    beforeDestroy() {
      // vue程序销毁时，需要清理相关资源
      console.log('vue程序销毁');

      window.$earth = window.$earth && window.$earth.destroy();
      websocketclose(null);
      //清除定时器
      clearInterval(this.timer);
      clearInterval(this.timer2);
      clearInterval(this.alarmTrackClearTimer);
    }
    // 资源销毁
    destroy() {
      // vue程序销毁时，需要清理相关资源
      console.log('vue程序销毁', window.$earth);

      // websocketclose();
      //清除定时器
      clearInterval(this.timer);
      clearInterval(this.timer2);
      clearInterval(this.alarmTrackClearTimer);
      // window.$uia.tools.sceneTree.destroy()
      // window.$earth = window.$earth && window.$earth.destroy();
      //利用store.xbsjEarthUI 重新赋值 window.XbsjEarthUI
      window.XbsjEarthUI = this.store.xbsjEarthUI;
      window.$earth = undefined;
    }
  }
</script>

<style>
  .xbsj-model-box,
  .detail-model,
  .xbsj-modal-box {
    background: linear-gradient(360deg, rgba(9, 39, 76, 0.9), rgba(9, 39, 76, 0.6)) !important;
    /* border: 1px solid #2c58a6; */
    box-shadow: 0 0 10px #2c58a6;
  }

  .xbsjSceneTreeBox {
    left: initial !important;
    width: 280px !important;
    height: 600px !important;
    right: 0 !important;
    top: 0 !important;
    background: -webkit-linear-gradient(270deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
    background: -o-linear-gradient(270deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
    background: -moz-linear-gradient(270deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
    background: linear-gradient(270deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
    box-shadow: none !important;
  }

  .xbsjSceneTreeBox .xbsj-model-close {
    display: none;
  }

  .xbsjcesium + div {
    background: -webkit-linear-gradient(360deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
    background: -o-linear-gradient(360deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
    background: -moz-linear-gradient(360deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
    background: linear-gradient(360deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
  }

  .distance-legend {
    background: RGBA(9, 39, 76, 0.8);
  }

  /* 标题 */
  .earthUI_header header {
    position: relative;
    top: -3px;
    height: 4rem;
    background: url(../../../assets/earthMap/head_bg.png) no-repeat top center;
    background-size: 100% 90%;
  }

  .earthUI_header p {
    font-family: 'Arial', 'Microsoft YaHei', '黑体', '宋体', sans-serif;
    color: #00ffe4;
    text-align: center;
    margin: 0;
    padding: 0;
  }

  .earthUI_header header > p:first-child {
    font-size: 1.1rem;
    line-height: 28px;
    padding-top: 0.5vh;
    /* 文字间隔 */
    letter-spacing: 5px;
  }

  .earthUI_header header > p:last-child {
    font-family: Microsoft YaHei;
    font-size: 0.8rem;
    font-weight: 400;
    /* 文字间隔 */
    letter-spacing: 0.5px;
  }

  .quitBtn {
    position: relative;
    text-align: center;
    font-size: 12px;
    min-width: 100px;
    width: 120px;
    height: 30px;
    padding: 0 7px;
    margin-left: 100px;
    line-height: 30px;
    border-radius: 100px;
    border: 1px solid #c9c9c9;
    background-color: #fff;
    color: #555;
    cursor: pointer;
    display: none;
  }

  /* 视频窗口 */
  .videos {
    display: none;
    border: 1px solid #080808;
    /*position: fixed;
   right: 0;
  bottom: 2px; */
    position: absolute;
    left: 0;
    top: 0;
    z-index: 100;
    width: 420px;
    height: 380px;
    -webkit-box-shadow: 0px 3px 3px #c8c8c8;
    -moz-box-shadow: 0px 3px 3px #c8c8c8;
    box-shadow: 0px 3px 3px #c8c8c8;
  }

  .vclose {
    position: absolute;
    right: 1%;
    top: 1%;
    border-radius: 100%;
    cursor: pointer;
  }

  .videosSpan1 {
    position: absolute;
    left: 1%;
    top: 1%;
    color: #000;
    font-size: 15px;
    font-weight: bold;
    font-family: 黑体;
    border-radius: 100%;
  }

  .videosSpan2 {
    position: absolute;
    right: 1%;
    bottom: 1%;
    color: #000;
    font-size: 16px;
    font-weight: bold;
    font-family: 黑体;
    border-radius: 100%;
  }

  /* 相机状态点 */
  .successStatus,
  .offlineStatus,
  .errorStatus {
    position: relative;
  }

  .successStatus::before {
    content: ' ';
    position: absolute;
    height: 7px;
    width: 7px;
    top: -60px;
    left: 0;
    /*transform: translateY(-50%);*/
    border-radius: 50%;
    background: rgb(0, 255, 0);
  }

  .offlineStatus::before {
    content: ' ';
    position: absolute;
    height: 7px;
    width: 7px;
    top: -60px;
    left: 0;
    /*transform: translateY(-50%);*/
    border-radius: 50%;
    background: rgb(170, 170, 170);
  }

  .errorStatus::before {
    content: ' ';
    position: absolute;
    height: 7px;
    width: 7px;
    top: -60px;
    left: 0;
    /*transform: translateY(-50%);*/
    border-radius: 50%;
    background: rgb(255, 0, 0);
  }

  /* 相机状态点 */

  /* 电线杆气泡窗 */
  .cameraModal {
    margin: 20px auto;
    position: absolute;
    left: 0;
    top: 0;
    width: auto;
    line-height: 25px;
    color: white;
    text-align: center;
    font-size: 14px;
    border: 1px solid rgb(255, 255, 255);
    opacity: 0.9;
    border-radius: 5px;
    background: rgb(255, 255, 255);
  }

  .cameraModal::after {
    /* 箭头靠下边 */
    content: '';
    position: absolute;
    width: 0;
    height: 0;
    left: 35px;
    bottom: -15px;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-top: 15px solid rgb(255, 255, 255);
  }

  .cameraModal ul {
    margin: 20px;
    padding: 0px;
    list-style: none;
  }

  .cameraModal li {
    float: left;
    list-style-type: none;
    display: inline;
    margin: 5px;
    width: 120px;
    border: 2px solid #fff;
  }

  .cameraModal li:hover {
    border-bottom-color: #00ffe4;
  }

  .cameraModal li > a {
    color: rgb(19, 15, 15);
    text-decoration: none;
    cursor: pointer;
  }

  .cameraModal img {
    width: 80px;
    height: 60px;
    display: block;
    margin: 0 auto;
  }

  .spinning {
    position: absolute;
    left: 50%;
    top: 35%;
    z-index: 999;
  }

  /* 电线杆气泡窗 */

  /* 地标气泡窗 */
  /*.poiModal {
  margin: 20px auto;
  padding: 5px;
  position: absolute;
  left: 0;
  top: 0;
  height: 160px;
  width: 300px;
  color: white;
  text-align: center;
  font-size: 14px;
  border: 1px solid RGBA(12, 177, 177, 0.8);
  border-radius: 5px;
  filter: alpha(opacity=50);
  background: RGBA(12, 177, 177, 0.9);
}

.poiModal::after {
  !* 箭头靠下边 *!
  content: '';
  position: absolute;
  width: 0;
  height: 0;
  left: 140px;
  bottom: -15px;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-top: 15px solid RGBA(12, 177, 177, 0.8);
}

.poiModal-content {
  width: 100%;
  height: 100%;
  box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.2);
  animation-name: modalopen;
  animation-duration: 1s;
}

.poiModal-header h2 {
  margin: 0;
  color: white;
}

.poiModal-header {
  line-height: 40px;
}

.poiModal-body {
  text-align: left;
  font-size: 16px;
  padding-left: 5px;
}

.poiModal-body span {
  color: #ffeb3b;
}*/

  /* 地标气泡窗 */
  /* 地图切换按钮 */
  .radioBtn {
    position: absolute;
    bottom: 40px;
    right: 15px;
  }

  .radioBtn span {
    transition: color 0.3s linear;
  }

  .radioBtn span:hover {
    color: #00ffe4bb !important;
    transition: color 0.3s linear;
  }

  .ant-radio-button-wrapper-checked {
    background: #00ffe4bb !important;
    border-color: #00ffe4 !important;
  }

  .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled)::before {
    background-color: #00ffe4 !important;
  }

  .earthChangeSpin {
    position: absolute;
    left: 45%;
    top: 35%;
  }

  .ant-spin {
    color: #00ffe4;
  }

  .ant-spin-dot-item {
    background-color: #00ffe4;
  }

  /* 地图切换按钮 */
  /* 比例尺和指南针属性 */
  #distanceLegendDiv .distance-legend {
    bottom: 80px !important;
    background-color: rgba(9, 39, 76, 0.7) !important;
  }

  #navigationDiv > div {
    top: unset !important;
    /*去掉已有的top值使bottom生效 */
    bottom: 120px !important;
    right: 40px !important;
  }

  .compass-outer-ring-background {
    border: 12px solid rgba(9, 39, 76, 0.7) !important;
  }

  .compass-gyro-background {
    background-color: rgba(9, 39, 76, 0.7) !important;
  }

  /* 比例尺和指南针属性 */

  body {
    user-select: none;
  }
</style>
