基于廊坊系统为基础,国防科技大学系统演示Demo
lixuliang
2024-04-29 415eb8a7e065301203568dd4e2d9c9dbdbe51f14
图层树
已添加5个文件
已修改5个文件
2836 ■■■■■ 文件已修改
src/components/demoAnimation/animationEdit.vue 595 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/demoAnimation/dataTree.vue 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/index.js 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/layerTree.js 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/mapStatus.js 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/mapTools.js 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Tools/LayerTree.vue 1857 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Tools/baseVuex.js 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Tools/maplayer.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/demoAnimation/animationEdit.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,595 @@
<template>
  <div>
    <Popup ref="demo" :title="title" :left="left" :top="top" @close="close">
      <div class="topbtn">
        <el-button type="primary" @click="pause(true)" v-if="isPlay"
          >暂停</el-button
        >
        <el-button
          type="primary"
          @click="pause(false)"
          v-if="!isPlay && playIndex"
          >ç»§ç»­</el-button
        >
        <el-button type="primary" @click="stop" v-if="isPlay || playIndex"
          >停止</el-button
        >
        <el-button
          type="primary"
          @click="start(undefined)"
          v-if="!isPlay && !playIndex"
          >开始播放</el-button
        >
        <el-button type="primary" @click="save">保存</el-button>
      </div>
      <div class="dataTable" v-contextmenu:contextmenu>
        <el-table
          ref="table"
          @cell-mouse-enter="mouseIn"
          @cell-mouse-leave="mouseOut"
          @row-contextmenu="rightClick"
          @row-dblclick="rowClick"
          :data="animationData"
          style="width: 100%"
          border
          max-height="450"
          highlight-current-row
        >
          <el-table-column
            label="ID"
            type="index"
            width="40px"
            align="center"
            :resizable="false"
          >
          </el-table-column>
          <el-table-column
            type="index"
            width="100px"
            label="类型"
            align="center"
            :resizable="false"
          >
            <template slot-scope="scope">
              <el-popover
                placement="top-start"
                title="位置信息"
                width="260"
                trigger="hover"
                v-if="scope.row.type === '位置'"
              >
                <div style="text-align: right; margin: 0">
                  <el-input
                    placeholder="请输入经度"
                    v-model="scope.row.view.lon"
                  >
                    <template slot="prepend">经度:</template>
                  </el-input>
                  <el-input
                    placeholder="请输入维度"
                    v-model="scope.row.view.lat"
                    style="margin-top: 5px"
                  >
                    <template slot="prepend">维度:</template>
                  </el-input>
                  <el-input
                    placeholder="请输入高度"
                    v-model="scope.row.view.height"
                    style="margin-top: 5px"
                  >
                    <template slot="prepend">高度:</template>
                  </el-input>
                  <!-- <el-button type="primary"
                    style="margin-top: 5px;">确定</el-button> -->
                </div>
                <el-button slot="reference" size="mini">
                  {{
                    scope.row.type === "位置" ? "位置" : scope.row.actionType
                  }}</el-button
                >
              </el-popover>
              <div size="medium" v-if="scope.row.type !== '位置'">
                {{ scope.row.type === "位置" ? "位置" : scope.row.actionType }}
              </div>
            </template>
          </el-table-column>
          <el-table-column
            label="描述"
            align="center"
            width=" 180px"
            :resizable="false"
          >
            <template slot-scope="scope">
              <el-input size="medium" v-model="scope.row.description">
              </el-input>
            </template>
          </el-table-column>
          <el-table-column
            label="响应方式"
            align="center"
            width="100px"
            :resizable="false"
          >
            <template slot-scope="scope">
              <el-select
                v-model="scope.row.value"
                @change="change(scope.row.value, scope.$index)"
                placeholder="请选择"
              >
                <el-option label="点击" value="0"> </el-option>
                <el-option label="立即" value="1"> </el-option>
                <el-option label="等待" value="2"> </el-option>
              </el-select>
            </template>
          </el-table-column>
          <el-table-column
            label="等待时间(秒)"
            align="center"
            :resizable="false"
            width="130px"
          >
            <template slot-scope="scope">
              <el-input-number
                controls-position="right"
                v-model="scope.row.time"
                :disabled="scope.row.value !== '2'"
              >
              </el-input-number>
            </template>
          </el-table-column>
          <el-table-column
            label="操作"
            align="center"
            width="200px"
            :resizable="false"
          >
            <template slot-scope="scope">
              <el-button-group class="btncontainer">
                <el-button
                  type="primary"
                  icon="el-icon-arrow-up"
                  @click="moveUp(scope.$index)"
                  :disabled="scope.$index == 0"
                ></el-button>
                <el-button
                  type="primary"
                  icon="el-icon-arrow-down"
                  @click="moveDown(scope.$index)"
                  :disabled="scope.$index == animationData.length - 1"
                ></el-button>
                <el-popconfirm
                  title="确定删除吗?"
                  @confirm="remove(scope.$index)"
                >
                  <el-button
                    slot="reference"
                    type="primary"
                    icon="el-icon-delete"
                  ></el-button>
                </el-popconfirm>
              </el-button-group>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <v-contextmenu ref="contextmenu" v-model="showRightMenu">
        <v-contextmenu-item @click="addData('location')"
          >添加位置</v-contextmenu-item
        >
        <v-contextmenu-submenu title="添加操作">
          <v-contextmenu-item @click="addData('action', '显示对象')"
            >显示对象</v-contextmenu-item
          >
          <v-contextmenu-item @click="addData('action', '隐藏对象')"
            >隐藏对象</v-contextmenu-item
          >
          <v-contextmenu-item @click="undergroundMode(true)"
            >开启地下模式</v-contextmenu-item
          >
          <v-contextmenu-item @click="undergroundMode(false)"
            >关闭地下模式
          </v-contextmenu-item>
        </v-contextmenu-submenu>
        <v-contextmenu-item
          @click="updateLocation"
          v-if="selectItem.type === '位置'"
          >更新位置</v-contextmenu-item
        >
        <v-contextmenu-item
          @click="updateAction"
          v-if="selectItem.type === '操作' && !selectItem.isUnderground"
          >更新操作</v-contextmenu-item
        >
      </v-contextmenu>
    </Popup>
    <div class="controlbtn" v-if="isPlay || playIndex">
      <el-button-group>
        <el-button
          type="primary"
          icon="el-icon-video-play"
          circle
          @click="next"
        ></el-button>
        <!-- <el-button type="primary" icon="el-icon-video-pause" circle></el-button> -->
        <el-button
          type="primary"
          icon="el-icon-close"
          @click="stop"
          circle
        ></el-button>
      </el-button-group>
    </div>
    <dataTree ref="dataTree" @success="getTreedata" @updateData="updateData" />
  </div>
</template>
<script>
import Popup from "@tools/Popup";
import dataTree from "@c/demoAnimation/dataTree";
import Bus from "@tools/Bus";
export default {
  name: "animationEdit",
  components: {
    Popup,
    dataTree,
  },
  data() {
    return {
      title: "演示动画",
      left: "calc(100% - 725px)",
      top: "10px",
      value: "0",
      selectItem: { type: "" },
      rightClickMenuStyle: {},
      rightClickMenuDisplay: false,
      animationData: [], // ä¸€ç»„动画的一系列片段
      nodeId: "", // å½“前操作演示动画id
      showRightMenu: false,
      playIndex: 0,
      palyingAnimation: [], //正在播放的数据
      isPlay: false, // æ˜¯å¦æ­£åœ¨æ’­æ”¾
      showControl: false,
    };
  },
  methods: {
    open(id, data) {
      this.nodeId = id;
      if (data) {
        this.animationData = data;
      }
      this.$refs.demo.open();
    },
    close() {
      this.nodeId = "";
      this.animationData = [];
      this.save();
      this.stop();
    },
    // èŽ·å–ä¸‹æ ‡
    getIndexById(id) {
      for (let i = 0; i < this.animationData.length; i++) {
        if (this.animationData[i].id === id) {
          return i;
        }
      }
      return undefined;
    },
    // ä¸Šç§»
    moveUp(index) {
      const upDate = this.animationData[index - 1];
      this.animationData.splice(index - 1, 1);
      this.animationData.splice(index, 0, upDate);
    },
    // ä¸‹ç§»
    moveDown(index) {
      const downDate = this.animationData[index + 1];
      this.animationData.splice(index + 1, 1);
      this.animationData.splice(index, 0, downDate);
    },
    // åˆ é™¤
    remove(index) {
      this.animationData.splice(index, 1);
    },
    //获取视角
    getView() {
      let degrees = sgworld.Navigate.getDegrees(); //经纬度
      let heading = Cesium.Math.toDegrees(Viewer.camera.heading); //水平角
      let pitch = Cesium.Math.toDegrees(Viewer.camera.pitch); //俯仰角度
      return {
        lon: degrees.lon.toFixed(6),
        lat: degrees.lat.toFixed(6),
        height: degrees.height.toFixed(2),
        heading,
        pitch,
      };
    },
    // èŽ·å–æ ‘ä¸­è®°å½•çš„æ•°æ®
    getTreedata(selectInfo, actionType) {
      let obj = {
        id: window.sgworld.Core.getuid(),
        description: "此处编辑描述",
        actionType, //记录 æ“ä½œçš„种类
        type: "操作",
        selectInfo,
        value: "1",
        time: undefined,
        isClick: false,
      };
      if (this.selectItem && this.selectItem.id) {
        let index = this.getIndexById(this.selectItem.id);
        this.animationData.splice(index + 1, 0, obj);
      } else {
        this.animationData.push(obj);
      }
    },
    // æ·»åŠ è®°å½•
    addData(type, actionType) {
      if (type === "action") {
        this.$refs.dataTree.open(actionType);
      } else {
        let location = this.getView();
        let obj = {
          id: window.sgworld.Core.getuid(),
          description: "此处编辑描述",
          type: "位置",
          view: location,
          value: "1",
          time: undefined,
          isClick: false,
        };
        if (this.selectItem) {
          let index = this.getIndexById(this.selectItem.id);
          this.animationData.splice(index + 1, 0, obj);
        } else {
          this.animationData.push(obj);
        }
      }
    },
    // åœ°ä¸‹æ¨¡å¼
    undergroundMode(val) {
      let actionType = val ? "开启地下模式" : "关闭地下模式";
      let obj = {
        id: window.sgworld.Core.getuid(),
        isUnderground: true,
        description: "此处编辑描述",
        actionType,
        type: "操作",
        value: "1",
        time: undefined,
        isClick: false,
      };
      if (this.selectItem) {
        let index = this.getIndexById(this.selectItem.id);
        this.animationData.splice(index + 1, 0, obj);
      } else {
        this.animationData.push(obj);
      }
    },
    // æ›´æ–°ä½ç½®
    updateLocation() {
      if (this.selectItem && this.selectItem.type === "位置") {
        let location = this.getView();
        let index = this.getIndexById(this.selectItem.id);
        if (this.animationData[index].view) {
          this.animationData[index].view = location;
        }
      }
    },
    // æ›´æ–°æ“ä½œ
    updateAction() {
      if (this.selectItem && this.selectItem.type === "操作") {
        this.$refs.dataTree.open(
          this.selectItem.actionType,
          this.selectItem.selectInfo,
          true
        );
      }
    },
    //保存更新
    updateData(newData) {
      let index = this.getIndexById(this.selectItem.id);
      this.animationData[index].selectInfo = newData;
    },
    // ä¿å­˜
    save() {
      this.$emit("success", this.nodeId, this.animationData);
    },
    // å¼€å§‹æ’­æ”¾
    start(data) {
      if (data) {
        this.animationData = data;
      }
      this.playIndex = 0;
      this.isPlay = true;
      this.display();
    },
    // æ’­æ”¾
    display(data, click = false) {
      if (data) {
        this.stop();
        this.playIndex = this.getIndexById(data.id);
        this.isPlay = true;
        click = true;
      }
      if (this.playIndex > this.animationData.length - 1) {
        this.stop();
        return;
      } else if (!this.isPlay) {
        return;
      }
      let thisPlay = this.animationData[this.playIndex];
      this.$refs.table && this.$refs.table.setCurrentRow(thisPlay);
      if (thisPlay.isClick && !click) {
        this.playIndex--;
      } else {
        if (thisPlay.type === "位置") {
          let position = thisPlay.view;
          let maximumHeight =
            position.height < 0 && Viewer.camera.positionCartographic.height < 0
              ? Math.max([
                  position.height,
                  Viewer.camera.positionCartographic.height,
                ])
              : undefined;
          Viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(
              position.lon,
              position.lat,
              position.height
            ),
            orientation: {
              heading: Cesium.Math.toRadians(position.heading),
              pitch: Cesium.Math.toRadians(position.pitch),
              roll: 0,
            },
            maximumHeight,
          });
        } else if (thisPlay.type === "操作") {
          let show;
          if (thisPlay.actionType === "显示对象") {
            show = true;
          } else if (thisPlay.actionType === "隐藏对象") {
            show = false;
          }
          if (thisPlay.actionType === "开启地下模式") {
            sgworld.Analysis.UndergroundMode(true, 0.5);
          } else if (thisPlay.actionType === "关闭地下模式") {
            sgworld.Analysis.UndergroundMode(false);
          }
          this.$emit("setAnimation", thisPlay.selectInfo, show);
        }
        let time = 0;
        if (thisPlay.type === "位置") {
          time = 3;
        }
        if (thisPlay.time) {
          this.timeOut(() => {
            // å®šæ—¶
            this.playIndex++;
            this.display();
          }, thisPlay.time + time);
        } else {
          this.timeOut(() => {
            this.playIndex++;
            this.display();
          }, time);
        }
      }
    },
    next() {
      this.playIndex++;
      this.display(undefined, true);
    },
    // åœæ­¢
    stop() {
      clearTimeout(this.time);
      sgworld.Navigate.Stop(); //取消飞行状态
      this.$refs.table && this.$refs.table.setCurrentRow();
      window.sgworld.Analysis.UndergroundMode(false, 0.5);
      this.playIn;
      this.playIndex = 0;
      this.isPlay = false;
    },
    //暂停
    pause(val) {
      this.isPlay = !this.isPlay;
      if (!val) {
        this.display();
      }
    },
    timeOut(callback, time) {
      clearTimeout(this.time);
      this.time = setTimeout(callback, time * 1000);
    },
    change(value, index) {
      switch (value) {
        case "0":
          this.animationData[index].isClick = true;
          this.animationData[index].time = undefined;
          break;
        case "1":
          this.animationData[index].time = undefined;
          this.animationData[index].isClick = false;
          break;
        case "2":
          this.animationData[index].time = 1;
          this.animationData[index].isClick = false;
          break;
      }
    },
    rowClick(row, column, event) {
      // this.display(row);
    },
    //鼠标操作
    mouseIn(row) {
      if (this.$refs.contextmenu.visible || this.$refs.dataTree.isOpen) {
        return;
      }
      this.selectItem = row;
    },
    mouseOut() {
      if (this.$refs.contextmenu.visible || this.$refs.dataTree.isOpen) {
        return;
      }
      this.selectItem = { type: "" };
    },
    rightClick(row, column, event) {
      if (row) {
        this.selectItem = row;
      }
    },
  },
  mounted() {
    Bus.$off("closeAnimationEdit");
    Bus.$on("closeAnimationEdit", () => {
      this.close();
      this.$refs.demo.close();
    });
  },
};
</script>
<style lang="less" scoped>
.topbtn {
  margin-left: 5px;
  .el-button {
    width: 100px;
  }
}
.popupBody {
  .dataTable {
    margin: 10px 5px;
    /deep/ .el-table__cell {
      padding: 7px 0 !important;
    }
    /deep/ .el-table__body-wrapper::-webkit-scrollbar {
      width: 10px;
      scrollbar-arrow-color: red;
    }
    // è®¾ç½®æ»šåŠ¨æ¡çš„èƒŒæ™¯è‰²å’Œåœ†è§’
    /deep/ .el-table__body-wrapper::-webkit-scrollbar-thumb {
      border-radius: 5px;
      -webkit-box-shadow: inset 0 0 5px rgba(218, 218, 218, 0.2);
      box-shadow: inset 0 0 5px rgba(218, 218, 218, 0.2);
      background: #797979;
      scrollbar-arrow-color: red;
    }
  }
}
.controlbtn {
  .el-button-group {
    width: 80px;
    position: fixed;
    top: 140px;
    left: 50%;
    right: 50%;
    z-index: 999;
    margin: auto auto;
  }
}
</style>
src/components/demoAnimation/dataTree.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,141 @@
<template>
  <Popup
    ref="pop"
    :title="title"
    @close="close"
    showBtn="true"
    @yes="sendData"
    @cancel="close(true)"
  >
    <div class="treeContainer">
      <el-tree
        ref="tree"
        show-checkbox
        :data="treeData"
        node-key="id"
        default-expand-all
        :render-content="renderContent"
        :expand-on-click-node="false"
        :auto-expand-parent="false"
        :default-checked-keys="defaultChecked"
      >
      </el-tree>
    </div>
  </Popup>
</template>
<script>
import Popup from "@tools/Popup";
import baseVuex from "../../views/Tools/baseVuex";
export default {
  name: "tree",
  components: { Popup },
  mixins: [baseVuex],
  data() {
    return {
      isOpen: false,
      title: "展示数据选取",
      actionType: "",
      defaultChecked: [],
      isUpdate: false,
    };
  },
  methods: {
    open(actionType, defaultChecked = [], isUpdate = false) {
      this.isUpdate = isUpdate;
      this.defaultChecked = defaultChecked;
      this.actionType = actionType;
      this.$refs.pop.open();
      this.isOpen = true;
    },
    close(isCancel) {
      Object.assign(this.$data, this.$options.data());
      if (isCancel) {
        this.$refs.pop.close();
      }
      this.isOpen = false;
    },
    // å®Œæˆé€‰æ‹©ï¼Œä¼ é€’数据
    sendData() {
      if (this.isUpdate) {
        this.$emit("updateData", this.$refs.tree.getCheckedKeys());
        this.close(true);
        return;
      }
      this.$emit("success", this.$refs.tree.getCheckedKeys(), this.actionType);
      this.close(true);
    },
    // æ¸²æŸ“
    renderContent(h, { node, data }) {
      return (
        <span class="custom-tree-node">
          <span>
            <i class={data.children ? "el-icon-folder" : ""}></i>
            {data.name}
          </span>
        </span>
      );
    },
  },
};
</script>
<style lang="less" scoped>
.treeContainer {
  max-height: 500px;
  overflow-y: auto;
  overflow-x: hidden;
  &::-webkit-scrollbar {
    /*滚动条整体样式*/
    width: 8px;
    /*高宽分别对应横竖滚动条的尺寸*/
    height: 8px;
    scrollbar-arrow-color: red;
  }
  &::-webkit-scrollbar-thumb {
    border-radius: 5px;
    -webkit-box-shadow: inset 0 0 5px rgba(218, 218, 218, 0.2);
    box-shadow: inset 0 0 5px rgba(218, 218, 218, 0.2);
    background: #797979;
    scrollbar-arrow-color: red;
  }
  &::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 5px rgba(218, 218, 218, 0.2);
    box-shadow: inset 0 0 5px rgba(218, 218, 218, 0.2);
    border-radius: 0;
    background: rgba(218, 218, 218, 0.1);
  }
  .el-tree {
    background: transparent;
    color: #fff;
  }
  /deep/ .el-tree-node__content:hover {
    background-color: rgba(245, 247, 250, 0.2);
  }
  /deep/ .el-tree-node:focus > .el-tree-node__content {
    background-color: rgba(245, 247, 250, 0.2);
  }
  /deep/ .custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 10px;
    i {
      margin-right: 5px;
    }
  }
}
.btnContainer {
  margin-top: 10px;
  display: flex;
  justify-content: space-evenly;
}
</style>
src/store/index.js
@@ -1,5 +1,8 @@
import Vue from 'vue';
import Vuex from 'vuex';
import layerTree from './modules/layerTree';
import mapStatus from './modules/mapStatus';
import mapTools from './modules/mapTools';
import { getToken, setToken, removeToken } from '@/utils/auth';
import { Loading, Message } from 'element-ui';
import { login, getPublicKey } from '@/api/api';
@@ -239,5 +242,9 @@
      commit('CHANGE_SETTING', data);
    },
  },
  modules: {},
  modules: {
    layerTree,
    mapStatus,
    mapTools,
  },
});
src/store/modules/layerTree.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
// éåŽ†èŠ‚ç‚¹
function ergodicNode(nodes) {
    if (nodes && nodes.length) {
        nodes.forEach((item) => {
            item.rename = false;
            item.children && ergodicNode(item.children);
        });
    }
}
/**
 * å›¾å±‚树数据
 */
export default {
    namespaced: true,
    state: {
        // å·¥ç¨‹æ ‘数据
        treeData: [],
    },
    mutations: {
        // å®šä¹‰å·¥ç¨‹æ ‘数据
        setTreeData(state, data = []) {
            ergodicNode(data);
            state.treeData = data;
        },
        // æ ‘指定位置增加子节点(必须标识为key)
        addTreeChildren({ treeData }, { parentNode, pid, item }) {
            if (!pid) {
                treeData.push(item)
                return;
            }
            (parentNode || treeData).forEach(ele => {
                if (ele.id === pid) {
                    if (ele.children) {
                        ele.children.push(item)
                    } else {
                        (parentNode || treeData).push(item)
                    }
                    return;
                } else {
                    if (ele.children) {
                        this.commit('layerTree/addTreeChildren', {
                            parentNode: ele.children,
                            pid,
                            item
                        })
                    }
                }
            })
        },
        // å‹¾é€‰èŠ‚ç‚¹
        checkTreeNode({ treeData }, { parentNode, id, checked }) {
            (parentNode || treeData).forEach(ele => {
                if (!id || (id && ele.id === id)) {
                    // id不存,勾选所有子节点,id存在,勾选当前节点
                    ele.checked = checked;
                    if (ele.children) {
                        this.commit('layerTree/checkTreeNode', { parentNode: ele.children, checked });
                    } else if (ele._children) {
                        this.commit('layerTree/checkTreeNode', { parentNode: ele._children, checked });
                    }
                    if (id) {
                        return;
                    }
                } else {
                    // é€’å½’
                    if (ele.children) {
                        this.commit('layerTree/checkTreeNode', {
                            parentNode: ele.children,
                            id,
                            checked
                        })
                    }
                }
            })
        },
        // æ›´æ–°èŠ‚ç‚¹æ•°æ®
        updataTreeNode({ treeData }, { parentNode, id, nodeValue, key, value }) {
            (parentNode || treeData).forEach(ele => {
                if (ele.id === id) {
                    if (nodeValue) {
                        for (let _key in nodeValue) {
                            if (nodeValue[_key] === undefined) {
                                delete ele[_key];
                            } else {
                                ele[_key] = nodeValue[_key];
                            }
                        }
                    } else {
                        ele[key] = value;
                    }
                    return;
                } else {
                    if (ele.children) {
                        this.commit('layerTree/updataTreeNode', {
                            parentNode: ele.children,
                            id,
                            nodeValue,
                            key,
                            value
                        })
                    }
                }
            })
        },
        // ç§»é™¤èŠ‚ç‚¹
        removeTreeNode({ treeData }, { id, parentNode }) {
            (parentNode || treeData).forEach((ele, index) => {
                if (ele.id === id) {
                    (parentNode || treeData).splice(index, 1)
                    return;
                } else {
                    if (ele.children) {
                        this.commit('layerTree/removeTreeNode', { id, parentNode: ele.children })
                    }
                }
            })
        }
    }
}
src/store/modules/mapStatus.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
/**
 * åœ°å›¾çŠ¶æ€
 */
export default {
    namespaced: true,
    state: {
        // åˆå§‹å®šä½
        viewCenter: [],
        // åœ°å›¾çŠ¶æ€
        mapStatus: {
            // åŒå‡»ç»•飞旋转速度
            rotateFlyTime: 30,
            // å¤ªé˜³å…‰
            sunLight: false,
            // å…‰ç…§å¼ºåº¦
            lightIntensity: 2,
            // å…‰ç…§é¢œè‰²
            lightColor: "#ffffff",
            // äº®åº¦
            brightness: 1,
            // å¯¹æ¯”度
            contrast: 1,
            // é¥±å’Œåº¦
            saturation: 1,
        }
    },
    mutations: {
        // å®šä¹‰å®šä½æ•°æ®
        setView(state, data = []) {
            for (let i = 0; i < data.length; i++) {
                data[i] = parseFloat(data[i]);
            }
            state.viewCenter = data;
        },
        // æ”¹å˜åœ°å›¾çŠ¶æ€
        changeMapStatus(state, { type, value }) {
            state.mapStatus[type] = value;
        }
    }
}
src/store/modules/mapTools.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
/**
 * åœ°å›¾æŽ§ä»¶
 */
export default {
    namespaced: true,
    state: {
        // å¤´éƒ¨å·¥å…·æ æ˜¯å¦æ”¶ç¼©
        hideTools: false,
        // å³ä¸Šè§’单位按钮
        hidePositionBtn: false,
        // åº•部状态栏是否显示
        statusbar: true,
        // å¯¼èˆªæŽ§ä»¶
        navBar: true,
        // æ¯”例尺控件
        scaleBarStatus: true
    },
    mutations: {
        changeMapToolsVisible(state, type) {
            state[type] = !state[type];
        },
        changeNavBarVisible(state) {
            state.navBar = !state.navBar
            window.sgworld.navControl('nav', state.navBar)
        },
        changeScaleBarVisible(state) {
            state.scaleBarStatus = !state.scaleBarStatus
            window.sgworld.navControl('scale', state.scaleBarStatus)
        },
    },
}
src/views/Tools/LayerTree.vue
@@ -1,1145 +1,926 @@
<template>
  <div class="lalala tree-container">
    <el-form ref="form">
      <el-form-item>
        <el-select
          v-model="$store.state.pigCode"
          clearable
          filterable
          style="width :100%"
          @change="prjChanged"
          placeholder="请选择项目"
  <div>
    <!-- <Popup
      ref="layer"
      :closeHidePage="true"
      :title="title"
      :left="left"
      :top="top"
      :maxHeight="maxHeight"
      @close="close"
    > -->
    <div class="treeContainer">
      <!-- <div class="treeTitle">
          <el-upload
            class="button-group"
            action=""
            :auto-upload="false"
            :show-file-list="false"
            :on-change="loadJsonFromFile"
            accept=".json"
        >
          <el-option
            v-for="item in menus"
            :key="item.code"
            :label="item.name"
            :value="item.code"
          >
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-input
          placeholder="输入关键字进行过滤"
          v-model="filterText"
          class="search"
        >
        </el-input>
      </el-form-item>
    </el-form>
            <el-button
              type="primary"
              size="mini"
              slot="trigger"
              icon="el-icon-folder-opened"
              title="打开配置文件"
            ></el-button>
            <el-button
              type="primary"
              size="mini"
              icon="el-icon-download"
              title="保存配置文件"
              @click="save"
            ></el-button>
          </el-upload>
        </div> -->
    <el-tree
      ref="tree"
      :data="treeData"
      node-key="id"
      show-checkbox
      :props="defaultProps"
      @node-click="handleLeftclick"
      @node-contextmenu="rightClick"
      @check="handleCheckChange"
      :default-checked-keys="handleTreeCheck"
        node-key="id"
        draggable
        :allow-drop="allowDrop"
      :expand-on-click-node="false"
      :filter-node-method="filterNode"
        :auto-expand-parent="false"
        :default-expanded-keys="defaultExpanded"
        :default-checked-keys="defaultCheck"
        @node-expand="changeNodeExpand($event, true)"
        @node-collapse="changeNodeExpand($event, false)"
        @check="check"
        @node-contextmenu="rightClick"
    >
      <span
        class="slot-t-node"
        slot-scope="{ node, data }"
          class="custom-tree-node"
          slot-scope="{ data }"
          @dblclick="flyTo(data)"
          @click="select(data)"
      >
        <span v-show="!data.isEdit">
          <span :class="[data.id >= 99 ? 'slot-t-node--label' : '']">{{
                              node.label
                            }}</span>
        </span>
        <span v-show="data.isEdit">
          <span>
            <i v-if="data.children" class="el-icon-folder"></i>
            <i
              v-else
              :class="
                data.sourceType === 'location' ? 'el-icon-location-outline' : ''
              "
            ></i>
          <el-input
            class="slot-t-input"
              v-if="data.rename"
              v-model="data.name"
            size="mini"
            autofocus
            v-model="data.label"
            :ref="'slotTreeInput' + data.id"
            @blur.stop="nodeBlur(node, data)"
            @keydown.native.enter="nodeBlur(node, data)"
              placeholder="请输入名称"
              @change="rename(data)"
              @blur="rename(data)"
          ></el-input>
            <span v-else>{{ data.name }}</span>
        </span>
      </span>
    </el-tree>
    <el-card
      class="box-card"
      ref="card"
    </div>
    <div
      class="rightClickMenu"
      v-if="rightClickMenuDisplay"
      :style="{ ...rightClickMenuStyle }"
      v-show="menuVisible"
    >
      <div
        class="edit"
        @click="showLayerAttribute()"
        v-if="showProp && !shwoHistogram"
      >
        <i class="el-icon-tickets"></i>&nbsp;&nbsp;属性
      <ul>
        <li @click="addFold"><i class="el-icon-plus"></i>添加目录</li>
        <li @click="addLayer"><i class="el-icon-plus"></i>添加图层</li>
        <li @click="addPosition">
          <i class="el-icon-location-outline"></i>添加定位
        </li>
        <li v-if="!isClickParent" @click="editTreeNode">
          <i class="el-icon-edit"></i>编辑
        </li>
        <li @click="openRename"><i class="el-icon-edit"></i>重命名</li>
        <li @click="deleteTreeNode"><i class="el-icon-delete"></i>删除</li>
      </ul>
      </div>
      <div
        class="edit"
        @click="positioning()"
        v-if="showLocal"
      >
        <i class="el-icon-tickets"></i>&nbsp;&nbsp;定位
      </div>
      <div
        class="edit"
        @click="pellucidity()"
        v-if="showOpacity"
      >
        <i class="el-icon-tickets"></i>&nbsp;&nbsp;透明度
      </div>
      <div
        class="edit"
        @click="histogram()"
        v-show="shwoHistogram"
      >
        <i class="el-icon-tickets"></i>&nbsp;&nbsp;钻孔柱状图
      </div>
      <div
        class="edit"
        v-show="shwoTileDown"
        @click="tileDownload()"
      >
        <i class="el-icon-download"></i>&nbsp;&nbsp;瓦片下载
      </div>
      <div
        class="edit"
        v-show="shwoAnnex"
        @click="annexDownload()"
      >
        <i class="el-icon-tickets"></i>&nbsp;&nbsp;附件
      </div>
    </el-card>
    <!-- </Popup> -->
    <!-- <add-terrain ref="addTerrain" @success="addSceneData" /> -->
    <!-- <add-online-map
      ref="addOnlineMap"
      @success="addOtherData('影像', $event)"
    /> -->
    <!-- <add-image ref="addImage" @success="addSceneData" /> -->
    <!-- <add-model ref="addModel" @success="addSceneData" /> -->
    <!-- <add-pathLayer ref="addPathLayer" @success="addSceneData" /> -->
    <!-- <add-wfs ref="addWfs" @success="addSceneData" /> -->
    <!-- <add-vector ref="addVector" @success="addSceneData" /> -->
    <!-- <add-geojson ref="addGeojson" @success="addSceneData" /> -->
    <!-- <add-other ref="addOther" @success="addSceneData" /> -->
    <!-- <get-scene ref="getScene" @success="openScene" /> -->
    <!-- <save-scene ref="saveScene" @success="saveScene" /> -->
    <!-- <select-data ref="select" @success="openThisTypePop" /> -->
    <animationEdit
      ref="animationEdit"
      @success="updateAnimation"
      @setAnimation="setAnimation"
    />
    <!-- <Video ref="video" @success="addSceneData"></Video>
    <Video3D ref="video3D" @success="addSceneData"></Video3D> -->
  </div>
</template>
<script>
import GeoJSON from "ol/format/GeoJSON.js";
import queryinfo from "./queryinfo.vue";
import { Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer } from "ol/layer";
import { perms_selectLayers, comprehensive_selectPubById, project_selectDirAll } from "../../api/api.js";
import Bus from "@tools/Bus";
import axios from "axios";
import baseVuex from "./baseVuex";
// import Popup from "@tools/Popup.vue";
// import AddImage from "./AddImage";
// import AddTerrain from "./AddTerrain";
// import AddModel from "./AddModel";
// import AddPathLayer from "./AddPathLayer";
// import AddWfs from "./AddWfs";
// import AddVector from "./AddVector";
// import AddGeojson from "./AddGeojson";
// import AddOther from "./AddOther";
// import SelectData from "./SelectData";
import animationEdit from "../../components/demoAnimation/animationEdit.vue";
// import AddOnlineMap from "./AddOnlineMap.vue";
// import GetScene from "./GetScene.vue";
// import SaveScene from "./SaveScene.vue";
// import Video from "@c/object/Video.vue";
// import Video3D from "@c/object/Video3D.vue";
// å·¥ç¨‹æ ‘工具
let _treeTool;
export default {
  name: "tree",
  components: { queryinfo },
  name: "Layer",
  components: {
    // Popup,
    // AddImage,
    // AddTerrain,
    // AddWfs,
    // AddVector,
    // AddGeojson,
    // AddModel,
    // AddPathLayer,
    // AddOther,
    // SelectData,
    animationEdit,
    // AddOnlineMap,
    // GetScene,
    // SaveScene,
    // Video,
    // Video3D,
  },
  mixins: [baseVuex],
  data() {
    return {
      isBusy: false, // æ­£å¿™
      lastPrjCode: "", // æœ€åŽé€‰æ‹©é¡¹ç›®ç¼–码
      showProp: false, // å±žæ€§
      shwoHistogram: false, // é’»å­”柱状图
      showLocal: false, // å®šä½
      showOpacity: false, // ä¸é€æ˜Žåº¦
      shwoTileDown: false, // ç“¦ç‰‡ä¸‹è½½
      menuVisible: false, // èœå•
      shwoAnnex: false,//附件
      levelArray: [ // é«˜ç¨‹æ•°ç»„
        0, 40000000, 20000000, 10000000, 5000000, 2000000, 1000000, 500000,
        250000, 200000, 100000, 50000, 17000, 9000, 5000, 2000, 1000, 500, 200,
        100, 50, 25, 10, 0,
      ],
      filterText: "", // å…³é”®å­—过滤
      currentData: "", // å½“前数据
      currentNode: "", // å½“前节点
      rightClickMenuStyle: {}, // å³é”®èœå•样式
      handleTreeCheck: [], // é»˜è®¤é€‰ä¸­é”®
      layerId: [
        "m_pipeline",
        "th_strategic_channel",
        "bs_project",
        "m_sitepoint",
      ],
      treeData: [], // æ ‘数据
      sourceData: [], // æºæ•°æ®
      defaultProps: { // é»˜è®¤å±žæ€§å€¼
        children: "children",
        label: "cnName",
      },
      mptLayer: [], // Mpt图层
      menus: [] // èœå•项
      title: "图层管理",
      left: "10px",
      top: "10px",
      maxHeight: "500px",
      defaultCheck: [],
      defaultExpanded: [],
      selectNode: undefined,
      rightClickMenuDisplay: false,
      rightClickMenuStyle: {},
      isClickParent: false,
      isNewFold: false,
      newFoldName: undefined,
      serverURL: "http://192.168.109.128:8080",
    };
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
  },
  mounted() {
    this.getMenus();
    this.$bus.$on("treeDataCopy", (res) => {
      this.$store.state.treeData = this.treeData;
      this.$store.state.checkedKeys = this.$refs.tree.getCheckedKeys();
    // èŽ·å–æœ¬åœ°é…ç½®æ–‡ä»¶
    if (this.$route.query.hasOwnProperty("layer")) {
      axios
        .get(`./layer/${this.$route.query.layer || "layer"}.json`)
        .then((data) => {
          data.name && sessionStorage.setItem("SmartEarthTitle", data.name);
          document.title = sessionStorage.getItem("SmartEarthTitle");
          this.setTreeData([]);
          this.initData(data.data);
    });
    if (this.$store.state.showAllLayers) {
      this.layersStart();
      this.$store.state.showAllLayers = false;
    } else if (this.treeData.length) {
      // å­˜åœ¨ç¼“存数据
      // åŠ è½½åœºæ™¯æ•°æ®
      this.loadDataToScene();
    } else {
      this.treeData = this.$store.state.treeData;
      this.$refs.tree.setCheckedKeys(this.$store.state.checkedKeys);
      axios.get(`/json/ZH链路.json`).then((data) => {
        this.setTreeData([]);
        this.initData(data.data);
      });
      // é»˜è®¤æ ‘结构
      // this.setTreeData([
      //   { id: "82A0C3DE", name: "影像", children: [] },
      //   { id: "82C3DE", name: "地形", children: [] },
      //   { id: "4FE10400", name: "模型", children: [] },
      //   { id: "0A51CF71", name: "矢量", children: [] },
      // ]);
      // åŠ è½½åœºæ™¯æ•°æ®
      this.loadDataToScene();
    }
    // æ‰“开弹窗
    // this.$refs.layer.open();
    // å®šä¹‰ä¸­è½¬ç«™äº‹ä»¶
    this.initBusEvent();
  },
  destroyed() {
    _treeTool = undefined;
  },
  methods: {
    // èŽ·å–èœå•
    async getMenus() {
      let data = await project_selectDirAll();
      if (data && data.code == 200) this.menus = data.result;
    close() {
      Bus.$emit("checkTab", "index/add/treeLayer", false);
    },
    // åˆå§‹åŒ–图层
    async layersStart() {
      let data = await perms_selectLayers();
      if (data.code != 200) {
        return this.$message.error("图层列表查询失败");
      }
      let checkKey = [], checkedLayers = [];
      let layers = data.result.filter((lyr) => {
        if (lyr.url && lyr.type == 2 && lyr.isShow == 1) {
          checkKey.push(lyr.id);
          if (lyr.serveType == "WMS") checkedLayers.push(lyr);
        }
        return lyr;
    // å®šä¹‰ä¸­è½¬ç«™äº‹ä»¶
    initBusEvent() {
      Bus.$off("addLayer");
      Bus.$on("addLayer", (type) => {
        this.selectNode = this.$refs.tree && this.$refs.tree.getCurrentNode();
        this.openThisTypePop(type);
      });
      // å­˜å‚¨é€‰ä¸­å›¾å±‚
      this.treeData = this.setTreeData(layers);
      this.sourceData = JSON.parse(JSON.stringify(this.treeData));
      this.$refs.tree.setCheckedKeys(checkKey);
      sessionStorage.setItem("checkedLayers", JSON.stringify(checkedLayers));
    },
    // è®¾ç½®æ ‘数据
    setTreeData(source) {
      /*let cloneData = JSON.parse(JSON.stringify(source)); // å¯¹æºæ•°æ®æ·±åº¦å…‹éš†
      return cloneData.filter((father) => {
        // å¾ªçŽ¯æ‰€æœ‰é¡¹
        let branchArr = cloneData.filter((child) => father.id == child.pid); // å¯¹æ¯”ID,分别上下级菜单,并返回数据
        branchArr.length > 0 ? (father.children = branchArr) : ""; // ç»™çˆ¶çº§æ·»åŠ ä¸€ä¸ªchildren属性,并赋值
        // å±žäºŽåŒä¸€å¯¹è±¡é—®é¢˜ï¼Œä¾‹å¦‚:令 a=b、c=1 ï¼Œç„¶åŽå†ä»¤ b.c=c ï¼Œé‚£ä¹ˆ a.c=b.c=c=1 ï¼›åŒç†ï¼ŒåŽç»­ä»¤ c.d=2 ,那么 a.c.d ä¹Ÿæ˜¯=2;
        return father.pid == 0; // è¿”回一级菜单
      });*/
      let arr = [];
      let data = JSON.parse(JSON.stringify(source));
      this.setTreeChildData(data, arr, 0);
      return arr;
    },
    // è®¾ç½®æ ‘子节点数据
    setTreeChildData(data, arr, pid) {
      let i = 0;
      while (i < data.length) {
        let d = data[i];
        if (d.pid == pid) {
          arr.push(d);
          data.splice(i, 1);
          continue;
      Bus.$off("addServerData");
      Bus.$on("addServerData", (data) => {
        this.selectNode = this.$refs.tree && this.$refs.tree.getCurrentNode();
        if (data.openProp) {
          this.openThisTypePop(data.sourceType, undefined, data);
        } else {
          this.addSceneData(data);
        }
        i++;
      }
      arr.sort(function (a, b) {
        return a.orderNum - b.orderNum;
      });
      for (let i in arr) {
        let children = [];
        this.setTreeChildData(data, children, arr[i].id);
        if (children.length) arr[i].children = children;
      Bus.$off("openLayer");
      Bus.$on("openLayer", (open = true) => {
        // æ‰“开弹窗
        // if (open) {
        //   this.$refs.layer.open();
        // } else {
        //   this.$refs.layer.close();
        // }
      });
      Bus.$off("openServerFile");
      Bus.$on("openServerFile", (open = true) => {
        // æ‰“开弹窗
        if (open) {
          this.$refs.getScene.open();
        } else {
          this.$refs.getScene.close();
        }
      });
      Bus.$off("saveServerFile");
      Bus.$on("saveServerFile", (open = true) => {
        // æ‰“开弹窗
        if (open) {
          this.$refs.saveScene.open();
        } else {
          this.$refs.saveScene.close();
        }
      });
      Bus.$off("saveFile");
      Bus.$on("saveFile", () => {
        // ä¿å­˜æ–‡ä»¶
        this.save();
      });
      Bus.$off("openFile");
      Bus.$on("openFile", (file) => {
        // JSON转为树
        this.loadJsonFromFile(file);
      });
      Bus.$off("addFile");
      Bus.$on("addFile", () => {
        this.selectNode = this.$refs.tree && this.$refs.tree.getCurrentNode();
        // æ·»åŠ æ–‡ä»¶
        this.append(this.selectNode);
      });
      Bus.$off("addOtherData");
      Bus.$on("addOtherData", (parentName, data) => {
        // æ·»åŠ å…¶ä»–æ•°æ®
        this.addOtherData(parentName, data);
      });
      Bus.$off("removeTreeNode");
      Bus.$on("removeTreeNode", (entity) => {
        // åˆ é™¤å…¶ä»–数据
        this.removeTreeNode({ id: entity.id });
      });
      Bus.$off("updataTreeNode");
      Bus.$on("updataTreeNode", (id, data) => {
        // æ›´æ–°å…¶ä»–数据
        this.updataTreeNode({
          id: id,
          nodeValue: data,
        });
      });
      Bus.$off("clearFirstParentNode");
      Bus.$on("clearFirstParentNode", (parentName) => {
        // æ¸…除所有对象
        this.clearFirstParentNode(parentName);
      });
      Bus.$off("editDemoAnimation");
      Bus.$on("editDemoAnimation", () => {
        this.editDemoAnimation();
      });
    },
    // è¯»å–json文件数据
    loadJsonFromFile(file) {
      let reader = new FileReader();
      reader.onload = (e) => {
        let data = JSON.parse(e.target.result);
        this.initData(data);
        debugger;
        window.localStorage.setItem("pathAnimation", data.pathAnimation);
      };
      reader.readAsText(file.raw);
    },
    // åˆå§‹åŒ–数据
    initData(data) {
      if (this.treeData.length) {
        this.removeChildData(this.treeData);
      }
      data.name && sessionStorage.setItem("SmartEarthTitle", data.name);
      // è®¾ç½®å·¥ç¨‹æ ‘数据
      this.setTreeData(data.children);
      // åˆå§‹å®šä½
      if (data.flyTo) {
        this.setView(data.flyTo);
      }
      // åŠ è½½åœºæ™¯æ•°æ®
      this.loadDataToScene();
    },
    // åŠ è½½æ•°æ®åˆ°åœºæ™¯
    loadDataToScene() {
      if (window.sgworld) {
        // å·¥ç¨‹æ ‘工具
        _treeTool = new window.TreeTool(window.sgworld);
        window.sgworld._treeTool = _treeTool;
        if (this.$refs.tree) {
          this.defaultCheck = [];
          this.defaultExpanded = [];
          // éåŽ†èŠ‚ç‚¹
          this.ergodicNode({ children: this.treeData });
        }
        // åˆå§‹å®šä½
        if (this.viewCenter.length) {
          this.flyTo({
            flyTo: this.viewCenter,
          });
        }
        document.title =
          sessionStorage.getItem("SmartEarthTitle") || "SmartEarth";
      } else {
        setTimeout(() => {
          this.loadDataToScene();
        }, 500);
      }
    },
    // èŠ‚ç‚¹èŽ·å¾—ç„¦ç‚¹äº‹ä»¶
    nodeBlur(node, data) {
      if (!data.label.length) return this.$message.error("菜单名不可为空!");
      if (data.isEdit) this.$set(data, "isEdit", false);
    // éåŽ†èŠ‚ç‚¹
    ergodicNode(node, addData = true) {
      node.rename = false;
      if (node.expanded) {
        this.defaultExpanded.push(node.id);
      }
      if (
        node.checked &&
        (!node.children || (node.children && !node.children.length))
      ) {
        this.defaultCheck.push(node.id);
        if (addData && node._children) {
          node._children.forEach((item) => {
            _treeTool.addData(item);
          });
        } else {
          addData && _treeTool.addData(node);
        }
      }
      if (node.children && node.children.length) {
        node.children.forEach((item) => {
          this.ergodicNode(item, addData);
        });
      }
    },
    // æ›´æ–°èŠ‚ç‚¹å±•å¼€çŠ¶æ€
    changeNodeExpand(data, expanded) {
      this.updataTreeNode({
        id: data.id,
        key: "expanded",
        value: expanded,
      });
    },
    // å‹¾é€‰
    check(treeNode, data) {
      let isCheck = data.checkedKeys.indexOf(treeNode.id) > -1;
      // å‹¾é€‰èŠ‚ç‚¹
      this.checkTreeNode({ id: treeNode.id, checked: isCheck });
      // æ›´æ–°åœºæ™¯æ•°æ®
      _treeTool.checkNode(treeNode, isCheck);
      // åªèƒ½åŒæ—¶åŠ è½½ä¸€ä¸ªåœ°å½¢
      if (
        isCheck &&
        treeNode.sourceType &&
        treeNode.sourceType.indexOf("terrain") > -1
      ) {
        let index = data.checkedNodes.findIndex((item) => {
          return (
            item.sourceType &&
            item.sourceType.indexOf("terrain") > -1 &&
            item.id !== treeNode.id
          );
        });
        if (index > -1) {
          // å–消勾选
          this.$refs.tree.setChecked(data.checkedNodes[index].id, false);
          this.checkTreeNode({
            id: data.checkedNodes[index].id,
            checked: false,
          });
        }
      }
    },
    // æ·»åŠ èŠ‚ç‚¹|文件夹
    append(data) {
      this.$confirm("请选择添加类型", "提示", {
        confirmButtonText: "数据",
        cancelButtonText: "文件夹",
        distinguishCancelAndClose: true,
        closeOnClickModal: false,
      })
        .then(() => {
          // é€‰æ‹©æ•°æ®
          this.selectData(data);
        })
        .catch((action) => {
          // æ·»åŠ æ–‡ä»¶å¤¹
          if (action === "cancel") {
            this.addFolder(data);
          }
        });
    },
    // æ·»åŠ æ–‡ä»¶å¤¹
    addFolder(data) {
      this.$prompt("请输入文件夹名称", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        inputValue: "新建文件夹",
        closeOnClickModal: false,
      })
        .then(({ value }) => {
          let newChild = {
            id: window.sgworld.Core.getuid(),
            name: value,
            rename: false,
            children: [],
          };
          this.addData(data, newChild);
        })
        .catch(() => {});
    },
    // é€‰æ‹©æ•°æ®
    selectData(data) {
      this.selectNode = data;
      this.$refs.select.open();
    },
    // æ‰“开对于类型的弹窗
    openThisTypePop(type, editData, defaultData) {
      switch (type) {
        case "wms":
        case "wmts":
        case "tdmap":
        case "txmap":
        case "gdmap":
        case "bdmap":
        case "local-map":
        case "arcgis":
          this.$refs.addImage.open(type, editData, defaultData);
          break;
        case "onlineMap":
          this.$refs.addOnlineMap.open(type, editData, defaultData);
          break;
        case "terrain":
        case "sgsterrain":
        case "arcgisterrain":
          this.$refs.addTerrain.open(type, editData, defaultData);
          break;
        case "CesiumGlobeTerrain":
          this.addSceneData({
            id: window.sgworld.Core.getuid(),
            name: "CesiumIon全球地形",
            sourceType: "CesiumGlobeTerrain",
          });
          break;
        case "b3dm":
        case "gltf":
          this.$refs.addModel.open(type, editData, defaultData);
          break;
        case "s3m":
          this.$refs.addModel.open(type, editData, defaultData);
          break;
        case "kml":
          this.$refs.addOther.open(type, editData, defaultData);
          break;
        case "wfs":
          this.$refs.addWfs.open(type, editData, defaultData);
          break;
        case "vector":
          this.$refs.addVector.open(type, editData, defaultData);
          break;
        case "geojson":
          this.$refs.addGeojson.open(type, editData, defaultData);
          break;
        case "pathLayer":
          this.$refs.addPathLayer.open(type, editData, defaultData);
          break;
        case "videoBox":
          this.$refs.video.open(type, editData, defaultData);
          break;
        case "video3D":
          this.$refs.video3D.open(type, editData, defaultData);
          break;
      }
    },
    openScene(filedata) {
      //http://localhost/iisweb/%E5%B7%A5%E7%A8%8B%E5%90%8D%E7%A7%B0.json
      //"../upload/" + filedata.name + ".json"
      axios
        .get("../upload/" + filedata.name + ".json")
        .then((data) => {
          let json = data.data;
          this.initData(json);
        })
        .catch(() => {});
    },
    saveScene(data) {
      let fileName = data.name;
      fileName = fileName + ".json";
      let layerdata = {
        name: document.title,
        id: 1,
        open: true,
        children: this.treeData,
        flyTo: this.viewCenter,
      };
      let content = JSON.stringify(layerdata);
      let fData = new FormData();
      fData.append("json", content);
      fData.append("fileName", fileName);
      //this.serverURL +
      axios
        .post("../FileManager/fmc/saveFile", fData)
        .then((data) => {
          if (data.data == "success") {
            alert("保存成功!");
          }
        })
        .catch(() => {});
    },
    // æ·»åŠ æ•°æ®åˆ°åœºæ™¯
    addSceneData(data, isEdit) {
      if (isEdit) {
        this.updataTreeNode({
          id: data.id,
          nodeValue: data,
        });
        return;
      }
      data.checked = true;
      // æ·»åŠ èŠ‚ç‚¹
      this.addData(this.selectNode, data);
      // æ·»åŠ æ•°æ®åˆ°åœºæ™¯
      if (!_treeTool) {
        // å·¥ç¨‹æ ‘工具
        _treeTool = new window.TreeTool(window.sgworld);
        window.sgworld._treeTool = _treeTool;
      }
      _treeTool.addData(data);
      this.selectNode = undefined;
    },
    // æ·»åŠ æ ‘èŠ‚ç‚¹
    addData(data, value) {
      !value.rename && (value.rename = false);
      this.addTreeChildren({ pid: data && data.id, item: value });
      this.expandedNode(data);
      value.checked &&
      this.$nextTick(() => {
        this.$refs["slotTreeInput" + data.id].$refs.input.focus();
          this.$refs.tree.setChecked(value, true);
      });
    },
    // é¼ æ ‡å·¦å‡»äº‹ä»¶
    handleLeftclick(data, node) {
      this.rmListener();
    // æ ¹æ®åå­—获取父节点
    getParentNodeByName(name) {
      let index = this.treeData.findIndex((item) => {
        return item.name === name;
      });
      return this.treeData[index];
    },
    // å–消鼠标监听事件
    rmListener() {
      this.menuVisible = false;
      //  è¦åŠæ—¶å…³æŽ‰ç›‘听,不关掉的是一个坑,不信你试试,虽然前台显示的时候没有啥毛病,加一个alert你就知道了
      document.removeEventListener("click", this.rmListener);
    },
    // è¿‡æ»¤èŠ‚ç‚¹
    filterNode(value, data) {
      if (!value) return true;
      return data.cnName.indexOf(value) !== -1;
    },
    // é¼ æ ‡å³å‡»äº‹ä»¶
    rightClick(event, object, node, element) {
      if (object.type == 1 || node.data.children != null) return;
    // æ·»åŠ å…¶ä»–æ•°æ®
    addOtherData(parentName, data) {
      let parentNode = this.getParentNodeByName(parentName);
      data.checked = true;
      this.currentNode = node;
      this.currentData = object;
      this.$store.state.propertiesName = object;
      this.showProp = object.serveType == "WMS"; // å±žæ€§
      this.shwoHistogram = this.showProp && object.enName == "s_explorationpoint"; // é’»å­”柱状图
      this.showLocal = ["Tileset", "3DML", "Mpt", "TMS", "DOM", "DEM"].indexOf(object.serveType) > -1; // å®šä½
      this.showOpacity = ["Tileset", "3DML"].indexOf(object.serveType) > -1; // ä¸é€æ˜Žåº¦
      this.shwoTileDown = ["TMS", "DOM"].indexOf(object.serveType) > -1 && object.pubid; // ç“¦ç‰‡ä¸‹è½½
      this.menuVisible = this.showProp || this.shwoHistogram || this.showLocal || this.showOpacity || this.shwoTileDown; // èœå•
      this.shwoAnnex = ['DEM', 'TMS'].indexOf(object.serveType) > -1;//附件
      this.$refs.card.$el.style.left = event.pageX + 20 + "px";
      this.$refs.card.$el.style.top = event.pageY + "px";
      if (!parentNode) {
        parentNode = {
          id: window.sgworld.Core.getuid(),
          name: parentName,
          children: [],
        };
        this.addData(undefined, parentNode);
        this.$nextTick(() => {
          this.addData(parentNode, { ...data, item: undefined });
          _treeTool.treeData && _treeTool.treeData.set(data.id, data);
        });
      } else {
        this.addData(parentNode, { ...data, item: undefined });
        _treeTool.treeData && _treeTool.treeData.set(data.id, data);
      }
    },
    // å±žæ€§æ˜¾ç¤º
    showLayerAttribute(data) {
      this.rmListener();
      this.currentData = data ? data : this.currentData;
      let layer = this.currentData.enName.replaceAll("_", "");
      this.$store.state.mapSpaceQueryLayer = layer;
      this.$store.state.showPopBoxFlag = true;
      this.$store.state.mapPopBoxFlag = "2";
    // æ·»åŠ æ¼”ç¤ºåŠ¨ç”»
    editDemoAnimation() {
      this.$prompt("请输入演示动画名称", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        inputValue: "新建演示动画",
        closeOnClickModal: false,
      })
        .then(({ value }) => {
          let id = window.sgworld.Core.getuid();
          let data = {
            id,
            name: value,
            sourceType: "demoAnimation",
            animationDatas: [],
          };
          this.addOtherData("演示动画", data);
          this.$refs.animationEdit.open(id);
        })
        .catch(() => {});
    },
    //更新动画
    updateAnimation(id, data) {
      this.updataTreeNode({
        id: id,
        key: "animationDatas",
        value: data,
      });
    },
    // è®¾ç½®åŠ¨ç”»æ•°æ®
    setAnimation(keys, isCheck) {
      if (keys) {
        keys.forEach((element) => {
          let treeNode = this.$refs.tree.getNode(element);
          // å‹¾é€‰èŠ‚ç‚¹
          this.checkTreeNode({ id: element, checked: isCheck });
          // æ›´æ–°åœºæ™¯æ•°æ®
          _treeTool.checkNode(treeNode.data, isCheck);
          this.$refs.tree.setChecked(element, isCheck);
        });
      }
    },
    // å®šä½
    async positioning() {
      this.rmListener();
      if (["Tileset", "3DML"].indexOf(this.currentData.serveType) > -1) {
        for (let i in Viewer.scene.primitives._primitives) {
          if (Viewer.scene.primitives._primitives[i].id == this.currentData.cnName) {
            Viewer.flyTo(Viewer.scene.primitives._primitives[i]);
            break;
          }
        }
        return;
      }
      if (["TMS", "DOM", "DEM"].indexOf(this.currentData.serveType) > -1 && this.currentData.pubid) {
        let data = await comprehensive_selectPubById({ id: this.currentData.pubid });
        if (data.result && data.result.geom) {
          let wkt = this.$wkt.parse(data.result.geom);
          let height = this.getHeight(wkt.coordinates[2]);
          Viewer.camera.flyTo({
            destination: Cesium.Cartesian3.fromDegrees(wkt.coordinates[1], wkt.coordinates[0], sceneConfig.extureHeight), // 2000
          });
        }
        return;
      }
      if ("Mpt" == this.currentData.serveType) {
        if (this.currentData.json) {
          var json = JSON.parse(this.currentData.json);
          if (json.west) {
            Viewer.camera.flyTo({
              destination: Cesium.Rectangle.fromDegrees(json.west, json.south, json.east, json.north)
            })
          }
    flyTo(treeNode) {
      if (treeNode.animationDatas) {
        this.$refs.animationEdit.start(treeNode.animationDatas);
        } else {
          Viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(101.8, 37.9, 10000000.0) }); // ä¸­å›½
        }
        _treeTool.flyTo(treeNode);
      }
    },
    // é’»å­”柱状图
    async histogram() {
      this.rmListener();
      let layer = this.currentData.enName.replaceAll("_", "");
      this.$store.state.mapSpaceQueryLayer = layer;
      this.$store.state.mapPopBoxFlag = "2";
      this.$store.state.showPopBoxFlag = true;
    select() {
      this.rightClickMenuDisplay = false;
    },
    // é€æ˜Žåº¦
    pellucidity() {
      this.rmListener();
      for (let j in Viewer.scene.primitives._primitives) {
        if (Viewer.scene.primitives._primitives[j].id == this.currentData.cnName) {
          this.$store.state.setAlphaDity = this.currentData;
          this.$bus.$emit("showPellucidity", true);
          break;
        }
      }
    },
    // èŽ·å–é«˜åº¦
    getHeight(level) {
      if (level > -1 && level < 23) return this.levelArray[level];
      var res = 7
      return this.levelArray[res];
    },
    //附件下载
    annexDownload() {
      this.$bus.$emit('annexDownload', this.currentData)
    },
    // ç“¦ç‰‡ä¸‹è½½
    tileDownload() {
      this.rmListener();
      var that = this;
      sgworld.Creator.createSimpleGraphic(
        "rectangle", {},
        function (entity) {
          that.getTileRectangle(entity);
          sgworld.Creator.SimpleGraphic.clear();
        }
      );
    },
    // èŽ·å–ç“¦ç‰‡å››è‡³èŒƒå›´
    getTileRectangle(res) {
      var value = res.rectangle.coordinates.getValue();
      var val = {
        pubid: this.currentData.pubid,
        pwd: "",
        title: "",
        xmax: Cesium.Math.toDegrees(value.east),
        xmin: Cesium.Math.toDegrees(value.west),
        ymax: Cesium.Math.toDegrees(value.north),
        ymin: Cesium.Math.toDegrees(value.south)
      }
      this.$bus.$emit("titleDown", val);
    },
    // å›¾å±‚选中事件
    handleCheckChange(data, checked) {
      if (this.isBusy) return;
      let nodes = [];
      this.getNodes(data, nodes);
      let obj = { WMS: [], Tileset: [], TMS: [], Mpt: [], DEM: [] };
      for (let i = 0, c = nodes.length; i < c; i++) {
        let node = nodes[i];
        switch (node.serveType) {
          case "WMS":
            obj.WMS.push(node);
            break;
          case "3DML":
          case "Tileset":
            obj.Tileset.push(node);
            break;
          case "TMS":
            obj.TMS.push(node);
            break;
          case "Mpt":
            obj.Mpt.push(node);
            break;
          case "DEM":
            obj.DEM.push(node);
            break;
        }
      }
      if (obj.DEM.length) this.setChangeDEM(obj.DEM, checked);
      if (obj.TMS.length) this.setChangeTMS(obj.TMS, checked);
      if (obj.Mpt.length) this.setChangeMpt(obj.Mpt, checked);
      if (obj.Tileset.length) this.setChangeTileset(obj.Tileset, checked);
      if (obj.WMS.length) this.setChangeWMS(obj.WMS, checked);
    },
    // èŽ·å–å­èŠ‚ç‚¹
    getNodes(data, arr) {
    // ç§»é™¤
    remove(data) {
      // ç§»é™¤èŠ‚ç‚¹
      this.removeTreeNode({ id: data.id });
      if (data.children) {
        for (let i = 0, c = data.children.length; i < c; i++) {
          let node = data.children[i];
          if (node.children) {
            this.getNodes(node, arr)
        this.removeChildData(data.children);
          } else {
            arr.push(node);
        // ç§»é™¤åœºæ™¯æ•°æ®
        _treeTool.deleteData(data.id);
        if (data.sourceType === "demoAnimation") {
          Bus.$emit("closeAnimationEdit");
          }
        }
    },
    removeChildData(nodes) {
      nodes.forEach((item) => {
        if (item.children) {
          this.removeChildData(item.children);
      } else {
        arr.push(data);
          // ç§»é™¤åœºæ™¯æ•°æ®
          _treeTool.deleteData(item.id);
          if (item.sourceType === "demoAnimation") {
            Bus.$emit("closeAnimationEdit");
      }
        }
      });
    },
    // èŽ·å–èŠ‚ç‚¹ID
    getCheckNodesIds() {
      let nodes = this.$refs.tree.getCheckedNodes();
      let ids = [];
      for (let i in nodes) {
        ids.push(nodes[i].id);
      }
      return ids;
    // æ¸…除所有对象
    clearFirstParentNode(name) {
      let parentnode = this.getParentNodeByName(name);
      parentnode && this.remove(parentnode);
    },
    // åˆ‡æ¢WMS服务
    setChangeWMS(layers, checked) {
      let value = this.$refs.tree.getCheckedNodes();
      this.$bus.$emit("showMenuLayer", value);
    // ä¿å­˜
    save() {
      let data = {
        name: document.title,
        id: 1,
        open: true,
        children: this.treeData,
        flyTo: this.viewCenter,
        pathAnimation: window.localStorage.getItem("pathAnimation"),
      };
      let content = JSON.stringify(data);
      let blob = new Blob([content], { type: "" });
      var reader = new FileReader();
      reader.onloadend = () => {
        let url = reader.result;
        let triggerDownload = document.createElement("a");
        triggerDownload.download = (document.title || "layers") + ".json";
        triggerDownload.href = url;
        triggerDownload.click();
      };
      reader.readAsDataURL(blob);
    },
    // åˆ‡æ¢Tileset
    setChangeTileset(layers, checked) {
      let ids = this.getCheckNodesIds(), arr = [];
      for (let k in layers) {
        let layer = layers[k];
        if (ids.indexOf(layer.id) > -1) {
          arr.push(layer);
          continue;
        }
        for (let j in Viewer.scene.primitives._primitives) {
          if (Viewer.scene.primitives._primitives[j].id == layer.cnName) {
            Viewer.scene.primitives.remove(Viewer.scene.primitives._primitives[j]);
            break;
          }
        }
        let list = this.$store.state.setAlphaList;
        for (let i = 0; i < list.length; i++) {
          if (list[i].name == layer.cnName) {
            list.splice(i, 1);
          }
        }
      }
      if (arr.length) this.addTilesetLayers(arr);
    // å³é”®èœå•元素
    rightClick(e, data, node, comp) {
      this.isClickParent = !!data.children;
      this.selectNode = data;
      this.rightClickMenuStyle = { top: e.pageY + "px", left: e.pageX + "px" };
      this.rightClickMenuDisplay = true;
      document.onclick = () => {
        this.rightClickMenuDisplay = false;
        document.onclick = undefined;
      };
    },
    // æ·»åŠ Tileset图层
    addTilesetLayers(layers) {
      for (let i in layers) {
        let res = layers[i];
        let url = res.url.indexOf("{host}") > -1 ? res.url.replace("{host}", iisHost) : modelUrl + "/" + res.url;
        let tileset = Viewer.scene.primitives.add(
          new Cesium.Cesium3DTileset({
            name: res.cnName,
            url: url,
            skipLevelOfDetail: true, // åœ¨éåŽ†æ—¶å€™è·³è¿‡è¯¦æƒ…ï¼šfalse
            baseScreenSpaceError: 1024,
            maximumScreenSpaceError: url.indexOf("/pnts/") > -1 ? 16 : 64, // æœ€å¤§å±å¹•空间错误:16,数值加大能让最终成像变模糊
            skipScreenSpaceErrorFactor: 16,
            skipLevels: 1,
            immediatelyLoadDesiredLevelOfDetail: false,
            loadSiblings: true, // è‡ªåŠ¨ä»Žä¸­å¿ƒå¼€å§‹è¶…æ¸…åŒ–æ¨¡åž‹ï¼šfalse
            cullWithChildrenBounds: true, // ä½¿ç”¨å­é¡¹è¾¹ç•Œä½“积的并集来剔除图块:true
            cullRequestsWhileMoving: true,
            cullRequestsWhileMovingMultiplier: 10, // å€¼è¶Šå°èƒ½å¤Ÿæ›´å¿«çš„剔除:60
            preloadWhenHidden: true,
            preferLeaves: true, // é¢„装子节点:false
            maximumMemoryUsage: 768, // å†…存分配变小有利于内存回收,提升性能体验
            progressiveResolutionHeightFraction: 0.5, // æ•°å€¼åäºŽ0能够让初始加载变得模糊
            dynamicScreenSpaceErrorDensity: 0.5, // æ•°å€¼åŠ å¤§ï¼Œèƒ½è®©å‘¨è¾¹åŠ è½½å˜å¿«
            dynamicScreenSpaceErrorFactor: 2, // åŠ¨æ€å±å¹•ç©ºé—´è¯¯å·®çš„ç³»æ•°
            dynamicScreenSpaceError: true, // å‡å°‘离相机较远的屏幕空间错误:false,全屏加载完之后才清晰化房屋
          })
    appendTreeNode() {
      this.append(this.selectNode);
    },
    // å³é”®åˆ é™¤æŒ‰é’®ç‚¹å‡»äº‹ä»¶
    deleteTreeNode() {
      this.remove(this.selectNode);
      this.$refs.tree && this.$refs.tree.setCurrentKey(null);
      this.selectNode = undefined;
    },
    // å³é”®ç¼–辑按钮编辑树节点
    editTreeNode() {
      debugger;
      if (this.selectNode) {
        if (this.selectNode.sourceType === "SimpleGraphic") {
          let entity = window.Viewer.entities.getById(this.selectNode.id);
          sgworld.Creator.SimpleGraphic.openEditProp(entity);
        } else if (this.selectNode.sourceType === "MilitaryPlotting") {
          let entity = window.Viewer.entities.getById(this.selectNode.id);
          sgworld.Creator.MilitaryPlotting.openEditProp(entity);
        } else if (this.selectNode.sourceType === "demoAnimation") {
          this.$refs.animationEdit.open(
            this.selectNode.id,
            this.selectNode.animationDatas
        );
        tileset.readyPromise.then((tileset) => {
          tileset.id = res.cnName;
          tileset.layerId = res.id;
          tileset.pubid = res.pubid;
          if (res.serveType != '3DML') {
            // Cesium.Matrix4.equals(a,b) åˆ¤æ–­çŸ©é˜µæ˜¯å¦ç›¸ç­‰ï¼Œæ•´ä¸ªæ ¹èŠ‚ç‚¹æ¨¡åž‹çŸ©é˜µï¼Œè¯¥tileSet=>世界坐标系,单位矩阵对角线值为1.0的4*4矩阵
            if (!Cesium.Matrix4.equals(tileset.root.transform, Cesium.Matrix4.IDENTITY)) {
              // èŽ·å–æ¨¡åž‹çš„ä¸–ç•Œåæ ‡(笛卡尔),Cesium.Matrix4.getTranslation é€šè¿‡ä»¿å°„变换矩阵获取该tileSet的世界坐标
              const transformCenter = Cesium.Matrix4.getTranslation(tileset.root.transform, new Cesium.Cartesian3());
              // å°†ç¬›å¡å°”坐标转换为WGS84经纬度坐标(模型的)
              const transformCartographic = Cesium.Cartographic.fromCartesian(transformCenter);
              // å°†ç¬›å¡å°”坐标转换为WGS84经纬度坐标(截面的)
              const boundingSphereCartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
              const height = boundingSphereCartographic.height - transformCartographic.height;
              // ä»Žä¸€ä¸ªCartesian3对象生成Matrix4变换矩阵(裁切面的)
              window.modelHeight = height;
            } else {
              window.modelHeight = 0;
          this.openThisTypePop(this.selectNode.sourceType, this.selectNode);
            }
            this.setTilesetArgs(tileset, res);
          }
        });
      }
    },
    // åˆ‡æ¢TMS
    setChangeTMS(layers, checked) {
      let ids = this.getCheckNodesIds(), arr = [];
      for (let j in layers) {
        let layer = layers[j];
        if (ids.indexOf(layer.id) > -1) {
          arr.push(layer);
          continue;
        }
        for (let i = 0; i < window.Viewer.imageryLayers._layers.length; i++) {
          if (window.Viewer.imageryLayers._layers[i].name == layer.cnName) {
            window.Viewer.imageryLayers.remove(window.Viewer.imageryLayers._layers[i]);
            break;
          }
        }
      }
      if (arr.length) this.addTMSLayers(arr);
    },
    // æ·»åŠ TMS图层
    addTMSLayers(layers) {
      for (let i in layers) {
        let res = layers[i];
        res.url = res.url.indexOf("{host}") > -1 ? res.url.replace("{host}", iisHost) : res.url;
        if (res.pubid) {
          this.setTMSLayerByPubid(res);
          continue;
        }
        let layer = Viewer.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
          url: res.url,
          maximumLevel: 22,
          enablePickFeatures: false
        }), 1);
        layer.id = res.id;
        layer.name = res.cnName;
        if (is_production) {
          Viewer.imageryLayers.raiseToTop(layer);//将图层上移一层
          Viewer.imageryLayers.lower(layer);//将图层上移一层
        }
      }
    },
    // åˆ‡æ¢Mpt
    setChangeMpt(layers, checked) {
      let ids = this.getCheckNodesIds(), arr = [];
      for (let j in layers) {
        let layer = layers[j];
        if (ids.indexOf(layer.id) != -1) {
          arr.push(layer);
          continue;
        }
        for (let i in this.mptLayer) {
          if (this.mptLayer[i].treeobj.name == layer.cnName) {
            this.mptLayer[i].deleteObject();
            this.mptLayer.splice(i, 1);
          }
        }
      }
      if (arr.length) this.addMptLayers(arr);
    },
    // æ·»åŠ Mpt图层
    addMptLayers(layers) {
      for (let i in layers) {
        let res = layers[i];
        if (res.url.indexOf("{host}") > -1) res.url = res.url.replace("{host}", iisHost);
        let urls = res.url.split(';');
        var ops = {
          url: urls[0],
          layers: urls[1]
    // æ·»åŠ ç›®å½•
    addFold() {
      let newChild = {
        id: window.sgworld.Core.getuid(),
        name: "新建目录",
        children: [],
        rename: true,
        };
        if (res && res.json) {
          var rs = JSON.parse(res.json);
          ops.rectangle = Cesium.Rectangle.fromDegrees(rs.west, rs.south, rs.east, rs.north);
        }
        let layer = sgworld.Creator.createImageryProvider(res.cnName, "wms", ops, "0", undefined, true, "");
        this.mptLayer.push(layer);
      }
      this.addData(this.selectNode, newChild);
    },
    // åˆ‡æ¢DEM
    setChangeDEM(layers, checked) {
      let ids = this.getCheckNodesIds(), arr = [];
      for (let i in layers) {
        let layer = layers[i];
        if (ids.indexOf(layer.id) != -1) {
          arr.push(layer.url);
          continue;
        }
      }
      let url = arr.length ? arr[arr.length - 1] : null;
      this.addDEMLayers(url, null == url);
    },
    // æ·»åŠ DEM图层
    addDEMLayers(url, useSG) {
      if (useSG) {
        if (Viewer.terrainProvider._isMPT) return;
        let option = {
          url: window.sceneConfig.SGUrl,
          layerName: window.sceneConfig.mptName,
          requestVertexNormals: true
    // æ·»åŠ å®šä½ç‚¹
    addPosition() {
      let degrees = sgworld.Navigate.getDegrees(); //经纬度
      let heading = Cesium.Math.toDegrees(Viewer.camera.heading); //水平角
      let pitch = Cesium.Math.toDegrees(Viewer.camera.pitch); //俯仰角度
      let newChild = {
        id: window.sgworld.Core.getuid(),
        name: "兴趣点",
        sourceType: "location",
        checked: true,
        rename: true,
        disabled: true,
        flyTo: [
          degrees.lon.toFixed(6),
          degrees.lat.toFixed(6),
          degrees.height.toFixed(2),
          heading,
          pitch,
        ],
        };
        sgworld.Creator.sfsterrainprovider("", option, "", true, "");
        return;
      this.addData(this.selectNode, newChild);
    },
    expandedNode(node) {
      if (node && node.children && !node.expanded) {
        let treeNode = this.$refs.tree.getNode(node.id);
        if (treeNode) {
          treeNode.expanded = true;
          this.updataTreeNode({
            id: node.id,
            key: "expanded",
            value: true,
          });
      }
      if (url.indexOf("{host}") > -1) url = url.replace("{host}", iisHost);
      Viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
        url: url,
        requestVertexNormals: true
      }
    },
    addLayer() {
      this.selectData(this.selectNode);
    },
    openRename() {
      if (this.selectNode) {
        this.selectNode.rename = true;
      }
    },
    rename(data) {
      data.rename = false;
      this.updataTreeNode({
        id: data.id,
        key: "name",
        value: data.name,
      });
    },
    // è®¾ç½®Tileset参数
    async setTilesetArgs(tileset, res) {
      if (res.serveType == '3DML' || !res.pubid) {
        this.setTilesetHeigth(tileset, parseFloat(res.elev));
        return;
      }
      const data = await comprehensive_selectPubById({ id: res.pubid })
      if (data.code == 200 && data.result.json) this.setTilesetCoord(tileset, data.result.json);
    },
    // è®¾ç½®Tileset高度
    setTilesetHeigth(tileset, height) {
      //3dtile模型的边界球体
      let boundingSphere = tileset.boundingSphere;
      //迪卡尔空间直角坐标=>地理坐标(弧度制)
      let cartographic_original = Cesium.Cartographic.fromCartesian(boundingSphere.center);
      //地理坐标(弧度制)=>迪卡尔空间直角坐标
      let Cartesian3_original = Cesium.Cartesian3.fromRadians(cartographic_original.longitude, cartographic_original.latitude, cartographic_original.height);
      let Cartesian3_offset = Cesium.Cartesian3.fromRadians(cartographic_original.longitude, cartographic_original.latitude, height);
      //获得地面和offset的转换
      let translation = Cesium.Cartesian3.subtract(Cartesian3_offset, Cartesian3_original, new Cesium.Cartesian3());
      //修改模型矩阵
      tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
      // Viewer.flyTo(tileset);
    },
    // è®¾ç½®Tileset坐标
    setTilesetCoord(tileset, json) {
      let vm = JSON.parse(json);
      let pos = Cesium.Cartesian3.fromDegrees(vm.lon, vm.lat, vm.height);
      let converter = Cesium.Transforms.eastNorthUpToFixedFrame;
      let hpr = new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(vm.yaw), 0, 0);
      let matrix = Cesium.Transforms.headingPitchRollToFixedFrame(pos, hpr, Cesium.Ellipsoid.WGS84, converter);
      tileset._root.transform = matrix;
      // Viewer.flyTo(tileset);
    },
    // æ ¹æ®Pubid设置TMS图层
    async setTMSLayerByPubid(res) {
      const data = await comprehensive_selectPubById({ id: res.pubid });
      if (!data || data.code != 200) return;
      let provider = data.result.max > 0 ?
        new Cesium.UrlTemplateImageryProvider({
          url: res.url,
          minimumLevel: data.result.min,
          maximumLevel: data.result.max,
          enablePickFeatures: false
        }) :
        new Cesium.UrlTemplateImageryProvider({
          url: res.url,
          minimumLevel: data.result.min,
          enablePickFeatures: false
        });
      let layer = Viewer.imageryLayers.addImageryProvider(provider, 1);
      layer.name = res.cnName;
      if (is_production) {
        Viewer.imageryLayers.raiseToTop(layer);//将图层上移一层
        Viewer.imageryLayers.lower(layer);//将图层上移一层
      }
      // if (data.result.geom) {
      //   let wkt = this.$wkt.parse(data.result.geom);
      //   Viewer.camera.flyTo({
      //     destination: Cesium.Cartesian3.fromDegrees(wkt.coordinates[1], wkt.coordinates[0], 2000)
      //   });
      // }
    },
    // åˆ‡æ¢é¡¹ç›®
    prjChanged(code) {
      this.$store.state.pigCode = code;
      //if (code) {
      this.isBusy = true;
      let checkedLayers = this.getCheckedLayersByCode(code);
      let checkedKeys = [];
      for (let i in checkedLayers) {
        checkedKeys.push(checkedLayers[i].id);
      }
      this.treeData = this.getNewTreeData(code);
      this.$store.state.treeData = this.treeData;
      this.$refs.tree.setCheckedKeys(checkedKeys);
      sessionStorage.setItem("checkedLayers", JSON.stringify(checkedLayers));
      this.isBusy = false;
      //}
      for (let i = 0, c = this.treeData.length; i < c; i++) {
        this.handleCheckChange(this.treeData[i], true);
      }
    },
    // æ ¹æ®é¡¹ç›®ç¼–码获取选中图层
    getCheckedLayersByCode(code) {
      let layers = [];
      for (let i = 0, c = this.treeData.length; i < c; i++) {
        this.getCheckedChildLayersByCode(this.treeData[i], code, layers, false);
      }
      return layers;
    },
    // æ ¹æ®é¡¹ç›®ç¼–码获取选中子图层
    getCheckedChildLayersByCode(data, code, layers, isPrj) {
      if (data.children && data.children.length) {
        for (let i = 0, c = data.children.length; i < c; i++) {
          let layer = data.children[i];
          if (layer.children && layer.children.length) {
            let flag = layer.type == 1 && layer.isProject && layer.enName == code;
            this.getCheckedChildLayersByCode(layer, code, layers, flag);
            continue;
          }
          //if (layer.type == 2 && (layer.isProject || isPrj)) {
          //  layers.push(layer);
          //}
          if (code) {
            if (layer.type == 2 && (layer.isProject || isPrj)) layers.push(layer);
    allowDrop(draggingNode, dropNode, type) {
      if (type === "inner") {
        return false;
          } else {
            if (layer.isShow) layers.push(layer);
          }
        }
        return;
      }
      if (data.type == 2 && (data.isProject || isPrj)) {
        layers.push(data);
        return true;
      }
    },
    // èŽ·å–æ–°æ ‘æ•°æ®
    getNewTreeData(code) {
      let data = JSON.parse(JSON.stringify(this.sourceData));
      if (!code) return data;
      this.setSubTreeData(data, code);
      this.rmPrjTreeData(data, code);
      return data;
    },
    // è®¾ç½®æ ‘数据子节点
    setSubTreeData(data, code) {
      let j = 0;
      while (j < data.length) {
        let d = data[j];
        if (d.type == 1 && d.isProject && d.enName != code) {
          data.splice(j, 1);
          continue;
        }
        j++;
      }
      for (let i = 0, c = data.length; i < c; i++) {
        if (data[i].children && data[i].children.length) {
          this.setSubTreeData(data[i].children, code);
        }
      }
    },
    // ç§»é™¤é¡¹ç›®æ ‘数据
    rmPrjTreeData(data, code) {
      /*let j = 0;
      while (j < data.length) {
        let d = data[j];
        if (d.type == 1 && d.isProject && d.enName == code) {
          data.splice(j, 1);
          data.concat(d.children);
          continue;
        }
        j++;
      }
      for (let i = 0, c = data.length; i < c; i++) {
        if (data[i].children && data[i].children.length) {
          this.rmPrjTreeData(data[i].children, code);
        }
      }*/
      let i = 0;
      while (i < data.length) {
        let d = data[i];
        if (!d.children) {
          i++;
          continue;
        }
        if (!d.children.length) {
          data.splice(i, 1);
          continue;
        }
        let j = 0;
        while (j < d.children.length) {
          let e = d.children[j];
          if (e.type == 1 && e.isProject && e.enName == code) {
            d.children.splice(j, 1);
            if (e.children && e.children.length) d.children = d.children.concat(e.children);
            continue;
          }
          j++;
        }
        i++;
      }
      for (let i = 0, c = data.length; i < c; i++) {
        if (data[i].children && data[i].children.length) {
          this.rmPrjTreeData(data[i].children, code);
        }
      }
    },
    // æ·»åŠ WFS图层 *
    addWFSLayers(res) {
      let url =
        res.resource +
        "?service=WFS&version=1.0.0&request=GetFeature&typeName=" +
        res.url +
        "&outputFormat=application%2Fjson";
      $.ajax({
        url: url,
        cache: false,
        async: true,
        success: function (data) {
          let datasource = Cesium.GeoJsonDataSource.load(data, {
            stroke: Cesium.Color.YELLOW,
            fill: Cesium.Color.YELLOW.withAlpha(0.1),
            alpha: 0.1,
            strokeWidth: 8,
            clampToGround: true, //是否贴地
          });
          datasource.then((data) => {
            data.name = res.cnName;
            window.Viewer.dataSources.add(data);
          });
        },
        error: function (data) {
          console.log("error");
        },
      });
      let vectorLayer = new VectorLayer({
        name: res.cnName,
        source: new VectorSource({
          url: url,
          format: new GeoJSON(),
        }),
      });
      window.map.addLayer(vectorLayer);
    }
  },
};
</script>
<style scoped lang="less">
/* ç‚¹å‡»èŠ‚ç‚¹æ—¶çš„é€‰ä¸­é¢œè‰² */
.tree-container /deep/.el-tree-node.is-current > .el-tree-node__content {
  color: #409eff !important;
}
.tree-container /deep/ .el-tree-node__expand-icon.expanded {
  -webkit-transform: rotate(90deg);
  transform: rotate(90deg);
}
.tree-container /deep/ .el-icon-caret-right:before {
  content: "\e791";
  font-size: 18px;
}
.tree-container /deep/ .el-tree-node__expand-icon {
  margin-left: 1px;
  padding: 0px;
}
.tree-container /deep/ .el-tree-node__expand-icon.is-leaf {
  margin-left: 0px;
}
.tree-container /deep/ .el-tree-node {
  position: relative;
  padding-left: 10px;
}
.tree-container /deep/ .el-tree-node__children {
  padding-left: 16px;
}
.tree-container /deep/ .el-tree > .el-tree-node:before {
  border-left: none;
}
.tree-container /deep/ .el-tree > .el-tree-node:after {
  border-top: none;
}
.tree-container /deep/ .el-tree > .el-tree-node:before {
  border-left: none;
}
.tree-container /deep/ .el-tree > .el-tree-node:after {
  border-top: none;
}
.tree-container /deep/ .el-tree-node:before {
  content: "";
  left: 10px;
  position: absolute;
  right: auto;
  border-width: 1px;
}
.tree-container /deep/ .el-tree-node:after {
  content: "";
  left: 10px;
  position: absolute;
  right: auto;
  border-width: 1px;
}
.tree-container /deep/ .el-tree-node:before {
  border-left: 1px dashed #ccc;
  bottom: 0px;
<style scoped lang="less" scoped>
.treeContainer {
  width: 100%;
  height: 100%;
  top: -19px;
  width: 1px;
}
.tree-container /deep/ .el-tree-node:after {
  border-top: 1px dashed #ccc;
  height: 25px;
  top: 20px;
  width: 20px;
}
  .treeTitle {
    text-align: center;
    margin: 10px 0;
.el-tree-node :last-child:before {
  height: 40px;
    /deep/ .el-upload {
      margin-right: 10px;
}
.tree-container {
  margin: 10px;
}
.tree-container /deep/ .el-tree .el-tree-node {
  position: relative;
}
.tree-container /deep/ .el-tree-node .el-tree-node__content {
  height: 34px;
  padding-left: 0px !important;
  border: none;
}
.tree-container /deep/ .el-tree-node .el-tree-node__content::before {
  border-left: 1px dashed #ccc;
  height: 100%;
  top: 0;
  width: 1px;
  margin-left: 1px;
  margin-top: 0px;
  z-index: 8;
}
.tree-container
  /deep/
  .el-tree-node
  .el-tree-node__children
  .el-tree-node__content::before {
  border-left: 0px dashed #ccc;
  height: 100%;
  top: 0;
  width: 1px;
  margin-left: 1px;
  margin-top: 0px;
  z-index: 8;
}
.tree-container /deep/ .el-tree-node .el-tree-node__content::after {
  border-top: 1px dashed #ccc;
  height: 1px;
  top: 18px;
  width: 13px;
  margin-left: 1px;
  z-index: 8;
}
.tree-container /deep/ .el-tree-node {
  .is-leaf + .el-checkbox .el-checkbox__inner {
    display: inline-block;
  }
  .el-checkbox .el-checkbox__inner {
    //display: none;
  }
}
.tree-container
  /deep/
  .el-tree-node
  .el-tree-node__children
  .el-tree-node__content::after {
  border-top: 0px dashed #ccc;
}
.tree-container .el-tree-node .el-tree-node__content::before,
.tree-container .el-tree-node .el-tree-node__content::after {
  content: "";
  position: absolute;
  right: auto;
}
/deep/.el-table__placeholder {
  padding-left: 8px;
}
/deep/.el-card__body {
  padding: 10px !important;
  > div {
    padding-bottom: 10px;
    border-bottom: 1px solid #ccc;
    &:hover {
      color: #409eff;
    }
  }
}
/deep/ .el-form .el-form-item {
  padding-right: 0px !important;
}
/deep/ .el-form-item {
  margin-bottom: 10px !important;
}
.text {
  font-size: 14px;
}
.el-tree {
  width: 100%;
  margin-top: 10px;
    background: transparent;
    color: #fff;
}
.search {
  width: 100%;
  /deep/ .el-tree-node__content:hover {
    background-color: rgba(245, 247, 250, 0.2);
}
.item {
  padding: 18px 0;
  /deep/ .el-tree-node:focus > .el-tree-node__content {
    background-color: rgba(245, 247, 250, 0.2);
}
.add {
  cursor: pointer;
  margin-top: 10px;
  /deep/ .custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 10px;
    i {
      margin-right: 5px;
    }
}
.delete {
  margin: 10px 0;
  cursor: pointer;
  /deep/ .el-checkbox > .is-disabled {
    display: none;
}
.edit {
  margin-bottom: 10px;
  cursor: pointer;
}
.search {
  cursor: pointer;
}
.box-card {
.rightClickMenu {
  position: fixed;
  display: block;
  z-index: 10000;
  padding: 0px 0px;
  background-color: #fff;
  padding: 5px 0;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.rightClickMenu ul {
  margin: 0;
  padding: 0;
}
.rightClickMenu ul li {
  list-style: none;
  margin: 0;
  padding: 0 15px;
  font-size: 14px;
  line-height: 30px;
  cursor: pointer;
  color: black;
}
.rightClickMenu ul li:hover {
  background-color: #ebeef5;
}
</style>
src/views/Tools/baseVuex.js
@@ -1,18 +1,26 @@
import { mapState, mapMutations } from 'vuex';
import {
  mapState,
  mapMutations
} from 'vuex'
export default {
  computed: {
    // ...mapState('layerTree', [
    //   'treeData',
    // ]),
    ...mapState('user', ['user']),
    ...mapState('layerTree', [
      'treeData',
    ]),
    ...mapState('user', [
      'user',
    ]),
    ...mapState('mapTools', [
      'hideTools',
      'hidePositionBtn',
      'statusbar',
      'navBar',
      'scaleBarStatus',
      'scaleBarStatus'
    ]),
    ...mapState('mapStatus', ['viewCenter', 'mapStatus']),
    ...mapState('mapStatus', [
      'viewCenter',
      'mapStatus',
    ])
  },
  methods: {
    ...mapMutations('layerTree', [
@@ -20,14 +28,19 @@
      'addTreeChildren',
      'updataTreeNode',
      'checkTreeNode',
      'removeTreeNode',
      'removeTreeNode'
    ]),
    ...mapMutations('user', ['changeUserData']),
    ...mapMutations('user', [
      'changeUserData',
    ]),
    ...mapMutations('mapTools', [
      'changeScaleBarVisible',
      'changeNavBarVisible',
      'changeMapToolsVisible',
    ]),
    ...mapMutations('mapStatus', ['setView', 'changeMapStatus']),
  },
};
    ...mapMutations('mapStatus', [
      'setView',
      'changeMapStatus',
    ])
  }
}
src/views/Tools/maplayer.vue
@@ -12,7 +12,7 @@
    >
      <div id="eagleMapContainer">
        <div
          style="width:300px;height:400px;"
          style="height:400px;"
          v-drag
          @mousedown="dragEagle"
        >
vue.config.js
@@ -21,6 +21,8 @@
    resolve: {
      alias: {
        "@": resolve("src"),
        '@c': resolve('src/components'),
        '@tools': resolve('src/views/Tools'),
      },
    },
  },