diff --git a/frontend/.env.development b/frontend/.env.development index 5ab3d705..f3d5f666 100644 --- a/frontend/.env.development +++ b/frontend/.env.development @@ -7,12 +7,12 @@ VITE_APP_TITLE = '水电水利建设项目全过程环境管理信息平台' VITE_APP_PORT = 3000 VITE_APP_BASE_API = '/dev-api' # 本地环境 -# VITE_APP_BASE_URL = 'http://localhost:8093' +VITE_APP_BASE_URL = 'http://localhost:8093' # 测试环境 # VITE_APP_BASE_URL = 'http://172.16.21.142:8096' # VITE_APP_BASE_URL = 'http://172.16.21.142:8096' # 汤伟 -VITE_APP_BASE_URL = 'http://10.84.121.21:8093' +# VITE_APP_BASE_URL = 'http://10.84.121.21:8093' # VITE_APP_BASE_URL = 'http://192.168.1.162:8093' # 测试环境线上 @@ -25,4 +25,7 @@ VITE_APP_TEST_ONLINE_URL = 'https://211.99.26.225:12122' VITE_APP_BASE_API_URL = 'http://10.84.121.21:8093' ## 开发环境预览 图片视频地址 VITE_APP_PREVIEW_URL = 'https://211.99.26.225:12125' + +# 地图服务地址 +VITE_APP_MAP_URL = 'https://211.99.26.225:18085' # ?menu=systemManageMenu&page=disposeManage \ No newline at end of file diff --git a/frontend/dist.rar b/frontend/dist.rar deleted file mode 100644 index 22299835..00000000 Binary files a/frontend/dist.rar and /dev/null differ diff --git a/frontend/src/api/auth/index.ts b/frontend/src/api/auth/index.ts index 7fddb581..bb131619 100644 --- a/frontend/src/api/auth/index.ts +++ b/frontend/src/api/auth/index.ts @@ -96,7 +96,7 @@ export function getStationList(params:any): AxiosPromise { * @param phone 手机号 * @param type 验证码类型:1-注册 2-找回密码 */ -export function sendSmsCode(phone: string, type: number = 1): AxiosPromise { +export function sendSmsCode(phone: string, type = 1): AxiosPromise { return request({ url: '/sms/sendCode', method: 'post', @@ -110,7 +110,7 @@ export function sendSmsCode(phone: string, type: number = 1): AxiosPromise * @param code 验证码 * @param type 验证码类型:1-注册 2-找回密码 */ -export function verifySmsCode(phone: string, code: string, type: number = 1): AxiosPromise { +export function verifySmsCode(phone: string, code: string, type = 1): AxiosPromise { return request({ url: '/sms/verifyCode', method: 'post', diff --git a/frontend/src/api/map.ts b/frontend/src/api/map.ts new file mode 100644 index 00000000..36d1d99b --- /dev/null +++ b/frontend/src/api/map.ts @@ -0,0 +1,21 @@ +import request from '@/utils/request'; + +// 获取图例列表 +export function getModuleMapLegendList(params?: { moduleId?: string }) { + const url = params?.moduleId + ? `/api/wmp-sys-server/mapLegend/getModuleMapLegendList?moduleId=${params.moduleId}` + : '/api/wmp-sys-server/mapLegend/getModuleMapLegendList'; + return request({ + url, + method: 'get' + }); +} + +// 获取地图配置列表 +export function getMapList(data: any) { + return request({ + url: '/api/wmp-sys-server/mapmodule/getMapData', + method: 'post', + data + }); +} diff --git a/frontend/src/assets/legend/map-dongwujiuzhuzhanZWeijian.svg b/frontend/src/assets/legend/map-dongwujiuzhuzhanZWeijian.svg new file mode 100644 index 00000000..5b7ae89d --- /dev/null +++ b/frontend/src/assets/legend/map-dongwujiuzhuzhanZWeijian.svg @@ -0,0 +1,23 @@ + + + map-dongwujiuzhuzhanZWeijian + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/assets/legend/map-dwsjhDieliangmenshiZWeijian.svg b/frontend/src/assets/legend/map-dwsjhDieliangmenshiZWeijian.svg new file mode 100644 index 00000000..aba73efb --- /dev/null +++ b/frontend/src/assets/legend/map-dwsjhDieliangmenshiZWeijian.svg @@ -0,0 +1,14 @@ + + + map-dwsjhDieliangmenshiZWeijian + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/assets/legend/map-dwsjhGeshuimuqiangZWeijian.svg b/frontend/src/assets/legend/map-dwsjhGeshuimuqiangZWeijian.svg new file mode 100644 index 00000000..6a8f2e3b --- /dev/null +++ b/frontend/src/assets/legend/map-dwsjhGeshuimuqiangZWeijian.svg @@ -0,0 +1,16 @@ + + + map-dwsjhGeshuimuqiangZWeijian + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/assets/legend/map-dwsjhQianzhidangqiangZWeijian.svg b/frontend/src/assets/legend/map-dwsjhQianzhidangqiangZWeijian.svg new file mode 100644 index 00000000..571275a9 --- /dev/null +++ b/frontend/src/assets/legend/map-dwsjhQianzhidangqiangZWeijian.svg @@ -0,0 +1,16 @@ + + + map-dwsjhQianzhidangqiangZWeijian + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/assets/legend/map-dwsjhQitaZWeijian.svg b/frontend/src/assets/legend/map-dwsjhQitaZWeijian.svg new file mode 100644 index 00000000..38014dd7 --- /dev/null +++ b/frontend/src/assets/legend/map-dwsjhQitaZWeijian.svg @@ -0,0 +1,16 @@ + + + map-dwsjhQitaZWeijian + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/assets/legend/map-dxsdzGaojing0.svg b/frontend/src/assets/legend/map-dxsdzGaojing0.svg new file mode 100644 index 00000000..08efe9fe --- /dev/null +++ b/frontend/src/assets/legend/map-dxsdzGaojing0.svg @@ -0,0 +1,23 @@ + + + map-dxsdzYijian + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/assets/legend/map-dxsdzGaojing1.svg b/frontend/src/assets/legend/map-dxsdzGaojing1.svg new file mode 100644 index 00000000..89ac2b74 --- /dev/null +++ b/frontend/src/assets/legend/map-dxsdzGaojing1.svg @@ -0,0 +1,23 @@ + + + map-dxsdzYijian + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/assets/legend/map-dxsdzGaojing2.svg b/frontend/src/assets/legend/map-dxsdzGaojing2.svg new file mode 100644 index 00000000..f5edd753 --- /dev/null +++ b/frontend/src/assets/legend/map-dxsdzGaojing2.svg @@ -0,0 +1,23 @@ + + + map-dxsdzYijian + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/assets/legend/map-dxsdzGaojing3.svg b/frontend/src/assets/legend/map-dxsdzGaojing3.svg new file mode 100644 index 00000000..ae29523f --- /dev/null +++ b/frontend/src/assets/legend/map-dxsdzGaojing3.svg @@ -0,0 +1,23 @@ + + + map-dxsdzYijian + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/components/BaseLayerSwitcher/index.vue b/frontend/src/components/BaseLayerSwitcher/index.vue index 599ba036..c6497fa7 100644 --- a/frontend/src/components/BaseLayerSwitcher/index.vue +++ b/frontend/src/components/BaseLayerSwitcher/index.vue @@ -20,45 +20,81 @@ diff --git a/frontend/src/components/BasicTable/index.vue b/frontend/src/components/BasicTable/index.vue index 422bfee7..54364f39 100644 --- a/frontend/src/components/BasicTable/index.vue +++ b/frontend/src/components/BasicTable/index.vue @@ -136,7 +136,7 @@ const getList = async (filter?: Record) => { const res = await props.listUrl(params); let finalRecords: any[] = []; - let finalTotal: number = 0; + let finalTotal = 0; if (props.transformData) { const result = props.transformData(res); diff --git a/frontend/src/components/MapModal/setting.config.ts b/frontend/src/components/MapModal/setting.config.ts index 387ab57a..f0009e47 100644 --- a/frontend/src/components/MapModal/setting.config.ts +++ b/frontend/src/components/MapModal/setting.config.ts @@ -1188,7 +1188,7 @@ const WATabs: Array = [ const handleTabs = (modaldata: any) => { console.log('modaldata', modaldata); if (!modaldata?.sttp) return; - let sttp = modaldata?.sttp ? modaldata?.sttp.toUpperCase() : ''; + const sttp = modaldata?.sttp ? modaldata?.sttp.toUpperCase() : ''; console.log('sttp', sttp); switch (sttp) { case 'ENG': diff --git a/frontend/src/components/gis/GisView.vue b/frontend/src/components/gis/GisView.vue index 190a205c..0be10300 100644 --- a/frontend/src/components/gis/GisView.vue +++ b/frontend/src/components/gis/GisView.vue @@ -1,7687 +1,382 @@ @@ -7722,14 +444,13 @@ onUnmounted(() => { border: none !important; margin: 0 !important; padding: 0 !important; - /* 关键:防止瓦片加载时的闪烁或横线 */ image-rendering: -webkit-optimize-contrast; image-rendering: crisp-edges; } /* 确保地图容器背景色与瓦片一致,避免透出底色 */ .leaflet-container { - background-color: #fff; /* 或者你的底图主要颜色,如 #f0f0f0 */ + background-color: #fff; } /* 如果使用 Canvas 模式,确保 Canvas 没有边框 */ @@ -7739,7 +460,7 @@ onUnmounted(() => { .map-popup-container { z-index: 1000; - pointer-events: auto; /* 允许鼠标操作 Popup */ + pointer-events: auto; } .custom-popup { diff --git a/frontend/src/components/gis/gisUtils.ts b/frontend/src/components/gis/gisUtils.ts index ecda92fb..944db0d1 100644 --- a/frontend/src/components/gis/gisUtils.ts +++ b/frontend/src/components/gis/gisUtils.ts @@ -1,23 +1,34 @@ // 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 domtoimage from 'dom-to-image'; +import { + offset2, + drawDotImg2, + drawDotImg1, + offset1, + drawDotImg3, + offset3, + drawDotImg5, + offset5 +} from '@/utils/GisUrlList'; declare global { - interface Window { - __lyConfigs?: { - theme?: string; - [key: string]: any; // 根据实际配置结构补充具体字段,或使用索引签名兼容其他属性 - }; - __mapMode?: string; // 建议同时声明代码中用到的其他全局变量 - } + interface Window { + __lyConfigs?: { + theme?: string; + [key: string]: any; // 根据实际配置结构补充具体字段,或使用索引签名兼容其他属性 + }; + __mapMode?: string; // 建议同时声明代码中用到的其他全局变量 + } } +console.log(import.meta.env.VITE_APP_PREVIEW_URL); + /** * 根据镜头高度获取地图级别 * @param {Number} height */ -const A = 40487.57 -const B = 0.00007096758 -const C = 91610.74 -const D = -40467.74 +const A = 40487.57; +const B = 0.00007096758; +const C = 91610.74; +const D = -40467.74; /** * 图例数据转对象 @@ -25,23 +36,23 @@ const D = -40467.74 * @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 { - if (item.nameEn.includes('_测试')) { - item.nameEn = item.nameEn.split('_测试')[0] - } - _tempData[item.nameEn] = item - } - }) - } - f(data) - return _tempData -} + const _tempData: any = {}; + const f = (_data: any[]) => { + _data.forEach(item => { + // childrenList有值表示这是一个分组 + if (item?.childrenList && item.childrenList?.length > 0) { + f(item.childrenList); + } else { + if (item.nameEn.includes('_测试')) { + item.nameEn = item.nameEn.split('_测试')[0]; + } + _tempData[item.nameEn] = item; + } + }); + }; + f(data); + return _tempData; +}; /** * 添加标签偏移量等属性到item中 @@ -49,69 +60,105 @@ export const legendData2Obj = (data: any[]) => { * @param index - item的索引 * @param labelType - 标签类型 */ -export const appendOffsetPropties = (item: any, index: any, labelType: number = 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) - } -} +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] -} +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] -} +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 + "尾" + 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.stnm || item.titleName; + 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 @@ -119,25 +166,25 @@ export const setPopName = (item: any) => { * @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 -} + 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" @@ -147,77 +194,128 @@ export const getCheckedLayerConfigs = (data: any[]): any[] => { * @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') { - 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) - } - }) + const rs: any[] = []; + const f = (arr: any[] = []) => { + arr.forEach((item: any) => { + const { type } = item; + if (type) { + if (type == 'GISMap') { + 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]); } - f(data) - return rs -} + } + + // 替换图层配置中的 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 = () => { - // const mapBaseUrls = MemoryCache.get('mapBaseUrls') || {} - // const r = { ...config } - // const { urlType } = r - // const baseUrlObj = mapBaseUrls[urlType as string] - // if (baseUrlObj) { - // r.url = baseUrlObj.url + r.url // 'http://localhost:8088' - // r.url_3d = baseUrlObj.url + 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.url + r.geojson_url + `&token=${Session.getToken()?.accessToken}` - // } - // } - // return r -} +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 // 底图模式切换 + 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' - } -} + 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'; + } +}; /** * 根据位置获取布局数据列表 @@ -225,7 +323,8 @@ export const resetMapElPos = () => { * @param position - 位置 * @returns 布局数据列表 */ -const getListByPosition = (data: any, position: string) => data?.data?.filter((el: any) => el.position === position && el.code) +const getListByPosition = (data: any, position: string) => + data?.data?.filter((el: any) => el.position === position && el.code); /** * 设置地图组件位置 @@ -233,143 +332,216 @@ const getListByPosition = (data: any, position: string) => data?.data?.filter((e * @param data - 布局数据 * @param offset - 偏移量 */ -export const setMapLegendPos = (layoutType: string, data: any, offset: number = 456) => { - const menuStateString = localStorage.getItem('menuState'); //处理澜沧江左侧菜单状态 - const menuState = menuStateString !== null ? JSON.parse(menuStateString) : true; - const _theme = localStorage.getItem("ly-theme") || window.__lyConfigs?.theme - const leftEle = document.querySelector('#page-layout-left') as HTMLElement - const rightEle = document.querySelector('#page-layout-right') as HTMLElement - const bottomEle = document.querySelector('#page-layout-bottom') as HTMLElement - 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 controller = document.querySelector('#map-controller') as HTMLElement // 地图工具栏 - const monitor = document.querySelector('#map-monitor') as HTMLElement // 地图工具栏 - const baselayer = document.querySelector('#map-baselayer') as HTMLElement // 底图模式切换 - // const vd = document.querySelector('#vd_operate') as HTMLElement // 底部视频 - const left = ['layout1', 'layout2', 'layout3', 'layout4', 'layout6', 'layout7', 'layout8', 'layout9', 'layout10', 'layout11', 'layout14', 'layout15', 'layout16', 'layout17'] // 左侧布局 - const right = ['layout1', 'layout2', 'layout3', 'layout4', 'layout5', 'layout6', 'layout8', 'layout10', 'layout11', 'layout15', 'layout16', 'layout17'] // 右侧布局 - const bottom1 = ['layout1', 'layout6', 'layout8', 'layout9', 'layout10', 'layout16'] // 三行底部布局 - const bottom2 = ['layout2', 'layout15'] // 四行底部布局 - const w = `${offset}px` - const l = `${_theme === 'ly-8' ? menuState ? 643 : 510 : offset}px` - let b = `0px` - const le = ['layout17', 'layout10'].includes(layoutType) ? 0 : 1 - const leftList = getListByPosition(data, 'left') - const rightList = getListByPosition(data, 'right') - const bottomList = getListByPosition(data, 'bottom') - let bottom = '0' +export const setMapLegendPos = ( + layoutType: string, + data: any, + offset = 456 +) => { + const menuStateString = localStorage.getItem('menuState'); //处理澜沧江左侧菜单状态 + const menuState = + menuStateString !== null ? JSON.parse(menuStateString) : true; + const _theme = localStorage.getItem('ly-theme') || window.__lyConfigs?.theme; + const leftEle = document.querySelector('#page-layout-left') as HTMLElement; + const rightEle = document.querySelector('#page-layout-right') as HTMLElement; + const bottomEle = document.querySelector( + '#page-layout-bottom' + ) as HTMLElement; + 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 controller = document.querySelector('#map-controller') as HTMLElement; // 地图工具栏 + const monitor = document.querySelector('#map-monitor') as HTMLElement; // 地图工具栏 + const baselayer = document.querySelector('#map-baselayer') as HTMLElement; // 底图模式切换 + // const vd = document.querySelector('#vd_operate') as HTMLElement // 底部视频 + const left = [ + 'layout1', + 'layout2', + 'layout3', + 'layout4', + 'layout6', + 'layout7', + 'layout8', + 'layout9', + 'layout10', + 'layout11', + 'layout14', + 'layout15', + 'layout16', + 'layout17' + ]; // 左侧布局 + const right = [ + 'layout1', + 'layout2', + 'layout3', + 'layout4', + 'layout5', + 'layout6', + 'layout8', + 'layout10', + 'layout11', + 'layout15', + 'layout16', + 'layout17' + ]; // 右侧布局 + const bottom1 = [ + 'layout1', + 'layout6', + 'layout8', + 'layout9', + 'layout10', + 'layout16' + ]; // 三行底部布局 + const bottom2 = ['layout2', 'layout15']; // 四行底部布局 + const w = `${offset}px`; + const l = `${_theme === 'ly-8' ? (menuState ? 643 : 510) : offset}px`; + let b = `0px`; + const le = ['layout17', 'layout10'].includes(layoutType) ? 0 : 1; + const leftList = getListByPosition(data, 'left'); + const rightList = getListByPosition(data, 'right'); + const bottomList = getListByPosition(data, 'bottom'); + let bottom = '0'; - if (_theme === 'ly-8') { - if (window.__mapMode === '3D') { - b = `200px` - } else { - b = `${menuState ? 200 : 50}px` - } - } - - if (bottomList?.length > 0) { - if (bottom1.includes(layoutType)) { - bottom = 'calc((100% - 16px) / 3 + 8px)' - } - if (bottom2.includes(layoutType)) { - bottom = 'calc((100% - 24px) / 4 + 8px)' - } + if (_theme === 'ly-8') { + if (window.__mapMode === '3D') { + b = `200px`; } else { - // 没有底部布局时,底部高度为 - bottom = '28px' + b = `${menuState ? 200 : 50}px`; } + } - const rle = ['layout6'].includes(layoutType) || bottom != '28px' ? 0 : 1 + if (bottomList?.length > 0) { + if (bottom1.includes(layoutType)) { + bottom = 'calc((100% - 16px) / 3 + 8px)'; + } + if (bottom2.includes(layoutType)) { + bottom = 'calc((100% - 24px) / 4 + 8px)'; + } + } else { + // 没有底部布局时,底部高度为 + bottom = '28px'; + } - const leftHide = leftEle?.classList?.contains('hide') - const rightHide = rightEle?.classList?.contains('hide') - const bottomHide = bottomEle?.classList?.contains('hide') - if (legend) { - legend.style.left = !leftHide && left.includes(layoutType) && leftList?.length > le ? l : b - legend.style.bottom = bottomHide ? '0' : bottomList?.length > 0 ? bottom : '12px' + const rle = ['layout6'].includes(layoutType) || bottom != '28px' ? 0 : 1; + + const leftHide = leftEle?.classList?.contains('hide'); + const rightHide = rightEle?.classList?.contains('hide'); + const bottomHide = bottomEle?.classList?.contains('hide'); + if (legend) { + legend.style.left = + !leftHide && left.includes(layoutType) && leftList?.length > le ? l : b; + legend.style.bottom = bottomHide + ? '0' + : bottomList?.length > 0 + ? bottom + : '12px'; + } + if (filter) { + if (layoutType === 'layout10') { + filter.style.left = + !leftHide && left.includes(layoutType) && leftList?.length > 1 ? l : b; + } else { + filter.style.left = + !leftHide && + left.includes(layoutType) && + leftList?.length > 0 && + layoutType !== 'layout17' + ? l + : b; } - if (filter) { - if (layoutType === 'layout10') { - filter.style.left = !leftHide && left.includes(layoutType) && leftList?.length > 1 ? l : b - } else { - filter.style.left = !leftHide && left.includes(layoutType) && leftList?.length > 0 && layoutType !== 'layout17' ? l : b - } + } + if (compassControl) { + if (layoutType === 'layout10') { + compassControl.style.left = + !leftHide && left.includes(layoutType) && leftList?.length > 1 ? l : b; + } else { + compassControl.style.left = + !leftHide && + left.includes(layoutType) && + leftList?.length > 0 && + layoutType !== 'layout17' + ? l + : b; } - if (compassControl) { - if (layoutType === 'layout10') { - compassControl.style.left = !leftHide && left.includes(layoutType) && leftList?.length > 1 ? l : b - } else { - compassControl.style.left = !leftHide && left.includes(layoutType) && leftList?.length > 0 && layoutType !== 'layout17' ? l : b - } - } - if (controller) { - controller.style.right = !rightHide && right.includes(layoutType) && rightList?.length > rle ? w : '0' - controller.style.bottom = bottomHide ? '0' : bottom - } - if (monitor) { - monitor.style.right = !rightHide && right.includes(layoutType) && rightList?.length > rle ? w : '0' - // monitor.style.bottom = bottomHide ? '0' : bottom - } - if (baselayer) { - baselayer.style.right = !rightHide && right.includes(layoutType) && rightList?.length > rle ? `calc(${w} + 60px)` : '60px' - baselayer.style.bottom = bottomHide ? '0' : bottom - } -} + } + if (controller) { + controller.style.right = + !rightHide && right.includes(layoutType) && rightList?.length > rle + ? w + : '0'; + controller.style.bottom = bottomHide ? '0' : bottom; + } + if (monitor) { + monitor.style.right = + !rightHide && right.includes(layoutType) && rightList?.length > rle + ? w + : '0'; + // monitor.style.bottom = bottomHide ? '0' : bottom + } + if (baselayer) { + baselayer.style.right = + !rightHide && right.includes(layoutType) && rightList?.length > rle + ? `calc(${w} + 60px)` + : '60px'; + baselayer.style.bottom = bottomHide ? '0' : bottom; + } +}; 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 -} + 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)) -} + 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 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((e: any) => { + console.log('e', e); + }); + } else { + downloadElement.href = canvas.toDataURL('image/png'); + downloadElement.download = 'download'; + downloadElement.click(); } - 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((e: any) => { - console.log('e', e) - }) - } else { - downloadElement.href = canvas.toDataURL('image/png') - downloadElement.download = 'download' - downloadElement.click() - } - } -} + }; +}; diff --git a/frontend/src/components/gis/map.cesium.ts b/frontend/src/components/gis/map.cesium.ts index ef10c460..e5c61180 100644 --- a/frontend/src/components/gis/map.cesium.ts +++ b/frontend/src/components/gis/map.cesium.ts @@ -8,7 +8,7 @@ import type { MapInterface, layer } from './map.d'; export class MapCesium implements MapInterface { private viewer: Cesium.Viewer | null = null; - private containerId: string = ''; + private containerId = ''; init(container: HTMLElement, rectangle?: any): Promise { return new Promise(async (resolve, reject) => { @@ -113,16 +113,19 @@ export class MapCesium implements MapInterface { } // ... 其他空实现方法保持不变 ... - jdPanelControlShowAndHidden(baseid: String, isAll: boolean): void {} + jdPanelControlShowAndHidden(baseid: string, isAll: boolean): void {} mdLayerShowOrHidden(): void {} addBaseDataLayer(layer: any): void {} controlBaseLayerTreeShowAndHidden( - layerType: String, - key: String, + layerType: string, + key: string, checked: boolean ): void {} - mdLayerTreeShowOrHidden(layerType: String, checked?: boolean): void {} + mdLayerTreeShowOrHidden(layerType: string, checked?: boolean): void {} + setLegendPointVisible(layerKey: string, anchoPointState: string, checked: boolean): void {} addInitDataLayer(pointData: any[], layerType: any, mdoptions?: any): void {} + switchView(type: any): void {} + fitBounds(bounds: any): void {} baseLayerSwitcher(key: string): void {} addTertiarybasinLayer( layer: layer, @@ -146,7 +149,7 @@ export class MapCesium implements MapInterface { * 地图截图下载 * @param fileName 可选,下载的文件名,默认为 'cesium_map.png' */ - mapOutPut(fileName: string = 'cesium_map.png'): void { + mapOutPut(fileName = 'cesium_map.png'): void { if (!this.viewer) { console.warn('Viewer is not initialized.'); return; diff --git a/frontend/src/components/gis/map.class.ts b/frontend/src/components/gis/map.class.ts index d3b49dfe..0b286029 100644 --- a/frontend/src/components/gis/map.class.ts +++ b/frontend/src/components/gis/map.class.ts @@ -47,36 +47,50 @@ export class MapClass implements MapClassInterface { }); } // 基地面板控制 - jdPanelControlShowAndHidden(baseid: String, isAll: boolean): void { + jdPanelControlShowAndHidden(baseid: string, isAll: boolean): void { this.service.jdPanelControlShowAndHidden(baseid, isAll); } - mdLayerShowOrHidden(): void { - // layerType: String, key?: String, baseid: String, checked: boolean, isAll: boolean - // this.service.mdLayerShowOrHidden(layerType, key, baseid, checked, isAll) + + mdLayerShowOrHidden( + layerType: string, + baseid: string, + key?: string, + checked?: boolean, + isAll?: boolean + ): void { + this.service.mdLayerShowOrHidden(layerType, baseid, key, checked, isAll); } // 添加基础数据图层 - addBaseDataLayer(layer: any): void { - return this.service.addBaseDataLayer(layer); + addBaseDataLayer(layer: any, isShow: boolean): void { + return this.service.addBaseDataLayer(layer, isShow); } // 基础图层显示影隐藏方法 controlBaseLayerTreeShowAndHidden( - layerType: String, - key: String, + layerType: string, + key: string, checked: boolean ) { this.service.controlBaseLayerTreeShowAndHidden(layerType, key, checked); } // 图层树控制描点数据显示隐藏方法 - mdLayerTreeShowOrHidden(layerType: String, checked?: boolean) { + mdLayerTreeShowOrHidden(layerType: string, checked?: boolean) { this.service.mdLayerTreeShowOrHidden(layerType, checked); } + // 根据图例控制锚点显示隐藏 + setLegendPointVisible( + layerKey: string, + anchoPointState: string, + checked: boolean + ): void { + this.service.setLegendPointVisible(layerKey, anchoPointState, checked); + } // 初始化加载描点数据 addInitDataLayer = (pointData: any[], layerType: any, mdoptions?: any) => { return this.service.addInitDataLayer(pointData, layerType, mdoptions); }; //切换底图 - baseLayerSwitcher(key: string): void { - this.service.baseLayerSwitcher(key); + baseLayerSwitcher(key: string, checked: boolean): void { + this.service.baseLayerSwitcher(key, checked); } // 添加梯级流域图 @@ -118,6 +132,10 @@ export class MapClass implements MapClassInterface { mapOutPut() { this.service.mapOutPut(); } + // 检查图层是否存在 + hasLayer(layerKey: string): void { + return this.service.hasLayer(layerKey); + } // 销毁地图 destroy(): void { this.service.destroy(); diff --git a/frontend/src/components/gis/map.d.ts b/frontend/src/components/gis/map.d.ts index 03409b75..b0b87d9c 100644 --- a/frontend/src/components/gis/map.d.ts +++ b/frontend/src/components/gis/map.d.ts @@ -82,13 +82,13 @@ export interface MapInterface { * 初始化加载基础图层 * @param layer */ - addBaseDataLayer(layer: any): void; + addBaseDataLayer(layer: any, isShow: boolean): void; /** * 切换底图 * @param layer */ - baseLayerSwitcher(key: string): void; + baseLayerSwitcher(key: string, checked: boolean): void; /** * 切换2D或者3D视图 @@ -103,6 +103,12 @@ export interface MapInterface { */ zoomToggle(type: 'out' | 'in'): void; + /** + * 检查图层是否存在 + * @param layerKey 图层 key + * @returns 是否存在 + */ + hasLayer(layerKey: string): void; /** * 地图输出打印 */ @@ -147,7 +153,7 @@ export interface MapInterface { * @param baseid * @param isAll */ - jdPanelControlShowAndHidden(baseid: String, isAll: boolean): void; + jdPanelControlShowAndHidden(baseid: string, isAll: boolean): void; /** * 图例和基地面板控制描点数据显示隐藏方法 * @param layerType @@ -155,16 +161,22 @@ export interface MapInterface { * @param checked * @param isAll */ - mdLayerShowOrHidden(): void; - // layerType: String, key?: String, baseid: String, checked: boolean, isAll: boolean + mdLayerShowOrHidden( + layerType: string, + baseid: string, + key?: string, + checked?: boolean, + isAll?: boolean + ): void; + /** * 基础图层显示影隐藏方法 * @param layerType * @param checked */ controlBaseLayerTreeShowAndHidden( - layerType: String, - key: String, + layerType: string, + key: string, checked: boolean ): void; @@ -173,7 +185,19 @@ export interface MapInterface { * @param layerType * @param checked */ - mdLayerTreeShowOrHidden(layerType: String, checked?: boolean): void; + mdLayerTreeShowOrHidden(layerType: string, checked?: boolean): void; + + /** + * 根据 anchoPointState 控制单个图例的锚点显示隐藏 + * @param layerKey 图层 key + * @param anchoPointState 锚点状态(对应图例的 nameEn) + * @param checked 是否显示 + */ + setLegendPointVisible( + layerKey: string, + anchoPointState: string, + checked: boolean + ): void; /** * 长度量算 diff --git a/frontend/src/components/gis/map.ol.ts b/frontend/src/components/gis/map.ol.ts index 0184d343..151e3046 100644 --- a/frontend/src/components/gis/map.ol.ts +++ b/frontend/src/components/gis/map.ol.ts @@ -13,6 +13,7 @@ import Icon from 'ol/style/Icon'; import Text from 'ol/style/Text'; import Circle from 'ol/style/Circle'; import RegularShape from 'ol/style/RegularShape'; +import Cluster from 'ol/source/Cluster'; // import LayerGroup from 'ol/layer/Group'; // import OSM from 'ol/source/OSM'; @@ -40,6 +41,10 @@ import { import { unByKey } from 'ol/Observable'; import { MDOptions } from './map.class'; import { getIconPath } from '@/utils/index'; // ✅ 确保引入获取图标路径的工具函数 +import { generatePopupHtml } from '@/utils/popupHtmlGenerator'; +import { useModelStore } from '@/store/modules/model'; + +const modelStore = useModelStore(); // 定义与 leaflet 中相同的常量 const CENTER_positionCN = [114.17112499999996, 38]; // OpenLayers 使用 [lon, lat] @@ -74,7 +79,7 @@ export class MapOl implements MapInterface { // ✅ 新增:声明用于存储 mask 事件监听器的引用,以便后续移除 private _maskPrerender: any = null; private _maskPostrender: any = null; - private BASEID: string = ''; + private BASEID = ''; // ✅ 新增:记录当前鼠标悬停的 Feature ID private hoveredFeatureId: string | number | null = null; // ✅ 新增:用于显示自定义内容的 Overlay @@ -147,68 +152,42 @@ export class MapOl implements MapInterface { // 如果需要防抖处理,可以添加 debounce console.log('当前缩放级别', this.view?.getZoom()); }); + // 点击弹出弹框 + this.map.on('click', evt => { + const pixel = evt.pixel; + + // 使用共享方法检测要素 + const { detectedFeature, isHitIcon } = this.detectFeatureAtPixel(pixel); + + if (detectedFeature && isHitIcon) { + modelStore.modalVisible = true; + modelStore.params = detectedFeature.values_; + modelStore.title = detectedFeature.values_.titleName + ' 详情信息'; + } + }); // ✅ 新增:监听鼠标移动,动态改变光标样式 let lastHoveredId: string | number | null = null; let animationFrameId: number | null = null; // pointermove - this.map.on('click', evt => { + this.map.on('pointermove', evt => { const pixel = evt.pixel; + // 判断地图层级,4.7 以上才进行 popup 显示 + const zoom = this.map.getView().getZoom(); + if (zoom !== undefined && zoom < 4.7) { + return; + } + // 取消之前的动画帧,确保只处理最新的一次移动 if (animationFrameId) { cancelAnimationFrame(animationFrameId); } animationFrameId = requestAnimationFrame(() => { - let detectedFeature: Feature | undefined = undefined; - let isHitIcon: boolean = false; // 标记是否真正命中了图标区域 - - // 1. 获取当前视口下的所有点图层 - const pointLayers = Array.from(this.pointLayerRegistry.values()); - - // 2. 遍历检测,但我们需要更精细的判断 - this.map?.forEachFeatureAtPixel( - pixel, - (feature, layer) => { - // 只关心点图层 - if (pointLayers.includes(layer)) { - detectedFeature = feature as Feature; - - // ✅ 关键优化:判断是否命中图标区域 - // OpenLayers 的 Icon 样式通常有 anchor [0.5, 0.5] - // 我们可以获取图标的尺寸,判断鼠标是否在图标矩形范围内 - const style = (layer as VectorLayer).getStyle(); - let iconSize = { width: 0, height: 0 }; - - // 尝试从样式中获取图标尺寸(如果样式是函数,可能需要调用它,这里简化处理,假设固定大小或从 feature 获取) - // 更通用的做法是:计算鼠标点到 Feature 坐标投影后的像素距离 - const geom = feature.getGeometry(); - if (geom && geom.getType() === 'Point') { - const coord = (geom as Point).getCoordinates(); - const iconPixel = this.map?.getPixelFromCoordinate(coord); - - if (iconPixel) { - // 计算鼠标像素与图标中心像素的距离 - const dx = pixel[0] - iconPixel[0]; - const dy = pixel[1] - iconPixel[1]; - const distance = Math.sqrt(dx * dx + dy * dy); - - // 假设图标大致大小为 30x30 或 40x40,半径设为 15-20 - // 你可以根据实际 icon 大小调整这个阈值,例如 15 - const hitRadius = 15; - if (distance <= hitRadius) { - isHitIcon = true; - } - } - } - - return true; // 找到第一个点图层要素即停止 - } - return false; - }, - { hitTolerance: 0 } // 设置为 0,完全依赖上面的距离计算 - ); + // 使用共享方法检测要素 + const { detectedFeature, isHitIcon } = + this.detectFeatureAtPixel(pixel); // 3. 根据是否命中图标来决定行为 const newHoveredId = @@ -261,6 +240,7 @@ export class MapOl implements MapInterface { layerType: any, mdoptions?: MDOptions ): void { + console.log('addInitDataLayer', pointData, layerType, mdoptions); if (!this.map) return; let dataArray: any[] = []; @@ -283,24 +263,26 @@ export class MapOl implements MapInterface { let vectorLayer = this.pointLayerRegistry.get(targetLayerKey); let vectorSource: VectorSource; - const shouldClear = mdoptions?.isRemove !== false; + // const shouldClear = mdoptions?.isRemove !== false; if (!vectorLayer) { vectorSource = new VectorSource(); vectorLayer = new VectorLayer({ source: vectorSource, zIndex: 100, // 确保点在底图之上 - // declutter: true, - // style: (feature: any) => this.createPointStyle(feature) // 使用动态样式函数 - style: (feature: any) => this.createPointStyle1(feature) // 使用动态样式函数 + // declutter: false, + // renderOrder: (a, b) => + // (b.get('distance') || 0) - (a.get('distance') || 0), + style: (feature: any) => this.createPointStyle(feature) // 使用动态样式函数 + // style: (feature: any) => this.createPointStyle1(feature) // 使用动态样式函数 }); this.pointLayerRegistry.set(targetLayerKey, vectorLayer); this.map.addLayer(vectorLayer); } else { vectorSource = vectorLayer.getSource() as VectorSource; - if (shouldClear) { - vectorSource.clear(); - } + // if (shouldClear) { + // vectorSource.clear(); + // } } if (dataArray.length === 0) { @@ -315,7 +297,7 @@ export class MapOl implements MapInterface { const features: Feature[] = []; dataArray.forEach((item: any) => { - let { lgtd, lttd, stnm, iconCode, titleName, ennm } = item; + const { lgtd, lttd, stnm, iconCode, titleName, ennm } = item; if (lgtd == null || lttd == null) { return; @@ -336,11 +318,19 @@ export class MapOl implements MapInterface { } // 显示的文字优先使用 titleName,其次 ennm,最后 stnm - const labelText = titleName || ennm || stnm || ''; + const labelText = titleName || stnm || ennm || ''; + if (lgtd == null || lttd == null) return; + const lon = Number(lgtd); + const lat = Number(lttd); + if (isNaN(lon) || isNaN(lat) || !isFinite(lon) || !isFinite(lat)) return; + if (Math.abs(lon) > 180 || Math.abs(lat) > 90) return; + const coord = fromLonLat([lon, lat]); + if (!isFinite(coord[0]) || !isFinite(coord[1])) return; + const geometry = new Point(coord); // 5. 创建 Feature const feature = new Feature({ - geometry: new Point(fromLonLat([lgtd, lttd])), // ✅ 关键:坐标转换 EPSG:4326 -> EPSG:3857 + geometry: geometry, // ✅ 关键:坐标转换 EPSG:4326 -> EPSG:3857 ...item, // 保留原始数据以便点击事件使用 _layerKey: targetLayerKey }); @@ -351,6 +341,8 @@ export class MapOl implements MapInterface { // 将自定义属性绑定到 feature,以便样式函数访问 feature.set('_iconUrl', iconUrl); feature.set('_labelText', labelText); + feature.set('_legendVisible', true); // 默认显示 + feature.set('_sttpMap', item.sttpMap); // 默认显示 if (item.popupHtml) { feature.set('popupHtml', item.popupHtml); } @@ -364,6 +356,7 @@ export class MapOl implements MapInterface { } console.log(`图层 [${targetLayerKey}] 描点加载完成`); + console.log(`图层 [${targetLayerKey}] 描点加载完成`); } /** * 初始化 Popup Overlay @@ -389,6 +382,67 @@ export class MapOl implements MapInterface { this.map.addOverlay(this.popupOverlay); } } + /** + * 在指定像素位置检测要素(共享方法) + * @param pixel 像素坐标 + * @returns 检测到的要素和是否命中图标区域 + */ + private detectFeatureAtPixel(pixel: number[]): { + detectedFeature: Feature | undefined; + isHitIcon: boolean; + } { + let detectedFeature: Feature | undefined = undefined; + let isHitIcon = false; + + // 1. 获取当前视口下的所有点图层 + const pointLayers = Array.from(this.pointLayerRegistry.values()); + + // 2. 遍历检测,但我们需要更精细的判断 + this.map?.forEachFeatureAtPixel( + pixel, + (feature, layer) => { + // 只关心点图层 + if (pointLayers.includes(layer)) { + detectedFeature = feature as Feature; + + // ✅ 关键优化:判断是否命中图标区域 + // OpenLayers 的 Icon 样式通常有 anchor [0.5, 0.5] + // 我们可以获取图标的尺寸,判断鼠标是否在图标矩形范围内 + const style = (layer as VectorLayer).getStyle(); + const iconSize = { width: 0, height: 0 }; + + // 尝试从样式中获取图标尺寸(如果样式是函数,可能需要调用它,这里简化处理,假设固定大小或从 feature 获取) + // 更通用的做法是:计算鼠标点到 Feature 坐标投影后的像素距离 + const geom = feature.getGeometry(); + if (geom && geom.getType() === 'Point') { + const coord = (geom as Point).getCoordinates(); + const iconPixel = this.map?.getPixelFromCoordinate(coord); + + if (iconPixel) { + // 计算鼠标像素与图标中心像素的距离 + const dx = pixel[0] - iconPixel[0]; + const dy = pixel[1] - iconPixel[1]; + const distance = Math.sqrt(dx * dx + dy * dy); + + // 假设图标大致大小为 30x30 或 40x40,半径设为 15-20 + // 你可以根据实际 icon 大小调整这个阈值,例如 15 + const hitRadius = 15; + if (distance <= hitRadius) { + isHitIcon = true; + } + } + } + + return true; // 找到第一个点图层要素即停止 + } + return false; + }, + { hitTolerance: 0 } // 设置为 0,完全依赖上面的距离计算 + ); + + return { detectedFeature, isHitIcon }; + } + /** * 在 pointermove 中调用此方法显示/隐藏 Popup * @param feature 当前悬停的要素 @@ -398,31 +452,22 @@ export class MapOl implements MapInterface { if (!this.popupOverlay || !this.popupElement) return; if (feature && coordinate) { - // 1. 获取数据 const props = feature.getProperties(); - // 2. 生成内容 (这里假设父组件已经在 feature 上绑定了 popupHtml 或者我们在这里构建) - // 方案 A: 如果父组件传入了 HTML 字符串 - const popupHtml = props.popupHtml || props.popup || ''; - - // 方案 B: 如果父组件希望动态更新 DOM (推荐,性能更好,支持交互) - // 我们可以触发一个事件,让 Vue 组件去更新这个 div 的内容 - // 这里为了简单,直接演示如何填充内容 + const popupHtml = props.popupHtml || generatePopupHtml(props); if (popupHtml) { this.popupElement.innerHTML = popupHtml; this.popupOverlay.setPosition(coordinate); this.popupElement.style.display = 'block'; } else { - // 如果没有预设 HTML,可以显示默认文本 - this.popupElement.innerHTML = `
${ - props.stnm || props.titleName || '未知' - }
`; - this.popupOverlay.setPosition(coordinate); - this.popupElement.style.display = 'block'; + // this.popupElement.innerHTML = `
${ + // props.stnm || props.titleName || '未知' + // }
`; + // this.popupOverlay.setPosition(coordinate); + // this.popupElement.style.display = 'block'; } } else { - // 隐藏 this.popupOverlay.setPosition(undefined); this.popupElement.style.display = 'none'; } @@ -432,13 +477,26 @@ export class MapOl implements MapInterface { */ private createPointStyle(feature: Feature): Style { const iconUrl = feature.get('_iconUrl') as string; + const sttpMap = feature.get('_sttpMap') as string; const labelText = feature.get('_labelText') as string; + const legendVisible = feature.get('_legendVisible'); + const regionVisible = feature.get('_regionVisible'); // 如果没图标,返回空样式 if (!iconUrl) { return new Style(); } + // 如果图例设置为隐藏,返回空样式 + if (legendVisible === false) { + return new Style(); + } + + // 如果区域外,返回空样式 + if (regionVisible === false) { + return new Style(); + } + // ✅ 1. 获取当前地图分辨率 // 注意:如果样式函数在地图未完全初始化时调用,view 可能为 null // const currentResolution = this.view ? this.view.getResolution() : 1000; @@ -455,8 +513,26 @@ export class MapOl implements MapInterface { // 限制最大和最小缩放,防止过大或过小 // let dynamicScale = baseScale * (baseResolution / (currentResolution || 1)); const currentZoom: any = this.view ? this.view.getZoom() : 4.5; + const distance = feature.get('distance'); // 你通过计算赋值的字段 + // ✅ 分级过滤规则(根据实际业务调整阈值) + if (distance !== undefined && distance !== null) { + let minDistanceRequired = 0; + if (currentZoom <= 6) { + // 极远视图:只显示最孤立的站点(distance >= 50000000 或 1500000?根据你的数据分布定) + // 假设 50000000 和 1500000 属于高值,都显示;400000 和 50000 不显示 + minDistanceRequired = 1500000; // 只显示 >=150万 的点 + } else if (currentZoom <= 8) { + minDistanceRequired = 800000; // 显示 >=80万 的点 + } else if (currentZoom <= 10.5) { + minDistanceRequired = 400000; // 显示 >=40万 的点 + } else { + minDistanceRequired = 0; // 放大到14级以上显示所有点(包括5万的) + } + if (distance <= minDistanceRequired) { + return new Style(); // 不满足,隐藏 + } + } let dynamicScale = 0.7 + (currentZoom - 4.5) * 0.08; - // 限制范围:最小 0.5,最大 3.0 (可根据需求调整) dynamicScale = Math.max(0.5, Math.min(3.0, dynamicScale)); @@ -472,7 +548,8 @@ export class MapOl implements MapInterface { src: iconUrl, scale: dynamicScale, anchor: [0.5, 0.5], - crossOrigin: 'anonymous' + crossOrigin: 'anonymous', + declutterMode: 'obstacle' // 图标参与碰撞,可被隐藏 }) // zIndex: zIndex // ✅ 设置样式的 zIndex @@ -574,7 +651,11 @@ export class MapOl implements MapInterface { * 初始化加载基础图层 * @param layer 图层配置对象 */ - addBaseDataLayer(layer: any, isCache: boolean = false): void { + addBaseDataLayer( + layer: any, + isShow: boolean, + isCache: boolean = false + ): void { if (!this.map) return; console.log('OL addBaseDataLayer', layer); @@ -640,10 +721,12 @@ export class MapOl implements MapInterface { if (layer.key === this.REGISTRY_KEY) { !isCache ? wmtsLayer.setZIndex(-100) : wmtsLayer.setZIndex(-99); } else { - wmtsLayer.setZIndex(-99); + wmtsLayer.setZIndex(-100); } - console.log('基础图层', wmtsLayer); + wmtsLayer.type = 'layer'; // 5. 注册与添加 + wmtsLayer.setVisible(isShow); + console.log('基础图层', wmtsLayer); this.layerRegistry.set(layer.key, wmtsLayer); this.map.addLayer(wmtsLayer); layer._layer = wmtsLayer; @@ -656,7 +739,9 @@ export class MapOl implements MapInterface { }) }); tileLayer.setZIndex(-100); - this.layerRegistry.set(this.REGISTRY_KEY, tileLayer); + tileLayer.setVisible(isShow); + tileLayer.type = 'layer'; + this.layerRegistry.set(layer.key, tileLayer); this.map.addLayer(tileLayer); } else if (layer.type === 'vector') { if (layer.key === 'hydropBase') { @@ -702,8 +787,9 @@ export class MapOl implements MapInterface { console.log(`切换区域至: ${this.BASEID}`); if (!isAll) { - // ✅ 情况 A: isAll == false -> 清空裁切 + // ✅ 情况 A: isAll == false -> 清空裁切,显示所有锚点 this.clearMapMask(); + this.showAllPoints(); return; } @@ -713,6 +799,10 @@ export class MapOl implements MapInterface { console.warn('未找到底图图层,无法应用遮罩'); return; } + + // ✅ 关键优化:在加载新区域数据前,先隐藏所有锚点,避免闪烁 + this.hideAllPoints(); + try { const url = this.hydropBaseConfig.geojson_url + @@ -723,7 +813,10 @@ export class MapOl implements MapInterface { const geoJsonData = await this.loadGeoJsonData(url); console.log('获取到的原始 GeoJSON:', geoJsonData); - // ✅ 新增:在应用遮罩前,先让地图视角聚焦到该区域 + // ✅ 先根据区域边界过滤锚点(此时锚点还是隐藏的) + this.filterPointsByRegion(geoJsonData); + + // ✅ 再让地图视角聚焦到该区域 this.fitViewToGeoJson(geoJsonData); console.log('基础图层', baseLayer); @@ -733,8 +826,150 @@ export class MapOl implements MapInterface { console.error('加载裁切数据失败:', error); // 出错时也清空遮罩,保证用户体验 this.clearMapMask(); + this.showAllPoints(); } } + + /** + * 隐藏所有锚点 + */ + private hideAllPoints(): void { + this.pointLayerRegistry.forEach(layer => { + const vectorSource = layer.getSource() as VectorSource; + if (!vectorSource) return; + + const features = vectorSource.getFeatures(); + features.forEach((feature: Feature) => { + feature.set('_regionVisible', false); + feature.changed(); + }); + }); + } + + /** + * 显示所有锚点 + */ + private showAllPoints(): void { + this.pointLayerRegistry.forEach(layer => { + const vectorSource = layer.getSource() as VectorSource; + if (!vectorSource) return; + + const features = vectorSource.getFeatures(); + features.forEach((feature: Feature) => { + feature.set('_regionVisible', true); + feature.changed(); + }); + }); + } + + /** + * 根据区域边界过滤锚点显示 + * 使用射线法判断点是否在多边形内 + */ + private filterPointsByRegion(geoJson: any): void { + // 解析 GeoJSON 获取区域多边形坐标 + const regionCoords = this.extractPolygonCoords(geoJson); + if (!regionCoords || regionCoords.length === 0) { + console.warn('无法解析区域边界,显示所有锚点'); + this.showAllPoints(); + return; + } + + // 遍历所有锚点图层 + this.pointLayerRegistry.forEach(layer => { + const vectorSource = layer.getSource() as VectorSource; + if (!vectorSource) return; + + const features = vectorSource.getFeatures(); + features.forEach((feature: Feature) => { + const props = feature.getProperties(); + const lon = props.lgtd; + const lat = props.lttd; + + if (lon == null || lat == null) { + feature.set('_regionVisible', false); + feature.changed(); + return; + } + + // 判断点是否在区域内 + const isInside = this.isPointInPolygon(lon, lat, regionCoords); + feature.set('_regionVisible', isInside); + feature.changed(); + }); + }); + } + + /** + * 从 GeoJSON 中提取多边形坐标 + */ + private extractPolygonCoords(geoJson: any): number[][][] { + if (!geoJson || !geoJson.features || geoJson.features.length === 0) { + return []; + } + + const coords: number[][][] = []; + geoJson.features.forEach((feature: any) => { + const geometry = feature.geometry; + if (!geometry) return; + + if (geometry.type === 'Polygon') { + // Polygon: [[[lon, lat], ...], ...] + coords.push(...geometry.coordinates); + } else if (geometry.type === 'MultiPolygon') { + // MultiPolygon: [[[[lon, lat], ...], ...], ...] + geometry.coordinates.forEach((polygon: number[][][]) => { + coords.push(...polygon); + }); + } + }); + + return coords; + } + + /** + * 射线法判断点是否在多边形内 + * @param lon 经度 + * @param lat 纬度 + * @param polygons 多边形坐标数组 [[[lon, lat], ...], ...] + */ + private isPointInPolygon( + lon: number, + lat: number, + polygons: number[][][] + ): boolean { + for (const polygon of polygons) { + if (this.isPointInRing(lon, lat, polygon)) { + return true; + } + } + return false; + } + + /** + * 射线法判断点是否在单个环内 + */ + private isPointInRing(lon: number, lat: number, ring: number[][]): boolean { + let inside = false; + const n = ring.length; + + for (let i = 0, j = n - 1; i < n; j = i++) { + const xi = ring[i][0]; + const yi = ring[i][1]; + const xj = ring[j][0]; + const yj = ring[j][1]; + + const intersect = + yi > lat !== yj > lat && + lon < ((xj - xi) * (lat - yi)) / (yj - yi) + xi; + + if (intersect) { + inside = !inside; + } + } + + return inside; + } /** * 基础图层显示影隐藏方法 * @param layerType 图层类型 (备用,优先使用 key) @@ -742,11 +977,12 @@ export class MapOl implements MapInterface { * @param checked true 为显示,false 为隐藏 */ controlBaseLayerTreeShowAndHidden( - layerType: String, - key: String, + layerType: string, + key: string, checked: boolean ): void { if (!this.map) return; + console.log('controlBaseLayerTreeShowAndHidden', layerType, key, checked); // 1. 确定查找的 Key:优先使用传入的 key,如果为空则尝试使用 layerType const registryKey = key || layerType; @@ -759,11 +995,12 @@ export class MapOl implements MapInterface { } // 2. 从注册表中获取图层实例 const layerInstance = this.layerRegistry.get(registryKey as string); - + console.log(layerInstance); if (layerInstance) { + layerInstance.setVisible(checked); // 3. 设置可见性 // OpenLayers 的 Layer.setVisible(boolean) 方法 - layerInstance.setVisible(checked); + // layerInstance.setVisible(checked); console.log( `图层 [${registryKey}] 已设置为: ${checked ? '显示' : '隐藏'}` @@ -776,11 +1013,23 @@ export class MapOl implements MapInterface { } } // 图层树控制描点数据显示隐藏方法 - mdLayerTreeShowOrHidden(layerType: String, checked?: boolean): void { - const layerInstance: any = this.pointLayerRegistry.get(layerType as string); - layerInstance.setVisible(checked); + mdLayerTreeShowOrHidden(layerType: string, checked?: boolean): void { + console.log('mdLayerTreeShowOrHidden', layerType, checked); + const layerInstance: any = this.pointLayerRegistry.get(layerType); + console.log('mdLayerTreeShowOrHidden', layerInstance); + if (layerInstance) { + layerInstance.setVisible(checked); + } // this.service.mdLayerTreeShowOrHidden(layerType, checked) } + + hasLayer(layerType: string): void { + console.log('hasLayer', layerType); + const layerInstance: any = this.pointLayerRegistry.get(layerType); + console.log('hasLayer', layerInstance); + return this.pointLayerRegistry.has(layerType as string); + } + /** * 缩放地图 * @param type 'out' 缩小, 'in' 放大 @@ -822,7 +1071,7 @@ export class MapOl implements MapInterface { * 切换底图 * @param key 业务标识 Key (如 's_province_boundaries', 'BASEMAP-white', 'BASEMAP-img') */ - baseLayerSwitcher(key: string): void { + baseLayerSwitcher(key: string, checked: boolean): void { if (!this.map || !this.view) return; console.log('OL 切换底图 key:', key); @@ -836,12 +1085,42 @@ export class MapOl implements MapInterface { // 2. 根据传入的业务 key 创建新的图层实例 if (key == 's_province_boundaries') { - this.addBaseDataLayer(this.baseLayerConfig); + this.addBaseDataLayer(this.baseLayerConfig, checked); + // 隐藏 BASEMAP-white 和 BASEMAP-img 图层(如果存在) + this.hideBaseMapLayers(['BASEMAP-white', 'BASEMAP-img']); } else { - this.addBaseDataLayer(this.baseLayerConfig, true); - this.addBaseDataLayer(servers.BaseLayer[key]); + this.addBaseDataLayer(this.baseLayerConfig, checked, true); + this.addBaseDataLayer(servers.BaseLayer[key], 1); + // 显示 BASEMAP-white 和 BASEMAP-img 图层(如果存在) + this.showBaseMapLayers(['BASEMAP-white', 'BASEMAP-img']); } } + /** + * 隐藏指定的底图图层 + * @param layerKeys 要隐藏的图层 key 数组 + */ + hideBaseMapLayers(layerKeys: string[]): void { + layerKeys.forEach(key => { + const layer = this.layerRegistry.get(key); + if (layer) { + layer.setVisible(false); + } + }); + } + + /** + * 显示指定的底图图层 + * @param layerKeys 要显示的图层 key 数组 + */ + showBaseMapLayers(layerKeys: string[]): void { + layerKeys.forEach(key => { + const layer = this.layerRegistry.get(key); + if (layer) { + layer.setVisible(true); + } + }); + } + /** * 添加梯级流域图 (Vector Layer) - 使用本地 GeoJSON 数据 * @param layer 图层配置对象 @@ -1348,6 +1627,7 @@ export class MapOl implements MapInterface { */ private applyMapMask(rasterLayer: TileLayer, clipGeoJson: any): void { if (!rasterLayer || !clipGeoJson) return; + console.log('地图遮罩开始'); // 1. 解析 GeoJSON 为 OL Features (EPSG:3857) const features = new GeoJSON().readFeatures(clipGeoJson, { @@ -1596,8 +1876,96 @@ export class MapOl implements MapInterface { const areaSqKm = areaSqMeters / 1000000; return '面积:' + areaSqKm.toFixed(3) + 'km²'; } + // 图例和基地面板控制描点数据显示隐藏方法 + /** + * 图例和基地面板控制描点数据显示隐藏方法 + * @param layerType 图层类型 + * @param key 图层标识符 + * @param baseid 基地ID + * @param checked 是否选中(显示/隐藏) + * @param isAll 是否全部操作 + */ + mdLayerShowOrHidden( + layerType: string, + baseid: string, + key?: string, + checked?: boolean, + isAll?: boolean + ): void { + console.log('mdLayerShowOrHidden', layerType, key, baseid, checked, isAll); + // 确定查找的 Key:优先使用传入的 key,如果为空则尝试使用 layerType + const registryKey = key || layerType; - mdLayerShowOrHidden(): void {} + if (isAll) { + // 如果是全部操作,则对所有相应类型的图层进行处理 + if (layerType === 'point') { + // 处理所有点图层 + this.pointLayerRegistry.forEach((layer, key) => { + if (layer) { + layer.setVisible(checked); + } + }); + } else { + // 处理其他类型的图层 + this.layerRegistry.forEach((layer, key) => { + if (key.startsWith(layerType as string)) { + layer.setVisible(checked); + } + }); + } + } else { + // 单独操作特定图层 + let targetLayer = null; + + // 先尝试在点图层注册表中查找 + targetLayer = this.pointLayerRegistry.get(registryKey as string); + + // 如果没找到,再在普通图层注册表中查找 + if (!targetLayer) { + targetLayer = this.layerRegistry.get(registryKey as string); + } + + // 如果指定了基地ID,可以进一步筛选 + if (targetLayer) { + targetLayer.setVisible(checked); + } + } + } + + /** + * 根据 anchoPointState 控制单个图例的锚点显示隐藏 + * @param layerKey 图层 key + * @param anchoPointState 锚点状态(对应图例的 nameEn) + * @param checked 是否显示 + */ + setLegendPointVisible( + layerKey: string, + anchoPointState: string, + checked: boolean + ): void { + const vectorLayer = this.pointLayerRegistry.get(layerKey); + if (!vectorLayer) return; + + const vectorSource = vectorLayer.getSource() as VectorSource; + if (!vectorSource) return; + + const features = vectorSource.getFeatures(); + features.forEach((feature: Feature) => { + const props = feature.getProperties(); + // 如果 anchoPointState 为空,隐藏所有锚点 + if (!anchoPointState) { + feature.set('_legendVisible', false); + feature.changed(); + } else if (props.anchoPointState === anchoPointState) { + // 根据 anchoPointState 匹配 + // 设置 feature 的可见性 + feature.set('_legendVisible', checked); + // 触发重新渲染 + feature.changed(); + } + // 不匹配的 feature 不做处理,保持原样 + }); + } switchView(type): void { console.log(type); diff --git a/frontend/src/components/gis/mapurlManage.ts b/frontend/src/components/gis/mapurlManage.ts index 87b51c3e..88161502 100644 --- a/frontend/src/components/gis/mapurlManage.ts +++ b/frontend/src/components/gis/mapurlManage.ts @@ -8,33 +8,33 @@ // import { Session } from '@zebras/qgc-share/service/Session' export interface MapBaseUrlItem { - code: string - name: string - url: string + code: string; + name: string; + url: string; } export interface ServerConfigItem { - id?: string - key?: string - urlType: 'gisurl' | 'online' - url?: string - url_3d?: string - layers?: string - rasteropacity?: number - _layer?: string - imgUrl?: string - visible?: boolean - visibility?: boolean //?是否可以删除 - minZoom?: number - maxZoom?: number - fillOpacity?: number - lineWidth?: number - [name: string]: any + id?: string; + key?: string; + urlType: 'gisurl' | 'online'; + url?: string; + url_3d?: string; + layers?: string; + rasteropacity?: number; + _layer?: string; + imgUrl?: string; + visible?: boolean; + visibility?: boolean; //?是否可以删除 + minZoom?: number; + maxZoom?: number; + fillOpacity?: number; + lineWidth?: number; + [name: string]: any; } -const tdtToken = 'e90d56e5a09d1767899ad45846b0cefd' //企业版密钥,勿换e650f138c4481cca888cd13094bb9026 -const mapType = 'w' //c:天地图经纬度底图;w:天地图墨卡托底图 -const URL_TerTDT = `https://t0.tianditu.gov.cn/ter_${mapType}/wmts?tk=${tdtToken}` //terMap +const tdtToken = 'e90d56e5a09d1767899ad45846b0cefd'; //企业版密钥,勿换e650f138c4481cca888cd13094bb9026 +const mapType = 'w'; //c:天地图经纬度底图;w:天地图墨卡托底图 +const URL_TerTDT = `https://t0.tianditu.gov.cn/ter_${mapType}/wmts?tk=${tdtToken}`; //terMap // const URL_TerLabelTDT = `http://t0.tianditu.gov.cn/cta_${mapType}/wmts?tk=${tdtToken}` //terLabel // const URL_VecTDT = `http://t0.tianditu.com/vec_${mapType}/wmts?tk=${tdtToken}` //vecMap // const URL_VecLableTDT = `http://t0.tianditu.com/cva_${mapType}/wmts?tk=${tdtToken}` //vecLabel @@ -44,685 +44,695 @@ const URL_TerTDT = `https://t0.tianditu.gov.cn/ter_${mapType}/wmts?tk=${tdtToken // const znyMapUrl = "http://10.219.26.6:8050/" //中南院的测试地图环境 // const djjtMapUrl = "http://210.72.227.199:18084/" //中南院的测试地图环境 //TODO:以后改成在系统管理里面配置地图可视化范围 -export const location_map_maxlon = 126.8267 -export const location_map_maxlat = 38.5769 -export const location_map_minlon = 73.7443 -export const location_map_minlat = 16.32 +export const location_map_maxlon = 126.8267; +export const location_map_maxlat = 38.5769; +export const location_map_minlon = 73.7443; +export const location_map_minlat = 16.32; // todo: 以后从接口获取数据 export const servers: Record | Record = { - // 省(自治区)界 - province_boundaries: { - id: 'province_boundaries', - key: 'province_boundaries', - urlType: 'gisurl', - // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', - url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:provinceline&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:provinceline&outputFormat=application%2Fjson&token= + // 省(自治区)界 + province_boundaries: { + id: 'province_boundaries', + key: 'province_boundaries', + urlType: 'gisurl', + // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', + url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:provinceline&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:provinceline&outputFormat=application%2Fjson&token= `, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:provinceline', - rasteropacity: 1, - minZoom: 0, - maxZoom: 21, - type: 'wms', - layerType: 'line', - lineWidth: 2, - visible: true - }, - //国界 - chinaBoundary: { - id: 'chinaBoundary', - key: 'chinaBoundary', - urlType: 'gisurl', - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Achina@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:china&maxFeatures=50&outputFormat=application%2Fjson&token= + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:provinceline', + rasteropacity: 1, + minZoom: 0, + maxZoom: 21, + type: 'wms', + layerType: 'line', + lineWidth: 2, + visible: true + }, + //国界 + chinaBoundary: { + id: 'chinaBoundary', + key: 'chinaBoundary', + urlType: 'gisurl', + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Achina@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:china&maxFeatures=50&outputFormat=application%2Fjson&token= `, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:china', - _layer: 'china', - layerType: 'line', - minZoom: 0, - maxZoom: 16, - minHeight: 0, - maxHeight: 80000000, - rasteropacity: 1, - type: 'vector_Boundary', - paint: { - 'line-color': '#AAA4C5', - 'line-width': 3, - 'line-opacity': 0.9 - } - }, - //九段线 - nineSegmentLine: { - id: 'nineSegmentLine', - key: 'nineSegmentLine', - urlType: 'gisurl', - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Azh_island1@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - url_3d: '/geoserver/qgc/wms', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:zh_island1&maxFeatures=50&outputFormat=application%2Fjson&token= + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:china', + _layer: 'china', + layerType: 'line', + minZoom: 0, + maxZoom: 16, + minHeight: 0, + maxHeight: 80000000, + rasteropacity: 1, + type: 'vector_Boundary', + paint: { + 'line-color': '#AAA4C5', + 'line-width': 3, + 'line-opacity': 0.9 + } + }, + //九段线 + nineSegmentLine: { + id: 'nineSegmentLine', + key: 'nineSegmentLine', + urlType: 'gisurl', + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Azh_island1@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + url_3d: '/geoserver/qgc/wms', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:zh_island1&maxFeatures=50&outputFormat=application%2Fjson&token= `, - layers: 'qgc:zh_island1', - _layer: 'zh_island1', - layerType: 'line', - minZoom: 0, - maxZoom: 16, - minHeight: 0, - maxHeight: 80000000, - rasteropacity: 1, - type: 'vector_Boundary', - paint: { - 'line-color': '#AAA4C5', - 'line-width': 3, - 'line-opacity': 0.9 - } + layers: 'qgc:zh_island1', + _layer: 'zh_island1', + layerType: 'line', + minZoom: 0, + maxZoom: 16, + minHeight: 0, + maxHeight: 80000000, + rasteropacity: 1, + type: 'vector_Boundary', + paint: { + 'line-color': '#AAA4C5', + 'line-width': 3, + 'line-opacity': 0.9 + } + }, + // 基础图层 + BaseLayer: { + 'BASEMAP-img': { + key: 'BASEMAP-img', + type: 'raster-dem', + urlType: 'online', + url: + 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}' + + `&token=`, + url_3d: + 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}' + + `&token=`, + _layer: 'img', + visible: false, + maxzoom: 20 }, - // 基础图层 - BaseLayer: { - 'BASEMAP-img': { - type: 'raster-dem', - urlType: 'online', - url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}' + `&token=`, - url_3d: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}' + `&token=`, - _layer: 'img', - visible: false, - maxzoom: 20 - }, - 'BASEMAP-white': { - urlType: 'online', - type: 'raster-dem', - url: `${URL_TerTDT}&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=${mapType}&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=tiles&token= + 'BASEMAP-white': { + key: 'BASEMAP-white', + urlType: 'online', + type: 'raster-dem', + url: `${URL_TerTDT}&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=${mapType}&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=tiles&token= `, - url_3d: URL_TerTDT + `&token=`, - _layer: 'ter', - visible: false, - maxzoom: 14 - } - }, - // 区|县 - county: { - id: 'county', - key: 'county', - urlType: 'gisurl', - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Acounty@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:county&outputFormat=application%2Fjson&token=`, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:county', - _layer: 'county', - rasteropacity: 0.5, - imgUrl: '/zfile/qgc/icons/map-xzXian.png', - minZoom: 8, - maxZoom: 16, - minHeight: 0, - maxHeight: 800000, - type: 'vector', - layerType: 'symbol', - visible: true - }, - //县注记 - county_lable: { - id: 'county_lable', - key: 'county_lable', - urlType: 'gisurl', - // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', - url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:countyAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:countyAno&outputFormat=application%2Fjso&token= + url_3d: URL_TerTDT + `&token=`, + _layer: 'ter', + visible: false, + maxzoom: 14 + } + }, + // 区|县 + county: { + id: 'county', + key: 'county', + urlType: 'gisurl', + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Acounty@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:county&outputFormat=application%2Fjson&token=`, + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:county', + _layer: 'county', + rasteropacity: 0.5, + imgUrl: '/zfile/qgc/icons/map-xzXian.png', + minZoom: 8, + maxZoom: 16, + minHeight: 0, + maxHeight: 800000, + type: 'vector', + layerType: 'symbol', + visible: true + }, + //县注记 + county_lable: { + id: 'county_lable', + key: 'county_lable', + urlType: 'gisurl', + // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', + url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:countyAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:countyAno&outputFormat=application%2Fjso&token= `, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:countyAno', - _layer: 'countyAno', - rasteropacity: 1, - minZoom: 8, - maxZoom: 16, - minHeight: 0, - maxHeight: 800000, - type: 'wms', - layerType: 'symbol', - visible: true - }, + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:countyAno', + _layer: 'countyAno', + rasteropacity: 1, + minZoom: 8, + maxZoom: 16, + minHeight: 0, + maxHeight: 800000, + type: 'wms', + layerType: 'symbol', + visible: true + }, - // 市 - city: { - id: 'city', - key: 'city', - urlType: 'gisurl', - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Acity@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:city&outputFormat=application%2Fjson&token=`, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:city', - _layer: 'city', - rasteropacity: 0.5, - imgUrl: '/zfile/qgc/icons/map-xzShi.png', - minZoom: 5, - maxZoom: 8, - minHeight: 800000, - maxHeight: 1200000, - type: 'vector', - layerType: 'symbol', - visible: false - }, - //市注记 - city_lable: { - id: 'city_lable', - key: 'city_lable', - urlType: 'gisurl', - // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', - url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:cityAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:cityAno&outputFormat=application%2Fjson&token= + // 市 + city: { + id: 'city', + key: 'city', + urlType: 'gisurl', + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Acity@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:city&outputFormat=application%2Fjson&token=`, + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:city', + _layer: 'city', + rasteropacity: 0.5, + imgUrl: '/zfile/qgc/icons/map-xzShi.png', + minZoom: 5, + maxZoom: 8, + minHeight: 800000, + maxHeight: 1200000, + type: 'vector', + layerType: 'symbol', + visible: false + }, + //市注记 + city_lable: { + id: 'city_lable', + key: 'city_lable', + urlType: 'gisurl', + // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', + url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:cityAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:cityAno&outputFormat=application%2Fjson&token= `, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:cityAno', - _layer: 'cityAno', - rasteropacity: 1, - minZoom: 5, - maxZoom: 8, - minHeight: 800000, - maxHeight: 1200000, - type: 'wms', - layerType: 'symbol', - visible: true - }, - // 省 - provincial_capital: { - id: 'provincial_capital', - key: 'provincial_capital', - urlType: 'gisurl', - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Aprovincecity@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:provincecity&outputFormat=application%2Fjson&token= + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:cityAno', + _layer: 'cityAno', + rasteropacity: 1, + minZoom: 5, + maxZoom: 8, + minHeight: 800000, + maxHeight: 1200000, + type: 'wms', + layerType: 'symbol', + visible: true + }, + // 省 + provincial_capital: { + id: 'provincial_capital', + key: 'provincial_capital', + urlType: 'gisurl', + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Aprovincecity@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:provincecity&outputFormat=application%2Fjson&token= `, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:provincecity', - _layer: 'provincecity', - rasteropacity: 0.5, - imgUrl: '/zfile/qgc/icons/map-xzSheng.png', - visible: true, - minZoom: 0, - maxZoom: 5, - minHeight: 1200000, - maxHeight: 99999999999, - type: 'vector', - layerType: 'symbol' - }, - //省注记 - province_lable: { - id: 'province_lable', - key: 'province_lable', - urlType: 'gisurl', - // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', - url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:provincecityAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:provincecityAno&outputFormat=application%2Fjson&token= + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:provincecity', + _layer: 'provincecity', + rasteropacity: 0.5, + imgUrl: '/zfile/qgc/icons/map-xzSheng.png', + visible: true, + minZoom: 0, + maxZoom: 5, + minHeight: 1200000, + maxHeight: 99999999999, + type: 'vector', + layerType: 'symbol' + }, + //省注记 + province_lable: { + id: 'province_lable', + key: 'province_lable', + urlType: 'gisurl', + // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', + url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:provincecityAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:provincecityAno&outputFormat=application%2Fjson&token= `, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:provincecityAno', - _layer: 'provinceAno', - rasteropacity: 0.5, - minZoom: 0, - maxZoom: 5, - minHeight: 1200000, - maxHeight: 99999999999, - type: 'wms', - layerType: 'symbol', - visible: true - }, - baseImageLayerUrl: { - id: 'BaseLayer', - key: 'BaseLayer', - urlType: 'online', - url: 'http://t{s}.tianditu.gov.cn/img_w/wmts?tk=88735d6d9bbd5930f1b1c8b8df72e762&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}' - }, - WhiteBaseLayerUrl: { - id: 'BaseLayer', - key: 'BaseLayer', - urlType: 'online', - url: `https://t0.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=e6372a5333c4bac9b9ef6097453c3cd6&token= + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:provincecityAno', + _layer: 'provinceAno', + rasteropacity: 0.5, + minZoom: 0, + maxZoom: 5, + minHeight: 1200000, + maxHeight: 99999999999, + type: 'wms', + layerType: 'symbol', + visible: true + }, + baseImageLayerUrl: { + id: 'BaseLayer', + key: 'BaseLayer', + urlType: 'online', + url: 'http://t{s}.tianditu.gov.cn/img_w/wmts?tk=88735d6d9bbd5930f1b1c8b8df72e762&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}' + }, + WhiteBaseLayerUrl: { + id: 'BaseLayer', + key: 'BaseLayer', + urlType: 'online', + url: `https://t0.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=e6372a5333c4bac9b9ef6097453c3cd6&token= ` - }, + }, - /** - * 电站基地 - */ - hydropBase: { - id: 'hydropBase', - key: 'hydropBase', - urlType: 'gisurl', - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3AstationEra1117@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:stationEra1117&maxFeatures=50&outputFormat=application/json&token= + /** + * 电站基地 + */ + hydropBase: { + id: 'hydropBase', + key: 'hydropBase', + urlType: 'gisurl', + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3AstationEra1117@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:stationEra1117&maxFeatures=50&outputFormat=application/json&token= `, - url_3d: '/geoserver/qgc/wms', - _layer: 'stationEra1117', - layers: 'qgc:stationEra1117', - rasteropacity: 0.5, - visible: true, - minZoom: 0, - maxZoom: 20, - type: 'vector', - layerType: 'fill', - paint: { - 'fill-color': '#f0dcda', - 'fill-opacity': 0.8, - 'fill-outline-color': '#dd7065' - } - }, - /** - * 电站基地配置 - */ - powerBaseStationLayerWFSUrl: { - id: 's_hydropBase_wfs', - key: 's_hydropBase_wfs', - urlType: 'gisurl', - url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:stationEra1117&maxFeatures=50&outputFormat=application/json&token= + url_3d: '/geoserver/qgc/wms', + _layer: 'stationEra1117', + layers: 'qgc:stationEra1117', + rasteropacity: 0.5, + visible: true, + minZoom: 0, + maxZoom: 20, + type: 'vector', + layerType: 'fill', + paint: { + 'fill-color': '#f0dcda', + 'fill-opacity': 0.8, + 'fill-outline-color': '#dd7065' + } + }, + /** + * 电站基地配置 + */ + powerBaseStationLayerWFSUrl: { + id: 's_hydropBase_wfs', + key: 's_hydropBase_wfs', + urlType: 'gisurl', + url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:stationEra1117&maxFeatures=50&outputFormat=application/json&token= `, - _layer: 'stationEra1117', - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:stationEra1117', - rasteropacity: 0.5, - visible: true, - minZoom: 0, - maxZoom: 20 - }, + _layer: 'stationEra1117', + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:stationEra1117', + rasteropacity: 0.5, + visible: true, + minZoom: 0, + maxZoom: 20 + }, - /** + /** * 电站基地配置 LM项目 */ - powerBaseStationLayerWFSUrlOfLM: { - id: 's_hydropBase_wfs', - key: 's_hydropBase_wfs', - urlType: 'gisurl', - url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:stationEraLM&maxFeatures=50&outputFormat=application/json&token= + powerBaseStationLayerWFSUrlOfLM: { + id: 's_hydropBase_wfs', + key: 's_hydropBase_wfs', + urlType: 'gisurl', + url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:stationEraLM&maxFeatures=50&outputFormat=application/json&token= `, - _layer: 'stationEraLM', - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:stationEraLM', - rasteropacity: 0.5, - visible: true, - minZoom: 0, - maxZoom: 20 - }, - /** - * 河流连通性分析中河流水系配置 - */ - YLJ_LCJ_LayerWFSUrl: { - id: 'river_riverEvaTemp', - key: 'river_riverEvaTemp', - urlType: 'gisurl', - url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:ylj_lcj&maxFeatures=50&outputFormat=application%2Fjson&token= + _layer: 'stationEraLM', + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:stationEraLM', + rasteropacity: 0.5, + visible: true, + minZoom: 0, + maxZoom: 20 + }, + /** + * 河流连通性分析中河流水系配置 + */ + YLJ_LCJ_LayerWFSUrl: { + id: 'river_riverEvaTemp', + key: 'river_riverEvaTemp', + urlType: 'gisurl', + url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:ylj_lcj&maxFeatures=50&outputFormat=application%2Fjson&token= `, - _layer: 'ylj_lcj', - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:ylj_lcj', - rasteropacity: 0.5, - visible: true, - minZoom: 0, - maxZoom: 20 - }, + _layer: 'ylj_lcj', + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:ylj_lcj', + rasteropacity: 0.5, + visible: true, + minZoom: 0, + maxZoom: 20 + }, - /** - * 水质水温渐变线配置 - */ - LCJ_WaterQuality_line: { - id: 'LCJ_WaterQuality_line', - key: 'LCJ_WaterQuality_line', - urlType: 'gisurl', - url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:lcj_waterquality_line&maxFeatures=50&outputFormat=application%2Fjson&token= + /** + * 水质水温渐变线配置 + */ + LCJ_WaterQuality_line: { + id: 'LCJ_WaterQuality_line', + key: 'LCJ_WaterQuality_line', + urlType: 'gisurl', + url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:lcj_waterquality_line&maxFeatures=50&outputFormat=application%2Fjson&token= `, - _layer: 'lcj_waterquality_line', - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:lcj_waterquality_line', - rasteropacity: 0.5, - visible: true, - minZoom: 0, - maxZoom: 20 - }, + _layer: 'lcj_waterquality_line', + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:lcj_waterquality_line', + rasteropacity: 0.5, + visible: true, + minZoom: 0, + maxZoom: 20 + }, - /** - * 全国乡镇名称 - */ - NationalTownships: { - id: 'NationalTownships', - key: 'NationalTownships', - layerType: 'symbol', - isShowLabel: true, - urlType: 'gisurl', - url: `/geoserver/gwc/service/tms/1.0.0/qgc%3ANationalTownships@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf?token=`, - _layer: 'NationalTownships', - layers: 'qgc:NationalTownships', - visible: true, - minZoom: 10.5, - maxZoom: 18, - isOnlyAno: true, - type: 'vector', - layout_text: { - 'text-field': ['get', 'NAME'], - 'text-font': ['Open Sans Bold'], - 'text-size': 16, - 'text-anchor': 'top', - 'text-padding': 0, - 'text-max-width': 100, - 'text-ignore-placement': false, - 'text-allow-overlap': false, - visibility: 'visible' - }, - paint_text: { 'text-color': '#404040', 'text-halo-color': '#fff', 'text-halo-width': 2 }, + /** + * 全国乡镇名称 + */ + NationalTownships: { + id: 'NationalTownships', + key: 'NationalTownships', + layerType: 'symbol', + isShowLabel: true, + urlType: 'gisurl', + url: `/geoserver/gwc/service/tms/1.0.0/qgc%3ANationalTownships@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf?token=`, + _layer: 'NationalTownships', + layers: 'qgc:NationalTownships', + visible: true, + minZoom: 10.5, + maxZoom: 18, + isOnlyAno: true, + type: 'vector', + layout_text: { + 'text-field': ['get', 'NAME'], + 'text-font': ['Open Sans Bold'], + 'text-size': 16, + 'text-anchor': 'top', + 'text-padding': 0, + 'text-max-width': 100, + 'text-ignore-placement': false, + 'text-allow-overlap': false, + visibility: 'visible' }, - - /** - * 一级流域 - */ - heliu1: { - id: 'heliu1', - key: 'heliu1', - urlType: 'gisurl', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river1_line&maxFeatures=50&outputFormat=application/json&token= - `, - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Ariver1_line@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - url_3d: '/geoserver/qgc/wms', - _layer: 'river1_line', - layers: 'qgc:river1_line', - rasteropacity: 0.5, - visible: true, - minZoom: 0, - maxZoom: 18, - minHeight: 0, - maxHeight: 99999999999, - type: 'vector', - layerType: 'line', - paint: { - 'line-color': '#00A1E9', - 'line-width': 4, - 'line-opacity': 0.9 - } - }, - //一级河流注记 - heliu1_lable: { - id: 'heliu1_lable', - key: 'heliu1_lable', - urlType: 'gisurl', - // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', - url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:river1_lineAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river1_lineAno&outputFormat=application%2Fjson&token= - `, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:river1_lineAno', - _layer: 'river1_lineAno', - rasteropacity: 1, - minZoom: 0, - maxZoom: 18, - minHeight: 0, - maxHeight: 99999999999, - type: 'wms', - layerType: 'symbol', - visible: true - }, - - /** - * 二级流域 - */ - heliu2: { - id: 'heliu2', - key: 'heliu2', - urlType: 'gisurl', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river2_line&maxFeatures=50&outputFormat=application/json&token= - `, - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Ariver2_line@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - url_3d: '/geoserver/qgc/wms', - _layer: 'river2_line', - layers: 'qgc:river2_line', - lineWidth: 2, - rasteropacity: 0.5, - visible: false, - minZoom: 4, - maxZoom: 18, - minHeight: 0, - maxHeight: 1200000, - type: 'vector', - layerType: 'line', - paint: { - 'line-color': '#00A1E9', - 'line-width': 3, - 'line-opacity': 0.9 - } - }, - //二级河流注记 - heliu2_lable: { - id: 'heliu2_lable', - key: 'heliu2_lable', - urlType: 'gisurl', - // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', - url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:river2_lineAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river2_lineAno&outputFormat=application%2Fjson&token= - `, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:river2_lineAno', - _layer: 'river2_lineAno', - rasteropacity: 1, - minZoom: 4, - maxZoom: 18, - minHeight: 0, - maxHeight: 1200000, - type: 'wms', - layerType: 'symbol', - visible: true - }, - /** - * 三级流域 - */ - heliu3: { - id: 'heliu3', - key: 'heliu3', - urlType: 'gisurl', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river3_line&maxFeatures=50&outputFormat=application/json&token= - `, - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Ariver3_line@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - url_3d: '/geoserver/qgc/wms', - _layer: 'river3_line', - layers: 'qgc:river3_line', - lineWidth: 1, - rasteropacity: 0.5, - visible: false, - minZoom: 6, - maxZoom: 18, - minHeight: 0, - maxHeight: 800000, - type: 'vector', - layerType: 'line', - paint: { - 'line-color': '#00A1E9', - 'line-width': 2, - 'line-opacity': 0.9 - } - }, - //三级河流注记 - heliu3_lable: { - id: 'heliu3_lable', - key: 'heliu3_lable', - urlType: 'gisurl', - // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', - url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:river3_lineAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river3_lineAno&outputFormat=application%2Fjson&token= - `, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:river3_lineAno', - _layer: 'river3_lineAno', - rasteropacity: 1, - minZoom: 6, - maxZoom: 18, - minHeight: 0, - maxHeight: 800000, - type: 'wms', - layerType: 'symbol', - visible: true - }, - /** - * 四级流域 - */ - heliu4: { - id: 'heliu4', - key: 'heliu4', - urlType: 'gisurl', - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Ariver4_line@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - url_3d: '/geoserver/qgc/wms', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river4_line&maxFeatures=8000&outputFormat=application%2Fjson&token= - `, - _layer: 'river4_line', - layers: 'qgc:river4_line', - visible: false, - minZoom: 8, - maxZoom: 18, - minHeight: 0, - maxHeight: 800000, - rasteropacity: 1, - type: 'vector', - layerType: 'line', - paint: { - 'line-color': '#00A1E9', - 'line-width': 1, - 'line-opacity': 0.9 - } - }, - //四级河流注记 - heliu4_lable: { - id: 'heliu4_lable', - key: 'heliu4_lable', - urlType: 'gisurl', - // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', - url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:river4_lineAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river4_lineAno&outputFormat=application%2Fjson&token= - `, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:river4_lineAno', - _layer: 'river4_lineAno', - rasteropacity: 1, - minZoom: 8, - maxZoom: 18, - minHeight: 0, - maxHeight: 800000, - type: 'wms', - layerType: 'symbol', - - visible: true - }, - /** - * 五级流域 - 水质等级图层 - */ - heliu5: { - id: 'heliu5', - key: 'heliu5', - urlType: 'gisurl', - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Ariver5_line@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - url_3d: '/geoserver/qgc/wms', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river5_line&maxFeatures=8000&outputFormat=application%2Fjson&token= - `, - _layer: 'river5_line', - layers: 'qgc:river5_line', - visible: false, - minZoom: 8, - maxZoom: 18, - minHeight: 0, - maxHeight: 800000, - rasteropacity: 1, - type: 'vector', - layerType: 'line', - paint: { - 'line-color': '#00A1E9', - 'line-width': 1, - 'line-opacity': 0.9 - } - }, - //五级河流注记 - heliu5_lable: { - id: 'heliu5_lable', - key: 'heliu5_lable', - urlType: 'gisurl', - // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', - url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:river5_lineAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river5_lineAno&outputFormat=application%2Fjson&token= - `, - url_3d: '/geoserver/qgc/wms', - layers: 'qgc:river5_lineAno', - _layer: 'river5_lineAno', - rasteropacity: 1, - minZoom: 8, - maxZoom: 18, - minHeight: 0, - maxHeight: 800000, - type: 'wms', - layerType: 'symbol', - visible: true - }, - //流域梯级图 - Tertiarybasin: { - id: 'Tertiarybasin', - key: 'Tertiarybasin', - urlType: 'gisurl', - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Anew_LiuYuThrLev@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - url_3d: '/geoserver/qgc/wms', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:new_LiuYuThrLev&outputFormat=application%2Fjson&token= - `, - _layer: 'new_LiuYuThrLev', - layers: 'qgc:new_LiuYuThrLev', - visible: true, - minZoom: 1, - maxZoom: 18, - minHeight: 0, - maxHeight: 800000, - rasteropacity: 0.8, - type: 'vector', - layerType: 'fill' - }, - // //鱼类栖息地 - // fishQxd: { - // id: 'fishQxd', - // key: 'fishQxd', - // urlType: 'gisurl', - // url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Afish_qxd@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - // url_3d: '/geoserver/qgc/wms', - // geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:fish_qxd&outputFormat=application%2Fjson&token= - // `, - // _layer: 'fish_qxd', - // layers: 'qgc:fish_qxd', - // visible: true, - // minZoom: 0, - // maxZoom: 18, - // minHeight: 0, - // maxHeight: 80000000, - // rasteropacity: 0.9, - // type: 'vector', - // layerType: 'line', - // lineWidth: 2, - // paint: { - // 'line-color': '#A21C83', - // 'line-width': 4, - // 'line-opacity': 1 - // } - // }, - /** - * 水功能分区 - */ - WaterFunctionPartition: { - id: 'WaterFunctionPartition', - key: 'WaterFunctionPartition', - urlType: 'gisurl', - url: '/geoserver/gwc/service/tms/1.0.0/qgc%3AGNQ@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', - url_3d: '/geoserver/qgc/wms', - geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:GNQ&outputFormat=application%2Fjson&token=`, - _layer: 'GNQ', - layers: 'qgc:GNQ', - visible: true, - minZoom: 0, - maxZoom: 18, - minHeight: 0, - maxHeight: 8000000, - rasteropacity: 0.9, - type: 'vector', - layerType: 'line', - lineWidth: 2, - paint: { - 'line-color': '#A21C83', - 'line-width': 3, - 'line-opacity': 0 - } + paint_text: { + 'text-color': '#404040', + 'text-halo-color': '#fff', + 'text-halo-width': 2 } -} + }, + + /** + * 一级流域 + */ + heliu1: { + id: 'heliu1', + key: 'heliu1', + urlType: 'gisurl', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river1_line&maxFeatures=50&outputFormat=application/json&token= + `, + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Ariver1_line@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + url_3d: '/geoserver/qgc/wms', + _layer: 'river1_line', + layers: 'qgc:river1_line', + rasteropacity: 0.5, + visible: true, + minZoom: 0, + maxZoom: 18, + minHeight: 0, + maxHeight: 99999999999, + type: 'vector', + layerType: 'line', + paint: { + 'line-color': '#00A1E9', + 'line-width': 4, + 'line-opacity': 0.9 + } + }, + //一级河流注记 + heliu1_lable: { + id: 'heliu1_lable', + key: 'heliu1_lable', + urlType: 'gisurl', + // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', + url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:river1_lineAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river1_lineAno&outputFormat=application%2Fjson&token= + `, + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:river1_lineAno', + _layer: 'river1_lineAno', + rasteropacity: 1, + minZoom: 0, + maxZoom: 18, + minHeight: 0, + maxHeight: 99999999999, + type: 'wms', + layerType: 'symbol', + visible: true + }, + + /** + * 二级流域 + */ + heliu2: { + id: 'heliu2', + key: 'heliu2', + urlType: 'gisurl', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river2_line&maxFeatures=50&outputFormat=application/json&token= + `, + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Ariver2_line@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + url_3d: '/geoserver/qgc/wms', + _layer: 'river2_line', + layers: 'qgc:river2_line', + lineWidth: 2, + rasteropacity: 0.5, + visible: false, + minZoom: 4, + maxZoom: 18, + minHeight: 0, + maxHeight: 1200000, + type: 'vector', + layerType: 'line', + paint: { + 'line-color': '#00A1E9', + 'line-width': 3, + 'line-opacity': 0.9 + } + }, + //二级河流注记 + heliu2_lable: { + id: 'heliu2_lable', + key: 'heliu2_lable', + urlType: 'gisurl', + // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', + url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:river2_lineAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river2_lineAno&outputFormat=application%2Fjson&token= + `, + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:river2_lineAno', + _layer: 'river2_lineAno', + rasteropacity: 1, + minZoom: 4, + maxZoom: 18, + minHeight: 0, + maxHeight: 1200000, + type: 'wms', + layerType: 'symbol', + visible: true + }, + /** + * 三级流域 + */ + heliu3: { + id: 'heliu3', + key: 'heliu3', + urlType: 'gisurl', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river3_line&maxFeatures=50&outputFormat=application/json&token= + `, + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Ariver3_line@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + url_3d: '/geoserver/qgc/wms', + _layer: 'river3_line', + layers: 'qgc:river3_line', + lineWidth: 1, + rasteropacity: 0.5, + visible: false, + minZoom: 6, + maxZoom: 18, + minHeight: 0, + maxHeight: 800000, + type: 'vector', + layerType: 'line', + paint: { + 'line-color': '#00A1E9', + 'line-width': 2, + 'line-opacity': 0.9 + } + }, + //三级河流注记 + heliu3_lable: { + id: 'heliu3_lable', + key: 'heliu3_lable', + urlType: 'gisurl', + // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', + url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:river3_lineAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river3_lineAno&outputFormat=application%2Fjson&token= + `, + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:river3_lineAno', + _layer: 'river3_lineAno', + rasteropacity: 1, + minZoom: 6, + maxZoom: 18, + minHeight: 0, + maxHeight: 800000, + type: 'wms', + layerType: 'symbol', + visible: true + }, + /** + * 四级流域 + */ + heliu4: { + id: 'heliu4', + key: 'heliu4', + urlType: 'gisurl', + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Ariver4_line@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + url_3d: '/geoserver/qgc/wms', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river4_line&maxFeatures=8000&outputFormat=application%2Fjson&token= + `, + _layer: 'river4_line', + layers: 'qgc:river4_line', + visible: false, + minZoom: 8, + maxZoom: 18, + minHeight: 0, + maxHeight: 800000, + rasteropacity: 1, + type: 'vector', + layerType: 'line', + paint: { + 'line-color': '#00A1E9', + 'line-width': 1, + 'line-opacity': 0.9 + } + }, + //四级河流注记 + heliu4_lable: { + id: 'heliu4_lable', + key: 'heliu4_lable', + urlType: 'gisurl', + // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', + url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:river4_lineAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river4_lineAno&outputFormat=application%2Fjson&token= + `, + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:river4_lineAno', + _layer: 'river4_lineAno', + rasteropacity: 1, + minZoom: 8, + maxZoom: 18, + minHeight: 0, + maxHeight: 800000, + type: 'wms', + layerType: 'symbol', + + visible: true + }, + /** + * 五级流域 - 水质等级图层 + */ + heliu5: { + id: 'heliu5', + key: 'heliu5', + urlType: 'gisurl', + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Ariver5_line@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + url_3d: '/geoserver/qgc/wms', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river5_line&maxFeatures=8000&outputFormat=application%2Fjson&token= + `, + _layer: 'river5_line', + layers: 'qgc:river5_line', + visible: false, + minZoom: 8, + maxZoom: 18, + minHeight: 0, + maxHeight: 800000, + rasteropacity: 1, + type: 'vector', + layerType: 'line', + paint: { + 'line-color': '#00A1E9', + 'line-width': 1, + 'line-opacity': 0.9 + } + }, + //五级河流注记 + heliu5_lable: { + id: 'heliu5_lable', + key: 'heliu5_lable', + urlType: 'gisurl', + // url: this.gisServers.gisurl + '/geoserver/qgc/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&STYLES&LAYERS=qgc%3Aprovinceline&exceptions=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A3857&WIDTH=768&HEIGHT=620&bbox={bbox-epsg-3857}', + url: '/geoserver/qgc/wms?service=WMS&version=1.1.0&request=GetMap&layers=qgc:river5_lineAno&styles=&bbox={bbox-epsg-3857}&width=768&height=620&srs=EPSG:3857&format=image%2Fpng&TRANSPARENT=true', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:river5_lineAno&outputFormat=application%2Fjson&token= + `, + url_3d: '/geoserver/qgc/wms', + layers: 'qgc:river5_lineAno', + _layer: 'river5_lineAno', + rasteropacity: 1, + minZoom: 8, + maxZoom: 18, + minHeight: 0, + maxHeight: 800000, + type: 'wms', + layerType: 'symbol', + visible: true + }, + //流域梯级图 + Tertiarybasin: { + id: 'Tertiarybasin', + key: 'Tertiarybasin', + urlType: 'gisurl', + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Anew_LiuYuThrLev@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + url_3d: '/geoserver/qgc/wms', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:new_LiuYuThrLev&outputFormat=application%2Fjson&token= + `, + _layer: 'new_LiuYuThrLev', + layers: 'qgc:new_LiuYuThrLev', + visible: true, + minZoom: 1, + maxZoom: 18, + minHeight: 0, + maxHeight: 800000, + rasteropacity: 0.8, + type: 'vector', + layerType: 'fill' + }, + // //鱼类栖息地 + // fishQxd: { + // id: 'fishQxd', + // key: 'fishQxd', + // urlType: 'gisurl', + // url: '/geoserver/gwc/service/tms/1.0.0/qgc%3Afish_qxd@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + // url_3d: '/geoserver/qgc/wms', + // geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:fish_qxd&outputFormat=application%2Fjson&token= + // `, + // _layer: 'fish_qxd', + // layers: 'qgc:fish_qxd', + // visible: true, + // minZoom: 0, + // maxZoom: 18, + // minHeight: 0, + // maxHeight: 80000000, + // rasteropacity: 0.9, + // type: 'vector', + // layerType: 'line', + // lineWidth: 2, + // paint: { + // 'line-color': '#A21C83', + // 'line-width': 4, + // 'line-opacity': 1 + // } + // }, + /** + * 水功能分区 + */ + WaterFunctionPartition: { + id: 'WaterFunctionPartition', + key: 'WaterFunctionPartition', + urlType: 'gisurl', + url: '/geoserver/gwc/service/tms/1.0.0/qgc%3AGNQ@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf', + url_3d: '/geoserver/qgc/wms', + geojson_url: `/geoserver/qgc/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=qgc:GNQ&outputFormat=application%2Fjson&token=`, + _layer: 'GNQ', + layers: 'qgc:GNQ', + visible: true, + minZoom: 0, + maxZoom: 18, + minHeight: 0, + maxHeight: 8000000, + rasteropacity: 0.9, + type: 'vector', + layerType: 'line', + lineWidth: 2, + paint: { + 'line-color': '#A21C83', + 'line-width': 3, + 'line-opacity': 0 + } + } +}; /** * 获取Gis图层配置 @@ -746,4 +756,4 @@ export const servers: Record | Record = { // } // console.warn(`The gis config which key is ${key} not exist!`) // return null -// } \ No newline at end of file +// } diff --git a/frontend/src/components/iconDiv/index.scss b/frontend/src/components/iconDiv/index.scss deleted file mode 100644 index 707e3701..00000000 --- a/frontend/src/components/iconDiv/index.scss +++ /dev/null @@ -1,203 +0,0 @@ -.map-tooltip { - height: auto; - color: rgba(255, 255, 255, 0.85); - text-align: center; - position: relative; - padding: 24px 0 25px; - // width: 279px; - width: 260px; - - &::after { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - height: 24px; - background: url(@/assets/images/mapTip/top@260.png) center no-repeat; - filter: opacity(75%); - } - - &::before { - content: ''; - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 25px; - background: url(@/assets/images/mapTip/bottom@260.png) center no-repeat; - filter: opacity(75%); - } - - &-box { - padding: 0 12px; - &::before { - content: ''; - position: absolute; - top: 24px; - bottom: 25px; - left: 0; - right: 0; - z-index: -1; - background: url(@/assets/images/mapTip/center@260.png) repeat-y; - filter: opacity(75%); - } - } - - &-title { - font-size: 16px; - font-weight: 500; - } - - &-list { - font-size: 14px; - line-height: 1.5; - - > li { - display: flex; - text-align: left; - - .__label { - flex: 0 0 100px; - width: 100px; - text-align: right; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - .__warn { - color: #ff4d4f; - } - } - } - - &-content { - margin-top: 10px; - border-top: 1px dashed #12aaeb; - padding: 10px 0; - margin: 10px 0 0; - &.__noborder { - border: none; - margin-top: 6px; - } - &.__small { - font-size: 12px; - } - } - - &-sub { - margin: 0; - padding: 10px 0 0; - text-align: center; - } - &-sub1 { - text-align: center; - position: relative; - height: 1px; - border-bottom: 1px dashed #12aaeb; - margin-top: 16px; - .__content { - position: absolute; - top: -9px; - left: 50%; - transform: translateX(-50%); - background-color: rgb(88 110 134); - padding: 0 6px; - font-size: 12px; - border-radius: 3px; - white-space: nowrap; - } - } - &.map-tooltip-small { - width: 175px; - padding: 18px 0 18px; - &::after { - background-image: url(@/assets/images/mapTip/top@175.png); - height: 18px; - filter: opacity(75%); - } - &::before { - background-image: url(@/assets/images/mapTip/bottom@175.png); - height: 18px; - filter: opacity(75%); - } - .map-tooltip-box { - padding: 0 10px; - &::before { - content: ''; - position: absolute; - top: 18px; - bottom: 18px; - left: 0; - right: 0; - z-index: -1; - background-image: url(@/assets/images/mapTip/center@175.png); - filter: opacity(75%); - } - } - .map-tooltip-list { - > li { - .__label { - flex: 0 0 80px; - width: 80px; - } - } - } - } - - &.map-tooltip-middle { - width: 215px; - padding: 18px 0 18px; - &::after { - background-image: url(@/assets/images/mapTip/top@215.png); - height: 18px; - filter: opacity(75%); - } - &::before { - background-image: url(@/assets/images/mapTip/bottom@215.png); - height: 18px; - filter: opacity(75%); - } - .map-tooltip-box { - padding: 0 10px; - &::before { - content: ''; - position: absolute; - top: 18px; - bottom: 18px; - left: 0; - right: 0; - z-index: -1; - background-image: url(@/assets/images/mapTip/center@215.png); - filter: opacity(75%); - } - } - .map-tooltip-list { - > li { - .__label { - flex: 0 0 110px; - width: 110px; - } - } - &.__list2 { - > li { - .__label { - flex: 0 0 90px; - width: 90px; - } - } - } - } - } - - .map-waterQuality-subtitle { - margin-top: 10px; - border: 1px solid rgba(77, 129, 167); - border-bottom: none; - - .map-waterQuality-leftType, - .map-waterQuality-rightType { - width: 50%; - } - } -} diff --git a/frontend/src/components/iconDiv/index.vue b/frontend/src/components/iconDiv/index.vue deleted file mode 100644 index 0a2cb441..00000000 --- a/frontend/src/components/iconDiv/index.vue +++ /dev/null @@ -1,1770 +0,0 @@ - - - - - diff --git a/frontend/src/components/mapController/LayerController.vue b/frontend/src/components/mapController/LayerController.vue index 794d2073..c40bb637 100644 --- a/frontend/src/components/mapController/LayerController.vue +++ b/frontend/src/components/mapController/LayerController.vue @@ -1,98 +1,265 @@ - diff --git a/frontend/src/components/mapController/index.vue b/frontend/src/components/mapController/index.vue index f67faea3..e164eb3f 100644 --- a/frontend/src/components/mapController/index.vue +++ b/frontend/src/components/mapController/index.vue @@ -8,7 +8,11 @@ :key="child.key" > -
+
@@ -16,10 +20,10 @@
diff --git a/frontend/src/docs/地图加载逻辑.md b/frontend/src/docs/地图加载逻辑.md new file mode 100644 index 00000000..918ec920 --- /dev/null +++ b/frontend/src/docs/地图加载逻辑.md @@ -0,0 +1,260 @@ +# 地图图层、图例和锚点加载逻辑 + +## 一、整体流程 + +``` +GisView.vue (onMounted) + │ + ├─> 1. 获取图层配置 (mapStore.setLayerData) + │ + ├─> 2. 收集初始选中的图层 keys (collectCheckedKeys) + │ + ├─> 3. 加载所有锚点数据 (mapStore.loadAllLayerData) + │ │ + │ ├─> 并行加载选中的图层数据 (优先) + │ ├─> 后台加载未选中的图层数据 + │ └─> 数据缓存到 pointDataCache + │ + └─> 4. 更新图例和图层显隐 (mapStore.updateLayerData) + │ + ├─> 更新图层 checked 状态 + ├─> 获取并排序图例数据 (getlegendData) + ├─> 处理环保设施图例 (fp_point/eq_point 联动) + └─> 控制锚点显示/隐藏 (setLegendPointVisible) +``` + +## 二、核心组件和 Store + +### 2.1 组件 +- **GisView.vue**: 主视图,负责初始化加载流程 +- **LayerController.vue**: 图层树控制器,处理图层勾选交互 +- **mapLegend/index.vue**: 图例显示组件 + +### 2.2 Store (map.ts) +- `layerData`: 图层树配置数据 +- `legendData`: 过滤排序后的图例数据 +- `legendDataOriginal`: 原始图例数据 +- `legendDataSelected`: 选中的图例数据 +- `legendDataMap`: 图例数据映射 (nameEn -> 图例项) +- `pointDataCache`: 锚点数据缓存 +- `checkedLayerKeys`: 选中的图层 key 列表 + +## 三、初始化加载流程 (GisView.vue) + +### 3.1 获取图层配置 +```typescript +const layerRes = await mapStore.getLayerConfig(); +mapStore.setLayerData(limitedLayers); // 设置图层数据 +``` + +### 3.2 收集初始选中的 keys +```typescript +const checkedKeys = collectCheckedKeys(limitedLayers); +``` + +### 3.3 加载锚点数据 +```typescript +await mapStore.loadAllLayerData(limitedLayers, checkedKeys); +``` + +### 3.4 更新图例和图层显隐 +```typescript +await mapStore.updateLayerData(checkedKeys, true); // isInit = true +``` + +## 四、锚点数据加载 (loadAllLayerData) + +### 4.1 处理逻辑 +1. 递归遍历所有图层配置 +2. 区分**选中的图层**和**未选中的图层** +3. 选中的图层**优先加载**,阻塞等待 +4. 未选中的图层**后台加载**,不阻塞 UI + +### 4.2 数据缓存 +- 所有加载的数据都会缓存到 `pointDataCache` +- 已缓存的数据不会重复加载 +- 即使图层未选中,也会加载数据并缓存,只是隐藏不显示 + +### 4.3 加载完成后 +1. 调用 `setSelectedLegendData()` 设置选中图例 +2. 未选中图层继续后台加载,完成后打印日志 + +## 五、图层勾选流程 (LayerController.vue) + +### 5.1 用户勾选图层 +``` +onCheck(v, e) + │ + ├─> 处理互斥逻辑 + │ ├─> 珍稀鱼类 vs 沿程鱼类 + │ ├─> 视频监控 vs AI视频监控 + │ └─> 环保设施 vs 环保设施在建 + │ + ├─> checkedKeys.value = checkKeys + │ + └─> broadcast(checkKeys) + │ + └─> mapStore.updateLayerData(v) +``` + +### 5.2 互斥图层处理 +- `rare_fish_point` 与 `fish_along_point` 互斥 +- `stinfo_video_point` 与 `stinfo_ai_video_point` 互斥 +- `facilities` 与 `facilities_built` 互斥 + +## 六、图例数据更新 (updateLayerData) + +### 6.1 处理流程 +```typescript +updateLayerData(checkKeys, isInit = false) + │ + ├─> 处理互斥图层 (stinfo_video_point vs stinfo_ai_video_point) + │ + ├─> 更新图层 checked 状态 (递归遍历 layerData) + │ 记录 newlyChecked 和 newlyUnchecked + │ + ├─> 获取有效 keys (过滤掉 '-', 'customBaseLayer', 'powerBaseStation') + │ + ├─> 获取图例数据 (getlegendData) + │ 过滤掉 name === '地图' 的项 + │ 递归匹配 layerCode + │ 去重 (根据 parent name) + │ + ├─> 处理环保设施图例联动 + │ 勾选 fp_point 或 eq_point → 自动添加环保设施图例 + │ 取消勾选 → 自动移除环保设施图例 + │ + ├─> 按 orderIndex 排序 + │ + ├─> 更新 legendDataSelected + │ + └─> 控制锚点显示/隐藏 + isInit = true: 处理所有图层 + isInit = false: 只处理变化的图层 +``` + +### 6.2 环保设施图例联动 +```typescript +const triggerKeys = ['fp_point', 'eq_point']; +const hasTriggerLayer = triggerKeys.some(key => checkKeys.includes(key)); + +if (hasTriggerLayer) { + // 添加环保设施图例 +} else { + // 移除环保设施图例 +} +``` + +## 七、图例点击处理 (mapLegend) + +### 7.1 单个图例项点击 +```typescript +legendItemClick(item) + │ + ├─> 切换 item.checked (0 ↔ 1) + │ + ├─> 更新 legendDataMap + │ + └─> 控制锚点显示/隐藏 + pointMap 图层 → setLegendPointVisible + GISMap 图层 → controlBaseLayerTreeShowAndHidden +``` + +### 7.2 groupTitle 点击 (全选/取消全选) +```typescript +toggleGroup(group) + │ + ├─> 获取组内所有叶子节点 (getAllLeafItems) + │ + ├─> 判断是否有任何选中 → 决定目标是全选还是取消全选 + │ + └─> 遍历所有叶子节点,切换 checked 状态 + 跳过 parentName === '环保设施' 的项 + 跳过 canBeChecked === 0 的项 +``` + +### 7.3 groupTitle 变灰判断 +```typescript +isGroupAllUnchecked(group) + │ + └─> 所有叶子节点 checked === 0 → 返回 true (变灰) +``` + +## 八、锚点显示/隐藏控制 + +### 8.1 pointMap 图层 +```typescript +setLegendPointVisible(layerKey, nameEn, visible) + │ + ├─> 隐藏所有锚点 (setLegendPointVisible(key, '', false)) + │ + └─> 显示选中的锚点 (遍历 legendData,checked === 1 的项) +``` + +### 8.2 GISMap 图层 +```typescript +controlBaseLayerTreeShowAndHidden(layerKey, configId, visible) +``` + +## 九、关键数据结构 + +### 9.1 图层配置 (mapLayerVos) +```typescript +{ + key: 'eng_point', + title: '水电站', + type: 'pointMap', // 或 'GISMap' + checked: 1, // 0: 未选中, 1: 选中 + url: '/api/xxx', + params: {}, + children: [] // 子图层 +} +``` + +### 9.2 图例数据 +```typescript +{ + name: '已建', + nameEn: 'large_eng_built', + layerCode: 'eng_point', + icon: 'xxx.png', + checked: 1, // 0: 未选中, 1: 选中 + canBeChecked: 1, // 0: 不可勾选, 1: 可勾选 + childrenList: [] // 子图例 +} +``` + +### 9.3 锚点数据 +```typescript +{ + stcd: 'xxx', // 站点编码 + stnm: '三峡电站', // 站点名称 + sttpMap: 'ENG', // 类型编码 + anchoPointState: 'large_eng_built', // 状态 + iconCode: 'xxx.png', // 图标编码 + lng: 111.11, // 经度 + lat: 33.33, // 纬度 +} +``` + +## 十、加载时序图 + +``` +时间轴 + │ + ├─1─┤ setLayerData() - 设置图层配置 + │ + ├─2─┤ loadAllLayerData() 开始 + │ │ + │ ├─3─┤ 选中图层数据请求 (阻塞) + │ │ │ + │ │ └─4─┤ 数据返回,添加到地图,缓存 + │ │ + │ ├─5─┤ setSelectedLegendData() - 设置图例 + │ │ + │ └─6─┤ 未选中图层数据请求 (后台,不阻塞) + │ │ + │ └─7─┤ 数据返回,添加到地图,缓存 + │ + └─8─┤ updateLayerData() - 更新图层显隐,控制锚点显示 +``` diff --git a/frontend/src/modules/chuixiangshuiwenChangeMod/index.vue b/frontend/src/modules/chuixiangshuiwenChangeMod/index.vue index 610f38c2..fdf9911d 100644 --- a/frontend/src/modules/chuixiangshuiwenChangeMod/index.vue +++ b/frontend/src/modules/chuixiangshuiwenChangeMod/index.vue @@ -43,8 +43,8 @@ function chartMax( targetTickCount: number, max: number, min: number, - round: boolean = true, - base: number = 0 + round = true, + base = 0 ): { min: number; max: number; scale: number } { const range = max - min; diff --git a/frontend/src/modules/jidiSelectorMod.vue b/frontend/src/modules/jidiSelectorMod.vue index c879b81e..79b7984c 100644 --- a/frontend/src/modules/jidiSelectorMod.vue +++ b/frontend/src/modules/jidiSelectorMod.vue @@ -1,13 +1,13 @@ @@ -32,7 +32,10 @@ onMounted(() => {});
@@ -44,7 +47,7 @@ onMounted(() => {});