guonan
2025-07-08 b040d81c856a77f280b38037e78a8b6a8bdb31ab
src/components/menu/Device.vue
@@ -9,7 +9,7 @@
        <el-select
          @change="handleChange1"
          v-model="selectValue1"
          placeholder="Select"
          placeholder="请选择行政区"
          size="mini"
          style="width: 240px"
        >
@@ -26,7 +26,7 @@
        <el-select
          @change="handleChange"
          v-model="selectValue"
          placeholder="Select"
          placeholder="请选择重点沟"
          size="mini"
          style="width: 240px"
        >
@@ -50,6 +50,7 @@
        <el-tree
          v-show="!isLoading"
          :data="deviceTree"
          default-expand-all
          node-key="deviceId"
          :props="treeProps"
          @node-click="handleTreeNodeClick"
@@ -57,13 +58,46 @@
        >
          <template #default="{ node, data }">
            <span v-if="!data.children" class="device-tree-item">
              <span class="device-item-text">{{ node.label }}</span>
              <span class="device-item-text" :title="node.label">{{
                node.label
              }}</span>
            </span>
            <span v-else class="device-tree-category">
              {{ node.label }} ({{ data.children.length }})
            </span>
          </template>
        </el-tree>
        <!-- <el-tree
          v-show="!isLoading"
          :data="deviceTree"
          default-expand-all
          node-key="deviceId"
          :props="treeProps"
          @node-click="handleTreeNodeClick"
          class="device-tree"
        >
          <template #default="{ node, data }">
            <span v-if="!data.children" class="device-tree-item">
              <el-tooltip :content="node.label" placement="top" effect="dark">
                <span class="device-item-text" :title="node.label">{{
                  node.label
                }}</span>
              </el-tooltip>
            </span>
            <span v-else class="device-tree-category">
              <el-tooltip
                :content="`${node.label} (${data.children.length})`"
                placement="top"
                effect="dark"
              >
                <span :title="`${node.label} (${data.children.length})`"
                  >{{ node.label }} ({{ data.children.length }})</span
                >
              </el-tooltip>
            </span>
          </template>
        </el-tree> -->
      </div>
    </div>
  </div>
@@ -72,12 +106,12 @@
<script setup>
import { ref, computed, onMounted, watch, onBeforeUnmount } from "vue";
import { useRoute, onBeforeRouteUpdate } from "vue-router";
import { createPoint, removeEntities } from "@/utils/map";
import { createPoint, clearAllPoints } from "@/utils/map";
import { deviceDictList, getDictName } from "@/constant/dict.js";
import { getDeviceInfo } from "@/api/hpApi";
import { initeWaterPrimitiveView } from "@/utils/water"; //相机flyTo函数,后续options列表中有对应经纬度后弃用
import { useSimStore } from "@/store/simulation";
import { Loading } from "@element-plus/icons-vue";
import { getDeviceInfoByPage } from "@/api/hpApi";
const simStore = useSimStore();
@@ -85,47 +119,51 @@
onMounted(async () => {
  try {
    await getData();
    await loadDeviceList(selectValue.value);
    initeWaterPrimitiveView();
    if (simStore.devices && simStore.devices.length > 0) {
      await loadDeviceList(selectValue.value);
    }
    // initeWaterPrimitiveView();
  } finally {
    isLoading.value = false;
  }
});
onBeforeRouteUpdate((to, from, next) => {
  if (to.path !== "/zhjc") {
    handleCleanup();
  }
  next();
});
const route = useRoute();
onBeforeUnmount(() => {
  if (route.path !== "/zhjc") {
    handleCleanup();
    clearAllPoints();
  }
});
watch(
  () => simStore.DeviceShowSwitch,
  (newValue, oldValue) => {
    if (newValue) {
      initializeDevicePoints();
    } else {
      handleCleanup();
    }
  }
);
const selectValue1 = ref("");
const BJoptions = ref([
  { label: "密云区", value: "110118000000" },
  { label: "房山区", value: "110111000000" },
  { label: "门头沟区", value: "110109000000" },
  { label: "延庆区", value: "110119000000" },
  { label: "怀柔区", value: "110116000000" },
  { label: "昌平区", value: "110114000000" },
  { label: "平谷区", value: "110117000000" },
  { label: "海淀区", value: "110108000000" },
  { label: "石景山区", value: "110107000000" },
  { label: "丰台区", value: "110106000000" },
]);
const selectValue = ref("孙胡沟");
const options = ref([
  { value: "孙胡沟", label: "孙胡沟" },
  { value: "鱼水洞后沟", label: "鱼水洞后沟" },
  { value: "于家西沟", label: "于家西沟" },
  { value: "北河沟", label: "北河沟" },
  { value: "龙泉峪村", label: "龙泉峪村" },
]);
const deviceListAll = ref([]);
const deviceEntities = ref([]);
const handleCleanup = () => {
  deviceListAll.value.forEach((item) => {
    removeEntities(item.deviceId);
  });
};
const initializeDevicePoints = () => {
  const list = [];
  deviceListAll.value.forEach((item, index) => {
    // 根据需求可增删
    item.type = getDictName(deviceDictList, item.dictDeviceType);
@@ -137,26 +175,33 @@
    // console.log(`设备名称: ${item.id}, 设备类型: ${item.name}`);
    createPoint(item);
  });
  deviceEntities.value = list;
};
const allDevices = ref([]);
const getData = async () => {
  const res = await getDeviceInfo();
  allDevices.value = res.data.pageData;
// 单个点渲染
const DevicePoints = async (item) => {
  // 根据需求可增删
  item.type = getDictName(deviceDictList, item.dictDeviceType);
  item.name = item.deviceName;
  // item.name = item.deviceName.split(selectValue.value)[1] || item.deviceName;
  item.id = item.deviceId;
  item.className = "device";
  item.showLabel = true;
  // 打印每个设备的名称和设备类型
  // console.log(`设备名称: ${item.id}, 设备类型: ${item.name}`);
  createPoint(item);
};
// 根据区域名称加载设备列表
const loadDeviceList = async (areaName) => {
  try {
    clearAllPoints();
    isLoading.value = true;
    handleCleanup();
    // const res = await getDeviceInfo();
    // const allDevices = res.data.pageData;
    const devicesInArea = allDevices.value.filter((item) =>
    deviceListAll.value = simStore.devices.filter((item) =>
      item.deviceName?.includes(areaName)
    );
    deviceListAll.value = devicesInArea;
    deviceListAll.length = 0;
    initializeDevicePoints();
    await initializeDevicePoints();
  } catch (error) {
    console.error("加载设备信息失败", error);
  } finally {
@@ -164,30 +209,68 @@
  }
};
// 监听 simStore.devices 变化
watch(
  () => simStore.devices,
  (newVal) => {
    if (newVal && newVal.length > 0) {
      loadDeviceList(selectValue.value);
    } else {
      clearAllPoints();
      deviceListAll.value = [];
    }
  }
);
// 处理区域变化事件
const handleChange = (item) => {
  if (!item) {
    ElMessage("请选择一个区域");
    return;
  }
  selectValue1.value = "";
  selectValue.value = item;
  // 根据新区域名重新加载设备列表
  loadDeviceList(item);
  // console.log(deviceListAll.value);
  initializeDevicePoints();
};
const selectValue1 = ref("北京市");
// 处理区域变化事件
const handleChange1 = async (item) => {
  if (!item) {
    ElMessage("请选择一个区域");
    return;
  }
  selectValue1.value = item;
  selectValue.value = "";
  deviceListAll.value = [];
  let pageNum = 1;
  let hasMore = true;
const BJoptions = ref([]);
  try {
    while (hasMore) {
      const res = await getDeviceInfoByPage(item, pageNum);
const selectValue = ref("孙胡沟");
      // 将新数据追加到列表中
      deviceListAll.value = [...deviceListAll.value, ...res.data.pageData];
const options = ref([
  { value: "孙胡沟", label: "孙胡沟" },
  { value: "鱼水洞后沟", label: "鱼水洞后沟" },
  { value: "于家西沟", label: "于家西沟" },
  { value: "北河沟", label: "北河沟" },
  { value: "龙泉峪村", label: "龙泉峪村" },
]);
      // 判断是否还有下一页
      if (pageNum < res.data.pageCount) {
        pageNum++;
        await new Promise((resolve) => setTimeout(resolve, 300));
      } else {
        hasMore = false;
      }
    }
  } catch (err) {
    console.error("获取监测设备失败", err);
    deviceListAll.value = []; // 可选:清空或保留已加载部分
  } finally {
    // 暂时先关闭加载状态,因为此处为分页请求数据,然后一点一点的渲染,最终会加载完成
    // 如果开启加载状态,最后还是会等所有数据都请求回来才会渲染
    // loading.value = false; // 关闭加载状态
  }
};
const treeProps = {
  label: "deviceName",
@@ -222,7 +305,17 @@
  }));
});
function handleTreeNodeClick(data) {
function handleTreeNodeClick(data, node) {
  if (data.children) {
    return; // 一级节点,不执行点击逻辑
  }
  if (selectValue.value) {
    // 此处调用是因为GisView页面会在点击下一乡镇之前把上一个选择的区域的隐患点清除掉(如果刚好选择了孙胡沟,那么下一个点击将会清空孙胡沟的隐患点)
    initializeDevicePoints();
  } else {
    // 行政区划的点位太多了,只能选中哪个渲染哪个
    DevicePoints(data);
  }
  // 只有设备节点才处理点击事件
  if (!data.children) {
    const entity = viewer.entities.getById(data.deviceId);
@@ -266,8 +359,8 @@
.tree-container {
  position: relative;
  height: calc(100% - 80px);
  margin-top: 10px;
  height: calc(100% - 22px);
  // margin-top: 10px;
  overflow-y: auto;
}
@@ -348,6 +441,7 @@
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: inline-block;
}
:deep(.el-select__placeholder) {