|
|
@@ -7,11 +7,7 @@
|
|
|
:body-style="{ padding: '0px' }"
|
|
|
class="border-none"
|
|
|
>
|
|
|
- <el-container
|
|
|
- v-loading="loading"
|
|
|
- style="height: 100%"
|
|
|
- :element-loading-text="t('sip.splitview998531-0')"
|
|
|
- >
|
|
|
+ <el-container style="height: 100%">
|
|
|
<el-aside width="250px" style="background-color: #ffffff">
|
|
|
<DeviceTree :click-event="clickEvent" />
|
|
|
</el-aside>
|
|
|
@@ -93,10 +89,11 @@
|
|
|
<div
|
|
|
v-for="i in Math.max(0, spilt - availableChannels.length)"
|
|
|
:key="`empty-${i}`"
|
|
|
- class="play-box"
|
|
|
- :style="liveStyle"
|
|
|
+ :class="availableChannels.length > 0 ? 'play-box' : ''"
|
|
|
+ :style="availableChannels.length > 0 ? liveStyle : ''"
|
|
|
>
|
|
|
<div
|
|
|
+ v-if="availableChannels.length > 0"
|
|
|
style="
|
|
|
color: #ffffff;
|
|
|
font-size: 30px;
|
|
|
@@ -178,42 +175,128 @@ const liveStyle = computed(() => {
|
|
|
return style
|
|
|
})
|
|
|
|
|
|
-// 监听分屏变化
|
|
|
+// const loadAdditionalChannelsForSplit = async (newSplit, oldSplit) => {
|
|
|
+// loading.value = true
|
|
|
+// try {
|
|
|
+// // 获取当前已经加载的通道数量
|
|
|
+// const currentlyLoaded = Math.min(oldSplit, availableChannels.value.length)
|
|
|
+// const toBeLoaded = Math.min(newSplit, availableChannels.value.length)
|
|
|
+
|
|
|
+// // 准备所有需要加载的通道
|
|
|
+// const channelsToLoad = []
|
|
|
+// for (let i = currentlyLoaded; i < toBeLoaded; i++) {
|
|
|
+// const channelData = availableChannels.value[i]
|
|
|
+
|
|
|
+// // 检查是否已有缓存的播放地址
|
|
|
+// if (channelData._playUrl) {
|
|
|
+// // 使用缓存的地址(立即设置,不需要等待)
|
|
|
+// setPlayUrl(channelData._playUrl, i)
|
|
|
+// } else {
|
|
|
+// // 需要获取的通道
|
|
|
+// channelsToLoad.push({
|
|
|
+// index: i,
|
|
|
+// channelData: channelData,
|
|
|
+// playData: {
|
|
|
+// deviceSipId: channelData.deviceId,
|
|
|
+// channelSipId: channelData.basicData?.channelSipId || channelData.id,
|
|
|
+// name: channelData.name || `通道${i + 1}`,
|
|
|
+// ...channelData.basicData
|
|
|
+// }
|
|
|
+// })
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+// // 并发执行所有请求(使用 Promise.all)
|
|
|
+// const requests = channelsToLoad.map(({ playData, index, channelData }) =>
|
|
|
+// sendDevicePush(playData, index)
|
|
|
+// .then(() => {
|
|
|
+// // 缓存获取到的地址
|
|
|
+// if (videoUrl.value[index]) {
|
|
|
+// channelData._playUrl = videoUrl.value[index]
|
|
|
+// }
|
|
|
+// })
|
|
|
+// .catch((error) => {
|
|
|
+// console.error(`加载通道${index + 1}失败:`, error)
|
|
|
+// // 标记该通道加载失败,可以在UI上显示错误状态
|
|
|
+// channelData._loadError = true
|
|
|
+// })
|
|
|
+// )
|
|
|
+
|
|
|
+// // 等待所有请求完成(或部分完成)
|
|
|
+// await Promise.allSettled(requests)
|
|
|
+// } catch (error) {
|
|
|
+// console.error('加载新增通道出错:', error)
|
|
|
+// } finally {
|
|
|
+// loading.value = false
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+const loadAdditionalChannelsForSplit = async (newSplit, oldSplit) => {
|
|
|
+ loading.value = true
|
|
|
+ try {
|
|
|
+ const currentlyLoaded = Math.min(oldSplit, availableChannels.value.length)
|
|
|
+ const toBeLoaded = Math.min(newSplit, availableChannels.value.length)
|
|
|
+
|
|
|
+ // 使用数组存储所有要执行的异步操作
|
|
|
+ const operations = []
|
|
|
+
|
|
|
+ for (let i = currentlyLoaded; i < toBeLoaded; i++) {
|
|
|
+ const channelData = availableChannels.value[i]
|
|
|
+
|
|
|
+ if (channelData._playUrl) {
|
|
|
+ // 同步操作:立即设置URL
|
|
|
+ setPlayUrl(channelData._playUrl, i)
|
|
|
+ } else {
|
|
|
+ // 异步操作:稍后并行执行
|
|
|
+ operations.push({
|
|
|
+ index: i,
|
|
|
+ channelData,
|
|
|
+ playData: {
|
|
|
+ deviceSipId: channelData.deviceId,
|
|
|
+ channelSipId: channelData.basicData?.channelSipId || channelData.id,
|
|
|
+ name: channelData.name || `通道${i + 1}`,
|
|
|
+ ...channelData.basicData
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 并行执行所有sendDevicePush请求
|
|
|
+ if (operations.length > 0) {
|
|
|
+ const promises = operations.map(({ playData, index, channelData }) =>
|
|
|
+ sendDevicePush(playData, index)
|
|
|
+ .then(() => {
|
|
|
+ // 成功后的回调
|
|
|
+ if (videoUrl.value[index]) {
|
|
|
+ channelData._playUrl = videoUrl.value[index]
|
|
|
+ }
|
|
|
+ return { success: true, index }
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ console.error(`通道${index + 1}加载失败:`, error)
|
|
|
+ return { success: false, index, error }
|
|
|
+ })
|
|
|
+ )
|
|
|
+
|
|
|
+ // 使用allSettled而不是all,这样即使有失败也不会中断其他请求
|
|
|
+ await Promise.allSettled(promises)
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载新增通道出错:', error)
|
|
|
+ } finally {
|
|
|
+ loading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
watch(
|
|
|
() => spilt.value,
|
|
|
async (newSplit, oldSplit) => {
|
|
|
- // 只有当分屏数增加(例如从1到4,或从4到9)且有当前选中设备时才执行
|
|
|
- if (newSplit > oldSplit && currentDevice.value) {
|
|
|
- console.log(
|
|
|
- `分屏从 ${oldSplit} 变为 ${newSplit},自动填充设备 ${currentDevice.value.name} 的通道`
|
|
|
- )
|
|
|
-
|
|
|
- // 延迟执行,确保DOM更新完成
|
|
|
+ // 如果当前有选中的设备
|
|
|
+ if (currentDevice.value && availableChannels.value.length > 0) {
|
|
|
await nextTick()
|
|
|
|
|
|
- loading.value = true
|
|
|
- try {
|
|
|
- // 重新分配通道到所有播放器
|
|
|
- await assignChannelsToPlayers(availableChannels.value)
|
|
|
- } catch (error) {
|
|
|
- console.error('分屏变化时填充通道出错:', error)
|
|
|
- ElMessage.error('自动填充通道失败')
|
|
|
- } finally {
|
|
|
- loading.value = false
|
|
|
- }
|
|
|
- }
|
|
|
- // 当分屏数减少时,清空超出当前通道数的播放器
|
|
|
- else if (newSplit < oldSplit) {
|
|
|
- // 清空超出当前分屏数或超出通道数的播放器
|
|
|
- const maxVisible = Math.min(newSplit, availableChannels.value.length)
|
|
|
- for (let i = maxVisible; i < Math.max(oldSplit, availableChannels.value.length); i++) {
|
|
|
- const newVideoUrls = [...videoUrl.value]
|
|
|
- if (newVideoUrls[i]) {
|
|
|
- newVideoUrls[i] = ''
|
|
|
- videoUrl.value = newVideoUrls
|
|
|
- clear(i + 1) // 清理存储的数据
|
|
|
- }
|
|
|
- }
|
|
|
+ // 只加载新出现的播放器,不重新加载已有播放器
|
|
|
+ await loadAdditionalChannelsForSplit(newSplit, oldSplit)
|
|
|
}
|
|
|
},
|
|
|
{ immediate: false }
|
|
|
@@ -310,9 +393,6 @@ const getDeviceChannels = async (deviceId) => {
|
|
|
const assignChannelsToPlayers = async (channels) => {
|
|
|
const currentSplit = spilt.value
|
|
|
const actualChannels = Math.min(channels.length, currentSplit)
|
|
|
-
|
|
|
- console.log(`分配 ${actualChannels} 个通道到最多 ${currentSplit} 个播放窗口`)
|
|
|
-
|
|
|
// 清空当前所有播放器
|
|
|
const newVideoUrls = Array(Math.max(currentSplit, channels.length)).fill('')
|
|
|
videoUrl.value = newVideoUrls
|
|
|
@@ -330,7 +410,7 @@ const assignChannelsToPlayers = async (channels) => {
|
|
|
name: channelData.name || `通道${i + 1}`,
|
|
|
...channelData.basicData
|
|
|
}
|
|
|
- console.log(`将通道 ${playData.name} 分配给播放器 ${i}`)
|
|
|
+
|
|
|
await sendDevicePush(playData, i)
|
|
|
}
|
|
|
|
|
|
@@ -338,7 +418,7 @@ const assignChannelsToPlayers = async (channels) => {
|
|
|
}
|
|
|
|
|
|
// 通知设备上传媒体流
|
|
|
-const sendDevicePush = (itemData, targetIndex = null) => {
|
|
|
+const sendDevicePush = async (itemData, targetIndex = null) => {
|
|
|
// 关键修改:允许从外部传入 targetIndex,默认使用当前激活的 playerIdx
|
|
|
const playIndex = targetIndex !== null ? targetIndex : playerIdx.value
|
|
|
|