144 lines
4.1 KiB
Vue
144 lines
4.1 KiB
Vue
<script setup>
|
||
import { ref, watch, onMounted, onUnmounted, computed } from 'vue';
|
||
import { isEmpty, getAssetsFile } from '@/utils';
|
||
import { useRoute, useRouter } from 'vue-router';
|
||
import Hls from 'hls.js';
|
||
const route = useRoute();
|
||
const router = useRouter();
|
||
|
||
const currentDevice = ref(0);
|
||
const currentPicture = ref(0);
|
||
const videoPlayer = ref(null);
|
||
const hls = ref(null);
|
||
|
||
const loading = ref(false);
|
||
const error = ref(false);
|
||
|
||
const props = defineProps({
|
||
title: {
|
||
type: String,
|
||
required: true,
|
||
default: () => '',
|
||
validator: (items) => {
|
||
return items;
|
||
},
|
||
},
|
||
devices: {
|
||
type: Array,
|
||
required: true,
|
||
default: () => [],
|
||
validator: (items) => {
|
||
const validItems = items.filter((item) => item.icon === 'camera');
|
||
return validItems.every((item) => {
|
||
return (
|
||
typeof item === 'object' &&
|
||
item !== null &&
|
||
typeof item.id === 'number' &&
|
||
typeof item.name === 'string' &&
|
||
typeof item.icon === 'string' &&
|
||
typeof item.detail === 'string' &&
|
||
(!item.status || typeof item.status === 'number')
|
||
);
|
||
});
|
||
},
|
||
},
|
||
});
|
||
|
||
const emit = defineEmits(['changeDevice']);
|
||
// 显示天气详情弹窗
|
||
const showWeatherDetail = (data) => {
|
||
emit('changeDevice', { message: data });
|
||
};
|
||
|
||
// 监听 currentDevice 的变化
|
||
watch(currentDevice, (newValue, oldValue) => {
|
||
showWeatherDetail(newValue);
|
||
// console.log(`count 从 ${oldValue} 变为 ${newValue}`);
|
||
});
|
||
|
||
onUnmounted(() => {
|
||
if (hls.value) {
|
||
hls.value.destroy();
|
||
}
|
||
});
|
||
|
||
onMounted(async () => {
|
||
if (Hls.isSupported()) {
|
||
hls.value = new Hls();
|
||
hls.value.loadSource('https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8');
|
||
hls.value.attachMedia(videoPlayer.value);
|
||
hls.value.on(Hls.Events.MANIFEST_PARSED, () => {
|
||
videoPlayer.value.play();
|
||
});
|
||
} else if (videoPlayer.value.canPlayType('application/vnd.apple.mpegurl')) {
|
||
// Safari原生支持HLS
|
||
videoPlayer.value.src = 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8';
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<el-card style="border-radius: 16px">
|
||
<div style="display: flex; justify-content: space-between">
|
||
<div style="font-size: 16px; font-weight: bold; text-align: left">{{ title }}</div>
|
||
<div>
|
||
<div>当前设备状态:</div>
|
||
<div>
|
||
<div class="dot"></div>
|
||
<span>正常</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="color: #999999; line-height: 25px">
|
||
当前设备
|
||
<el-select v-model="currentDevice" placeholder="Select" size="small" style="width: 160px; margin-left: 10px">
|
||
<el-option v-for="item in devices" :key="item.value" :label="item.detail" :value="item.id" />
|
||
</el-select>
|
||
</div>
|
||
</div>
|
||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||
<div class="video-wrapper">
|
||
<video ref="videoPlayer" controls autoplay muted></video>
|
||
<div v-if="loading" class="status-message">正在加载直播流...</div>
|
||
<div v-if="error" class="status-message error">{{ error }}</div>
|
||
</div>
|
||
<div class="pictures-wrapper">
|
||
<img :src="getAssetsFile('images/smartFarm/goUp.png')" alt="" style="width: 100px" />
|
||
<img :src="getAssetsFile('images/smartFarm/testPic1.png')" style="width: 80%; margin: 5px 0" :alt="devices[currentDevice].detail" />
|
||
<img :src="getAssetsFile('images/smartFarm/testPic1.png')" style="width: 80%; margin: 5px 0" :alt="devices[currentDevice].detail" />
|
||
<img :src="getAssetsFile('images/smartFarm/goDown.png')" alt="" style="width: 100px" />
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</template>
|
||
|
||
<style scoped lang="scss">
|
||
.video-wrapper {
|
||
height: 100%;
|
||
margin-top: 30px;
|
||
width: 58%;
|
||
video {
|
||
width: 100%;
|
||
border-radius: 16px;
|
||
}
|
||
}
|
||
.pictures-wrapper {
|
||
width: 38%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-top: 20px;
|
||
img {
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
.dot {
|
||
height: 10px;
|
||
width: 10px;
|
||
display: inline-block;
|
||
border-radius: 90px;
|
||
background-color: #25bf82;
|
||
}
|
||
</style>
|