@@ -265,6 +265,9 @@ export default {
},
selectChannel(channel) {
if (!channel) return
+ if (!this.channels.some(item => item.cameraCode === channel.cameraCode)) {
+ this.channels.push(channel)
+ }
this.selectedCode = channel.cameraCode
this.loadPresets(true)
},
@@ -289,9 +292,11 @@ export default {
this.activeIndex = index
this.placementCursor = (index + 1) % this.capacity
try {
- const result = await startLive(channel.cameraCode)
+ const result = await startLive(channel)
this.applyLiveResult(index, slot, result)
- if (!result || result.status !== 'PLAYING') this.pollLive(index, slot, 0)
+ if (!slot.streamSource.hlsUrl && !slot.streamSource.flvUrl) {
+ throw new Error('实时视频接口未返回可播放地址')
+ }
} catch (error) {
this.$set(this.slots, index, null)
this.$message.error(error.message)
@@ -299,8 +304,10 @@ export default {
},
applyLiveResult(index, slot, result) {
if (this.slots[index] !== slot || !result) return
- if (result.hlsUrl) slot.streamSource.hlsUrl = result.hlsUrl
- if (result.flvUrl) slot.streamSource.flvUrl = result.flvUrl
+ const payload = result.data || result
+ const mediaUrl = payload.url || payload.playUrl || payload.mediaUrl || payload.address || ''
+ slot.streamSource.hlsUrl = payload.hlsUrl || payload.hls || (/\.m3u8(?:\?|$)/i.test(mediaUrl) ? mediaUrl : '')
+ slot.streamSource.flvUrl = payload.flvUrl || payload.flv || (/\.flv(?:\?|$)/i.test(mediaUrl) ? mediaUrl : '')
slot.loading = !(slot.streamSource.hlsUrl || slot.streamSource.flvUrl)
},
pollLive(index, slot, attempt) {
@@ -374,16 +381,10 @@ export default {
this.ptzActive = false
this.sendPtz(1).catch(error => this.$message.error(error.message))
},
- splitCameraCode() {
- const parts = String(this.selectedCode || '').split('#')
- if (parts.length !== 2 || !parts[0] || !parts[1]) throw new Error('摄像机编码格式不正确')
- return parts
- },
async loadPresets(silent = false) {
if (!this.selectedCode) return
try {
- const [deviceCode, domainCode] = this.splitCameraCode()
- const result = await getPresetList(deviceCode, domainCode)
+ const result = await getPresetList(this.selectedCode)
const source = result && result.ptzPresetInfoList && result.ptzPresetInfoList.ptzPresetInfo
this.presets = (Array.isArray(source) ? source : []).map(item => ({ id: Number(item.presetIndex), name: item.presetName || `预置位 ${item.presetIndex}` })).filter(item => item.id > 0)
if (this.presets.length && !this.presets.some(item => item.id === this.presetId)) this.presetId = this.presets[0].id
@@ -397,7 +398,7 @@ export default {
prepareNewPreset() {
const used = new Set(this.presets.map(item => Number(item.id)))
let nextId = 1
- while (used.has(nextId) && nextId < 256) nextId += 1
+ while (used.has(nextId) && nextId < 255) nextId += 1
this.newPresetId = nextId
this.newPresetName = ''
this.$message.info(`请填写预置位 ${nextId} 的名称后保存`)
@@ -412,13 +413,13 @@ export default {
async savePreset() {
const channel = this.selectedChannel
if (!channel) { this.$message.warning('请先选择摄像机'); return }
- if (!Number.isInteger(this.newPresetId) || this.newPresetId < 1 || this.newPresetId > 256) {
+ if (!Number.isInteger(this.newPresetId) || this.newPresetId < 1 || this.newPresetId > 255) {
this.$message.warning('请输入 1-256 的预置位编号')
return
}
try {
await this.$confirm(`确认保存预置位 ${this.newPresetId}${this.newPresetName ? ` · ${this.newPresetName}` : ''}?`, '保存预置位')
- await createPreset({ nvrIp: channel.nvrIp, channel: Number(channel.channel), preset: this.newPresetId, presetName: this.newPresetName || null })
+ await createPreset({ cameraCode: channel.cameraCode, nvrIp: channel.nvrIp, channel: Number(channel.channel), preset: this.newPresetId, presetName: this.newPresetName || null })
await this.loadPresets(true)
this.$message.success('预置位保存成功')
} catch (error) { if (error !== 'cancel' && error !== 'close') this.$message.error(error.message) }
@@ -426,11 +427,10 @@ export default {
async capture() {
if (!this.selectedCode) { this.$message.warning('请先选择摄像机'); return }
try {
- const [deviceCode, domainCode] = this.splitCameraCode()
- const command = await createSnapshot(deviceCode, domainCode)
+ const command = await createSnapshot(this.selectedCode)
if (!command || Number(command.resultCode) !== 0 || !command.taskID) throw new Error('抓图任务创建失败')
- const response = await downloadSnapshot(command.taskID)
- const url = URL.createObjectURL(response.data)
+ const blob = await downloadSnapshot(command.taskID)
+ const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = `camera-${this.selectedCode.replace(/[^A-Za-z0-9_-]/g, '_')}-${Date.now()}.jpg`
diff --git a/src/views/video/components/NvrDeviceTree.vue b/src/views/video/components/NvrDeviceTree.vue
index bfd1cef..b0fe23d 100644
--- a/src/views/video/components/NvrDeviceTree.vue
+++ b/src/views/video/components/NvrDeviceTree.vue
@@ -1,60 +1,80 @@