yanghao преди 5 дни
родител
ревизия
d86e2ad987
променени са 2 файла, в които са добавени 162 реда и са изтрити 42 реда
  1. 4 3
      src/views/pms/video_center/sip/components/player/DeviceTree.vue
  2. 158 39
      src/views/pms/video_center/sip/splitview.vue

+ 4 - 3
src/views/pms/video_center/sip/components/player/DeviceTree.vue

@@ -138,9 +138,10 @@ const handleNodeClick = (data, node, element) => {
   selectchannelId.value = node.data.value
   
   if (node.level !== 0) {
-    const deviceNode = treeRef.value.getNode(data.userData.channelSipId)
-    if (typeof props.clickEvent === 'function' && node.level > 1) {
-      props.clickEvent(deviceNode.data.userData)
+    // 修正:设备节点(level=1)和通道节点(level>1)都触发事件
+    if (typeof props.clickEvent === 'function') {
+      // 直接传递当前节点的完整数据
+      props.clickEvent(node.data)
     }
   }
 }

+ 158 - 39
src/views/pms/video_center/sip/splitview.vue

@@ -88,6 +88,7 @@ import { FullScreen, Menu, Grid } from '@element-plus/icons-vue'
 import player from './components/player/jessibuca.vue'
 import DeviceTree from './components/player/DeviceTree.vue'
 import { startPlay } from '@/api/pms/video/channel'
+import { listSipDeviceChannel } from '@/api/pms/video/sipdevice';
 
 const { t } = useI18n()
 
@@ -106,6 +107,8 @@ const count = ref(15)
 const total = ref(0)
 const loading = ref(false)
 
+
+
 // 设置播放器引用
 const setPlayerRef = (el, index) => {
   if (el) {
@@ -138,19 +141,49 @@ const liveStyle = computed(() => {
 })
 
 // 监听分屏变化
-watch(spilt, (newValue) => {
-  for (let i = 1; i <= newValue; i++) {
-    const player = playerRefs.value[i - 1]
-    if (player) {
-      nextTick(() => {
-        if (typeof player.resize === 'function') {
-          player.resize()
+watch(
+  () => spilt.value,
+  async (newSplit, oldSplit) => {
+    // 只有当分屏数增加(例如从1到4,或从4到9)且有当前选中设备时才执行
+    if (newSplit > oldSplit && currentDevice.value) {
+      console.log(`分屏从 ${oldSplit} 变为 ${newSplit},自动填充设备 ${currentDevice.value.name} 的通道`)
+      
+      // 延迟执行,确保DOM更新完成
+      await nextTick()
+      
+      loading.value = true
+      try {
+        // 1. 重新获取当前设备的通道
+        const channels = await getDeviceChannels(currentDevice.value.id)
+        
+        if (!channels || channels.length === 0) {
+          console.warn('该设备下没有可用通道')
+          return
         }
-      })
+        
+        // 2. 重新分配通道到所有播放器
+        await assignChannelsToPlayers(channels)
+        
+      } catch (error) {
+        console.error('分屏变化时填充通道出错:', error)
+        ElMessage.error('自动填充通道失败')
+      } finally {
+        loading.value = false
+      }
     }
-  }
-  window.localStorage.setItem('split', newValue.toString())
-})
+    // 可选:当分屏数减少时,可以清空多余的播放器
+    else if (newSplit < oldSplit) {
+      // 清空超出当前分屏数的播放器
+      for (let i = newSplit; i < oldSplit; i++) {
+        const newVideoUrls = [...videoUrl.value]
+        newVideoUrls[i] = ''
+        videoUrl.value = newVideoUrls
+        clear(i + 1) // 清理存储的数据
+      }
+    }
+  },
+  { immediate: false } // 不需要立即执行
+)
 
 // 监听路由变化
 watch(
@@ -174,40 +207,126 @@ const destroy = (idx) => {
   console.log(idx)
   clear(idx.substring(idx.length - 1))
 }
-
+const currentDevice = ref(null) // 存储当前选中的设备信息
 // 点击事件
-const clickEvent = (data) => {
-  if (data.channelSipId) {
-    sendDevicePush(data)
+const clickEvent = async (data) => {
+  // 情况1:点击的是设备节点 (type === 0)
+  if (data.type === 0) {
+     currentDevice.value = {
+      id: data.userData?.serialNumber,
+      name: data.name,
+      data: data
+    }
+    const deviceId = data.userData?.serialNumber; // 从树节点数据中提取设备ID
+    if (!deviceId) return;
+
+    loading.value = true;
+    try {
+      // 1. 获取该设备下的所有通道
+      const channels = await getDeviceChannels(deviceId);
+      if (!channels || channels.length === 0) {
+        console.warn('该设备下没有可用通道');
+        return;
+      }
+
+      // 2. 将通道智能分配给播放器
+      await assignChannelsToPlayers(channels);
+
+    } catch (error) {
+      console.error('处理设备通道时出错:', error);
+    } finally {
+      loading.value = false;
+    }
+  }
+  // 情况2:点击的是具体的通道节点,保持原有逻辑不变
+  else if (data.userData?.channelSipId) {
+    sendDevicePush(data.userData);
+  }
+};
+
+const getDeviceChannels = async (deviceId) => {
+  try {
+    const response = await listSipDeviceChannel(deviceId);
+    console.log('获取设备通道列表成功:', response);
+    // 假设接口返回的是通道数组,且每个通道对象结构符合 { basicData: { channelSipId, ... }, ... }
+    return response || [];
+  } catch (error) {
+    console.error('获取设备通道列表失败:', error);
+    return [];
+  }
+};
+
+const assignChannelsToPlayers = async (channels) => {
+  const currentSplit = spilt.value
+  console.log(`分配 ${channels.length} 个通道到 ${currentSplit} 个播放窗口`)
+  
+  // 决定从哪个播放器窗口开始分配:始终从第一个窗口(0)开始
+  // 这样保证每次分屏变化时都能从头开始重新分配
+  const startPlayerIndex = 0
+  
+  // 决定从哪个通道开始取:总是从第一个通道开始
+  const startChannelIndex = 0
+  
+  // 循环,为当前分屏布局中的每个位置分配通道
+  for (let screenPosition = 0; screenPosition < currentSplit; screenPosition++) {
+    const channelIndex = startChannelIndex + screenPosition
+    const targetPlayerIndex = startPlayerIndex + screenPosition
+    
+    // 延迟执行,避免同时发起大量请求
+    await new Promise(resolve => setTimeout(resolve, 50))
+    
+    if (channelIndex < channels.length) {
+      // 有对应通道,开始播放
+      const channelData = channels[channelIndex]
+      // 构建符合 sendDevicePush 要求的参数格式
+      const playData = {
+        deviceSipId: channelData.deviceId,
+        channelSipId: channelData.basicData?.channelSipId || channelData.id,
+        name: channelData.name || `通道${channelIndex + 1}`,
+        ...channelData.basicData
+      }
+      console.log(`将通道 ${playData.name} 分配给播放器 ${targetPlayerIndex}`)
+      await sendDevicePush(playData, targetPlayerIndex)
+    } else {
+      // 没有更多通道,清空当前位置
+      const newVideoUrls = [...videoUrl.value]
+      newVideoUrls[targetPlayerIndex] = ''
+      videoUrl.value = newVideoUrls
+      // 清理存储的数据
+      clear(targetPlayerIndex + 1)
+      console.log(`播放器 ${targetPlayerIndex} 没有可用通道,已清空`)
+    }
   }
 }
-
 // 通知设备上传媒体流
-const sendDevicePush = (itemData) => {
-  save(itemData)
-  let deviceId = itemData.deviceSipId
-  let channelId = itemData.channelSipId
+const sendDevicePush = (itemData, targetIndex = null) => {
+  // 关键修改:允许从外部传入 targetIndex,默认使用当前激活的 playerIdx
+  const playIndex = targetIndex !== null ? targetIndex : playerIdx.value;
 
-  let idxTmp = playerIdx.value
-  loading.value = true
+  save(itemData, playIndex); // 保存数据也要使用正确的索引
 
-  startPlay(deviceId, channelId)
-    .then((response) => {
-      let res = response
+  let deviceId = itemData.deviceSipId;
+  let channelId = itemData.channelSipId;
+  loading.value = true;
 
+  return startPlay(deviceId, channelId)
+    .then((response) => {
+      let res = response;
       if (window.location.protocol === 'http:') {
-          itemData.playUrl = res.ws_flv
-        
+        itemData.playUrl = res.ws_flv;
       } else {
-        itemData.playUrl = res.wss_flv
+        itemData.playUrl = res.wss_flv;
       }
-      itemData.streamId = res.streamId
-      setPlayUrl(itemData.playUrl, idxTmp)
+      itemData.streamId = res.streamId;
+      setPlayUrl(itemData.playUrl, playIndex); // 播放URL设置到指定位置
     })
     .finally(() => {
-      loading.value = false
-    })
-}
+      loading.value = false;
+    });
+};
+
+
+
 
 // 设置播放URL
 const setPlayUrl = (url, idx) => {
@@ -254,12 +373,12 @@ const shot = (e) => {
 }
 
 // 保存数据
-const save = (item) => {
-  let dataStr = window.localStorage.getItem('playData') || '[]'
-  let data = JSON.parse(dataStr)
-  data[playerIdx.value] = item
-  window.localStorage.setItem('playData', JSON.stringify(data))
-}
+const save = (item, index) => {
+  let dataStr = window.localStorage.getItem('playData') || '[]';
+  let data = JSON.parse(dataStr);
+  data[index] = item;
+  window.localStorage.setItem('playData', JSON.stringify(data));
+};
 
 // 清除数据
 const clear = (idx) => {