huweili-cesium 1.3.3 → 1.3.4
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/components/wsIndicator/wsIndicator.vue +168 -145
- package/index.vue +1 -1
- package/package.json +1 -1
|
@@ -1,152 +1,175 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return 'disconnected' // 断开连接时红色高亮
|
|
43
|
-
}
|
|
44
|
-
if (wsDroneIndicatorActive.value) {
|
|
45
|
-
return 'active' // 收到无人机数据时绿色高亮
|
|
46
|
-
}
|
|
47
|
-
return 'connected' // 连接正常但无数据时微弱绿色
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* 处理无人机数据接收事件
|
|
52
|
-
* 收到数据时设置连接状态为true,并触发高亮闪烁
|
|
53
|
-
*/
|
|
54
|
-
const handleWsDroneDataReceived = () => {
|
|
55
|
-
wsConnected.value = true // 收到数据说明连接正常
|
|
56
|
-
wsDroneIndicatorActive.value = true // 触发绿色高亮
|
|
57
|
-
// 300ms后恢复微弱绿色状态
|
|
58
|
-
setTimeout(() => {
|
|
59
|
-
wsDroneIndicatorActive.value = false
|
|
60
|
-
}, 300)
|
|
2
|
+
<!-- WebSocket连接状态指示器:挂载到当前地图容器内的 .cesium-viewer -->
|
|
3
|
+
<Teleport v-if="cesiumViewerEl" :to="cesiumViewerEl">
|
|
4
|
+
<div class="ws-drone-indicator">
|
|
5
|
+
<div class="ws-drone-indicator-dot" :class="wsIndicatorClass"></div>
|
|
6
|
+
</div>
|
|
7
|
+
</Teleport>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup>
|
|
11
|
+
/**
|
|
12
|
+
* WsIndicator.vue - WebSocket连接状态指示器组件
|
|
13
|
+
*
|
|
14
|
+
* 状态说明:
|
|
15
|
+
* - 断开连接时红色高亮(.disconnected)
|
|
16
|
+
* - 连接正常时微弱绿色(.connected)
|
|
17
|
+
* - 收到无人机数据时绿色高亮闪烁(.active)
|
|
18
|
+
*/
|
|
19
|
+
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
|
|
20
|
+
import { useEventBus } from '../../js/utils/useEventBus.js'
|
|
21
|
+
|
|
22
|
+
const props = defineProps({
|
|
23
|
+
/** 地图根容器 ref(index.vue 中的 cesium-container) */
|
|
24
|
+
container: {
|
|
25
|
+
type: Object,
|
|
26
|
+
default: null,
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const { on, off } = useEventBus()
|
|
31
|
+
|
|
32
|
+
const cesiumViewerEl = ref(null)
|
|
33
|
+
const wsConnected = ref(false)
|
|
34
|
+
const wsDroneIndicatorActive = ref(false)
|
|
35
|
+
|
|
36
|
+
let viewerObserver = null
|
|
37
|
+
let resolveTimer = null
|
|
38
|
+
|
|
39
|
+
const wsIndicatorClass = computed(() => {
|
|
40
|
+
if (!wsConnected.value) {
|
|
41
|
+
return 'disconnected'
|
|
61
42
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
* 处理WebSocket连接成功事件
|
|
65
|
-
*/
|
|
66
|
-
const handleWsConnected = () => {
|
|
67
|
-
wsConnected.value = true
|
|
43
|
+
if (wsDroneIndicatorActive.value) {
|
|
44
|
+
return 'active'
|
|
68
45
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
|
|
46
|
+
return 'connected'
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
const resolveViewerElement = () => {
|
|
50
|
+
const root = props.container?.value
|
|
51
|
+
if (!root) return null
|
|
52
|
+
return root.querySelector('.cesium-viewer')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const bindViewerElement = () => {
|
|
56
|
+
const viewer = resolveViewerElement()
|
|
57
|
+
if (!viewer) return false
|
|
58
|
+
cesiumViewerEl.value = viewer
|
|
59
|
+
return true
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const stopResolveViewerElement = () => {
|
|
63
|
+
viewerObserver?.disconnect()
|
|
64
|
+
viewerObserver = null
|
|
65
|
+
if (resolveTimer) {
|
|
66
|
+
clearTimeout(resolveTimer)
|
|
67
|
+
resolveTimer = null
|
|
75
68
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// 订阅WebSocket断开连接事件
|
|
89
|
-
on('wsDisconnected', handleWsDisconnected)
|
|
90
|
-
|
|
91
|
-
// 检查全局连接状态(处理组件挂载前已连接的情况)
|
|
92
|
-
if (window.wsConnected) {
|
|
93
|
-
wsConnected.value = true
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const startResolveViewerElement = () => {
|
|
72
|
+
stopResolveViewerElement()
|
|
73
|
+
if (bindViewerElement()) return
|
|
74
|
+
|
|
75
|
+
const root = props.container?.value
|
|
76
|
+
if (!root) return
|
|
77
|
+
|
|
78
|
+
viewerObserver = new MutationObserver(() => {
|
|
79
|
+
if (bindViewerElement()) {
|
|
80
|
+
stopResolveViewerElement()
|
|
94
81
|
}
|
|
95
82
|
})
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
.
|
|
136
|
-
|
|
137
|
-
box-shadow: none;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/* 收到数据状态 - 绿色高亮 */
|
|
141
|
-
.ws-drone-indicator-dot.active {
|
|
142
|
-
opacity: 1;
|
|
143
|
-
box-shadow: 0 0 6px #0f3;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/* 断开连接状态 - 红色高亮 */
|
|
147
|
-
.ws-drone-indicator-dot.disconnected {
|
|
148
|
-
background: #f33;
|
|
149
|
-
opacity: 1;
|
|
150
|
-
box-shadow: 0 0 6px #f33;
|
|
83
|
+
viewerObserver.observe(root, { childList: true, subtree: true })
|
|
84
|
+
|
|
85
|
+
// 地图初始化较慢时兜底重试,避免 Teleport 目标一直为空
|
|
86
|
+
resolveTimer = window.setTimeout(() => {
|
|
87
|
+
bindViewerElement()
|
|
88
|
+
stopResolveViewerElement()
|
|
89
|
+
}, 10000)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const handleWsDroneDataReceived = () => {
|
|
93
|
+
wsConnected.value = true
|
|
94
|
+
wsDroneIndicatorActive.value = true
|
|
95
|
+
setTimeout(() => {
|
|
96
|
+
wsDroneIndicatorActive.value = false
|
|
97
|
+
}, 300)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const handleWsConnected = () => {
|
|
101
|
+
wsConnected.value = true
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const handleWsDisconnected = () => {
|
|
105
|
+
wsConnected.value = false
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
watch(
|
|
109
|
+
() => props.container?.value,
|
|
110
|
+
() => {
|
|
111
|
+
cesiumViewerEl.value = null
|
|
112
|
+
startResolveViewerElement()
|
|
113
|
+
},
|
|
114
|
+
{ immediate: true },
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
onMounted(() => {
|
|
118
|
+
on('wsDroneDataReceived', handleWsDroneDataReceived)
|
|
119
|
+
on('wsConnected', handleWsConnected)
|
|
120
|
+
on('wsDisconnected', handleWsDisconnected)
|
|
121
|
+
|
|
122
|
+
if (window.wsConnected) {
|
|
123
|
+
wsConnected.value = true
|
|
151
124
|
}
|
|
152
|
-
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
onUnmounted(() => {
|
|
128
|
+
stopResolveViewerElement()
|
|
129
|
+
off('wsDroneDataReceived', handleWsDroneDataReceived)
|
|
130
|
+
off('wsConnected', handleWsConnected)
|
|
131
|
+
off('wsDisconnected', handleWsDisconnected)
|
|
132
|
+
})
|
|
133
|
+
</script>
|
|
134
|
+
|
|
135
|
+
<style scoped lang="scss">
|
|
136
|
+
.ws-drone-indicator {
|
|
137
|
+
position: absolute;
|
|
138
|
+
left: 0px;
|
|
139
|
+
bottom: 0px;
|
|
140
|
+
width: 13px;
|
|
141
|
+
height: 13px;
|
|
142
|
+
border-radius: 3px;
|
|
143
|
+
background: rgba(40, 40, 40, 0.7);
|
|
144
|
+
display: flex;
|
|
145
|
+
align-items: center;
|
|
146
|
+
justify-content: center;
|
|
147
|
+
z-index: 2147483647;
|
|
148
|
+
pointer-events: none;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.ws-drone-indicator-dot {
|
|
152
|
+
width: 4px;
|
|
153
|
+
height: 4px;
|
|
154
|
+
border-radius: 50%;
|
|
155
|
+
background: #0f3;
|
|
156
|
+
opacity: 0.25;
|
|
157
|
+
transition: opacity 0.08s ease, box-shadow 0.08s ease;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.ws-drone-indicator-dot.connected {
|
|
161
|
+
opacity: 0.3;
|
|
162
|
+
box-shadow: none;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.ws-drone-indicator-dot.active {
|
|
166
|
+
opacity: 1;
|
|
167
|
+
box-shadow: 0 0 6px #0f3;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.ws-drone-indicator-dot.disconnected {
|
|
171
|
+
background: #f33;
|
|
172
|
+
opacity: 1;
|
|
173
|
+
box-shadow: 0 0 6px #f33;
|
|
174
|
+
}
|
|
175
|
+
</style>
|
package/index.vue
CHANGED