<template>
<div id="video_window" class="video_window">
<div class="header-wrapper">
<h3>{{props.deviceId}}——{{props.selectedCamera.name}}——Camera</h3>
<el-button
class="close-btn"
circle
@click="handleCloseAspect"
><el-icon><Close /></el-icon></el-button>
</div>
<el-form :model="formData" class="timepicker">
<el-form-item label="起始时间">
<el-date-picker v-model="formData.starttime" type="datetime" placeholder="请选择起始时间" format="YYYY-MM-DD HH:mm:ss" value-format="YYYYMMDDTHHmmss[Z]"></el-date-picker>
</el-form-item>
<el-form-item label="结束时间">
<el-date-picker v-model="formData.endtime" type="datetime" placeholder="请选择结束时间" format="YYYY-MM-DD HH:mm:ss" value-format="YYYYMMDDTHHmmss[Z]"></el-date-picker>
</el-form-item>
<el-form-item><el-button type="primary" @click="startPlay">播放</el-button></el-form-item>
<el-form-item><el-button type="primary" :disabled="isDisabled" @click="stopPlay">停止</el-button></el-form-item>
<el-form-item><el-button type="primary" :disabled="isDisabled" @click="pausePlay">{{ isPlaying ? "暂停":"继续" }}</el-button></el-form-item>
</el-form>
<div class="mainAspect">
<div v-if="videoLoading" class="custom-loading-layer">
<div class="loading-spinner"></div>
<p>视频加载中...</p>
</div>
<video id="videoElement" class="videoElement" ref="flvPlayer" autoplay preload="metadata"></video>
</div>
</div>
</template>
<script setup>
import flvjs from "flv.js"
import { Close } from '@element-plus/icons-vue'
import { computed, onMounted, ref, watch, onUnmounted,defineEmits,nextTick } from 'vue';
import { getActionCallBack,videoCloseCallBack } from '../api';
import {useStatusStore} from '../stores/videoCache'
import { ElMessage } from "element-plus";
import dayjs from 'dayjs';
const props = defineProps({
deviceId: {
type: String,
required: true
},
selectedCamera:{
type: Object,
required: true
}
});
const emit= defineEmits(['close'])
const videCache=useStatusStore();
const originVideoPath='rtsp://admin:sess2025@'
const flvPath=ref(null);
const flvPlayer = ref(null);
let player=null;
const videoLoading=ref(false);
const formData=ref({starttime:null,endtime:null});
const isDisabled=ref(true);
const isPlaying=ref(true);
watch(
()=>props.selectedCamera,
async (newVal,oldVal) =>{
console.log(newVal);
console.log(oldVal);
if (player) {
player.destroy();
player=null;
videoLoading.value=false;
await closeOldVideoStream(oldVal.ip, oldVal.channelNo);
}
},{deep:true}
)
const handleCloseAspect=()=>{
emit('close');
}
const fetchVideoStream=async (starttime,endtime)=>{
const res = await getActionCallBack(originVideoPath+String(props.selectedCamera.ip)+":554/streaming/tracks/"+String(props.selectedCamera.channelNo)+"01?starttime="+starttime+"^&endtime="+endtime);
flvPath.value=res.data;
};
const closeVideoStream=async ()=>{
const res = await videoCloseCallBack(props.selectedCamera.ip,props.selectedCamera.channelNo);
console.log(res.data);
};
const closeOldVideoStream=async (ip, channelNo)=>{
const res = await videoCloseCallBack(ip, channelNo);
console.log(res.data);
};
const initPlayer=()=>{
if(flvPath.value!==null){
if (flvjs.isSupported()) {
let videoElement = document.getElementById('videoElement')
player = flvjs.createPlayer({
type: 'flv',
isLive: true,
fluid: true,
stashInitialSize: 128,// 减少首桢显示等待时长
url: flvPath.value, //url地址
})
player.attachMediaElement(videoElement)
player.load()
player.on(flvjs.Events.METADATA_ARRIVED,()=>{
videoLoading.value=false;
})
player.play()
}
}else{
return;
}
};
const startPlay=async ()=>{
const now=dayjs().format('YYYYMMDDTHHmmss[Z]');
if(formData.value.starttime===null){
ElMessage.error("请选择起始时间!");
return null;
}else if(formData.value.endtime===null){
ElMessage.error("请选择结束时间!!");
return null;
}else if(formData.value.endtime>=now){
ElMessage.error("结束时间不能大于当前时间!")
return null;
}else{
videoLoading.value=true;
await fetchVideoStream(formData.value.starttime,formData.value.endtime);
initPlayer();
isDisabled.value=false;
}
}
const stopPlay=()=>{
if(player){
closeVideoStream();
player.destroy();
player=null;
}
}
const pausePlay=()=>{
if(!isPlaying.value){
console.log(isPlaying.value);
player.play();
isPlaying.value=true;
}
if (player) {
player.pause(); // 暂停播放
isPlaying.value=false;
}
}
onUnmounted(() => {
if (player) {
closeVideoStream();
player.destroy();
player=null;
}
});
</script>
<style scoped>
.video_window{
position: fixed;
top: 15%;
left: 30%;
width: 49%;
height: 70%;
border-radius: 5%;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(12px);
border-radius: 20px;
box-shadow:
0 12px 40px rgba(100, 100, 150, 0.15),
0 0 0 1px rgba(255, 255, 255, 0.6) inset;
overflow: hidden;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.1);
}
/* 标题栏 - 渐变背景与现代化按钮 */
.header-wrapper {
padding: 18px 25px;
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
position: relative;
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
.header-wrapper h3 {
margin: 0;
color: white;
font-weight: 500;
font-size: 1.2rem;
letter-spacing: 0.5px;
text-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
/* 时间选择表单 - 融入整体设计 */
.timepicker {
padding: 15px 30px;
background: rgba(245, 245, 255, 0.85);
border-bottom: 1px solid rgba(210, 210, 255, 0.6);
display: flex;
gap: 20px;
flex-wrap: wrap;
justify-content: center;
}
.el-form-item {
margin-bottom: 0;
}
.el-form-item label {
color: #5a5a8a;
font-weight: 500;
}
.el-date-editor, .el-button {
border-radius: 12px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
}
.el-button--primary {
background: linear-gradient(135deg, #7f5af0 0%, #2cb67d 100%);
border: none;
transition: all 0.3s ease;
}
.el-button--primary:hover {
transform: translateY(-2px);
box-shadow: 0 4px 10px rgba(127, 90, 240, 0.3);
}
.mainAspect{
width: 100%;
height: 82%;
background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
position: relative;
overflow: hidden;
border-radius: 0 0 28px 28px;
}
.videoElement{
width: 100%;
height: 100%;
transform-origin: center;
object-fit: contain;
transition: opacity 0.3s;
}
.close-btn {
position: absolute;
right: 10px;
top: 10px;
z-index: 20;
background: rgba(255,255,255,0.2);
border: none;
transition: all 0.3s ease;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
/*加载状态样式 */
.custom-loading-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 10;
background: rgba(15, 12, 41, 0.85);
backdrop-filter: blur(4px);
color: #94a3b8;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(255,255,255,0.3);
border-radius: 50%;
border-top-color: gray;
animation: spin 1s linear infinite;
border-top-color: #2cb67d;
border-left-color: rgba(124, 58, 237, 0.5);
border-bottom-color: rgba(44, 182, 125, 0.3);
border-right-color: rgba(124, 58, 237, 0.2);
border-width: 4px;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
</style>我这样写为什么点击继续没有重新播放
最新发布