<!-- 
    电子地图    
    -编辑页面
 -->
<template>
  <div>
    <div id="earthContainer" ref="earthContainer" style="width: 100%; height: 100%; top: 300px"></div>
    <div class="earthUI_header">
      <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"></Toolbar>
    <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>
  </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 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 { getRealTime } from "@/utils/date";
  import $mitt from "@/utils/earthMap/mitt";
  import { drawInit } from "@/utils/earthMap/earthDraw"
  import { keyControlInit } from "@/utils/earthMap/keyControlInit"
  import redFlag from '@/assets/earthMap/redFlag.png';
  import { addModel, addPin, addViewShedRadar } from '@/utils/earthMap/earthObj'
  import hidePng from '@/assets/earthMap/hide.png'
  import alarmImg from '@/assets/earthMap/alarm.gif'
  import VideoFusionWin from "./components/VideoFusionWin.vue"

  import circleDot2 from '@/assets/earthMap/circleDot2.png'
  import circleDot1 from '@/assets/earthMap/circleDot1.png'
  import circleDot3 from '@/assets/earthMap/circleDot3.png'

  class HandleNodeType {
    #sn
    #sensorCallback
    #modelCallback
    #markerPositionCallback
    #polylineCallBack
    #default

    constructor(sn) {
      this.#sn = sn
    }

    sensor(callback) {
      this.#sensorCallback = callback
      return this
    }

    // 模型回调
    modelCallback(callback) {
      this.#modelCallback = callback
      return this
    }

    // 微波雷达回调
    markerPosition(callback) {
      this.#markerPositionCallback = callback
      return this
    }

    // 区域回调
    polylineCallBack(callback) {
      this.#polylineCallBack = callback
      return this
    }

    default(callback) {
      this.#default = callback
      return this
    }

    run() {
      // 判断节点的类型
      if (!this.#sn.czmObject) {
        return null
      }
      // 模型类型
      let tempCondition = this.#sn.czmObject.xbsjType
      switch (tempCondition) {
        case 'Model':
          this.#modelCallback ? this.#modelCallback() : this.#default()
          break
        case 'Pin':
          this.#markerPositionCallback ? this.#markerPositionCallback() : this.#default()
          break
        case 'Polyline':
          this.#polylineCallBack ? this.#polylineCallBack() : this.#default()
          break
        default:
          this.#default ? this.#default() : null
      }
    }
  }

  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,
      VideoSplitScreen,
      VideoWindow,
      WarnInfoList,
      AddModelWin,
      AddRoamVideo,
      VideoFusionWin
    },
    props: {},
    // data() {
    //   return {
    //     earthTitle: '态势监控一张图',
    //     realTime: '……',
    //     // 注意：Earth和Cesium的相关变量放在vue中，必须使用下划线作为前缀！
    //     _earth: undefined,
    //     _earthUI: 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: sceneTree,
    //     // areaB: require('@/assets/earthMap/resjson/area_b.json'),
    //     url: {
    //       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: 'checkpoint/msAisInfo/list',
    //       keepAlive: '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: {},
    //     cameraModalShow: false,
    //     poiModalShow: false,
    //     radioBtnShow: true,
    //     glmId: [],

    //     earthChangeSpin: false,
    //     websock: [],
    //     timer: null, // 保活定时器
    //     timer2: null, // 时间定时器
    //     // 报警清除-定时器
    //     alarmTrackClearTimer: null,
    //     videoWindowProps: {
    //       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: 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: null,
    //     node: null,
    //     type: '',
    //     lineId: '',
    //     areaCode: '',
    //     areaByNodeIdModel: '',
    //     el:null,
    //     eidtId: null,
    //     //addroamVideo
    //     addRoamVideoShow: false
    //   };
    // },
  })
  export default class EarthComp extends Vue {
    /**
     * 资源创建
     */
    userStore = useUserStore()
    store = useEarthMapStore()

    earthTitle = '态势监控一张图'
    realTime = '……'
    // 注意：Earth和Cesium的相关变量放在vue中，必须使用下划线作为前缀！
    _earth = undefined
    _earthUI = 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 = []
    ///////////////////////////////////////////////////////////////////////////

    mounted() {
      let that = this
      //随机数
      window.guid = this.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)
          }
        })
      }

      {
        $mitt.on("winShow", function (e: any) {
            that.VideoFusionWinShow = e
        })
        //其他页面调用本页面的methods方法
        $mitt.on('openNotification', (res: any) => {
          // that.openNotification(msg, dt, type, top)
          that.openNotification(res.msg, res.dt, res.type, res.top)
        })
        $mitt.on('listenMouseHandler', function () {
          that.listenMouseHandler()
        })
        $mitt.on('removeHandler', function () {
          that.removeHandler()
        })
        $mitt.on('createBBHLine', function () {
          that.createBBHLine()
        })
        $mitt.on('createRealTimeObj', function () {
          that.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("失败");

                this.$message.error(res.message)
              }
            })
          } else {
            // 不是告警事件,直接清除
            this.clearAlarmModel(eventSerialNum)
          }
        })
      }


    }
    // 随机数
    guid() {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0,
          v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
      });
    }
    // 打开视频融合
      roamPathSet() {
        // 打开视频融合
        this.VideoFusionWinShow = true
        // 关闭相机列表
        this.cameraModalShow = false
    }

    // 控制子元素的显示或者隐藏
    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.nodeCheckedByRef.set(ref, parentChecked);
            this.showOrHideChild(child, earthUI, parentChecked);
          }
        }
      }
    }
    // 告警模型显示/隐藏
    showAlarmPin(show) {
      this.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;
      XbsjEarthUI.create('earthContainer').then(async (earthUI: any) => {
        // 设置全局变量，可调试
        window.$uia = earthUI;
        window.$earth = earthUI.earth;
        earthUI.controls.mainBar.show = false; //隐藏主工具栏
        earthUI.controls.statusBar.show = true; //状态栏
        //图层管理
        let sceneTree = earthUI.tools.sceneTree;
        // 显示图层管理
        sceneTree.show = true;
        // 设置图层管理 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 }) => {
          that.sceneTreePopContextMenu({ item, vueObject }, earthUI);
        };
        earthUI.tools.featureProperty.disabled = true; //禁用对象属性面板

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

        this._viewer = earthUI.earth.czm.viewer;
        // this._viewer.scene.fxaa = true //图像改善
        // this._viewer.scene.globe.baseColor = 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'];
        // this.sceneTree.children.push(this.areaB)

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

        //加载地图实时资源（无人机、车辆、人员、巡逻路线等）
        // this.createRealTimeObj(earthUI)
        //监听鼠标事件
        this.listenMouseHandler(earthUI);
        // 获取部门信息
        await this.getSceneInfo();

        //加载地图线路资源
        await this.createBBHLine(earthUI);

        //飞入地点
        await this.fly();

        //创建工具栏
        // console.log("earthUI",earthUI);

        this.toolbarShow = true
        // window.$flyTo = this.flyTo
        // console.log("window.$flyTo",window);
        // console.log("this.flyTo",this);
        // earthUI.showPropertyWindow(
        //   {
        //     flyTo: this.flyTo,
        //     setLabelStatus: this.setLabelStatus,
        //   },
        //   {
        //     component: Toolbar,
        //   }
        // );

      });
    }
    async fly() {
      let position, rotation, viewDistance, duration;
      //
      let parentData =
        this.sceneInfo instanceof Array
          ? this.sceneInfo.filter((item, index) => {
            return item.sceneCode == "00001-00001";
          })
          : this.sceneInfo;
      //过滤掉总部层级的
      let data = this.sceneInfo instanceof Array ?
        this.sceneInfo.filter((item, index) => {
          return item.sceneCode.length > 3;
        })
        : this.sceneInfo;
      // console.log("data",data);
      // console.log("this.sceneInfo",this.sceneInfo);
      if (data) {
        if (!(data instanceof Array)) {
          // debugger;
          // 各岛礁
          position = [data.lon, data.lat, data.altitude];
          rotation = [data.rotationX, data.rotationY, data.rotationZ];
          viewDistance = data.viewDistance;
          duration = data.duration ? data.duration : 0;
          this._earth.camera.flyTo(position, viewDistance, rotation, duration);
          // 地图复原事件
          window.$flyTo = this.flyTo = () => {
            this._earth.camera.flyTo(position, viewDistance, rotation, duration);
          };
        } else {
          // 总指挥中心
          position = [parentData[0].lon, parentData[0].lat, parentData[0].altitude];
          rotation = [parentData[0].rotationX, parentData[0].rotationY, parentData[0].rotationZ];
          viewDistance = parentData[0].viewDistance;
          duration = parentData[0].duration;
          // 先飞入到能看见红旗
          this._earth.camera.flyTo(position, viewDistance, rotation, duration);
          // 地图复原事件
          window.$flyTo = this.flyTo = () => {
            this._earth.camera.flyTo(position, viewDistance, rotation, duration);
          };
          for (let record of data) {
            if (record.sceneCode.length == 11) {
              continue;
            }
            // 设置红旗
            this.setLoginPoint(record);
          }
        }
      } else {
        // 没权限人员控制
      }
    }

    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 = () => {
        this._viewer._container.style.cursor = 'pointer';
      };
      pin.onmouseout = () => {
        this._viewer._container.style.cursor = 'default';
      };
      pin.onclick = function () {
        this._earth.camera.flyTo(position, viewDistance, rotation, duration);
      };
    }

    async getSceneInfo() {
      // 登录人部门信息
      // const orgCode = Vue.ls.get(USER_INFO).orgCode;
      // const userStore = useUserStore()
      const orgCode = this.userStore.userInfo?.orgCode;
      this.orgCode = orgCode;
      // console.log("orgCode",orgCode);

      // 登录人部门信息长度为3则为总部，否则为岛屿
      if (orgCode.length == 3) {
        // 总部
        await defHttp.get({
          url: '/military/msMapScene/list',
          params: {
            pageNo: 1,
            pageSize: 999,
            sceneCode: "00001-00001*",
            column: 'sysOrgCode',
            order: 'asc',
          }
        }, { isTransformResponse: false }).then((response) => {
          // console.log("response",response);

          const records = response.result.records
          // 设置岛屿信息为数组
          this.sceneInfo = records;
          return records;
        });
      } else {
        await defHttp.get({ url: '/military/msMapScene/queryByOrgCode', params: { orgCode: orgCode } }, { isTransformResponse: false }).then((response) => {

          const data = response.result;
          // 设置岛屿信息为Object
          this.sceneInfo = data;
          return data;
        });
      }
    }

    //设置按钮颜色状态
    setIconByRef(ref, el) {
      const status = this.statusByNodeId.get(ref);
      if (status != undefined && status != null) {
        let img = this.imgByRef.get(ref);
        const icon = el.children[0].children[2];
        if (!img) {
          img = document.createElement('img');
          this.imgByRef.set(ref, img);
        }
        if (icon.nodeName == 'I') {
          icon.replaceWith(img);
        }
        if (status == 1) {
          img.src = circleDot2
        } else if (status == 0) {
          img.src = circleDot1
        } else {
          img.src = circleDot3
        }
        img.setAttribute('style', 'width:16px;height:16px;margin-top:7px');
      }
    }
    /* 使用async/await 处理异步方法顺序执行。成功的操作放到try里，失败的放在catch里 */
    async createBBHLine(earthUI =null) {
      let models: any = null;
      let type = 0;
      if (!(this.sceneInfo instanceof Array)) {
        type = 2;
        models = {
          ref: 'areas',
          expand: true,
          title: '岛礁',
          children: [],
        };
      } else {
        type = 1;
        models = {
          ref: 'main',
          expand: true,
          title: '岛礁',
          children: [],
        };
        for (let record of this.sceneInfo) {
          if (record.parentSceneCode.length == 5) {
            continue;
          }
          models.children.push({
            ref: record.sysOrgCode,
            expand: false,
            title: record.sceneName,
            children: [],
          });
        }
      }
      // console.log('models',models);

      // 加载区域
      // console.log("加载区域");
      await this.getLineInfo(models, type);
      // 加载站点
      // console.log("加载站点");
      await this.getCameraInfo(models, type);
      // 加载雷达和微波
      // console.log("加载雷达和微波");
      const labelItems: any = await this.getLabelInfo(models, type);
      //加载绘画资源
      await drawInit();
      //加载重点监控区域
      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.hostDeviceMapById.has(customProp.deviceId)) {
                    let device = that.hostDeviceMapById.get(customProp.deviceId);
                    // 设置状态
                    that.setLabelStatus(device, customProp.labelCode, child.ref, 2);
                  }

                  // 设置图标
                  that.setIconByRef(child.ref, eventTarget);
                }
              });
            }
            if (nodeObject.czmObject && nodeObject.czmObject.xbsjType == 'Pin') {
              that.setIconByRef(ref, el);
            }
            // ref不为空并且大于0时 设置为input的id属性
            if (ref && ref.length > 0) {
              inputEl.id = ref;
            }
            // 首次展开添加元素默认为true，显示展示的对象
            if (that.nodeCheckedByRef.size <= 0) {
              // item.checkStatus = 'checked'
              inputEl.checked = true;
              //***设置样式为选中 */
              setClassChecked(setClassEl1, setClassEl2, item);
              that.nodeCheckedByRef.set(ref, true);
            } else {
              // 之后的展开根据ref获取应该显示的状态是选中还是非选中
              let checked = that.nodeCheckedByRef.get(ref);
              if (checked == undefined) {
                checked = true;
                if (ref && ref.length > 0 && ref.startsWith('node_')) {
                  // 分割ref
                  const refSplit = ref.split('_');
                  // 取出真实对象
                  const readyNode = earthUI.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.nodeCheckedByRef.set(ref, checked);
                setClassEl(setClassEl, setClassEl2, checked, item);
              } else {
                setClassEl(setClassEl, setClassEl2, checked, item);
              }
            }
            // 显示隐藏样式监听
            classMutationObserver(setClassEl1, setClassEl2, that.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 = earthUI.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 = earthUI.earth.sceneTree.$refs[refSplit[1]];
                } else if (ref && ref.length > 0 && ref.startsWith('nodeSecondary_')) {
                  // 分割ref
                  const refSplit = ref.split('_');
                  // 取出真实对象
                  readyNode = earthUI.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, earthUI, 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.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 = () => {
              this._viewer._container.style.cursor = 'pointer';
            };
            window.$earth.sceneTree.$refs[itemId].czmObject.onmouseout = () => {
              this._viewer._container.style.cursor = 'default';
            };
          }
        });
      });
      // 隐藏图层管理 "地图场景" 一栏
      // document.getElementsByClassName('XbsjVritualTreeItem').item(0).style.display = 'none'
      this._earth.sceneTree.root.children.splice(1, 0, models);
    }

    async createRealTimeObj(earthUI =null) {
      let that = this;
      let models = {
        expand: true,
        title: '地图实况',
        children: [
          {
            expand: false,
            title: '巡逻路线',
            children: [],
          },
          {
            expand: false,
            title: '执勤巡逻',
            children: [],
          },
          {
            expand: false,
            title: '预警/报警',
            children: [],
          },
          {
            expand: false,
            title: 'AIS',
            children: [],
          },
        ],
      };
      try {
        await this.getAllModelInfo(models);
        await this.getPatrolRouteInfo(models);
        //添加对象到场景树
        // this._earth.sceneTree.root.children.push(models);
        this._earth.sceneTree.root.children.splice(1, 0, models);
      } catch (e) {
        console.log(e);
      }
    }

    //加载区域
    getLineInfo(models, type) {
      const that = this;
      // console.log("type",type);

      return new Promise((resolve, reject) => {
        let submitData: any = {
            pageNo: 1,
            pageSize: 99999,
          };

        // 如果进入单位是岛屿，则只加载相关岛屿信息
        if (type == 2) {
          submitData.sysOrgCode = that.orgCode
        }
        //请求线路信息
        defHttp.get({ url: this.url.queryLineList, params: submitData }, { isTransformResponse: false }).then(async (res) => {
          // console.log('res',res);
          if (res.success) {
            //一级区域
            let parentArea: any = []
            //二级区域
            let childArea: any = []
            res.result.records.forEach((data) => {
              if (data.parentCode) {
                childArea.push(data)
              } else {
                parentArea.push(data)
              }
            })
            parentArea.forEach((data) => {
              // data.sysOrgCode
              let updatedPositions: any = []
              let positionsData = JSON.parse(data.positions)
              if (!positionsData) {
                positionsData = []
              }
              updatedPositions = positionsData
              // //地形是否开启
              // if (window.$earth.sceneTree.$refs.terrain.czmObject.show) {
              //   // 设置位置
              //   updatedPositions = positionsData
              // } else {
              //   // 删除高度，只设置经纬度。
              //   positionsData.forEach((item) => updatedPositions.push([item[0], item[1], 0]))
              // }
              let lineOptions: any = {
                maxShowHeight: 30000,
                customProp: data.lineCode,
              }
              lineOptions.name = data.name
              lineOptions.xbsjType = 'Polyline'
              lineOptions.width = data.width
              lineOptions.positions = updatedPositions
              lineOptions.loop = Boolean(data.isLoop)
              lineOptions.depthTest = Boolean(data.isDepthCheck)
              lineOptions.arcType = data.interpolation
              let material: any = {}
              switch (data.materialType) {
                // 实线
                case 0:
                  material.type = 'XbsjColorMaterial'
                  material.XbsjColorMaterial = {}
                  if (!data.color || data.color.length <= 0) {
                    data.color = '[1,1,1,1]'
                  }
                  material.XbsjColorMaterial.color = JSON.parse(data.color)
                  break
                // 虚线
                case 1:
                  material.type = 'XbsjPolylineDashMaterial'
                  material.XbsjPolylineDashMaterial = {}
                  material.XbsjPolylineDashMaterial.color = JSON.parse(data.color)
                  material.XbsjPolylineDashMaterial.gapColor = JSON.parse(data.intervalColor)
                  material.XbsjPolylineDashMaterial.dashLength = data.dashLength
                  material.XbsjPolylineDashMaterial.dashPattern = data.dashStyle
                  break
                // 箭头线
                case 2:
                  material.type = 'XbsjPolylineArrowMaterial'
                  material.XbsjPolylineArrowMaterial = {}
                  material.XbsjPolylineArrowMaterial.color = JSON.parse(data.color)
                  break
                // 轨迹线
                case 3:
                  material.type = 'XbsjODLineMaterial'
                  material.XbsjODLineMaterial = {}
                  material.XbsjODLineMaterial.color = JSON.parse(data.color)
                  material.XbsjODLineMaterial.totoalFrameCount = data.cycleFrame
                  break
              }
              lineOptions.material = material
              let currentChildArea: any = []
              if (childArea.length) {
                childArea.forEach(element => {
                  let obj = {}
                  if (data.id == element.parentCode) {
                    obj = {
                      expand: false,
                      title: element.name,
                      ref: 'nodeSecondary_' + element.id,
                      children: [],
                    }
                    let updatedPositions: any = []
                    let positionsData = JSON.parse(element.positions)
                    if (!positionsData) {
                      positionsData = []
                    }
                    updatedPositions = positionsData
                    let lineOptions: any = {
                      maxShowHeight: 30000,
                      customProp: element.lineCode,
                    }
                    lineOptions.name = element.name
                    lineOptions.xbsjType = 'Polyline'
                    lineOptions.width = element.width
                    lineOptions.positions = updatedPositions
                    lineOptions.loop = Boolean(element.isLoop)
                    lineOptions.depthTest = Boolean(element.isDepthCheck)
                    lineOptions.arcType = element.interpolation
                    let material: any = {}
                    switch (element.materialType) {
                      // 实线
                      case 0:
                        material.type = 'XbsjColorMaterial'
                        material.XbsjColorMaterial = {}
                        if (!element.color || element.color.length <= 0) {
                          element.color = '[1,1,1,1]'
                        }
                        material.XbsjColorMaterial.color = JSON.parse(element.color)
                        break
                      // 虚线
                      case 1:
                        material.type = 'XbsjPolylineDashMaterial'
                        material.XbsjPolylineDashMaterial = {}
                        material.XbsjPolylineDashMaterial.color = JSON.parse(element.color)
                        material.XbsjPolylineDashMaterial.gapColor = JSON.parse(element.intervalColor)
                        material.XbsjPolylineDashMaterial.dashLength = element.dashLength
                        material.XbsjPolylineDashMaterial.dashPattern = element.dashStyle
                        break
                      // 箭头线
                      case 2:
                        material.type = 'XbsjPolylineArrowMaterial'
                        material.XbsjPolylineArrowMaterial = {}
                        material.XbsjPolylineArrowMaterial.color = JSON.parse(element.color)
                        break
                      // 轨迹线
                      case 3:
                        material.type = 'XbsjODLineMaterial'
                        material.XbsjODLineMaterial = {}
                        material.XbsjODLineMaterial.color = JSON.parse(element.color)
                        material.XbsjODLineMaterial.totoalFrameCount = element.cycleFrame
                        break
                    }

                    let pos = [0, 0, 0]
                    positionsData.forEach(element => {
                      pos[0] += element[0]
                      pos[1] += element[1]
                      pos[2] += element[2]
                    });
                    pos[0] = pos[0] / positionsData.length
                    pos[1] = pos[1] / positionsData.length
                    pos[2] = pos[2] / positionsData.length
                    let pinBuilder = {
                      extTextFont: '30px 宋体',
                      extTextPixelOffset: [-40, 10],
                      fillColor: [0, 0.3450980392156863, 1, 0.9],
                      outlineColor: [1, 1, 1, 1],
                      extText: element.name,
                    }
                    let pin = addPin(element.name, hidePng, { position: pos, scale: 0.8, pinBuilder, far: 107374 });
                    lineOptions.pinXbsjGuid = pin.xbsjGuid
                    lineOptions.material = material
                    that._earth.sceneTree.root.children.push({ czmObject: lineOptions, ref: element.id })
                    currentChildArea.push(obj)
                    // 如果是总部
                    if (type == 1) {
                      this.nodeConfigByRef.set('nodeSecondary_' + element.id, obj)
                    }
                  }
                });
              }
              // 如果是总部
              if (type == 1) {
                const childs = models.children
                for (const child of childs) {
                  if (child.ref == data.sysOrgCode) {
                    const node = {
                      ref: 'node_' + data.id,
                      expand: false,
                      title: data.name,
                      children: [
                        {
                          expand: false,
                          title: '监控点位',
                          ref: 'monitor_' + window.guid(),
                          children: [],
                        },
                        {
                          expand: false,
                          title: '雷达点位',
                          ref: 'ldList_' + window.guid(),
                          children: currentChildArea,
                        },
                        {
                          expand: false,
                          title: '微波点位',
                          ref: 'wbList_' + window.guid(),
                          children: [],
                        },
                      ],
                    }
                    child.children.push(node)
                    this.nodeConfigByRef.set(node.ref, node)
                    this.areaByNodeId.set(node.ref, data.sysOrgCode)
                  }
                }
              } else {
                const node = {
                  ref: 'node_' + data.id,
                  expand: false,
                  title: data.name,
                  children: [
                    {
                      expand: false,
                      title: '监控点位',
                      ref: 'monitor_' + window.guid(),
                      children: [],
                    },
                    {
                      expand: false,
                      title: '雷达点位',
                      ref: 'ldList_' + window.guid(),
                      children: currentChildArea,
                    },
                    {
                      expand: false,
                      title: '微波点位',
                      ref: 'wbList_' + window.guid(),
                      children: [],
                    },
                  ],
                }
                models.children.push(node)
                this.areaByNodeId.set(node.ref, data.sysOrgCode)
              }
              that._earth.sceneTree.root.children.push({ czmObject: lineOptions, ref: data.id })
              // models[0].children.push({ ref: 'node_' + data.id, expand: false, title: data.name, children: [] })
              // models.children[0].children.push({ czmObject: lineOptions, ref: data.id })
            })
            //加载二级区域模型
            childArea.forEach((data) => {

            })
            this.$nextTick(() => {
              const divs = $('#earthContainer>div>div>div:nth-child(5)')
                .children('div')
                .eq(1)
                .children()
                .eq(0)
                .children()
                .eq(0)
                .children()
                .each((index, element) => {
                  // const paddingLeft = $(element).children().eq(0).css('padding-left')
                  $(element).css('display', 'none')
                })
            })
            resolve(models)

          }
        });
      });
    }

    getCameraInfo(models, type) {
      return new Promise((resolve, reject) => {
        //请求电线杆信息
        defHttp.get({ url: this.url.queryCameraInfo }, { isTransformResponse: false }).then(async (res) => {
          if (res.success) {
            // console.log("res",res);

            this.setCamera(res.result, models, type);
            this.cameraData = res.result;
            resolve(models);
          }
        });
      });
    }

    async setCamera(res, models, type) {
      //根据经纬度算出该点地形高度
      let posArr: any = [],
        updatedPositions: any = [];
      const that = this;
      //地形是否开启
      if (window.$earth.sceneTree.$refs.terrain.czmObject.show) {
        res.forEach((data, index) => {
          if (data.msCameraSiteList != null) {
            data.msCameraSiteList.forEach((data, index) => {
              posArr.push(window.Cesium.Cartographic.fromDegrees(data.longitude, data.latitude));
            });
          }
        });
        var promise = window.Cesium.sampleTerrainMostDetailed(this._viewer.terrainProvider, posArr);
        updatedPositions = await window.Cesium.when(promise);
      } else {
        res.forEach((data, index) => {
          if (data.msCameraSiteList != null) {
            data.msCameraSiteList.forEach((data, index) => {
              updatedPositions.push(window.Cesium.Cartographic.fromDegrees(data.longitude, data.latitude, 0));
            });
          }
        });
      }
      // console.log("根据经纬度算出该点地形高度",res);
      // console.log("根据经纬度算出该点地形高度",updatedPositions);

      //设置电线杆
      res.forEach((data, index) => {
        let siteConfig: any = null;
        const lineId = data.id;
        let childs: any = null;
        if (type == 2) {
          childs = models.children;
          for (const child of childs) {
            if ('node_' + data.id == child.ref) {
              siteConfig = child.children[0];
            }
          }
        } else {
          const parentNode = that.nodeConfigByRef.get('node_' + data.id);
          if (!parentNode) {
            return;
          }
          childs = parentNode.children;
          siteConfig = childs[0];
        }
        if (!siteConfig) {
          return;
        }
        if (data.msCameraSiteList != null) {
          data.msCameraSiteList.forEach((data, index) => {
            // 判断电线杆状态
            let num = 0;
            if (data.msCameraSettingList != null) {
              data.msCameraSettingList.forEach((data, index) => {
                if (data.status == '3') {
                  //1-在线，2-离线，3-异常
                  num = num + 1;
                }
              });
            }
            let gltfStr;
            if (!data.modelUrl) {
              return;
            }
            let fileInfos = data.modelUrl.split('.');
            if (num == 0) {
              gltfStr = window._CONFIG['domianURL'] + '/sys/common/static/' + fileInfos[0] + '.' + fileInfos[1];
            } else if (num < data.msCameraSettingList.length) {
              let newName = fileInfos[0].substring(0, fileInfos[0].length - 1) + 'R';
              gltfStr = window._CONFIG['domianURL'] + '/sys/common/static/' + newName + '.' + fileInfos[1];
            } else if (num == data.msCameraSettingList.length) {
              let newName = fileInfos[0].substring(0, fileInfos[0].length - 1) + 'Y';
              gltfStr = window._CONFIG['domianURL'] + '/sys/common/static/' + newName + '.' + fileInfos[1];
            }
            const modelConfig = {
              ref: data.id,
              name: lineId,
              czmObject: {
                name: data.sitename,
                xbsjType: 'Model',
                url: gltfStr,
                // "color": [0.52, 0.6, 0.58, 1],
                minimumPixelSize: data.minimumPixelSize,
                // maximumScale: 0.02,
                scale: data.scale,
                xbsjScale: data.xyzScale ? data.xyzScale.split(',') : [1, 1, 1],
                xbsjPosition: [window.Cesium.Math.toRadians(data.longitude), window.Cesium.Math.toRadians(data.latitude), data.height],
                xbsjRotation: [
                  window.Cesium.Math.toRadians(data.yaw),
                  window.Cesium.Math.toRadians(data.pitch),
                  window.Cesium.Math.toRadians(data.roll),
                ],
                viewDistance: 150,
                distanceDisplayCondition: [1.0, 30000.0],
                customProp: data.id,
              },
            };

            window.$earth.sceneTree.root.children.push(modelConfig);
            //鼠标事件
            window.$earth.sceneTree.$refs[data.id].czmObject.onmouseover = () => {
              this._viewer._container.style.cursor = 'pointer';
            };
            window.$earth.sceneTree.$refs[data.id].czmObject.onmouseout = () => {
              this._viewer._container.style.cursor = 'default';
            };

            this.$nextTick(() => {
              const divs = $('#earthContainer>div>div>div:nth-child(5)')
                .children('div')
                .eq(1)
                .children()
                .eq(0)
                .children()
                .eq(0)
                .children()
                .each((index, element) => {
                  $(element).css('display', 'none');
                });
            });
            //加载相机
            let cameraList: any = [];
            if (data.msCameraSettingList) {
              for (let camera of data.msCameraSettingList) {
                let name = camera.cameraName;
                const obj = {
                  ref: 'camera_' + camera.id,
                  expand: false,
                  title: name,
                  czmObject: {
                    name: name,
                    xbsjType: 'Model',
                  },
                };
                // let id = camera.id
                cameraList.push(obj);
                // 默认设置为在线
              }
            }
            // 杆
            const node = {
              ref: 'node_' + data.id,
              title: data.sitename,
              expand: false,
              children: cameraList,
            };
            siteConfig.children.push(node);
          });
        }
      });
    }

    async getLabelInfo(models, type) {
      return new Promise((resolve, reject) => {
        //请求地图标志信息
        defHttp.get({ url: this.url.queryLabelList }, { isTransformResponse: false }).then(async (res) => {
          if (res.success) {
            const labelItems = await this.setLabel(res.result, models, type);
            resolve(labelItems);
          }
        });
      });
    }

    async setLabel(res, models, type) {
      const that = this;
      const args = { pageNo: 1, pageSize: 999 };
      await defHttp.get({ url: this.url.queryDeviceInfoList, params: args }, { isTransformResponse: false })
        .then((reponse) => {
          if (reponse.success) {
            const hostDeviceList = reponse.result.records
            for (const hostDevice of hostDeviceList) {
              that.hostDeviceMapById.set(hostDevice.id, hostDevice);
            }
            return that.hostDeviceMapById;
          }
        })
        .catch(() => {
          throw '获取主机信息错误';
        });
      //根据经纬度算出该点地形高度
      let posArr: any = [],
        updatedPositions: any = [];
      res.forEach((data, index) => {
        updatedPositions.push(window.Cesium.Cartographic.fromDegrees(data.mapLabel.labelLon, data.mapLabel.labelLat, data.mapLabel.labelHeight));
      });
      const labelItems: any = [];
      //设置标志
      res.forEach((data, index) => {
        const item: any = data.mapLabel;
        labelItems.push(item.id);
        const objConfig3 = {
          ref: item.id,
          name: item.lineId,
          czmObject: {
            customProp: '{"labelAttr":' + item.labelAttr + ',"labelCode":"' + item.labelCode + '","deviceId":"' + data.deviceId + '"}',
            name: item.labelName,
            xbsjType: 'Pin',
            imageUrl: window._CONFIG['staticDomainURL'] + '/' + item.labelImgUrl,
            position: [updatedPositions[index].longitude, updatedPositions[index].latitude, Number(item.labelHeight)],
            scale: item.labelAttr == 4 ? 1 : 0.7,
            pinBuilder: {
              extText: item.labelName,
              extTextFont: '30px 楷体',
              extTextPixelOffset: item.labelAttr == 4 ? [30, -20] : [15, -20],
              fillColor: [1, 1, 1, 0.9],
              outlineColor: [0, 0, 0, 0.9],
            },
            far: 25000,
          },
        };
        if (item.labelAttr == 4) {
          that.statusByNodeId.set(item.id, 1);
          that.addLabelNodeToTree(item, models, objConfig3, type);
        } else {
          that.statusByNodeId.set(item.id, -10);
          that.addLabelNodeToTree(item, models, objConfig3, type);
          const device = that.hostDeviceMapById.get(data.deviceId);
          if (device) {
            //参数3 2为查询状态
            that.setLabelStatus(device, item.labelCode, item.id, 2);
          }
        }
      });
      return labelItems;
    }

    addLabelNodeToTree(item, models, objConfig3, type) {
      const that = this;
      if (item.labelAttr == 10) {
        if (type == 2) {
          let childs1 = models.children;
          for (const child of childs1) {
            if ('node_' + item.lineId == child.ref) {
              child.children[2].children.push(objConfig3);
            }
          }
        } else {
          const parentNode = that.nodeConfigByRef.get('node_' + item.lineId);
          if (!parentNode) {
            return;
          }
          let childs2 = parentNode.children;
          childs2[2].children.push(objConfig3);
        }
      } else if (item.labelAttr == 4) {
        if (type == 2) {
          let childs3 = models.children;
          for (const child of childs3) {
            for (const element of child.children[1].children) {
              if ('nodeSecondary_' + item.lineId == element.ref) {
                element.children.push(objConfig3);
              }
            }
          }
        } else {
          const parentNode1 = that.nodeConfigByRef.get('nodeSecondary_' + item.lineId);
          if (!parentNode1) {
            return;
          }
          const childs4 = parentNode1.children;
          childs4.push(objConfig3);
        }
      }
    }

    setLabelStatus(device, labelCode, id, code) {
      const args = {
        device: device,
        code: code, // 命令码：0-撤防 1-布防 2-状态查询 3-其他预留
        deviceType: 2, // 设备类型：1-探测主机 2-探测器 3-串口设备 4-预留
        deviceSn: labelCode, // 设备条码
      };
      // console.log("device",device);

      if (device.deviceType_dictText.indexOf('微波探测器') > -1) {
        // console.log("微波探测器");

        return defHttp.post({ url: '/military/netty/microwaveDetector/maintenance', params: args }, { isTransformResponse: false })
          // postAction('netty/microwaveDetector/maintenance', args)
          .then((response) => {
            // console.log('response',response);

            if (response.success) {
              const status = response;
              this.statusByNodeId.set(id, status);
            } else {
              this.statusByNodeId.set(id, -10);
            }
            return response;
          })
          .catch((error) => {
            // console.log('error',error);
            this.statusByNodeId.set(id, -10);
            return error;
          });
      } else if (device.deviceType_dictText.indexOf('雷达') > -1) {
        this.statusByNodeId.set(id, 1);
        //雷达周界防区列表
        return defHttp.get({ url: this.url.perimeterRegionList, params: { regionType: 2 } }, { isTransformResponse: false })
          .then(
            (res) => {
              // console.log(res);
              if (res.success) {
                // (未测试)
                res.result.forEach((element) => {
                  if (element.id == id) {
                    // this.statusByNodeId.set(id, element.isOnline)
                  }
                });
              } else {
                this.statusByNodeId.set(id, 1);
              }
              return res;
            },
            (err) => {
              this.statusByNodeId.set(id, 1);
              return err;
            }
          )
          .catch((err) => {
            this.statusByNodeId.set(id, 1);
            return err;
          });
      }

    }

    getAllModelInfo(models) {
      return new Promise((resolve, reject) => {
        //模型位置

        defHttp.get({ url: this.url.queryAllModelInfo }, { isTransformResponse: false }).then(async (res) => {
          if (res.success) {
            res.result.forEach((data, index) => {
              let childrenConfig: any = {},
                objConfig: any = {},
                pathConfig: any = {},
                viewshedConfig: any = {},
                pinConfig: any = {};
              let positions: any = [],
                rotations: any = [];
              switch (data.modelType) {
                case 1: //无人机
                  childrenConfig = {
                    expand: false,
                    title: '无人机_' + (index + 1) + '号',
                    children: [],
                  };
                  objConfig = {
                    ref: data.eventSerialNum,
                    czmObject: {
                      name: '无人机',
                      xbsjType: 'Model',
                      url: window._CONFIG['staticDomainURL'] + '/uav.gltf',
                      minimumPixelSize: 1000,
                      maximumScale: 20,
                      xbsjPosition: earthUtils.degreeToRadianInLngLatHeight(data.lon, data.lat, data.height),
                      distanceDisplayCondition: [10.0, 25000.0],
                    },
                  };
                  childrenConfig.children.push(objConfig);
                  // 加载视域
                  viewshedConfig = {
                    ref: 'viewshed_' + data.eventSerialNum,
                    czmObject: {
                      xbsjType: 'Viewshed',
                      name: '视域',
                      position: earthUtils.degreeToRadianInLngLatHeight(data.lon, data.lat, data.height),
                      rotation: earthUtils.degreeToRadianInLngLatHeight(data.yaw, data.pitch, data.roll),
                      near: 1.0,
                      far: 1500,
                      enabled: false,
                      show: false,
                    },
                  };
                  childrenConfig.children.push(viewshedConfig);
                  //加载历史轨迹
                  data.msModelTrajectoryList.forEach((data, index) => {
                    positions.push(earthUtils.degreeToRadianInLngLatHeight(data.lon, data.lat, data.height));
                    rotations.push(earthUtils.degreeToRadianInLngLatHeight(data.yaw, data.pitch, data.roll));
                  });
                  pathConfig = {
                    ref: 'path_' + data.eventSerialNum,
                    czmObject: {
                      xbsjType: 'Path',
                      name: '轨迹',
                      positions: positions,
                      rotations: rotations,
                      enabled: false,
                      show: true,
                      loop: false,
                      showDirection: false,
                      playing: true,
                      loopPlay: true,
                      alwaysAlongThePath: true,
                      currentSpeed: 30,
                    },
                  };
                  childrenConfig.children.push(pathConfig);
                  /* // 显示当前坐标
                    pinConfig = {
                      "ref": "pin_" + data.eventSerialNum,
                      "czmObject": {
                        "xbsjType": "Pin",
                        "name": "当前位置",
                        "position": earthUtils.degreeToRadianInLngLatHeight(data.lon, data.lat, data.height),
                        "evalString": "const width = 430;\nconst height = 70;\nfunction createLabelCanvas(p) {\n  if (p._labelDiv) {\n    p._earth.czm.viewer.container.removeChild(p._labelDiv);\n    p._labelDiv = undefined;\n  }\n  const labelDiv = document.createElement('div');\n  labelDiv.style = 'width:'+width+'px;height: '+height+'px;position: absolute; pointer-events: none;'\n\n  p._earth.czm.viewer.container.appendChild(labelDiv);\n  p._labelDiv = labelDiv;\n\n  var dis = XE.MVVM.watch(() => {\n    labelDiv.style.display = p.enabled ? 'block' : 'none';\n  });\n\n  p.disposers.push(() => {\n    if (p._labelDiv) {\n      p._earth.czm.viewer.container.removeChild(p._labelDiv);\n      p._labelDiv = undefined;\n    }\n    dis();\n  });\n\n  const labelCanvas = document.createElement('canvas');\n  labelCanvas.style = 'width: 100%;height: 100%;';\n\n  labelCanvas.width = width;\n  labelCanvas.height = height;\n  labelDiv.appendChild(labelCanvas);\n  return labelCanvas;\n}\n\nfunction createDrawFunc(p) {\n  const labelCanvas = createLabelCanvas(p);\n  const ctx = labelCanvas.getContext('2d');\n\n  function draw(w) {\n    ctx.clearRect(0, 0, width, height);\n\n    ctx.save();\n    ctx.lineWidth = 2;\n    ctx.strokeStyle = 'rgb(31, 255,255)';\n    ctx.beginPath();\n    ctx.moveTo(width, height);\n    ctx.lineTo(width-height, 22);\n    ctx.lineTo(0, 22);\n    ctx.stroke();\n    ctx.restore();\n    ctx.font = \"15px console\"; \n    ctx.fillStyle = 'rgb(255, 255, 0)';\n    ctx.fillText('" +
                          "经度：" + data.lon + "/" + "纬度：" + data.lat + "/" + "高度：" + data.height + "', 0, 20);\n    ctx.restore();\n  }\n\n  p._dDraw = draw;\n}\n\ncreateDrawFunc(p);\n\nlet d = 0;\nlet c = 0;\np._dDraw(c);\nconst preUpdateListener = p._earth.czm.scene.preUpdate.addEventListener(() => {\n  if (d !== c) {\n    c += (d - c) * 0.1;\n    if (Math.abs(c - d) < 0.1) {\n      c = d;\n    }\n    p._dDraw(c);\n  }\n});\np.disposers.push(() => preUpdateListener && preUpdateListener());\n\nconst container = p._earth.czm.viewer.container;\nconst unwatch = XE.MVVM.watch(() => [...p.winPos], winPos => {\n  if (p._labelDiv) {\n    p._labelDiv.style.left = (winPos[0] -  p._labelDiv.clientWidth) + 'px';\n    p._labelDiv.style.bottom = winPos[3]+'px';\n  } \n});\np.disposers.push(() => {\n  unwatch && unwatch();\n});",
                        "isDivImage": true,
                        "pinBuilder": {},
                        "far": 25000
                      }
                    };
                    childrenConfig.children.push(pinConfig); */
                  //加入树
                  models.children[1].children.push(childrenConfig);
                  break;
                case 2: //执勤人员
                  childrenConfig = {
                    expand: false,
                    title: '执勤人员_' + (index + 1) + '号',
                    children: [],
                  };
                  objConfig = {
                    ref: data.eventSerialNum,
                    czmObject: {
                      xbsjType: 'GroundImage',
                      name: '执勤人员',
                      playing: true,
                      width: 90,
                      height: 90,
                      position: earthUtils.degreeToRadianInLngLatHeight(data.lon, data.lat, 0),
                      imageUrls: [window._CONFIG['staticDomainURL'] + '/xunluo_point1.png', window._CONFIG['staticDomainURL'] + '/xunluo_point2.png'],
                    },
                  };
                  childrenConfig.children.push(objConfig);
                  //加载历史轨迹
                  data.msModelTrajectoryList.forEach((data, index) => {
                    positions.push(earthUtils.degreeToRadianInLngLatHeight(data.lon, data.lat, data.height));
                    rotations.push(earthUtils.degreeToRadianInLngLatHeight(data.yaw, data.pitch, data.roll));
                  });
                  pathConfig = {
                    ref: 'path_' + data.eventSerialNum,
                    czmObject: {
                      xbsjType: 'Path',
                      name: '轨迹',
                      positions: positions,
                      rotations: rotations,
                      enabled: false,
                      show: true,
                      loop: false,
                      showDirection: false,
                      playing: true,
                      loopPlay: true,
                      alwaysAlongThePath: true,
                      currentSpeed: 30,
                    },
                  };
                  childrenConfig.children.push(pathConfig);
                  //加入树
                  models.children[1].children.push(childrenConfig);
                  break;
                case 3: //可疑人员
                  childrenConfig = {
                    expand: false,
                    title: '可疑人员_' + (index + 1) + '号',
                    children: [],
                  };
                  objConfig = {
                    ref: data.eventSerialNum,
                    czmObject: {
                      xbsjType: 'GroundImage',
                      name: '可疑人员',
                      playing: true,
                      width: 90,
                      height: 90,
                      position: earthUtils.degreeToRadianInLngLatHeight(data.lon, data.lat, 0),
                      imageUrls: [window._CONFIG['staticDomainURL'] + '/keyi_point1.png', window._CONFIG['staticDomainURL'] + '/keyi_point2.png'],
                    },
                  };
                  childrenConfig.children.push(objConfig);
                  //加载历史轨迹
                  data.msModelTrajectoryList.forEach((data, index) => {
                    positions.push(earthUtils.degreeToRadianInLngLatHeight(data.lon, data.lat, data.height));
                    rotations.push(earthUtils.degreeToRadianInLngLatHeight(data.yaw, data.pitch, data.roll));
                  });
                  pathConfig = {
                    ref: 'path_' + data.eventSerialNum,
                    czmObject: {
                      xbsjType: 'Path',
                      name: '轨迹',
                      positions: positions,
                      rotations: rotations,
                      enabled: false,
                      show: true,
                      loop: false,
                      showDirection: false,
                      playing: true,
                      loopPlay: true,
                      alwaysAlongThePath: true,
                      currentSpeed: 30,
                    },
                  };
                  childrenConfig.children.push(pathConfig);
                  //加入树
                  models.children[2].children.push(childrenConfig);
                  break;
                case 11: //传感器
                  objConfig = {
                    ref: data.eventSerialNum,
                    czmObject: {
                      name: data.eventSerialNum,
                      xbsjType: 'Model',
                      url: window._CONFIG['staticDomainURL'] + '/zalan.gltf',
                      minimumPixelSize: 1000,
                      maximumScale: 0.01,
                      // xbsjPosition: [window.Cesium.Math.toRadians(data.lon), window.Cesium.Math.toRadians(data.lat), data.height],
                      xbsjPosition: earthUtils.degreeToRadianInLngLatHeight(data.lon, data.lat, data.height),
                      xbsjRotation: earthUtils.degreeToRadianInLngLatHeight(data.yaw, data.pitch, data.roll),
                      distanceDisplayCondition: [10.0, 25000.0],
                      customProp: data.eventSerialNum,
                      color: [0.08235294117647059, 1, 0, 1],
                      luminanceAtZenith: 2,
                    },
                  };
                  //加入树
                  models.children[0].children[0].children.push(objConfig);
                  break;
                default:
              }
            });
            resolve(models);
          }
        });
      });
    }

    getPatrolRouteInfo(models) {
      return new Promise((resolve, reject) => {
        //执勤巡逻路线
        defHttp.get({ url: this.url.queryPatrolRouteInfo }, { isTransformResponse: false }).then(async (res) => {
          if (res.success) {
            res.result.forEach((data, index) => {
              //将路线上的点拼成坐标数组
              let positions: any = [];
              data.msLineConstList.forEach((data, index) => {
                positions.push(earthUtils.degreeToRadianInLngLatHeight(data.lon, data.lat, data.height));
              });
              const objConfig = {
                ref: data.lineCode,
                czmObject: {
                  name: data.lineName,
                  xbsjType: 'Polyline',
                  width: 2,
                  material: {
                    type: 'XbsjODLineMaterial',
                    XbsjODLineMaterial: {
                      bgColor: [0.5, 0.5, 0.5, 1],
                      color: [0, 1, 0.11, 1],
                      totoalFrameCount: 200,
                    },
                  },
                  positions: positions,
                },
              };
              models.children[0].children.push(objConfig);
            });
            resolve(models);
          }
        });
      });
    }

    listenMouseHandler(earthUI =null) {
      let that: any = this;
      this._handler = new window.Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas);

      //取消双击旋转事件
      this._viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
        window.Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
      );
      /* MOUSE事件（有性能问题，慎用！） */

      /* 鼠标左键事件 */
      {
        this._handler.setInputAction((click: any) => {
          if (typeof this._pin !== 'undefined') {
            // 销毁指示线
            this._pin.destroy();
          }

          let pickedFeature = this._viewer.scene.pick(click.position);
          if (pickedFeature && pickedFeature.id) {
            if (pickedFeature.id.xbsjType && pickedFeature.id.xbsjType === 'Model') {
              //点击电线杆触发弹窗
              this.cameraData.forEach((data) => {
                if (!$.isEmptyObject(data.msCameraSiteList)) {
                  if (!data.msCameraSiteList) {
                    return;
                  }
                  data.msCameraSiteList.forEach((data) => {
                    if (pickedFeature.id.customProp === data.id) {
                      if ($('.cameraModal ul').length > 0) {
                        $('.cameraModal ul').remove();
                      }
                      $('.cameraModal').append('<ul></ul>');
                      if (!data.msCameraSettingList) return;
                      // 将监控相机列表传入弹窗组件中
                      this.cameraList = data.msCameraSettingList
                      // 将监控点位置传入弹窗组件中
                      this.monitorPosition = pickedFeature.id._primitive.xbsjPosition
                      data.msCameraSettingList.forEach((data, index) => {
                        let camera_img =
                          data.type == '4'
                            ? window._CONFIG['staticDomainURL'] + '/qiuji.png'
                            : data.type == '3'
                              ? window._CONFIG['staticDomainURL'] + '/qiangji.png'
                              : window._CONFIG['staticDomainURL'] + '/qiangji.png';
                        let cameraStatus = data.status == '1' ? 'successStatus' : data.status == '2' ? 'offlineStatus' : 'errorStatus';
                        let rtspUrl = data.cameraCode;
                        // 'rtsp://' + data.user + ':' + data.password + '@' + data.ip + window._CONFIG['cameraMain']
                        $('.cameraModal ul').append(
                          '<li><a class="openIframe" id="' +
                          data.id +
                          '" videoUrl="' +
                          rtspUrl +
                          '" cameraIP="' +
                          data.ip +
                          '" cameraUser="' +
                          data.user +
                          '" cameraPsd="' +
                          data.password +
                          '"><img src="' +
                          camera_img +
                          '" /><div class="' +
                          cameraStatus +
                          '">' +
                          data.cameraName +
                          '</div> </a></li>'
                        );
                      });
                      cameraModal.style.left = click.position.x + -45 + 'px';
                      cameraModal.style.top = click.position.y + -180 + 'px';
                      this.cameraModalShow = true;
                    }
                  });
                }
              });
            }
            //雷达扫描范围
            if (
              pickedFeature.id._xbsjOwner &&
              pickedFeature.id._xbsjOwner.customProp &&
              JSON.parse(pickedFeature.id._xbsjOwner.customProp).labelAttr == '4'
            ) {
              let labelCode = JSON.parse(pickedFeature.id._xbsjOwner.customProp).labelCode;
              console.log(pickedFeature.id._xbsjOwner);
              if (pickedFeature.id._xbsjOwner.addViewShedReturn) {
                pickedFeature.id._xbsjOwner.addViewShedReturn.show = !pickedFeature.id._xbsjOwner.addViewShedReturn.show;
              } else {
                defHttp.get({ url: this.url.radarList, params: { radarCode: labelCode } }, { isTransformResponse: false }).then((res) => {
                  if (res.success) {
                    if (res.result.records.length > 0) {
                      let data = res.result.records[0];
                      let rgb;
                      if (data.customProp) {
                        rgb = JSON.parse(data.customProp).color;
                      }
                      let radarRadius = data.workingRadius;
                      let radarRange = data.elevation;
                      let radarShifting = data.angularRadian;
                      let left = Number(radarShifting) - Number(radarRange) / 2;
                      //参数：经纬度、半径、起始角度（正北方向）、结束角度
                      pickedFeature.id._xbsjOwner.addViewShedReturn = addViewShedRadar(
                        pickedFeature.id._xbsjOwner.position,
                        radarRadius,
                        left,
                        Number(radarRange) / 2 + Number(radarShifting),
                        [rgb.r / 255, rgb.g / 255, rgb.b / 255, rgb.a]
                      );
                    }
                  }
                });
              }
            }
          } else {
            //关闭所有气泡窗
            that.cameraModalShow = false;
            that.poiModalShow = false;
          }
          console.debug('点击到的模型', pickedFeature);
        }, window.Cesium.ScreenSpaceEventType.LEFT_CLICK);
      }
      /* 鼠标右键事件 */
      {
        this._handler.setInputAction((click) => {
          // 判断点击位置是否有实体
          //返回具有 `primitive` 属性的对象，该属性包含场景中特定窗口坐标处的第一个（顶部）图元，如果该位置没有任何内容，则返回未定义的对象。其他属性可能会根据基元的类型进行设置，并可用于进一步识别拾取的对象。
          let pickedFeature = this._viewer.scene.pick(click.position);
          // console.log("pick",pickedFeature);

          let entity = pickedFeature && pickedFeature.id;
          console.log("pick",pickedFeature);
          console.log("entity", entity);
          if (entity == undefined) {
            return;
          }
          if (typeof pickedFeature !== 'undefined' && pickedFeature.id.xbsjType == 'Model') {
            //点击电线杆触发弹窗
            this.cameraData.forEach((data) => {
              if (!$.isEmptyObject(data.msCameraSiteList)) {
                if (!data.msCameraSettingList) {
                  return;
                }
                data.msCameraSiteList.forEach((data) => {
                  if (pickedFeature.id.customProp === data.id) {
                    window.$uia.contextMenu.pop([
                      {
                        text: '监控视域分析属性',
                        func: () => {
                          let testConfig = {
                            ref: 'testView',
                            name: '雷达视域分析',
                            position: [1.514482876761954, 0.8497520519403554, -0.7553906497788317],
                            rotation: [4.535844766941594, 0.32288591161895097, 0],
                            near: 1,
                            far: 400,
                            fovH: Math.PI / 3,
                            fovV: Math.PI / 6,
                            show: false,
                          };
                          let Viewshed = new window.XE.Obj.Viewshed(window.$earth);
                          Viewshed.xbsjFromJSON(testConfig);
                          window.$uia.showPropertyWindow(Viewshed);
                        },
                      },
                    ]);
                  }
                });
              }
            });
          }
          //巡检监控视频
          else if (typeof pickedFeature !== 'undefined' && entity._name == '视频图元') {
            // console.log(pickedFeature)
            // console.log("entity",entity)
            window.$uia.contextMenu.pop([
              {
                text: '编辑',
                func: () => {
                  $mitt.emit('addRoamPathVideoClose');
                  // store.commit('customPrimitive', entity.xbsjGuid);
                  this.store.customPrimitive = entity.xbsjGuid
                  // 打开对应的创建巡检视频窗口
                  this.$nextTick(() => {
                    this.addRoamVideoShow = true
                  })
                  // window.$uia.showPropertyWindow(
                  //   {},
                  //   {
                  //     component: addroamVideo,
                  //   }
                  // );

                },
              },
              {
                text: '删除',
                func: () => {
                  window.$uia.confirm('确认删除?', () => {
                    // console.log('confirmed')

                    // axios({
                    //   method: 'delete',
                    //   url: '/military/msAreaCustomPrimitive/delete',
                    //   params: { id: entity.id },
                    // })
                    defHttp.delete({
                      url: '/military/msAreaCustomPrimitive/delete',
                      params: { id: entity.id },
                    }, { isTransformResponse: false, joinParamsToUrl: true })
                      .then((response) => {
                        if (response.code == 200) {
                          let customPrimitiveList = this.store.customPrimitiveList;
                          // console.log("a",customPrimitiveList);
                          customPrimitiveList.forEach((element, index) => {
                            const model = window.$earth.getObject(element);
                            // console.log("model.id",model.id);
                            // console.log("entity.id",entity.id);
                            if (model.id == entity.id) {
                              let customPrimitive = customPrimitiveList.splice(index, 1)[0];
                              model.destroy();
                            }
                          });
                          // store.dispatch('asyncCustomPrimitive', customPrimitiveList);
                          this.store.customPrimitiveList = customPrimitiveList

                          // notification.close("RoamVideoSet");
                          // sessionStorage.setItem("RoamVideoSet", "false");
                        } else {
                          // Msg.error('删除失败');
                          $mitt.emit('openNotification', { msg: '删除失败', dt: 2, type: 'error', top: '50px' })
                          console.error('删除失败', response);
                        }
                      })
                      .catch((res) => {
                        console.error('错误', res);
                      });
                  });
                },
              },
            ]);
          }
          //绘画图形
          else if (typeof pickedFeature !== 'undefined' && entity.name == '绘画') {
            // console.log("entity", entity);
            window.$uia.contextMenu.pop([
              {
                text: '编辑',
                func: () => {
                  window.$uia.showPropertyWindow(entity)
                  //记录编辑前信息
                  let oldEntity = ({
                    depthTest: entity.depthTest, //深度检测
                    color: [...entity.color], //颜色
                    outline: {
                      color: [...entity.outline.color], //边框颜色
                      show: entity.outline.show, //边框显示
                      width : entity.outline.width, //边框宽度

                    },
                    positions: [...entity.positions]
                  })
                  this.$nextTick(() => {
                    // 主要ui窗口
                    const mainUI = window.$uia._vm.$refs.mainUI
                    // 所有打开的ui窗口Ref值
                    const windowsAttrList = Object.keys(mainUI.$refs)
                    // 寻找当前窗体的工具对象
                    const modelToolKey = windowsAttrList.filter((f) => f.indexOf(entity.guid) > -1)[0]
                    const modelTool = mainUI.$refs[modelToolKey][0]
                    // 当前窗体的元素
                    const el = modelTool.$el
                    // this.cloneEl(el)
                    // 样式
                    el.style.width = '380px' //宽度
                    el.children[2].style.padding = '0px'
                    el.children[2].style.transition = 'none'
                    el.children[2].children[0].children[0].style.minWidth = '370px'
                    // 关闭名称input
                    el.children[2].children[0].children[0].children[0].style.display = 'none';
                    // 关闭创建按钮
                    el.children[2].children[0].children[0].children[1].children[0].children[1].style.display = 'none';
                    // 关闭贴地
                    el.children[2].children[0].children[0].children[2].children[0].style.display = 'none';
                    // 关闭拉伸
                    el.children[2].children[0].children[0].children[3].children[0].style.display = 'none';
                    el.children[2].children[0].children[0].children[3].children[1].style.display = 'none';
                    el.children[2].children[0].children[0].children[3].children[2].style.display = 'none';
                    el.children[2].children[0].children[0].children[3].children[3].style.marginLeft = '8px';
                    // 右上角关闭
                    const cancelTopRightBtn = el.children[1].children[1]
                    // 取消按钮元素
                    const cancelBtn = el.children[3].children[0]
                    // 确认按钮元素
                    const okBtn = el.children[3].children[1]
                    // 取消按钮
                    cancelTopRightBtn.onclick = cancelBtn.onclick = function () {
                      //恢复原来设置
                      // console.log("oldEntity", oldEntity);
                      // console.log("entity", entity);
                      // entity.xbsjFromJSON(oldEntity)
                      // entity = JSON.parse(oldEntity)
                      entity.depthTest= oldEntity.depthTest
                      entity.color= oldEntity.color
                      entity.outline= oldEntity.outline
                      entity.positions= oldEntity.positions
                      entity.editing= false
                    }
                    okBtn.onclick = function () {
                      let params = {
                        id: entity.customProp?.id,
                        drawData: JSON.stringify(entity),
                      }
                      // console.log("submit", entity);
                      defHttp.post({
                        url: '/military/dtMapDraw/edit',
                        params: params
                      }, { isTransformResponse: false }).then((response) => {
                        $mitt.emit('openNotification', { msg: '编辑成功', dt: 2, type: 'success', top: '50px' })
                        // console.error('编辑成功', response);
                      }).catch((response) => {
                        $mitt.emit('openNotification', { msg: '编辑失败', dt: 2, type: 'error', top: '50px' })
                        // console.error('删除失败', response);
                      })
                    }

                  })

                },
              },
              {
                text: '删除',
                func: () => {
                  window.$uia.confirm('确认删除?', () => {
                    defHttp.delete({
                      url: '/military/dtMapDraw/delete',
                      params: { id: entity.customProp?.id },
                    }, { isTransformResponse: false, joinParamsToUrl: true })
                      .then((response) => {
                        if (response.code == 200) {
                          let shapeList = this.store.shapeList;
                          shapeList.forEach((element, index) => {
                            const model = window.$earth.getObject(element);
                            if (model.id == entity.customProp?.id) {
                              let shape = shapeList.splice(index, 1)[0];
                              model.destroy();
                            }
                          });
                          this.store.shapeList = shapeList
                        } else {
                          $mitt.emit('openNotification', { msg: '删除失败', dt: 2, type: 'error', top: '50px' })
                          console.error('删除失败', response);
                        }
                      })
                      .catch((res) => {
                        console.error('错误', res);
                      });
                  });
                },
              },
            ]);

          }
        }, window.Cesium.ScreenSpaceEventType.RIGHT_CLICK); //右键事件
      }
      /* picked事件 */
      {
        /* let canvasbox = this._viewer.canvas, pickPosition = {}, cameraModal = this.$refs.cameraModal;//操作cameraModal组件
          canvasbox.onclick = e => {
            pickPosition.x = e.offsetX;
            pickPosition.y = e.offsetY;
            var picked = this._viewer.scene.pick(pickPosition);
            console.log("picked", picked);
            if (picked !== undefined && picked.id !== undefined) {
              console.log(e)
            } else {
              that.cameraModalShow = false;
            }
          } */
      }
    }

    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');
    }

    /* websocket-start */
    initWebSocket(configName) {
      if ('WebSocket' in window) {
        let url = '';
        switch (configName) {
          case 'domianURL': //接收后台模型数据
            // WebSocket与普通的请求所用协议有所不同，ws等同于http，wss等同于https
            // const userStore = useUserStore()
            // const orgCode = userStore.userInfo?.orgCode;
            // let userId = store.getters.userInfo.id;
            let userId = this.userStore.userInfo?.id;
            url = window._CONFIG[configName].replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
            // url = 'ws://127.0.0.1:5004'
            this.websock[configName] = new WebSocket(url);
            this.websock[configName].onopen = this.websocketonopen;
            this.websock[configName].onerror = this.websocketonerror;
            this.websock[configName].onmessage = this.websocketonmessage;
            this.websock[configName].onclose = this.websocketclose;
            break;
          case 'clientURL': //调用客户端监控视频窗口
            url = window._CONFIG['clientURL'];
            this.websock[configName] = new WebSocket(url);
            this.websock[configName].onopen = this.websocketonopen;
            this.websock[configName].onerror = this.websocketonerror;
            this.websock[configName].onclose = this.websocketclose;
            break;
          default:
            console.log('websocket初始化失败');
        }
        // console.log('url', url)
      } else {
        console.log('当前浏览器不支持websocket，请更换浏览器！');
      }
    }
    websocketonopen(e) {
      console.log('WebSocket连接成功');
    }
    websocketonerror(e) {
      console.log('WebSocket连接发生错误');
    }
    loreadAlarmInfo = _.debounce((url, eventSerialNum) => {
      defHttp.get({
        url: url,
        params: eventSerialNum,
      }, { isTransformResponse: false })
        // getAction(url, {eventSerialNum: eventSerialNum})
        .then(res => {
          if (!res.success) {
            console.log("重新发送websocket报警数据失败!")
          } else {
            console.log("重新发送websocket报警数据成功!")
          }
        })
    }, 2000, { maxWait: 3000, trailing: true })
    async websocketonmessage(e) {
      //接收后端数据
      var data = eval('(' + e.data + ')')
      const cesium = window.Cesium
      // Cesium Math
      const math = cesium.Math
      // earth
      const earth = window.$earth
      //处理订阅信息
      if (data.cmd == 'new_warn_info') {
        //有新增的预警信息
        //1.调起客户端窗体
        // chrome.call("formactive");
        //2.若警示界面打开着，则刷新列表
        if ($('.infoList').css('visibility') == 'visible') {
          $mitt.emit('getWarnData')
        }
        //3.弹出监控窗口或围栏信息
        if (data.msgTxt != undefined && data.dealStatus == 1) {
          $mitt.emit('listenerVideoNum', data.msgTxt)
          //显示报警位置
          window.$earth.sceneTree.$refs[data.labelCode].czmObject.color = [1, 0.09803921568627451, 0, 1]
        } else if (data.msgTxt != undefined && data.dealStatus == 3) {
          this.$notification.open({
            key: 'fenceInfo',
            message: '围栏信息通知',
            description: data.msgTxt + '！',
            duration: 0,
          })
        } else if (data.dealStatus == 2) {
          //消除单个报警位置
          window.$earth.sceneTree.$refs[data.labelCode].czmObject.color = [0.08235294117647059, 1, 0, 1]
        } else if (data.dealStatus == 0) {
          //消除所有报警位置
          window.$earth.sceneTree.$refs.sensor.children.forEach((data, index) => {
            data.czmObject.color = [0.08235294117647059, 1, 0, 1]
          })
        }

        //4.提示音
        if (data.dealStatus !== 2 && data.dealStatus !== 0) {
          await this.$refs.audio.play()
          setTimeout(() => {
            this.$refs.audio.pause() //N秒后暂停播放
          }, data.alarmNum * 1000)
        }
      } else if (
        data.cmd == 'new_microwave_warn_info' ||
        data.cmd == 'new_radar_warn_info' ||
        data.cmd == 'new_video_warn_info'
      ) {
        if (this.alarmInfoMap.has(data.serialNum)) {
          return
        }
        const evalString = `
                if(p._div){
                  return
                }
                let left=p.winPos[0];
                let bottom=p.winPos[3];
                const div = document.createElement('div');
                div.style="position: absolute;left:"+left+"px;bottom:"+bottom+"px "
                const img = document.createElement('img');
                img.src="${alarmImg}";
                img.style="width:60px;height:60px"
                div.appendChild(img);
                div.onclick=()=>{
                  p.flyTo()
                }
                p._div = div;
                const root=document.getElementById('earthContainer');
                root.appendChild(div);
                XE.MVVM.watch(p.winPos,() => {
                  left=p.winPos[0]-30;
                  bottom=p.winPos[3];
                  div.style="position: absolute;left:"+left+"px;bottom:"+bottom+"px "
              })
          `;
        const pinConfig = {
          name: 'Pin1',
          xbsjType: 'Pin',
          position: [math.toRadians(data.lon), math.toRadians(data.lat), 0],
          evalString: evalString,
          // imageUrl: alarmImg,
          isDivImage: true,
          show: false,
          far: 3000,
        }
        // scanline
        const scanlineConfig = {
          name: 'AlarmScanline',
          xbsjType: 'Scanline',
          position: [math.toRadians(data.lon), math.toRadians(data.lat), 0],
          playing: true,
          radius: 30,
          timeDuration: 0.5,
          color: [1, 0, 0, 1],
          show: false,
        }
        const pin = new window.XE.Obj.Pin(window.$earth)
        const scanline = new window.XE.Obj.Scanline(window.$earth)
        //1、获取到世界坐标
        let start = cesium.Cartesian3.fromDegrees(data.lon, data.lat, 0);
        let height = await window.$earth.czm.viewer.scene
          .clampToHeightMostDetailed([start])
          .then(function (clampedCartesians) {
            //2、获取到经纬高度
            let ellipsoid = window.$earth.czm.viewer.scene.globe.ellipsoid;
            let cartographic = ellipsoid.cartesianToCartographic(clampedCartesians[0]);
            return cartographic.height;
          });
        if (height > 0) {
          pinConfig.position[2] = height;
        } else if (window.$earth.sceneTree.$refs.terrain.czmObject.show) {
          height = await cesium.sampleTerrainMostDetailed(earth._viewer.terrainProvider, [start]).then((updatedPositions) => {
            return updatedPositions[0].height ? updatedPositions[0].height : 0;
          })
          pinConfig.position[2] = height;
        } else {
          pinConfig.position[2] = 0;
        }

        // 保存报警类型到对象上
        let customProp = {};
        customProp.alarmType = data.cmd
        pinConfig.customProp = JSON.stringify(customProp);
        scanlineConfig.customProp = JSON.stringify(customProp);
        pin.xbsjFromJSON(pinConfig)
        scanline.xbsjFromJSON(scanlineConfig)
        // 判断现在相机的高度来显示报警相关模型
        if (this._earth.camera.position[2] < 100) {
          // 隐藏 pin, 显示 scanline
          pin._div.hidden = true
          scanline.show = true
        } else {
          // 隐藏 scanline, 显示 pin
          pin._div.hidden = false
          scanline.show = false
        }
        scanline.flyTo()
        this.alarmInfoMap.set(data.serialNum, { pin: pin, scanline: scanline, timestamp: Date.now() })
        //报警弹窗
        this.videoWindowProps.title = `实时报警窗口（${data.cameraName}）`
        this.videoWindowProps.videoUrl = data.cameraCode//相机编码
        this.videoWindowProps.isAlarm = true
        this.videoWindowProps.visible = true
        this.videoWindowProps.playRecord = false

        this.videoWindowProps.warnEvent.happenTime = data.happenTime
        this.videoWindowProps.warnEvent.happenLoc = `${Number(data.lon).toFixed(6)},${Number(data.lat).toFixed(6)}`
        this.videoWindowProps.warnEvent.warnNum = 1
        this.videoWindowProps.warnEvent.warnLevel = filterDictTextByCache('ms_warn_level', data.warnLevel)
        this.videoWindowProps.warnEvent.warnType = filterDictTextByCache('ms_warn_type', data.warnType)
        this.videoWindowProps.warnEvent.warnContent = data.warnContent

        //若警示界面打开着，则刷新列表
        if ($('.infoList').css('visibility') == 'visible') {
          $mitt.emit('getWarnData')
        }

        //提示音
        await this.$refs.audio.play()
        setTimeout(() => {
          this.$refs.audio.pause() //N秒后暂停播放
        }, 3 * 1000)

      } else if (data.cmd == 'earthMap_model_realtime_info') {
        console.log(data)
        console.log(this.radarAlarmDataMap)
        // 雷达轨迹报警数据
        const alarmContent = data.content;

        if (this.radarAlarmDataMap.has(data.eventSerialNum)) {
          // 存在雷达报警数据
          let radarAlarmData = this.radarAlarmDataMap.get(data.eventSerialNum);
          let targetMap = radarAlarmData.target;
          if (targetMap.has(data.modelId)) {
            // 存在目标数据
            let targetData = targetMap.get(data.modelId);
            let pathModel = targetData.path;
            let groundImageModel = targetData.groundImage;
            //更新目标数据
            // 更新报警数据
            let positionRadian = earthUtils.degreeToRadianInLngLatHeight(alarmContent.lon, alarmContent.lat, 0);
            // 更新路径
            pathModel.positions.push(positionRadian);
            groundImageModel.position = positionRadian;
            if (pathModel.positions.length > 1) {
              pathModel.show = true;
              groundImageModel.show = true;
            }
          } else {
            // 不存在目标数据
            // 创建目标数据
            let positionRadian = earthUtils.degreeToRadianInLngLatHeight(alarmContent.lon, alarmContent.lat, 0);
            // 路径
            let pathModel = new window.XE.Obj.Path(window.$earth);
            let pathConfig = {
              name: 'path',
              xbsjType: 'Path',
              positions: [positionRadian],
              loop: false,
              playing: true,
              width: 2,
              color: [1, 0, 0, 1],
              show: false,
              showDirection: false,
              currentSpeed: 30,
              alwaysAlongThePath: true,
              material: {
                type: 'Color',
                color: [1, 0, 0, 1],
              },
            }
            pathModel.xbsjFromJSON(pathConfig);
            // 地面图片
            let groundImageModel = new window.XE.Obj.GroundImage(window.$earth);
            let imageUrls: any = []
            if (data.mainTarget) {
              imageUrls.push(window._CONFIG['staticDomainURL'] + '/keyi_point1.png')
              imageUrls.push(window._CONFIG['staticDomainURL'] + '/keyi_point2.png')
            } else {
              imageUrls.push(window._CONFIG['staticDomainURL'] + '/keyi_point3.png')
              imageUrls.push(window._CONFIG['staticDomainURL'] + '/keyi_point4.png')
            }
            let groundImageConfig = {
              name: 'groundImage',
              xbsjType: 'GroundImage',
              position: positionRadian,
              width: 3,
              height: 3,
              playing: true,
              imageUrls: imageUrls,
              show: false,
            }
            groundImageModel.xbsjFromJSON(groundImageConfig);
            // 保存目标数据
            let targetData = {
              path: pathModel,
              groundImage: groundImageModel,
            }
            targetMap.set(data.modelId, targetData);
          }
          // 更新时间
          const updateTime = Date.now();
          radarAlarmData.timestamp = updateTime;
          // 更新 pin 的时间
          let alarm = this.alarmInfoMap.get(data.eventSerialNum)
          if (alarm) {
            alarm.timestamp = updateTime
          }
        } else {
          // 不存在报警数据
          // 路径
          let pathModel = new window.XE.Obj.Path(window.$earth);
          let pathConfig = {
            name: 'path',
            xbsjType: 'Path',
            positions: [earthUtils.degreeToRadianInLngLatHeight(alarmContent.lon, alarmContent.lat, 0)],
            loop: false,
            playing: true,
            width: 2,
            color: [1, 0, 0, 1],
            show: false,
            showDirection: false,
            currentSpeed: 30,
            alwaysAlongThePath: true,
            material: {
              type: 'Color',
              color: [1, 0, 0, 1],
            },
          };
          // 地面图片
          let groundImage = new window.XE.Obj.GroundImage(window.$earth);
          let imageUrls: any = []
          if (data.mainTarget) {
            imageUrls.push(window._CONFIG['staticDomainURL'] + '/keyi_point1.png')
            imageUrls.push(window._CONFIG['staticDomainURL'] + '/keyi_point2.png')
          } else {
            imageUrls.push(window._CONFIG['staticDomainURL'] + '/keyi_point3.png')
            imageUrls.push(window._CONFIG['staticDomainURL'] + '/keyi_point4.png')
          }
          let groundImageConfig = {
            name: 'groundImage',
            xbsjType: 'GroundImage',
            playing: true,
            width: 3,
            height: 3,
            position: earthUtils.degreeToRadianInLngLatHeight(alarmContent.lon, alarmContent.lat, 0),
            imageUrls: imageUrls,
            show: false,
          };
          // 创建路径
          groundImage.xbsjFromJSON(groundImageConfig);
          // 创建地面图片
          pathModel.xbsjFromJSON(pathConfig);

          // 保存数据到map中
          let target = {
            path: pathModel,
            groundImage: groundImage,
            mainTarget: alarmContent.mainTarget,
          }
          let targetMap = new Map();
          targetMap.set(data.modelId, target);
          this.radarAlarmDataMap.set(data.eventSerialNum, {
            target: targetMap,
            timestamp: Date.now(),
          });

          if (!this.alarmInfoMap.has(data.eventSerialNum)) {
            // 不存在告警信息(小灯或扫描线)时发送
            // 事件编号到后台使其重新发送websocket报警数据
            await new Promise(r => setTimeout(r, 500));
            if (!this.alarmInfoMap.has(data.eventSerialNum)) {
              console.log('发送websocket报警数据')
              this.loreadAlarmInfo(this.url.sendRadarAlarmByWebSocket, data.eventSerialNum);
            }
          }
        }
        if (this.videoWindowProps.visible) {
          this.videoWindowProps.warnEvent.warnNum = this.radarAlarmDataMap.get(data.eventSerialNum).target.size;
        }
        // console.debug('雷达轨迹报警数据', this.radarAlarmDataMap);
      } else if (data.cmd == '') {
        earth.sceneTree.$refs[data.eventSerialNum].destroy()
      } else if (data.cmd == 'eventPublish') {
        window.getEventData()
      }
    }
    websocketclose(e) {
      console.log('connection closed (' + e.code + ')')
      this.openNotification('websocket连接已断开', 3, 'warning')
    }
    websocketdosend(configName) {
      //发送数据
      this.spinning = !this.spinning //加载状态
      console.log('this.websock[configName]', this.websock[configName])
      let that = this
      let message = {
        topic: 'Show_Single_Video',
        msg: '192.168.1.65',
      }
      //readyState：0:正在连接中，1:已建立连接，2:连接正在关闭，3:连接已关闭或连接失败
      if (that.websock[configName].readyState == 1) {
        that.websock[configName].send(JSON.stringify(message))
        that.spinning = !that.spinning //加载状态
        console.log('已发送')
      } else {
        //重新连接websocket
        this.initWebSocket('clientURL')
        setTimeout(function () {
          if (that.websock[configName].readyState == 1) {
            that.websock[configName].send(JSON.stringify(message))
          }
          that.spinning = !that.spinning //加载状态
        }, 3000)
      }
    }
    /* websocket-end */
    openNotification(msg, dt = 2, type = 'info', top = '300px') {
      // console.log("openNotification收到");
      // console.log("proxy",this);
      // console.log("window",window);
      // debugger
      this.$message.config({
        top: top,
        duration: dt,
        maxCount: 3,
      })
      switch (type) {
        case 'info':
          this.$message.info(msg)
          break
        case 'success':
          this.$message.success(msg)
          break
        case 'error':
          this.$message.error(msg)
          break
        case 'warning':
          this.$message.warning(msg)
          break
        default:
      }
    }
    getRandomArr(arr, count) {
      //从数组随机抽取元素
      var shuffled = arr.slice(0),
        i = arr.length,
        min = i - count,
        temp,
        index
      while (i-- > min) {
        //打乱数组
        index = Math.floor((i + 1) * Math.random())
        temp = shuffled[index]
        shuffled[index] = shuffled[i]
        shuffled[i] = temp
      }
      return shuffled.slice(min)
    }
    // 根据经纬度获取高度
    async getHeigthByLonLat(lon = 88.8296258, lat = 27.4061859) {
      var positions = [window.Cesium.Cartographic.fromDegrees(lon, lat)]
      // var promise = Cesium.sampleTerrain(this._viewer.terrainProvider, 13, positions);
      var promise = window.Cesium.sampleTerrainMostDetailed(this._viewer.terrainProvider, positions)
      return new Promise((resolve, reject) => {
        window.Cesium.when(promise, function (updatedPositions) {
          // updatedPositions[0].height ? updatedPositions[0].height : 0;
          resolve(updatedPositions)
        })
      })
      /* var terCartographic = new Cesium.Cartographic(1.5503694435245020004000376611976, 0.47832817936864542131039019315313, 0)
      var terHigh = this._viewer.scene.globe.getHeight(terCartographic);
      return terHigh; */
    }
    cloneModel(modelObject) {
      if (modelObject.czmObject.xbsjType === 'Model') {
        const modelConfig = {
          ref: '',
          name: modelObject.name,
          czmObject: {
            name: modelObject.czmObject.name,
            xbsjType: modelObject.czmObject.xbsjType,
            url: modelObject.czmObject.url,
            // "color": [0.52, 0.6, 0.58, 1],
            minimumPixelSize: modelObject.czmObject.minimumPixelSize,
            // maximumScale: 0.02,
            scale: modelObject.czmObject.scale,
            xbsjScale: [...modelObject.czmObject.xbsjScale],
            xbsjPosition: [...modelObject.czmObject.xbsjPosition],
            xbsjRotation: [...modelObject.czmObject.xbsjRotation],
            viewDistance: 150,
            distanceDisplayCondition: [1.0, 30000.0],
          },
        }
        const index = modelObject.parent.children.push(modelConfig)
        return index
        // const model = new window.XE.Obj.Model(window.$earth)
        // model.xbsjFromJSON(modelConfig)
        // const leaf = new window.XE.SceneTree.Leaf(model)
        // window.$earth.sceneTree.root.push(leaf)
      } else {
        const objConfig3 = {
          ref: '',
          name: modelObject.name,
          czmObject: {
            customProp: modelObject.czmObject.customProp,
            name: modelObject.czmObject.name,
            xbsjType: modelObject.czmObject.xbsjType,
            imageUrl: modelObject.czmObject.imageUrl,
            position: [...modelObject.czmObject.position],
            scale: modelObject.czmObject.scale,
            pinBuilder: {
              extText: modelObject.czmObject.pinBuilder.extText,
              extTextFont: '30px 楷体',
              extTextPixelOffset: [30, -20],
              fillColor: [1, 1, 1, 0.9],
              outlineColor: [0, 0, 0, 0.9],
            },
            far: 1073741824,
          },
        }
        const index = modelObject.parent.children.push(objConfig3)
        return index
      }

      // return model
    }
    cloneShamNode(oldRef, id, title) {
      const shamNode = window.$earth.sceneTree.$refs['node_' + oldRef]
      const newShamNode = {
        ref: 'node_' + id,
        title: title,
        expand: false,
        children: [],
      }
      // that.currentModel = response.result
      shamNode.parent.children.push(newShamNode)
    }
    getAreaCode(item) {
      const currentRef = item._inner.sn.ref
      if (!this.areaByNodeId.has(currentRef)) {
        if (item.parent) {
          return this.getAreaCode(item.parent)
        }
      } else {
        return this.areaByNodeId.get(currentRef)
      }
    }
    setAllLabelStatus(selectRef, item, wbUnifiedResponse) {
      const that = this
      //监控点
      if (selectRef.startsWith('monitor')) {
        let grandsons: any = []
        const childs = item.children
        for (const child of childs) {
          const grandson1 = child.children
          if (grandson1 && grandson1.length > 0) {
            grandsons = grandsons.concat(grandson1)
          }
        }
        for (const grandson of grandsons) {
          const xbsjObject = grandson._inner.sn
          const ref = xbsjObject.ref
          if (ref.startsWith('camera_')) {
            const state = that.statusByNodeId.get(ref)
            if (state == 1) {
              that.statusByNodeId.set(ref, 0)
              const img = that.imgByRef.get(ref)
              img.src = require('@/assets/earthMap/circleDot1.png')
            } else if (state == 0) {
              that.statusByNodeId.set(ref, 1)
              const img = that.imgByRef.get(ref)
              img.src = require('@/assets/earthMap/circleDot1.png')
            }
          }
        }
      }
      //微波
      else if (selectRef.startsWith('wbList')) {
        const parentNode = item.parent
        let areaCode = null
        if (parentNode) {
          const falseNodeRef = item.parent._inner.sn.ref
          const nodeRef = falseNodeRef.split('_')[1]
          const trueNode = window.$earth.sceneTree.$refs[nodeRef]
          areaCode = trueNode.czmObject.customProp
        }
        const childs1 = item.children
        if (!childs1 || childs1.length < 0) {
          return
        }
        const length = childs1.length
        let index = -1
        for (const child of childs1) {
          index++
          let xbsjObject = child._inner.sn
          let jsonObj = JSON.parse(xbsjObject.czmObject.customProp)
          let deviceId = jsonObj.deviceId
          let device = that.hostDeviceMapById.get(deviceId)
          if (!device) {
            console.error('主机设备为null')
            continue
          }
          const args = {
            device: device,
            isDefence: wbUnifiedResponse,
            defenceArea: areaCode,
            detectorList: null,
          }
          defHttp.post({
            url: this.url.setDefenseArea,
            params: args
          }, { isTransformResponse: false })
            // postAction(this.url.setDefenseArea, args)
            .then((response) => {
              if (!response.success) {
                return
              } else {
                for (let i = index; i < length; i++) {
                  const child1 = childs1[i]
                  const xbsjObject1 = child1._inner.sn
                  const ref1 = xbsjObject1.ref
                  if (ref1 && ref1.length > 0) {
                    const state1 = that.statusByNodeId.get(ref1)
                    if (state1 == 0 && wbUnifiedResponse) {
                      that.statusByNodeId.set(ref1, 1)
                      const img1 = that.imgByRef.get(ref1)
                      if (!img1) return
                      img1.src = require('@/assets/earthMap/circleDot2.png')
                    } else if (state1 == 1 && !wbUnifiedResponse) {
                      that.statusByNodeId.set(ref1, 0)
                      const img1 = that.imgByRef.get(ref1)
                      if (!img1) return
                      img1.src = require('@/assets/earthMap/circleDot1.png')
                    }
                  }
                }
              }
              console.log(response)
            })
          break
        }
      } else if (selectRef.startsWith("nodeSecondary")) {
        const childs1 = item.children
        if (!childs1 || childs1.length < 0) {
          return
        }
        for (const child of childs1) {
          let xbsjObject = child._inner.sn
          let jsonObj = JSON.parse(xbsjObject.czmObject.customProp)
          let deviceId = jsonObj.deviceId
          let device = that.hostDeviceMapById.get(deviceId)
          if (!device) {
            console.error('主机设备为null')
            continue
          }
          let regionIdList: any = []
          if (item.children.length > 0) {
            item.children.forEach(element => {
              regionIdList.push(element._inner.sn.ref)
            });
          }
          const args = {
            "regionIdList": regionIdList, // 周界防区区域ID列表（雷达设备列表的ID）
            "regionStatus": wbUnifiedResponse ? 1 : 0, // 布防状态 0 - 未布防 1 - 布防
            "defenceRule": { // 布防规则
              "startTime": "yyyy-MM-dd HH:mm:ss", // 布防开始时间 每日循环情况下只包含时分秒，格式："HH:mm:ss" 非每日循环情况下包含年月日、时分秒，格式："yyyy-MM-dd HH:mm:ss"
              "endTime": "yyyy-MM-dd HH:mm:ss", // 布防结束时间 每日循环情况下只包含时分秒，格式："HH:mm:ss" 非每日循环情况下包含年月日、时分秒，格式："yyyy-MM-dd HH:mm:ss"
              "dailyCycle": true // 每日循环布防 true - 是 false - 否
            }
          }
          // putAction(this.url.perimeterControl,{})
          console.log(device, that.statusByNodeId, xbsjObject);
          let ref1 = xbsjObject.ref
          let state1 = that.statusByNodeId.get(ref1)
          //一键布防撤防测试使用
          if (wbUnifiedResponse) {
            state1 = 0
          } else {
            state1 = 1
          }
          if (state1 == 0 && wbUnifiedResponse) {
            that.statusByNodeId.set(ref1, 1)
            const img1 = that.imgByRef.get(ref1)
            if (!img1) return
            img1.src = require('@/assets/earthMap/circleDot2.png')
          } else if (state1 == 1 && !wbUnifiedResponse) {
            that.statusByNodeId.set(ref1, 0)
            const img1 = that.imgByRef.get(ref1)
            if (!img1) return
            console.log(img1);
            img1.src = require('@/assets/earthMap/circleDot1.png')
          }
          //   break
        }

      }
    }

    // 图层管理-模型右键菜单
    sceneTreePopContextMenu({ item, vueObject }, earthUI) {
      let that: any = this
      let earth = window.$earth
      let XE = window.XE
      let sceneTree = earthUI.tools.sceneTree
      let sceneTreeComp = sceneTree._comp
      // 转换方法
      let transform = window.Cesium.Math
      //右键之后设置当前 node
      item._inner.sn.isSelected = true
      const el = vueObject.$el
      let baseItems = [
        {
          text: '克隆',
          keys: '',
          func: () => {
            let sn: any = null
            if (item._inner.sn.ref.startsWith('node_')) {
              const objectId = item._inner.sn.ref.split('_')[1]
              sn = earth.sceneTree.$refs[objectId]
            } else {
              sn = item._inner.sn
            }
            if (sn) {
              let newSn: any = null
              let newSnData: any = null
              let index = 0
              if (sn.czmObject.xbsjType !== 'Polyline') {
                index = that.cloneModel(sn)
                newSn = sn.parent.children[index - 1]
                newSnData = newSn.czmObject
                if (newSnData.xbsjType === 'Model') {
                  that.$nextTick(() => {
                    const divs = $('#earthContainer>div>div>div:nth-child(5)')
                      .children('div')
                      .eq(1)
                      .children()
                      .eq(0)
                      .children()
                      .eq(0)
                      .children()
                      .each((index, element) => {
                        if (index <= 1) {
                          return
                        }
                        const paddingLeft = $(element).children().eq(0).css('padding-left')
                        if (paddingLeft === '10px') {
                          $(element).css('display', 'none')
                        }
                      })
                  })
                }
              }
              // 保存数据到数据库中
              that
                .handleNodeType(sn)
                // 传感器
                .sensor(() => {
                  // debugger
                  // 设置 ref 属性 防止数据库中 eventSerialNum 重复
                  newSn.ref += '_copy'
                  // 发送请求 保存到数据库中
                  let saveSensorModelParameter = {
                    eventSerialNum: newSn.ref,
                    lon: transform.toDegrees(newSnData.xbsjPosition[0]).toFixed(5),
                    lat: transform.toDegrees(newSnData.xbsjPosition[1]).toFixed(5),
                    height: newSnData.xbsjPosition[2].toFixed(2),
                    yaw: transform.toDegrees(newSnData.xbsjRotation[0]).toFixed(2),
                    pitch: transform.toDegrees(newSnData.xbsjRotation[1]).toFixed(2),
                    roll: transform.toDegrees(newSnData.xbsjRotation[2]).toFixed(2),
                    isShow: 1,
                    modelType: '11',
                    eventType: 1,
                  }
                  defHttp.post({
                    url: this.url.SaveSensorModel,
                    params: saveSensorModelParameter
                  }, { isTransformResponse: false })
                    // postAction(this.url.SaveSensorModel, saveSensorModelParameter)
                    .then((res) => {
                      if (res.success) {
                        that.$message.success('克隆成功')
                      } else {
                        newSn.parent.children.splice(index, 1)
                        that.$message.error('克隆失败: ', res.message ? res.message : '')
                      }
                    })
                })
                // 标志点 微波雷达回调
                .markerPosition(() => {
                  // debugger
                  newSn.title += '_copy'
                  let pinImage = newSnData.imageUrl
                  const staticDomainURL = window._CONFIG['staticDomainURL'] + '/'
                  // 去除 image 地址中的 staticDomainURL 链接
                  let imageUri = pinImage.substring(
                    pinImage.indexOf(staticDomainURL) + staticDomainURL.length,
                    pinImage.length
                  )
                  const jsonObj = JSON.parse(newSnData.customProp)
                  const labelAttr = jsonObj.labelAttr
                  let savePinModelParameter = {
                    mapLabel: {
                      labelName: newSnData.name,
                      labelLon: transform.toDegrees(newSnData.position[0]).toFixed(5),
                      labelLat: transform.toDegrees(newSnData.position[1]).toFixed(5),
                      labelHeight: newSnData.position[2].toFixed(2),
                      labelImgUrl: imageUri,
                      // 1 启用， 0 禁用
                      labelStatus: 1,
                      // 标记属性-> 3: 标记位置
                      labelAttr: labelAttr,
                      labelCode: '',
                      lineId: newSn.name,
                    },
                    deviceId: jsonObj.deviceId,
                  }
                  defHttp.post({
                    url: this.url.saveMapLabel,
                    params: savePinModelParameter
                  }, { isTransformResponse: false })
                    // postAction(this.url.saveMapLabel, savePinModelParameter)
                    .then((res) => {
                      if (res.success) {
                        // 修改 ref 成 数据库返回的 id
                        newSn.ref = res.result
                        that.setIconByRef(newSn.ref, newSn.ref);
                        newSn.czmObject.pinBuilder.extText = newSnData.name
                        jsonObj.labelCode = ''
                        newSn.czmObject.customProp = JSON.stringify(jsonObj)
                        // 保存成功
                        that.$message.success('克隆成功')
                      } else {
                        newSn.parent.children.splice(index, 1)
                        that.$message.error('克隆失败: ', res.message ? res.message : '')
                      }
                    })
                    .catch((err) => {
                      newSn.parent.children.splice(index, 1)
                      that.$message.error('克隆失败')
                    })
                })
                //区域回调
                .polylineCallBack(() => {
                  // debugger
                  const currentModel = new window.XE.Obj.Polyline(window.$earth)
                  const submitData: any = {}
                  const poistions = sn.czmObject.positions
                  if (poistions.length <= 0) {
                    return
                  }
                  submitData.name = sn.czmObject.name + '_copy'
                  submitData.lineCode = currentModel.guid
                  submitData.isLoop = Number(sn.czmObject.loop)
                  submitData.isDepthCheck = Number(sn.czmObject.depthTest)
                  submitData.width = sn.czmObject.width
                  submitData.interpolation = sn.czmObject.arcType
                  submitData.positions = JSON.stringify(poistions)
                  switch (sn.czmObject.material.type) {
                    // 实线
                    case 'XbsjColorMaterial':
                      submitData.materialType = 0
                      submitData.color = JSON.stringify(sn.czmObject.material.XbsjColorMaterial.color)
                      submitData.intervalColor = null
                      submitData.dashLength = 0
                      submitData.dashStyle = 0
                      break
                    // 虚线
                    case 'XbsjPolylineDashMaterial':
                      submitData.materialType = 1
                      submitData.color = JSON.stringify(sn.czmObject.material.XbsjPolylineDashMaterial.color)
                      submitData.intervalColor = JSON.stringify(sn.czmObject.material.XbsjPolylineDashMaterial.gapColor)
                      submitData.dashLength = sn.czmObject.material.XbsjPolylineDashMaterial.dashLength
                      submitData.dashStyle = sn.czmObject.material.XbsjPolylineDashMaterial.dashPattern
                      break
                    // 箭头线
                    case 'XbsjPolylineArrowMaterial':
                      submitData.materialType = 2
                      submitData.color = JSON.stringify(sn.czmObject.material.XbsjPolylineArrowMaterial.color)
                      submitData.intervalColor = null
                      submitData.dashLength = 0
                      submitData.dashStyle = 0
                      break
                    // 轨迹线
                    case 'XbsjODLineMaterial':
                      submitData.materialType = 3
                      submitData.color = JSON.stringify(sn.czmObject.material.XbsjODLineMaterial.color)
                      submitData.intervalColor = null
                      submitData.dashLength = 0
                      submitData.dashStyle = 0
                      submitData.cycleFrame = sn.czmObject.material.XbsjODLineMaterial.totoalFrameCount
                      break
                  }
                  defHttp.post({
                    url: this.url.saveMapLine,
                    params: submitData
                  }, { isTransformResponse: false })
                    // postAction(this.url.saveMapLine, submitData)
                    .then((response) => {
                      if (response.success) {
                        currentModel.name = submitData.name
                        currentModel.loop = submitData.isLoop
                        currentModel.depthTest = submitData.isDepthCheck
                        currentModel.width = submitData.width
                        currentModel.arcType = submitData.interpolation
                        currentModel.positions = JSON.parse(submitData.positions)
                        switch (sn.czmObject.material.type) {
                          // 实线
                          case 'XbsjColorMaterial':
                            currentModel.material.type = 'XbsjColorMaterial'
                            currentModel.material.color = submitData.color
                            break
                          // 虚线
                          case 'XbsjPolylineDashMaterial':
                            currentModel.material.type = 'XbsjPolylineDashMaterial'
                            currentModel.material.color = submitData.color
                            currentModel.material.XbsjPolylineDashMaterial.gapColor = submitData.intervalColor
                            currentModel.material.XbsjPolylineDashMaterial.dashLength = submitData.dashLength
                            currentModel.material.XbsjPolylineDashMaterial.dashPattern = submitData.dashStyle
                            break
                          // 箭头线
                          case 'XbsjPolylineArrowMaterial':
                            currentModel.material.type = 'XbsjPolylineArrowMaterial'
                            currentModel.material.XbsjPolylineArrowMaterial.color = submitData.color
                            break
                          // 轨迹线
                          case 'XbsjODLineMaterial':
                            currentModel.material.type = 'XbsjODLineMaterial'
                            currentModel.material.XbsjODLineMaterial.color = submitData.color
                            currentModel.material.XbsjODLineMaterial.totoalFrameCount = submitData.cycleFrame
                            break
                        }
                        const leaf = new XE.SceneTree.Leaf(currentModel)
                        leaf.ref = response.result
                        sn.parent.children.push(leaf)
                      } else {
                        throw '克隆区域数据出错'
                      }
                    })
                    .catch((e) => {
                      currentModel.destroy()
                      // $mitt.emit('openNotification', '克隆区域数据出错', 2, 'error', '50px')
                      $mitt.emit('openNotification', { msg: '克隆区域数据出错', dt: 2, type: 'error', top: '50px' })

                    })
                })
                //监控点
                .modelCallback(() => {
                  this.$message.warning('监控点不支持克隆')
                })
                .run()
            }
          },
        },
        {
          text: '删除',
          keys: '',
          func: () => {
            earthUI.confirm('确认删除图层?', () => {
              try {
                // debugger
                let sn: any = null
                const ref = item._inner.sn.ref
                // update:-- 判断方式要修改
                if (ref.startsWith('node_')) {
                  const objectId = item._inner.sn.ref.split('_')[1]
                  sn = earth.sceneTree.$refs[objectId]
                } else {
                  sn = item._inner.sn
                }
                let id = sn.ref
                // 删除数据库中的数据
                that
                  .handleNodeType(sn)
                  // 传感器
                  .sensor(() => {
                    // 发送请求 删除数据库中的数据
                    that.handlerModelDelete(this.url.deleteSensor, { eventSerialNum: id })
                  })
                  // 标志点
                  .markerPosition(() => {
                    if (sn.czmObject.addViewShedReturn) {
                      window.$earth.czm.viewer.entities.remove(sn.czmObject.addViewShedReturn)
                    }
                    if (sn.czmObject.customProp) {
                      let prop = JSON.parse(sn.czmObject.customProp)
                      if (prop.labelAttr == 4) {
                        defHttp.delete({
                          url: "/military/RadarConfig/deleteByRadarCode",
                          params: { radarCode: prop.labelCode }
                        }, { isTransformResponse: false, joinParamsToUrl: true })
                        // deleteAction("/military/RadarConfig/deleteByRadarCode", {radarCode: prop.labelCode}).then(res => {
                        //   // console.log(res,'delete');
                        // })
                      }
                    }
                    this.handlerModelDelete(this.url.deleteMapLabel, {
                      id: id,
                    })
                  })
                  // 线
                  .modelCallback(() => {
                    that.handlerModelDelete(this.url.deleteSite, { id: id }).then(() => {
                      sn.destroy()
                      const node = item._inner.sn
                      const childList = node.parent.children
                      childList.splice(childList.indexOf(node), 1)
                      node.destroy()
                    })
                  })
                  .polylineCallBack(() => {
                    const childList = item._inner.sn.children

                    for (const child of childList) {
                      if (child.children.length > 0) {
                        this.$message.warning('存在下级数据无法删除')
                        throw '存在下级数据无法删除'
                      }
                    }
                    that.handlerModelDelete(this.url.deleteMapLine, { id: id }).then(() => {
                      const nodeRef = 'node_' + id
                      const node = $earth.sceneTree.$refs[nodeRef]
                      const childList = node.parent.children
                      childList.splice(childList.indexOf(node), 1)
                      node.destroy()
                    })
                  })
                  .run()
                const index = sn.parent.children.indexOf(sn)
                sn.parent.children.splice(index, 1)
              } catch (error) {
              }
            })
          },
        },
      ]
      const bf = {
        text: '布防/撤防',
        keys: '',
        func: () => {
          const xbsjObject = item._inner.sn
          if (!xbsjObject || !xbsjObject.czmObject) return
          const jsonObj = JSON.parse(xbsjObject.czmObject.customProp)
          const deviceId = jsonObj.deviceId
          if (!deviceId) {
            console.error('主机设备为空')
            return
          }
          const labelCode = jsonObj.labelCode
          if (!labelCode) {
            console.error('设备编码为null')
            return
          }
          const device = that.hostDeviceMapById.get(deviceId)
          const ref = xbsjObject.ref
          if (device.deviceType_dictText.indexOf("微波探测器") > -1) {
            if (ref && ref.length > 0) {
              const state = that.statusByNodeId.get(ref)
              if (state == 1) {
                that.setLabelStatus(device, labelCode, ref, 0).then((response) => {
                  that.setIconByRef(ref, el)
                })
              } else if (state == 0) {
                that.setLabelStatus(device, labelCode, ref, 1).then((response) => {
                  that.setIconByRef(ref, el)
                })
              } else {
                that.$message.error("设备不在线")
              }
            }
          } else if (device.deviceType_dictText.indexOf("雷达") > -1) {
            // console.log("leida");
            //处理单个雷达布防撤防
            //参数
            // {
            //   "regionIdList": [
            // 2
            //   ], // 周界防区区域ID列表（雷达设备列表的ID）
            //   "regionStatus": 0, // 布防状态 0 - 未布防 1 - 布防
            //   "defenceRule": { // 布防规则
            // "startTime": "yyyy-MM-dd HH:mm:ss", // 布防开始时间 每日循环情况下只包含时分秒，格式："HH:mm:ss" 非每日循环情况下包含年月日、时分秒，格式："yyyy-MM-dd HH:mm:ss"
            // "endTime": "yyyy-MM-dd HH:mm:ss", // 布防结束时间 每日循环情况下只包含时分秒，格式："HH:mm:ss" 非每日循环情况下包含年月日、时分秒，格式："yyyy-MM-dd HH:mm:ss"
            // "dailyCycle": true // 每日循环布防 true - 是 false - 否
            //   }
            // }
            // putAction(this.url.perimeterControl,{})
          }
        }
      }
      const selectRef = item._inner.sn.ref
      if (selectRef.startsWith('wbList') || selectRef.startsWith('nodeSecondary_')) {
        baseItems = [
          {
            text: '一键布防',
            keys: '',
            func: () => {
              that.setAllLabelStatus(selectRef, item, true)
            },
          },
          {
            text: '一键撤防',
            keys: '',
            func: () => {
              that.setAllLabelStatus(selectRef, item, false)
            },
          },
        ]
        earthUI.contextMenu.pop(baseItems)
        return
      } else if (selectRef.startsWith('monitor') || selectRef.startsWith('ldList')) {
        earthUI.contextMenu.pop([])
        return
      } else if (item.level <= 2) {
        if (!item._inner.sn.ref.startsWith('node_')) {
          earthUI.contextMenu.pop([])
          return
        } else {
          baseItems.splice(0, 1)
        }
      } else {
        if (selectRef.startsWith('camera')) {
          //   baseItems = [bf]
          //   earthUI.contextMenu.pop(baseItems)
          return
        } else if (!selectRef.startsWith('node_')) {//站点
          baseItems.unshift({
            type: 'divider',
          })
          baseItems.unshift(bf)
        }
      }
      let num = 2
      //判断定位的位置
      if (
        item.level <= 2 ||
        selectRef.startsWith('monitor') ||
        selectRef.startsWith('wbList') ||
        selectRef.startsWith('ldList') ||
        //站点
        selectRef.startsWith('node_')
      )
        num = 0
      baseItems.splice(num, 0, {
        text: '定位',
        keys: '',
        func: () => {
          // const czmObject = item._inner.sn.czmObject
          // czmObject.flyTo()
          const ref = item._inner.sn.ref
          let czmObject: any = null
          if (ref.startsWith('node_')) {
            const objectId = ref.split('_')[1]
            const sn = earth.sceneTree.$refs[objectId]
            czmObject = sn.czmObject
          } else {
            const sn = item._inner.sn
            czmObject = sn.czmObject
          }

          czmObject.flyTo()
        },
      })
      baseItems.push(
        ...[
          {
            type: 'divider',
          },
          {
            text: '属性',
            func: () => {

              $mitt.emit('windowCancel')
              // 属性面板
              const mainUI = earthUI._vm.$refs.mainUI
              const areaCode = that.getAreaCode(item)
              let sn: any = null
              if (item._inner.sn.ref.startsWith('node_')) {
                const objectId = item._inner.sn.ref.split('_')[1]
                sn = earth.sceneTree.$refs[objectId]
                // window.XE.MVVM.watch(() => {
                //   item._inner.sn.title = sn.title
                // })

                sn.czmObject.distanceDisplayCondition = [1.0, 30000.0]
                if (sn.czmObject.xbsjType == 'Model') {
                  const lineId = item.parent.parent._inner.sn.ref.split('_')[1]

                  this.czmObject = sn.czmObject
                  this.node = item
                  this.type = 'jkd'
                  this.lineId = lineId
                  this.areaCode = areaCode
                  this.areaByNodeIdModel = that.areaByNodeId
                  // this.addModelWinShow = true
                  this.$nextTick(() => {
                    this.addModelWinShow = true
                  })

                  //////////////////////////
                  // 只有组件中有getBind属性才能传递属性
                  // this._earthUI.showPropertyWindow(
                  //   {
                  //     czmObject: sn.czmObject,
                  //     node: item,
                  //     type: 'jkd',
                  //     lineId: lineId,
                  //     areaCode: areaCode,
                  //     areaByNodeId: that.areaByNodeId,
                  //   },
                  //   {
                  //     // component: addModelModal,
                  //     component: addModelWin,
                  //   }
                  // )
                  return
                }
              } else {
                sn = item._inner.sn
                if (sn.czmObject.xbsjType == 'Pin') {
                  const jsonObj = JSON.parse(sn.czmObject.customProp)

                  const lineId = jsonObj.labelAttr == 4 ? item.parent._inner.sn.ref.split('_')[1] : item.parent.parent._inner.sn.ref.split('_')[1]

                  this.czmObject = sn.czmObject
                  this.node = item
                  this.type = jsonObj.labelAttr == 4 ? 'ld' : 'wb'
                  this.lineId = lineId
                  this.areaCode = areaCode
                  this.eidtId = sn.ref
                  this.areaByNodeIdModel = that.areaByNodeId
                  // setLabelStatus: that.setLabelStatus, 已经有了
                  //     setIconByRef: that.setIconByRef,
                  this.el = el,

                    this.$nextTick(() => {
                      this.addModelWinShow = true
                    })




                  // 只有组件中有getBind属性才能传递属性
                  // this._earthUI.showPropertyWindow(
                  //   {
                  //     czmObject: sn.czmObject,
                  //     node: item,
                  //     type: jsonObj.labelAttr == 4 ? 'ld' : 'wb',
                  //     lineId: lineId,
                  //     areaCode: areaCode,
                  //     areaByNodeId: that.areaByNodeId,
                  //     eidtId: sn.ref,
                  //     setLabelStatus: that.setLabelStatus,
                  //     setIconByRef: that.setIconByRef,
                  //     el: el,
                  //   },
                  //   {
                  //     // component: addModelModal,
                  //     component: addModelWin,
                  //   }
                  // )
                  return
                }
              }
              let index = sn.parent.children.indexOf(sn)
              let tempData = sn.czmObject.toAllJSON()
              // 设置属性面板的确定按钮方法
              // 显示属性面板
              earthUI.showPropertyWindow(sn.czmObject)
              that.$nextTick(() => {
                // 模型窗口
                const windowsAttrList = Object.keys(mainUI.$refs)
                // 找到该模型设置属性窗口
                const modelToolKey = windowsAttrList.filter((f) => f.indexOf(sn.czmObject.guid || sn.guid) > -1)[0]
                const modelTool = mainUI.$refs[modelToolKey][0]
                // 对应处理方法
                that
                  .handleNodeType(sn)
                  // 感应器
                  .sensor(() => {
                    // 禁用模型名称编辑
                    modelTool.$el
                      .getElementsByClassName('xbsj-flatten')[0]
                      .children[0].children[1].setAttribute('disabled', 'disabled')
                  })
                  .default(() => {
                    // 启用模型名称编辑
                    modelTool.$el
                      .getElementsByClassName('xbsj-flatten')[0]
                      .children[0].children[1].removeAttribute('disabled')
                  })
                  .run()

                // modelTool
                modelTool.ok = () => {
                  // 确定时清除这个事件
                  $mitt.off('windowCancel')
                  // 保存前端数据
                  const modelToolObj = modelTool._czmObj
                  if (!modelToolObj) {
                    return
                  }
                  modelToolObj.positionEditing = false
                  if (modelToolObj.isCreating) {
                    modelToolObj.isCreating = false
                    const sceneObject = new XE.SceneTree.Leaf(modelToolObj)
                    earthUI.addSceneObject(sceneObject)
                  }

                  // 保存到数据库
                  that.propertiesWindowConfirm(modelTool, sn, index)
                  // 关闭属性面板
                  modelTool.close()
                }
                modelTool.cancel = () => {
                  // 清除这个事件
                  $mitt.off('windowCancel')
                  // 关闭属性面板
                  modelTool.close()
                  let t = modelTool._czmObj
                  // 如果是创建的话，需要删除
                  t && t.positionEditing === false && t.isCreating && t.isCreating === false && t.destroy()
                  // 恢复之前的数据
                  t && t.xbsjFromJSON(tempData)
                }
                $mitt.on('windowCancel', modelTool.cancel)
                // 下面的代码，是切换属性面板里选项窗口， 必须
                // 否侧 ok cancel 等方法执行是原本的方法而不是已经修改的方法
                modelTool.tabShow = '3'
                modelTool.tabShow = '1'
              })
            },
          },
        ]
      )
      // 右键菜单-重命名
      // 先销毁之前的 on-change-title 事件
      vueObject.$off('on-change-title', that.handleChangeTitle)
      // 重命名时 on-change-title 事件
      vueObject.$on('on-change-title', that.handleChangeTitle)

      // 弹出右键菜单
      earthUI.contextMenu.pop(baseItems)
    }

    // 重命名 on-change-title 事件 使用 lodash.debounce 函数(防抖)
    handleChangeTitle = _.debounce(function (options) {
      const sn = options.item._inner.sn
      const newTitle = options.title

      // 修改模型属性后，提交到后台。先判断模型的节点，调用不同的接口
      this.handleNodeType(sn)
        // 感应器
        .sensor(() => {
          // 不支持修改名称
          this.$message.warning('不支持修改感应器的名称')
        })
        // 传感器标志线
        .modelCallback(() => {
          // 发送请求 保存模型属性
          let editCameraSiteModelParameter = {
            id: sn.ref,
            sitename: newTitle,
          }
          defHttp.put({
            url: this.url.updateSite,
            params: editCameraSiteModelParameter,
          }, { isTransformResponse: false })
            // putAction(this.url.updateSite, editCameraSiteModelParameter)
            .then((res) => {
              if (res.success) {
                this.$message.success('修改成功')
              } else {
                this.$message.error('修改失败')
              }
            })
            .catch((error) => {
              this.$message.error('修改失败')
            })
        })
        .markerPosition(() => {
          // 发送请求 保存模型属性
          let editPinModelParameter = {
            id: sn.ref,
            labelName: newTitle,
          }
          defHttp.put({
            url: this.url.updateMapLabel,
            params: editPinModelParameter,
          }, { isTransformResponse: false })
            // putAction(this.url.updateMapLabel, editPinModelParameter)
            .then((res) => {
              if (res.success) {
                // 修改扩展文本
                sn.czmObject.pinBuilder.extText = newTitle
                this.$message.success('修改成功')
              } else {
                this.$message.error('修改失败')
              }
            })
            .catch((error) => {
              this.$message.error('修改失败')
            })
        })
        .run()
    }, 150)

    // 右键菜单删除按钮的删除方法
    handlerModelDelete(url, params) {
      // return deleteAction(url, params).then((res) => {
      return defHttp.delete({
        url: url,
        params: params
      }, { isTransformResponse: false, joinParamsToUrl: true }).then((res) => {
        if (res.success) {
          this.$message.success('删除成功')
        } else {
          this.$message.error('删除失败')
          console.log('asdasdasd');

        }
      })
    }

    // 属性面板确定按钮方法
    propertiesWindowConfirm(propertiesWindow, sn, index) {
      // 属性面板 所修改的模型
      let model: any = null
      if (sn.ref && !sn.ref.startsWith('node_')) {
        model = sn
      } else {
        model = sn.parent.children[index]
      }

      let modelData = model.czmObject
      // 转换方法
      let transform = window.Cesium.Math

      // 修改模型属性后，提交到后台。先判断模型的节点，调用不同的接口
      this.handleNodeType(sn)
        // 传感器
        .sensor(() => {
          // 发送请求 保存模型属性
          let editSensorParams = {
            eventSerialNum: model.ref,
            lon: transform.toDegrees(modelData.xbsjPosition[0]).toFixed(5),
            lat: transform.toDegrees(modelData.xbsjPosition[1]).toFixed(5),
            height: modelData.xbsjPosition[2].toFixed(2),
            yaw: transform.toDegrees(modelData.xbsjRotation[0]).toFixed(2),
            pitch: transform.toDegrees(modelData.xbsjRotation[1]).toFixed(2),
            roll: transform.toDegrees(modelData.xbsjRotation[2]).toFixed(2),
            isShow: 1,
            // 传感器类型
            modelType: '11',
            // 事件类型
            eventType: 1,
          }
          defHttp.put({
            url: this.url.updateSensor,
            params: editSensorParams
          }, { isTransformResponse: false })
            // putAction(this.url.updateSensor, editSensorParams)
            .then((res) => {
              if (res.success) {
                this.$message.success('修改成功')
              } else {
                this.$message.error('修改失败: ', res.message)
              }
            })
        })
        // 站点
        .modelCallback(() => {
          let startNum = modelData.url.lastIndexOf('/') + 1
          let modelName = ''
          if (startNum > 0) {
            modelName = modelData.url.substring(startNum, modelData.url.length)
          }
          // 发送请求 保存模型属性
          let editCameraSiteModelParameter = {
            id: model.ref,
            longitude: transform.toDegrees(modelData.xbsjPosition[0]).toFixed(6),
            latitude: transform.toDegrees(modelData.xbsjPosition[1]).toFixed(6),
            height: modelData.xbsjPosition[2],
            yaw: transform.toDegrees(modelData.xbsjRotation[0]).toFixed(6),
            pitch: transform.toDegrees(modelData.xbsjRotation[1]).toFixed(6),
            roll: transform.toDegrees(modelData.xbsjRotation[2]).toFixed(6),
            modelUrl: modelName,
            sitename: modelData.name,
          }
          defHttp.put({
            url: this.url.updateSite,
            params: editCameraSiteModelParameter
          }, { isTransformResponse: false })
            // putAction(this.url.updateSite, editCameraSiteModelParameter)
            .then((res) => {
              if (res.success) {
                modelData.pinBuilder.extText = modelData.name
                this.$message.success('修改成功')
              } else {
                this.$message.error('修改失败')
              }
            })
        })
        // 标志点
        .markerPosition(() => {
          let pinImage = modelData.imageUrl
          const staticDomainURL = window._CONFIG['staticDomainURL'] + '/'
          // 去除 image 地址中的 staticDomainURL 链接
          let imageUri = pinImage.substring(pinImage.indexOf(staticDomainURL) + staticDomainURL.length, pinImage.length)
          let editPinModelParameter = {
            id: model.ref,
            labelName: modelData.name,
            labelLon: transform.toDegrees(modelData.position[0]).toFixed(5),
            labelLat: transform.toDegrees(modelData.position[1]).toFixed(5),
            labelHeight: modelData.position[2].toFixed(2),
            labelImgUrl: imageUri,
          }
          defHttp.put({
            url: this.url.updateMapLabel,
            params: editPinModelParameter
          }, { isTransformResponse: false })
            // putAction(this.url.updateMapLabel, editPinModelParameter)
            .then((res) => {
              if (res.success) {
                modelData.pinBuilder.extText = modelData.name
                this.$message.success('修改成功')
              } else {
                this.$message.error('修改失败')
              }
            })
            .catch((error) => {
              this.$message.error('修改失败')
            })
        })
        .polylineCallBack(() => {
          const submitData: any = {}
          const poistions = modelData.positions
          if (poistions.length <= 0) {
            return
          }
          submitData.id = model.ref
          submitData.name = modelData.name
          if (!modelData.customProp) {
            submitData.lineCode = modelData.guid
          }

          submitData.isLoop = Number(modelData.loop)
          submitData.isDepthCheck = Number(modelData.depthTest)
          submitData.width = modelData.width
          submitData.interpolation = modelData.arcType
          submitData.positions = JSON.stringify(poistions)
          switch (modelData.material.type) {
            // 实线
            case 'XbsjColorMaterial':
              submitData.materialType = 0
              // material.XbsjColorMaterial = {}
              submitData.color = JSON.stringify(modelData.material.XbsjColorMaterial.color)
              submitData.intervalColor = null
              submitData.dashLength = 0
              submitData.dashStyle = 0
              break
            // 虚线
            case 'XbsjPolylineDashMaterial':
              submitData.materialType = 1
              submitData.color = JSON.stringify(modelData.material.XbsjPolylineDashMaterial.color)
              submitData.intervalColor = JSON.stringify(modelData.material.XbsjPolylineDashMaterial.gapColor)
              submitData.dashLength = modelData.material.XbsjPolylineDashMaterial.dashLength
              submitData.dashStyle = modelData.material.XbsjPolylineDashMaterial.dashPattern
              // material.XbsjPolylineDashMaterial = {}
              // material.XbsjPolylineDashMaterial.dashLength = data.dashLength
              // material.XbsjPolylineDashMaterial.dashPattern = data.dashStyle
              break
            // 箭头线
            case 'XbsjPolylineArrowMaterial':
              submitData.materialType = 2
              // material.XbsjPolylineArrowMaterial = {}
              submitData.color = JSON.stringify(modelData.material.XbsjPolylineArrowMaterial.color)
              submitData.intervalColor = null
              submitData.dashLength = 0
              submitData.dashStyle = 0
              break
            // 轨迹线
            case 'XbsjODLineMaterial':
              submitData.materialType = 3
              submitData.color = JSON.stringify(modelData.material.XbsjODLineMaterial.color)
              submitData.intervalColor = null
              submitData.dashLength = 0
              submitData.dashStyle = 0
              submitData.cycleFrame = modelData.material.XbsjODLineMaterial.totoalFrameCount

              // material.XbsjODLineMaterial = {}
              // material.XbsjODLineMaterial.color = JSON.parse(data.color)
              // material.XbsjODLineMaterial.totoalFrameCount = data.cycleFrame
              break
          }
          defHttp.put({
            url: this.url.updateMapLine,
            params: submitData
          }, { isTransformResponse: false })
            // putAction(this.url.updateMapLine, submitData)
            .then((res) => {
              if (res.success) {
                // $mitt.emit('openNotification', '修改成功', 2, 'info')
                $mitt.emit('openNotification', { msg: '修改成功！', dt: 2, type: 'info', top: '50px' })
                sn.title = submitData.name
                window.$earth.sceneTree.$refs['node_' + sn.ref].title = submitData.name
              } else {
                // $mitt.emit('openNotification', '修改失败', 2, 'error', '50px')
                $mitt.emit('openNotification', { msg: '修改失败', dt: 2, type: 'error', top: '50px' })
              }
            })
            .catch((error) => {
              // $mitt.emit('openNotification', '修改失败', 2, 'error', '50px')
              $mitt.emit('openNotification', { msg: '修改失败', dt: 2, type: 'error', top: '50px' })
            })
        })
        .run()
    }


    /**
     * 保存更改的ref到模型和后台数据中;
     * @param {Object} model 当前模型
     * @param {string} newRef 新的ref
     * @param {string} oldRef 旧的ref
     */
    changeRef = _.debounce(function (model, newRef, oldRef) {
      // 当数值改变时且旧值不等于空时，更新模型的ref
      if (newRef !== oldRef && oldRef !== '') {
        // 修改后台的数据
        this.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
                  this.$message.success('修改成功')
                } else {
                  this.$message.error('修改失败: ' + res.message)
                }
              })
              .catch((err) => {
                this.$message.error('修改失败: ', err)
              })
          })
          .modelCallback(() => {
            // 传感器标志线不能修改ref，因为 ref 是后台数据库的ID;
            this.$message.warning('无法修改传感器标志线的ref')
          })
          .run()
      }
    }, 150)
    handleNodeType(sn) {
      return new HandleNodeType(sn)
    }
    radarAlarmTimeOutCheck() {
      const now = Date.now()
      const timeout = 5 * 60 * 1000
      // 遍历报警数据
      this.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()
        }
        radarAlarmDataMap.delete(eventNum)
      }
    }
    clearAlarmModel(eventNum) {
      let alarmInfoMap = this.alarmInfoMap
      let radarAlarmDataMap = this.radarAlarmDataMap
      if (alarmInfoMap.has(eventNum)) {
        let alarmData = alarmInfoMap.get(eventNum)
        // 清除报警
        alarmData.pin && alarmData.pin._div.remove()
        alarmData.pin && alarmData.pin.destroy()
        alarmData.scanline && alarmData.scanline.destroy()
        this.alarmInfoMap.delete(eventNum)
      }
      this.clearRadarAlarmModel(radarAlarmDataMap, eventNum)
    }
    // 获取当前实时时间
    getRealTime() {
      this.timer2 = setInterval(() => {
        this.realTime = getRealTime();
      }, 1000);
    }
    // 资源销毁
    beforeDestroy() {
      // vue程序销毁时，需要清理相关资源
      this._earth = this._earth && this._earth.destroy()
      this.websocketclose()
      //清除定时器
      clearInterval(this.timer)
      clearInterval(this.timer2)
      clearInterval(this.alarmTrackClearTimer)
    }
  }
</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>
