guonan
2025-06-17 be9c1145fc79165142fbe29aacb04dd8e34dd23f
避险场所以及完善弹窗详情
已修改8个文件
414 ■■■■■ 文件已修改
src/api/hpApi.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tools/Detail.vue 71 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tools/LayerTree.vue 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constant/dict.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/simulation.js 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/area.js 187 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/GisView.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mnfz.vue 99 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/hpApi.js
@@ -127,7 +127,6 @@
// 监测设备接口
/**
 * 检查时间列是否按升序排列
 * @param {string} data - 雨量计设备类型id
 * @param {string} townCode - 乡镇code,可以查询乡镇监测设备信息
 */
@@ -136,6 +135,8 @@
    filterObject: {
      "dictDeviceType": data,
      "townCode": townCode,
      "year": 2025
      // 所属项目
      // "belongObjList": [
      //   "1797461961110261762"
@@ -152,6 +153,7 @@
    filterObject: {
      "divisionDistrict": data,
      // 所属项目
      // 如果不加这个,则返回的全是强震仪(1933099069385355265)
      "belongObjList": [
        "1797461961110261762"
      ],
@@ -216,4 +218,14 @@
    params
  });
  return response.data;
}
// 查询孙胡沟避险场所
export async function getSafePoint() {
  const response = await axios.get("/hp/safeHavenLocation/getDataSelect", {
    params: {
      divisionId: "110116110218"
    }
  });
  return response.data;
}
src/components/tools/Detail.vue
@@ -1,6 +1,6 @@
<template>
  <div class="detail" ref="detailRef">
    <div class="detail-top">{{ detailTitle }}</div>
    <div class="detail-top" :title="name">{{ detailTitle }}</div>
    <div class="detail-close" @click="closeMsg"></div>
    <div class="detail-context">
      <div v-for="(item, key) in detailList" :key="key" class="detail-item">
@@ -24,13 +24,13 @@
const detailList = ref([]);
const detailTitle = ref("设备详情");
const name = ref("");
function closeMsg() {
  showDeviceDetail.value = false;
  coloseDialog();
}
// 监测设备具体信息
function handlDeviceDetail() {
  // const name = deviceDetail.value.deviceForShort;
  detailTitle.value = deviceDetail.value.deviceForShort;
  detailList.value = [
    {
@@ -43,17 +43,16 @@
      value: deviceDetail.value.type || "",
    },
    {
      name: "安装时间",
      value: "2024-01-15 12:55:18" || deviceDetail.value.startTime,
      name: "关联隐患点",
      value: deviceDetail.value.hdName,
    },
    {
      name: "更新时间",
      value: "2025-02-15 8:15:28",
      name: "群防员",
      value: deviceDetail.value.groupTestGroupDefenseUserName,
    },
    {
      name: "设备位置",
      value: deviceDetail.value.deviceForShort || cityData.listData[0],
      //   value: deviceDetail.value.name.split("孙胡沟")[0] || cityData.listData[0],
      name: "群防员电话",
      value: deviceDetail.value.groupTestGroupDefenseMobile,
    },
  ];
}
@@ -62,21 +61,46 @@
  const name = deviceDetail.value.hdName;
  detailTitle.value = name;
  detailList.value = [
    // {}
    {
      name: "隐患类型",
      name: "灾害类型",
      value: deviceDetail.value.disasterType || "泥石流",
    },
    {
      name: "主管科长",
      value: "张浩",
      name: "威胁对象",
      value: deviceDetail.value.threatObj || "居民点",
    },
    {
      name: "主管镇长",
      value: deviceDetail.value.supervisorAlcaldeUserName,
      name: "规模等级",
      value: deviceDetail.value.disasterGrade || "小型",
    },
    {
      name: "险情等级",
      value: deviceDetail.value.riskLevel || "小型",
    },
    {
      name: "威胁人数",
      value: deviceDetail.value.threatPersonNum || "0",
    },
    {
      name: "威胁户数",
      value: deviceDetail.value.threatHouseNum || "0",
    },
    {
      name: "威胁房数",
      value: deviceDetail.value.threatRoomNum || "0",
    },
    {
      name: "是否治理",
      value: deviceDetail.value.isGovern || "否",
    },
    {
      name: "群测群防",
      value: deviceDetail.value.groupTestGroupDefenseUserName,
    },
    {
      name: "群测群防",
      value: deviceDetail.value.groupTestGroupDefenseMobile,
    },
    {
      name: "隐患位置",
@@ -91,8 +115,10 @@
function loadClassNameDetail() {
  if (className.value == "device") {
    handlDeviceDetail();
    name.value = deviceDetail.value.deviceName;
  } else if (className.value == "district") {
    handleDistrictDetail();
    name.value = deviceDetail.value.hdName;
  }
}
const detailRef = ref(null);
@@ -155,11 +181,18 @@
  left: 1.25rem;
  font-weight: 700;
  font-size: 1.125rem;
  font-weight: 700;
  color: #fff;
  line-height: 2.5rem;
  width: 16.875rem;
  width: 16.875rem; /* 容器宽度固定或限制 */
  cursor: pointer;
  /* 超出隐藏 + 省略号 */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* 可选:添加过渡动画 */
  transition: all 0.3s ease;
}
.detail-close {
@@ -184,6 +217,8 @@
  top: 3.8rem;
  left: 1.25rem;
  width: 21.875rem;
  overflow-y: auto;
  height: 63%;
}
.detail-item {
@@ -193,9 +228,11 @@
  margin-left: 0.625rem;
}
.detail-name {
  width: 100px;
  display: inline-block; /* 关键 */
  max-width: 100%; /* 防止溢出 */
  font-weight: 700;
  color: #94e0c4;
  white-space: nowrap; /* 可选:防止文字换行 */
  &::after {
    content: ":";
  }
src/components/tools/LayerTree.vue
@@ -17,10 +17,15 @@
import { createPoint, removeEntities, addTileset } from "@/utils/map";
import { deviceDictList, getDictName } from "@/constant/dict.js";
import { useRoute } from "vue-router";
import { loadAreaPolygon, clearAreaPolygon } from "@/utils/area";
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();
@@ -319,9 +324,13 @@
 * 添加避险场所数据
 */
function addTetrahedron() {
  loadAreaPolygon("/json/emergency_area.geojson", true).then((entities) => {
    entities.forEach((entity) => (entity.show = false));
    treeMap.set("避险场所", entities);
  getSafePoint().then((res) => {
    const geoJsonData = convertToGeoJson(res.data); // 转换为 GeoJSON
    // 加载 GeoJSON 数据到地图
    loadAreaPolygon(geoJsonData, true).then((entities) => {
      entities.forEach((entity) => (entity.show = false));
      treeMap.set("避险场所", entities);
    });
  });
}
@@ -350,6 +359,7 @@
    const defaultKeys = [...defaultSelectedKeys.value];
    const checkedKeys =
      {
        // 页面默认勾选显示在此处
        "/yhgl": [...defaultKeys, "孙胡沟隐患点"],
        "/zhjc": [...defaultKeys, "综合监测设备信息"],
        // "/mnfz": [...defaultKeys, "孙胡沟断面"],
src/constant/dict.js
@@ -8,6 +8,10 @@
        value: "1874719366287368194",
    },
    {
        label: "强震仪",
        value: "1933049314953330689",
    },
    {
        label: "雨量计1",
        value: "1437295810",
    },
@@ -35,6 +39,10 @@
        label: "墒情",
        value: "14372958380",
    },
    {
        label: '位移倾角振动加速度计',
        value: '1437295831'
    }
]
export function getDictName(dictList, value) {
src/store/simulation.js
@@ -2,12 +2,11 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useSimStore = defineStore('simulation', () => {
    // 目录树选中
    const userSelectedLayers = ref([])
    // 隐患点列表
    const DangerPoint = ref([])
    const DeviceShowSwitch = ref(false)
    const DangerShowSwitch = ref(false)
    const DangerPoint = ref([])
    // 监测设备列表
    const devices = ref([])
    const navigationShow = ref(true)
@@ -154,9 +153,7 @@
        }
    }
    const updateSelectedLayers = (keys) => {
        userSelectedLayers.value = keys;
    }
@@ -188,7 +185,6 @@
        DangerShowSwitch,
        waterLegendData,
        isShowEarth,
        userSelectedLayers,
        devices,
        // 方案相关方法
@@ -210,6 +206,5 @@
        startMNFZ,
        startMNPG,
        handleNavClick,
        updateSelectedLayers
    }
})
src/utils/area.js
@@ -1,112 +1,116 @@
let areaPrimitives = []
let areaDataSource = []
export function loadAreaPolygon(url, isPolluted = false) {
    let color = new Cesium.Color(1.0, 0.0, 0.0, 0.1)
/**
 * 将避险场所数据转为 GeoJSON FeatureCollection
 */
export function convertToGeoJson(data, offset = 0.0001) {
    const features = data.map((item) => {
        const lon = parseFloat(item.lon);
        const lat = parseFloat(item.lat);
        // 构造一个小正方形区域(5米左右)
        const coordinates = [
            [
                [lon, lat],
                [lon + offset, lat],
                [lon + offset, lat - offset],
                [lon, lat - offset],
                [lon, lat],
            ],
        ];
        return {
            type: "Feature",
            properties: {
                id: item.safeHavenId,
                name: item.safeHavenName,
                locationInfo: item.locationInfo,
                area: item.area,
                safeHavenType: item.safeHavenType,
                accommodatePersonNum: item.accommodatePersonNum,
                planResettlementPersonNum: item.planResettlementPersonNum,
                materialReserve: item.materialReserve,
                remark: item.remark,
            },
            geometry: {
                type: "MultiPolygon",
                coordinates: [coordinates],
            },
        };
    });
    return {
        type: "FeatureCollection",
        name: "emergency_area",
        crs: {
            type: "name",
            properties: {
                name: "urn:ogc:def:crs:OGC:1.3:CRS84",
            },
        },
        features,
    };
}
export function loadAreaPolygon(geoJsonData, isPolluted = false) {
    let color = new Cesium.Color(1.0, 0.0, 0.0, 0.1);
    if (isPolluted) {
        color = Cesium.Color.GREEN
        color = Cesium.Color.GREEN;
    }
    // 使用 GeoJsonDataSource 加载 GeoJSON 数据
    const dataSourcePromise = Cesium.GeoJsonDataSource.load(url, {
    const dataSourcePromise = Cesium.GeoJsonDataSource.load(geoJsonData, {
        clampToGround: true,
    })
    });
    // 获取 GeoJSON 中的第一个 Polygon feature
    return dataSourcePromise.then(function (dataSource) {
        viewer.dataSources.add(dataSource)
        // console.log("dataSource", dataSource)
        // 获取 GeoJSON 中的第一个 Polygon feature
        areaDataSource.push(dataSource)
        viewer.dataSources.add(dataSource);
        areaDataSource.push(dataSource);
        // const polygonEntity = dataSource.entities.values[0]
        // let areaPrimitive = createAreaPolygon(polygonEntity, color)
        // areaPrimitives.push(areaPrimitive)
        // return areaPrimitive
        const polygonEntity = dataSource.entities.values
        // console.log("polygonEntity", polygonEntity)
        const distanceDisplayCondition = new Cesium.DistanceDisplayCondition(1000, 50000000)
        const polygonEntity = dataSource.entities.values;
        const distanceDisplayCondition = new Cesium.DistanceDisplayCondition(1000, 50000000);
        polygonEntity.forEach(entity => {
            // console.log("entity", entity)
            entity.polygon.material = new Cesium.ColorMaterialProperty(color);
            entity.polygon.material = new Cesium.ColorMaterialProperty(
                // Cesium.Color.LIGHTSTEELBLUE.withAlpha(0.2)
                color
                // new Cesium.Color.fromCssColorString("#0f2636b3")
                // Cesium.Color.fromRandom({
                //     alpha: 0.5,
                //     minimumAlpha: 0.2,
                //     maximumAlpha: 0.9,
                // })
            )
            const properties = entity.properties;
            const fullname = properties.name.getValue();
            // entity.polygon.distanceDisplayCondition = distanceDisplayCondition
            const positions = entity.polygon.hierarchy._value.positions;
            const properties = entity.properties
            const fullname = properties.name.getValue()
            const positions = entity.polygon.hierarchy._value.positions
            // entity.position = positions
            entity.label = {
                // 文本。支持显式换行符“ \ n”
                text: fullname || "默认标签",
                // 字体样式,以CSS语法指定字体
                font: "20pt Source Han Sans CN",
                // 字体颜色
                fillColor: Cesium.Color.WHITE,
                // 背景颜色
                backgroundColor: Cesium.Color.BLACK.withAlpha(0.8),
                // 是否显示背景颜色
                showBackground: false,
                // 字体边框
                outline: true,
                // 字体边框颜色
                outlineColor: Cesium.Color.WHITE,
                // 字体边框尺寸
                outlineWidth: 0,
                // 应用于图像的统一比例。比例大于会1.0放大标签,而比例小于会1.0缩小标签。
                scale: 1.0,
                scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.5),
                // 设置样式:FILL:填写标签的文本,但不要勾勒轮廓;OUTLINE:概述标签的文本,但不要填写;FILL_AND_OUTLINE:填写并概述标签文本。
                style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                // 相对于坐标的水平位置
                verticalOrigin: Cesium.VerticalOrigin.CENTER,
                // 相对于坐标的水平位置
                horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                // 该属性指定标签在屏幕空间中距此标签原点的像素偏移量
                pixelOffset: new Cesium.Cartesian2(0, 0),
                // pixelOffset: new Cesium.Cartesian2(0, 0),
                // 显示在距相机的距离处的属性,多少区间内是可以显示的
                // distanceDisplayCondition: distanceDisplayCondition,
                // : new Cesium.DistanceDisplayCondition(0, 50000),
                heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
                disableDepthTestDistance: Number.POSITIVE_INFINITY,
                // 是否显示
                show: true,
            }
            };
            entity.polyline = {
                positions: positions,
                width: 2,
                material: new Cesium.ColorMaterialProperty(
                    Cesium.Color.YELLOW
                    // Cesium.Color.fromRandom({
                    //     alpha: 0.5,
                    //     minimumAlpha: 0.2,
                    //     maximumAlpha: 0.9,
                    // })
                ),
                material: new Cesium.ColorMaterialProperty(Cesium.Color.YELLOW),
                clampToGround: true,
                // distanceDisplayCondition: distanceDisplayCondition,
            }
            };
            viewer.entities.add(entity)
        })
            viewer.entities.add(entity);
        });
        return polygonEntity
    })
        return polygonEntity;
    });
}
function createAreaPolygon(polygonEntity, color, height) {
    if (!polygonEntity) return
@@ -140,29 +144,29 @@
}
export function clearAreaPolygon() {
    // 1. 清除通过 viewer.entities 添加的实体
    if (Array.isArray(areaDataSource)) {
        areaDataSource.forEach(dataSource => {
            // 移除数据源中的所有实体
            dataSource.entities.values.forEach(entity => {
                viewer.entities.remove(entity);
            });
            // 移除数据源本身
            viewer.dataSources.remove(dataSource);
        });
        areaDataSource = [];
    }
    // 1. 清除通过 viewer.entities 添加的实体
    if (Array.isArray(areaDataSource)) {
        areaDataSource.forEach(dataSource => {
            // 移除数据源中的所有实体
            dataSource.entities.values.forEach(entity => {
                viewer.entities.remove(entity);
            });
            // 移除数据源本身
            viewer.dataSources.remove(dataSource);
        });
        areaDataSource = [];
    }
    // 2. 清除通过 viewer.scene.primitives 添加的图元
    if (Array.isArray(areaPrimitives)) {
        areaPrimitives.forEach(primitive => {
            viewer.scene.primitives.remove(primitive);
        });
        areaPrimitives = [];
    }
    // 2. 清除通过 viewer.scene.primitives 添加的图元
    if (Array.isArray(areaPrimitives)) {
        areaPrimitives.forEach(primitive => {
            viewer.scene.primitives.remove(primitive);
        });
        areaPrimitives = [];
    }
    // 3. 强制场景重绘
    viewer.scene.requestRender();
    // 3. 强制场景重绘
    viewer.scene.requestRender();
}
export function initAreaLine() {
@@ -236,3 +240,4 @@
    })
    viewer.dataSources.add(dataSourcePromise)
}
src/views/GisView.vue
@@ -564,7 +564,7 @@
          point.name = point.hdName; // 隐患点名称
          point.className = "district";
        } else if (route.path === "/zhjc") {
          point.name = point.deviceForShort; // 设备简称
          point.name = point.deviceName; // 设备简称
          point.className = "device";
        }
@@ -703,8 +703,8 @@
  addCityPolygon();
  initHandler();
  // initView()
  loadAreaPolygon("/json/nsl_area.geojson");
  loadAreaPolygonAll("/json/geometry.json", true);
  // loadAreaPolygon("/json/nsl_area.geojson");
  // loadAreaPolygonAll("/json/geometry.json", true);
  flyToHomeView();
  // 页面加载时初始化
  initAllDistrictCounts();
src/views/mnfz.vue
@@ -34,7 +34,11 @@
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 {
  loadAreaPolygon,
  clearAreaPolygon,
  convertToGeoJson,
} from "@/utils/area";
import colors from "@/assets/img/left/colors3.png";
@@ -43,6 +47,7 @@
import { useSimStore } from "@/store/simulation";
import { storeToRefs } from "pinia";
import { getSafePoint } from "@/api/hpApi";
const simStore = useSimStore();
const { rightRiverShow } = storeToRefs(simStore);
@@ -139,51 +144,41 @@
  dataSources.length = 0;
}
// 避险场所,绿色富文本
function addTetrahedron(visible) {
async 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);
  try {
    const res = await getSafePoint();
    const geoJsonData = convertToGeoJson(res.data);
    // 加载底层面片(多边形)
    const polygonEntities = await loadAreaPolygon(geoJsonData, true);
    emergencyAreaList.push(...polygonEntities);
    // 添加绿色富文本标注
    const textPromises = res.data.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() {
@@ -542,9 +537,9 @@
function playbackFinished(val) {
  isFinish.value = val;
}
function isColorRender(val){
function isColorRender(val) {
  // console.log('这里打印是否显示水位图例的值:',val);
  isShowLegend.value = val
  isShowLegend.value = val;
}
// 定义全局变量存储当前正在闪动的面片
let flashingPolygon = null;
@@ -654,11 +649,11 @@
<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;
  // background: url("@/assets/img/right/rightbg.png");
  color: white;
  position: fixed;
  bottom: 6%;
  right: 20%;
  z-index: 3333;
}
</style>