<template>
|
<div class="layer-tree">
|
<el-tree
|
ref="treeRef"
|
style="max-width: 600px"
|
show-checkbox
|
node-key="label"
|
:default-checked-keys="defaultSelectedKeys"
|
@check-change="handleCheckChange"
|
:data="treeData"
|
/>
|
</div>
|
</template>
|
|
<script setup>
|
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,
|
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: "图层数据",
|
children: [
|
{ label: "北京市隐患点" },
|
{ label: "孙胡沟隐患点" },
|
{ label: "综合监测设备信息" },
|
{ label: "孙胡沟断面" },
|
{ label: "避险场所" },
|
],
|
},
|
]);
|
|
// 默认选中的节点(地形数据默认开启)
|
const defaultSelectedKeys = ref(["地形数据"]);
|
|
// Tree 实例引用
|
const treeRef = ref(null);
|
|
// 存储图层实体的 Map,用于管理所有图层
|
const treeMap = new Map();
|
|
// 地形数据实例
|
let TerrainLayer = null;
|
// 影像数据实例
|
let ImageryLayer = null;
|
|
/**
|
* 初始化地形数据图层
|
*/
|
async function initTerrainLayer() {
|
try {
|
TerrainLayer = await earthCtrl.factory.createTerrainLayer({
|
sourceType: "ctb",
|
url: "http://106.120.22.26:9103/gisserver/ctsserver/sunhugoudem",
|
requestVertexNormals: true,
|
});
|
treeMap.set("地形数据", TerrainLayer);
|
} catch (error) {
|
console.error("地形数据初始化失败:", error);
|
}
|
}
|
|
/**
|
* 初始化影像数据图层
|
*/
|
async function initImageryLayer() {
|
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);
|
}
|
}
|
|
/**
|
* 处理树节点勾选变化
|
* @param {Object} data - 节点数据
|
* @param {Boolean} checked - 是否选中
|
* @param {Boolean} indeterminate - 不确定状态
|
*/
|
function handleCheckChange(data, checked) {
|
const label = data.label;
|
|
// 地形数据处理
|
if (label === "地形数据") {
|
handleTerrainLayer(checked);
|
return;
|
}
|
|
// 影像数据处理
|
if (label === "影像数据") {
|
handleImageryLayer(checked);
|
return;
|
}
|
|
// 模型数据处理
|
if (label === "模型数据") {
|
handleModelLayer(checked);
|
return;
|
}
|
|
// 设备信息处理
|
if (label === "综合监测设备信息") {
|
simStore.DeviceShowSwitch = checked;
|
return;
|
}
|
|
// 隐患点处理
|
if (label === "孙胡沟隐患点") {
|
simStore.DangerShowSwitch = checked;
|
return;
|
}
|
|
// 其他图层的处理
|
const layer = treeMap.get(label);
|
if (layer) {
|
toggleLayerVisible(label, checked);
|
}
|
}
|
|
/**
|
* 处理地形图层
|
*/
|
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"
|
)
|
.then((model) => {
|
treeMap.set("模型数据", model);
|
toggleLayerVisible("模型数据", true);
|
})
|
.catch(console.error);
|
} else {
|
toggleLayerVisible("模型数据", false);
|
}
|
}
|
|
/**
|
* 切换图层可见性
|
* @param {String} name - 图层名称
|
* @param {Boolean} visible - 是否可见
|
*/
|
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();
|
}
|
|
/**
|
* 清除图层实体
|
* @param {String} layerName - 图层名称
|
*/
|
// 暂且保留
|
// 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 - 图层名称
|
*/
|
// 此函数优化了在模拟仿真页面,如果点击目录树选中取消,泥位计仍显示
|
async function clearLayerEntities(layerName) {
|
const isMnfzPage = route.path === "/mnfz"; // 判断是否为 /mnfz 页面
|
|
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);
|
}
|
|
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 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;
|
return entity;
|
});
|
treeMap.set("孙胡沟断面", list);
|
});
|
}
|
|
/**
|
* 添加避险场所数据
|
*/
|
function addTetrahedron() {
|
getSafePoint().then((res) => {
|
const geoJsonData = convertToGeoJson(res.data); // 转换为 GeoJSON
|
// 加载 GeoJSON 数据到地图
|
loadAreaPolygon(geoJsonData, true).then((entities) => {
|
entities.forEach((entity) => (entity.show = false));
|
treeMap.set("避险场所", entities);
|
});
|
});
|
}
|
|
/**
|
* 初始化所有数据
|
*/
|
function initData() {
|
initDuanmianPoint();
|
addTetrahedron();
|
}
|
|
// 监听 store 中的 checkedKeys 变化
|
watch(
|
() => checkedKeys.value,
|
(keys) => {
|
if (Array.isArray(keys)) {
|
treeRef.value?.setCheckedKeys([...defaultSelectedKeys.value, ...keys]);
|
}
|
}
|
);
|
|
// 监听路由变化
|
watch(
|
() => route.fullPath,
|
(path) => {
|
const defaultKeys = [...defaultSelectedKeys.value];
|
const checkedKeys =
|
{
|
// 页面默认勾选显示在此处
|
"/yhgl": [...defaultKeys, "孙胡沟隐患点"],
|
"/zhjc": [...defaultKeys, "综合监测设备信息"],
|
// "/mnfz": [...defaultKeys, "孙胡沟断面"],
|
}[path] || defaultKeys;
|
|
treeRef.value?.setCheckedKeys(checkedKeys);
|
},
|
{ immediate: true }
|
);
|
|
// 组件挂载时初始化
|
onMounted(() => {
|
initTerrainLayer();
|
initData();
|
nextTick(() => {
|
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;
|
z-index: 99;
|
overflow: hidden;
|
|
:deep(.el-tree) {
|
overflow: hidden !important;
|
}
|
}
|
</style>
|