guonan
2025-06-10 2280e8be717608bb36c3cf921f129db24349396d
src/components/menu/Location.vue
@@ -1,56 +1,94 @@
  <template>
    <div class="district">
      <div class="left-top">
        <span>监测位置</span>
<template>
  <div class="district">
    <div class="left-top">
      <span>监测位置</span>
    </div>
    <div class="left-content district-content">
      <div style="margin-left: 5px; margin-bottom: 5px">
        <span style="color: white">北京市:</span>
        <el-select
          @change="handleChange1"
          v-model="selectValue1"
          placeholder="Select"
          size="mini"
          style="width: 240px"
        >
          <el-option
            v-for="item in BJoptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </div>
      <div style="margin-left: 5px">
        <span style="color: white">重点沟:</span>
        <el-select
          @change="handleChange"
          v-model="selectValue"
          placeholder="Select"
          size="mini"
          style="width: 240px"
        >
          <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </div>
      <div class="left-content district-content">
        <div style="margin-left: 5px">
          <span style="color: white">重点沟:</span>
          <el-select @change="handleChange" v-model="selectValue" placeholder="Select" size="large"
            style="width: 240px">
            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
      <!-- 滚动区域 -->
      <div style="overflow-y: auto; height: 91%; position: relative">
        <!-- 加载遮罩层 -->
        <div v-if="loading" class="loading-overlay">
          <div class="loading-content">
            <el-icon class="loading-icon"><Loading /></el-icon>
            <span class="loading-text">数据加载中...</span>
          </div>
        </div>
        <!-- 滚动区域 -->
        <div style="overflow-y: auto; height: 95%">
          <!-- 加载遮罩层 -->
          <div v-if="loading" class="loading-overlay">
            <div class="spinner"></div>
          </div>
          <div v-else v-for="(item, key) in districtList" :key="key" class="district-item" @click="handleClick(item)">
            <div class="district-item-icon"></div>
            <div class="district-item-text">{{ item.hdName }}</div>
          </div>
        <div
          v-else
          v-for="(item, key) in districtList"
          :key="key"
          class="district-item"
          @click="handleClick(item)"
        >
          <div class="district-item-icon"></div>
          <div class="district-item-text">{{ item.hdName }}</div>
        </div>
      </div>
    </div>
  </template>
  </div>
</template>
<script setup>
import { ref, onMounted, watch, onBeforeUnmount } from "vue";
import { createPoint, removeEntities } from "@/utils/map";
import { createPoint,clearAllPoints } from "@/utils/map";
import { useSimStore } from "@/store/simulation";
import { initeWaterPrimitiveView } from "@/utils/water"; //相机flyTo函数,后续options列表中有对应经纬度后弃用
import { useRoute, onBeforeRouteUpdate } from 'vue-router';
import { useRoute, onBeforeRouteUpdate } from "vue-router";
import { Loading } from "@element-plus/icons-vue";
const districtList = ref([]);
const simStore = useSimStore();
onBeforeRouteUpdate((to, from, next) => {
  if (to.path !== '/yhgl') {
    handleCleanup();
  }
  next();
});
const route = useRoute();
onBeforeUnmount(() => {
  if (route.path !== '/yhgl') {
    console.log('zzzzzzzzzzzzzzzzzzzzzzzzzz');
    handleCleanup();
  if (route.path !== "/yhgl") {
    clearAllPoints();
  }
});
const selectValue = ref("孙胡沟");
const selectValue1 = ref("北京市");
const BJoptions = ref([]);
const options = ref([
  {
@@ -75,10 +113,11 @@
  },
]);
const districtList = ref([]);
const loading = ref(true); // 控制加载状态
function handleClick(district) {
  // 此处调用是因为GisView页面会在点击下一乡镇之前把上一个选择的区域的隐患点清除掉(如果刚好选择了孙胡沟,那么下一个点击将会清空孙胡沟的隐患点)
  initializeDevicePoints();
  const entity = viewer.entities.getById(district.hdId);
  if (entity) {
    viewer.flyTo(entity, {
@@ -90,27 +129,27 @@
    });
  }
}
const handleCleanup = async () => {
  await Promise.all(districtList.value.map(item => removeEntities(item.hdId)));
}
const initializeDevicePoints = async () => {
  await Promise.all(districtList.value.map(async (item, index) => {
    // 根据需求可增删
    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);
    // 打印每个设备的名称和设备类型
    // console.log(`设备名称: ${item.id}, 设备类型: ${item.name}`);
  }));
  await Promise.all(
    districtList.value.map(async (item, index) => {
      // 根据需求可增删
      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);
      // 打印每个设备的名称和设备类型
      // console.log(`设备名称: ${item.id}, 设备类型: ${item.name}`);
    })
  );
};
// 根据区域名称过滤数据
const filterDataByArea = async (areaName) => {
  handleCleanup();
  clearAllPoints();
  if (!areaName || !simStore.DangerPoint || simStore.DangerPoint.length === 0) {
    districtList.value = [];
    return;
@@ -119,8 +158,9 @@
    item.position?.includes(areaName)
  );
  if (JSON.stringify(districtList.value) !== JSON.stringify(filteredData)) { // 检查是否真的需要更新
  if (JSON.stringify(districtList.value) !== JSON.stringify(filteredData)) {
    districtList.value = filteredData;
    await initializeDevicePoints();
  }
};
@@ -136,19 +176,22 @@
};
let isInitialized = false;
watch(() => simStore.DangerShowSwitch, async (newValue, oldValue) => {
  console.log('当前状态:', newValue);
// watch(
//   () => simStore.DangerShowSwitch,
//   async (newValue, oldValue) => {
//     console.log("当前状态:", newValue);
  if (newValue) {
    if (!isInitialized) {
      await initializeDevicePoints();
      isInitialized = true;
    }
  } else {
    handleCleanup();
    isInitialized = false; // 或者保持为 true,取决于你的需求
  }
});
//     if (newValue) {
//       if (!isInitialized) {
//         await initializeDevicePoints();
//         isInitialized = true;
//       }
//     } else {
//       clearAllPoints();
//       isInitialized = false;
//     }
//   }
// );
// 监听 simStore.DangerPoint 变化
watch(
  () => simStore.DangerPoint,
@@ -157,7 +200,7 @@
      filterDataByArea(selectValue.value);
      loading.value = false; // 数据加载完成
    } else {
      handleCleanup();
      clearAllPoints();
      districtList.value = [];
      loading.value = true; // 数据未准备就绪
    }
@@ -165,8 +208,8 @@
);
onMounted(() => {
  handleCleanup()
  initeWaterPrimitiveView()
  clearAllPoints();
  // initeWaterPrimitiveView();
  // 默认先检查一遍数据
  if (simStore.DangerPoint && simStore.DangerPoint.length > 0) {
    filterDataByArea("孙胡沟");
@@ -178,35 +221,6 @@
</script>
<style lang="less" scoped>
.loading-overlay {
  position: absolute;
  top: 120px;
  left: 0px;
  right: 0px;
  bottom: 10px;
  background-color: rgba(236, 233, 233, 0.5);
  /* 半透明遮罩 */
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 999;
}
.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #fff;
  border-top: 4px solid transparent;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
.district {
  position: absolute;
  width: 345px;
@@ -225,6 +239,8 @@
.district-content {
  padding: 10px;
  box-sizing: border-box;
  height: calc(100% - 70px);
  position: relative;
}
.district-item-icon {
@@ -242,12 +258,44 @@
  overflow: hidden;
  text-overflow: ellipsis;
}
.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  // background-color: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 100;
  // border-radius: 4px;
}
.loading-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: #fff;
}
.loading-icon {
  font-size: 24px;
  margin-bottom: 8px;
  animation: rotating 2s linear infinite;
}
.loading-text {
  color: white;
  font-size: 14px;
  text-align: center;
  margin-top: 20px;
}
@keyframes rotating {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
/deep/ .el-select__placeholder {