wujingjing
2025-02-07 4c20089472b20319746649decbce3a11f16cb6a0
src/components/chat/chatComponents/summaryCom/components/recordSetTable/map/Map.vue
@@ -1,56 +1,36 @@
<template>
   <div class="h-[60vh] relative">
      <!-- 原始地图容器 -->
      <div v-show="!isFullscreen" ref="containerRef" class="h-full"></div>
      <BasicMap
         ref="normalMapRef"
         v-show="!isFullscreen"
         class="h-full"
         :data="data"
         @markerClick="markerClick"
         @closeInfoWindow="closeInfoWindow"
      />
      <!-- 全屏按钮 -->
      <div class="absolute right-2 top-2 cursor-pointer" @click="toggleFullScreen">
         <el-tooltip content="全屏展开" placement="top">
            <div class="ywifont text-[20px] text-black rounded-lg ywicon-fullscreen"></div>
            <div class="ywifont !text-[20px] text-black rounded-lg ywicon-fullscreen"></div>
         </el-tooltip>
      </div>
      <div ref="infoWindowRef" v-show="infoWindowIsShow">
         <div
            class="bg-white rounded-md text-nowrap flex flex-col w-fit border border-solid border-blue-600 relative z-[1]"
            style="padding: 12px"
         >
            <span
               @click="closeInfoWindow"
               class="guanbi absolute ywifont ywicon-guanbi right-[4px] top-[-2px] font-bold text-[#c3c3c3] cursor-pointer"
            ></span>
            <div class="space-x-4 flex w-full">
               <div class="flex flex-col w-1/2 key-list">
                  <span
                     v-for="(col, index) in colsArray"
                     :key="index"
                     class="flex-items-center justify-start text-gray-600"
                     style="height: 20px"
                     >{{ col.title ?? '' }}</span
                  >
               </div>
               <div class="flex flex-col w-1/2 value-list" v-if="infoWindowMapRow">
                  <span
                     v-for="(col, index) in colsArray"
                     :key="index"
                     class="flex-items-center justify-end text-black"
                     style="height: 20px"
                     >{{ infoWindowMapRow[index] ?? '' }}</span
                  >
               </div>
            </div>
         </div>
      </div>
      <!-- Teleport 全屏地图 -->
      <Teleport to=".layout-parent">
         <Transition name="fullscreen">
            <div v-if="isFullscreen" class="absolute inset-0 z-50 w-full h-full">
               <div ref="fullscreenContainerRef" class="w-full h-full"></div>
            <div v-if="isRenderFullscreen" v-show="isFullscreen" class="absolute inset-0 z-50 w-full h-full">
               <BasicMap
                  ref="fullScreenMapRef"
                  :config="fullScreenMapConfig"
                  class="h-full"
                  :data="data"
                  @markerClick="markerClick"
                  @closeInfoWindow="closeInfoWindow"
               />
               <div class="absolute right-2 top-2 cursor-pointer" @click="toggleFullScreen">
                  <el-tooltip content="退出全屏(Esc)" placement="top">
                     <div class="ywifont text-[20px] text-black rounded-lg ywicon-tuichuquanping"></div>
                     <div class="ywifont !text-[20px] text-black rounded-lg ywicon-tuichuquanping"></div>
                  </el-tooltip>
               </div>
               <div class="absolute bottom-0 w-full">
@@ -63,6 +43,7 @@
                     :tableHeight="240"
                  />
               </div>
               <SmallChat class="absolute bottom-0 right-0" :olMap="fullScreenOlMap" />
            </div>
         </Transition>
      </Teleport>
@@ -72,49 +53,26 @@
<script setup lang="ts">
import 'ol/ol.css';
import { computed, nextTick, onDeactivated, onMounted, onUnmounted, ref } from 'vue';
import equipSelectPic from './img/equip-select.svg';
import equipPic from './img/equip.svg';
import { OLMap } from '/@/model/map/OLMap';
import type Overlay from 'ol/Overlay';
import EquipCurve from '../components/EquipCurve.vue';
import { GaoDeMap } from '/@/model/map/GaoDeMap';
let gaoDeMap = new GaoDeMap();
const containerRef = ref<HTMLDivElement>(null);
const fullscreenContainerRef = ref<HTMLDivElement>(null);
import BasicMap from './BasicMap.vue';
import SmallChat from '/@/components/chat/smallChat/index.vue';
import { GaoDeSourceType } from '/@/model/map/OLMap';
import { useCompRef } from '/@/utils/types';
const isRenderFullscreen = ref(false);
const isFullscreen = ref(false);
const props = defineProps(['data']);
const normalMapRef = useCompRef(BasicMap);
const fullScreenMapRef = useCompRef(BasicMap);
const fullScreenOlMap = computed(() => fullScreenMapRef.value?.olMap);
const emit = defineEmits(['equipClick', 'closeInfoWindow']);
const colsArray = computed(() => {
   return props.data.cols ?? [];
});
const infoWindowRef = ref<HTMLDivElement>(null);
const infoWindowIsShow = ref(false);
const infoWindowMapRow = ref(null);
let olMap: OLMap;
let infoWindowOverlay: Overlay;
let lastOverlay: Overlay;
const setMarkerIcon = (overlay, icon: string) => {
   if (!overlay) return;
   const ele = overlay.getElement() as HTMLImageElement;
   if (!ele) return;
   ele.src = icon;
};
const showInfoWindow = (overlay, row, position) => {
   lastOverlay && setMarkerIcon(lastOverlay, equipPic);
const markerClick = (row) => {
   if (isFullscreen.value) {
      showCurve(row);
   } else {
      emit('equipClick', row);
   }
   infoWindowIsShow.value = true;
   infoWindowOverlay.setPosition(position);
   infoWindowMapRow.value = row;
   setMarkerIcon(overlay, equipSelectPic);
   lastOverlay = overlay;
};
const closeInfoWindow = () => {
   if (isFullscreen.value) {
@@ -122,69 +80,32 @@
   } else {
      emit('closeInfoWindow');
   }
   infoWindowIsShow.value = false;
   infoWindowMapRow.value = null;
   setMarkerIcon(lastOverlay, equipPic);
};
const addMarkerLayer = () => {
   const map = props.data.map;
   if (map.pos_x == null && map.pos_y == null) return;
   const dataList = (props.data?.values ?? []).map((item) => {
      const x = item[map.pos_x];
      const y = item[map.pos_y];
      return {
         position: [x, y],
         // textColor: item.color,
         extData: item,
         title: item.title,
      };
   });
   olMap.addMarkerLayer(dataList, {
      markerOpt: {
         icon: {
            url: equipPic,
            size: 30,
            selectUrl: equipSelectPic,
         },
         click(e, label, item, position) {
            const extData = item.extData;
            showInfoWindow(label, extData, position);
         },
      },
      layerOpt: {
         // allowCollision:false
      },
   });
};
const fullScreenMapConfig = ref({
   sourceType: GaoDeSourceType.Vector,
   markerIsVisible: true,
});
// 切换全屏
const toggleFullScreen = async () => {
   isFullscreen.value = !isFullscreen.value;
   // 等待 DOM 更新完成
   await nextTick();
   // 重新初始化地图
   if (isFullscreen.value) {
      const config = normalMapRef.value.olMap.getConfig();
      if (!isRenderFullscreen.value) {
         fullScreenMapConfig.value = config;
         isRenderFullscreen.value = true;
      } else {
         // fullScreenMapRef.value.olMap.setConfig(config);
      }
      closeInfoWindow();
      await initMap(fullscreenContainerRef.value);
   } else {
      // await initMap(containerRef.value);
      const config = fullScreenMapRef.value.olMap.getConfig();
      // normalMapRef.value.olMap.setConfig(config);
   }
};
// 初始化地图
const initMap = async (container: HTMLDivElement) => {
   olMap = new OLMap({
      container,
   });
   addMarkerLayer();
   infoWindowOverlay = olMap.createEleOverlay(infoWindowRef.value);
   olMap.map.addOverlay(infoWindowOverlay);
};
//#region ====================== 设备曲线 ======================
const chartDlgIsShow = ref(false);
const equipCurveMapRow = ref(null);
@@ -207,9 +128,9 @@
};
onMounted(async () => {
   initMap(containerRef.value);
   // 添加 ESC 键监听
   document.addEventListener('keydown', handleEscKey);
   // toggleFullScreen();
});
onDeactivated(async () => {