<template>
|
<Left @start="startSimulate" @end="endSimulate" />
|
<echartInfo :isDynamicMode="isDynamicMode" :isFinish="isFinish" v-if="rightRiverShow" />
|
<TimeLine v-if="showWaterSimulate" @time-update="timeUpdate" @is-playing="isPlaying"
|
:waterSimulateParams="waterSimulateParams" @playbackFinished="playbackFinished" @end="endSimulate" />
|
<DebuffDetail v-if="showDebuffDetail" @open="openDetail" @close="showDebuffDetail = false" />
|
<DebuffTable v-if="showDebuffTable" @close="closeDebuffTable" />
|
</template>
|
|
<script setup>
|
import { EventBus } from "@/eventBus"; // 引入事件总线
|
import { ref, onMounted, onUnmounted, provide } from "vue";
|
import TimeLine from "@/components/menu/TimeLine.vue";
|
import Left from "./left/Left.vue";
|
import echartInfo from "@/components/monifangzhen/echartInfo.vue";
|
import DebuffDetail from "@/components/tools/DebuffDetail.vue";
|
import DebuffTable from "@/components/tools/DebuffTable.vue";
|
import { getMaxInfluenceArea } from "@/api/index";
|
import { createPoint, geomToGeoJSON } from "@/utils/map.js";
|
import { loadAreaPolygon, clearAreaPolygon } from "@/utils/area";
|
|
import danger from "@/assets/img/left/danger.png";
|
import { checkedKeys } from "@/store/index";
|
|
|
import { useSimStore } from "@/store/simulation";
|
import { storeToRefs } from "pinia";
|
const simStore = useSimStore();
|
const { rightRiverShow } = storeToRefs(simStore);
|
|
|
const waterSimulateParams = ref({});
|
const showWaterSimulate = ref(false);
|
const showDebuffDetail = ref(false);
|
const showDebuffTable = ref(false);
|
const isDynamicMode = ref(false);
|
const isFinish = ref(true);
|
|
const treeMap = new Map();
|
|
|
|
|
// 提供方法给所有子组件
|
provide("simulateActions", {
|
startSimulate,
|
endSimulate,
|
});
|
|
function startSimulate(form) {
|
// console.log("form", form);
|
showWaterSimulate.value = true;
|
rightRiverShow.value = true;
|
waterSimulateParams.value = form;
|
}
|
function endSimulate() {
|
rightRiverShow.value = false;
|
showDebuffDetail.value = false;
|
clearTrailLine();
|
removeEmergencyPoints();
|
removeDataSources();
|
setTimeout(() => {
|
showWaterSimulate.value = false;
|
isDynamicMode.value = false;
|
// 清除威胁对象表格内容
|
EventBus.emit("reset-table");
|
// 清除降雨数据内容
|
EventBus.emit("clear-echart");
|
}, 1000);
|
}
|
const MaxInfluenceAreaList = ref([]);
|
// 初始化 dataSources 全局数组
|
const dataSources = [];
|
async function getTimeMarkers() {
|
const list = MaxInfluenceAreaList.value;
|
try {
|
const loadPromises = list.map(async (item) => {
|
const geojson = JSON.parse(item.geom);
|
const dataSource = await Cesium.GeoJsonDataSource.load(geojson);
|
dataSource.entities.values.forEach((entity) => {
|
if (!entity.properties) {
|
entity.properties = new Cesium.PropertyBag();
|
}
|
entity.properties.addProperty("id", item.id);
|
entity.properties.addProperty("warningLevel", item.warningLevel);
|
entity.properties.addProperty("zoneId", item.zoneId);
|
entity.polygon.outlineColor = Cesium.Color.YELLOW;
|
entity.polygon.outline = true;
|
const position = Cesium.Cartesian3.fromDegrees(item.X, item.Y, item.Z);
|
const billboardEntity = viewer.entities.add({
|
position: position,
|
billboard: {
|
image: danger,
|
scale: 1.0,
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
|
0,
|
1500
|
),
|
},
|
});
|
dataSource.entities.add(billboardEntity);
|
});
|
viewer.dataSources.add(dataSource);
|
dataSources.push(dataSource);
|
});
|
await Promise.all(loadPromises);
|
setupRowClickListener(dataSources);
|
} catch (error) { }
|
}
|
// 清除隐患点
|
function removeDataSources() {
|
dataSources.forEach((dataSource, index) => {
|
// 遍历当前数据源的所有实体
|
const entities = dataSource.entities.values;
|
entities.forEach((entity, entityIndex) => {
|
if (entity.billboard) {
|
viewer.entities.remove(entity);
|
}
|
});
|
viewer.dataSources.remove(dataSource);
|
});
|
dataSources.length = 0;
|
}
|
// 避险点,绿色富文本
|
function addTetrahedron(visible) {
|
const emergencyAreaList = [];
|
// 这里是添加避险点底层面片
|
loadAreaPolygon("/json/emergency_area.geojson", true).then((entities) => {
|
emergencyAreaList.push(...entities);
|
});
|
// console.log('polygon', polygon);
|
|
let list = [
|
{
|
name: "尹建华家",
|
longitude: 116.593517,
|
latitude: 40.568391,
|
altitude: 528.45,
|
},
|
// {
|
// name: "范振江家",
|
// longitude: 116.591059,
|
// latitude: 40.574068,
|
// altitude: 528,
|
// },
|
// {
|
// name: "后坡",
|
// longitude: 116.597975,
|
// latitude: 40.558199,
|
// altitude: 528,
|
// },
|
];
|
// 这里是添加避险点富文本高亮显示
|
list.forEach((item) => {
|
let point = earthCtrl.factory.createRichTextPoint(
|
"避险点",
|
[item.longitude, item.latitude, item.altitude - 10],
|
{
|
distanceDisplayCondition:
|
new SmartEarth.Cesium.DistanceDisplayCondition(0, 2000),
|
fontColor: "#ffffff",
|
fontSize: 20,
|
},
|
"0"
|
);
|
console.log("point", point);
|
emergencyAreaList.push(point);
|
});
|
treeMap.set("避险点", emergencyAreaList);
|
}
|
// 删除避险点的富文本实体
|
function removeEmergencyPoints() {
|
const emergencyAreaList = treeMap.get("避险点"); // 获取存储的避险点实体列表
|
if (emergencyAreaList && emergencyAreaList.length > 0) {
|
emergencyAreaList.forEach((entity) => {
|
if (entity && typeof entity.deleteObject === "function") {
|
// 如果有 deleteObject 方法,优先调用
|
entity.deleteObject();
|
} else if (entity && typeof entity.clear === "function") {
|
// 如果有 clear 方法,调用 clear
|
entity.clear();
|
} else if (entity && earthCtrl && earthCtrl.coreMap) {
|
// 如果是 Cesium 实体,使用 coreMap.entities.remove 移除
|
earthCtrl.coreMap.entities.remove(entity);
|
}
|
});
|
treeMap.set("避险点", []); // 清空存储的避险点列表
|
}
|
}
|
|
// 避险路线
|
let pathLayer = null; // 存储创建的图层
|
function showLine() {
|
// 创建新图层
|
pathLayer = earthCtrl.factory.createPathLayer({
|
url: "/json/line.json",
|
color: "#0033FF",
|
width: 15.0,
|
pointColor: "#FFFFFF",
|
speed: 2,
|
far: 50000,
|
});
|
}
|
|
// 清除避险路线
|
function clearTrailLine() {
|
if (pathLayer) {
|
pathLayer.clear();
|
}
|
// if (item && typeof item.deleteObject === "function") {
|
// item.deleteObject();
|
// } else if (item && typeof item.clear === "function") {
|
// item.clear();
|
// } else if (item && earthCtrl && earthCtrl.coreMap) {
|
// earthCtrl.coreMap.entities.remove(item);
|
// }
|
// });
|
// pathLayer = [];
|
}
|
function timeUpdate(percentage) {
|
if (percentage > 99) {
|
if (showDebuffDetail.value) {
|
return;
|
}
|
checkedKeys.value = ["避险点"];
|
showDebuffDetail.value = true;
|
getTimeMarkers();
|
addTetrahedron();
|
showLine();
|
}
|
}
|
function openDetail() {
|
showDebuffTable.value = true;
|
}
|
function closeDebuffTable() {
|
showDebuffTable.value = false;
|
showDebuffDetail.value = true;
|
}
|
function getMaxInfluenceAreaData() {
|
getMaxInfluenceArea().then((res) => {
|
MaxInfluenceAreaList.value = res.data.items;
|
});
|
}
|
|
function isPlaying(val) {
|
isDynamicMode.value = val;
|
}
|
|
function playbackFinished(val) {
|
isFinish.value = val;
|
}
|
// 定义全局变量存储当前正在闪动的面片
|
let flashingPolygon = null;
|
|
// 添加事件监听器,接收来自表格组件的事件
|
function setupRowClickListener(dataSources) {
|
if (!Array.isArray(dataSources) || dataSources.length === 0) {
|
console.error("Data sources array is undefined or empty!");
|
return;
|
}
|
EventBus.on("row-clicked", (id) => {
|
const clickedEntity = findEntityById(id, dataSources);
|
if (clickedEntity) {
|
// 如果点击的是同一个实体,则停止闪动并清空选择
|
if (flashingPolygon && flashingPolygon === clickedEntity) {
|
stopFlashing(flashingPolygon);
|
flashingPolygon = null; // 清空当前选中的实体
|
return;
|
}
|
// 如果有其他实体正在闪动,先停止它的闪动
|
if (flashingPolygon && flashingPolygon !== clickedEntity) {
|
stopFlashing(flashingPolygon);
|
}
|
// 开始新的闪动
|
startFlashing(clickedEntity);
|
flashingPolygon = clickedEntity;
|
} else {
|
console.warn(`No entity found with ID: ${id}`);
|
}
|
});
|
}
|
|
// 根据ID查找实体
|
function findEntityById(id, dataSources) {
|
if (!Array.isArray(dataSources) || dataSources.length === 0) {
|
console.error("Data sources array is undefined or empty!");
|
return null;
|
}
|
console.log("Searching for ID:", id);
|
for (const dataSource of dataSources) {
|
const entities = dataSource.entities.values;
|
for (const entity of entities) {
|
const entityId = entity.properties?.id?.getValue();
|
if (String(entityId) === String(id)) {
|
return entity;
|
}
|
}
|
}
|
return null;
|
}
|
|
// 开始闪动效果
|
function startFlashing(polygonEntity) {
|
// 存储原始颜色
|
const originalColor = polygonEntity.polygon.material.color.getValue();
|
polygonEntity._originalColor = originalColor; // 将原始颜色保存到实体中
|
|
// 创建颜色变化的回调函数
|
let isFlashing = true; // 标记是否正在闪动
|
polygonEntity.polygon.material = new Cesium.ColorMaterialProperty(
|
new Cesium.CallbackProperty(() => {
|
if (!isFlashing) return originalColor; // 如果停止闪动,恢复原始颜色
|
// 切换颜色(例如红色和原始颜色交替)
|
const currentTime = Date.now();
|
const flashColor = Cesium.Color.RED.withAlpha(1); // 闪动颜色
|
return Math.floor(currentTime / 500) % 2 === 0
|
? flashColor
|
: originalColor;
|
}, false)
|
);
|
|
// 将闪动状态保存到实体上,便于后续控制
|
polygonEntity._isFlashing = isFlashing;
|
}
|
|
// 停止闪动效果
|
function stopFlashing(polygonEntity) {
|
// 恢复原始颜色
|
const originalColor = polygonEntity._originalColor || Cesium.Color.WHITE; // 如果没有原始颜色,默认使用白色
|
polygonEntity.polygon.material = new Cesium.ColorMaterialProperty(
|
originalColor
|
);
|
|
// 清空闪动状态
|
polygonEntity._isFlashing = false;
|
polygonEntity._originalColor = null; // 清除保存的原始颜色
|
}
|
onMounted(() => {
|
setupRowClickListener();
|
getMaxInfluenceAreaData();
|
});
|
onUnmounted(() => {
|
endSimulate();
|
});
|
// // 转换坐标系,笛卡尔坐标转为WGS48
|
// const positions = [[-2171569.1995107993, 4338474.198855222, 4127198.938949332]];
|
// const wgs84Positions = positions.map((xyz) => {
|
// const cartesian = Cesium.Cartesian3.fromArray(xyz);
|
// const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
|
|
// // 弧度转角度
|
// const lon = Cesium.Math.toDegrees(cartographic.longitude);
|
// const lat = Cesium.Math.toDegrees(cartographic.latitude);
|
// const height = cartographic.height; // 单位:米
|
|
// return [lon, lat, height];
|
// });
|
</script>
|
<style lang="less" scoped>
|
@import url("../assets/css/home.css");
|
</style>
|