| | |
| | | <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"> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { onMounted, ref, nextTick, onDeactivated, onUnmounted } from 'vue'; |
| | | |
| | | import equipPic from './img/equip.svg'; |
| | | 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 { GaoDePosition, LabelMarkerData } from '/@/model/map/GaoDeMap'; |
| | | import { GaoDeMap } from '/@/model/map/GaoDeMap'; |
| | | 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); |
| | |
| | | const props = defineProps(['data']); |
| | | |
| | | const emit = defineEmits(['equipClick', 'closeInfoWindow']); |
| | | const createInfoWindow = () => { |
| | | // title |
| | | // <div class="title flex-center bg-[#ca0dab] text-white py-0.5 mb-2 w-full over-ellipsis"> |
| | | // 罗汉鱼 |
| | | // </div> |
| | | const dom = `<div class="rounded-md text-nowrap flex flex-col w-fit border border-solid border-blue-600 relative" style="padding: 12px"> |
| | | <span 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"> |
| | | |
| | | </div> |
| | | |
| | | <div class="flex flex-col w-1/2 value-list"> |
| | | |
| | | </div> |
| | | </div> |
| | | </div>`; |
| | | const colsArray = computed(() => { |
| | | return props.data.cols ?? []; |
| | | }); |
| | | |
| | | return dom; |
| | | 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); |
| | | 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) { |
| | | closeChartDlg(); |
| | | } else { |
| | | emit('closeInfoWindow'); |
| | | } |
| | | infoWindowIsShow.value = false; |
| | | infoWindowMapRow.value = null; |
| | | setMarkerIcon(lastOverlay, equipPic); |
| | | }; |
| | | |
| | | const updateInfoWindow = (item) => { |
| | | const cellHeight = '20px'; |
| | | const keyListDom = infoWindow.dom.querySelector('.key-list'); |
| | | const valueListDom = infoWindow.dom.querySelector('.value-list'); |
| | | |
| | | const colsArray = props.data.cols ?? []; |
| | | const keyItemHtml = colsArray |
| | | .map((col) => { |
| | | return `<span class="flex-items-center justify-start text-gray-600" style="height:${cellHeight}">${col.title ?? ''}</span>`; |
| | | }) |
| | | .join(''); |
| | | |
| | | const valueItemHtml = colsArray |
| | | .map((col, index) => { |
| | | return `<span class="flex-items-center justify-end text-black" style="height:${cellHeight}">${item[index] ?? ''}</span>`; |
| | | }) |
| | | .join(''); |
| | | |
| | | keyListDom.innerHTML = keyItemHtml; |
| | | valueListDom.innerHTML = valueItemHtml; |
| | | }; |
| | | let curMarkerLabel: AMap.LabelMarker; |
| | | const addMarkerLayer = () => { |
| | | const map = props.data.map; |
| | | if (map.pos_x == null && map.pos_y == null) return; |
| | |
| | | title: item.title, |
| | | }; |
| | | }); |
| | | gaoDeMap.addMarkerLayer(dataList, { |
| | | olMap.addMarkerLayer(dataList, { |
| | | markerOpt: { |
| | | icon: { |
| | | url: equipPic, |
| | | size: 30, |
| | | selectUrl: equipSelectPic, |
| | | }, |
| | | click(e, label) { |
| | | curMarkerLabel && curMarkerLabel !== label && restoreLabel(); |
| | | curMarkerLabel = label; |
| | | infoWindow.open(gaoDeMap.map, label.getPosition() as any); |
| | | const extData = label.getExtData(); |
| | | if (isFullscreen.value) { |
| | | showCurve(extData); |
| | | } else { |
| | | emit('equipClick', extData); |
| | | } |
| | | label.setRank(999); |
| | | click(e, label, item, position) { |
| | | const extData = item.extData; |
| | | |
| | | updateInfoWindow(extData); |
| | | showInfoWindow(label, extData, position); |
| | | }, |
| | | }, |
| | | layerOpt: { |
| | | // allowCollision:false |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | const bottomBarIsShow = ref(false); |
| | | const chartIsShow = ref(true); |
| | | const toggleShowChart = () => { |
| | | chartIsShow.value = !chartIsShow.value; |
| | | }; |
| | | |
| | | let infoWindow: AMap.InfoWindow; |
| | | const restoreLabel = () => { |
| | | // 关闭恢复图片 |
| | | curMarkerLabel?.setIcon({ |
| | | image: equipPic, |
| | | }); |
| | | curMarkerLabel?.setRank(1); |
| | | }; |
| | | |
| | | // 初始化信息窗口 |
| | | const initInfoWindow = () => { |
| | | infoWindow = new AMap.InfoWindow({ |
| | | content: createInfoWindow(), |
| | | anchor: 'top-left', |
| | | closeWhenClickMap: true, |
| | | }); |
| | | |
| | | (infoWindow as any).on('close', () => { |
| | | restoreLabel(); |
| | | curMarkerLabel = null; |
| | | if (isFullscreen.value) { |
| | | closeChartDlg(); |
| | | } else { |
| | | emit('closeInfoWindow'); |
| | | } |
| | | }); |
| | | |
| | | // 自带关闭去掉,自带关闭监听 close 会多次触发 close 事件 |
| | | const closeBtnDom = infoWindow.dom.querySelector('.amap-info-close'); |
| | | closeBtnDom.remove(); |
| | | const myCloseBtn = infoWindow.dom.querySelector('.guanbi'); |
| | | myCloseBtn.addEventListener('click', () => { |
| | | infoWindow.close(); |
| | | }); |
| | | }; |
| | | |
| | |
| | | await nextTick(); |
| | | // 重新初始化地图 |
| | | if (isFullscreen.value) { |
| | | closeInfoWindow(); |
| | | await initMap(fullscreenContainerRef.value); |
| | | } else { |
| | | // await initMap(containerRef.value); |
| | |
| | | |
| | | // 初始化地图 |
| | | const initMap = async (container: HTMLDivElement) => { |
| | | // 销毁旧实例 |
| | | // gaoDeMap.map?.destroy(); |
| | | gaoDeMap = new GaoDeMap(); |
| | | |
| | | // 初始化新实例 |
| | | await gaoDeMap.init({ |
| | | olMap = new OLMap({ |
| | | container, |
| | | aMapOption: { |
| | | resizeEnable: true, |
| | | }, |
| | | }); |
| | | |
| | | gaoDeMap.applyBasicPlugins(); |
| | | addMarkerLayer(); |
| | | gaoDeMap.map.setFitView(); |
| | | |
| | | // 初始化信息窗口 |
| | | initInfoWindow(); |
| | | infoWindowOverlay = olMap.createEleOverlay(infoWindowRef.value); |
| | | olMap.map.addOverlay(infoWindowOverlay); |
| | | }; |
| | | //#region ====================== 设备曲线 ====================== |
| | | const chartDlgIsShow = ref(false); |
| | |
| | | }; |
| | | |
| | | onMounted(async () => { |
| | | await initMap(containerRef.value); |
| | | initMap(containerRef.value); |
| | | // 添加 ESC 键监听 |
| | | document.addEventListener('keydown', handleEscKey); |
| | | }); |