Newer
Older
safe_production_front / src / views / ycjg / ssjk / index-new-gm-plugin.vue
dutingting on 25 Oct 10 KB gm视频调试
<script lang="ts" setup name="ResourceList">
import type { Ref } from 'vue'
import { getCurrentInstance, nextTick, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { createStream, sendHeart, stopStream } from '@/api/ycjg/index-new-gm'
import { videoTree } from '@/api/ycjg/aqbb'
const router = useRouter()
const timer = ref() // 定时器
const treeRef = ref(null) as any
const filterText = ref('')
const data = ref([])

const defaultProps = ref({
  children: 'children',
  label: 'name',
  isDisabled: 'disabled',
})
const baseurl = ref(window.location.href.split('/#')[0])
console.log('baseurl', baseurl.value)
const { proxy } = getCurrentInstance() as any
const mediaToken = ref('') // 流媒体token
const width = ref(0)
const height = ref(0)
const loading = ref(false)
const src = ref([''])
const title = ref('')
const leafLoading = ref(false)
const currentLeafId = ref('')
const currentStreamId = ref('') // 正在播的流的国标号
const resize = () => {
  const divPlugin = document.getElementById('home') as any
  console.log(divPlugin)
  // width.value = divPlugin.clientWidth / 2 - 20
  // height.value = divPlugin.clientHeight / 2 - 5
  width.value = divPlugin.clientWidth
  height.value = divPlugin.clientHeight - 5
}

const iframeDblclick = () => {
  // page(0)
}

function filterNode(value: any, data: { name: string | any[] }) {
  if (value === '' || value === null) {
    return true
  }
  return data.name.includes(value)
}

let treeClickCount = 0
const currentCameras = [{}] as any

function handleNodeClick(data: any, node: any, self: any) {
  console.log('获取设备信息', data)
  if (data.device.deviceStatusName === '离线') {
    ElMessage.warning(`设备 ${data.device.monitorName} 离线`)
    return false
  }

  const now = new Date().getTime()
  if (now - treeClickCount < 300) { // 双击事件的判断,300毫秒内重复点击
    if (data.children.length !== 0) { // 点击父亲
      return
    }
    if (data.device.id === currentLeafId.value) {
      return
    }

    // ElMessage.warning('正在加载流,请稍等!')
    leafLoading.value = true
    currentLeafId.value = data.device.id

    // 先停心跳
    if (timer.value) {
      clearInterval(timer.value)
    }

    // 播下一个流先停止上一个流
    if (currentStreamId.value) {
      handleStopStream(currentStreamId.value)
    }
    // 获取视频流接口
    fetchStream(data.device.cameraIndexCode).then((res: any) => {
      leafLoading.value = false
      const { url, createStreamResponseId } = res
      src.value[0] = `${url}?token=${window.localStorage.getItem('token')}`
      currentCameras[0] = data
      title.value = data.device.monitorName.replace('-', ' - ')
      // 记录正在播的流的国标号
      currentStreamId.value = createStreamResponseId

      // 发送心跳
      timer.value = setInterval(() => {
        handleSendHeart(createStreamResponseId)
      }, Number(window.localStorage.getItem('timeGap')))
    }).catch(() => {
      ElMessage.warning('未获取到流!请联系管理员!')
      leafLoading.value = false
    })
  }
  treeClickCount = now
}

// 创建流
async function fetchStream(deviceId: string) {
  loading.value = true
  const res = await createStream(deviceId)
  loading.value = false
  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) {
  const res = await sendHeart(deviceId)
  if (res && res.data) {
    if (`${res.data.status}` !== 'on') { // 停止状态
      if (timer.value) {
        clearInterval(timer.value)
      }
    }
  }
}

function page(index: any) {
  console.log('跳转控制页')

  // if (src.value[index] !== '') {
    router.push({
      path: '/ssjk/control',
      query: {
        id: currentCameras[index].id,
      },
    })
  // }
}

const unwatch = watch(filterText, (newVal) => {
  treeRef.value.filter(newVal)
})

onBeforeUnmount(() => {
  unwatch()
  window.removeEventListener('resize', resize)
  // window.removeEventListener('dblclick', iframeDblclick)
  clearInterval(timer.value)
  // 停止正在播放的流
  if (currentStreamId.value) {
    handleStopStream(currentStreamId.value)
  }
})

function solveData(data: any) {
  data.forEach((item: any) => {
    if (item.device) {
      item.name = `${item.name} (${item.device.deviceStatusName})`
      console.log('修改后的name', item.name)
    }
    if (item.children && item.children.length) {
      solveData(item.children)
    }
  })
  return data
}

onMounted(() => {
  videoTree().then((response) => {
    if (response.code === 200) {
      data.value = response.data
      // data.value = solveData(data.value)
    }
  })
  setTimeout(() => {
    // 双击跳转控制页
    // const iframe = document.getElementById('myframe')
    // const iframeDoc = iframe.contentDocument || iframe.contentWindow.document

    // iframeDoc.addEventListener('dblclick', iframeDblclick)
    resize()
    window.addEventListener('resize', resize)
  }, 200)
})
</script>

<template>
  <app-container style="height: calc(100vh - 110px)">
    <div style="display: flex;height: 100%">
      <el-card class="left">
        <el-input
          v-model="filterText"
          placeholder="设备名称过滤"
          style="margin-bottom: 10px;"
        />
        <el-tree
          ref="treeRef"
          class="filter-tree"
          style="width: 100%;height: 100%"
          :data="data"
          :filter-node-method="filterNode"
          node-key="id"
          :default-expand-all="true"
          :props="defaultProps"
          @node-click="handleNodeClick"
        >
          <template #default="{ node, data }">
            <span style="display: flex;align-items: center;">
              <!-- && leafLoading -->
              <el-icon class="loading-rotate" style="margin-right: 5px" v-if="data.device.id === currentLeafId && leafLoading">
                <svg-icon name="icon-loading" />
              </el-icon>
              <!-- <el-image style="margin-right: 5px;width: 20px;height: 20px;" src="/loading.gif" v-if="data.device.id === currentLeafId"></el-image> -->
              <el-icon v-if="data.device.deviceStatusName === '在线'" style="margin-right: 5px">
                <svg-icon name="icon-online" />
              </el-icon>
              <el-icon v-if="data.device.deviceStatusName === '离线'" style="margin-right: 5px">
                <svg-icon name="icon-offline" />
              </el-icon>
              <el-tooltip
                class="box-item"
                effect="dark"
                :content="node.label"
                placement="right"
              >
                <template #content>
                  <span>{{ node.label }}</span>
                  <span v-if="data.device.deviceTypeName">({{ data.device.deviceTypeName }})</span>
                </template>
                <span v-if="data.device.deviceTypeName" :style="{ 'color': data.device.deviceStatusName === '在线' ? '#0e932e' : '#606266', 'font-weight': data.device.deviceStatusName === '在线' ? 600 : 500 }">{{ node.label }}</span>
                <span v-else>{{ node.label }}</span>
              </el-tooltip>
              <el-icon v-if="data.device.deviceType === '0'" style="margin-left: 5px">
                <svg-icon name="icon-qiang" :color="data.device.deviceStatusName === '在线' ? '#0e932e' : '#979797'"/>
              </el-icon>
              <el-icon v-if="data.device.deviceType === '1' || data.device.deviceType === '2'" style="margin-left: 5px;">
                <svg-icon name="icon-ball" :color="data.device.deviceStatusName === '在线' ? '#0e932e' : '#979797'" />
              </el-icon>
              <el-icon v-if="data.device.deviceType === '3'" style="margin-left: 5px;">
                <svg-icon name="icon-ball" :color="data.device.deviceStatusName === '在线' ? '#0e932e' : '#979797'" />
              </el-icon>
              <el-icon v-if="data.device.deviceType === '4'" style="margin-left: 5px;">
                <svg-icon name="icon-ytqiang" :color="data.device.deviceStatusName === '在线' ? '#0e932e' : '#979797'" />
              </el-icon>
              <!-- <span v-if="data.device.deviceTypeName">{{ node.label.slice(node.label.indexOf('(')) }}</span> -->
            </span>
          </template>
        </el-tree>
      </el-card>
      <div id="home" class="right">
        <!-- <video id="video0" :src="src[0]" autoPlay :width="width" :height="height - 24" @dblclick="page(0)"/> -->
        <!-- <iframe
          id="myframe"
          :src="`${baseurl}/player/player.html?playUrl=${src[0]}`"
          frameborder="0"
          :style="{ width: `${width}px`, height: `${height - 28}px` }"
        /> -->
        <iframe
          id="myframe"
          :src="`${baseurl}/player/player.html?playUrl=${src[0]}`"
          frameborder="0"
          :style="{ width: `${width}px`, height: `${height - 28}px` }"
        />
        <div class="title">
          {{ title }}
        </div>
        <div v-if="leafLoading" style="font-size: 28px;color: #fff;font-weight: 600;position: absolute;
          z-index: 1000;top: 50%;left: 35%;letter-spacing: 4px;">视频加载中,请稍等...</div>
      </div>
    </div>
  </app-container>
</template>

<style lang="scss" scoped>
.right {
  position: relative;
  box-sizing: border-box;
  flex: 1;
  margin-left: 10px;
  padding-top: 30px;
  background: #111;
  border-radius:  15px 15px  0 0 ;
}

.title {
  position: absolute;
  z-index: 1000;
  font-size: 16px;
  letter-spacing: 1px;
  cursor: pointer;
  background: linear-gradient(180deg, #71b5ff, #4384ff);
  color: white;
  font-weight: bold;
  line-height: 30px;
  width: 100%;
  height: 30px;
  top: 0px;
  border-radius:  15px 15px  0 0 ;
  padding-left: 6px;
}
.left {
  width: 300px;
  height: 100%;
  padding: 10px;
  overflow-y: scroll;

}

.video-container {
  display: flex;
  flex: 1;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  margin-bottom: 5px;
}
video {
  position: relative;
  object-fit: fill;
  overflow: hidden;
  background: #000;
}

/* 定义一个名为rotate的动画 */
@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

/* 应用动画到具体的元素上 */
.loading-rotate {
  animation: rotate 2s linear infinite;
}
</style>