vue2-client 1.22.14 → 1.22.16

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 (23) hide show
  1. package/.idea/MarsCodeWorkspaceAppSettings.xml +7 -0
  2. package/.idea/encodings.xml +6 -0
  3. package/.idea/gradle.xml +7 -0
  4. package/.idea/misc.xml +5 -5
  5. package/.idea/modules.xml +1 -1
  6. package/package.json +1 -1
  7. package/src/assets/svg/unknown-icon.svg +3 -3
  8. package/src/base-client/components/common/AfMap/InfoWindowComponent.vue +141 -141
  9. package/src/base-client/components/common/AfMap/demo.vue +492 -492
  10. package/src/base-client/components/common/AmapMarker/index.js +3 -3
  11. package/src/base-client/components/common/FileImage/FileImageGroup.vue +14 -1
  12. package/src/base-client/components/common/ImagePreviewModal/ImagePreviewModal.vue +16 -4
  13. package/src/base-client/components/common/XDetailsView/index.js +3 -3
  14. package/src/base-client/components/common/XFormGroupDetails/index.js +3 -3
  15. package/src/base-client/components/common/XInspectionDetailDrawer/components/AiDeviceStatus.vue +53 -6
  16. package/src/base-client/components/common/XInspectionDetailDrawer/components/CheckItems.vue +28 -35
  17. package/src/base-client/components/common/XInspectionDetailDrawer/components/DeviceStatus.vue +80 -5
  18. package/src/base-client/components/common/XInspectionDetailDrawer/components/HazardPhotos.vue +49 -1
  19. package/src/base-client/components/common/XInspectionDetailDrawer/demo.vue +3 -3
  20. package/src/base-client/components/common/XInspectionDetailDrawer/index.vue +191 -4
  21. package/src/components/ImagePreview/ImagePreview.vue +323 -323
  22. package/tests/unit/a.log +0 -0
  23. /package/.idea/{vue2-client.iml → af-vue2-client.iml} +0 -0
@@ -1,492 +1,492 @@
1
- <template>
2
- <div class="demo-page" :style="{ height: '87vh' }">
3
- <AfMap
4
- v-if="gisConfig && webConfig"
5
- ref="mapTool"
6
- class="map-area"
7
- map-options-name="GisHomeConfig"
8
- serviceName="af-linepatrol"
9
- :show-group-id-arr="showGroupIdArr"
10
- :get-dynamic-icon="getDynamicIcon"
11
- :handle-svg-error="handleSvgError"
12
- @closeAllActiveBusiness="closeAllActiveBusiness"
13
- @inited="handleInited"
14
- @loading-change="loading = $event"
15
- @dock-click="handleDockClick"
16
- @panel-select="panelSelect"
17
- @wms-click="handleWmsClick"
18
- @map-click="handleMapClick"
19
- />
20
-
21
- <div v-if="tipMessage" class="map-tip">
22
- {{ tipMessage }}
23
- </div>
24
- </div>
25
- </template>
26
-
27
- <script>
28
- import AfMap from '@vue2-client/base-client/components/common/AfMap/map/index.vue'
29
- import {getConfigByNameAsync, runLogic} from '@vue2-client/services/api/common'
30
- import { mapState } from 'vuex'
31
- import InfoWindowComponent from '@vue2-client/base-client/components/common/AfMap/InfoWindowComponent.vue'
32
- export default {
33
- name: 'MapDemo',
34
- components: {
35
- AfMap,
36
- InfoWindowComponent
37
- },
38
- computed: {
39
- ...mapState('account', { currUser: 'user' }),
40
- },
41
- data () {
42
- return {
43
- inited: false,
44
- loading: false,
45
- groups: [],
46
- currentEngine: 'OPENLAYERS',
47
- mapViewMode: '3D',
48
- mapConfig: {},
49
- tipMessage: '',
50
- gisConfig: null,
51
- webConfig: null,
52
- // WMS点击查询事件是否开启
53
- wmsClickEnabled: false,
54
- showGroupIdArr: ['line-patrol-plan-point']
55
- }
56
- },
57
- async created () {
58
- this.mapConfig = await getConfigByNameAsync('GisHomeConfig', 'af-linepatrol')
59
- this.pageSize = this.mapConfig.queryResultPageSize || 20
60
- this.businessLayers = this.mapConfig?.businessLayers || []
61
- this.gisConfig = await getConfigByNameAsync('gisConfig', 'af-linepatrol')
62
- this.webConfig = await getConfigByNameAsync('webConfig', 'af-linepatrol')
63
- },
64
- async mounted () {
65
- },
66
- methods: {
67
- getDynamicIcon(iconName) {
68
- // console.log(iconName)
69
- if (!iconName) {
70
- console.warn('svgName 未定义,使用默认SVG')
71
- return require('@vue2-client/assets/svg/unknown-icon.svg')
72
- }
73
- try {
74
- return require(`@vue2-client/assets/svg/${iconName}.svg`)
75
- } catch (error) {
76
- console.warn(`SVG ${iconName} 未找到,使用默认SVG`, error)
77
- return require('@vue2-client/assets/svg/unknown-icon.svg')
78
- }
79
- },
80
- handleSvgError(event) {
81
- console.warn('图片加载失败,使用默认图片')
82
- // 设置默认图片
83
- event.target.src = require('@vue2-client/assets/svg/unknown-icon.svg')
84
- },
85
- // ===== 生命周期 & 初始化 =====
86
- async handleInited() {
87
- this.inited = true
88
- this.currentEngine = this.$refs.mapTool.getCurrentEngine()
89
- if (this.$refs.mapTool.getMapViewMode) {
90
- this.mapViewMode = this.$refs.mapTool.getMapViewMode() || '3D'
91
- }
92
- // 添加一个demo图层
93
- const defaultParams = {}
94
- if (this.webConfig?.setting?.isGroup) {
95
- defaultParams.f_orgid = this.currUser?.orgid || this.currUser?.operaInfo?.f_orgid || this.currUser?.operInfo?.f_orgid
96
- }
97
- const getMarkerData = async (params) => {
98
- const param = {
99
- endDate: params?.endDate || this.getNowDay()
100
- }
101
- if (params?.f_orgid) {
102
- param.f_orgid = params?.f_orgid || params?.orgid
103
- }
104
- try {
105
- const locationList = await runLogic('getPatrolTaskPoints', param, 'af-linepatrol')
106
- return locationList.map(item => {
107
- // eslint-disable-next-line camelcase
108
- const {f_longitude, f_latitude, f_state, f_check_state, ...rest} = item
109
- return {
110
- lng: Number(f_longitude),
111
- lat: Number(f_latitude),
112
- icon: (() => {
113
- let iconUrl = ''
114
- // eslint-disable-next-line camelcase
115
- if (f_state === '正常') {
116
- iconUrl = this.getDynamicIcon('inspected')
117
- }
118
- // eslint-disable-next-line camelcase
119
- if (f_state === '有隐患') {
120
- iconUrl = this.getDynamicIcon('pointhidden')
121
- }
122
- // eslint-disable-next-line camelcase
123
- if (f_check_state === '已检') {
124
- iconUrl = this.getDynamicIcon('checked')
125
- }
126
- return iconUrl
127
- })(),
128
- // eslint-disable-next-line camelcase
129
- f_state,
130
- // eslint-disable-next-line camelcase
131
- f_check_state,
132
- name: item.f_name,
133
- ...rest
134
- }
135
- })
136
- // 处理最新的数据
137
- } catch (e) {
138
- console.log('>>>>获取固定点位失败', e)
139
- return []
140
- }
141
- }
142
- // 点击巡检计划
143
- const onClickLinePatrolPlanPoint = async (mapService, marker, markerOptions) => {
144
- console.warn('>> 点击巡检计划', marker, markerOptions)
145
-
146
- try {
147
- const data = await runLogic('getPointAndPlanByPlanPointIdLogic', { id: marker.id }, 'af-linepatrol')
148
- console.warn('>> 获取到的数据', data)
149
-
150
-
151
- // 调用openInfoWindow
152
- this.$refs.mapTool.openInfoWindow(
153
- [marker.lng, marker.lat],
154
- InfoWindowComponent,
155
- {
156
- props: { data },
157
- on: {
158
- close: () => console.log('信息窗口关闭')
159
- }
160
- }
161
- )
162
-
163
- } catch (error) {
164
- console.error('获取数据失败:', error)
165
- }
166
- }
167
- await this.$refs.mapTool.addMarker(getMarkerData,
168
- {
169
- groupId: 'line-patrol-plan-point',
170
- groupName: '巡检计划',
171
- desc: '巡线任务安排',
172
- func: 'getLinePatrolPlanPoint',
173
- visible: true,
174
- groupType: '业务图层',
175
- icon: 'patrol-plan',
176
- color: '#1890ff',
177
- onClick: 'onClickLinePatrolPlanPoint'
178
- },
179
- onClickLinePatrolPlanPoint)
180
- // 添加 WMS
181
- await this.handleAddWms()
182
- await this.handleRefreshGroups()
183
- this.$refs.mapTool.updateGroupsByGroupType()
184
- },
185
- getNowDay () {
186
- const today = new Date()
187
- const year = today.getFullYear()
188
- const month = String(today.getMonth() + 1).padStart(2, '0') // 月份从0开始,需要加1,并补零
189
- const day = String(today.getDate()).padStart(2, '0') // 补零
190
- return `${year}-${month}-${day}`
191
- },
192
- async handleRefreshGroups () {
193
- if (!this.inited) return
194
- this.groups = await this.$refs.mapTool.getGroups()
195
- // console.warn('>>>> groups', this.groups)
196
- },
197
- async handleAddWms() {
198
- try {
199
- const layers = this.gisConfig?.layers ?? []
200
- const wmsCfg = this.gisConfig?.wms ?? {}
201
- const geoserverUrl = wmsCfg.target || '/gis/geoserver/aofeng/wms'
202
- const version = wmsCfg.version || '1.3.0'
203
- const format = wmsCfg.format || 'image/png'
204
- const srs = wmsCfg.srs || 'EPSG:3857'
205
- // 版本号获取回调
206
- const getLayerVersion = async (tableName) => {
207
- const layersVersion = await runLogic('getLayersVersion', {f_table_name: tableName}, 'af-linepatrol')
208
- return layersVersion[0]?.f_version || Date.now()
209
- }
210
- for (const layer of layers) {
211
- const wms = {
212
- id: layer.key,
213
- name: layer.value || layer.layerName || `layer-${layer.id}`,
214
- url: geoserverUrl,
215
- // 注入版本号回调:由地图适配器缓存,refresh 时直接调用,无需再传 不传递或调用失败时使用时间戳
216
- getLayerVersion,
217
- params: {
218
- SERVICE: 'WMS',
219
- REQUEST: 'GetMap',
220
- VERSION: version,
221
- FORMAT: layer.format || format,
222
- TRANSPARENT: true,
223
- LAYERS: layer.layerName,
224
- STYLES: '',
225
- SRS: srs,
226
- CRS: srs,
227
- },
228
- visible: layer.show !== false
229
- }
230
- // 现在可以安全地使用 await 了
231
- await this.$refs.mapTool.addWmsLayer(
232
- wms,
233
- layer.key,
234
- layer.value || layer.layerName || `layer-${layer.id}`,
235
- 'vtb' in layer ? '输配管线' : '站场与设备'
236
- )
237
- }
238
- } catch (e) {
239
- console.error('WMS图层加载失败', e)
240
- }
241
- await this.handleRefreshGroups()
242
- },
243
- // ===== custom dock 事件(父组件处理) =====
244
- async handleDockClick (btn) {
245
- // this.$message.info(`>>>> 点击了 ${btn.click} - ${btn.text}`)
246
- // 查询过程中不允许触发业务按钮
247
- if (this.queryLoading) {
248
- this.$message.warning(this.loadingMessage)
249
- return
250
- }
251
-
252
- // 【重要】每次接收到新的 dock 点击事件时,先关闭所有之前激活的业务功能
253
- // 这样可以确保状态清理干净,避免残留
254
- await this.closeAllActiveBusiness()
255
-
256
- // 只处理 custom=true 的 dock 事件,其余由地图内部处理
257
- if (!btn?.custom) return
258
-
259
- // 如果点击的是当前已激活的 dock(visible=false),则只关闭,不打开新功能
260
- if (!btn.visible) {
261
- this.$refs.mapTool.togglePanelIsCollapsed(false)
262
- return
263
- }
264
- this.$refs.mapTool.togglePanelIsCollapsed()
265
- switch (btn.click) {
266
- // 数据筛选
267
- case 'toggle-filter': {
268
- const layers = Array.isArray(this.gisConfig?.layers) ? [...this.gisConfig.layers] : []
269
- this.toggleFilterLayers = layers
270
- this.showToggleFilter = true
271
- break
272
- }
273
- // 数据编辑
274
- case 'panel-edit': {
275
- this.showDataEditPanel = true
276
- // 重置编辑模式状态
277
- this.dataEditMode = {
278
- enabled: false
279
- }
280
- break
281
- }
282
- // 报警监控
283
- case 'panel-layers': {
284
- this.showPanelLayers = true
285
- break
286
- }
287
- // 告警列表
288
- case 'panel-alarms': {
289
- this.showpanelAlarms = true
290
- break
291
- }
292
- // 巡线业务
293
- case 'linepatrol': {
294
- this.showLinePatrol = true
295
- break
296
- }
297
- // 巡线人员定位
298
- case 'panel-inspectors': {
299
- this.$refs.mapTool.setGroupVisible('line-patrol-person-real-time-info', true)
300
- this.showPersonInspectors = true
301
- break
302
- }
303
- default: {
304
- const panelButton = this.mapConfig?.toolButton?.find(item => item.click === btn.click)
305
- if (!panelButton?.button) return
306
- const position = panelButton?.buttonPosition || 'right'
307
- this.businessCard = {
308
- visible: true,
309
- title: btn.text,
310
- buttons: panelButton.button,
311
- position,
312
- activeButton: null
313
- }
314
- break
315
- }
316
- }
317
- },
318
- async panelSelect (data) {
319
- console.log('panelSelect', data)
320
- },
321
- // 处理WMS点击事件:统一交给 ModeManager(包括编辑点选模式)
322
- handleWmsClick (data) {
323
- try {
324
- console.log('WMS点击查询结果:', JSON.stringify(data))
325
- } catch (e) {
326
- console.error('>>> handleWmsClick', e)
327
- }
328
- },
329
- // 处理通用地图点击事件
330
- handleMapClick (coordinate) {
331
- try {
332
- console.log('onMapClick', coordinate)
333
- } catch (e) {
334
- console.error('>>> handleMapClick', e)
335
- }
336
- },
337
- closeAllActiveBusiness() {
338
- },
339
- }
340
- }
341
- </script>
342
-
343
- <style scoped>
344
- .demo-page {
345
- position: relative;
346
- width: 100%;
347
- }
348
-
349
- .map-area {
350
- height: 100%;
351
- width: 100%;
352
- }
353
-
354
- .map-tip {
355
- position: absolute;
356
- top: 12px;
357
- left: 50%;
358
- transform: translateX(-50%);
359
- z-index: 998;
360
- background: rgba(255, 255, 255, 0.75);
361
- border: 1px solid rgba(24, 144, 255, 0.35);
362
- font-size: 16px;
363
- color: #000;
364
- border-radius: 30px;
365
- padding: 10px 18px;
366
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
367
- font-weight: 600;
368
- }
369
-
370
- .panel-toggle-mini {
371
- position: absolute;
372
- bottom: 12px;
373
- right: 12px;
374
- z-index: 10000;
375
- padding: 4px 8px;
376
- font-size: 12px;
377
- border: 1px solid #d9d9d9;
378
- background: #fff;
379
- border-radius: 4px;
380
- cursor: pointer;
381
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
382
- }
383
-
384
- .panel-overlay {
385
- position: absolute;
386
- bottom: 12px;
387
- left: 12px;
388
- right: 12px;
389
- z-index: 10000;
390
- pointer-events: none;
391
- }
392
-
393
- .panel-overlay > * {
394
- pointer-events: auto;
395
- }
396
-
397
- .query-result {
398
- position: absolute;
399
- bottom: 10%;
400
- display: flex;
401
- flex-direction: column;
402
- z-index: 998;
403
- right: 12px;
404
- }
405
-
406
- .query-result button {
407
- width: 48px;
408
- height: 48px;
409
- border-radius: 50%;
410
- border: none;
411
- background: #1890ff;
412
- color: #fff;
413
- cursor: pointer;
414
- display: inline-flex;
415
- align-items: center;
416
- justify-content: center;
417
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
418
- transition: all 0.2s ease;
419
- padding: 0;
420
- }
421
-
422
- .query-result button:hover {
423
- background: #40a9ff;
424
- box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
425
- }
426
-
427
- .panel-header {
428
- display: flex;
429
- justify-content: space-between;
430
- align-items: center;
431
- background: rgba(255, 255, 255, 0.95);
432
- border: 1px solid #e0e0e0;
433
- border-radius: 0 0 8px 8px;
434
- padding: 8px 12px;
435
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
436
- }
437
-
438
- .panel-title {
439
- font-size: 14px;
440
- font-weight: 600;
441
- }
442
-
443
- .panel-actions button {
444
- margin-left: 8px;
445
- padding: 4px 8px;
446
- font-size: 12px;
447
- border: 1px solid #d9d9d9;
448
- border-radius: 4px;
449
- background: #fff;
450
- cursor: pointer;
451
- }
452
-
453
- .op-section h3 {
454
- margin: 0 0 8px 0;
455
- font-size: 14px;
456
- font-weight: 600;
457
- color: #333;
458
- }
459
-
460
- .op-section button {
461
- margin-right: 8px;
462
- margin-bottom: 8px;
463
- padding: 6px 12px;
464
- font-size: 12px;
465
- border: 1px solid #d9d9d9;
466
- border-radius: 4px;
467
- background: #fff;
468
- cursor: pointer;
469
- transition: all 0.3s;
470
- }
471
-
472
- .op-section button:hover {
473
- border-color: #1890ff;
474
- color: #1890ff;
475
- }
476
-
477
- .engine-switch button {
478
- width: 100%;
479
- }
480
-
481
- .engine-switch button.active {
482
- background: #1890ff;
483
- color: #fff;
484
- border-color: #1890ff;
485
- }
486
-
487
- .engine-switch button:disabled {
488
- opacity: 0.5;
489
- cursor: not-allowed;
490
- }
491
- </style>
492
-
1
+ <template>
2
+ <div class="demo-page" :style="{ height: '87vh' }">
3
+ <AfMap
4
+ v-if="gisConfig && webConfig"
5
+ ref="mapTool"
6
+ class="map-area"
7
+ map-options-name="GisHomeConfig"
8
+ serviceName="af-linepatrol"
9
+ :show-group-id-arr="showGroupIdArr"
10
+ :get-dynamic-icon="getDynamicIcon"
11
+ :handle-svg-error="handleSvgError"
12
+ @closeAllActiveBusiness="closeAllActiveBusiness"
13
+ @inited="handleInited"
14
+ @loading-change="loading = $event"
15
+ @dock-click="handleDockClick"
16
+ @panel-select="panelSelect"
17
+ @wms-click="handleWmsClick"
18
+ @map-click="handleMapClick"
19
+ />
20
+
21
+ <div v-if="tipMessage" class="map-tip">
22
+ {{ tipMessage }}
23
+ </div>
24
+ </div>
25
+ </template>
26
+
27
+ <script>
28
+ import AfMap from '@vue2-client/base-client/components/common/AfMap/map/index.vue'
29
+ import {getConfigByNameAsync, runLogic} from '@vue2-client/services/api/common'
30
+ import { mapState } from 'vuex'
31
+ import InfoWindowComponent from '@vue2-client/base-client/components/common/AfMap/InfoWindowComponent.vue'
32
+ export default {
33
+ name: 'MapDemo',
34
+ components: {
35
+ AfMap,
36
+ InfoWindowComponent
37
+ },
38
+ computed: {
39
+ ...mapState('account', { currUser: 'user' }),
40
+ },
41
+ data () {
42
+ return {
43
+ inited: false,
44
+ loading: false,
45
+ groups: [],
46
+ currentEngine: 'OPENLAYERS',
47
+ mapViewMode: '3D',
48
+ mapConfig: {},
49
+ tipMessage: '',
50
+ gisConfig: null,
51
+ webConfig: null,
52
+ // WMS点击查询事件是否开启
53
+ wmsClickEnabled: false,
54
+ showGroupIdArr: ['line-patrol-plan-point']
55
+ }
56
+ },
57
+ async created () {
58
+ this.mapConfig = await getConfigByNameAsync('GisHomeConfig', 'af-linepatrol')
59
+ this.pageSize = this.mapConfig.queryResultPageSize || 20
60
+ this.businessLayers = this.mapConfig?.businessLayers || []
61
+ this.gisConfig = await getConfigByNameAsync('gisConfig', 'af-linepatrol')
62
+ this.webConfig = await getConfigByNameAsync('webConfig', 'af-linepatrol')
63
+ },
64
+ async mounted () {
65
+ },
66
+ methods: {
67
+ getDynamicIcon(iconName) {
68
+ // console.log(iconName)
69
+ if (!iconName) {
70
+ console.warn('svgName 未定义,使用默认SVG')
71
+ return require('@vue2-client/assets/svg/unknown-icon.svg')
72
+ }
73
+ try {
74
+ return require(`@vue2-client/assets/svg/${iconName}.svg`)
75
+ } catch (error) {
76
+ console.warn(`SVG ${iconName} 未找到,使用默认SVG`, error)
77
+ return require('@vue2-client/assets/svg/unknown-icon.svg')
78
+ }
79
+ },
80
+ handleSvgError(event) {
81
+ console.warn('图片加载失败,使用默认图片')
82
+ // 设置默认图片
83
+ event.target.src = require('@vue2-client/assets/svg/unknown-icon.svg')
84
+ },
85
+ // ===== 生命周期 & 初始化 =====
86
+ async handleInited() {
87
+ this.inited = true
88
+ this.currentEngine = this.$refs.mapTool.getCurrentEngine()
89
+ if (this.$refs.mapTool.getMapViewMode) {
90
+ this.mapViewMode = this.$refs.mapTool.getMapViewMode() || '3D'
91
+ }
92
+ // 添加一个demo图层
93
+ const defaultParams = {}
94
+ if (this.webConfig?.setting?.isGroup) {
95
+ defaultParams.f_orgid = this.currUser?.orgid || this.currUser?.operaInfo?.f_orgid || this.currUser?.operInfo?.f_orgid
96
+ }
97
+ const getMarkerData = async (params) => {
98
+ const param = {
99
+ endDate: params?.endDate || this.getNowDay()
100
+ }
101
+ if (params?.f_orgid) {
102
+ param.f_orgid = params?.f_orgid || params?.orgid
103
+ }
104
+ try {
105
+ const locationList = await runLogic('getPatrolTaskPoints', param, 'af-linepatrol')
106
+ return locationList.map(item => {
107
+ // eslint-disable-next-line camelcase
108
+ const {f_longitude, f_latitude, f_state, f_check_state, ...rest} = item
109
+ return {
110
+ lng: Number(f_longitude),
111
+ lat: Number(f_latitude),
112
+ icon: (() => {
113
+ let iconUrl = ''
114
+ // eslint-disable-next-line camelcase
115
+ if (f_state === '正常') {
116
+ iconUrl = this.getDynamicIcon('inspected')
117
+ }
118
+ // eslint-disable-next-line camelcase
119
+ if (f_state === '有隐患') {
120
+ iconUrl = this.getDynamicIcon('pointhidden')
121
+ }
122
+ // eslint-disable-next-line camelcase
123
+ if (f_check_state === '已检') {
124
+ iconUrl = this.getDynamicIcon('checked')
125
+ }
126
+ return iconUrl
127
+ })(),
128
+ // eslint-disable-next-line camelcase
129
+ f_state,
130
+ // eslint-disable-next-line camelcase
131
+ f_check_state,
132
+ name: item.f_name,
133
+ ...rest
134
+ }
135
+ })
136
+ // 处理最新的数据
137
+ } catch (e) {
138
+ console.log('>>>>获取固定点位失败', e)
139
+ return []
140
+ }
141
+ }
142
+ // 点击巡检计划
143
+ const onClickLinePatrolPlanPoint = async (mapService, marker, markerOptions) => {
144
+ console.warn('>> 点击巡检计划', marker, markerOptions)
145
+
146
+ try {
147
+ const data = await runLogic('getPointAndPlanByPlanPointIdLogic', { id: marker.id }, 'af-linepatrol')
148
+ console.warn('>> 获取到的数据', data)
149
+
150
+
151
+ // 调用openInfoWindow
152
+ this.$refs.mapTool.openInfoWindow(
153
+ [marker.lng, marker.lat],
154
+ InfoWindowComponent,
155
+ {
156
+ props: { data },
157
+ on: {
158
+ close: () => console.log('信息窗口关闭')
159
+ }
160
+ }
161
+ )
162
+
163
+ } catch (error) {
164
+ console.error('获取数据失败:', error)
165
+ }
166
+ }
167
+ await this.$refs.mapTool.addMarker(getMarkerData,
168
+ {
169
+ groupId: 'line-patrol-plan-point',
170
+ groupName: '巡检计划',
171
+ desc: '巡线任务安排',
172
+ func: 'getLinePatrolPlanPoint',
173
+ visible: true,
174
+ groupType: '业务图层',
175
+ icon: 'patrol-plan',
176
+ color: '#1890ff',
177
+ onClick: 'onClickLinePatrolPlanPoint'
178
+ },
179
+ onClickLinePatrolPlanPoint)
180
+ // 添加 WMS
181
+ await this.handleAddWms()
182
+ await this.handleRefreshGroups()
183
+ this.$refs.mapTool.updateGroupsByGroupType()
184
+ },
185
+ getNowDay () {
186
+ const today = new Date()
187
+ const year = today.getFullYear()
188
+ const month = String(today.getMonth() + 1).padStart(2, '0') // 月份从0开始,需要加1,并补零
189
+ const day = String(today.getDate()).padStart(2, '0') // 补零
190
+ return `${year}-${month}-${day}`
191
+ },
192
+ async handleRefreshGroups () {
193
+ if (!this.inited) return
194
+ this.groups = await this.$refs.mapTool.getGroups()
195
+ // console.warn('>>>> groups', this.groups)
196
+ },
197
+ async handleAddWms() {
198
+ try {
199
+ const layers = this.gisConfig?.layers ?? []
200
+ const wmsCfg = this.gisConfig?.wms ?? {}
201
+ const geoserverUrl = wmsCfg.target || '/gis/geoserver/aofeng/wms'
202
+ const version = wmsCfg.version || '1.3.0'
203
+ const format = wmsCfg.format || 'image/png'
204
+ const srs = wmsCfg.srs || 'EPSG:3857'
205
+ // 版本号获取回调
206
+ const getLayerVersion = async (tableName) => {
207
+ const layersVersion = await runLogic('getLayersVersion', {f_table_name: tableName}, 'af-linepatrol')
208
+ return layersVersion[0]?.f_version || Date.now()
209
+ }
210
+ for (const layer of layers) {
211
+ const wms = {
212
+ id: layer.key,
213
+ name: layer.value || layer.layerName || `layer-${layer.id}`,
214
+ url: geoserverUrl,
215
+ // 注入版本号回调:由地图适配器缓存,refresh 时直接调用,无需再传 不传递或调用失败时使用时间戳
216
+ getLayerVersion,
217
+ params: {
218
+ SERVICE: 'WMS',
219
+ REQUEST: 'GetMap',
220
+ VERSION: version,
221
+ FORMAT: layer.format || format,
222
+ TRANSPARENT: true,
223
+ LAYERS: layer.layerName,
224
+ STYLES: '',
225
+ SRS: srs,
226
+ CRS: srs,
227
+ },
228
+ visible: layer.show !== false
229
+ }
230
+ // 现在可以安全地使用 await 了
231
+ await this.$refs.mapTool.addWmsLayer(
232
+ wms,
233
+ layer.key,
234
+ layer.value || layer.layerName || `layer-${layer.id}`,
235
+ 'vtb' in layer ? '输配管线' : '站场与设备'
236
+ )
237
+ }
238
+ } catch (e) {
239
+ console.error('WMS图层加载失败', e)
240
+ }
241
+ await this.handleRefreshGroups()
242
+ },
243
+ // ===== custom dock 事件(父组件处理) =====
244
+ async handleDockClick (btn) {
245
+ // this.$message.info(`>>>> 点击了 ${btn.click} - ${btn.text}`)
246
+ // 查询过程中不允许触发业务按钮
247
+ if (this.queryLoading) {
248
+ this.$message.warning(this.loadingMessage)
249
+ return
250
+ }
251
+
252
+ // 【重要】每次接收到新的 dock 点击事件时,先关闭所有之前激活的业务功能
253
+ // 这样可以确保状态清理干净,避免残留
254
+ await this.closeAllActiveBusiness()
255
+
256
+ // 只处理 custom=true 的 dock 事件,其余由地图内部处理
257
+ if (!btn?.custom) return
258
+
259
+ // 如果点击的是当前已激活的 dock(visible=false),则只关闭,不打开新功能
260
+ if (!btn.visible) {
261
+ this.$refs.mapTool.togglePanelIsCollapsed(false)
262
+ return
263
+ }
264
+ this.$refs.mapTool.togglePanelIsCollapsed()
265
+ switch (btn.click) {
266
+ // 数据筛选
267
+ case 'toggle-filter': {
268
+ const layers = Array.isArray(this.gisConfig?.layers) ? [...this.gisConfig.layers] : []
269
+ this.toggleFilterLayers = layers
270
+ this.showToggleFilter = true
271
+ break
272
+ }
273
+ // 数据编辑
274
+ case 'panel-edit': {
275
+ this.showDataEditPanel = true
276
+ // 重置编辑模式状态
277
+ this.dataEditMode = {
278
+ enabled: false
279
+ }
280
+ break
281
+ }
282
+ // 报警监控
283
+ case 'panel-layers': {
284
+ this.showPanelLayers = true
285
+ break
286
+ }
287
+ // 告警列表
288
+ case 'panel-alarms': {
289
+ this.showpanelAlarms = true
290
+ break
291
+ }
292
+ // 巡线业务
293
+ case 'linepatrol': {
294
+ this.showLinePatrol = true
295
+ break
296
+ }
297
+ // 巡线人员定位
298
+ case 'panel-inspectors': {
299
+ this.$refs.mapTool.setGroupVisible('line-patrol-person-real-time-info', true)
300
+ this.showPersonInspectors = true
301
+ break
302
+ }
303
+ default: {
304
+ const panelButton = this.mapConfig?.toolButton?.find(item => item.click === btn.click)
305
+ if (!panelButton?.button) return
306
+ const position = panelButton?.buttonPosition || 'right'
307
+ this.businessCard = {
308
+ visible: true,
309
+ title: btn.text,
310
+ buttons: panelButton.button,
311
+ position,
312
+ activeButton: null
313
+ }
314
+ break
315
+ }
316
+ }
317
+ },
318
+ async panelSelect (data) {
319
+ console.log('panelSelect', data)
320
+ },
321
+ // 处理WMS点击事件:统一交给 ModeManager(包括编辑点选模式)
322
+ handleWmsClick (data) {
323
+ try {
324
+ console.log('WMS点击查询结果:', JSON.stringify(data))
325
+ } catch (e) {
326
+ console.error('>>> handleWmsClick', e)
327
+ }
328
+ },
329
+ // 处理通用地图点击事件
330
+ handleMapClick (coordinate) {
331
+ try {
332
+ console.log('onMapClick', coordinate)
333
+ } catch (e) {
334
+ console.error('>>> handleMapClick', e)
335
+ }
336
+ },
337
+ closeAllActiveBusiness() {
338
+ },
339
+ }
340
+ }
341
+ </script>
342
+
343
+ <style scoped>
344
+ .demo-page {
345
+ position: relative;
346
+ width: 100%;
347
+ }
348
+
349
+ .map-area {
350
+ height: 100%;
351
+ width: 100%;
352
+ }
353
+
354
+ .map-tip {
355
+ position: absolute;
356
+ top: 12px;
357
+ left: 50%;
358
+ transform: translateX(-50%);
359
+ z-index: 998;
360
+ background: rgba(255, 255, 255, 0.75);
361
+ border: 1px solid rgba(24, 144, 255, 0.35);
362
+ font-size: 16px;
363
+ color: #000;
364
+ border-radius: 30px;
365
+ padding: 10px 18px;
366
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
367
+ font-weight: 600;
368
+ }
369
+
370
+ .panel-toggle-mini {
371
+ position: absolute;
372
+ bottom: 12px;
373
+ right: 12px;
374
+ z-index: 10000;
375
+ padding: 4px 8px;
376
+ font-size: 12px;
377
+ border: 1px solid #d9d9d9;
378
+ background: #fff;
379
+ border-radius: 4px;
380
+ cursor: pointer;
381
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
382
+ }
383
+
384
+ .panel-overlay {
385
+ position: absolute;
386
+ bottom: 12px;
387
+ left: 12px;
388
+ right: 12px;
389
+ z-index: 10000;
390
+ pointer-events: none;
391
+ }
392
+
393
+ .panel-overlay > * {
394
+ pointer-events: auto;
395
+ }
396
+
397
+ .query-result {
398
+ position: absolute;
399
+ bottom: 10%;
400
+ display: flex;
401
+ flex-direction: column;
402
+ z-index: 998;
403
+ right: 12px;
404
+ }
405
+
406
+ .query-result button {
407
+ width: 48px;
408
+ height: 48px;
409
+ border-radius: 50%;
410
+ border: none;
411
+ background: #1890ff;
412
+ color: #fff;
413
+ cursor: pointer;
414
+ display: inline-flex;
415
+ align-items: center;
416
+ justify-content: center;
417
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
418
+ transition: all 0.2s ease;
419
+ padding: 0;
420
+ }
421
+
422
+ .query-result button:hover {
423
+ background: #40a9ff;
424
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
425
+ }
426
+
427
+ .panel-header {
428
+ display: flex;
429
+ justify-content: space-between;
430
+ align-items: center;
431
+ background: rgba(255, 255, 255, 0.95);
432
+ border: 1px solid #e0e0e0;
433
+ border-radius: 0 0 8px 8px;
434
+ padding: 8px 12px;
435
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
436
+ }
437
+
438
+ .panel-title {
439
+ font-size: 14px;
440
+ font-weight: 600;
441
+ }
442
+
443
+ .panel-actions button {
444
+ margin-left: 8px;
445
+ padding: 4px 8px;
446
+ font-size: 12px;
447
+ border: 1px solid #d9d9d9;
448
+ border-radius: 4px;
449
+ background: #fff;
450
+ cursor: pointer;
451
+ }
452
+
453
+ .op-section h3 {
454
+ margin: 0 0 8px 0;
455
+ font-size: 14px;
456
+ font-weight: 600;
457
+ color: #333;
458
+ }
459
+
460
+ .op-section button {
461
+ margin-right: 8px;
462
+ margin-bottom: 8px;
463
+ padding: 6px 12px;
464
+ font-size: 12px;
465
+ border: 1px solid #d9d9d9;
466
+ border-radius: 4px;
467
+ background: #fff;
468
+ cursor: pointer;
469
+ transition: all 0.3s;
470
+ }
471
+
472
+ .op-section button:hover {
473
+ border-color: #1890ff;
474
+ color: #1890ff;
475
+ }
476
+
477
+ .engine-switch button {
478
+ width: 100%;
479
+ }
480
+
481
+ .engine-switch button.active {
482
+ background: #1890ff;
483
+ color: #fff;
484
+ border-color: #1890ff;
485
+ }
486
+
487
+ .engine-switch button:disabled {
488
+ opacity: 0.5;
489
+ cursor: not-allowed;
490
+ }
491
+ </style>
492
+