地图锚点图层图例添加,以及放大显示功能添加
@ -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
|
||||
@ -96,7 +96,7 @@ export function getStationList(params:any): AxiosPromise<any[]> {
|
||||
* @param phone 手机号
|
||||
* @param type 验证码类型:1-注册 2-找回密码
|
||||
*/
|
||||
export function sendSmsCode(phone: string, type: number = 1): AxiosPromise<any> {
|
||||
export function sendSmsCode(phone: string, type = 1): AxiosPromise<any> {
|
||||
return request({
|
||||
url: '/sms/sendCode',
|
||||
method: 'post',
|
||||
@ -110,7 +110,7 @@ export function sendSmsCode(phone: string, type: number = 1): AxiosPromise<any>
|
||||
* @param code 验证码
|
||||
* @param type 验证码类型:1-注册 2-找回密码
|
||||
*/
|
||||
export function verifySmsCode(phone: string, code: string, type: number = 1): AxiosPromise<any> {
|
||||
export function verifySmsCode(phone: string, code: string, type = 1): AxiosPromise<any> {
|
||||
return request({
|
||||
url: '/sms/verifyCode',
|
||||
method: 'post',
|
||||
|
||||
21
frontend/src/api/map.ts
Normal file
@ -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
|
||||
});
|
||||
}
|
||||
23
frontend/src/assets/legend/map-dongwujiuzhuzhanZWeijian.svg
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="23px" viewBox="0 0 20 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>map-dongwujiuzhuzhanZWeijian</title>
|
||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="图例备份-4" transform="translate(-513.000000, -134.000000)" fill-rule="nonzero">
|
||||
<g id="编组-9" transform="translate(511.000000, 73.000000)">
|
||||
<g id="编组" transform="translate(0.000000, 60.000000)">
|
||||
<g id="ExtinctionSquadGreen" transform="translate(2.000000, 1.000000)">
|
||||
<path d="M10,0 C15.5228475,0 20,4.48367994 20,10.0145795 C20,14.5981513 16.9251889,18.4625155 12.7285722,19.6518192 C12.0801126,20.2555114 11.512719,20.9434728 11.0416667,21.6982555 L10.4241725,22.6876865 C10.2779707,22.9219506 9.96954214,22.993339 9.73527812,22.8471372 C9.67067972,22.806822 9.6161427,22.7522849 9.57582748,22.6876865 L8.95833333,21.6982555 C8.48728096,20.9434728 7.91988742,20.2555114 7.27176537,19.6511428 C3.07481109,18.4625155 0,14.5981513 0,10.0145795 C0,4.48367994 4.4771525,0 10,0 Z" id="路径" fill="#C1C1C1"></path>
|
||||
<path d="M10,1 C5.02976365,1 1,5.03563882 1,10.0145795 C1,13.9819459 3.58136776,17.4404602 7.28412666,18.6110508 L7.77691051,18.7548749 L7.95375471,18.9197807 C8.56499354,19.489756 9.11007499,20.1266528 9.57875348,20.8184146 L9.80667838,21.1688117 L10,21.478 L10.1933216,21.1688117 C10.6366411,20.4584664 11.1579737,19.8014467 11.7470472,19.210064 L12.0471815,18.9198993 L12.2237777,18.7554947 L12.4559139,18.6897083 C16.2972752,17.6010825 19,14.0740888 19,10.0145795 C19,5.03563882 14.9702364,1 10,1 Z" id="路径" fill="#ABABAB"></path>
|
||||
<g id="编组" transform="translate(4.000000, 3.000000)" fill="#FFFFFF">
|
||||
<g id="路径" transform="translate(0.000000, 0.750000)">
|
||||
<polygon points="10.875 4.5 10.875 11.25 1.125 11.25 1.125 4.5 1.875 4.5 1.875 10.5 10.125 10.5 10.125 4.5"></polygon>
|
||||
<path d="M5.99949383,4.96447889 C6.67450486,4.35550941 7.69047373,4.34769678 8.37336406,4.92716844 L8.49146602,5.03674798 C9.14571049,5.70005088 9.16747093,6.74976529 8.56371984,7.43930899 L8.47321526,7.53528448 L6.39365573,9.594412 C6.19192974,9.79215339 5.87920854,9.80771639 5.66059081,9.64219611 L5.59803369,9.58710862 L3.50898437,7.51703373 C2.82358027,6.82214497 2.83161245,5.70390133 3.5257724,5.01849209 C4.20606465,4.34914721 5.29073738,4.32506093 5.99949383,4.96447889 Z M7.94691339,5.55282003 C7.57613564,5.18761167 6.9994374,5.15126266 6.58749808,5.45179201 L6.50188227,5.52135038 L5.99949201,5.97458791 L5.49710338,5.52134857 C5.08326332,5.14799497 4.44938056,5.1619074 4.05272796,5.55217536 C3.67961282,5.92058695 3.65089103,6.50579436 3.96642977,6.90431163 L4.03931446,6.98670364 L5.99925,8.92875 L7.94682981,7.00103888 C8.32016884,6.63319265 8.34924559,6.04776046 8.0339059,5.64936394 L7.96106138,5.5670035 L7.94691339,5.55282003 Z"></path>
|
||||
<polygon points="0 5.25 6 -4.61860726e-14 12 5.25 11.4921155 5.75788455 6 1.0156924 0.507884548 5.75788455"></polygon>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="23px" viewBox="0 0 20 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>map-dwsjhDieliangmenshiZWeijian</title>
|
||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="图例备份-4" transform="translate(-271.000000, -74.000000)">
|
||||
<g id="map-dieliangmen" transform="translate(269.000000, 73.000000)">
|
||||
<rect id="矩形" x="0" y="0" width="24" height="24"></rect>
|
||||
<path d="M12,1 C17.5228475,1 22,5.48367994 22,11.0145795 C22,15.5981513 18.9251889,19.4625155 14.7285722,20.6518192 C14.0801126,21.2555114 13.512719,21.9434728 13.0416667,22.6982555 L12.4241725,23.6876865 C12.2779707,23.9219506 11.9695421,23.993339 11.7352781,23.8471372 C11.6706797,23.806822 11.6161427,23.7522849 11.5758275,23.6876865 L10.9583333,22.6982555 C10.487281,21.9434728 9.91988742,21.2555114 9.27176537,20.6511428 C5.07481109,19.4625155 2,15.5981513 2,11.0145795 C2,5.48367994 6.4771525,1 12,1 Z" id="路径" fill="#C1C1C1" fill-rule="nonzero"></path>
|
||||
<path d="M12,2 C7.02976365,2 3,6.03563882 3,11.0145795 C3,14.9819459 5.58136776,18.4404602 9.28412666,19.6110508 L9.77691051,19.7548749 L9.95375471,19.9197807 C10.5649935,20.489756 11.110075,21.1266528 11.5787535,21.8184146 L11.8066784,22.1688117 L12,22.478 L12.1933216,22.1688117 C12.6366411,21.4584664 13.1579737,20.8014467 13.7470472,20.210064 L14.0471815,19.9198993 L14.2237777,19.7554947 L14.4559139,19.6897083 C18.2972752,18.6010825 21,15.0740888 21,11.0145795 C21,6.03563882 16.9702364,2 12,2 Z" id="路径" fill="#ABABAB" fill-rule="nonzero"></path>
|
||||
<path d="M14.7811001,10.5551365 C14.5138652,10.5551365 14.2963802,10.766443 14.2963802,11.0291867 L14.2963802,11.8132457 C14.2963802,12.0745982 14.5138638,12.2872959 14.7811001,12.2872959 C15.048335,12.2872959 15.26582,12.0745996 15.26582,11.8132457 L15.26582,11.0291867 C15.26582,10.766443 15.0483364,10.5551365 14.7811001,10.5551365 Z M16.0845832,5.98146365 L11.1023479,5.02502315 C11.0184816,5.00834105 10.9331933,5 10.8479054,5 C10.218196,5 9.72494835,5.46570874 9.72494835,6.06209443 L9.72494835,6.30120489 L8.36176364,6.08989838 C8.28216159,6.07738681 8.20113819,6.07182609 8.12295707,6.07182609 C7.48329742,6.07182609 7,6.47219703 7,7.00324357 L7,14.999536 C7,15.5305825 7.48329742,15.9295637 8.12295707,15.9295637 C8.20113763,15.9295637 8.28073899,15.924003 8.36176364,15.9114914 L9.72636942,15.6987951 L9.72636942,15.9379056 C9.72636942,16.5329001 10.2196171,17 10.8493265,17 C10.9346144,17 11.0199022,16.9916589 11.1023465,16.976367 L16.0859987,16.0185368 C16.606255,15.9184442 17,15.4374428 17,14.9008358 L17,7.09916829 C16.9971571,6.56255988 16.6048326,6.08155937 16.0845762,5.98146731 L16.0845832,5.98146365 Z M8.24093928,15.1691309 C7.97512543,15.2094459 7.76474861,15.1010123 7.76474861,14.9981392 L7.76474861,7.000461 C7.76474861,6.897588 7.9765465,6.7877647 8.23951821,6.82946927 L9.72353006,7.06023828 L9.72353006,14.9383646 L8.24094901,15.1691336 L8.24093928,15.1691309 Z M16.2309965,14.896656 C16.2309965,15.0732082 16.0959574,15.2483707 15.9367529,15.2789542 L10.9531008,16.2367845 C10.9189856,16.2437354 10.883449,16.2465157 10.8479124,16.2465157 C10.6375355,16.2465157 10.491125,16.1186196 10.491125,15.9351158 L10.491125,6.06070476 C10.491125,5.84661731 10.7015018,5.7103812 10.9531008,5.75903608 L15.9381837,6.71686637 C16.0973881,6.74884037 16.2324273,6.92400215 16.2324273,7.09916461 L16.2324273,14.8966614 L16.2309965,14.896656 Z" id="形状" fill="#FFFFFF" fill-rule="nonzero" transform="translate(12.000000, 11.000000) rotate(-90.000000) translate(-12.000000, -11.000000) "></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="23px" viewBox="0 0 20 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>map-dwsjhGeshuimuqiangZWeijian</title>
|
||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="图例备份-4" transform="translate(-271.000000, -130.000000)">
|
||||
<g id="编组-9备份-4" transform="translate(269.000000, 73.000000)">
|
||||
<g id="map-geshuimuqiang" transform="translate(0.000000, 56.000000)">
|
||||
<rect id="矩形" x="0" y="0" width="24" height="24"></rect>
|
||||
<path d="M12,1 C17.5228475,1 22,5.48367994 22,11.0145795 C22,15.5981513 18.9251889,19.4625155 14.7285722,20.6518192 C14.0801126,21.2555114 13.512719,21.9434728 13.0416667,22.6982555 L12.4241725,23.6876865 C12.2779707,23.9219506 11.9695421,23.993339 11.7352781,23.8471372 C11.6706797,23.806822 11.6161427,23.7522849 11.5758275,23.6876865 L10.9583333,22.6982555 C10.487281,21.9434728 9.91988742,21.2555114 9.27176537,20.6511428 C5.07481109,19.4625155 2,15.5981513 2,11.0145795 C2,5.48367994 6.4771525,1 12,1 Z" id="路径" fill="#C1C1C1" fill-rule="nonzero"></path>
|
||||
<path d="M12,2 C7.02976365,2 3,6.03563882 3,11.0145795 C3,14.9819459 5.58136776,18.4404602 9.28412666,19.6110508 L9.77691051,19.7548749 L9.95375471,19.9197807 C10.5649935,20.489756 11.110075,21.1266528 11.5787535,21.8184146 L11.8066784,22.1688117 L12,22.478 L12.1933216,22.1688117 C12.6366411,21.4584664 13.1579737,20.8014467 13.7470472,20.210064 L14.0471815,19.9198993 L14.2237777,19.7554947 L14.4559139,19.6897083 C18.2972752,18.6010825 21,15.0740888 21,11.0145795 C21,6.03563882 16.9702364,2 12,2 Z" id="路径" fill="#ABABAB" fill-rule="nonzero"></path>
|
||||
<path d="M14.6829236,6 C14.8849788,6 15.0487771,6.16398891 15.0487771,6.36627918 L15.0487771,6.73255837 L16.6341461,6.73255837 C16.8225904,6.73256742 16.9802012,6.87588227 16.9982927,7.06367475 L17,7.09883755 L17,14.9011619 C17,15.1034522 16.8362017,15.2674411 16.6341465,15.2674411 L15.0487775,15.2674411 L15.0487775,15.6337203 C15.0487775,15.8223662 14.9056362,15.9801673 14.7180631,15.998289 L14.6829236,16 L7.36585352,16 C7.16379833,16 7,15.8360111 7,15.6337208 L7,6.3662797 C7,6.16398938 7.16379833,6 7.36585351,6 L14.6829236,6 Z M14.3170701,6.73255837 L7.73170701,6.73255837 L7.73170701,15.2674411 L14.3170701,15.2674411 L14.3170701,6.73255837 Z M16.2682926,7.46511674 L15.0487771,7.46511674 L15.0487771,14.5348827 L16.2682926,14.5348827 L16.2682926,7.46511674 Z M12.7785228,10.301827 C12.9365516,10.4045553 12.9908088,10.6106331 12.9038958,10.7779941 L12.8860909,10.8085174 L10.6299981,14.2881696 C10.5212801,14.4586817 10.2950798,14.5086731 10.124767,14.3998281 C9.96414932,14.2971801 9.90912496,14.0882916 9.99829146,13.9196933 L10.0163403,13.88917 L12.2724331,10.4095178 C12.3824826,10.2398641 12.6090663,10.1916492 12.7785228,10.301827 Z M11.8029138,8.10415051 C11.9609427,8.20688016 12.0151999,8.41295798 11.9282868,8.58031896 L11.910482,8.61084226 L9.65438916,12.0904945 C9.5456711,12.2610066 9.31947085,12.3109969 9.14915804,12.2021528 C8.98854035,12.0995048 8.93351598,11.8906163 9.02268249,11.7220169 L9.0407313,11.6914936 L11.2968241,8.2118413 C11.4068737,8.04218763 11.6334574,7.9939727 11.8029138,8.10415051 Z" id="形状结合" fill="#FFFFFF" fill-rule="nonzero"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="23px" viewBox="0 0 20 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>map-dwsjhQianzhidangqiangZWeijian</title>
|
||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="图例备份-4" transform="translate(-271.000000, -102.000000)">
|
||||
<g id="编组-9备份-4" transform="translate(269.000000, 73.000000)">
|
||||
<g id="map-qianzhidangqiang" transform="translate(0.000000, 28.000000)">
|
||||
<rect id="矩形" x="0" y="0" width="24" height="24"></rect>
|
||||
<path d="M12,1 C17.5228475,1 22,5.48367994 22,11.0145795 C22,15.5981513 18.9251889,19.4625155 14.7285722,20.6518192 C14.0801126,21.2555114 13.512719,21.9434728 13.0416667,22.6982555 L12.4241725,23.6876865 C12.2779707,23.9219506 11.9695421,23.993339 11.7352781,23.8471372 C11.6706797,23.806822 11.6161427,23.7522849 11.5758275,23.6876865 L10.9583333,22.6982555 C10.487281,21.9434728 9.91988742,21.2555114 9.27176537,20.6511428 C5.07481109,19.4625155 2,15.5981513 2,11.0145795 C2,5.48367994 6.4771525,1 12,1 Z" id="路径" fill="#C1C1C1" fill-rule="nonzero"></path>
|
||||
<path d="M12,2 C7.02976365,2 3,6.03563882 3,11.0145795 C3,14.9819459 5.58136776,18.4404602 9.28412666,19.6110508 L9.77691051,19.7548749 L9.95375471,19.9197807 C10.5649935,20.489756 11.110075,21.1266528 11.5787535,21.8184146 L11.8066784,22.1688117 L12,22.478 L12.1933216,22.1688117 C12.6366411,21.4584664 13.1579737,20.8014467 13.7470472,20.210064 L14.0471815,19.9198993 L14.2237777,19.7554947 L14.4559139,19.6897083 C18.2972752,18.6010825 21,15.0740888 21,11.0145795 C21,6.03563882 16.9702364,2 12,2 Z" id="路径" fill="#ABABAB" fill-rule="nonzero"></path>
|
||||
<path d="M10.0519815,12.9205132 L7.7118534,12.9205132 L7.72330394,14.2987312 L10.0519828,14.2987312 L10.0519828,15 L7,15 L7,10.1469013 L10.0519815,10.1469013 L10.0519815,8.77366828 L7.72870375,8.77366828 L7.72870375,10.1469013 L7,10.1469013 L7,6 L17,6 L17,8.07937399 L16.29493,8.07937399 L16.29493,6.70579619 L13.9480371,6.70579619 L13.9480759,8.07937399 L17,8.07937399 L17,12.2262753 L16.29493,12.2262753 L16.3021599,10.8530423 L13.9480759,10.8530423 L13.9480759,12.2262753 L17,12.2262753 L17,15 L10.0519828,15 L10.0519815,12.9205132 Z M16.2817281,14.2936887 L16.2817281,12.932528 L10.770252,12.932528 L10.770252,14.2936887 L16.2817281,14.2936887 Z M13.2297466,12.2143147 L13.2297466,10.853154 L7.71827055,10.853154 L7.71827055,12.2143147 L13.2297466,12.2143147 Z M16.2817281,10.1467874 L16.2817281,8.78562666 L10.770252,8.78562666 L10.770252,10.1467874 L16.2817281,10.1467874 Z M13.2297466,8.06741336 L13.2297466,6.70625266 L7.71827055,6.70625266 L7.71827055,8.06741336 L13.2297466,8.06741336 Z" id="形状" fill="#FFFFFF" fill-rule="nonzero"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
16
frontend/src/assets/legend/map-dwsjhQitaZWeijian.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="23px" viewBox="0 0 20 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>map-dwsjhQitaZWeijian</title>
|
||||
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="图例备份-4" transform="translate(-271.000000, -158.000000)">
|
||||
<g id="编组-9备份-4" transform="translate(269.000000, 73.000000)">
|
||||
<g id="map-dwsjhQita" transform="translate(0.000000, 84.000000)">
|
||||
<rect id="矩形" x="0" y="0" width="24" height="24"></rect>
|
||||
<path d="M12,1 C17.5228475,1 22,5.48367994 22,11.0145795 C22,15.5981513 18.9251889,19.4625155 14.7285722,20.6518192 C14.0801126,21.2555114 13.512719,21.9434728 13.0416667,22.6982555 L12.4241725,23.6876865 C12.2779707,23.9219506 11.9695421,23.993339 11.7352781,23.8471372 C11.6706797,23.806822 11.6161427,23.7522849 11.5758275,23.6876865 L10.9583333,22.6982555 C10.487281,21.9434728 9.91988742,21.2555114 9.27176537,20.6511428 C5.07481109,19.4625155 2,15.5981513 2,11.0145795 C2,5.48367994 6.4771525,1 12,1 Z" id="路径" fill="#C1C1C1" fill-rule="nonzero"></path>
|
||||
<path d="M12,2 C7.02976365,2 3,6.03563882 3,11.0145795 C3,14.9819459 5.58136776,18.4404602 9.28412666,19.6110508 L9.77691051,19.7548749 L9.95375471,19.9197807 C10.5649935,20.489756 11.110075,21.1266528 11.5787535,21.8184146 L11.8066784,22.1688117 L12,22.478 L12.1933216,22.1688117 C12.6366411,21.4584664 13.1579737,20.8014467 13.7470472,20.210064 L14.0471815,19.9198993 L14.2237777,19.7554947 L14.4559139,19.6897083 C18.2972752,18.6010825 21,15.0740888 21,11.0145795 C21,6.03563882 16.9702364,2 12,2 Z" id="路径" fill="#ABABAB" fill-rule="nonzero"></path>
|
||||
<path d="M17.3285024,6.28571322 L12.4556195,4.09751195 C12.1661029,3.96749602 11.8340457,3.96749602 11.5445304,4.09751195 L6.67164751,6.28571322 C6.263666,6.46887583 6,6.88024173 6,7.33364584 L6,13.6662796 C6,14.1196838 6.263666,14.5310496 6.67164751,14.7143621 L11.5443805,16.9025633 C11.6891381,16.9675712 11.8445316,17 11.9999251,17 C12.1553185,17 12.310712,16.967421 12.4554696,16.9025633 L17.3283525,14.7143621 C17.736334,14.5310484 18,14.1196825 18,13.6662796 L18,7.33364584 C18,6.88024173 17.736334,6.46887583 17.3283525,6.28556342 L17.3285024,6.28571322 Z M17.1138759,13.6662873 C17.1138759,13.7632736 17.0574498,13.8511015 16.9702998,13.8902871 L12.0975668,16.0784884 C12.0356754,16.1062631 11.9646253,16.1062631 11.9027342,16.0784884 L7.02985136,13.8902871 L7.02985138,13.8902871 C6.94259532,13.8510798 6.88627531,13.7632546 6.88627531,13.6662873 L6.88627531,7.33365346 C6.88627531,7.2366671 6.94270136,7.14883918 7.02985138,7.10965362 L11.9027342,4.92145235 C11.9646257,4.89367765 12.0356758,4.89367765 12.0975668,4.92145235 L16.9702998,7.10965362 C17.0575977,7.14883854 17.1138759,7.2368169 17.1138759,7.33365346 L17.1138759,13.6662873 L17.1138759,13.6662873 Z M9.17611666,10.4999704 L8.38497002,10.4999704 L8.38497002,10.4999703 C8.38497002,10.9440712 8.73917812,11.3040855 9.17611666,11.3040855 C9.61305521,11.3040855 9.9672633,10.9440712 9.9672633,10.4999703 C9.9672633,10.4999702 9.9672633,10.4999702 9.9672633,10.4999702 L9.9672633,10.4999702 C9.9672633,10.0558693 9.61305521,9.69585494 9.17611666,9.69585494 C8.73917812,9.69585494 8.38497002,10.0558693 8.38497002,10.4999702 L9.17611666,10.4999704 Z M12.0260792,10.4999704 L11.2349326,10.4999704 L11.2349326,10.4999705 C11.2349326,10.9440714 11.5891406,11.3040858 12.0260792,11.3040858 C12.4630177,11.3040858 12.8172258,10.9440714 12.8172258,10.4999705 L12.8172258,10.4999705 C12.8172258,10.0558695 12.4630177,9.69585518 12.0260792,9.69585518 C11.5891406,9.69585518 11.2349326,10.0558695 11.2349326,10.4999705 C11.2349326,10.4999705 11.2349326,10.4999705 11.2349326,10.4999705 L12.0260792,10.4999704 Z M14.8758918,10.4999704 L14.0847452,10.4999704 L14.0847452,10.5000713 C14.0847452,10.9441722 14.4389533,11.3041866 14.8758918,11.3041866 C15.3128304,11.3041866 15.6670385,10.9441722 15.6670385,10.5000713 C15.6670385,10.5000039 15.6670385,10.4999366 15.6670385,10.4998692 L15.6670385,10.4997682 C15.6670385,10.0556672 15.3128304,9.69565288 14.8758918,9.69565288 C14.4389533,9.69565288 14.0847452,10.0556672 14.0847452,10.4997682 C14.0847452,10.4998355 14.0847452,10.4999029 14.0847452,10.4999702 L14.8758918,10.4999704 Z" id="形状" fill="#FFFFFF" fill-rule="nonzero"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
23
frontend/src/assets/legend/map-dxsdzGaojing0.svg
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>map-dxsdzYijian</title>
|
||||
<defs>
|
||||
<path d="M10,0 C15.5228475,0 20,4.4771525 20,10 C20,15.5228475 15.5228475,20 10,20 C4.4771525,20 0,15.5228475 0,10 C0,4.4771525 4.4771525,0 10,0 Z" id="path-1"></path>
|
||||
</defs>
|
||||
<g id="1-首页" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="1.1-首页-水电开发-全国" transform="translate(-158.000000, -812.000000)">
|
||||
<g id="图例备份-4" transform="translate(16.000000, 737.000000)">
|
||||
<g id="编组-9" transform="translate(142.000000, 74.000000)">
|
||||
<g id="map-shuikudaxing-yijian" transform="translate(0.000000, 1.000000)">
|
||||
<g id="路径" fill-rule="nonzero">
|
||||
<use fill="#499934" xlink:href="#path-1"></use>
|
||||
<use fill="#71B603" xlink:href="#path-1"></use>
|
||||
<use fill="#78C300" xlink:href="#path-1"></use>
|
||||
</g>
|
||||
<path d="M10,1.66666667 C14.6023729,1.66666667 18.3333333,5.39762709 18.3333333,10 L18.3333333,10 L1.66666667,10 L1.67048694,9.74522729 C1.80514922,5.26072284 5.48285621,1.66666667 10,1.66666667 Z" id="形状结合" fill="#FFFFFF"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
23
frontend/src/assets/legend/map-dxsdzGaojing1.svg
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>map-dxsdzYijian</title>
|
||||
<defs>
|
||||
<path d="M10,0 C15.5228475,0 20,4.4771525 20,10 C20,15.5228475 15.5228475,20 10,20 C4.4771525,20 0,15.5228475 0,10 C0,4.4771525 4.4771525,0 10,0 Z" id="path-1"></path>
|
||||
</defs>
|
||||
<g id="1-首页" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="1.1-首页-水电开发-全国" transform="translate(-158.000000, -812.000000)">
|
||||
<g id="图例备份-4" transform="translate(16.000000, 737.000000)">
|
||||
<g id="编组-9" transform="translate(142.000000, 74.000000)">
|
||||
<g id="map-shuikudaxing-yijian" transform="translate(0.000000, 1.000000)">
|
||||
<g id="路径" fill-rule="nonzero">
|
||||
<use fill="#6B8E23" xlink:href="#path-1"></use> <!-- 前两个调整为较深的橄榄绿 -->
|
||||
<use fill="#9ACD32" xlink:href="#path-1"></use> <!-- 中间的黄绿色 -->
|
||||
<use fill="#EECA47" xlink:href="#path-1"></use> <!-- 最后一个改为指定的黄橙色 -->
|
||||
</g>
|
||||
<path d="M10,1.66666667 C14.6023729,1.66666667 18.3333333,5.39762709 18.3333333,10 L18.3333333,10 L1.66666667,10 L1.67048694,9.74522729 C1.80514922,5.26072284 5.48285621,1.66666667 10,1.66666667 Z" id="形状结合" fill="#FFFFFF"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
23
frontend/src/assets/legend/map-dxsdzGaojing2.svg
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>map-dxsdzYijian</title>
|
||||
<defs>
|
||||
<path d="M10,0 C15.5228475,0 20,4.4771525 20,10 C20,15.5228475 15.5228475,20 10,20 C4.4771525,20 0,15.5228475 0,10 C0,4.4771525 4.4771525,0 10,0 Z" id="path-1"></path>
|
||||
</defs>
|
||||
<g id="1-首页" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="1.1-首页-水电开发-全国" transform="translate(-158.000000, -812.000000)">
|
||||
<g id="图例备份-4" transform="translate(16.000000, 737.000000)">
|
||||
<g id="编组-9" transform="translate(142.000000, 74.000000)">
|
||||
<g id="map-shuikudaxing-yijian" transform="translate(0.000000, 1.000000)">
|
||||
<g id="路径" fill-rule="nonzero">
|
||||
<use fill="#C5862B" xlink:href="#path-1"></use> <!-- 前两个调整为较深的橄榄绿 -->
|
||||
<use fill="#E69730" xlink:href="#path-1"></use> <!-- 中间的黄绿色 -->
|
||||
<use fill="#F7A737" xlink:href="#path-1"></use> <!-- 最后一个改为指定的黄橙色 -->
|
||||
</g>
|
||||
<path d="M10,1.66666667 C14.6023729,1.66666667 18.3333333,5.39762709 18.3333333,10 L18.3333333,10 L1.66666667,10 L1.67048694,9.74522729 C1.80514922,5.26072284 5.48285621,1.66666667 10,1.66666667 Z" id="形状结合" fill="#FFFFFF"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
23
frontend/src/assets/legend/map-dxsdzGaojing3.svg
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>map-dxsdzYijian</title>
|
||||
<defs>
|
||||
<path d="M10,0 C15.5228475,0 20,4.4771525 20,10 C20,15.5228475 15.5228475,20 10,20 C4.4771525,20 0,15.5228475 0,10 C0,4.4771525 4.4771525,0 10,0 Z" id="path-1"></path>
|
||||
</defs>
|
||||
<g id="1-首页" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="1.1-首页-水电开发-全国" transform="translate(-158.000000, -812.000000)">
|
||||
<g id="图例备份-4" transform="translate(16.000000, 737.000000)">
|
||||
<g id="编组-9" transform="translate(142.000000, 74.000000)">
|
||||
<g id="map-shuikudaxing-yijian" transform="translate(0.000000, 1.000000)">
|
||||
<g id="路径" fill-rule="nonzero">
|
||||
<use fill="#B24444" xlink:href="#path-1"></use> <!-- 前两个调整为较深的橄榄绿 -->
|
||||
<use fill="#D44D4D" xlink:href="#path-1"></use> <!-- 中间的黄绿色 -->
|
||||
<use fill="#E55555" xlink:href="#path-1"></use> <!-- 最后一个改为指定的黄橙色 -->
|
||||
</g>
|
||||
<path d="M10,1.66666667 C14.6023729,1.66666667 18.3333333,5.39762709 18.3333333,10 L18.3333333,10 L1.66666667,10 L1.67048694,9.74522729 C1.80514922,5.26072284 5.48285621,1.66666667 10,1.66666667 Z" id="形状结合" fill="#FFFFFF"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@ -20,45 +20,81 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from "vue";
|
||||
import { useUiStore } from "@/store/modules/ui";
|
||||
import shiliangImg from "@/assets/images/map-shiliangtu.png";
|
||||
import dixingImg from "@/assets/images/map-dixingtu.png";
|
||||
import yingxiangImg from "@/assets/images/map-yingxiangtu.png";
|
||||
import nineSectionsShiliangImg from "@/assets/images/nineSections-shiliang.png";
|
||||
import nineSectionsDixingImg from "@/assets/images/nineSections-dixing.png";
|
||||
import nineSectionsYingxiangImg from "@/assets/images/nineSections-yingxiang.png";
|
||||
import { ref, watch } from 'vue';
|
||||
import { useUiStore } from '@/store/modules/ui';
|
||||
import { useMapStore } from '@/store/modules/map';
|
||||
import { layerConfig2Flat } from '@/components/gis/gisUtils';
|
||||
import shiliangImg from '@/assets/images/map-shiliangtu.png';
|
||||
import dixingImg from '@/assets/images/map-dixingtu.png';
|
||||
import yingxiangImg from '@/assets/images/map-yingxiangtu.png';
|
||||
import nineSectionsShiliangImg from '@/assets/images/nineSections-shiliang.png';
|
||||
import nineSectionsDixingImg from '@/assets/images/nineSections-dixing.png';
|
||||
import nineSectionsYingxiangImg from '@/assets/images/nineSections-yingxiang.png';
|
||||
const props = defineProps({
|
||||
map: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
default: () => {}
|
||||
}
|
||||
});
|
||||
const uiStore = useUiStore();
|
||||
const mapStore = useMapStore();
|
||||
const drawerOpen = ref(uiStore.drawerOpen);
|
||||
|
||||
// 监听 store 中的 drawerOpen 变化
|
||||
watch(
|
||||
() => uiStore.drawerOpen,
|
||||
(newVal) => {
|
||||
newVal => {
|
||||
drawerOpen.value = newVal;
|
||||
}
|
||||
);
|
||||
const layers = [
|
||||
{ key: "s_province_boundaries", name: "矢量", img: shiliangImg },
|
||||
{ key: "BASEMAP-white", name: "地形", img: dixingImg },
|
||||
{ key: "BASEMAP-img", name: "影像", img: yingxiangImg },
|
||||
{ key: 's_province_boundaries', name: '矢量', img: shiliangImg },
|
||||
{ key: 'BASEMAP-white', name: '地形', img: dixingImg },
|
||||
{ key: 'BASEMAP-img', name: '影像', img: yingxiangImg }
|
||||
];
|
||||
const nineSectionsImg: any = {
|
||||
s_province_boundaries: nineSectionsShiliangImg,
|
||||
"BASEMAP-white": nineSectionsDixingImg,
|
||||
"BASEMAP-img": nineSectionsYingxiangImg,
|
||||
'BASEMAP-white': nineSectionsDixingImg,
|
||||
'BASEMAP-img': nineSectionsYingxiangImg
|
||||
};
|
||||
|
||||
const activeKey = ref(layers[0].key);
|
||||
|
||||
/**
|
||||
* 判断图层管理中的基础底图(customBaseLayer)是否被选中
|
||||
*/
|
||||
const isCustomBaseLayerChecked = (): boolean => {
|
||||
const layerConfig = layerConfig2Flat(mapStore.layerData);
|
||||
const customBaseLayer = layerConfig.find(
|
||||
(item: any) => item.key === 'customBaseLayer'
|
||||
);
|
||||
|
||||
if (!customBaseLayer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 判断是否被选中:直接选中或子节点被选中
|
||||
const checkedKeys = mapStore.checkedLayerKeys;
|
||||
if (checkedKeys.includes('customBaseLayer')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查子节点
|
||||
if (customBaseLayer.children && customBaseLayer.children.length > 0) {
|
||||
return customBaseLayer.children.some((child: any) =>
|
||||
checkedKeys.includes(child.key)
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const handleSwitch = (key: string) => {
|
||||
// 判断图层管理中的基础底图是否被选中
|
||||
const customBaseLayerChecked = isCustomBaseLayerChecked();
|
||||
|
||||
activeKey.value = key;
|
||||
props.map.baseLayerSwitcher(key);
|
||||
props.map.baseLayerSwitcher(key, customBaseLayerChecked ? 1 : 0);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@ -136,7 +136,7 @@ const getList = async (filter?: Record<string, any>) => {
|
||||
const res = await props.listUrl(params);
|
||||
|
||||
let finalRecords: any[] = [];
|
||||
let finalTotal: number = 0;
|
||||
let finalTotal = 0;
|
||||
|
||||
if (props.transformData) {
|
||||
const result = props.transformData(res);
|
||||
|
||||
@ -1188,7 +1188,7 @@ const WATabs: Array<any> = [
|
||||
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':
|
||||
|
||||
@ -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<string, any[]> = {};
|
||||
|
||||
// 构建 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -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<any> {
|
||||
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;
|
||||
|
||||
@ -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();
|
||||
|
||||
40
frontend/src/components/gis/map.d.ts
vendored
@ -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;
|
||||
|
||||
/**
|
||||
* 长度量算
|
||||
|
||||
@ -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 = `<div style="padding:5px; background:white; border-radius:4px;">${
|
||||
props.stnm || props.titleName || '未知'
|
||||
}</div>`;
|
||||
this.popupOverlay.setPosition(coordinate);
|
||||
this.popupElement.style.display = 'block';
|
||||
// this.popupElement.innerHTML = `<div style="padding:5px; background:white; border-radius:4px;">${
|
||||
// props.stnm || props.titleName || '未知'
|
||||
// }</div>`;
|
||||
// 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);
|
||||
|
||||
@ -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%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,98 +1,265 @@
|
||||
<template>
|
||||
<a-tooltip
|
||||
placement="leftBottom"
|
||||
trigger="click"
|
||||
color="transparent"
|
||||
:overlayInnerStyle="{ boxShadow: 'none' }"
|
||||
>
|
||||
<template #title>
|
||||
<div class="layers-tree">
|
||||
<div class="layers-tree-title">图层管理</div>
|
||||
<div class="layers-tree-content">
|
||||
<a-Tree
|
||||
checkable
|
||||
:onCheck="onCheck"
|
||||
:checkedKeys="checkedKeys"
|
||||
:treeData="layerConfigs"
|
||||
/>
|
||||
<div class="layer-controller" :ref="componentRef">
|
||||
<a-tooltip
|
||||
placement="leftBottom"
|
||||
trigger="click"
|
||||
color="transparent"
|
||||
:overlayInnerStyle="{ boxShadow: 'none' }"
|
||||
:open="tooltipVisible"
|
||||
@openChange="handleTooltipVisibleChange"
|
||||
>
|
||||
<template #title>
|
||||
<div class="layers-tree" :ref="tipRef">
|
||||
<div class="layers-tree-title">图层管理</div>
|
||||
<div class="layers-tree-content">
|
||||
<a-tree
|
||||
checkable
|
||||
:onCheck="onCheck"
|
||||
:checkedKeys="checkedKeys"
|
||||
:treeData="layerConfigs"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="map-item">
|
||||
<i class="icon iconfont icon-layer"></i>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<a-tooltip title="图层管理" placement="left">
|
||||
<div class="map-item" @click="handleClick">
|
||||
<i class="icon iconfont icon-layer"></i>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from "vue";
|
||||
import { useMapStore } from "@/store/modules/map";
|
||||
import { useRoute } from "vue-router";
|
||||
let route = useRoute();
|
||||
const mapStore: any = useMapStore();
|
||||
import { ref, onMounted, computed, watch, onUnmounted } from 'vue';
|
||||
import { useMapStore } from '@/store/modules/map';
|
||||
import { MapClass } from '@/components/gis/map.class';
|
||||
import { layerConfig2Flat, getMapConfig } from '@/components/gis/gisUtils';
|
||||
|
||||
const mapStore = useMapStore();
|
||||
const mapClass = MapClass.getInstance();
|
||||
|
||||
// 图层数据
|
||||
const layerConfigs = computed(() => mapStore.layerData);
|
||||
const layerConfigs = computed(() => {
|
||||
const convertCheckedToBoolean = (items: any[]) => {
|
||||
return items.map(item => {
|
||||
const newItem = { ...item };
|
||||
// 将checked属性从数字(0/1)转换为布尔值(false/true)
|
||||
if (typeof newItem.checkable === 'number') {
|
||||
newItem.checkable = !!newItem.checkable;
|
||||
}
|
||||
// 递归处理子节点
|
||||
if (newItem.children && Array.isArray(newItem.children)) {
|
||||
newItem.children = convertCheckedToBoolean(newItem.children);
|
||||
}
|
||||
return newItem;
|
||||
});
|
||||
};
|
||||
|
||||
return convertCheckedToBoolean(mapStore.layerData);
|
||||
});
|
||||
|
||||
// 选中的图层
|
||||
const checkedKeys: any = ref([]);
|
||||
const checkedKeys = ref<string[]>([]);
|
||||
const tooltipVisible = ref(false);
|
||||
const componentRef = ref<any | null>(null);
|
||||
const tipRef = ref<any | null>(null);
|
||||
|
||||
// 临时存储初始选中的图层 key
|
||||
let baseLayersInited = false;
|
||||
|
||||
/**
|
||||
* 广播图层配置变化
|
||||
*/
|
||||
const broadcast = (v: string[]) => {
|
||||
console.log('broadcast 被调用,图层 keys:', v);
|
||||
|
||||
// 使用 store 更新图层状态和图例(内部只处理变化的图层)
|
||||
mapStore.updateLayerData(v);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加基础图层(GISMap 类型)
|
||||
*/
|
||||
const addBaseLayers = (configs: any[]) => {
|
||||
// 将图层配置转换为一维数组
|
||||
const layerConfigsArr = layerConfig2Flat(configs);
|
||||
|
||||
layerConfigsArr.forEach((item: any) => {
|
||||
// 过滤掉非基础图层
|
||||
if (item.type !== 'GISMap') {
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析 paramJson 生成 config
|
||||
if (!item.config && item.paramJson) {
|
||||
try {
|
||||
const jsonObj = JSON.parse(item.paramJson);
|
||||
item.config = getMapConfig(jsonObj);
|
||||
} catch {
|
||||
item.config = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加基础图层
|
||||
if (item.config) {
|
||||
if (item.key === 'customBaseLayer') {
|
||||
sessionStorage.setItem('customBaseLayer', JSON.stringify(item.config));
|
||||
}
|
||||
mapClass.addBaseDataLayer(item.config, item.checked === 1);
|
||||
mapClass.controlBaseLayerTreeShowAndHidden(
|
||||
item.key,
|
||||
item.config?.id,
|
||||
item.checked === 1
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取初始选中的图层 key
|
||||
*/
|
||||
const getInitCheckedKeys = (data: any[] = []): string[] => {
|
||||
const keys: string[] = [];
|
||||
const f = (arr: any[] = []) => {
|
||||
arr.forEach((item: any) => {
|
||||
if (item.key && item.checked) {
|
||||
keys.push(item.key);
|
||||
}
|
||||
if (item.children && item.children.length > 0) {
|
||||
f(item.children);
|
||||
}
|
||||
});
|
||||
};
|
||||
f(data);
|
||||
return keys;
|
||||
};
|
||||
|
||||
const onCheck = (v: any, e: any) => {
|
||||
// 环保设施和环保设施在建数据获取,两者只能同时存在勾选一项
|
||||
const fData = layerConfigs.value?.filter((e: any) => e.key === "facilities")?.[0];
|
||||
const fbData = layerConfigs.value?.filter((e: any) => e.key === "facilities_built")?.[0];
|
||||
const fData = layerConfigs.value?.filter(
|
||||
(item: any) => item.key === 'facilities'
|
||||
)?.[0];
|
||||
const fbData = layerConfigs.value?.filter(
|
||||
(item: any) => item.key === 'facilities_built'
|
||||
)?.[0];
|
||||
const facilities_built_data =
|
||||
(fbData && [fbData.key, ...fbData?.children?.map((e: any) => e.key)]) || [];
|
||||
(fbData && [
|
||||
fbData.key,
|
||||
...fbData?.children?.map((item: any) => item.key)
|
||||
]) ||
|
||||
[];
|
||||
const facilities_data =
|
||||
(fData && [fData.key, ...fData?.children?.map((e: any) => e.key)]) || [];
|
||||
(fData && [fData.key, ...fData?.children?.map((item: any) => item.key)]) ||
|
||||
[];
|
||||
|
||||
let checkKeys = v;
|
||||
|
||||
if (e?.node.key === "rare_fish_point") {
|
||||
checkKeys = v?.filter((item: any) => item !== "fish_along_point");
|
||||
} else if (e?.node.key === "fish_along_point") {
|
||||
checkKeys = v?.filter((item: any) => item !== "rare_fish_point");
|
||||
// 珍稀鱼类和沿程鱼类互斥
|
||||
if (e?.node.key === 'rare_fish_point') {
|
||||
checkKeys = v?.filter((item: any) => item !== 'fish_along_point');
|
||||
} else if (e?.node.key === 'fish_along_point') {
|
||||
checkKeys = v?.filter((item: any) => item !== 'rare_fish_point');
|
||||
}
|
||||
|
||||
if (e.checked) {
|
||||
if (e?.node.key === "stinfo_video_point" || e?.node.key == "stinfo") {
|
||||
checkKeys = v?.filter((item: any) => item !== "stinfo_ai_video_point");
|
||||
} else if (e?.node.key === "stinfo_ai_video_point") {
|
||||
checkKeys = v?.filter(
|
||||
(item: any) => item !== "stinfo_video_point" && item !== "stinfo"
|
||||
// 视频监控和AI视频监控互斥
|
||||
if (e?.node.key === 'stinfo_video_point' || e?.node.key == 'stinfo') {
|
||||
checkKeys = v?.filter((item: any) => item !== 'stinfo_ai_video_point');
|
||||
} else if (e?.node.key === 'stinfo_ai_video_point') {
|
||||
checkKeys = checkKeys.filter(
|
||||
(item: any) => item !== 'stinfo_video_point' && item !== 'stinfo'
|
||||
);
|
||||
}
|
||||
console.log(checkKeys, "res111");
|
||||
|
||||
// 环保设施和环保设施在建互斥
|
||||
if (
|
||||
checkKeys.some((e: any) => facilities_data.includes(e)) &&
|
||||
checkKeys.some((e: any) => facilities_built_data.includes(e))
|
||||
checkKeys.some((item: any) => facilities_data.includes(item)) &&
|
||||
checkKeys.some((item: any) => facilities_built_data.includes(item))
|
||||
) {
|
||||
if (
|
||||
facilities_built_data.some((e: any) =>
|
||||
e.includes(checkKeys[checkKeys.length - 1])
|
||||
facilities_built_data.some((item: any) =>
|
||||
item.includes(checkKeys[checkKeys.length - 1])
|
||||
)
|
||||
) {
|
||||
checkKeys = checkKeys.filter((e: any) => !facilities_data.includes(e));
|
||||
checkKeys = checkKeys.filter(
|
||||
(item: any) => !facilities_data.includes(item)
|
||||
);
|
||||
} else if (
|
||||
facilities_data.some((e: any) => e.includes(checkKeys[checkKeys.length - 1]))
|
||||
facilities_data.some((item: any) =>
|
||||
item.includes(checkKeys[checkKeys.length - 1])
|
||||
)
|
||||
) {
|
||||
checkKeys = checkKeys.filter((e: any) => !facilities_built_data.includes(e));
|
||||
checkKeys = checkKeys.filter(
|
||||
(item: any) => !facilities_built_data.includes(item)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkedKeys.value = checkKeys;
|
||||
mapStore.updateLayerData(checkKeys);
|
||||
broadcast(checkKeys);
|
||||
};
|
||||
const getCheckedKeys = () => {
|
||||
const name = route.path.split("/")[2];
|
||||
if (name === "shuiDianKaiFaZhuangKuang") {
|
||||
checkedKeys.value = ["customBaseLayer","powerBaseStation", "eng", "eng_point"];
|
||||
|
||||
const handleClick = () => {
|
||||
tooltipVisible.value = !tooltipVisible.value;
|
||||
};
|
||||
|
||||
const handleTooltipVisibleChange = (visible: boolean) => {
|
||||
tooltipVisible.value = visible;
|
||||
};
|
||||
|
||||
// 点击外部关闭tooltip
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (
|
||||
componentRef.value &&
|
||||
!componentRef.value.contains(event.target as Node)
|
||||
) {
|
||||
if (tipRef.value && !tipRef.value.contains(event.target as Node)) {
|
||||
tooltipVisible.value = false;
|
||||
}
|
||||
}
|
||||
mapStore.updateLayerData(checkedKeys.value);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getCheckedKeys();
|
||||
// router.push({ name: 'map' })
|
||||
// 绑定点击外部事件
|
||||
document.addEventListener('click', handleClickOutside);
|
||||
|
||||
// 热更新时重置基础图层初始化标志,确保重新加载
|
||||
baseLayersInited = false;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('click', handleClickOutside);
|
||||
});
|
||||
|
||||
// 监听图层配置变化
|
||||
watch(
|
||||
() => layerConfigs.value,
|
||||
newVal => {
|
||||
if (newVal && newVal.length > 0 && !baseLayersInited) {
|
||||
addBaseLayers(newVal);
|
||||
baseLayersInited = true;
|
||||
|
||||
const keys = getInitCheckedKeys(newVal);
|
||||
checkedKeys.value = keys;
|
||||
// 注意:loadAllLayerData 和 updateLayerData 由 GisView.vue 统一调用
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 监听 store 中 checkedLayerKeys 的变化
|
||||
watch(
|
||||
() => mapStore.checkedLayerKeys,
|
||||
newVal => {
|
||||
if (newVal && newVal.length > 0) {
|
||||
checkedKeys.value = newVal;
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
<style lang="scss">
|
||||
.map-item {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
@ -109,12 +276,21 @@ onMounted(() => {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.ant-tooltip-inner {
|
||||
height: auto !important;
|
||||
max-height: 300px !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
.layers-tree {
|
||||
width: 230px;
|
||||
max-height: 300px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 1px 2px #00000026;
|
||||
background-color: #fff;
|
||||
cursor: initial;
|
||||
border: 1px solid #ccdae7;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.layers-tree-title {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
text-align: left;
|
||||
@ -123,10 +299,12 @@ onMounted(() => {
|
||||
line-height: 40px;
|
||||
font-size: 16px;
|
||||
border-bottom: 1px dotted #ccc;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.layers-tree-content {
|
||||
max-height: 300px;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -8,7 +8,11 @@
|
||||
:key="child.key"
|
||||
>
|
||||
<component v-if="child.component" :is="child.component" :map="map" />
|
||||
<div v-else class="map-controller-item" @click="handleControllerClick(child)">
|
||||
<div
|
||||
v-else
|
||||
class="map-controller-item"
|
||||
@click="handleControllerClick(child)"
|
||||
>
|
||||
<i class="icon iconfont" :class="'icon-' + child.icon"></i>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
@ -16,10 +20,10 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, computed } from "vue";
|
||||
import { useUiStore } from "@/store/modules/ui";
|
||||
import Calculate from "./Calculate.vue";
|
||||
import LayerController from "./LayerController.vue";
|
||||
import { ref, watch, computed } from 'vue';
|
||||
import { useUiStore } from '@/store/modules/ui';
|
||||
import Calculate from './Calculate.vue';
|
||||
import LayerController from './LayerController.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
map: any;
|
||||
@ -34,7 +38,7 @@ const drawerOpen = ref(uiStore.drawerOpen);
|
||||
// 监听 store 中的 drawerOpen 变化
|
||||
watch(
|
||||
() => uiStore.drawerOpen,
|
||||
(newVal) => {
|
||||
newVal => {
|
||||
drawerOpen.value = newVal;
|
||||
}
|
||||
);
|
||||
@ -46,11 +50,11 @@ const controllers: any = computed(() => [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
name: "全屏",
|
||||
key: "fullScreen",
|
||||
icon: isFullScreen.value ? "exitFullScreen" : "fullScreen",
|
||||
},
|
||||
],
|
||||
name: '全屏',
|
||||
key: 'fullScreen',
|
||||
icon: isFullScreen.value ? 'exitFullScreen' : 'fullScreen'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
@ -61,136 +65,150 @@ const controllers: any = computed(() => [
|
||||
// icon: "iconGlobal",
|
||||
// },
|
||||
{
|
||||
name: "放大",
|
||||
key: "zoomIn",
|
||||
icon: "zoomIn",
|
||||
name: '放大',
|
||||
key: 'zoomIn',
|
||||
icon: 'zoomIn'
|
||||
},
|
||||
{
|
||||
name: "缩小",
|
||||
key: "zoomOut",
|
||||
icon: "zoomOut",
|
||||
},
|
||||
],
|
||||
name: '缩小',
|
||||
key: 'zoomOut',
|
||||
icon: 'zoomOut'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
name: "3D",
|
||||
key: "dim",
|
||||
icon: uiStore.mapType === "2D" ? "a-3D" : "a-2D",
|
||||
},
|
||||
],
|
||||
name: '3D',
|
||||
key: 'dim',
|
||||
icon: uiStore.mapType === '2D' ? 'a-3D' : 'a-2D'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
name: "图层管理",
|
||||
key: "layerController",
|
||||
component: LayerController,
|
||||
},
|
||||
],
|
||||
name: '图层管理',
|
||||
key: 'layerController',
|
||||
component: LayerController
|
||||
}
|
||||
]
|
||||
},
|
||||
uiStore.mapType === "2D"
|
||||
uiStore.mapType === '2D'
|
||||
? {
|
||||
children: [
|
||||
{
|
||||
name: "测量工具",
|
||||
key: "Calculate",
|
||||
component: Calculate,
|
||||
},
|
||||
],
|
||||
name: '测量工具',
|
||||
key: 'Calculate',
|
||||
component: Calculate
|
||||
}
|
||||
]
|
||||
}
|
||||
: {},
|
||||
uiStore.mapType === "2D"
|
||||
uiStore.mapType === '2D'
|
||||
? {
|
||||
children: [
|
||||
{
|
||||
name: "梯级",
|
||||
key: "TJ",
|
||||
icon: "tiji",
|
||||
},
|
||||
],
|
||||
name: '梯级',
|
||||
key: 'TJ',
|
||||
icon: 'tiji'
|
||||
}
|
||||
]
|
||||
}
|
||||
: {},
|
||||
uiStore.mapType === "3D"
|
||||
uiStore.mapType === '3D'
|
||||
? {
|
||||
children: [
|
||||
{
|
||||
name: "电站倾斜摄影",
|
||||
key: "OSBGController",
|
||||
icon: "obliquePhotography",
|
||||
},
|
||||
],
|
||||
name: '电站倾斜摄影',
|
||||
key: 'OSBGController',
|
||||
icon: 'obliquePhotography'
|
||||
}
|
||||
]
|
||||
}
|
||||
: {},
|
||||
uiStore.mapType === "3D"
|
||||
uiStore.mapType === '3D'
|
||||
? {
|
||||
children: [
|
||||
{
|
||||
name: "流域三维漫游",
|
||||
key: "threedRoam",
|
||||
icon: "roaming",
|
||||
},
|
||||
],
|
||||
name: '流域三维漫游',
|
||||
key: 'threedRoam',
|
||||
icon: 'roaming'
|
||||
}
|
||||
]
|
||||
}
|
||||
: {},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
name: "下载",
|
||||
key: "screenShot",
|
||||
icon: "downLoad",
|
||||
},
|
||||
],
|
||||
},
|
||||
name: '下载',
|
||||
key: 'screenShot',
|
||||
icon: 'downLoad'
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
// 添加全屏切换功能
|
||||
// const toggleFullScreen = () => {
|
||||
// isFullScreen.value = !isFullScreen.value;
|
||||
// // 这里可以添加实际的浏览器全屏切换逻辑
|
||||
// if (isFullScreen.value) {
|
||||
// document.documentElement.requestFullscreen();
|
||||
// } else {
|
||||
// document.exitFullscreen();
|
||||
// }
|
||||
// };
|
||||
const toggleFullScreen = () => {
|
||||
if (!document.fullscreenElement) {
|
||||
// 进入全屏
|
||||
document.documentElement.requestFullscreen().catch(err => {
|
||||
console.error('进入全屏失败:', err);
|
||||
isFullScreen.value = false;
|
||||
});
|
||||
} else {
|
||||
// 退出全屏
|
||||
document.exitFullscreen().catch(err => {
|
||||
console.error('退出全屏失败:', err);
|
||||
isFullScreen.value = true;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 监听全屏状态变化
|
||||
document.addEventListener('fullscreenchange', () => {
|
||||
isFullScreen.value = !!document.fullscreenElement;
|
||||
});
|
||||
|
||||
// 控制器点击事件处理
|
||||
const handleControllerClick = (item: any) => {
|
||||
switch (item.key) {
|
||||
case "fullScreen":
|
||||
isFullScreen.value = !isFullScreen.value;
|
||||
map.jdPanelControlShowAndHidden("01", false);
|
||||
case 'fullScreen':
|
||||
// map.jdPanelControlShowAndHidden("01", false);
|
||||
// map.mdLayerTreeShowOrHidden('fp_point',!isFullScreen.value);
|
||||
// map.controlBaseLayerTreeShowAndHidden('customBaseLayer','customBaseLayer',!isFullScreen.value);
|
||||
// map.controlBaseLayerTreeShowAndHidden(
|
||||
// 'customBaseLayer',
|
||||
// 'customBaseLayer',
|
||||
// !isFullScreen.value
|
||||
// );
|
||||
// map.controlBaseLayerTreeShowAndHidden('lcj_bhq','lcj_bhq',!isFullScreen.value);
|
||||
// toggleFullScreen();
|
||||
toggleFullScreen();
|
||||
break;
|
||||
case "zoomIn":
|
||||
map.zoomToggle("in");
|
||||
case 'zoomIn':
|
||||
map.zoomToggle('in');
|
||||
break;
|
||||
case "zoomOut":
|
||||
map.zoomToggle("out");
|
||||
case 'zoomOut':
|
||||
map.zoomToggle('out');
|
||||
break;
|
||||
case "dim":
|
||||
uiStore.mapType = uiStore.mapType === "2D" ? "3D" : "2D";
|
||||
if (uiStore.mapType === "2D") {
|
||||
case 'dim':
|
||||
uiStore.mapType = uiStore.mapType === '2D' ? '3D' : '2D';
|
||||
if (uiStore.mapType === '2D') {
|
||||
uiStore.drawerOpen = true;
|
||||
} else {
|
||||
uiStore.drawerOpen = false;
|
||||
}
|
||||
props.onClick("dim", uiStore.mapType);
|
||||
props.onClick('dim', uiStore.mapType);
|
||||
break;
|
||||
case "rightDrawer":
|
||||
case 'rightDrawer':
|
||||
// 使用全局事件切换右侧面板
|
||||
// GlobalEvents.get('rightDrawerState').set(!drawerOpen);
|
||||
break;
|
||||
// 可以在这里添加其他控制器的处理逻辑
|
||||
case "screenShot":
|
||||
case 'screenShot':
|
||||
map.mapOutPut();
|
||||
break;
|
||||
case "TJ":
|
||||
case 'TJ':
|
||||
props.onClick(4, null);
|
||||
// map.addTertiarybasinLayer(servers.Tertiarybasin, '#4DFFDD', '#92A0A5')
|
||||
break;
|
||||
|
||||
@ -10,9 +10,11 @@
|
||||
placeholder="装机容量"
|
||||
style="width: 120px"
|
||||
>
|
||||
<a-select-option v-for="item in siteRangePicker" :key="item.value">{{
|
||||
item.label
|
||||
}}</a-select-option>
|
||||
<a-select-option
|
||||
v-for="item in siteRangePicker"
|
||||
:key="item.value"
|
||||
>{{ item.label }}</a-select-option
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@ -25,28 +27,40 @@
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col>
|
||||
<a-button @click="handleSearch">查询</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
map: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
});
|
||||
const siteRangePicker = [
|
||||
{ label: "0-10", value: "0-10" },
|
||||
{ label: "10-20", value: "10-20" },
|
||||
{ label: "20-30", value: "20-30" },
|
||||
{ label: "30-40", value: "30-40" },
|
||||
{ label: "40-50", value: "40-50" },
|
||||
{ label: "50-60", value: "50-60" },
|
||||
{ label: '0-10', value: '0-10' },
|
||||
{ label: '10-20', value: '10-20' },
|
||||
{ label: '20-30', value: '20-30' },
|
||||
{ label: '30-40', value: '30-40' },
|
||||
{ label: '40-50', value: '40-50' },
|
||||
{ label: '50-60', value: '50-60' }
|
||||
];
|
||||
const formModel = ref({
|
||||
siteRangePicker: [],
|
||||
siteRangePicker: []
|
||||
});
|
||||
const rules = ref({
|
||||
siteRangePicker: [{ required: true, message: "请选择装机容量" }],
|
||||
siteRangePicker: [{ required: true, message: '请选择装机容量' }]
|
||||
});
|
||||
const handleSearch = () => {
|
||||
props.map.flyTopanto([98.958315, 30.754818], 14);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -4,7 +4,12 @@
|
||||
class="legendItem"
|
||||
:class="{ gray: item.checked == 0, disabled: item.canBeChecked == 0 }"
|
||||
>
|
||||
<div class="legendIcon" :class="{ smallIcon: item.layerCode == 'eng_point' || item.layerCode == 'ef_point' }">
|
||||
<div
|
||||
class="legendIcon"
|
||||
:class="{
|
||||
smallIcon: item.layerCode == 'eng_point' || item.layerCode == 'ef_point'
|
||||
}"
|
||||
>
|
||||
<img :src="getIconPath(item.icon)" alt="" />
|
||||
</div>
|
||||
<div class="legendIconTitle">
|
||||
@ -14,7 +19,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getIconPath } from "@/utils/index";
|
||||
import { getIconPath } from '@/utils/index';
|
||||
defineProps<{ item: any }>();
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@ -40,7 +45,6 @@ defineProps<{ item: any }>();
|
||||
width: 22px !important;
|
||||
height: 22px !important;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
.legendIconTitle {
|
||||
cursor: pointer;
|
||||
|
||||
@ -3,32 +3,62 @@
|
||||
<div class="legendTitle">
|
||||
图例
|
||||
<span class="legendBtn" @click="isOpen = !isOpen">
|
||||
<i class="icon iconfont" :class="isOpen ? 'icon-fold' : 'icon-unFold'"></i>
|
||||
<i
|
||||
class="icon iconfont"
|
||||
:class="isOpen ? 'icon-fold' : 'icon-unFold'"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="legendContent" v-show="isOpen">
|
||||
<a-spin :spinning="loadLegendData">
|
||||
<div class="legendGroup" v-for="i in legendData">
|
||||
<div class="groupTitle">{{ i.name }} {{ i.layerCode }}</div>
|
||||
<div class="groupContent">
|
||||
<template v-for="j in i.childrenList" :key="j.name">
|
||||
<LegendItem v-if="j.layerCode" :item="j" @click="legendItemClick(j)" />
|
||||
<div
|
||||
v-else-if="j.childrenList && j.childrenList.length > 0"
|
||||
class="legendGroup"
|
||||
>
|
||||
<div class="groupTitle">{{ j.name }}</div>
|
||||
<div class="groupContent">
|
||||
<LegendItem
|
||||
v-for="item in j.childrenList"
|
||||
:key="item.layerCode"
|
||||
:item="item"
|
||||
@click="legendItemClick(item)"
|
||||
/>
|
||||
<a-spin :spinning="loadLegendData" tip="加载中...">
|
||||
<div class="legendContainer">
|
||||
<div
|
||||
class="legendGroup"
|
||||
v-for="i in legendData"
|
||||
:key="i.name"
|
||||
:class="{ envFac: i.name == '环保设施' }"
|
||||
>
|
||||
<div
|
||||
class="groupTitle"
|
||||
v-if="i.name != '环保设施'"
|
||||
:class="{ gray: isGroupAllUnchecked(i) }"
|
||||
@click="toggleGroup(i)"
|
||||
>
|
||||
{{ i.name }}
|
||||
</div>
|
||||
<div
|
||||
class="groupContent"
|
||||
:class="{ envFacBottom: hasEnvFac && i.name != '环保设施' }"
|
||||
>
|
||||
<template v-for="j in i.childrenList" :key="j.name">
|
||||
<LegendItem
|
||||
v-if="j.layerCode"
|
||||
:item="j"
|
||||
@click="legendItemClick(j)"
|
||||
/>
|
||||
<div
|
||||
v-else-if="j.childrenList && j.childrenList.length > 0"
|
||||
class="legendGroup"
|
||||
>
|
||||
<div
|
||||
class="groupTitle"
|
||||
:class="{ gray: isGroupAllUnchecked(j) }"
|
||||
@click="toggleGroup(j)"
|
||||
>
|
||||
{{ j.name }}
|
||||
</div>
|
||||
<div class="groupContent">
|
||||
<LegendItem
|
||||
v-for="item in j.childrenList"
|
||||
:key="item.layerCode"
|
||||
:item="item"
|
||||
@click="legendItemClick(item)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
@ -36,53 +66,170 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
import { useMapStore } from "@/store/modules/map";
|
||||
import LegendItem from "@/components/mapLegend/LegendItem.vue";
|
||||
import { onMounted, ref, watch, computed } from 'vue';
|
||||
import { useMapStore } from '@/store/modules/map';
|
||||
import { useRoute } from 'vue-router';
|
||||
import LegendItem from '@/components/mapLegend/LegendItem.vue';
|
||||
import { MapClass } from '@/components/gis/map.class';
|
||||
|
||||
const mapStore: any = useMapStore();
|
||||
// 图层数据
|
||||
const legendData = ref(mapStore.legendDataSelected);
|
||||
const route = useRoute();
|
||||
const mapClass = MapClass.getInstance();
|
||||
|
||||
// 从路由获取 pageKey
|
||||
const pageKey = computed(() => {
|
||||
const path = route.path;
|
||||
const parts = path.split('/');
|
||||
if (parts.length >= 3) {
|
||||
return parts[1] + '_' + parts[2];
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
// 图例数据:使用选中的图例(由图层勾选状态决定)
|
||||
const legendData = ref<any[]>([]);
|
||||
const loadLegendData = ref(false);
|
||||
|
||||
// 判断图例数据中是否有"环保设施"
|
||||
const hasEnvFac = computed(() => {
|
||||
return legendData.value.some((item: any) => item.name === '环保设施');
|
||||
});
|
||||
|
||||
const legendItemClick = (item: any) => {
|
||||
if (item.parentName == '环保设施') return;
|
||||
if (item.canBeChecked == 0) {
|
||||
return;
|
||||
}
|
||||
item.checked = item.checked == 0 ? 1 : 0;
|
||||
const newChecked = item.checked == 0 ? 1 : 0;
|
||||
item.checked = newChecked;
|
||||
|
||||
// 更新 store 中的图例状态
|
||||
if (item.nameEn) {
|
||||
mapStore.updateLegendChecked(item.nameEn, newChecked);
|
||||
}
|
||||
|
||||
// 通过 nameEn 和 anchoPointState 控制单个图例的锚点显示隐藏
|
||||
if (item.nameEn && item.layerCode) {
|
||||
const layerKey = item.layerCode;
|
||||
// 查找图层对象,判断图层类型(图层可能有多层嵌套)
|
||||
const layerItem = mapStore.findLayerByKey(mapStore.layerData, layerKey);
|
||||
console.log(`图例 ${item.nameEn} 控制图层:`, layerItem);
|
||||
|
||||
// 处理 alarm_range_ 前缀转换:添加 large_eng_built_ 前缀
|
||||
const nameEnToUse = item.nameEn.includes('alarm_range_')
|
||||
? `large_eng_built_${item.nameEn}`
|
||||
: item.nameEn;
|
||||
|
||||
if (layerItem) {
|
||||
if (layerItem.type === 'pointMap') {
|
||||
// 锚点图层:控制锚点显示隐藏
|
||||
mapClass.setLegendPointVisible(layerKey, nameEnToUse, newChecked === 1);
|
||||
} else if (layerItem.type === 'GISMap') {
|
||||
// GIS图层:控制图层显示隐藏
|
||||
mapClass.controlBaseLayerTreeShowAndHidden(
|
||||
layerKey,
|
||||
layerItem.config?.id,
|
||||
newChecked === 1
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// 默认处理为锚点图层
|
||||
mapClass.setLegendPointVisible(layerKey, nameEnToUse, newChecked === 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 监听选中图例数据的变化(图层勾选变化时更新)
|
||||
watch(
|
||||
() => mapStore.legendDataSelected,
|
||||
(newValue) => {
|
||||
// layerConfigs.value = newValue;
|
||||
console.log(newValue);
|
||||
newValue => {
|
||||
console.log('图例数据更新:', newValue);
|
||||
legendData.value = newValue;
|
||||
// for (let i = 0; i < newValue.length; i++) {
|
||||
// console.log(mapStore.layerData[i]);
|
||||
// if (newValue[i].key != "-") {
|
||||
// if (newValue[i].checked == 1) {
|
||||
// if (newValue[i].children?.length > 0) {
|
||||
// legendData.value.push(newValue[i]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
onMounted(() => {
|
||||
// for (let i = 0; i < mapStore.layerData.length; i++) {
|
||||
// console.log(mapStore.layerData[i]);
|
||||
// if (mapStore.layerData[i].key != "-") {
|
||||
// if (mapStore.layerData[i].checked == 1) {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// console.log(layerConfigs.value)
|
||||
// setTimeout(() => {
|
||||
// data.value = 10;
|
||||
// }, 1000);
|
||||
// console.log(data.value);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => mapStore.loading,
|
||||
newValue => {
|
||||
console.log('图例加载状态:', newValue);
|
||||
loadLegendData.value = newValue;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const isOpen = ref(true);
|
||||
|
||||
const getAllLeafItems = (group: any): any[] => {
|
||||
const items: any[] = [];
|
||||
if (!group.childrenList) return items;
|
||||
|
||||
group.childrenList.forEach((child: any) => {
|
||||
if (child.layerCode) {
|
||||
items.push(child);
|
||||
} else if (child.childrenList && child.childrenList.length > 0) {
|
||||
items.push(...getAllLeafItems(child));
|
||||
}
|
||||
});
|
||||
return items;
|
||||
};
|
||||
|
||||
const isGroupAllUnchecked = (group: any): boolean => {
|
||||
const leafItems = getAllLeafItems(group);
|
||||
if (leafItems.length === 0) return false;
|
||||
return leafItems.every((item: any) => item.checked === 0);
|
||||
};
|
||||
|
||||
const toggleGroup = (group: any) => {
|
||||
const leafItems = getAllLeafItems(group);
|
||||
if (leafItems.length === 0) return;
|
||||
|
||||
const hasAnyChecked = leafItems.some((item: any) => item.checked === 1);
|
||||
const targetChecked = hasAnyChecked ? 0 : 1;
|
||||
|
||||
leafItems.forEach((item: any) => {
|
||||
if (item.parentName === '环保设施') return;
|
||||
if (item.canBeChecked === 0) return;
|
||||
if (item.checked !== targetChecked) {
|
||||
item.checked = targetChecked;
|
||||
|
||||
if (item.nameEn) {
|
||||
mapStore.updateLegendChecked(item.nameEn, targetChecked);
|
||||
}
|
||||
|
||||
if (item.nameEn && item.layerCode) {
|
||||
const layerKey = item.layerCode;
|
||||
const layerItem = mapStore.findLayerByKey(mapStore.layerData, layerKey);
|
||||
|
||||
const nameEnToUse = item.nameEn.includes('alarm_range_')
|
||||
? `large_eng_built_${item.nameEn}`
|
||||
: item.nameEn;
|
||||
|
||||
if (layerItem) {
|
||||
if (layerItem.type === 'pointMap') {
|
||||
mapClass.setLegendPointVisible(
|
||||
layerKey,
|
||||
nameEnToUse,
|
||||
targetChecked === 1
|
||||
);
|
||||
} else if (layerItem.type === 'GISMap') {
|
||||
mapClass.controlBaseLayerTreeShowAndHidden(
|
||||
layerKey,
|
||||
layerItem.config?.id,
|
||||
targetChecked === 1
|
||||
);
|
||||
}
|
||||
} else {
|
||||
mapClass.setLegendPointVisible(
|
||||
layerKey,
|
||||
nameEnToUse,
|
||||
targetChecked === 1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -107,13 +254,48 @@ const isOpen = ref(true);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.envFac {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background-color: #ffffff;
|
||||
border-top: 1px solid #eeeeee;
|
||||
.groupContent {
|
||||
padding: 0 !important;
|
||||
:deep(.legendItem) {
|
||||
cursor: none;
|
||||
&:hover {
|
||||
.legendIconTitle {
|
||||
cursor: auto;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.envFacBottom {
|
||||
padding-bottom: 80px !important;
|
||||
}
|
||||
.legendContent {
|
||||
white-space: nowrap;
|
||||
max-width: 450px;
|
||||
max-height: 392px;
|
||||
max-height: 450px;
|
||||
overflow-x: scroll;
|
||||
overflow-y: scroll;
|
||||
border-top: 1px solid #eeeeee;
|
||||
:deep(.ant-spin-nested-loading) {
|
||||
min-height: 50px;
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.legendContainer {
|
||||
position: relative;
|
||||
min-height: 20px;
|
||||
min-width: 30px;
|
||||
overflow: auto;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
.legendGroup {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
@ -138,4 +320,35 @@ const isOpen = ref(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
.legendItem {
|
||||
cursor: pointer;
|
||||
margin-right: 10px;
|
||||
padding: 4px 0;
|
||||
min-height: 30px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.legendIcon {
|
||||
width: 25px !important;
|
||||
height: 25px !important;
|
||||
text-align: center;
|
||||
img {
|
||||
max-width: 80%;
|
||||
max-height: 80%;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
.smallIcon {
|
||||
width: 22px !important;
|
||||
height: 22px !important;
|
||||
text-align: center;
|
||||
}
|
||||
.legendIconTitle {
|
||||
cursor: pointer;
|
||||
flex: 1 1;
|
||||
}
|
||||
&:hover {
|
||||
color: #2f6b98;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
260
frontend/src/docs/地图加载逻辑.md
Normal file
@ -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() - 更新图层显隐,控制锚点显示
|
||||
```
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useJidiSelectEventStore } from "@/store/modules/jidiSelectEvent";
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||
const loading = ref(false);
|
||||
const isOpen = ref(true);
|
||||
const JidiSelectEventStore = useJidiSelectEventStore();
|
||||
|
||||
const jidiDataNum = ref(9);
|
||||
const itemClick = (index: any) => {
|
||||
useJidiSelectEventStore().updataJidiData(index);
|
||||
JidiSelectEventStore.updataJidiData(index);
|
||||
};
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
@ -32,7 +32,10 @@ onMounted(() => {});
|
||||
<div
|
||||
v-if="isOpen"
|
||||
class="item"
|
||||
v-for="(i, index) in JidiSelectEventStore.jidiData.slice(0, jidiDataNum)"
|
||||
v-for="(i, index) in JidiSelectEventStore.jidiData.slice(
|
||||
0,
|
||||
jidiDataNum
|
||||
)"
|
||||
:class="{ selected: i.selected }"
|
||||
@click="itemClick(index)"
|
||||
>
|
||||
@ -44,7 +47,7 @@ onMounted(() => {});
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
@use "@/styles/variables.module.scss" as *;
|
||||
@use '@/styles/variables.module.scss' as *;
|
||||
.jidiSelectorMod {
|
||||
width: 175px;
|
||||
max-height: 941px;
|
||||
|
||||
449
frontend/src/store/modules/GisUrlList.ts
Normal file
@ -0,0 +1,449 @@
|
||||
import moment from 'moment';
|
||||
|
||||
export const urlList = [
|
||||
{
|
||||
url: '/wmp-eng-server/eng/point/GetKendoListCust',
|
||||
title: '常规水电',
|
||||
params: {
|
||||
anchoPointState: [{ field: 'anchoPointState', operator: 'isnotnull' }]
|
||||
},
|
||||
orders:
|
||||
'{"baseId":"asc","rvcdStepSort":"asc","siteStepSort":"asc","ennm":"asc"}'
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/sw/getFacilityPointList/GetKendoListCust',
|
||||
title: '低温水减缓设施',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-eng-server/eng/eq/interval/GetKendoListCust',
|
||||
title: '生态流量达标率',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] },
|
||||
orders:
|
||||
'{"baseId":"asc","rvcdStepSort":"asc","siteStepSort":"asc","ennm":"asc"}'
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/wq/anchorPoint/reach/GetKendoListCust',
|
||||
title: '实际水质',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/wq/anchorPoint/reach/GetKendoListCust',
|
||||
title: '目标水质',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/wq/anchorPoint/GetKendoListCust',
|
||||
title: '自建站',
|
||||
params: {
|
||||
dtinType: [{ field: 'dtinType', operator: 'eq', value: '0' }],
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
},
|
||||
orders: '{"siteStepSort":"asc"}'
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/wq/anchorPoint/GetKendoListCust',
|
||||
title: '国家站',
|
||||
params: {
|
||||
dtinType: [{ field: 'dtinType', operator: 'eq', value: '1' }],
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/wq/anchorPoint/GetKendoListCust',
|
||||
title: '人工站',
|
||||
params: {
|
||||
dtinType: [{ field: 'dtinType', operator: 'eq', value: '2' }],
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/wq/anchorPoint/GetKendoListCust',
|
||||
title: '栖息地水质站',
|
||||
params: {
|
||||
fhstcd: [{ field: 'fhstcd', operator: 'isnotnull' }],
|
||||
fhFlag: [{ field: 'fhFlag', operator: 'eq', value: '1' }],
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fp/point/qgc/GetKendoListCust',
|
||||
title: '过鱼设施',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-eng-server/eng/eq/eqds/GetKendoListCust',
|
||||
title: '生态流量泄放设施',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/fb/point/GetKendoListCust',
|
||||
title: '鱼类增殖站',
|
||||
params: {
|
||||
sttp: [{ field: 'sttp', operator: 'eq', value: 'FB' }],
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fhvap/GetKendoListCust',
|
||||
title: '珍稀植物园',
|
||||
params: { sttpCode: 'VP', lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fhvap/GetKendoListCust',
|
||||
title: '动物救助站',
|
||||
params: { sttpCode: 'VA', lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/fb/point/GetKendoListCust',
|
||||
title: '人工产卵场',
|
||||
params: { sttp: 'SG', lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/sw/getEngTempPointList/GetKendoListCust',
|
||||
title: '水温监测断面',
|
||||
keyType: 'wt_point',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/sw/getEngTempPointList/GetKendoListCust',
|
||||
title: '自建水温站',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }], flag: '0' }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/sw/getEngTempPointList/GetKendoListCust',
|
||||
title: '人工水温站',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }], flag: '2' }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/sw/getEngTempPointList/GetKendoListCust',
|
||||
title: '栖息地水温站',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
fhstcd: [{ field: 'fhstcd', operator: 'isnotnull' }],
|
||||
fhFlag: '1'
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fhvap/GetKendoListCust',
|
||||
title: '栖息地',
|
||||
params: { sttpCode: 'FH', lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
|
||||
{
|
||||
url: '/wmp-env-server/env/fhvap/fhPoint/GetKendoListCust',
|
||||
title: '水质监测站',
|
||||
params: { sttpCode: 'WQ', lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fhvap/fhPoint/GetKendoListCust',
|
||||
title: '水温监测站',
|
||||
params: {
|
||||
sttpCode: 'WTRV',
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fhvap/fhPoint/GetKendoListCust',
|
||||
title: '流量监测站',
|
||||
params: { sttpCode: 'ZQ', lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fhvap/fhPoint/GetKendoListCust',
|
||||
title: '视频监控',
|
||||
params: { sttpCode: 'VD', lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/vd/aiPoint/GetKendoListCust',
|
||||
title: 'AI视频监控站',
|
||||
params: { sttpCode: 'AIVD' }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/vdpoint/GetKendoListCust',
|
||||
title: '水电站监控视频',
|
||||
keyType: 'video_fbfm_point',
|
||||
params: {
|
||||
sttp: 'VD_FBFM',
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/vdpoint/GetKendoListCust',
|
||||
title: '生态流量监测断面视频',
|
||||
keyType: 'video_eqs_point',
|
||||
params: {
|
||||
sttp: 'VD_EQS',
|
||||
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/vdpoint/GetKendoListCust',
|
||||
title: '水质站运行视频',
|
||||
keyType: 'video_wq_point',
|
||||
params: {
|
||||
sttp: 'VD_WQ',
|
||||
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/vdpoint/GetKendoListCust',
|
||||
title: '过鱼设施视频',
|
||||
keyType: 'video_fp_point',
|
||||
params: {
|
||||
sttp: 'VD_FP',
|
||||
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/vdpoint/GetKendoListCust',
|
||||
title: '鱼类增殖站视频',
|
||||
keyType: 'video_fb_point',
|
||||
params: {
|
||||
sttp: 'VD_FB',
|
||||
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/vdpoint/GetKendoListCust',
|
||||
title: '栖息地视频',
|
||||
keyType: 'video_fh_point',
|
||||
params: {
|
||||
sttp: 'VD_FH',
|
||||
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/vdpoint/GetKendoListCust',
|
||||
title: '低温水减缓设施视频',
|
||||
keyType: 'video_dw_point',
|
||||
params: {
|
||||
sttp: 'VD_DW',
|
||||
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/vdpoint/GetKendoListCust',
|
||||
title: '动物救助站视频',
|
||||
keyType: 'video_va_point',
|
||||
params: {
|
||||
sttp: 'VD_VA',
|
||||
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/vdpoint/GetKendoListCust',
|
||||
title: '珍稀植物园视频',
|
||||
keyType: 'video_vp_point',
|
||||
params: {
|
||||
sttp: 'VD_VP',
|
||||
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
url: '/wmp-env-server/env/we/point/qgc/GetKendoListCust',
|
||||
title: '水生生态调查断面',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] },
|
||||
orders: '{"siteStepSort":"asc"}'
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/we/fishPoint/qgc/GetKendoListCust',
|
||||
title: '鱼类分布',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-eng-server/eng/alarmPoint/GetKendoListCust',
|
||||
title: '水电站告警情况',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/fb/point/discharge/GetKendoListCust',
|
||||
title: '水电站',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/zqpoint/GetKendoListCust',
|
||||
title: '国家水文站',
|
||||
params: { dtinType: 1, lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/zqpoint/GetKendoListCust',
|
||||
title: '自建水文站',
|
||||
params: { dtinType: 0, lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/wq/anchorPoint/GetKendoListCust',
|
||||
title: '增殖站水质站',
|
||||
params: {
|
||||
dtinType: 0,
|
||||
sttpCode: 'WQFB',
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fh/vdpoint/GetKendoListCust',
|
||||
title: '视频监控站',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/wb/point/GetKendoListCust',
|
||||
title: '气象站',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/sw/getEngTempPointList/getLastData',
|
||||
title: '水温站点',
|
||||
params: {
|
||||
logic: 'and',
|
||||
filters: []
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/wq/anchorPoint/GetKendoListCust',
|
||||
title: '水质站点',
|
||||
params: {
|
||||
logic: 'and',
|
||||
filters: [
|
||||
{
|
||||
field: 'lgtd',
|
||||
operator: 'isnotnull',
|
||||
dataType: 'string'
|
||||
},
|
||||
{
|
||||
field: 'orderIndex',
|
||||
operator: 'isnotnull',
|
||||
dataType: 'string'
|
||||
}
|
||||
]
|
||||
},
|
||||
orders: '{"orderIndex":"asc"}'
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/warn/stcd/point/GetKendoListCust',
|
||||
title: '水质告警',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'WQ' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/warn/stcd/point/GetKendoListCust',
|
||||
title: '水温告警',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'WTRV' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/warn/stcd/point/GetKendoListCust',
|
||||
title: '水位告警',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'ENG' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/warn/stcd/operatePoint/GetKendoListCust',
|
||||
title: '环保设施告警',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
yr: moment().format('YYYY')
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fp/point/built/GetKendoListCust',
|
||||
title: '在建过鱼设施-地图锚点',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fb/point/built/GetKendoListCust',
|
||||
title: '在建鱼类增殖站',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'FB' }],
|
||||
bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fb/point/built/GetKendoListCust',
|
||||
title: '在建人工产卵场',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'SG' }],
|
||||
bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fhvap/built/GetKendoListCust',
|
||||
title: '珍稀植物园-在建',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'VP' }],
|
||||
bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/fhvap/built/GetKendoListCust',
|
||||
title: '动物救助站-在建',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'VA' }],
|
||||
bldsttCcode: [{ field: 'bldsttCcode', operator: 'eq', value: '1' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/eng/eq/eqds/built/GetKendoListCust',
|
||||
title: '在建生态流量泄放设施',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
BLDSTT_CCODE: [{ field: 'BLDSTT_CCODE', operator: 'eq', value: '1' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/we/fishList/point/GetKendoList',
|
||||
title: '鱼类沿程',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/wva/point/GetKendoListCust',
|
||||
title: '野生动物监测',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }],
|
||||
sttpCode: [{ field: 'sttpCode', operator: 'eq', value: 'WVA' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/env/we/fishList/point/GetNativeRareFish',
|
||||
title: '土著珍稀鱼类',
|
||||
params: {
|
||||
rare: '1',
|
||||
specOrigin: '1',
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/te/tet/point/GetTerrestrialAnimal',
|
||||
title: '陆生动物分布',
|
||||
params: {
|
||||
lgtd: [{ field: 'lgtd', operator: 'isnotnull' }]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/wmp-env-server/sdFprdR/point/getFprdPointList',
|
||||
title: '鱼类调查装置',
|
||||
params: { lgtd: [{ field: 'lgtd', operator: 'isnotnull' }] }
|
||||
}
|
||||
];
|
||||
@ -2,6 +2,7 @@
|
||||
@use 'src/styles/ant-design-vue' as permission;
|
||||
@use './sidebar' as sidebar;
|
||||
@use './tailwind' as tailwind;
|
||||
@use './popup-styles' as popup;
|
||||
@import './iconfont/iconfont.css';
|
||||
|
||||
html,
|
||||
|
||||
422
frontend/src/styles/popup-styles.scss
Normal file
@ -0,0 +1,422 @@
|
||||
// Popup 相关样式 - 用于 map.ol.ts 中 generatePopupHtml 生成的 HTML
|
||||
|
||||
.iconDiv {
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 5px;
|
||||
font-size: 12px;
|
||||
&.smallfont {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.iconDivContent {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.iconDivTitle {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.iconDivLeft {
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.iconDivRight {
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// 标题文字自适应大小
|
||||
.iconDivTitle.title-md {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
.iconDivTitle.title-sm {
|
||||
font-size: 13px !important;
|
||||
}
|
||||
.iconDivTitle.title-xs {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
.iconDivTitle.title-xxs {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
.iconEngDiv_large_eng_built,
|
||||
.iconEngDiv_large_eng_ubuilt,
|
||||
.iconEngDiv_large_eng_nbuilt {
|
||||
width: 156px;
|
||||
height: 170px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 0 !important;
|
||||
.iconDivTitle {
|
||||
width: 100%;
|
||||
height: 48%;
|
||||
line-height: 100px;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
font-weight: normal;
|
||||
position: relative;
|
||||
&::after {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
width: 80%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
content: ' ';
|
||||
}
|
||||
}
|
||||
.iconDivContent {
|
||||
width: 100%;
|
||||
height: 52%;
|
||||
font-size: 12px;
|
||||
padding-top: 4px;
|
||||
position: relative;
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
right: 0;
|
||||
width: 2px;
|
||||
height: 62%;
|
||||
transform: translateX(-50%);
|
||||
content: ' ';
|
||||
}
|
||||
.iconDivLeft {
|
||||
width: 50%;
|
||||
padding-left: 38px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.iconDivRight {
|
||||
width: 50%;
|
||||
padding-left: 6px;
|
||||
box-sizing: border-box;
|
||||
padding-right: 34px;
|
||||
div:nth-child(1) {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.iconEngDiv_mid_eng_built,
|
||||
.iconEngDiv_mid_eng_ubuilt,
|
||||
.iconEngDiv_mid_eng_nbuilt {
|
||||
width: 150px;
|
||||
height: 112px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 0 !important;
|
||||
.iconDivTitle {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
line-height: 52px;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
font-weight: normal;
|
||||
}
|
||||
.iconDivContent {
|
||||
width: 100%;
|
||||
height: 36;
|
||||
padding: 0 10px;
|
||||
font-size: 11px;
|
||||
position: relative;
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
right: 0;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
content: ' ';
|
||||
}
|
||||
.iconDivLeft {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
}
|
||||
.iconDivRight {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.iconEngDiv-large_eng_nbuilt-0 {
|
||||
background-image: url('@/assets/images/mapTip/map-dxsdzGuihuaNetMonitor.svg');
|
||||
color: #859ea3;
|
||||
.iconDivTitle,
|
||||
.iconDivContent {
|
||||
&::after {
|
||||
background-color: #859ea3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.iconEngDiv-large_eng_ubuilt-1 {
|
||||
background-image: url('@/assets/images/mapTip/map-dxsdzZaijianNetMonitor.svg');
|
||||
color: #5389b9;
|
||||
.iconDivTitle,
|
||||
.iconDivContent {
|
||||
&::after {
|
||||
background-color: #5389b9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.iconEngDiv-large_eng_built-2 {
|
||||
background-image: url('@/assets/images/mapTip/map-dxsdzYijianNetMonitor.svg');
|
||||
color: #7dbc18;
|
||||
.iconDivTitle,
|
||||
.iconDivContent {
|
||||
&::after {
|
||||
background-color: #95c842;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.iconEngDiv-mid_eng_nbuilt-0 {
|
||||
background-image: url('@/assets/images/mapTip/map-zxsdzGuihuaNetMonitor.svg');
|
||||
color: #859ea3;
|
||||
.iconDivContent {
|
||||
&::after {
|
||||
background-color: #859ea3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.iconEngDiv-mid_eng_ubuilt-1 {
|
||||
background-image: url('@/assets/images/mapTip/map-zxsdzZaijianNetMonitor.svg');
|
||||
color: #5389b9;
|
||||
.iconDivContent {
|
||||
&::after {
|
||||
background-color: #5389b9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.iconEngDiv-mid_eng_built-2 {
|
||||
background-image: url('@/assets/images/mapTip/map-zxsdzYijianNetMonitor.svg');
|
||||
color: #7dbc18;
|
||||
.iconDivContent {
|
||||
&::after {
|
||||
background-color: #95c842;
|
||||
}
|
||||
}
|
||||
}
|
||||
.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;
|
||||
background-size: 100% auto;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 25px;
|
||||
background: url(@/assets/images/mapTip/bottom@260.png) center no-repeat;
|
||||
background-size: 100% auto;
|
||||
}
|
||||
|
||||
&-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;
|
||||
background-size: 100% auto;
|
||||
}
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
&-list {
|
||||
font-size: 14px !important;
|
||||
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 !important;
|
||||
}
|
||||
}
|
||||
|
||||
&-sub {
|
||||
margin: 0;
|
||||
padding: 4px 0 0 0;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
&-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: 190px;
|
||||
padding: 18px 0 18px;
|
||||
&::after {
|
||||
background-image: url(@/assets/images/mapTip/top@175.png);
|
||||
height: 18px;
|
||||
}
|
||||
&::before {
|
||||
background-image: url(@/assets/images/mapTip/bottom@175.png);
|
||||
height: 18px;
|
||||
}
|
||||
.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);
|
||||
}
|
||||
}
|
||||
.map-tooltip-list {
|
||||
> li {
|
||||
.__label {
|
||||
flex: 0 0 84px;
|
||||
width: 84px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.map-tooltip-middle {
|
||||
width: 225px;
|
||||
padding: 18px 0 18px;
|
||||
&::after {
|
||||
background-image: url(@/assets/images/mapTip/top@215.png);
|
||||
height: 18px;
|
||||
}
|
||||
&::before {
|
||||
background-image: url(@/assets/images/mapTip/bottom@215.png);
|
||||
height: 18px;
|
||||
}
|
||||
.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);
|
||||
}
|
||||
}
|
||||
.map-tooltip-list {
|
||||
> li {
|
||||
.__label {
|
||||
flex: 0 0 100px;
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
&.__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%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -173,11 +173,13 @@ export function downloadFileByUrl(url: string, fileName?: string) {
|
||||
document.body.removeChild(link);
|
||||
});
|
||||
}
|
||||
const modules = import.meta.glob('@/assets/legend/*.svg', { eager: true });
|
||||
const modules = import.meta.glob('@/assets/legend/*.{svg,png}', {
|
||||
eager: true
|
||||
});
|
||||
// 图例图标映射
|
||||
export const iconMap: Record<string, string> = {};
|
||||
Object.entries(modules).forEach(([path, module]) => {
|
||||
const fileName = path.match(/\/([^/]+)\.svg$/)?.[1];
|
||||
const fileName = path.match(/\/([^/]+)\.(svg|png)$/)?.[1];
|
||||
if (fileName) {
|
||||
iconMap[fileName] = (module as any).default;
|
||||
}
|
||||
@ -188,10 +190,7 @@ export const getIconPath = (icon: string): string => {
|
||||
};
|
||||
|
||||
// 动态计算表格滚动高度
|
||||
export const calcTableScrollY = (
|
||||
tableContainerRef: any,
|
||||
otherHeight: number = 112
|
||||
) => {
|
||||
export const calcTableScrollY = (tableContainerRef: any, otherHeight = 112) => {
|
||||
if (!tableContainerRef) return;
|
||||
// 获取容器高度
|
||||
const containerHeight = tableContainerRef.clientHeight;
|
||||
|
||||
3617
frontend/src/utils/popupHtmlGenerator.ts
Normal file
@ -7,7 +7,7 @@ import router from '@/router';
|
||||
// 创建 axios 实例
|
||||
const service = axios.create({
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||
timeout: 15000, // 15秒
|
||||
timeout: 25000, // 15秒
|
||||
headers: { 'Content-Type': 'application/json;charset=utf-8' }
|
||||
});
|
||||
|
||||
@ -22,7 +22,8 @@ service.interceptors.request.use(
|
||||
if (
|
||||
config.url.includes('/dec-lygk-base-server') ||
|
||||
config.url.includes('/wmp-env-server') ||
|
||||
config.url.includes('/wmp-sys-server')
|
||||
config.url.includes('/wmp-sys-server') ||
|
||||
config.url.includes('/wmp-eng-server')
|
||||
) {
|
||||
config.headers._appid = '974975A6-47FD-4C04-9ACD-68938D2992BD';
|
||||
config.headers._isolateid = '5b34aecb-adfb-4dfc-ad95-21505a9eb388';
|
||||
@ -30,7 +31,7 @@ service.interceptors.request.use(
|
||||
config.headers._sysid = '10EC2E0B-AEA9-4757-83A2-201BA1BC54E9';
|
||||
|
||||
config.headers.authorization =
|
||||
'bearer a385ef90-a17d-429f-817f-7d961594020c';
|
||||
'bearer a31a19b6-508c-4773-bde8-62df5c448183';
|
||||
config.baseURL = '/';
|
||||
} else {
|
||||
const user = useUserStoreHook();
|
||||
|
||||
@ -473,7 +473,7 @@ const ensureRowState = (index: number) => {
|
||||
const handleHbrvcdChange = async (
|
||||
hbrvcd: string,
|
||||
index: number,
|
||||
type: string = "start"
|
||||
type = "start"
|
||||
) => {
|
||||
const state = ensureRowState(index);
|
||||
editingData.value.hbrvnm = hbrvcdOptions.value.find(
|
||||
@ -504,7 +504,7 @@ const handleHbrvcdChange = async (
|
||||
}
|
||||
};
|
||||
|
||||
const handleEngChange = async (rstcd: string, index: number, type: string = "start") => {
|
||||
const handleEngChange = async (rstcd: string, index: number, type = "start") => {
|
||||
const state = ensureRowState(index);
|
||||
editingData.value.ennm = state.engOptions.find(
|
||||
(item: any) => item.stcd === rstcd
|
||||
|
||||
@ -34,13 +34,6 @@ export default ({ mode }: ConfigEnv): UserConfig => {
|
||||
rewrite: path =>
|
||||
path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '')
|
||||
},
|
||||
'/geoserver': {
|
||||
target: 'https://211.99.26.225:18085', // 地图-线上API地址
|
||||
// target: 'http://172.16.31.112:8093', // 地图-本地API地址
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
rewrite: path => path.replace(new RegExp('^/geoserver'), '/geoserver')
|
||||
},
|
||||
'/process': {
|
||||
target: 'http://localhost:5174',
|
||||
changeOrigin: true
|
||||
@ -55,6 +48,13 @@ export default ({ mode }: ConfigEnv): UserConfig => {
|
||||
'/api/dec-lygk-base-server'
|
||||
)
|
||||
},
|
||||
'/wmp-env-server': {
|
||||
target: 'https://211.99.26.225:12122',
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
rewrite: path =>
|
||||
path.replace(new RegExp('^/wmp-env-server'), '/api/wmp-env-server')
|
||||
},
|
||||
'/api/wmp-env-server': {
|
||||
target: 'https://211.99.26.225:12122',
|
||||
changeOrigin: true,
|
||||
@ -65,6 +65,16 @@ export default ({ mode }: ConfigEnv): UserConfig => {
|
||||
'/api/wmp-env-server'
|
||||
)
|
||||
},
|
||||
'/api/wmp-eng-server': {
|
||||
target: 'https://211.99.26.225:12122',
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
rewrite: path =>
|
||||
path.replace(
|
||||
new RegExp('^/api/wmp-eng-server'),
|
||||
'/api/wmp-eng-server'
|
||||
)
|
||||
},
|
||||
'/api/wmp-sys-server': {
|
||||
target: 'https://211.99.26.225:12122',
|
||||
changeOrigin: true,
|
||||
|
||||