guonan
6 天以前 a57caa72a54efe9de3fe26a6c36d3e8038267377
src/components/tools/Detail.vue
@@ -1,233 +1,273 @@
<template>
   <div class="detail" ref="detailRef">
      <div class="detail-top">{{ 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">
            <div class="detail-name">{{ item.name }}</div>
            <div class="detail-value" :title="item.value">{{ item.value || "--" }}</div>
         </div>
      </div>
   </div>
  <div class="detail" ref="detailRef">
    <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">
        <div class="detail-name">{{ item.name }}</div>
        <div class="detail-value" :title="item.value">
          {{ item.value || "--" }}
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
   import { ref, onMounted, nextTick, onUnmounted } from "vue";
   import { showDeviceDetail, deviceDetail, className, dialogPositon } from "@/store"
import { ref, onMounted, nextTick, onUnmounted } from "vue";
import {
  showDeviceDetail,
  deviceDetail,
  className,
  dialogPositon,
} from "@/store";
   // props: {
   //    deviceDetail: {
   //       type: Object,
   //       default: {
   //          deviceCode: "1101161102180100031040",
   //          deviceId: "1554360448383913986",
   //          deviceName: "怀柔区琉璃庙镇孙胡沟村于家西沟次声仪1040",
   //          dictDeviceType: "1437295832",
   //          latitude: 40.563822,
   //          longitude: 116.592648,
   //          type: "次生仪",
   //          name: "怀柔区琉璃庙镇孙胡沟村于家西沟次声仪1040",
   //          id: "1554360448383913986",
   //       },
   //    },
   // },
   const detailList = ref([])
   const detailTitle = ref("设备详情")
   function closeMsg() {
      showDeviceDetail.value = false
      coloseDialog()
   }
   function handlDeviceDetail() {
      const name = deviceDetail.value.name.split("孙胡沟")[1] || deviceDetail.value.deviceName
      detailTitle.value = name
      detailList.value = [
         {
            name: "设备编号",
            value: deviceDetail.value.deviceCode || Math.floor(Math.random() * 100000),
         },
         {
            name: "设备类型",
            value: deviceDetail.value.type || "",
         },
         {
            name: "安装时间",
            value: "2024-01-15 12:55:18",
         },
         {
            name: "更新时间",
            value: "2025-02-15 8:15:28",
         },
         {
            name: "设备位置",
            value: deviceDetail.value.name.split("孙胡沟")[0] || cityData.listData[0],
         },
      ]
   }
   function handleDistrictDetail() {
      const name = deviceDetail.value.name || deviceDetail.value.district
      detailTitle.value = name
      detailList.value = [
         {
            name: "隐患类型",
            value: deviceDetail.value.type || "泥石流",
         },
         // {
         //    name: "威胁人数",
         //    value: deviceDetail.value.type || "",
         // },
         {
            name: "主管科长",
            value: "张浩",
         },
         {
            name: "主管镇长",
            value: "刘佳斌",
         },
         {
            name: "群测群防",
            value: deviceDetail.value.groupMonitor,
         },
         {
            name: "隐患位置",
            value: deviceDetail.value.district,
         },
         {
            name: "预防方案",
            value: deviceDetail.value.preventionPlan,
         },
      ]
   }
   function loadClassNameDetail() {
      if (className.value == "device") {
         handlDeviceDetail()
      } else if (className.value == "district") {
         handleDistrictDetail()
      }
   }
   const detailRef = ref(null)
   //展示属性框
   function calcDialogPostion() {
    const position = dialogPositon.value;
    if (!position) {
        console.error("dialogPositon is null or invalid");
        return;
    }
import { hdByDevice } from "@/api/hpApi";
    const bubble = detailRef.value;
    if (!bubble) {
        console.error("detailRef is null, DOM not ready");
        return;
    }
    let winpos = window.viewer.scene.cartesianToCanvasCoordinates(position);
    if (!winpos || isNaN(winpos.x) || isNaN(winpos.y)) {
        console.error("Invalid canvas coordinates:", winpos);
        return;
    }
    let poph = bubble.offsetHeight;
    bubble.style.left = winpos.x - 200 + "px";
    let top = winpos.y - poph - 50;
    bubble.style.top = top + "px";
const detailList = ref([]);
const detailTitle = ref("设备详情");
const name = ref("");
function closeMsg() {
  showDeviceDetail.value = false;
  coloseDialog();
}
// 监测设备具体信息
async function handlDeviceDetail() {
  const hdInfo = ref();
   //关闭属性框
   const coloseDialog = () => {
      window.viewer.scene.postRender.removeEventListener(calcDialogPostion)
   }
   onMounted(() => {
    loadClassNameDetail();
    nextTick(() => {
        window.viewer.scene.postRender.addEventListener(calcDialogPostion);
    });
  try {
    const res = await hdByDevice(deviceDetail.value.hdUnifiedCode);
    hdInfo.value = res.data;
    detailList.value = [
      {
        name: "设备编号",
        value: deviceDetail.value.deviceCode || Math.floor(Math.random() * 100000),
      },
      {
        name: "设备类型",
        value: deviceDetail.value.type || deviceDetail.value.deviceTypeName,
      },
      {
        name: "关联隐患点",
        value: deviceDetail.value.hdName,
      },
      {
        name: "群测群防员",
        value: hdInfo.value?.groupTestGroupDefenseUserName || "暂无信息",
      },
      {
        name: "群测群防员电话",
        value: hdInfo.value?.groupTestGroupDefenseMobile || "暂无信息",
      },
    ];
    detailTitle.value = deviceDetail.value.deviceForShort;
  } catch (err) {
    console.error("获取 hdInfo 失败", err);
  }
}
// 隐患点具体信息
function handleDistrictDetail() {
  const name = deviceDetail.value.hdName;
  detailTitle.value = name;
  detailList.value = [
    // {}
    {
      name: "灾害类型",
      value: deviceDetail.value.disasterType || "泥石流",
    },
    {
      name: "威胁对象",
      value: deviceDetail.value.threatObj || "居民点",
    },
    {
      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: "隐患位置",
      value: deviceDetail.value.position,
    },
    {
      name: "预防方案",
      value: deviceDetail.value.preventionSuggestion,
    },
  ];
}
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);
//展示属性框
function calcDialogPostion() {
  const position = dialogPositon.value;
  if (!position) {
    console.error("dialogPositon is null or invalid");
    return;
  }
  const bubble = detailRef.value;
  if (!bubble) {
    console.error("detailRef is null, DOM not ready");
    return;
  }
  let winpos = window.viewer.scene.cartesianToCanvasCoordinates(position);
  if (!winpos || isNaN(winpos.x) || isNaN(winpos.y)) {
    console.error("Invalid canvas coordinates:", winpos);
    return;
  }
  let poph = bubble.offsetHeight;
  bubble.style.left = winpos.x - 200 + "px";
  let top = winpos.y - poph - 50;
  bubble.style.top = top + "px";
}
//关闭属性框
const coloseDialog = () => {
  window.viewer.scene.postRender.removeEventListener(calcDialogPostion);
};
onMounted(() => {
  loadClassNameDetail();
  nextTick(() => {
    window.viewer.scene.postRender.addEventListener(calcDialogPostion);
  });
});
onUnmounted(() => {
   // 解决dom中offHeight报错
    window.viewer.scene.postRender.removeEventListener(calcDialogPostion);
  // 解决dom中offHeight报错
  window.viewer.scene.postRender.removeEventListener(calcDialogPostion);
});
</script>
<style lang="less" scoped>
   .detail {
      background: url("@/assets/img/tools/messagebg.png");
      background-size: 100% 100%;
      width: 24.4375rem;
      height: 24.5rem;
      position: absolute;
      top: 30%;
      right: 30%;
   }
.detail {
  background: url("@/assets/img/tools/messagebg.png");
  background-size: 100% 100%;
  width: 24.4375rem;
  height: 24.5rem;
  position: absolute;
  top: 30%;
  right: 30%;
}
   .detail-top {
      position: absolute;
      top: 0.3125rem;
      left: 1.25rem;
      font-weight: 700;
      font-size: 1.125rem;
      font-weight: 700;
      color: #fff;
      line-height: 2.5rem;
      width: 16.875rem;
      cursor: pointer;
   }
.detail-top {
  position: absolute;
  top: 0.3125rem;
  left: 1.25rem;
  font-weight: 700;
  font-size: 1.125rem;
  color: #fff;
  line-height: 2.5rem;
  width: 16.875rem; /* 容器宽度固定或限制 */
  cursor: pointer;
   .detail-close {
      position: absolute;
      right: 0.1875rem;
      top: 0rem;
      width: 1.25rem;
      height: 1.25rem;
      text-align: center;
      line-height: 1.25rem;
      text-align: center;
  /* 超出隐藏 + 省略号 */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
      font-weight: 700;
      font-size: 1.125rem;
      font-weight: 700;
      color: #fff;
      cursor: pointer;
   }
  /* 可选:添加过渡动画 */
  transition: all 0.3s ease;
}
   .detail-context {
      position: absolute;
      top: 3.8rem;
      left: 1.25rem;
      width: 21.875rem;
   }
.detail-close {
  position: absolute;
  right: 0.1875rem;
  top: 0rem;
  width: 1.25rem;
  height: 1.25rem;
  text-align: center;
  line-height: 1.25rem;
  text-align: center;
   .detail-item {
      display: flex;
      height: 1.4375rem;
      margin-top: 0.9375rem;
      margin-left: 0.625rem;
   }
   .detail-name {
      width: 100px;
      font-weight: 700;
      color: #94e0c4;
      &::after {
         content: ":";
      }
   }
  font-weight: 700;
  font-size: 1.125rem;
  font-weight: 700;
  color: #fff;
  cursor: pointer;
}
   .detail-value {
      color: #e1eee9;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      width: 250px;
   }
.detail-context {
  position: absolute;
  top: 3.8rem;
  left: 1.25rem;
  width: 21.875rem;
  overflow-y: auto;
  height: 63%;
}
   .detail-btn {
      background: url("@/assets/img/tools/messagebtn.png") no-repeat;
      position: absolute;
      bottom: 3.75rem;
      right: 3.75rem;
      width: 6.5625rem;
      height: 1.625rem;
      text-align: center;
      color: #fff;
      cursor: pointer;
   }
.detail-item {
  display: flex;
  height: 1.4375rem;
  margin-top: 0.9375rem;
  margin-left: 0.625rem;
}
.detail-name {
  display: inline-block; /* 关键 */
  max-width: 100%; /* 防止溢出 */
  font-weight: 700;
  color: #94e0c4;
  white-space: nowrap; /* 可选:防止文字换行 */
  &::after {
    content: ":";
  }
}
.detail-value {
  color: #e1eee9;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 250px;
}
.detail-btn {
  background: url("@/assets/img/tools/messagebtn.png") no-repeat;
  position: absolute;
  bottom: 3.75rem;
  right: 3.75rem;
  width: 6.5625rem;
  height: 1.625rem;
  text-align: center;
  color: #fff;
  cursor: pointer;
}
</style>