<template>
  <div class="container">
    <el-row id="earth" style="height: 100%; width: 100%; display: flex; position: relative">
      <el-col style="height: 100%; position: relative" :span="this.leftwidth">
        <div class="main-layout" v-on:mouseover="changeActive('2D')" @mousemove="getMouseLocation">
          <div id="2DcesiumContainer" class="map"></div>
        </div>
      </el-col>
      <el-col style="height: 100%; position: relative" :span="24 - this.leftwidth">
        <div class="main-layout" v-on:mouseover="changeActive('3D')" @mousemove="getMouseLocation">
          <div id="3DcesiumContainer" class="map"></div>
        </div>
      </el-col>
      <el-tabs type="border-card" v-model="activeName" tab-position="left" class="menu" :stretch="true"
        @tab-click="legendClick">
        <el-tab-pane name="fouth">
          <el-tooltip placement="right" effect="light" slot="label">
            <span slot="content" class="item">想定</span>
            <span><i class="el-icon-house"></i></span>
          </el-tooltip>
          <el-table :data="situation">
            <el-table-column label="名称" prop="xdname" width="150px"></el-table-column>
            <el-table-column label="操作" align="center">
              <template slot-scope="scope">
                <el-button type="primary" @click="getJson(scope.row)">导入</el-button>
                <!-- <el-button type="primary" @click="saveJson()">保存</el-button> -->
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
        <el-tab-pane name="fifth">
          <el-tooltip placement="right" effect="light" slot="label">
            <span slot="content" class="item">消息</span>
            <span><i class="el-icon-chat-line-round"></i></span>
          </el-tooltip>
          <el-table :data="messageList">
            <el-table-column label="序号" prop="order" width="50px"></el-table-column>
            <el-table-column label="时间" align="center" prop="time"></el-table-column>
            <el-table-column label="消息" align="center" prop="context"></el-table-column>
          </el-table>
        </el-tab-pane>
      </el-tabs>
      <div class="buttons">
        <el-button icon="el-icon-full-screen" circle @click="ismax()"></el-button>
        <el-button icon="el-icon-house" circle @click="home()"></el-button>
        <el-button icon="el-icon-plus" circle @click="big()"></el-button>
        <el-button icon="el-icon-minus" circle @click="small()"></el-button>
      </div>
    </el-row>
    <!-- <TimeLine :showLayers="showLayers" :timeDataArray="timeDataArray" class="TimeLine"></TimeLine> -->
    <div>
      <el-dialog title="模拟消息列表" :visible.sync="dialogVisible" width="50%">
        <el-table :data="messageList">
          <el-table-column label="序号" prop="order" width="50px"></el-table-column>
          <el-table-column label="时间" align="center" prop="time"></el-table-column>
          <el-table-column label="消息" align="center" prop="context"></el-table-column>
        </el-table>
        <div slot="footer" class="dialog-footer">
          <el-button @click="dialogVisible = false">关闭</el-button>
        </div>
      </el-dialog>
    </div>
  </div>
</template>
<script>
import screenfull from "screenfull";
import fireController from "@/api/fireController.js";
import { getToken } from "@/utils";
import axios from "axios";
import satelliteModel from 'public/static/model/satelite1.glb';
import TimeLine from '@/components/TimeLine/index.vue';
import missileModel from 'public/static/model/basic_missle.glb';
import centerModel from 'public/static/model/the_white_house.glb';
import radarModel from 'public/static/model/radar.glb'
import { mapGetters } from "vuex";
import CesiumNavigation from 'cesium-navigation-es6/viewerCesiumNavigationMixin'
export default {
  components: {
    TimeLine
  },
  computed: {
    ...mapGetters([
      "dimension"
    ])
  },
  data() {
    return {
      save: false,
      messageList: [],
      situation: [],
      nameIdList: [],
      satelliteRange: [],
      missileList: {},
      thaadList: {},
      websocket: null,
      centerPosition: null,
      leftwidth: 12,
      unit: [],
      dialogVisible: false,
      satellite: [],
      center: [],
      move_data: {},
      order: 1,
      _viewer2D: null,
      _viewer3D: null,
      mousevalue: null,
      // 选中的点
      selectedMarker: null,
      // 以前的标记点坐标
      oldPosition: null,
      activeName: 'fouth',
      currentLab: {
        index: -1,
        isActive: false
      },
      url: "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
      isShow: false,
      handler3D: null,
      handler2D: null,
      image: null,
      modeltooltip: null,
      id: 1,
      showLayers: null,
      timeDataArray: ['Time 1', 'Time 2', 'Time 3', 'Time 4'],
      jsonData: null,
      mapNavOptions: {
        // 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和Cesium.Rectangle.     
        defaultResetView: this.Cesium.Cartographic.fromDegrees(110, 30, 2000000),
        // 罗盘     
        enableCompass: true,
        // 缩放控件     
        enableZoomControls: false,
        // 距离图例     
        enableDistanceLegend: true,
        // 指南针外环     
        enableCompassOuterRing: true
      }
    };
  },
  watch: {
    dimension: {
      handler: function (val, oldVal) {
        console.log(val)
        if (val == 2) {
          this.leftwidth = 24;
        } else if (val == 3) {
          this.leftwidth = 0;
        } else if (val == 5) {
          this.leftwidth = 12;
        }
      },
    },
  },
  activated() {
    this.getData();

  },
  mounted() {
    this.cesiumInit();
    // this.pointMove();
    // this.startWebSocket();
  },
  methods: {
    async getJson(row) {
      this.order = 1;
      this.messageList = [];
      this.nameIdList = [];
      this.satelliteRange = [];
      this.missileList = {};
      this.thaadList = {};
      let redunit = [];
      let blueunit = [];
      let satellite = [];
      let center = [];
      let fileInfoStr = row.xdfile;
      let fileInfoArr = JSON.parse(fileInfoStr);
      this.$data._viewer2D.entities.removeAll();
      this.$data._viewer3D.entities.removeAll();
      await axios
        .get("http://127.0.0.1:8084/admin/online/onlineOperation/downloadDatasource/main", {
          params: {
            datasourceId: "1656243335922192384",
            fieldName: "xdfile",
            asImage: false,
            dataId: row.id,
            filename: fileInfoArr[0].filename,
            Authorization: getToken(),
            MenuId: "1656244747347431424"
          }
        })
        .then((response) => {
          console.log('response.data :>> ', response.data);
          // // 处理成功的响应
          // jsonData = response.data
          blueunit = response.data.blueunit
          redunit = response.data.redunit
          satellite = response.data.satellite
          center = response.data.center
          this.save = true
          this.jsonData = {
            id: row.id,
            xdname: response.data.xdname,
            type: response.data.type,
            // creator: row.creator,
            createtime: response.data.createtime,
            bluecnt: response.data.bluecnt,
            target: response.data.target,
            starttime: response.data.starttime,
            steptime: response.data.steptime,
            endtime: response.data.endtime,
            blueunit: blueunit,
            redunit: redunit,
            satellite: satellite,
            center: center
          }
          this.setTimeLine(response.data.starttime, response.data.endtime, response.data.steptime)//传入时间到时间轴
        })
        .catch((error) => {
          // 处理错误
          console.error(error);
        });

      for (let i = 0; i < blueunit.length; i++) {
        this.markLocationbyJson(parseFloat(blueunit[i].pos.lat), parseFloat(blueunit[i].pos.lon), parseFloat(blueunit[i].pos.height), blueunit[i].name, "blue")
      }
      for (let i = 0; i < center.length; i++) {
        let item = center[i]
        this.markLocationbyJson(parseFloat(item[center[i].name].properties.lat), parseFloat(item[center[i].name].properties.lon), parseFloat(item[center[i].name].properties.h), item.name, "center")
      }
      for (let i = 0; i < redunit.length; i++) {
        this.markLocationbyJson(parseFloat(redunit[i].component_movementjson.properties.launch_lat), parseFloat(redunit[i].component_movementjson.properties.launch_lon), parseFloat(redunit[i].component_movementjson.properties.launch_h), redunit[i].name, "red")
        let point1 = {
          longitude: parseFloat(redunit[i].component_movementjson.properties.launch_lon),
          latitude: parseFloat(redunit[i].component_movementjson.properties.launch_lat),
          height: parseFloat(redunit[i].component_movementjson.properties.launch_h)
        }
        let point2 = {
          longitude: parseFloat(redunit[i].component_movementjson.properties.target_lon),
          latitude: parseFloat(redunit[i].component_movementjson.properties.target_lat),
          height: parseFloat(redunit[i].component_movementjson.properties.target_h)
        }
        this.markLine(point1, point2, "red")
      }
    },
    //获取所有数据
    getData() {
      this.getCenter();
      this.getSatellite();
      this.getUnit();
      this.getSituation();
    },
    // 获取场景想定数据
    getSituation() {
      let params = {
        datasourceId: "1656243335922192384",
        filterDtoList: [],
        pageParam: {
          pageNum: 1,
          pageSize: 10
        }
      };
      fireController.situation(this, params).then((res) => {
        this.situation = res.data.dataList;
      });
    },
    // 获取作战单元数据
    getUnit() {
      let params = {
        datasourceId: "1657931215497334784",
        filterDtoList: [],
        pageParam: {
          pageNum: 1,
          pageSize: 10
        }
      };
      fireController.unit(this, params).then((res) => {
        this.unit = res.data.dataList;
      });
    },
    // 获取指挥中心数据
    getCenter() {
      let params = {
        datasourceId: "1654421731512684544",
        filterDtoList: [],
        pageParam: {
          pageNum: 1,
          pageSize: 10
        }
      };
      fireController.center(this, params).then((res) => {
        this.center = res.data.dataList;
      });
    },
    // 获取预警卫星数据
    getSatellite() {
      let params = {
        datasourceId: "1654424480958648320",
        filterDtoList: [],
        pageParam: {
          pageNum: 1,
          pageSize: 10
        }
      };
      fireController.satellite(this, params).then((res) => {
        this.satellite = res.data.dataList;
      });
    },
    cesiumInit() {
      this.$data._viewer2D = new this.Cesium.Viewer("2DcesiumContainer", {
        sceneMode: this.Cesium.SceneMode.SCENE2D,
        animation: true, // 是否显示时间轴动画
        baseLayerPicker: false,
        homeButton: false,
        geocoder: false,
        timeline: true, //是否显示时间线控件
        fullscreenButton: false,
        sceneModePicker: false,
        navigationHelpButton: false,
        selectionIndicator: false,
        imageryProvider: new this.Cesium.UrlTemplateImageryProvider({
          url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
          layer: "tdtVecBasicLayer",
          style: "default",
          format: "image/png",
          tileMatrixSetID: "GoogleMapsCompatible",
          show: false
        })
      });

      this.$data._viewer3D = new this.Cesium.Viewer("3DcesiumContainer", {
        animation: true, // 是否显示时间轴动画
        baseLayerPicker: false,
        homeButton: false,
        geocoder: false,
        timeline: true, //是否显示时间线控件
        fullscreenButton: false,
        sceneModePicker: false,
        navigationHelpButton: false,
        selectionIndicator: false,
        // imageryProvider:  new this.Cesium.WebMapServiceImageryProvider({
        //   url: '/geoserver/map/wms',
        //     // 这里是自定义的图层名称
        //     layers: 'map',
        //     parameters: {
        //         service: 'WMS',
        //         format: 'image/png',
        //         transparent: true
        //     }
        // }),

        imageryProvider:
          // new this.Cesium.WebMapTileServiceImageryProvider({
          //     url: "http://10.170.16.95:8080/geoserver/gwc/service/wmts/rest/map:map/{style}/{TileMatrixSet}/{TileMatrixSet}:{TileMatrix}/{TileRow}/{TileCol}?format=image/png",
          //     layer: 'map:map',
          //     style: 'raster',
          //     format: 'image/png',
          //     tileMatrixSetID: 'EPSG:900913',      //一般使用EPSG:3857坐标系

          //   }),
          new this.Cesium.UrlTemplateImageryProvider({
            url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
            layer: "tdtVecBasicLayer",
            style: "default",
            format: "image/png",
            tileMatrixSetID: "GoogleMapsCompatible",
            show: false
          })
      });

      this.$data._viewer3D._cesiumWidget._creditContainer.style.display = "none";
      this.$data._viewer2D._cesiumWidget._creditContainer.style.display = "none";
      this.$data._viewer3D.camera.setView({
        destination: new this.Cesium.Cartesian3.fromDegrees(117.918977, 25.0, 1500000)
        // 方向，俯视和仰视的视角
        // orientation:{
        //   heading: this.Cesium.Math.toRadians(90),//坐标系旋转90度
        //   pitch: this.Cesium.Math.toRadians(-45) ,//设置俯仰角度为-45度
        // }
      });
      this.$data._viewer2D.camera.setView({
        destination: new this.Cesium.Cartesian3.fromDegrees(117.918977, 25.0, 1500000)
        // 方向，俯视和仰视的视角
        // orientation:{
        //   heading: this.Cesium.Math.toRadians(90),//坐标系旋转90度
        //   pitch: this.Cesium.Math.toRadians(-45) ,//设置俯仰角度为-45度
        // }
      });
      // this.viewer.scene.screenSpaceCameraController.maximumZoomDistance = 1500000;  //相机高度的最大值
      this.$data._viewer2D.camera.percentageChanged = 0.01;
      this.$data._viewer2D.camera.changed.addEventListener(this.sync); //地图移动事件
      this.$data._viewer3D.camera.percentageChanged = 0.01;
      this.$data._viewer3D.camera.changed.addEventListener(this.sync); //地图移动事件
      this.$data._viewer2D.camera.moveEnd.addEventListener(this.getCammeraHeightAndZoom)  //地图缩放事件
      this.$data._viewer3D.camera.moveEnd.addEventListener(this.getCammeraHeightAndZoom)  //地图缩放事件
      this.handler2D = new this.Cesium.ScreenSpaceEventHandler(this.$data._viewer2D.scene.canvas);
      this.handler3D = new this.Cesium.ScreenSpaceEventHandler(this.$data._viewer3D.scene.canvas);
      //设置导航组件
      new CesiumNavigation(this.$data._viewer2D, this.mapNavOptions);
      new CesiumNavigation(this.$data._viewer3D, this.mapNavOptions);
    },
    sync() {
      if (this.mousevalue == "3D") {
        // 三维地图中心点
        let center = new this.Cesium.Cartesian2(
          Math.floor(this.$data._viewer3D.canvas.clientWidth / 2),
          Math.floor(this.$data._viewer3D.canvas.clientHeight / 2)
        );
        // 转为世界坐标系
        let position = this.$data._viewer3D.scene.camera.pickEllipsoid(center);
        // 判断中心点是否在椭球体上
        if (this.Cesium.defined(position)) {
          // 获取三维地图中心点与相机之间的距离
          let distance = this.Cesium.Cartesian3.distance(position, this.$data._viewer3D.scene.camera.positionWC);
          position = this.convertWorldToCartographic(position);
          // 更新二维地图
          this.$data._viewer2D.scene.camera.setView({
            destination: new this.Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude, distance)
          });
        }
      }
      if (this.mousevalue == "2D") {
        // 二维地图中心点
        let center = new this.Cesium.Cartesian2(
          Math.floor(this.$data._viewer2D.canvas.clientWidth / 2),
          Math.floor(this.$data._viewer2D.canvas.clientHeight / 2)
        );
        // 转为世界坐标系
        let position = this.$data._viewer2D.scene.camera.pickEllipsoid(center);
        // 判断中心点是否在椭球体上
        if (this.Cesium.defined(position)) {
          // 获取三维地图中心点与相机之间的距离
          let distance = this.$data._viewer2D.scene.camera.positionCartographic.height;
          position = this.convertWorldToCartographic(position);
          // 更新三维地图
          this.$data._viewer3D.scene.camera.setView({
            destination: new this.Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude, distance)
          });
        }
      }
    },
    // 将世界坐标系转换为经纬度坐标系
    convertWorldToCartographic(worldPosition) {
      const ellipsoid = this.$data._viewer2D.scene.globe.ellipsoid;
      const cartographic = ellipsoid.cartesianToCartographic(worldPosition);
      const longitude = this.Cesium.Math.toDegrees(cartographic.longitude);
      const latitude = this.Cesium.Math.toDegrees(cartographic.latitude);
      const height = cartographic.height;
      return { longitude, latitude, height };
    },
    // 监听地图变化
    changeActive(value) {
      this.mousevalue = value;
    },
    dimensionswitch(value) {
      this.dimension = value;
      this.selectModel();
    },
    // 全屏缩小
    ismax() {
      if (screenfull.isEnabled && screenfull.isFullscreen) {
        screenfull.exit();
      } else {
        screenfull.request();
      }
    },
    /* 获取camera中心点坐标 */
    getCenterPosition(is3D = false) {
      let viewer = is3D ? this.$data._viewer3D : this.$data._viewer2D;
      let result = viewer.camera.pickEllipsoid(
        new this.Cesium.Cartesian2(viewer.canvas.clientWidth / 2, viewer.canvas.clientHeight / 2)
      );
      let curPosition = this.Cesium.Ellipsoid.WGS84.cartesianToCartographic(result);
      let lon = (curPosition.longitude * 180) / Math.PI;
      let lat = (curPosition.latitude * 180) / Math.PI;
      let height = viewer.camera.positionCartographic.height;
      return {
        lon: lon,
        lat: lat,
        height: height
      };
    },
    /* 地图放大 */
    big() {
      let { lon, lat, height } = this.getCenterPosition(this.dimension === 3);
      let viewer = (this.dimension === 3 || this.dimension === 5) ? this.$data._viewer3D : this.$data._viewer2D;
      // 镜头拉进
      viewer.camera.flyTo({
        destination: this.Cesium.Cartesian3.fromDegrees(lon, lat, height / 1.8),
        duration: 1.0
      });
    },
    /* 地图缩小 */
    small() {
      let { lon, lat, height } = this.getCenterPosition(this.dimension === 3);
      let viewer = (this.dimension === 3 || this.dimension === 5) ? this.$data._viewer3D : this.$data._viewer2D;
      // 镜头远离
      viewer.camera.flyTo({
        destination: this.Cesium.Cartesian3.fromDegrees(lon, lat, height * 1.2),
        duration: 1.0
      });
    },
    home() {
      let viewer = (this.dimension === 3 || this.dimension === 5) ? this.$data._viewer3D : this.$data._viewer2D;
      viewer.camera.flyTo({
        destination: this.Cesium.Cartesian3.fromDegrees(117.918977, 25.0, 1500000),
        duration: 2.0
      });
    },
    // tabs 切换点击
    legendClick({ index }) {
      this.selectModel();
      let tab_content = document.querySelectorAll(".menu .el-tabs__content");
      if (this.currentLab.index == index) {
        tab_content[0].style.display == "none" || ""
          ? (tab_content[0].style.display = "block")
          : (tab_content[0].style.display = "none");
      }
      if (this.currentLab.index != index) {
        this.currentLab.index = index;
        tab_content[0].style.display = "block";
      }
    },
    mouseMove(event) {
      if (this.$refs.modeltooltip) {
        this.$refs.modeltooltip.style.left = event.pageX - 240 + "px";
        this.$refs.modeltooltip.style.top = event.pageY - 115 + "px";
      }
    },
    //显示鼠标经纬度
    getMouseLocation(event) {
      let { longitude, latitude } = this.getCoordinatesFromEvent(event);
      this.$store.commit("app/setMouseLocation", { longitude, latitude });
    },
    /*根据camera高度近似计算当前层级*/
    heightToZoom(height) {
      var A = 40487.57;
      var B = 0.00007096758;
      var C = 91610.74;
      var D = -40467.74;
      return Math.round(D + (A - D) / (1 + Math.pow(height / C, B)));
    },
    getCammeraHeightAndZoom() {
      let viewer = (this.dimension === 3 || this.dimension === 5) ? this.$data._viewer3D : this.$data._viewer2D;
      //获取当前相机高度 
      let height = viewer.camera.positionCartographic.height;
      let zoom = this.heightToZoom(height);
      this.$store.commit("app/setCameraHeightAndZoom", { height, zoom });
    },
    selectModel(cursorStyle, image, info) {
      console.log('image :>> ', image);
      let earthMap = document.getElementById("earth");
      earthMap.style.cursor = cursorStyle || "auto";
      if (cursorStyle) {
        document.addEventListener("mousemove", this.mouseMove);
        this.isShow = true;
        this.image = image;
        this.modeltooltip = info;
      } else {
        document.removeEventListener("mousemove", this.mouseMove);
        this.isShow = false;
        this.image = null;
        this.modeltooltip = null;
      }
    },
    markLocationbyJson(latitude, longitude, height, name, type) {
      const position = this.Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
      console.log('position :>> ', position);
      let color = ''
      let modelUrl = ''
      if (type == 'red') {
        color = 'Red'
        modelUrl = missileModel
        this.missileList[name] = {
          disturb: 20,
          id: this.id
        }
      }
      else if (type == 'blue') {
        color = 'Blue'
        modelUrl = radarModel
        this.thaadList[name] = {
          range: 700000.0,
          health: 100.0,
          id: this.id
        }
      }
      else if (type == 'center') {
        color = 'Blue'
        modelUrl = centerModel
        this.centerPosition = position
      }
      else if (type == 'satelite') {
        color = 'Blue'
        modelUrl = satelliteModel
      }
      if (type == 'blue') {
        console.log(' radar!!!');
        const range = 700000;
        this.$data._viewer2D.entities.add({
          id: this.id,
          position: position,
          ellipsoid: {
            radii: new this.Cesium.Cartesian3(range, range, range),
            material: this.Cesium.Color.GREEN.withAlpha(0.5), // 设置球体的颜色和透明度
            outline: true,
            outlineColor: this.Cesium.Color.GREEN,
          },
          point: {
            pixelSize: 12, // 调整点的大小，可以增大点的像素大小
            color: this.Cesium.Color.fromCssColorString(color)
          },
          model: {
            uri: modelUrl, // 替换为你的3D模型文件路径
            scale: 1.0, // 调整3D模型的缩放大小
            minimumPixelSize: 64 // 设置3D模型的最小像素大小，确保在视图中可见
          },
          label: {
            text: type + ' ' + name,
            show: true,
            font: "18px Helvetica", // 调整标签的字体样式和大小
            pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移，向下偏移20像素
          }
        });
        this.$data._viewer3D.entities.add({
          id: this.id,
          position: position,
          ellipsoid: {
            radii: new this.Cesium.Cartesian3(range, range, range),
            material: this.Cesium.Color.GREEN.withAlpha(0.5), // 设置球体的颜色和透明度
            outline: true,
            outlineColor: this.Cesium.Color.GREEN,
          },
          point: {
            pixelSize: 12, // 调整点的大小，可以增大点的像素大小
            color: this.Cesium.Color.fromCssColorString(color)
          },
          model: {
            uri: modelUrl, // 替换为你的3D模型文件路径
            scale: 1.0, // 调整3D模型的缩放大小
            minimumPixelSize: 64 // 设置3D模型的最小像素大小，确保在视图中可见
          },
          label: {
            text: type + ' ' + name,
            show: true,
            font: "18px Helvetica", // 调整标签的字体样式和大小
            pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移，向下偏移20像素
          }
        });
        this.nameIdList.push({
          id: this.id,
          name: name
        })
        this.id++;

      }
      else {
        this.$data._viewer2D.entities.add({
          id: this.id,
          position: position,
          point: {
            pixelSize: 12, // 调整点的大小，可以增大点的像素大小
            color: this.Cesium.Color.fromCssColorString(color)
          },
          model: {
            uri: modelUrl, // 替换为你的3D模型文件路径
            scale: 1.0, // 调整3D模型的缩放大小
            minimumPixelSize: 64 // 设置3D模型的最小像素大小，确保在视图中可见
          },
          label: {
            text: type + ' ' + name,
            show: true,
            font: "18px Helvetica", // 调整标签的字体样式和大小
            pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移，向下偏移20像素
          }
        });
        this.$data._viewer3D.entities.add({
          id: this.id,
          position: position,
          point: {
            pixelSize: 12, // 调整点的大小，可以增大点的像素大小
            color: this.Cesium.Color.fromCssColorString(color)
          },
          model: {
            uri: modelUrl, // 替换为你的3D模型文件路径
            scale: 1.0, // 调整3D模型的缩放大小
            minimumPixelSize: 64 // 设置3D模型的最小像素大小，确保在视图中可见
          },
          label: {
            text: type + ' ' + name,
            show: true,
            font: "18px Helvetica", // 调整标签的字体样式和大小
            pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移，向下偏移20像素
          }
        });
        this.nameIdList.push({
          id: this.id,
          name: name
        })
        this.id++;
      }
    },
    // 从鼠标点击事件获取坐标
    getCoordinatesFromEvent(event) {
      let viewer = this.mousevalue === "2D" ? this.$data._viewer2D : this.$data._viewer3D;
      let clickPosition;
      if (this.dimension === 5 && this.mousevalue === "3D") {
        clickPosition = new this.Cesium.Cartesian2(event.clientX - 1080, event.clientY - 160);
      } else {
        clickPosition = new this.Cesium.Cartesian2(event.clientX - 280, event.clientY - 160);
      }
      // 获取地图上的经纬度
      const viewerPosition = viewer.scene.camera.pickEllipsoid(clickPosition);
      const cartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(viewerPosition);
      const latitude = this.Cesium.Math.toDegrees(cartographic.latitude);
      const longitude = this.Cesium.Math.toDegrees(cartographic.longitude);
      return {
        latitude,
        longitude
      };
    },
    markLine(point1, point2, color) {
      // 从点1和点2的WGS84坐标创建Cartesian3对象
      const position1 = this.Cesium.Cartesian3.fromDegrees(point1.longitude, point1.latitude, point1.height || 0);
      const position2 = this.Cesium.Cartesian3.fromDegrees(point2.longitude, point2.latitude, point2.height || 0);
      // 创建一个带有箭头图标的PolylineMaterial
      const material = new this.Cesium.PolylineArrowMaterialProperty(
        this.Cesium.Color.fromCssColorString(color || "red")
      );

      // 将点1和点2之间的连线添加到Viewer中
      this.$data._viewer2D.entities.add({
        polyline: {
          positions: [position1, position2],
          width: 5, // 设置线的宽度
          material: material,
          followSurface: false // 设置为false，使连线保持在固定的高度，不会贴地显示
        }
      });
      this.$data._viewer3D.entities.add({
        polyline: {
          positions: [position1, position2],
          width: 5, // 设置线的宽度
          material: material,
          followSurface: false // 设置为false，使连线保持在固定的高度，不会贴地显示
        }
      });
    },
    markSatelliteLine(position1, position2, color, viewer) {

      // 创建一个带有箭头图标的PolylineMaterial
      const material = new this.Cesium.PolylineArrowMaterialProperty(
        this.Cesium.Color.fromCssColorString(color || "red")
      );

      // 将点1和点2之间的连线添加到Viewer中
      viewer.entities.add({
        polyline: {
          positions: [position1, position2],
          width: 5, // 设置线的宽度
          material: material,
          followSurface: false // 设置为false，使连线保持在固定的高度，不会贴地显示
        }
      });

    },
    setTimeLine(startTime, endtime, stepTime) {
      let start = this.Cesium.JulianDate.fromDate(new Date(startTime));  // 设置时间轴当前时间为开始时间
      let stop = this.Cesium.JulianDate.fromDate(new Date(endtime));
      // 添加8小时，使地图时间和北京时间相同
      start = this.Cesium.JulianDate.addHours(start, 8, new this.Cesium.JulianDate());
      stop = this.Cesium.JulianDate.addHours(stop, 8, new this.Cesium.JulianDate());
      // 设置时钟开始时间
      this.$data._viewer2D.clock.startTime = start.clone();
      this.$data._viewer3D.clock.startTime = start.clone();
      // 设置时钟当前时间
      this.$data._viewer2D.clock.currentTime = start.clone();
      this.$data._viewer3D.clock.currentTime = start.clone();
      // 设置时钟结束时间
      this.$data._viewer2D.clock.stopTime = stop.clone();
      this.$data._viewer3D.clock.stopTime = stop.clone();
      // 时间速率，数字越大时间过的越快，设置1好像是和实际时间一样
      this.$data._viewer2D.clock.multiplier = stepTime;
      this.$data._viewer3D.clock.multiplier = stepTime;
      // 时间轴绑定到viewer上去
      this.$data._viewer2D.timeline.zoomTo(start, stop);
      this.$data._viewer3D.timeline.zoomTo(start, stop);
      // 循环执行，到达终止时间，重新从起点时间开始
      this.$data._viewer2D.clock.clockRange = this.Cesium.ClockRange.LOOP_STOP;
      this.$data._viewer3D.clock.clockRange = this.Cesium.ClockRange.LOOP_STOP;
      this.messageList.push({
        order: this.order++,
        time: startTime,
        context: "开始模拟！！！"
      })
      this.$data._viewer2D.clock.onTick.addEventListener(clock => {
        const currentTime = clock.currentTime; // 获取当前时间轴的时间
        const elapsedTime = this.Cesium.JulianDate.secondsDifference(
          currentTime,
          this.$data._viewer2D.clock.startTime
        ); // 获取从起始时间到当前时间的秒数
        if (parseInt(elapsedTime) % stepTime === 0 && elapsedTime != 0) {
          // 当从起始时间到当前时间的秒数是 stepTime 的倍数时，发送请求
          this.requestDataAndUpdateModel2D(startTime, elapsedTime);
        }
      });
      this.$data._viewer3D.clock.onTick.addEventListener(clock => {
        const currentTime = clock.currentTime; // 获取当前时间轴的时间
        const elapsedTime = this.Cesium.JulianDate.secondsDifference(
          currentTime,
          this.$data._viewer3D.clock.startTime
        ); // 获取从起始时间到当前时间的秒数
        if (parseInt(elapsedTime) % stepTime === 0 && elapsedTime != 0) {
          // 当从起始时间到当前时间的秒数是 stepTime 的倍数时，发送请求
          this.requestDataAndUpdateModel3D(startTime, elapsedTime);
        }
      });
      this.initSTK()
    },
    // 初始化stk方法，生成轨迹文件
    async initSTK() {
      console.log('this.jsonData :>> ', this.jsonData);
      // await axios
      //   .get("/api", this.jsonData).then(res=>{
      //     console.log('res :>> ', res);
      //   })
      const config = {
        timeout: 0 // 设置超时时间为0，表示忽略超时问题
      };
      await axios
        .post("/api/traj", this.jsonData, config).then(res => {
          console.log('res :>> ', res);
          let data = res.data[1].data[0]
          for (let key in data) {
            let isSatellite = true
            //判断是否为卫星
            for (let i = 0; i < this.nameIdList.length; i++) {
              if (key === this.nameIdList[i].name || key === 'dateTime') {
                isSatellite = false
                break
              }
            }
            // 新建卫星实体
            if (isSatellite) {
              let range = 1000000
              console.log('key :>> ', key);
              let x = parseFloat(data[key].x) * 1000
              let y = parseFloat(data[key].y) * 1000
              let z = parseFloat(data[key].z) * 1000
              //终点位置
              let position = new this.Cesium.Cartesian3(x, y, z);
              let cylinderposition = this.convertWorldToCartographic(position)
              cylinderposition.height = cylinderposition.height / 10.0
              cylinderposition = this.Cesium.Cartesian3.fromDegrees(cylinderposition.longitude, cylinderposition.latitude, cylinderposition.height);
              this.$data._viewer2D.entities.add({
                id: this.id,
                position: position,
                point: {
                  pixelSize: 12, // 调整点的大小，可以增大点的像素大小
                  color: this.Cesium.Color.fromCssColorString('Blue')
                },
                // cylinder: {
                //   length: range, // 锥形的高度，可以根据需要调整
                //   topRadius: 0,
                //   bottomRadius: range / 2,
                //   material: this.Cesium.Color.BLUE.withAlpha(0.5), // 设置锥形的颜色和透明度
                //   outline: true,
                //   outlineColor: this.Cesium.Color.BLUE,
                // },
                model: {
                  uri: satelliteModel, // 替换为你的3D模型文件路径
                  scale: 1.0, // 调整3D模型的缩放大小
                  minimumPixelSize: 64 // 设置3D模型的最小像素大小，确保在视图中可见
                },
                label: {
                  text: 'satellite ' + key,
                  show: true,
                  font: "18px Helvetica", // 调整标签的字体样式和大小
                  pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移，向下偏移20像素
                }
              });
              this.$data._viewer2D.entities.add({
                id: this.id + 1,
                position: cylinderposition,
                cylinder: {
                  length: range, // 锥形的高度，可以根据需要调整
                  topRadius: 0,
                  bottomRadius: range / 2,
                  material: this.Cesium.Color.BLUE.withAlpha(0.5), // 设置锥形的颜色和透明度
                  outline: true,
                  outlineColor: this.Cesium.Color.BLUE,
                },
              });
              this.$data._viewer3D.entities.add({
                id: this.id,
                position: position,
                point: {
                  pixelSize: 12, // 调整点的大小，可以增大点的像素大小
                  color: this.Cesium.Color.fromCssColorString('Blue')
                },
                // cylinder: {
                //   length: range, // 锥形的高度，可以根据需要调整
                //   topRadius: 0,
                //   bottomRadius: range / 2,
                //   material: this.Cesium.Color.BLUE.withAlpha(0.5), // 设置锥形的颜色和透明度
                //   outline: true,
                //   outlineColor: this.Cesium.Color.BLUE,
                // },
                model: {
                  uri: satelliteModel, // 替换为你的3D模型文件路径
                  scale: 1.0, // 调整3D模型的缩放大小
                  minimumPixelSize: 64 // 设置3D模型的最小像素大小，确保在视图中可见
                },
                label: {
                  text: 'satellite ' + key,
                  show: true,
                  font: "18px Helvetica", // 调整标签的字体样式和大小
                  pixelOffset: new this.Cesium.Cartesian2(0, 20) // 调整标签的像素偏移，向下偏移20像素
                },
              });
              this.$data._viewer3D.entities.add({
                id: this.id + 1,
                position: cylinderposition,
                cylinder: {
                  length: range, // 锥形的高度，可以根据需要调整
                  topRadius: 0,
                  bottomRadius: range / 2,
                  material: this.Cesium.Color.BLUE.withAlpha(0.5), // 设置锥形的颜色和透明度
                  outline: true,
                  outlineColor: this.Cesium.Color.BLUE,
                },
              });
              this.nameIdList.push({
                id: this.id,
                name: key
              })
              this.satelliteRange.push({
                satelliteId: this.id,
                rangeId: this.id + 1
              })
              this.id++;
              this.id++;
            }
          }
        })

    },
    // 根据时间参数请求模型位置并更新 2D
    async requestDataAndUpdateModel2D(startTime, elapsedTime) {
      const jsDate = new Date(startTime);
      // 增加 elapsedTime 秒
      jsDate.setSeconds(jsDate.getSeconds() + elapsedTime);
      // 转换为需求字符串格式
      const newTimeString = `${jsDate.getFullYear()}-${(jsDate.getMonth() + 1).toString().padStart(2, '0')}-${jsDate.getDate().toString().padStart(2, '0')} ${jsDate.getHours().toString().padStart(2, '0')}:${jsDate.getMinutes().toString().padStart(2, '0')}:${jsDate.getSeconds().toString().padStart(2, '0')}`;
      await axios
        .post("/api/pos", { simulation_time: newTimeString + '.000' }).then(res => {
          console.log('res :>> ', res);
          let data = res.data[1].data
          //依次更新每个模型位置
          for (let i = 0; i < this.nameIdList.length; i++) {
            if (data[this.nameIdList[i].name] != null && data[this.nameIdList[i].name] != undefined) {
              this.modelEntityMoveByIDAndLocation(this.$data._viewer2D, this.nameIdList[i].id, data[this.nameIdList[i].name].x, data[this.nameIdList[i].name].y, data[this.nameIdList[i].name].z)
            }
          }
          for (let i = 0; i < this.nameIdList.length; i++) {
            if (this.thaadList[this.nameIdList[i].name] != null || this.thaadList[this.nameIdList[i].name] != undefined) {
              //查看在雷达原侦察范围内有几颗导弹
              let missileNum = this.howManyMissile(this.$data._viewer2D, this.thaadList[this.nameIdList[i].name].id, this.nameIdList[i].name)
              let health = 100.0
              for (let j = 0; j < missileNum; j++) {
                health = health * 0.8
              }
              if (this.thaadList[this.nameIdList[i].name].health != health) {
                //修改健康值并修改范围
                let mark = true
                if (health > this.thaadList[this.nameIdList[i].name].health) {
                  mark = false
                }
                this.thaadList[this.nameIdList[i].name].health = health
                this.changeRange(this.$data._viewer2D, this.thaadList[this.nameIdList[i].name].id, this.thaadList[this.nameIdList[i].name].range, this.thaadList[this.nameIdList[i].name].health, newTimeString, this.nameIdList[i].name, mark)
              }
            }
          }
          this.judgeMissile(this.$data._viewer2D, newTimeString);
          //判断攻防是否结束
          if (this.ifFinish(this.$data._viewer3D, newTimeString)) {
            // 停止时间轴动画
            this.$data._viewer2D.clock.shouldAnimate = false;
            this.dialogVisible = true
          }

          //更新模型位置
          // this.modelEntityMoveByIDAndLocation(this.$data._viewer2D,"1654426964397658112",res.data[1].data.W1.x,res.data[1].data.W1.y,res.data[1].data.W1.z)
        })

    },
    // 根据时间参数请求模型位置并更新 3D
    async requestDataAndUpdateModel3D(startTime, elapsedTime) {
      const jsDate = new Date(startTime);
      // 增加 elapsedTime 秒
      jsDate.setSeconds(jsDate.getSeconds() + elapsedTime);
      // 转换为需求字符串格式
      const newTimeString = `${jsDate.getFullYear()}-${(jsDate.getMonth() + 1).toString().padStart(2, '0')}-${jsDate.getDate().toString().padStart(2, '0')} ${jsDate.getHours().toString().padStart(2, '0')}:${jsDate.getMinutes().toString().padStart(2, '0')}:${jsDate.getSeconds().toString().padStart(2, '0')}`;
      await axios
        .post("/api/pos", { simulation_time: newTimeString + '.000' }).then(res => {
          let data = res.data[1].data

          //依次更新每个模型位置
          for (let i = 0; i < this.nameIdList.length; i++) {
            if (this.nameIdList[i].name in data) {
              console.log(' 开始移动' + this.nameIdList[i].name);
              this.modelEntityMoveByIDAndLocation(this.$data._viewer3D, this.nameIdList[i].id, data[this.nameIdList[i].name].x, data[this.nameIdList[i].name].y, data[this.nameIdList[i].name].z)
            }
          }
          for (let i = 0; i < this.nameIdList.length; i++) {
            if (this.thaadList[this.nameIdList[i].name] != null || this.thaadList[this.nameIdList[i].name] != undefined) {
              //查看在雷达原侦察范围内有几颗导弹
              let missileNum = this.howManyMissile(this.$data._viewer3D, this.thaadList[this.nameIdList[i].name].id, this.nameIdList[i].name)
              let health = 100.0
              //变化健康值
              for (let j = 0; j < missileNum; j++) {
                health = health * 0.8
              }
              if (this.thaadList[this.nameIdList[i].name].health != health) {
                //修改健康值并修改范围
                let mark = true
                if (health > this.thaadList[this.nameIdList[i].name].health) {
                  mark = false
                }
                this.thaadList[this.nameIdList[i].name].health = health
                this.changeRange(this.$data._viewer3D, this.thaadList[this.nameIdList[i].name].id, this.thaadList[this.nameIdList[i].name].range, this.thaadList[this.nameIdList[i].name].health, newTimeString, this.nameIdList[i].name, mark)
              }

            }
          }
          //判断是否有导弹被拦截
          this.judgeMissile(this.$data._viewer3D, newTimeString);
          //判断攻防是否结束
          if (this.ifFinish(this.$data._viewer3D, newTimeString)) {
            // 停止时间轴动画
            this.$data._viewer3D.clock.shouldAnimate = false;
            this.dialogVisible = true
          }

          //更新模型位置
          //  this.modelEntityMoveByIDAndLocation(this.$data._viewer3D,viewer,"1654426964397658112",res.data[1].data.W1.x,res.data[1].data.W1.y,res.data[1].data.W1.z)  
        })
    },
    // 根据模型实体Id和终点位置进行移动
    modelEntityMoveByIDAndLocation(viewer, id, x, y, z) {
      x = parseFloat(x) * 1000
      y = parseFloat(y) * 1000
      z = parseFloat(z) * 1000
      let entity = viewer.entities.getById(id)
      for (let i = 0; i < this.satelliteRange.length; i++) {
        if (id == this.satelliteRange[i].satelliteId) {
          //是卫星
          let rangeEntity = viewer.entities.getById(this.satelliteRange[i].rangeId)
          let position = new this.Cesium.Cartesian3(x, y, z);
          let cylinderposition = this.convertWorldToCartographic(position)

          cylinderposition = this.Cesium.Cartesian3.fromDegrees(cylinderposition.longitude, cylinderposition.latitude, cylinderposition.height / 10.0);
          let oldPosition = viewer.entities.getById(id).position._value
          //设置方向,根据实体的位置来配置方向
          entity.orientation = new this.Cesium.VelocityOrientationProperty(entity.position);
          //设置实体位置
          entity.position.setValue(position)
          //设置方向,根据实体的位置来配置方向
          rangeEntity.orientation = new this.Cesium.VelocityOrientationProperty(rangeEntity.position);
          //设置实体位置getValue
          rangeEntity.position.setValue(cylinderposition)
          this.markSatelliteLine(oldPosition, position, 'Blue', viewer)
        }
      }
      //终点位置
      let position = new this.Cesium.Cartesian3(x, y, z);
      let oldPosition = viewer.entities.getById(id).position._value
      //设置方向,根据实体的位置来配置方向
      entity.orientation = new this.Cesium.VelocityOrientationProperty(entity.position);
      //设置实体位置
      entity.position.setValue(position)
      this.markSatelliteLine(oldPosition, position, 'Blue', viewer)
    },
    //计算有多少个导弹进入了雷达的原始范围
    howManyMissile(viewer, id, name) {
      let radar = viewer.entities.getById(id)
      let radarPos = radar.position._value
      let num = 0
      for (let key in this.missileList) {
        let missilePos = viewer.entities.getById(this.missileList[key].id).position._value
        if (this.Cesium.Cartesian3.distance(radarPos, missilePos) <= this.thaadList[name].range) {//距离小于range
          num++
        }
      }
      return num;
    },
    //判断导弹是否被拦截
    judgeMissile(viewer, time) {
      for (let key in this.missileList) {
        let missile = viewer.entities.getById(this.missileList[key].id)
        let missilePos = viewer.entities.getById(this.missileList[key].id).position._value
        for (let item in this.thaadList) {
          let radarPos = viewer.entities.getById(this.thaadList[item].id).position._value
          if (this.Cesium.Cartesian3.distance(radarPos, missilePos) <= this.thaadList[item].range * this.thaadList[item].health * 0.01) {
            // 导弹进入了被干扰后的雷达探测范围，判断被拦截 移除实体，删除信息
            this.messageList.push({
              order: this.order++,
              time: time,
              context: '导弹' + key + '被雷达' + item + '拦截！！！'
            })
            viewer.entities.remove(missile)
            this.nameIdList = this.nameIdList.filter(item => item.id !== this.missileList[key].id);
            delete this.missileList[key]
            break
          }
        }
      }
    },
    //修改雷达的显示范围
    changeRange(viewer, id, range, health, time, name, mark) {
      let context = '雷达' + name + '受到干扰！健康值变化为： ' + health
      if (!mark) {
        context = '雷达' + name + '恢复健康值，健康值变化为： ' + health
      }
      this.messageList.push({
        order: this.order++,
        time: time,
        context: context
      })
      let radar = viewer.entities.getById(id)
      let newRange = range * health * 0.01
      radar.ellipsoid.radii = new this.Cesium.Cartesian3(newRange, newRange, newRange);
    },
    isObjectEmpty(obj) {
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      return false; // 如果对象有任何属性，返回 false
    }
  }
  return true; // 如果对象没有任何属性，返回 true
},
    //判断攻防是否完成
    ifFinish(viewer, time) {
      if (this.isObjectEmpty(this.missileList)) {
        this.messageList.push({
          order: this.order,
          time: time,
          context: '全部导弹被拦截，红方进攻失败，蓝方防守成功！！！'
        })
        return true
      }
      else {
        for (let key in this.missileList) {
          let missilePos = viewer.entities.getById(this.messageList[key].id).position._value
          if (this.Cesium.Cartesian3.distance(this.centerPosition, missilePos) <= 100) {
            this.messageList.push({
              order: this.order,
              time: time,
              context: '导弹' + key + '成功摧毁蓝方指挥中心！！！'
            })
            return true
          }
        }
      }
      return false
    }

  }
};
</script>
<style scoped>
::v-deep .cesium-infoBox {
  display: none !important;
}

::v-deep .cesium-infoBox-bodyless {
  display: none !important;
}

::v-deep .cesium-infoBox-visible {
  display: none !important;
}

.container {
  height: 100%;
  position: relative;
}

.modeltooltip {
  position: absolute;
  padding: 5px;
  color: #fff;
  font-size: 20px;
  pointer-events: none;
  z-index: 999;
}

.myHeader {
  background-color: #1c222b !important;
  color: #fff;
  height: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
  /*由于flex-direction: column，因此align-items代表的是水平方向*/
  justify-content: center;
  /*由于flex-direction: column，因此justify-content代表的是垂直方向*/
}

.myHeader .el-button {
  width: 100px;
  height: 20px;
  padding: 1px 23px;
}

.box-card {
  min-height: 100%;
  height: 100%;
}

::v-deep .el-card__body {
  height: 100% !important;
  padding: 0px !important;
}

.main-layout {
  height: 100%;
  width: 100%;
}

.map {
  width: 100%;
  height: 100%;
}

.menu {
  position: absolute;
  height: 400px;
  z-index: 999;
  left: 20px;
  top: 20px;
}

::v-deep .el-tabs--left .el-tabs__header.is-left {
  margin-right: 0px !important;
}

.buttons {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-items: center;
  position: absolute;
  z-index: 999;
  right: 20px;
  top: 20px;
}

.el-button {
  margin: 5px !important;
}

::v-deep .el-tabs--border-card>.el-tabs__content {
  width: 300px;
  height: 100%;
  overflow-y: visible;
}

.model {
  display: flex;
  width: 100%;
  flex-wrap: wrap;
}

.model>div {
  width: 50%;
  height: 120px;
  padding: 5px;
}

.model>div:hover {
  border: 2px solid blue;
}

.model>div:active {
  border: 2px solid red;
}

.active {
  border: 2px solid red !important;
}

.model .el-image {
  display: block !important;
}

::v-deep .el-image .el-image__inner {
  border: 1px solid #ddd;
  border-radius: 5px;
}

.item {
  font-size: 14px;
  /* right: 20px; */
}

.TimeLine {
  position: absolute;
  left: 21%;
  bottom: 15px;
  transform: translateX(-50%);
}

/* 罗盘样式 */
/deep/.compass {
  pointer-events: auto;
  position: absolute;
  right: 0px;
  top: 280px;
  width: 95px;
  height: 95px;
  overflow: hidden;
}
</style>
