wangjuncheng
7 天以前 bf0eb543e2deab8a1629dd2a46f8e1cd191531e1
src/views/mnfz.vue
@@ -1,6 +1,10 @@
<template>
  <Left @start="startSimulate" @end="endSimulate" />
  <echartInfo :isDynamicMode="isDynamicMode" :isFinish="isFinish" />
  <echartInfo
    :isDynamicMode="isDynamicMode"
    :isFinish="isFinish"
    v-if="rightRiverShow"
  />
  <TimeLine
    v-if="showWaterSimulate"
    @time-update="timeUpdate"
@@ -8,7 +12,9 @@
    :waterSimulateParams="waterSimulateParams"
    @playbackFinished="playbackFinished"
    @end="endSimulate"
    @isColorRender="isColorRender"
  />
  <LegendMNFZ class="legend" v-if="isShowLegend"></LegendMNFZ>
  <DebuffDetail
    v-if="showDebuffDetail"
    @open="openDetail"
@@ -18,24 +24,42 @@
</template>
<script setup>
import { EventBus } from "@/eventBus"; // 引入事件总线
import { ref, onMounted, onUnmounted, provide } from "vue";
import TimeLine from "@/components/menu/TimeLine.vue";
import LegendMNFZ from "@/components/tools/Legend_mnfz.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,
  convertToGeoJson,
} from "@/utils/area";
import colors from "@/assets/img/left/colors3.png";
import danger from "@/assets/img/left/danger.png";
import { checkedKeys } from "@/store/index";
import { useSimStore } from "@/store/simulation";
import { storeToRefs } from "pinia";
import { getSafePoint } from "@/api/hpApi";
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 isShowLegend = ref(false);
const treeMap = new Map();
// 提供方法给所有子组件
provide("simulateActions", {
@@ -44,183 +68,479 @@
});
function startSimulate(form) {
  // console.log("form", form);
  showWaterSimulate.value = true;
  rightRiverShow.value = true;
  waterSimulateParams.value = form;
}
function endSimulate() {
  // showDebuffDetail.value = true
  rightRiverShow.value = false;
  showDebuffDetail.value = false;
  clearTrailLine();
  removeEmergencyPoints();
  removeDataSources();
  showWaterSimulate.value = false;
  setTimeout(() => {
    showWaterSimulate.value = false;
    isDynamicMode.value = false;
  }, 2000);
    // 清除威胁对象表格内容
    EventBus.emit("reset-table");
    // 清除降雨数据内容
    EventBus.emit("clear-echart");
  }, 1000);
}
const MaxInfluenceAreaList = ref([]);
// 初始化 dataSources 全局数组
const dataSources = [];
function getTimeMarkers() {
  // 将改 list数据的 gemo EPSG:4548 坐标 转为 wgs84 坐标系的 geojson 数据
async function getTimeMarkers() {
  const list = MaxInfluenceAreaList.value;
  list.forEach((item, index) => {
    const geosjon = geomToGeoJSON(item.geom);
    Cesium.GeoJsonDataSource.load(geosjon, {
      stroke: Cesium.Color.RED, // 边框颜色
      strokeWidth: 2, // 边框宽度
      fill: Cesium.Color.RED.withAlpha(0.5), // 填充颜色(带透明度)
    }).then((dataSource) => {
  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) => {
  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;
}
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;
  });
// 避险场所,绿色富文本
async function addTetrahedron(visible) {
  const emergencyAreaList = [];
  console.log(min, max);
  try {
    let codesToFetch = [];
  let _TrailLine = earthCtrl.factory.createTrailLineWall(
    LineInterpolation.positions,
    {
      maximumHeights: max,
      minimumHeights: min,
      color: "#ffffff", //线颜色(可选)
      url: colors,
    // 判断当前选择区域是否为“区”
    if (simStore.selectedScheme.areaName.includes("区")) {
      // 从 simStore.townCodeAll 中拿到该区下的所有乡镇 code
      const townList = simStore.townCodeAll[simStore.selectedScheme.areaName];
      // 假设 townList 是一个数组,里面每个元素有 .code 字段
      if (Array.isArray(townList)) {
        codesToFetch = townList.map((item) => item.code);
      } else {
        console.warn("未找到对应的乡镇列表");
        return;
      }
    } else {
      // 不是“区”,就使用默认 code
      codesToFetch = ["110116110218"];
    }
  );
  TrailLine.push(_TrailLine);
}
// function showLine() {
//   earthCtrl.factory.createSimpleGraphic(
//     "polyline",
//     { clampToGround: true },
//     (entity) => {
//       if (entity) {
//         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,
//           },
//         ];
//         // console.log("positions", positions);
//         addWall(position, [entity]);
//         earthCtrl.factory.SimpleGraphic.remove(entity.id);
    // 并发请求所有 code 的避险点数据
    const allRes = await Promise.all(
      codesToFetch.map((code) => getSafePoint(code))
    );
    // 合并结果(假设每个 res.data 是一个数组)
    const allSafePoints = allRes.flatMap((res) => res.data);
    // 转换为 GeoJSON(如果每个 data 都需要单独处理)
    const geoJsonData = convertToGeoJson(allSafePoints);
    // 加载底层面片(多边形)
    const polygonEntities = await loadAreaPolygon(geoJsonData, true);
    emergencyAreaList.push(...polygonEntities);
    // 添加绿色富文本标注
    const textPromises = allSafePoints.map(async (item) => {
      const point = earthCtrl.factory.createRichTextPoint(
        "避险场所",
        [item.lon, item.lat, 540],
        {
          distanceDisplayCondition:
            new SmartEarth.Cesium.DistanceDisplayCondition(0, 2000),
          fontColor: "#fff",
          fontSize: 20,
        },
        "0"
      );
      emergencyAreaList.push(point);
    });
    await Promise.all(textPromises);
    // 将结果保存到 treeMap
    treeMap.set("避险场所", emergencyAreaList);
  } catch (error) {
    console.error("加载避险场所失败:", error);
  }
}
// 删除避险场所的富文本实体
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) {
        // 清除避险点绿色面片
        clearAreaPolygon();
        // 如果是 Cesium 实体,使用 coreMap.entities.remove 移除
        earthCtrl.coreMap.entities.remove(entity);
      }
    });
    treeMap.set("避险场所", []); // 清空存储的避险场所列表
  }
}
// 虚线避险路线
//   const position1 = [
//     {
//       x: -2172867.1941179745,
//       y: 4339567.67446477,
//       z: 4125575.4386990573,
//     },
//     {
//       x: -2172867.1941179745,
//       y: 4339567.67446477,
//       z: 4125575.4386990573,
//     },
//     {
//       x: -2172700.396781143,
//       y: 4339454.037139385,
//       z: 4125736.906847591,
//     },
//     {
//       x: -2172744.4001612393,
//       y: 4339361.421455601,
//       z: 4125804.324253885,
//     },
//     {
//       x: -2172824.3311673277,
//       y: 4339274.56533081,
//       z: 4125844.432999503,
//     },
//     {
//       x: -2172822.298957661,
//       y: 4339226.700024104,
//       z: 4125896.451233209,
//     },
//     {
//       x: -2172776.0573917977,
//       y: 4339194.843872361,
//       z: 4125947.9581145854,
//     },
//     {
//       x: -2172755.2828807314,
//       y: 4339149.410126468,
//       z: 4125995.9286539108,
//     },
//     {
//       x: -2172660.9533022284,
//       y: 4339085.401362197,
//       z: 4126101.3750262205,
//     },
//     {
//       x: -2172613.460204307,
//       y: 4339073.342332504,
//       z: 4126134.479399525,
//     },
//     {
//       x: -2172583.664140033,
//       y: 4339085.533980615,
//       z: 4126140.3272964833,
//     },
//     {
//       x: -2172348.977405535,
//       y: 4338967.122025027,
//       z: 4126358.7532469626,
//     },
//     {
//       x: -2172276.019363938,
//       y: 4338943.999121099,
//       z: 4126416.339696519,
//     },
//     {
//       x: -2172178.064812976,
//       y: 4338928.9482959965,
//       z: 4126475.798078439,
//     },
//     {
//       x: -2172171.5451145098,
//       y: 4338941.186930828,
//       z: 4126466.425301899,
//     },
//     {
//       x: -2172177.9565195283,
//       y: 4338940.424956708,
//       z: 4126463.8688932694,
//     },
//   ];
///////////////////////////// 流光线避险路线/////////////////////////////
let pathLayer = null; // 存储创建的图层
function showLine() {
  // 创建新图层
  pathLayer = earthCtrl.factory.createPathLayer({
    url: "/json/line.json",
    color: "#00FF00",
    width: 12.0,
    pointColor: "#FFFF73",
    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 = null;
}
///////////////////////////// 流光线避险路线/////////////////////////////
///////////////////////////// 箭头版避险路线/////////////////////////////
// let TrailLine = [];
// async function showLine() {
//   const position1 = [
//     {
//       x: -2172867.1941179745,
//       y: 4339567.67446477,
//       z: 4125575.4386990573,
//     },
//     {
//       x: -2172867.1941179745,
//       y: 4339567.67446477,
//       z: 4125575.4386990573,
//     },
//     {
//       x: -2172700.396781143,
//       y: 4339454.037139385,
//       z: 4125736.906847591,
//     },
//     {
//       x: -2172744.4001612393,
//       y: 4339361.421455601,
//       z: 4125804.324253885,
//     },
//     {
//       x: -2172824.3311673277,
//       y: 4339274.56533081,
//       z: 4125844.432999503,
//     },
//     {
//       x: -2172822.298957661,
//       y: 4339226.700024104,
//       z: 4125896.451233209,
//     },
//     {
//       x: -2172776.0573917977,
//       y: 4339194.843872361,
//       z: 4125947.9581145854,
//     },
//     {
//       x: -2172755.2828807314,
//       y: 4339149.410126468,
//       z: 4125995.9286539108,
//     },
//     {
//       x: -2172660.9533022284,
//       y: 4339085.401362197,
//       z: 4126101.3750262205,
//     },
//     {
//       x: -2172613.460204307,
//       y: 4339073.342332504,
//       z: 4126134.479399525,
//     },
//     {
//       x: -2172583.664140033,
//       y: 4339085.533980615,
//       z: 4126140.3272964833,
//     },
//     {
//       x: -2172348.977405535,
//       y: 4338967.122025027,
//       z: 4126358.7532469626,
//     },
//     {
//       x: -2172276.019363938,
//       y: 4338943.999121099,
//       z: 4126416.339696519,
//     },
//     {
//       x: -2172178.064812976,
//       y: 4338928.9482959965,
//       z: 4126475.798078439,
//     },
//     {
//       x: -2172171.5451145098,
//       y: 4338941.186930828,
//       z: 4126466.425301899,
//     },
//     {
//       x: -2172177.9565195283,
//       y: 4338940.424956708,
//       z: 4126463.8688932694,
//     },
//   ];
//   const position2 = [
//     {
//       x: -2171569.1995107993,
//       y: 4338474.198855222,
//       z: 4127198.938949332,
//     },
//     {
//       x: -2171596.1458028457,
//       y: 4338508.014766663,
//       z: 4127160.0148374927,
//     },
//     {
//       x: -2171663.8877153755,
//       y: 4338521.115613981,
//       z: 4127111.758040112,
//     },
//     {
//       x: -2171815.8899659193,
//       y: 4338612.264105235,
//       z: 4126950.0428421027,
//     },
//     {
//       x: -2171839.2819730053,
//       y: 4338700.186548507,
//       z: 4126845.712987762,
//     },
//     {
//       x: -2171792.4015423204,
//       y: 4338769.135301243,
//       z: 4126802.7938519563,
//     },
//     {
//       x: -2171943.7495626938,
//       y: 4338851.9854133595,
//       z: 4126649.5658632508,
//     },
//     {
//       x: -2172026.1490882114,
//       y: 4338896.137127666,
//       z: 4126571.6284971433,
//     },
//     {
//       x: -2172182.2854437083,
//       y: 4338931.410179759,
//       z: 4126471.0308961133,
//     },
//     {
//       x: -2172175.3377184337,
//       y: 4338941.338674108,
//       z: 4126464.288707359,
//     },
//     {
//       x: -2172175.3377184337,
//       y: 4338941.338674108,
//       z: 4126464.288707359,
//     },
//   ];
//   // 定义一个函数来创建轨迹线
//   function createTrailLine(positions, color = "#ffffff") {
//     let LineInterpolation = earthCtrl.core.LineInterpolation(
//       earthCtrl.coreMap,
//       {
//         positions: positions,
//         num: 50,
//         getHeight: true,
//       }
//     }
//   );
//     );
//     let min = LineInterpolation.height;
//     let max = min.map((item) => item + 35);
//     console.log(min, max);
//     let _TrailLine = earthCtrl.factory.createTrailLineWall(
//       LineInterpolation.positions,
//       {
//         maximumHeights: max,
//         minimumHeights: min,
//         color: color, // 线颜色
//         url: colors, // 如果没有设置 colors,请用纯色或删除此行
//       }
//     );
//     TrailLine.push(_TrailLine);
//   }
//   // 分别创建两条轨迹线
//   createTrailLine(position1, "#ff0000"); // 红色轨迹
//   createTrailLine(position2, "#0000ff"); // 蓝色轨迹
// }
// // 清除轨迹线对象
// 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 (percentage > 99.9) {
    if (showDebuffDetail.value) {
      return;
    }
    checkedKeys.value = ["避险点"];
    checkedKeys.value = ["避险场所"];
    showDebuffDetail.value = true;
    getTimeMarkers();
    addTetrahedron();
    showLine();
  }
}
@@ -244,13 +564,123 @@
function playbackFinished(val) {
  isFinish.value = val;
}
function isColorRender(val) {
  // console.log('这里打印是否显示水位图例的值:',val);
  isShowLegend.value = val;
}
// 定义全局变量存储当前正在闪动的面片
let flashingPolygon = null;
// 添加事件监听器,接收来自表格组件的事件
function setupRowClickListener(dataSources) {
  if (!Array.isArray(dataSources) || dataSources.length === 0) {
    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) {
    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");
.legend {
  // background: url("@/assets/img/right/rightbg.png");
  color: white;
  position: fixed;
  bottom: 6%;
  right: 20%;
  z-index: 3333;
}
</style>