<template>
|
<Left @start="startSimulate" @end="endSimulate" />
|
<echartInfo :isDynamicMode="isDynamicMode" :isFinish="isFinish" v-if="loadingSim" />
|
<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 colors from "@/assets/img/left/colors3.png";
|
import danger from "@/assets/img/left/danger.png";
|
import { checkedKeys } from "@/store/index";
|
const waterSimulateParams = ref({});
|
const showWaterSimulate = ref(false);
|
const showDebuffDetail = ref(false);
|
const showDebuffTable = ref(false);
|
const isDynamicMode = ref(false);
|
const isFinish = ref(true);
|
const loadingSim = ref(false);
|
|
const treeMap = new Map();
|
|
// 提供方法给所有子组件
|
provide("simulateActions", {
|
startSimulate,
|
endSimulate,
|
});
|
|
function startSimulate(form) {
|
// console.log("form", form);
|
showWaterSimulate.value = true;
|
loadingSim.value = true
|
waterSimulateParams.value = form;
|
}
|
function endSimulate() {
|
loadingSim.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 TrailLine = [];
|
async function showLine() {
|
const position = [
|
{
|
x: -2172540.8322597803,
|
y: 4339064.62665997,
|
z: 4126183.3895281963,
|
},
|
{
|
x: -2172480.18394144,
|
y: 4339033.15167176,
|
z: 4126240.9529584926,
|
},
|
{
|
x: -2172454.114348403,
|
y: 4339020.0398392705,
|
z: 4126261.946960697,
|
},
|
{
|
x: -2172377.9670952093,
|
y: 4338976.609385458,
|
z: 4126333.862357211,
|
},
|
{
|
x: -2172299.4142002705,
|
y: 4338951.971578909,
|
z: 4126397.5205803993,
|
},
|
{
|
x: -2172245.1703274297,
|
y: 4338940.86037857,
|
z: 4126436.276389208,
|
},
|
{
|
x: -2172176.7332184147,
|
y: 4338930.525741544,
|
z: 4126477.629952572,
|
},
|
{
|
x: -2172173.8151051304,
|
y: 4338939.043883864,
|
z: 4126469.336927342,
|
},
|
{
|
x: -2172173.7151194704,
|
y: 4338939.023235937,
|
z: 4126469.4107743693,
|
},
|
];
|
let LineInterpolation = earthCtrl.core.LineInterpolation(earthCtrl.coreMap, {
|
positions: position,
|
num: 50,
|
getHeight: true,
|
});
|
// console.log(LineInterpolation.height, "A");
|
|
let min = LineInterpolation.height;
|
let max = min.map((item) => {
|
return item + 35;
|
});
|
|
console.log(min, max);
|
|
let _TrailLine = earthCtrl.factory.createTrailLineWall(
|
LineInterpolation.positions,
|
{
|
maximumHeights: max,
|
minimumHeights: min,
|
color: "#ffffff", //线颜色(可选)
|
url: colors,
|
}
|
);
|
TrailLine.push(_TrailLine);
|
}
|
// 清除轨迹线对象
|
function clearTrailLine() {
|
TrailLine.forEach((item, index) => {
|
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);
|
}
|
});
|
TrailLine = [];
|
}
|
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);
|
}
|
|
startFlashing(clickedEntity);
|
flashingPolygon = clickedEntity;
|
} else {
|
}
|
});
|
}
|
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();
|
});
|
</script>
|
<style lang="less" scoped>
|
@import url("../assets/css/home.css");
|
</style>
|