Newer
Older
safe_production_front / src / views / bigScreen / components / videoCommon.vue
dutingting on 8 Apr 6 KB 暂存
<script lang="ts" setup name="video6">
import { ElLoading, ElMessage, ElMessageBox } from 'element-plus'
import jessibuca from '../jessibuca.vue'
import jessibucaPro from '../jessibucaPro.vue'
// import flvjs from '../flvjs.vue'
import { createStream, sendHeart, stopStream } from '@/api/monitor/index-new-gm'
import { getConfig } from '@/api/bs'
import { getMediaStream, getMediaToken } from '@/api/monitor/media'
const props = defineProps({
  splitScreen: {
    type: Number,
    default: 6,
  },
  showEchart: {
    type: Boolean,
  },
})
const jessibucaVersion = ref('open') // 使用的jessibuca版本
const jessibucaRef = ref()
const baseurl = ref(window.location.href.split('/#')[0])
const mediaToken = ref('') // 流媒体token
const width = ref(0)
const height = ref(0)
const getConfigData: any = ref([])
const videoUrl = ref(['', '', '', '', '', '']) // 流url
const timers: any = ref([null, null, null, null, null, null]) // 定时器
const currentStreamId = ref(['', '', '', '', '', '']) // 正在播的流的国标号
// ----------------------------------------gm流---------------------------------------------------
// 创建流
async function fetchStream(deviceId: string) {
  const res = await createStream(deviceId)
  if (res && res.data) {
    return {
      url: res.data.url,
      createStreamResponseId: res.data.id,
    }
  }
  else {
    ElMessage.warning('创建流失败!')
  }
}

// 停止流
async function handleStopStream(deviceId: string) {
  const res = await stopStream(deviceId)
  if (res.code !== 200) {
    ElMessage.warning('停止流失败!')
  }
}

// 发送心跳
async function handleSendHeart(deviceId: string, index: number) {
  const res = await sendHeart(deviceId)
  if (res && res.data) {
    if (`${res.data.status}` !== 'on') { // 停止状态
      if (timers.value[index]) {
        clearInterval(timers.value[index])
      }
    }
  }
}

// 播放流
function playGmStream(cameraIndexCode: string, index: number) {
  if (timers.value[index]) {
    clearInterval(timers.value[index])
  }

  // 播下一个流先停止上一个流
  if (currentStreamId.value[index]) {
    handleStopStream(currentStreamId.value[index])
  }
  // 获取视频流接口
  fetchStream(cameraIndexCode).then((res: any) => {
    const { url, createStreamResponseId } = res
    console.log(`videoUrl.value[${index}]`, url)
    console.log('url字符串拼接', `${url}?token=${window.localStorage.getItem('token')}`)

    videoUrl.value[index] = `${url}?token=${window.localStorage.getItem('token')}`
    console.log(`请求成功url:videoUrl.value[${index}]`, videoUrl.value[index])
    jessibucaRef.value[index].play(videoUrl.value[index])
    // 记录正在播的流的国标号
    currentStreamId.value[index] = createStreamResponseId
    // 发送心跳
    timers.value[index] = setInterval(() => {
      handleSendHeart(createStreamResponseId, index)
    }, Number(window.localStorage.getItem('timeGap')))
  }).catch(() => {
    console.log('请求失败videoUrl.value[currentIndex]', index)
    ElMessage.warning('未获取到流!请联系管理员!')
  })
}

// ----------------------------------------sm流---------------------------------------------------
// 拉取流(流媒体)
async function fetchMediaStream(deviceId: string, channelId: string, index: number) {
  const res = await getMediaStream(deviceId, channelId, mediaToken.value)
  if (res && res.data) {
    videoUrl.value[index] = res.data.ws_flv
    nextTick(() => {
      console.log('jessibucaRef.value', jessibucaRef.value)
      jessibucaRef.value[index].play(res.data.ws_flv)
    })
  }
  else {
    ElMessage.warning('设备未注册')
  }
}
// -----------------------------------------------------------------------------------------------
onBeforeUnmount(() => {
  // 先停心跳
  if (window.localStorage.getItem('systemType') === 'gm') {
    timers.value.forEach((item: any) => {
      if (item) {
        clearInterval(item)
      }
    })

    // 停所有流
    currentStreamId.value.forEach((item: any) => {
      if (item) {
        handleStopStream(item)
      }
    })
  }
})

// 获取配置并播放
const fetchConfig = async (splitScreen: number) => {
  const res = await getConfig()
  if (res.data) {
    const configData = JSON.parse(res.data)
    getConfigData.value = configData
    if (configData && configData.length) {
      console.log('视频页面:获取设备数据', configData)
      configData.forEach((item: { cameraIndexCode: string; nvrIndexCode: string }, index: number) => {
        if (index < splitScreen) {
          if (window.localStorage.getItem('systemType') === 'gm') {
            playGmStream(item.cameraIndexCode, index)
          }
          else if (window.localStorage.getItem('systemType') === 'sm') {
            fetchMediaStream(item.cameraIndexCode, item.nvrIndexCode, index)
          }
        }
      })
    }
  }
}
onMounted(async () => {
  jessibucaVersion.value = window.localStorage.getItem('jessibucaVersion')!
  if (window.localStorage.getItem('systemType') === 'sm') {
    const res = await getMediaToken()
    mediaToken.value = res.data
  }
})

watch(() => props.splitScreen, (newValue: number) => {
  if (window.localStorage.getItem('systemType') === 'gm') {
    // 先停心跳
    timers.value.forEach((item: any) => {
      if (item) {
        clearInterval(item)
      }
    })

    // 停所有流
    currentStreamId.value.forEach((item: any) => {
      if (item) {
        handleStopStream(item)
      }
    })
  }
  fetchConfig(newValue)
  // setTimeout(() => {
  //   jessibucaRef.value[0].play('https://mister-ben.github.io/videojs-flvjs/bbb.flv')
  // })
}, { immediate: true })
</script>

<template>
  <div id="result" style="margin-top: 20px" />
  <div id="videoArea" class="video-area">
    <div v-if="jessibucaVersion === 'open'" :class="splitScreen === 1 ? 'oneScreen' : 'jessibuca-root'">
      <jessibuca
        v-for="item in props.splitScreen"
        :id="`container${item + 1}`"
        :key="item"
        ref="jessibucaRef"
      />
      <!-- <flvjs
        v-for="(item, index) in props.splitScreen"
        :key="item"
        :url="videoUrl[index]"
      /> -->
    </div>
    <div v-if="jessibucaVersion === 'pro'" :class="splitScreen === 1 ? 'oneScreen' : 'jessibuca-root'">
      <jessibuca-pro
        v-for="item in props.splitScreen"
        :id="`container${item + 1}`"
        :key="item"
        ref="jessibucaRef"
      />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.video-area {
  width: 100%;
  height: 100%;
  z-index: 0;
}
.title {
  position: absolute;
  color: red;
  top: 10rem;
  z-index: 99999;
}
.oneScreen {
  width: 100%;
  height: 100%;
  padding: 0px !important;
  margin: 0px !important;
}
.jessibuca-root {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr; /* 定义两列,每列占据相等空间 */
  gap: 3px; /* 可选,添加一些间距 */
  padding: 0px !important;
  margin: 0px !important;
}
</style>