wangjuncheng
昨天 cf7752d995e09d48eca9a1ca5634a9e71ae46553
src/components/tools/LayerTree.vue
@@ -13,28 +13,38 @@
</template>
<script setup>
import { ref, onMounted, watch, nextTick, onUnmounted } from "vue";
import { createPoint, removeEntities, addTileset } from "@/utils/map";
import { ref, onMounted, watch, nextTick, onUnmounted, watchEffect } from "vue";
import {
  createPoint,
  removeEntities,
  addTileset,
  clearAllPoints,
} from "@/utils/map";
import { deviceDictList, getDictName } from "@/constant/dict.js";
import { useRoute } from "vue-router";
import { loadAreaPolygon, clearAreaPolygon } from "@/utils/area";
import { checkedKeys } from "@/store/index";
import {
  getDuanMainData,
  getDevicetListData,
  getDistrictListData,
} from "@/api/index.js";
import { init } from "echarts";
  loadAreaPolygon,
  convertToGeoJson,
  clearAreaPolygon,
} from "@/utils/area";
import { checkedKeys } from "@/store/index";
import { getDuanMainData } from "@/api/index.js";
import { useSimStore } from "@/store/simulation";
import { getSafePoint } from "@/api/hpApi";
const simStore = useSimStore();
const route = useRoute();
// 树形结构数据
/**
 * 图层树配置数据
 * 包含三维服务和图层数据两大分类
 */
const treeData = ref([
  {
    label: "三维服务",
    children: [
      { label: "模型数据" },
      { label: "地形数据" },
      { label: "地形数据" },
      { label: "影像数据" },
    ],
  },
@@ -50,277 +60,335 @@
  },
]);
// 默认选中的节点
const defaultSelectedKeys = ref(["地形数据"]); // 确保与 treeData 的 label 完全匹配
// 默认选中的节点(地形数据默认开启)
const defaultSelectedKeys = ref(["地形数据"]);
// Tree 实例引用
const treeRef = ref(null);
// 存储图层实体的 Map
// 存储图层实体的 Map,用于管理所有图层
const treeMap = new Map();
/**
 * 初始化地图
 */
// function initMap() {
//   // 初始化地形数据
//   let TerrainLayer = earthCtrl.factory.createTerrainLayer({
//     sourceType: "ctb",
//     url: "http://106.120.22.26:9103/gisserver/ctsserver/sungugoudem",
//   });
//   treeMap.set("地形数据", TerrainLayer);
//   console.log(TerrainLayer,'aaaa')
//   // 初始化模型数据
//   // let modelPromise = addTileset(
//   //   "http://106.120.22.26:9103/gisserver/c3dserver/sunhugou3d/tileset.json"
//   // );
//   // modelPromise.then((model) => {
//   //   treeMap.set("模型数据", model);
//   // });
//   // 初始化影像数据
//   // let ImageryLayer = earthCtrl.factory.createImageryLayer({
//   //   sourceType: "tms",
//   //   url: "http://106.120.22.26:9103/gisserver/tmsserver/sunhugoudom",
//   // });
//   // treeMap.set("影像数据", ImageryLayer);
// }
// 地形数据
// 地形数据实例
let TerrainLayer = null;
async function initMap() {
// 影像数据实例
let ImageryLayer = null;
/**
 * 初始化地形数据图层
 */
async function initTerrainLayer() {
  try {
    // 初始化地形数据(使用await等待Promise解析)
    TerrainLayer = await earthCtrl.factory.createTerrainLayer({
      sourceType: "ctb",
      url: "http://106.120.22.26:9103/gisserver/ctsserver/sungugoudem",
      url: "http://106.120.22.26:9103/gisserver/ctsserver/sunhugoudem",
      requestVertexNormals: true,
    });
    treeMap.set("地形数据", TerrainLayer);
  } catch (error) {
    console.error("初始化失败:", error);
    console.error("地形数据初始化失败:", error);
  }
}
/**
 * 处理复选框状态变化
 * 初始化影像数据图层
 */
// 应用初始化时预先加载
// 影像数据初始
let ImageryLayer = null;
async function initImageryLayer() {
  ImageryLayer = await earthCtrl.factory.createImageryLayer({
    sourceType: "tms",
    url: "http://106.120.22.26:9103/gisserver/tmsserver/sunhugoudom",
  });
  try {
    ImageryLayer = await earthCtrl.factory.createImageryLayer({
      sourceType: "tms",
      url: "http://106.120.22.26:9103/gisserver/tmsserver/sunhugoudom",
    });
    treeMap.set("影像数据", ImageryLayer);
  } catch (error) {
    console.error("影像数据初始化失败:", error);
  }
}
function handleCheckChange(data, checked, indeterminate) {
/**
 * 处理树节点勾选变化
 * @param {Object} data - 节点数据
 * @param {Boolean} checked - 是否选中
 * @param {Boolean} indeterminate - 不确定状态
 */
function handleCheckChange(data, checked) {
  const label = data.label;
  // 地形数据处理
  if (label === "地形数据") {
    if (checked) {
      initMap();
      treeMap.set("地形数据", TerrainLayer);
      toggleLayerVisible("地形数据", true); // 显示影像数据
    } else {
      const layer = treeMap.get("地形数据");
      if (layer) {
        toggleLayerVisible("地形数据", false); // 隐藏影像数据
        TerrainLayer.removeFromMap(); // 从 Map 中移除
        console.log("影像数据已移除");
      }
    }
    handleTerrainLayer(checked);
    return;
  }
  // 影像数据处理
  if (label === "影像数据") {
    if (checked) {
      initImageryLayer();
      // // 加载影像数据
      // console.log("开始加载影像数据...");
      // ImageryLayer = earthCtrl.factory.createImageryLayer({
      //   sourceType: "tms",
      //   url: "http://106.120.22.26:9103/gisserver/tmsserver/sunhugoudom",
      // });
      treeMap.set("影像数据", ImageryLayer);
      toggleLayerVisible("影像数据", true); // 显示影像数据
    } else {
      // 移除影像数据
      const layer = treeMap.get("影像数据");
      if (layer) {
        toggleLayerVisible("影像数据", false); // 隐藏影像数据
        ImageryLayer.removeFromMap(); // 从 Map 中移除
        console.log("影像数据已移除");
      }
    }
    handleImageryLayer(checked);
    return;
  }
  // 模型数据处理
  if (label === "模型数据") {
    if (checked) {
      // 动态加载模型数据
      console.log("开始加载模型数据...");
      let modelPromise = addTileset(
        "http://106.120.22.26:9103/gisserver/c3dserver/sunhugou3d/tileset.json"
      );
      modelPromise
        .then((model) => {
          console.log("模型数据加载完成");
          treeMap.set("模型数据", model); // 将模型数据存储到 treeMap
          toggleLayerVisible("模型数据", true); // 显示模型数据
        })
        .catch((error) => {
          console.error("模型数据加载失败:", error);
        });
    } else {
      // 隐藏模型数据
      toggleLayerVisible("模型数据", false);
    }
    handleModelLayer(checked);
    return;
  }
  // 其他图层的处理逻辑
  const list = treeMap.get(label);
  if (list) {
  // 设备信息处理
  if (label === "综合监测设备信息") {
    simStore.DeviceShowSwitch = checked;
    return;
  }
  // 隐患点处理
  if (label === "孙胡沟隐患点") {
    simStore.DangerShowSwitch = checked;
    return;
  }
  // 其他图层的处理
  const layer = treeMap.get(label);
  if (layer) {
    toggleLayerVisible(label, checked);
    return;
  }
}
  switch (label) {
    case "影像数据":
    case "地形数据":
    case "北京市隐患点":
    case "孙胡沟隐患点":
    case "泥石流隐患点面数据":
    case "综合监测设备信息":
    case "孙胡沟断面":
    case "避险场所":
      console.log(label, checked, indeterminate);
      break;
/**
 * 处理地形图层
 */
function handleTerrainLayer(checked) {
  if (checked) {
    initTerrainLayer();
    toggleLayerVisible("地形数据", true);
  } else {
    const layer = treeMap.get("地形数据");
    if (layer) {
      toggleLayerVisible("地形数据", false);
      layer.removeFromMap();
      treeMap.delete("地形数据");
    }
  }
}
/**
 * 处理影像图层
 */
function handleImageryLayer(checked) {
  if (checked) {
    initImageryLayer();
    toggleLayerVisible("影像数据", true);
  } else {
    const layer = treeMap.get("影像数据");
    if (layer) {
      toggleLayerVisible("影像数据", false);
      layer.removeFromMap();
      treeMap.delete("影像数据");
    }
  }
}
/**
 * 处理模型图层
 */
function handleModelLayer(checked) {
  if (checked) {
    addTileset(
      // "http://106.120.22.26:9103/gisserver/c3dserver/sunhugou3d/tileset.json"
      "http://192.168.37.61:9004/tile/model/service/Iakp0nhx/tileset.json?labtoken=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiItMSxUaHUgQXByIDE4IDE1OjMwOjU3IENTVCAyMDI0In0.j_YKsCRsIQtpgOWfFvMwAP65Rlx9uXyVte_xkE95Vdo"
    )
      .then((model) => {
        treeMap.set("模型数据", model);
        toggleLayerVisible("模型数据", true);
      })
      .catch(console.error);
  } else {
    toggleLayerVisible("模型数据", false);
  }
}
/**
 * 切换图层可见性
 * @param {String} name - 图层名称
 * @param {Boolean} visible - 是否可见
 */
function toggleLayerVisible(name, checked) {
  const entityList = treeMap.get(name);
  if (Array.isArray(entityList)) {
    entityList.forEach((entity) => {
      // console.log(`Setting entity show to:`, checked);
      entity.show = checked;
    });
  } else if (entityList && typeof entityList.show !== "undefined") {
    entityList.show = checked;
  } else {
    console.error(`无法设置图层 ${name} 的可见性`);
function toggleLayerVisible(name, visible) {
  const layer = treeMap.get(name);
  if (!layer) {
    console.warn(`图层 ${name} 不存在`);
    return;
  }
  // 处理不同类型的图层
  if (Array.isArray(layer)) {
    // 实体数组
    layer.forEach((entity) => {
      entity.show = visible;
      if (visible && !viewer.entities.contains(entity)) {
        viewer.entities.add(entity);
      }
    });
  } else if (typeof layer.setVisible === "function") {
    // 自定义图层接口
    layer.setVisible(visible);
  } else if (typeof layer.show === "boolean") {
    // 普通可显示对象
    layer.show = visible;
  }
  viewer.scene.requestRender();
}
// 设备列表
const devicetList = ref([]);
/**
 * 获取设备列表并初始化设备点
 * 清除图层实体
 * @param {String} layerName - 图层名称
 */
const getDevicetList = async () => {
  await getDevicetListData().then((res) => {
    devicetList.value = res.data;
  });
};
async function initDevicePoint() {
  let list = [];
  await getDevicetList();
  devicetList.value.forEach((item) => {
    item.type = getDictName(deviceDictList, item.dictDeviceType);
    item.name = item.type;
    item.id = item.deviceId;
    item.className = "device";
    item.showLabel = true;
    const entity = createPoint(item);
    entity.show = false;
    list.push(entity);
  });
  treeMap.set("综合监测设备信息", list);
}
// 区域列表
const districtList = ref([]);
// 暂且保留
// async function clearLayerEntities(layerName) {
//   const list = treeMap.get(layerName);
//   if (list && Array.isArray(list)) {
//     for (const item of list) {
//       const entity = await item;
//       if (layerName == "综合监测设备信息") {
//         removeEntities(entity.deviceId);
//       } else if (layerName == "孙胡沟隐患点") {
//         removeEntities(entity.hdId);
//       }
//     }
//   }
//   treeMap.delete(layerName);
// }
/**
 * 获取区域列表并初始化区域点
 * 清除图层实体
 * @param {String} layerName - 图层名称
 */
const getDistrictList = async () => {
  await getDistrictListData().then((res) => {
    districtList.value = res.data;
  });
};
// 此函数优化了在模拟仿真页面,如果点击目录树选中取消,泥位计仍显示
async function clearLayerEntities(layerName) {
  const isMnfzPage = route.path === "/mnfz"; // 判断是否为 /mnfz 页面
async function initDistrictPoint() {
  let list = [];
  await getDistrictList();
  districtList.value.forEach((item) => {
    item.showBillboard = true;
    item.className = "district";
    item.type = "泥石流";
    const entity = createPoint(item);
    entity.show = false;
    list.push(entity);
  });
  treeMap.set("孙胡沟隐患点", list);
  const list = treeMap.get(layerName);
  if (list && Array.isArray(list)) {
    for (const item of list) {
      const entity = await item;
      let shouldRemove = true; // 默认要删除
      // 如果是 /mnfz 页面,并且是“泥位计”,则不删除
      if (isMnfzPage && entity.type === "泥位计") {
        shouldRemove = false;
      }
      if (shouldRemove) {
        if (layerName === "综合监测设备信息") {
          removeEntities(entity.deviceId);
        } else if (layerName === "孙胡沟隐患点") {
          removeEntities(entity.hdId);
        }
      }
    }
  }
  treeMap.delete(layerName);
}
let divPointList = [];
watchEffect(async () => {
  clearLayerEntities("综合监测设备信息");
  if (simStore.DeviceShowSwitch) {
    // 使用 Promise.all 等待所有异步操作完成
    const deviceListPromises = simStore.devices
      .filter((item) => item.deviceName?.includes("孙胡沟"))
      .map(async (item) => {
        const entity = viewer.entities.getById(item.deviceId);
        item.type = getDictName(deviceDictList, item.dictDeviceType);
        item.name = item.deviceName.split("孙胡沟")[1];
        item.id = item.deviceId;
        item.className = "device";
        item.showLabel = true;
        await createPoint(item); // 确保 createPoint 返回一个 Promise 或者本身就是异步函数
        return item; // 返回处理后的 item
      });
    // 等待所有异步操作完成
    const deviceList = await Promise.all(deviceListPromises);
    if (deviceList.length) {
      treeMap.set("综合监测设备信息", deviceList);
    }
  }
});
// 监控隐患点开关变化
watchEffect(async () => {
  clearLayerEntities("孙胡沟隐患点");
  if (simStore.DangerShowSwitch) {
    const filteredPoints = simStore.DangerPoint.filter((item) =>
      item.position?.includes("孙胡沟")
    );
    const dangerPointPromises = filteredPoints.map(async (item) => {
      const entity = viewer.entities.getById(item.hdId);
      item.id = item.hdId;
      item.name = item.hdName;
      item.latitude = item.lat;
      item.longitude = item.lon;
      item.showBillboard = true;
      item.type = item.disasterType;
      item.className = "district";
      await createPoint(item); // 确保 createPoint 是异步函数
      return item; // 返回处理好的 item
    });
    try {
      const resolvedPoints = await Promise.all(dangerPointPromises);
      if (resolvedPoints.length) {
        treeMap.set("孙胡沟隐患点", resolvedPoints);
      }
    } catch (error) {
      console.error("创建隐患点时发生错误:", error);
    }
  }
});
/**
 * 初始化断面点
 * 初始化断面点数据
 */
function initDuanmianPoint() {
  getDuanMainData().then((res) => {
    const duanmianList = res.data;
    const list = [];
    duanmianList.forEach((item) => {
      item.id = item.id + item.alias;
      item.name = item.alias;
      item.longitude = item.lon;
      item.latitude = item.lat;
      item.showBillboard = false;
      item.className = "district";
      const entity = createPoint(item);
    const list = res.data.map((item) => {
      const entity = createPoint({
        id: item.id + item.alias,
        name: item.alias,
        latitude: item.lat,
        longitude: item.lon,
        showBillboard: false,
        className: "district",
      });
      entity.show = false;
      list.push(entity);
      return entity;
    });
    treeMap.set("孙胡沟断面", list);
  });
}
/**
 * 添加避险场所
 * 添加避险场所数据
 */
function addTetrahedron(visible) {
  const emergencyAreaList = [];
  // 加载避险场所底层面片
  loadAreaPolygon("/json/emergency_area.geojson", true).then((entities) => {
    emergencyAreaList.push(...entities);
    // 默认隐藏避险场所
    entities.forEach((entity) => {
      entity.show = false;
function addTetrahedron() {
  getSafePoint(110116110218).then((res) => {
    const geoJsonData = convertToGeoJson(res.data); // 转换为 GeoJSON
    // 加载 GeoJSON 数据到地图
    loadAreaPolygon(geoJsonData, true).then((entities) => {
      entities.forEach((entity) => (entity.show = false));
      treeMap.set("避险场所", entities);
    });
    // 将避险场所实体存储到 treeMap
    treeMap.set("避险场所", entities);
  });
}
/**
 * 初始化所有数据
 */
function getData() {
  initDevicePoint();
  initDistrictPoint();
function initData() {
  initDuanmianPoint();
  addTetrahedron();
}
@@ -329,11 +397,8 @@
watch(
  () => checkedKeys.value,
  (keys) => {
    if (keys && Array.isArray(keys)) {
      treeRef.value.setCheckedKeys(
        defaultSelectedKeys.value.concat(keys),
        true
      );
    if (Array.isArray(keys)) {
      treeRef.value?.setCheckedKeys([...defaultSelectedKeys.value, ...keys]);
    }
  }
);
@@ -342,56 +407,53 @@
watch(
  () => route.fullPath,
  (path) => {
    const defaultKeys = defaultSelectedKeys.value;
    if (path == "/yhgl") {
      treeRef.value.setCheckedKeys(defaultKeys.concat("孙胡沟隐患点"), true);
      toggleLayerVisible("孙胡沟隐患点", true);
      toggleLayerVisible("综合监测设备信息", false);
      toggleLayerVisible("孙胡沟断面", false);
    } else if (path == "/zhjc") {
      treeRef.value.setCheckedKeys(
        defaultKeys.concat("综合监测设备信息"),
        true
      );
      toggleLayerVisible("综合监测设备信息", true);
      toggleLayerVisible("孙胡沟隐患点", false);
      toggleLayerVisible("孙胡沟断面", false);
    } else if (path == "/mnfz") {
      treeRef.value.setCheckedKeys(defaultKeys.concat("孙胡沟断面"), false);
      toggleLayerVisible("孙胡沟断面", false);
      toggleLayerVisible("孙胡沟隐患点", false);
      toggleLayerVisible("综合监测设备信息", false);
    } else {
      treeRef.value.setCheckedKeys(defaultKeys, true);
    }
  }
    const defaultKeys = [...defaultSelectedKeys.value];
    const checkedKeys =
      {
        // 页面默认勾选显示在此处
        "/yhgl": [...defaultKeys, "孙胡沟隐患点"],
        "/zhjc": [...defaultKeys, "综合监测设备信息"],
        // "/mnfz": [...defaultKeys, "孙胡沟断面"],
      }[path] || defaultKeys;
    treeRef.value?.setCheckedKeys(checkedKeys);
  },
  { immediate: true }
);
// 组件挂载时初始化
onMounted(() => {
  initMap();
  getData();
  initTerrainLayer();
  initData();
  nextTick(() => {
    // 确保树组件渲染完成后设置默认选中项
    treeRef.value.setCheckedKeys(defaultSelectedKeys.value, true);
    treeRef.value?.setCheckedKeys(defaultSelectedKeys.value);
  });
});
// 组件卸载时清理资源
onUnmounted(() => {
  viewer.entities.removeAll();
  // 清理所有图层引用
  treeMap.forEach((layer) => {
    if (layer.removeFromMap) {
      layer.removeFromMap();
    }
  });
  treeMap.clear();
});
</script>
<style lang="less" scoped>
@import url("../../assets/css/infobox.css");
.layer-tree {
  background: url("@/assets/img/tools/plotting_new.png");
  width: 200px;
  // height: 200px;
  z-index: 99;
  overflow: hidden;
}
/deep/ .el-tree {
  :deep(.el-tree) {
    overflow: hidden !important;
  }
}
</style>