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.
- package/.idea/MarsCodeWorkspaceAppSettings.xml +7 -0
- package/.idea/encodings.xml +6 -0
- package/.idea/gradle.xml +7 -0
- package/.idea/misc.xml +5 -5
- package/.idea/modules.xml +1 -1
- package/package.json +1 -1
- package/src/assets/svg/unknown-icon.svg +3 -3
- package/src/base-client/components/common/AfMap/InfoWindowComponent.vue +141 -141
- package/src/base-client/components/common/AfMap/demo.vue +492 -492
- package/src/base-client/components/common/AmapMarker/index.js +3 -3
- package/src/base-client/components/common/FileImage/FileImageGroup.vue +14 -1
- package/src/base-client/components/common/ImagePreviewModal/ImagePreviewModal.vue +16 -4
- package/src/base-client/components/common/XDetailsView/index.js +3 -3
- package/src/base-client/components/common/XFormGroupDetails/index.js +3 -3
- package/src/base-client/components/common/XInspectionDetailDrawer/components/AiDeviceStatus.vue +53 -6
- package/src/base-client/components/common/XInspectionDetailDrawer/components/CheckItems.vue +28 -35
- package/src/base-client/components/common/XInspectionDetailDrawer/components/DeviceStatus.vue +80 -5
- package/src/base-client/components/common/XInspectionDetailDrawer/components/HazardPhotos.vue +49 -1
- package/src/base-client/components/common/XInspectionDetailDrawer/demo.vue +3 -3
- package/src/base-client/components/common/XInspectionDetailDrawer/index.vue +191 -4
- package/src/components/ImagePreview/ImagePreview.vue +323 -323
- package/tests/unit/a.log +0 -0
- /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
|
+
|