<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>