@sword916/vae-map-plus 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +3 -0
  2. package/build/index.mjs +113 -0
  3. package/examples/App.vue +18 -0
  4. package/examples/index.js +13 -0
  5. package/examples/router/index.js +35 -0
  6. package/examples/views/amap.vue +29 -0
  7. package/examples/views/amarker.vue +58 -0
  8. package/examples/views/buffer.vue +66 -0
  9. package/examples/views/cluster.vue +74 -0
  10. package/examples/views/cover.vue +85 -0
  11. package/examples/views/draw-line.vue +49 -0
  12. package/examples/views/draw.vue +54 -0
  13. package/examples/views/echarts.vue +142 -0
  14. package/examples/views/emarker.vue +39 -0
  15. package/examples/views/image.vue +182 -0
  16. package/examples/views/index.vue +61 -0
  17. package/examples/views/lrmap.vue +108 -0
  18. package/examples/views/map.vue +82 -0
  19. package/examples/views/measure.vue +86 -0
  20. package/examples/views/parts/popup.vue +39 -0
  21. package/examples/views/parts/tooltip.vue +39 -0
  22. package/examples/views/push-area.vue +52 -0
  23. package/examples/views/push-line.vue +84 -0
  24. package/examples/views/trace.vue +49 -0
  25. package/index.html +13 -0
  26. package/jsconfig.json +17 -0
  27. package/package.json +47 -0
  28. package/public/favicon.ico +0 -0
  29. package/public/images/game.png +0 -0
  30. package/public/images/grid.png +0 -0
  31. package/public/images/marker.png +0 -0
  32. package/public/index.html +30 -0
  33. package/src/components/resize-listener/component.jsx +30 -0
  34. package/src/components/resize-listener/index.js +3 -0
  35. package/src/composables/useAutoMessage.js +41 -0
  36. package/src/composables/useContextMenu.js +99 -0
  37. package/src/composables/useMapMeasure.js +191 -0
  38. package/src/composables/useResizeObserver.js +81 -0
  39. package/src/mixins/message.js +1 -0
  40. package/src/packages/index.js +16 -0
  41. package/src/packages/vae-amap/index.js +8 -0
  42. package/src/packages/vae-amap/style.less +9 -0
  43. package/src/packages/vae-amap/vae-amap.jsx +98 -0
  44. package/src/packages/vae-cloudmap/ctrl-context-menu/index.vue +74 -0
  45. package/src/packages/vae-cloudmap/ctrl-draw/index.vue +499 -0
  46. package/src/packages/vae-cloudmap/ctrl-draw-line/index.vue +161 -0
  47. package/src/packages/vae-cloudmap/index.js +57 -0
  48. package/src/packages/vae-cloudmap/scripts/L.MarkerCluster/index.js +2690 -0
  49. package/src/packages/vae-cloudmap/scripts/L.MarkerCluster/style.css +14 -0
  50. package/src/packages/vae-cloudmap/scripts/L.Vae.CRS/index.js +212 -0
  51. package/src/packages/vae-cloudmap/scripts/L.Vae.Client/index.js +780 -0
  52. package/src/packages/vae-cloudmap/scripts/Mixin.ContextMenu/index.js +101 -0
  53. package/src/packages/vae-cloudmap/style.less +163 -0
  54. package/src/packages/vae-cloudmap/vae-cloudmap.jsx +272 -0
  55. package/src/packages/vae-map/ctrl-context-menu/index.vue +74 -0
  56. package/src/packages/vae-map/ctrl-draw/index.vue +498 -0
  57. package/src/packages/vae-map/ctrl-draw-line/index.vue +128 -0
  58. package/src/packages/vae-map/index.js +59 -0
  59. package/src/packages/vae-map/scripts/L.MarkerCluster/index.js +2690 -0
  60. package/src/packages/vae-map/scripts/L.MarkerCluster/style.css +14 -0
  61. package/src/packages/vae-map/scripts/L.Vae.CRS/index.js +114 -0
  62. package/src/packages/vae-map/scripts/L.Vae.Client/index.js +548 -0
  63. package/src/packages/vae-map/scripts/Mixin.ContextMenu/index.js +1 -0
  64. package/src/packages/vae-map/style.less +161 -0
  65. package/src/packages/vae-map/vae-lrmap.jsx +237 -0
  66. package/src/packages/vae-map/vae-map.jsx +135 -0
  67. package/src/plugins/L.AnimatedMarker/index.js +158 -0
  68. package/src/plugins/L.EchartsLayer/index.js +339 -0
  69. package/src/plugins/L.ElasticMarker/index.js +162 -0
  70. package/src/plugins/L.FootageCalculator.Area/index.js +263 -0
  71. package/src/plugins/L.FootageCalculator.Line/index.js +273 -0
  72. package/src/plugins/L.GeoUtil/buffer.js +67 -0
  73. package/src/plugins/L.GeoUtil/index.js +284 -0
  74. package/src/plugins/L.Glyphicon/index.js +91 -0
  75. package/src/plugins/L.Glyphicon/style.less +37 -0
  76. package/src/plugins/L.MarkerClusterX/index.js +93 -0
  77. package/src/plugins/L.MarkerClusterX/style.less +162 -0
  78. package/src/plugins/L.SafeDivOverlay/index.js +55 -0
  79. package/src/plugins/L.TileLayer.ChinaProvider/index.js +108 -0
  80. package/src/plugins/L.VuePopup/index.js +67 -0
  81. package/src/plugins/L.VueTooltip/index.js +63 -0
  82. package/src/plugins/Mixin.Map.Measure/index.js +248 -0
  83. package/src/plugins/globals/index.js +7 -0
  84. package/src/utils/index.js +36 -0
  85. package/src/utils/resize-event.js +45 -0
  86. package/vite.config.mjs +25 -0
@@ -0,0 +1,14 @@
1
+ .leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
2
+ -webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in;
3
+ -moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in;
4
+ -o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in;
5
+ transition: transform 0.3s ease-out, opacity 0.3s ease-in;
6
+ }
7
+
8
+ .leaflet-cluster-spider-leg {
9
+ /* stroke-dashoffset (duration and function) should match with leaflet-marker-icon transform in order to track it exactly */
10
+ -webkit-transition: -webkit-stroke-dashoffset 0.3s ease-out, -webkit-stroke-opacity 0.3s ease-in;
11
+ -moz-transition: -moz-stroke-dashoffset 0.3s ease-out, -moz-stroke-opacity 0.3s ease-in;
12
+ -o-transition: -o-stroke-dashoffset 0.3s ease-out, -o-stroke-opacity 0.3s ease-in;
13
+ transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in;
14
+ }
@@ -0,0 +1,114 @@
1
+ // 偏移墨卡托投影
2
+ const OffsetSphericalMercator = (offset = L.point(0, 0)) => {
3
+
4
+ const Mercator = L.Projection.SphericalMercator
5
+ const R = Mercator.R
6
+ const D = Math.PI / 180
7
+
8
+ return L.extend({}, Mercator, {
9
+ project(latlng) {
10
+ const max = Mercator.MAX_LATITUDE
11
+ const lat = Math.max(Math.min(max, latlng.lat), -max)
12
+ const sin = Math.sin(lat * D)
13
+ const point = L.point(R * latlng.lng * D, R * Math.log((1 + sin) / (1 - sin)) / 2)
14
+
15
+ return point.add(offset)
16
+ },
17
+
18
+ unproject(point) {
19
+ const [x, y] = point.subtract(offset)
20
+
21
+ return L.latLng((2 * Math.atan(Math.exp(y / R)) - (Math.PI / 2)) * D, x * D / R)
22
+ }
23
+ })
24
+ }
25
+
26
+ // LRMAP常用CRS
27
+ const fns = {
28
+
29
+ SIMPLE(count = 2) {
30
+ const ratio = Math.pow(0.1, count)
31
+
32
+ return L.extend({}, L.CRS.Simple, {
33
+ scale: zoom => ratio * Math.pow(2, zoom),
34
+ zoom: scale => Math.log(scale / ratio) / Math.log(2)
35
+ })
36
+ },
37
+
38
+ OFFSET_EPSG3857(offset = L.point(0, 0)) {
39
+
40
+ return L.extend({}, L.CRS.EPSG3857, {
41
+ projection: OffsetSphericalMercator(offset)
42
+ })
43
+ },
44
+
45
+ BJ54(x,options={}) {
46
+ // console.log(options);
47
+ let resolutions = [307.2, 153.6, 76.8, 38.4, 19.2, 9.6, 4.8, 2.4, 1.2, 0.6, 0.3, 0.15, 0.075, 0.0375, 0.01875]
48
+ //为了解决矿政的1:500000的图纸新增了一个分辨率的参数,如果另外的项目需要改动,联系史新国
49
+ if(options.resolutions){
50
+ resolutions=options.resolutions
51
+ };
52
+ // 确定投影带和带号
53
+ let pType, pCode
54
+ if (x > 25000000 && x < 40000000) {
55
+ pType = 3
56
+ pCode = parseInt(x / 1000000)
57
+ } else if (x > 12000000 && x < 22000000) {
58
+ pType = 6
59
+ pCode = parseInt(x / 1000000)
60
+ }
61
+ // 确定proj4的各项参数:ESPG代码,中央经线,东伪偏移
62
+ let EPSGCode, lon_0, x_0
63
+ if (pCode >= 0) {
64
+ if (pType == 3) {
65
+ EPSGCode = 2376 + pCode
66
+ lon_0 = pCode * 3
67
+ x_0 = 1000000 * pCode + 500000
68
+ } else if (pType == 6) {
69
+ EPSGCode = 2325 + pCode
70
+ lon_0 = pCode * 6 - 3
71
+ x_0 = 1000000 * pCode + 500000
72
+ }
73
+ }
74
+ // 返回3度带/6度带坐标系
75
+ if (EPSGCode) {
76
+ let proj = '+proj=tmerc +lat_0=0 +lon_0=' + lon_0 + ' +k=1 +x_0=' + x_0 + ' +y_0=0 +ellps=krass +units=m +no_defs no_defs'
77
+ return new L.Proj.CRS('EPSG:' + EPSGCode, proj, { resolutions:resolutions })
78
+ } else {
79
+ return this.SIMPLE()
80
+ }
81
+ },
82
+
83
+ XA80(x) {
84
+ let EPSGCode = 900099,
85
+ x_0 = 0,
86
+ lon_0 = 0,
87
+ pcode = parseInt(x / 1000000)
88
+ if (pcode > 0) {
89
+ lon_0 = pcode * 3
90
+ x_0 = 1000000 * pcode + 500000
91
+ EPSGCode = 2376 + pcode
92
+ }
93
+ let proj = '+proj=tmerc +lat_0=0 +lon_0=' + lon_0 + ' +k=1 +x_0=' + x_0 + ' +y_0=0 +a=6378140 +b=6356755.288157528 +units=m +no_defs no_defs'
94
+ let resolutions = [307.2, 153.6, 76.8, 38.4, 19.2, 9.6, 4.8, 2.4, 1.2, 0.6, 0.3, 0.15, 0.075, 0.0375, 0.01875]
95
+ return new L.Proj.CRS('EPSG:' + EPSGCode, proj, { resolutions, origin: [0, 0] })
96
+ },
97
+ CGCS2000(options={}){
98
+ let resolutions = [307.2, 153.6, 76.8, 38.4, 19.2, 9.6, 4.8, 2.4, 1.2, 0.6, 0.3, 0.15, 0.075, 0.0375, 0.01875]
99
+ if(options.resolutions){
100
+ resolutions=options.resolutions
101
+ };
102
+ let origin= [0, 0]
103
+ if(options.origin){
104
+ origin=options.origin
105
+ };
106
+ return new L.Proj.CRS("EPSG:4525","+proj=tmerc +lat_0=0 +lon_0=111 +k=1 +x_0=37500000 +y_0=0 +ellps=GRS80 +units=m +no_defs +type=crs",{
107
+ resolutions: resolutions,
108
+ origin: origin
109
+ });
110
+ }
111
+ }
112
+
113
+ L.Vae = L.Vae || {}
114
+ L.Vae.CRS = L.extend(L.Vae.CRS || {}, fns)
@@ -0,0 +1,548 @@
1
+ import axios from 'axios'
2
+ import { idGen, getTreeNode } from '@/utils'
3
+
4
+ L.Vae = L.Vae || {}
5
+
6
+ // LRMAP客户端
7
+ L.Vae.Client = L.Evented.extend({
8
+
9
+ options: {},
10
+
11
+ requestOptions: {},
12
+
13
+ leafletOptions: {},
14
+
15
+ extent: [],
16
+
17
+ treeLayers: [],
18
+
19
+ visibleKeys: [],
20
+
21
+ initialize(options) {
22
+ this.options = options
23
+ this.requestOptions = { url: null, uid: null, dsid: null, dsname: null }
24
+ this.leafletOptions = {}
25
+ },
26
+
27
+ /**
28
+ * 连接地图服务,构建地图参数
29
+ * @param {Boolean} alert 是否提示参数错误
30
+ */
31
+ async start({ alert } = {}) {
32
+ return new Promise(async resolve => {
33
+ for (let v of ['url', 'dsname']) {
34
+ const value = this.options ? this.options[v] : null
35
+ const message = `参数 options.${v} 无效`
36
+ if (!_.isString(value) || value.trim().length == 0) {
37
+ if (alert) {
38
+ this.fire('message', { message, messageType: 'error' })
39
+ }
40
+ return
41
+ }
42
+ }
43
+ this.requestOptions.uid = this.options?.uid || `vae_client_${idGen()}`
44
+
45
+ try {
46
+ this.fire('openmask', { text: `正在 获取图元信息` })
47
+ const metaData = (await axios.get(this.options.url + 'map/getMeta', {
48
+ params: {
49
+ uid: this.requestOptions.uid,
50
+ dsname: this.options.dsname
51
+ }
52
+ })).data
53
+ this.fire('closemask')
54
+ if (metaData.status == 'success') {
55
+ this.buildMapOptions(metaData.result)
56
+ resolve(true)
57
+ } else {
58
+ console.error(metaData.errinfo)
59
+ this.fire('message', { message: "未获取到正确的图元信息", messageType: 'error' })
60
+ resolve(false)
61
+ }
62
+ } catch (error) {
63
+ console.error(error)
64
+ this.fire('message', { message: "获取图元失败,请检查地图服务和请求参数", messageType: 'error' })
65
+ this.fire('closemask')
66
+ resolve(false)
67
+ }
68
+ })
69
+ },
70
+
71
+ // 构建地图配置项
72
+ buildMapOptions({ dsid, extent }) {
73
+ try {
74
+ // 参数整理
75
+ if (dsid) {
76
+ this.requestOptions.url = this.options.url
77
+ this.requestOptions.dsid = dsid
78
+ this.requestOptions.dsname = this.options.dsname
79
+ } else {
80
+ throw new Error('数据源dsid错误')
81
+ }
82
+ // 构建配置
83
+ if (Array.isArray(extent) && extent.length == 4) {
84
+ // extent
85
+ this.extent = extent
86
+ let centerX = (extent[0] + extent[2]) * 0.5
87
+ let centerY = (extent[1] + extent[3]) * 0.5
88
+ // crs
89
+ let crs = this.options.crs || L.Vae.CRS.SIMPLE()
90
+ if (crs == 'bj54') {
91
+ crs = L.Vae.CRS.BJ54(centerX,this.options)
92
+ } else if (crs == 'xa80') {
93
+ crs = L.Vae.CRS.XA80(centerX)
94
+ } else if (crs == 'simple') {
95
+ crs = L.Vae.CRS.SIMPLE()
96
+ }else if (crs == 'CGCS2000' || crs == 'cgcs2000') {
97
+ crs = L.Vae.CRS.CGCS2000(this.options)
98
+ }
99
+ // wmscrs
100
+ let wmscrs = this.options.wmscrs || crs
101
+ if (wmscrs == 'bj54') {
102
+ wmscrs = L.Vae.CRS.BJ54(centerX)
103
+ } else if (wmscrs == 'xa80') {
104
+ wmscrs = L.Vae.CRS.XA80(centerX)
105
+ } else if (crs == 'simple') {
106
+ wmscrs = L.Vae.CRS.SIMPLE()
107
+ }else if (crs == 'CGCS2000' || crs == 'cgcs2000') {
108
+ wmscrs = L.Vae.CRS.CGCS2000(this.options)
109
+ }
110
+ // center
111
+ const center = this.options.center || wmscrs.unproject(L.point(centerX, centerY))
112
+ // maxzoom
113
+ const maxZoom = this.options.maxZoom ? this.options.maxZoom :
114
+ (crs.options && crs.options.resolutions) ? crs.options.resolutions.length - 1 : 25
115
+ // bounds
116
+ const corner1 = wmscrs.unproject(L.point(extent[0], extent[1]))
117
+ const corner2 = wmscrs.unproject(L.point(extent[2], extent[3]))
118
+ const bounds = L.latLngBounds(corner1, corner2)
119
+ this.leafletOptions = { crs, wmscrs, center, maxZoom, bounds }
120
+ } else {
121
+ throw new Error('地图属性extent错误')
122
+ }
123
+ } catch (e) {
124
+ console.error(e)
125
+ this.fire('message', { message: "地图参数构建错误", type: 'error' })
126
+ }
127
+ },
128
+
129
+ /**
130
+ * 请求地图服务
131
+ * @param {string} api 请求动作
132
+ * @param {string} message 提示消息
133
+ * @param {object} params 额外参数
134
+ * @param {boolean} forceResolve 请求结果无效时,强制resolve而不是reject
135
+ * @param {boolean} checkResult 是否校验结果
136
+ * @param {boolean} loadMask 是否添加遮罩层
137
+ */
138
+ requestServer({ api, message = '加载数据', params = {}, forceResolve, checkResult = true, loadMask = true }) {
139
+ return new Promise((resolve, reject) => {
140
+ if (api) {
141
+ if (loadMask) { this.fire('openmask', { text: `正在 ${message}` }) }
142
+ axios.post(`${this.requestOptions.url}${api}`, L.extend({
143
+ uid: this.requestOptions.uid,
144
+ dsid: this.requestOptions.dsid
145
+ }, params)).then(result => {
146
+ if (checkResult) {
147
+ const data = result.data
148
+ if (data && data.status == 'success') {
149
+ resolve(data.result)
150
+ } else {
151
+ if (forceResolve) {
152
+ console.error(data.errinfo)
153
+ resolve('')
154
+ } else {
155
+ this.fire('message', { message: `${message}结果无效`, messageType: 'error' })
156
+ console.error(data.errinfo)
157
+ reject(data.errinfo)
158
+ }
159
+ }
160
+ } else { resolve(result.data) }
161
+ }).catch(e => {
162
+ this.fire('message', { message: `${message}失败,请检查地图服务和和请求参数`, messageType: 'error' })
163
+ console.error(e)
164
+ reject(e)
165
+ }).finally(() => {
166
+ if (loadMask) { this.fire('closemask') }
167
+ })
168
+ }
169
+ })
170
+ },
171
+
172
+ // 设置默认图层
173
+ async setDefaultLayers() {
174
+ this.fire('openmask', { text: `正在 加载默认图层` })
175
+ const { defaultLayers, defaultLayerSets, disabledLayerSets, layerTreeType } = this.options
176
+ await this.formatLayerGroup(layerTreeType, disabledLayerSets)
177
+ if (Array.isArray(defaultLayers)) {
178
+ this.visibleKeys = await this.showLayers(defaultLayers, { loadMask: false, refreshTiles: false })
179
+ } else if (Array.isArray(defaultLayerSets)) {
180
+ this.visibleKeys = await this.showLayerSets(defaultLayerSets, { loadMask: false, refreshTiles: false })
181
+ } else if (Array.isArray(disabledLayerSets)) {
182
+ await this.showLayers(this.visibleKeys, { loadMask: false, refreshTiles: false })
183
+ }
184
+ this.fire('closemask')
185
+ },
186
+
187
+ /**
188
+ * 初始化图层信息
189
+ * 有协同服务时,处理为树结构
190
+ * 无协同服务时,处理为列表结构
191
+ * @param {enum} type 类型,'leaf'(默认):叶子节点为实际图层,'branch':叶子节点为末级图集,图层置于layers属性
192
+ * @param {array<string>} disabledLayerSets 禁用的图集,支持'x>y>z'的选择方式
193
+ * @returns {treeLayers,visibleLayers}
194
+ * @property {array<object>} treeLayers 树结构:{id,label,children}
195
+ * @property {array<string>} visibleKeys 可见图层keys
196
+ */
197
+ async formatLayerGroup(type = 'leaf', disabledLayerSets = []) {
198
+ // 处理结果:树结构和IDS
199
+ // 处理结果:树结构和IDS
200
+ let treeLayers = [], visibleKeys = []
201
+ let {treeLayersGroup} =this.options;
202
+ // 请求数据
203
+ const _layers = await this.requestServer({
204
+ api: 'layer/getlayers',
205
+ message: '获取图层',
206
+ loadMask: false
207
+ })
208
+ let _groups;
209
+ //如果不用协同服务,业务自定义接口,可以按时业务需求按照layer/showlayers接口格式传入数据
210
+ if(treeLayersGroup){
211
+ _groups=treeLayersGroup;
212
+ }else {
213
+ _groups = await this.requestServer({
214
+ api: 'layer/getlayergroups',
215
+ params: { type: 1 },
216
+ message: '获取图层分组',
217
+ forceResolve: true,
218
+ loadMask: false
219
+ })
220
+ }
221
+
222
+
223
+ // let treeLayers = [], visibleKeys = []
224
+ // // 请求数据
225
+ // const _layers = await this.requestServer({
226
+ // api: 'layer/getlayers',
227
+ // message: '获取图层',
228
+ // loadMask: false
229
+ // })
230
+ // const _groups = await this.requestServer({
231
+ // api: 'layer/getlayergroups',
232
+ // params: { type: 1 },
233
+ // message: '获取图层分组',
234
+ // forceResolve: true,
235
+ // loadMask: false
236
+ // })
237
+ // 组织数据
238
+ if (_layers && _layers.layers) {
239
+ // 有协同:树结构
240
+ if (_groups && _groups.layergroups) {
241
+ _groups.layergroups.forEach((g, i) => {
242
+ // 初始化分支
243
+ let branch = treeLayers
244
+ // 叶子节点,具体图层
245
+ let leafLayers = []
246
+ g.layers.forEach(v => {
247
+ const target = _.find(_layers.layers, { name: v })
248
+ if (target) {
249
+ const id = `LEAF_${i}_${target.guid}`
250
+ if (target.visible) {
251
+ visibleKeys.push(id)
252
+ }
253
+ leafLayers.push({ id, label: v })
254
+ }
255
+ })
256
+ // n1^n2^n3
257
+ const labels = _.split(g.name, '^')
258
+ labels.forEach((l, j) => {
259
+ // 当前层级
260
+ const level = j + 1
261
+ // 确认节点
262
+ let index = _.findIndex(branch, { label: l })
263
+ // 新增空节点
264
+ if (index < 0) {
265
+ index = branch.length
266
+ branch.push({ id: `NODE_${i}_${j}`, label: l, level, children: [] })
267
+ }
268
+ // 合并节点
269
+ if (j == labels.length - 1) {
270
+ // 添加层级
271
+ const leafLayersWithLevel = leafLayers.map(node => _.merge(node, { level: level + 1 }))
272
+ // 叶子
273
+ if (type == 'leaf') {
274
+ branch[index].children = _.concat(branch[index].children, leafLayersWithLevel)
275
+ }
276
+ // 枝干
277
+ else if (type == 'branch') {
278
+ branch[index].layers = _.concat(branch[index].children, leafLayersWithLevel)
279
+ if (g.visible) {
280
+ visibleKeys.push(branch[index].id)
281
+ }
282
+ }
283
+ } else {
284
+ // 下钻当前分支
285
+ branch = branch[index].children
286
+ }
287
+ })
288
+ })
289
+ }
290
+ // 无协同:列表结构
291
+ else {
292
+ _layers.layers.forEach(v => {
293
+ if (v.name && v.name !== "0") {
294
+ treeLayers.push({
295
+ id: v.guid,
296
+ label: v.name
297
+ })
298
+ if (v.visible) {
299
+ visibleKeys.push(v.guid)
300
+ }
301
+ }
302
+ })
303
+ }
304
+
305
+ // 处理禁用的图集
306
+ if (Array.isArray(disabledLayerSets) && disabledLayerSets.length > 0) {
307
+ let disabledKeys = []
308
+ let disabledAllKeys = []
309
+ disabledLayerSets.forEach(set => {
310
+ let node
311
+ set.split('>').forEach(v => {
312
+ if (v) {
313
+ node = getTreeNode(node ? [node] : treeLayers, { label: v })
314
+ }
315
+ })
316
+ if (node) {
317
+ disabledKeys.push(node.id)
318
+ }
319
+ })
320
+ if (disabledKeys.length > 0) {
321
+ // 获取节点下的图层
322
+ const collectLayers = node => {
323
+ let result = []
324
+ if (Array.isArray(node.children) && node.children.length > 0) {
325
+ node.children.forEach(v => {
326
+ result = _.concat(result, collectLayers(v))
327
+ })
328
+ } else {
329
+ result = _.concat(result, node.layers || node)
330
+ }
331
+ return result
332
+ }
333
+ // 去除禁用的节点集
334
+ const collectNodes = node => {
335
+ let result = node
336
+ if (_.includes(disabledKeys, node.id)) {
337
+ result = null
338
+ disabledAllKeys.push(node.id)
339
+ collectLayers(node).forEach(v => {
340
+ disabledAllKeys.push(v.id)
341
+ })
342
+ } else {
343
+ let children = result.children
344
+ if (children && children.length > 0) {
345
+ result.children = _.compact(children.map(v => collectNodes(v)))
346
+ }
347
+ }
348
+ return result
349
+ }
350
+ // 更新图层树和全量keys
351
+ treeLayers = _.compact(treeLayers.map(v => collectNodes(v)))
352
+ visibleKeys = _.pull(visibleKeys, ..._.uniq(disabledAllKeys))
353
+ }
354
+ }
355
+
356
+ this.treeLayers = treeLayers
357
+ this.visibleKeys = visibleKeys
358
+ }
359
+ },
360
+
361
+ /**
362
+ * 显示指定图层
363
+ * @param {array} nodes 图层节点集,兼容keys/leaf节点/branch节点
364
+ * @param {boolean} args.loadMask 是否添加遮罩层
365
+ * @param {boolean} args.refreshTiles 是否刷新瓦片
366
+ * @returns {array} 对应的图层keys
367
+ */
368
+ async showLayers(nodes = [], args = { loadMask: true, refreshTiles: true }) {
369
+ // 参数对象转义
370
+ const loadMask = _.isUndefined(args.loadMask) ? true : !!args.loadMask
371
+ const refreshTiles = _.isUndefined(args.refreshTiles) ? true : !!args.refreshTiles
372
+ // 关闭全部图层
373
+ await this.requestServer({
374
+ api: 'layer/hidelayers',
375
+ params: { type: 'all' },
376
+ message: '关闭全部图层',
377
+ loadMask
378
+ })
379
+ const nodesToLabels = ns => {
380
+ let ls = [], ks = []
381
+ if (Array.isArray(ns)) {
382
+ const getLabelByKey = (tree, key) => {
383
+ let labels = []
384
+ function doRecursion(array) {
385
+ for (let node of array) {
386
+ if (node.id == key) {
387
+ if (Array.isArray(node.layers)) {
388
+ labels = node.layers.map(v => v.label)
389
+ } else {
390
+ labels = [node.label]
391
+ }
392
+ break
393
+ } else if (Array.isArray(node.children) && node.children.length > 0) {
394
+ doRecursion(node.children)
395
+ }
396
+ }
397
+ }
398
+ doRecursion(tree)
399
+ return labels
400
+ }
401
+ ns.forEach(n => {
402
+ if (typeof (n) == 'string') {
403
+ ls = _.concat(ls, getLabelByKey(this.treeLayers, n))
404
+ ks.push(n)
405
+ } else if (typeof (n) == 'object') {
406
+ if (Array.isArray(n.layers)) {
407
+ ls = _.concat(ls, n.layers.map(v => v.label))
408
+ ks = _.concat(ls, n.layers.map(v => v.id))
409
+ } else {
410
+ ls.push(n.label)
411
+ ks.push(n.id)
412
+ }
413
+ }
414
+ })
415
+ }
416
+ return [ls, ks]
417
+ }
418
+ const [labels, keys] = nodesToLabels(nodes)
419
+ await this.requestServer({
420
+ api: 'layer/showlayers',
421
+ params: { layers: _.join(labels) },
422
+ message: '打开指定图层',
423
+ loadMask
424
+ })
425
+ if (refreshTiles) {
426
+ this.fire('refreshtilelayer')
427
+ }
428
+ this.visibleKeys = keys
429
+
430
+ return this.visibleKeys
431
+ },
432
+
433
+ /**
434
+ * 显示指定图组,支持'xx>yy>zz'形式的精确选择
435
+ * @param {array} sets 图组名称
436
+ * @param {boolean} args.loadMask 是否添加遮罩层
437
+ * @param {boolean} args.refreshTiles 是否刷新瓦片
438
+ * @returns {array} 对应的图层keys
439
+ */
440
+ async showLayerSets(sets = [], args = { loadMask: true, refreshTiles: true }) {
441
+ // 参数对象转义
442
+ const loadMask = _.isUndefined(args.loadMask) ? true : !!args.loadMask
443
+ const refreshTiles = _.isUndefined(args.refreshTiles) ? true : !!args.refreshTiles
444
+ if (_.isString(sets) && sets.length > 0) {
445
+ sets = [sets]
446
+ }
447
+ if (this.treeLayers.length > 0) {
448
+ // 获取目标节点的图层集
449
+ const collectLayers = node => {
450
+ let result = []
451
+ if (Array.isArray(node.children) && node.children.length > 0) {
452
+ node.children.forEach(v => {
453
+ result = _.concat(result, collectLayers(v))
454
+ })
455
+ } else {
456
+ result = _.concat(result, node.layers || node)
457
+ }
458
+ return result
459
+ }
460
+
461
+ // 组织并定位图集
462
+ let keys = []
463
+ sets.forEach(set => {
464
+ let node
465
+ set.split('>').forEach(v => {
466
+ if (v) {
467
+ node = getTreeNode(node ? [node] : this.treeLayers, { label: v })
468
+ }
469
+ })
470
+ if (node) {
471
+ keys.push(node.id)
472
+ collectLayers(node).forEach(v => {
473
+ keys.push(v.id)
474
+ })
475
+ }
476
+ })
477
+ await this.showLayers(keys, { loadMask, refreshTiles })
478
+ return keys
479
+ }
480
+ },
481
+
482
+ /**
483
+ * 查询实体信息
484
+ * @param {object} params 查询参数
485
+ * @param {boolean} loadMask 是否添加遮罩层
486
+ */
487
+ queryEntity(params = {}, loadMask) {
488
+ return this.requestServer({
489
+ api: 'query/entity',
490
+ params,
491
+ message: '查询实体',
492
+ loadMask
493
+ })
494
+ },
495
+
496
+ // 获取缩略图
497
+ getThumbnail() {
498
+ return new Promise(resolve => {
499
+ if (this.extent.length == 4) {
500
+ const { url, dsid, uid } = this.requestOptions
501
+ axios.get(`${url}wmsmap/getmap`, {
502
+ params: {
503
+ dsid,
504
+ uid,
505
+ request: 'GetMap',
506
+ service: 'WMS',
507
+ width: 256,
508
+ height: 256,
509
+ format: 'image/png',
510
+ transparent: true,
511
+ version: '1.1.1',
512
+ bbox: _.join(this.extent, ','),
513
+ },
514
+ responseType: 'arraybuffer'
515
+ }).then(result => {
516
+ const base64Data = btoa(new Uint8Array(result.data).reduce((data, byte) => data + String.fromCharCode(byte), ''))
517
+ resolve(`data:image/png;base64,${base64Data}`)
518
+ })
519
+ }
520
+ })
521
+ },
522
+
523
+
524
+ // 获取切片图层对象
525
+ // 适用于requestOptions、leafletOptions以及图层状态已经准备的场景
526
+ currentTileLayer() {
527
+ const { url, dsid, uid } = this.requestOptions
528
+ const { wmscrs, maxZoom } = this.leafletOptions
529
+ const wmsUrl = `${url}wmsmap/getmap?dsid=${dsid}&uid=${uid}&tid=${idGen()}`
530
+ return L.tileLayer.wms(wmsUrl, {
531
+ format: 'image/png',
532
+ transparent: true,
533
+ crs: wmscrs,
534
+ maxZoom: maxZoom
535
+ })
536
+ },
537
+
538
+ // 生成切片图层对象
539
+ async createTileLayer({ beforeCreate } = {}) {
540
+ await this.start()
541
+ if (_.isFunction(beforeCreate)) {
542
+ await beforeCreate(this)
543
+ }
544
+ await this.setDefaultLayers()
545
+ return this.currentTileLayer()
546
+ }
547
+
548
+ })
@@ -0,0 +1 @@
1
+ export { useContextMenu as default } from '@/composables/useContextMenu'