|
@@ -1,11 +1,12 @@
|
1
|
1
|
<!-- 实时视频监控 -->
|
2
|
2
|
<script setup>
|
3
|
|
- import { getPreview, controlling } from '@/api/previewPlayback'
|
|
3
|
+ import { getPreview, controlling, manualCapture } from '@/api/previewPlayback'
|
4
|
4
|
import { useRoute } from 'vue-router'
|
5
|
5
|
import commonSelect from '@/components/CommonSelector/index.vue'
|
6
|
6
|
import api from '@/api/orgInfo/info'
|
7
|
7
|
import cameraApi from '@/api/camera/index'
|
8
|
8
|
import { message } from 'ant-design-vue'
|
|
9
|
+ import { downloadLink } from '@/utils/systemUtils'
|
9
|
10
|
|
10
|
11
|
const activeKey = ref('1')
|
11
|
12
|
const route = useRoute()
|
|
@@ -21,6 +22,7 @@
|
21
|
22
|
let videoMap = {}
|
22
|
23
|
let currentWindowIndex = 0
|
23
|
24
|
const mode = 0 // 0 普通模式 1 高级模式
|
|
25
|
+ const isActive = ref(false)
|
24
|
26
|
|
25
|
27
|
const init = () => {
|
26
|
28
|
window.addEventListener('resize', () => {
|
|
@@ -59,7 +61,7 @@
|
59
|
61
|
const createPlayer = () => {
|
60
|
62
|
player.value = new window.JSPlugin({
|
61
|
63
|
szId: 'player',
|
62
|
|
- szBasePath: './',
|
|
64
|
+ szBasePath: '/h5player/',
|
63
|
65
|
iMaxSplit: 4,
|
64
|
66
|
iCurrentSplit: parseInt(splitNum.value),
|
65
|
67
|
openDebug: true,
|
|
@@ -193,8 +195,10 @@
|
193
|
195
|
}
|
194
|
196
|
|
195
|
197
|
const doControl = (command, action = 0, speed = 50, presetIndex = 10) => {
|
|
198
|
+ console.log('do control 2', command)
|
196
|
199
|
if (videoMap[currentWindowIndex]) {
|
197
|
200
|
const data = videoMap[currentWindowIndex]
|
|
201
|
+ const cameraId = data.cameraId
|
198
|
202
|
const c = findCameraByCameraId(cameraId)
|
199
|
203
|
if (c.cameraType !== '1') {
|
200
|
204
|
return message.warning('该操作必须是球形摄像机')
|
|
@@ -212,6 +216,23 @@
|
212
|
216
|
}
|
213
|
217
|
}
|
214
|
218
|
|
|
219
|
+ const circle = () => {
|
|
220
|
+ if (isActive.value) {
|
|
221
|
+ doControl('LEFT', 1)
|
|
222
|
+ } else {
|
|
223
|
+ doControl('LEFT', 0)
|
|
224
|
+ }
|
|
225
|
+ isActive.value = !isActive.value
|
|
226
|
+ }
|
|
227
|
+
|
|
228
|
+ const doControl1 = (command) => {
|
|
229
|
+ console.log('do control 1', command)
|
|
230
|
+ doControl(command, 0)
|
|
231
|
+ setTimeout(() => {
|
|
232
|
+ doControl(command, 1)
|
|
233
|
+ }, 2000)
|
|
234
|
+ }
|
|
235
|
+
|
215
|
236
|
const startTrack = () => {
|
216
|
237
|
doControl('START_TRACK', 0)
|
217
|
238
|
}
|
|
@@ -220,6 +241,30 @@
|
220
|
241
|
doControl('STOP_TRACK', 1)
|
221
|
242
|
}
|
222
|
243
|
|
|
244
|
+ const captureOne = (i = null) => {
|
|
245
|
+ console.log('ready capture one')
|
|
246
|
+ if (i == null) {
|
|
247
|
+ i = currentWindowIndex
|
|
248
|
+ }
|
|
249
|
+ if (videoMap[i]) {
|
|
250
|
+ const data = videoMap[i]
|
|
251
|
+ const cameraIndexCode = data.cameraIndexCode
|
|
252
|
+ manualCapture({ cameraIndexCode }).then((url) => {
|
|
253
|
+ console.log('capture url', url)
|
|
254
|
+ downloadLink(url)
|
|
255
|
+ })
|
|
256
|
+ } else {
|
|
257
|
+ return message.warning('请选择播放中的窗口')
|
|
258
|
+ }
|
|
259
|
+ }
|
|
260
|
+
|
|
261
|
+ const captureAll = () => {
|
|
262
|
+ let i = 0
|
|
263
|
+ for (const _ of Object.values(videoMap)) {
|
|
264
|
+ captureOne(i++)
|
|
265
|
+ }
|
|
266
|
+ }
|
|
267
|
+
|
223
|
268
|
const orgSelect = (orgId, event) => {
|
224
|
269
|
const org = event.node
|
225
|
270
|
cameraListData.value = []
|
|
@@ -247,7 +292,7 @@
|
247
|
292
|
}
|
248
|
293
|
]
|
249
|
294
|
list.forEach((d) => {
|
250
|
|
- const type = d.cameraType
|
|
295
|
+ const type = d.live
|
251
|
296
|
const temp = {
|
252
|
297
|
title: d.cameraName,
|
253
|
298
|
key: d.cameraId,
|
|
@@ -273,9 +318,9 @@
|
273
|
318
|
console.log('选择摄像头', camera)
|
274
|
319
|
const { cameraIndexCode } = camera
|
275
|
320
|
getPreview({ cameraIndexCode, protocol: 'WS' }).then((resp) => {
|
276
|
|
- if (!resp || !resp.data || !resp.data.url) return message.error('无法获取视频地址')
|
277
|
|
- const url = resp.data.url
|
278
|
|
- const exists = Object.values(videoMap).findIndex((u) => u.url === url)
|
|
321
|
+ if (!resp || !resp.url) return message.error('无法获取视频地址')
|
|
322
|
+ const url = resp.url
|
|
323
|
+ const exists = Object.values(videoMap).findIndex((u) => u.cameraIndexCode === cameraIndexCode)
|
279
|
324
|
if (exists >= 0) {
|
280
|
325
|
return message.warning(`该视频已经在 ${exists + 1} 窗口播放`)
|
281
|
326
|
}
|
|
@@ -283,7 +328,7 @@
|
283
|
328
|
.then((_) => {
|
284
|
329
|
videoMap[currentWindowIndex] = {
|
285
|
330
|
url,
|
286
|
|
- cameraIndexCode: n.cameraIndexCode,
|
|
331
|
+ cameraIndexCode,
|
287
|
332
|
cameraId
|
288
|
333
|
}
|
289
|
334
|
})
|
|
@@ -335,11 +380,11 @@
|
335
|
380
|
<a-button type="primary" class="btn">中止轮巡</a-button>
|
336
|
381
|
</div>
|
337
|
382
|
<div class="row">
|
338
|
|
- <a-button type="primary" class="mr-5 btn">窗口抓图</a-button>
|
|
383
|
+ <a-button type="primary" class="mr-5 btn" @click="captureOne(null)">窗口抓图</a-button>
|
339
|
384
|
<a-button type="primary" class="btn" @click="stopPlay">窗口关闭</a-button>
|
340
|
385
|
</div>
|
341
|
386
|
<div class="row">
|
342
|
|
- <a-button type="primary" class="mr-5 btn">全部抓图</a-button>
|
|
387
|
+ <a-button type="primary" class="mr-5 btn" @click="captureAll()">全部抓图</a-button>
|
343
|
388
|
<a-button type="primary" class="btn" @click="stopAllPlay">全部关闭</a-button>
|
344
|
389
|
</div>
|
345
|
390
|
<div v-if="hasPerm(['controlCloud'])" class="flex flex-col">
|
|
@@ -366,10 +411,15 @@
|
366
|
411
|
>
|
367
|
412
|
<div class="control-row">
|
368
|
413
|
<template v-for="item in list">
|
369
|
|
- <a-button v-if="item.code !== 'GOTO_PRESET'" :key="item.code" class="small-btn"
|
|
414
|
+ <a-button
|
|
415
|
+ v-if="item.code !== 'GOTO_PRESET'"
|
|
416
|
+ :key="item.code"
|
|
417
|
+ class="small-btn"
|
|
418
|
+ @mousedown="doControl(item.code, 0)"
|
|
419
|
+ @mouseup="doControl(item.code, 1)"
|
370
|
420
|
>{{ item.label }}
|
371
|
421
|
</a-button>
|
372
|
|
- <a-button v-else class="small-btn">
|
|
422
|
+ <a-button v-else class="small-btn" :class="{ 'active-button': isActive }" @click="circle()">
|
373
|
423
|
<template #icon>
|
374
|
424
|
<UndoOutlined />
|
375
|
425
|
</template>
|
|
@@ -380,12 +430,38 @@
|
380
|
430
|
</div>
|
381
|
431
|
</div>
|
382
|
432
|
<div class="row">
|
383
|
|
- <a-button type="primary" class="mr-5 btn"> + 聚焦 </a-button>
|
384
|
|
- <a-button type="primary" class="btn">- 聚焦</a-button>
|
|
433
|
+ <a-button
|
|
434
|
+ type="primary"
|
|
435
|
+ class="mr-5 btn"
|
|
436
|
+ @mousedown="doControl('FOCUS_NEAR', 0)"
|
|
437
|
+ @mouseup="doControl('FOCUS_NEAR', 1)"
|
|
438
|
+ >
|
|
439
|
+ + 聚焦
|
|
440
|
+ </a-button>
|
|
441
|
+ <a-button
|
|
442
|
+ type="primary"
|
|
443
|
+ class="btn"
|
|
444
|
+ @mousedown="doControl('FOCUS_FAR', 0)"
|
|
445
|
+ @mouseup="doControl('FOCUS_FAR', 1)"
|
|
446
|
+ >- 聚焦</a-button
|
|
447
|
+ >
|
385
|
448
|
</div>
|
386
|
449
|
<div class="row">
|
387
|
|
- <a-button type="primary" class="mr-5 btn"> + 调焦 </a-button>
|
388
|
|
- <a-button type="primary" class="btn">- 调焦</a-button>
|
|
450
|
+ <a-button
|
|
451
|
+ type="primary"
|
|
452
|
+ class="mr-5 btn"
|
|
453
|
+ @mousedown="doControl('ZOOM_IN', 0)"
|
|
454
|
+ @mouseup="doControl('ZOOM_IN', 1)"
|
|
455
|
+ >
|
|
456
|
+ + 调焦
|
|
457
|
+ </a-button>
|
|
458
|
+ <a-button
|
|
459
|
+ type="primary"
|
|
460
|
+ class="btn"
|
|
461
|
+ @mousedown="doControl('ZOOM_OUT', 0)"
|
|
462
|
+ @mouseup="doControl('ZOOM_OUT', 1)"
|
|
463
|
+ >- 调焦</a-button
|
|
464
|
+ >
|
389
|
465
|
</div>
|
390
|
466
|
<!-- <div class="row">-->
|
391
|
467
|
<!-- <a-button type="primary" class="mr-5 btn"> 录像开始 </a-button>-->
|
|
@@ -427,4 +503,9 @@
|
427
|
503
|
margin-top: 5px;
|
428
|
504
|
}
|
429
|
505
|
}
|
|
506
|
+
|
|
507
|
+ .active-button {
|
|
508
|
+ background-color: #1890ff;
|
|
509
|
+ color: white;
|
|
510
|
+ }
|
430
|
511
|
</style>
|