// import { Session } from '@zebras/qgc-share/service/Session' import domtoimage from 'dom-to-image'; import { offset2, drawDotImg2, drawDotImg1, offset1, drawDotImg3, offset3, drawDotImg5, offset5 } from '@/utils/GisUrlList'; import { LAYOUT_GRID_SKELETONS } from '@/views/dianZhanZhuanTi/layoutGridSkeletons'; import { useUiStore } from '@/store/modules/ui'; declare global { interface Window { __lyConfigs?: { theme?: string; [key: string]: any; // 根据实际配置结构补充具体字段,或使用索引签名兼容其他属性 }; __mapMode?: string; // 建议同时声明代码中用到的其他全局变量 } } /** * 根据镜头高度获取地图级别 * @param {Number} height */ const A = 40487.57; const B = 0.00007096758; const C = 91610.74; const D = -40467.74; /** * 图例数据转对象 * @param data 图例数据 * @returns 以nameEn为下标的图例数据 */ export const legendData2Obj = (data: any[]) => { const _tempData: any = {}; const f = (_data: any[]) => { _data.forEach(item => { // childrenList有值表示这是一个分组 if (item?.childrenList && item.childrenList?.length > 0) { f(item.childrenList); } else { _tempData[item.nameEn] = item; } }); }; f(data); return _tempData; }; /** * 添加标签偏移量等属性到item中 * @param item - 待添加属性的item * @param index - item的索引 * @param labelType - 标签类型 */ export const appendOffsetPropties = (item: any, index: any, labelType = 2) => { let drawDotImg = null; let offset = null; if (labelType == 2) { drawDotImg = drawDotImg1; offset = offset1; addItemProperty(item, index, drawDotImg, offset); } else if (labelType == 3) { drawDotImg = drawDotImg2; offset = offset2; addItemProperty(item, index, drawDotImg, offset); } else if (labelType == 4) { drawDotImg = drawDotImg3; offset = offset3; addItemProperty2(item, index, drawDotImg, offset); } else if (labelType == 5) { drawDotImg = drawDotImg5; offset = offset5; addItemProperty2(item, index, drawDotImg, offset); } }; const addItemProperty2 = ( item: any, index: any, drawDotImg: any, offset: any ) => { if (!drawDotImg || !offset) return; item.icon_image = index % 2 !== 0 ? drawDotImg[item.anchoPointState]?.left || '' : drawDotImg[item.anchoPointState]?.right || ''; item.text_anchor = index % 2 !== 0 ? 'right' : 'left'; item.text_offset = offset[item.icon_image]?.text_offset ?? [-10, -1.8]; item.text_offset2 = offset[item.icon_image]?.text_offset2 ?? [-10, -1.8]; item.icon_offset = [ offset[item.icon_image]?.icon_x ?? -200, offset[item.icon_image]?.icon_y ?? -50 ]; item.icon_offset2 = offset[item.icon_image]?.icon_offset2 ?? [-200, -50]; item.billboard_offset = [ offset[item.icon_image]?.billboard_x ?? -80, offset[item.icon_image]?.billboard_y ?? -15 ]; item.label_offset = offset[item.icon_image]?.labelOffset ?? [100, 41]; }; export const addItemProperty = ( item: any, index: any, drawDotImg: any, offset: any ) => { if (!drawDotImg || !offset) return; item.icon_image = index % 2 !== 0 ? drawDotImg[item.anchoPointState]?.left || '' : drawDotImg[item.anchoPointState]?.right || ''; item.text_offset = [ offset[item.icon_image]?.text_x ?? -10, offset[item.icon_image]?.text_y ?? -1.8 ]; item.icon_offset = [ offset[item.icon_image]?.icon_x ?? -200, offset[item.icon_image]?.icon_y ?? -50 ]; item.billboard_offset = [ offset[item.icon_image]?.billboard_x ?? -80, offset[item.icon_image]?.billboard_y ?? -15 ]; item.label_offset = offset[item.icon_image]?.labelOffset ?? [100, 41]; }; /** * 设置popName属性 * @param item - 待设置popName的item */ export const setPopName = (item: any) => { if (item.sttp === 'ENG') { item.popName = item.ennm || item.titleName; } else if (item.sttp === 'ylfb') { if (item?.ftp?.length > 20) { item.popName = item.ftp.slice(0, 20) + '...'; } else { item.popName = item?.ftp; } } else if (item.sttp === 'WE_FISH') { item.popName = item.fishList?.[0]?.fishName + `(${item.fishList?.[0]?.ptypeName})`; item.popName1 = item.total + '尾'; } else { item.popName = item.stnm || item.titleName; } }; /** * 获取图例配置中选中项的key * @param data - 图例配置数据 * @returns 选中项的key数组 */ export const getCheckedLayerConfigs = (data: any[]): any[] => { const rs: any[] = []; const f = (arr: any[] = []) => { let count = 0; arr.forEach((item: any) => { if (item?.children && item.children.length > 0) { const childrenCount = f(item.children); if (childrenCount) { rs.push(item.key); } } else if (item.checked) { count++; rs.push(item.key); // 对应图例的layerCode } }); return count; }; f(data); return rs; }; // type mapType = "" | "pointMap" | "gisLayer" /** * 将图层配置数据转换为一维数组 * @param data - 图层配置数据 * @returns 一维数组 */ export const layerConfig2Flat = (data: any): any[] => { const rs: any[] = []; const f = (arr: any[] = []) => { arr.forEach((item: any) => { const { type } = item; if (type) { if (type == 'GISMap' || type == 'geojson') { if (item?.children && item.children.length > 0) { f(item.children); } else { rs.push(item); } } else if (type == 'pointMap') { if ( item.url || item.title === '国家水文站' || item.title === '自建水文站' ) { rs.push(item); } else if (item.children.length > 0) { f(item.children); } } } else if (item.children.length > 0) { f(item.children); } }); }; f(data); return rs; }; /** * 替换图层配置中的 URL * @param layerConfigsArr - 图层配置数组 * @param urlList - URL 配置列表 * @returns 更新后的图层配置数组 */ export const replaceUrl = (layerConfigsArr: any[], urlList: any[]): any[] => { const bDict: Record = {}; // 构建 URL 映射字典 for (let i = 0; i < urlList.length; i++) { const key = urlList[i].url; const title = urlList[i].title; const keyType = urlList[i].keyType; if (!bDict[key]) bDict[key] = []; if (!bDict[title]) bDict[title] = []; if (!bDict[keyType]) bDict[keyType] = []; bDict[key].push(urlList[i]); bDict[title].push(urlList[i]); if (bDict[keyType]) { bDict[keyType].push(urlList[i]); } } // 替换图层配置中的 URL for (let i = 0; i < layerConfigsArr.length; i++) { const obj = layerConfigsArr[i]; const key = obj.url; const title = obj.title; const keyType = obj.key; const bObjList = bDict[keyType] || bDict[title] || bDict[key]; if (bObjList && bObjList.length > 0) { const bObj = bObjList[0]; obj.url = bObj.url; obj.urlThd = bObj.url; obj.params = bObj.params; obj.orders = bObj.orders; } else { obj.url = ''; } } return layerConfigsArr; }; /** * 获取基础图层配置 * @param config - 接口获取的配置数据 * @returns 基础图层配置 */ export const getMapConfig = (config: any) => { const r = { ...config }; const baseUrlObj = import.meta.env.VITE_APP_MAP_URL; if (baseUrlObj) { r.url = baseUrlObj + r.url; // 'http://localhost:8088' r.url_3d = baseUrlObj + r.url_3d; // r.url = baseUrlObj.url + r.url //baseUrlObj.url // r.url_3d = baseUrlObj.url + r.url_3d if (r.geojson_url) { r.geojson_url = baseUrlObj + r.geojson_url; } } return r; }; /** * 重置地图元素位置 */ export const resetMapElPos = () => { const legend = document.querySelector('#qgc-legendtl') as HTMLElement; // 图例 // const filter = document.querySelector('#map-filter-container') as HTMLElement // 全局表单 const controller = document.querySelector('#map-controller') as HTMLElement; // 地图工具栏 const baselayer = document.querySelector('#map-baselayer') as HTMLElement; // 底图模式切换 if (legend) { legend.style.left = '0'; legend.style.bottom = '0'; } if (controller) { controller.style.right = '480px'; controller.style.bottom = '114px'; } if (baselayer) { baselayer.style.right = '480px'; baselayer.style.bottom = '20px'; } }; /** * 根据位置获取布局数据列表 * @param data - 布局数据 * @param position - 位置 * @returns 布局数据列表 */ const getListByPosition = (data: any, position: string) => data?.data?.filter((el: any) => el.position === position && el.code); /** * 设置地图组件位置 * @param layoutType - 布局类型 * @param data - 布局数据({ type, data: BclDataItem[] }) * @param offset - 面板宽度 + padding + gap,默认 460(440px + 10px + 10px) * @param bottomRowHeight - 底部行高度(如 '200px'),无底部模块时不传 */ export const setMapLegendPos = ( layoutType: string, data: any, offset = 460, bottomRowHeight?: string ) => { const menuStateString = localStorage.getItem('menuState'); const menuState = menuStateString !== null ? JSON.parse(menuStateString) : true; const _theme = localStorage.getItem('ly-theme') || window.__lyConfigs?.theme; const legend = document.querySelector('#qgc-legendtl') as HTMLElement; const filter = document.querySelector('#map-filter-container') as HTMLElement; const compassControl = document.querySelector('#map-compassControl') as HTMLElement; const monitor = document.querySelector('#map-monitor') as HTMLElement; const leftList = getListByPosition(data, 'left'); const rightList = getListByPosition(data, 'right'); const bottomList = getListByPosition(data, 'bottom'); const hasLeft = leftList?.length > 0; const hasRight = rightList?.length > 0; const hasBottom = bottomList?.length > 0; const w = `${offset}px`; const l = `${_theme === 'ly-8' ? (menuState ? 643 : 510) : offset}px`; let b = `0px`; if (_theme === 'ly-8') { b = window.__mapMode === '3D' ? '200px' : `${menuState ? 200 : 50}px`; } // 底部偏移 // px 值:直接 + padding(10px) // fr 值:按占比算,如 3 行各 1fr = calc((100% - 40px) / 3 + 10px) let bottomOffset = '12px'; if (hasBottom && bottomRowHeight) { const pxMatch = bottomRowHeight.match(/^(\d+)px$/); if (pxMatch) { bottomOffset = `${parseInt(pxMatch[1]) + 10}px`; } else if (bottomRowHeight.endsWith('fr')) { const rows = (LAYOUT_GRID_SKELETONS[layoutType]?.gridTemplateRows || '').split(' ').filter(Boolean); const n = rows.length; // 总行数 const gaps = (n - 1) * 10; // 行间距 bottomOffset = `calc((100% - 20px - ${gaps}px) / ${n} + 10px)`; } } if (legend) { legend.style.left = hasLeft ? `calc(${l} - 10px)` : b; legend.style.bottom = bottomOffset; } if (filter) { filter.style.left = hasLeft ? l : b; } if (compassControl) { compassControl.style.left = hasLeft ? l : b; } if (monitor) { monitor.style.right = hasRight ? w : '0'; } // 地图控制器/底图切换器:通过 store 发布位置覆盖,组件内联样式优先读取, // 避免 JS 直写 el.style 与组件自身 :style 绑定互相覆盖(刷新后重叠问题)。 const uiStore = useUiStore(); if (hasBottom) { // 有底部模块:有右模块时整体左移避让;两者同底(bottomOffset) uiStore.setMapControlsPosition({ controllerRight: hasRight ? w : null, controllerBottom: bottomOffset, baselayerRight: hasRight ? `calc(${w} + 60px)` : null, baselayerBottom: bottomOffset }); } else { // 无底部模块:完全回退组件自身默认样式(与非电站专题页面一致) uiStore.setMapControlsPosition({ controllerRight: null, controllerBottom: null, baselayerRight: null, baselayerBottom: null }); } }; export const altitudeToZoom = (height: number) => { const lv = Math.round(D + (A - D) / (1 + Math.pow(Number(height) / C, B))) + 1; return lv > -1 ? lv : 0; }; /** * 根据地图级别获取镜头高度 * @param {Number} zoom */ export const zoomToAltitude = (zoom: number) => { return Math.round(C * Math.pow((A - D) / (zoom - D) - 1, 1 / B)); }; export const mapOutPut = (imageUrl: string) => { const canvas = document.createElement('canvas'); const downloadElement = document.createElement('a'); const mapElem = document.getElementById('mapContainer'); if (mapElem == null) { return; } const context = canvas.getContext('2d')!; canvas.width = mapElem.offsetWidth; canvas.height = mapElem.offsetHeight; const image = new Image(); image.src = imageUrl; image.onload = () => { context.drawImage(image, 0, 0); const elem: any = document.getElementById('qgc-legendtl'); const l = elem?.style?.left === '' ? 0 : parseInt(elem?.style?.left); if (elem) { domtoimage .toPng(elem, { quality: 1.0, width: elem.offsetWidth + (l + 24), height: mapElem.offsetHeight - 20 }) .then((legendUrl: string) => { const image = new Image(); image.src = legendUrl; image.width = elem.offsetWidth; image.onload = () => { context.drawImage(image, 0, 0); downloadElement.href = canvas.toDataURL('image/png'); downloadElement.download = '地图截图'; downloadElement.click(); }; }) .catch(() => {}); } else { downloadElement.href = canvas.toDataURL('image/png'); downloadElement.download = 'download'; downloadElement.click(); } }; };