Files
tangguo_admin/src/views/videoManagement/videoExamine/components/preview-video.vue
T
rootandClaude Opus 5 d999a5c0e6 Initial commit
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 12:02:35 +08:00

180 lines
4.1 KiB
Vue

<template>
<div>
<el-dialog
:title="title"
align="center"
:visible.sync="dialogVisible"
width="40%"
:before-close="handleClose"
:close-on-click-modal="false"
>
<div :data="myData" class="my_data">
<span>视频状态:{{ myData.status | videoStatus }}</span>
<span>视频高度:{{ myData.height }}</span>
<span>视频宽度:{{ myData.width }}</span>
<span>视频时长:{{ myData.playTime + "s" }}</span>
</div>
<div class="media-box" v-if="videoShow">
<video
ref="videoEl"
class="preview-video"
controls
preload="auto"
playsinline
></video>
</div>
<div class="media-box" id="img-box" v-if="imgShow">
<img :src="mediaUrl" />
</div>
</el-dialog>
</div>
</template>
<script>
import Hls from "hls.js";
import baseConfig from "@/utils/serverUrlConfig";
import API from "@/api";
export default {
data() {
return {
dialogVisible: false,
imgShow: true,
mediaUrl: "",
videoShow: false,
title: "封面图查看",
params: {},
urll: "",
myData: [],
hls: null
};
},
computed: {
token() {
return this.$store.state.token;
}
},
beforeDestroy() {
this.destroyPlayer();
},
methods: {
// 视频审查列表
videoFeviewList() {
let urll = this.urll;
API.videoFeviewList(this.params, urll).then(res => {
this.myData = res.data;
});
},
destroyPlayer() {
if (this.hls) {
this.hls.destroy();
this.hls = null;
}
const video = this.$refs.videoEl;
if (video) {
video.pause();
video.removeAttribute("src");
video.load();
}
},
handleClose() {
this.destroyPlayer();
this.dialogVisible = false;
this.imgShow = false;
this.videoShow = false;
this.mediaUrl = "";
},
initHlsPlayer(src) {
const video = this.$refs.videoEl;
if (!video || !src) return;
if (Hls.isSupported()) {
this.hls = new Hls({
enableWorker: true,
maxBufferLength: 15,
maxMaxBufferLength: 180
});
this.hls.loadSource(src);
this.hls.attachMedia(video);
this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
video.play().catch(() => {});
});
this.hls.on(Hls.Events.ERROR, (event, data) => {
if (!data.fatal || !this.hls) return;
if (data.type === Hls.ErrorTypes.NETWORK_ERROR) {
this.hls.startLoad();
} else if (data.type === Hls.ErrorTypes.MEDIA_ERROR) {
this.hls.recoverMediaError();
} else {
this.destroyPlayer();
}
});
return;
}
// Safari 等原生 HLS
if (video.canPlayType("application/vnd.apple.mpegurl")) {
video.src = src;
video.addEventListener(
"loadedmetadata",
() => {
video.play().catch(() => {});
},
{ once: true }
);
}
},
open(url, type, data) {
this.destroyPlayer();
this.dialogVisible = true;
if (type === "img") {
this.imgShow = true;
this.videoShow = false;
this.title = "封面图查看";
this.mediaUrl = url;
} else {
this.imgShow = false;
this.videoShow = true;
this.title = "视频查看";
this.mediaUrl =
baseConfig.baseServerUrl +
baseConfig.playVideoUrl +
url +
"?token=" +
this.token;
this.urll = data.id;
this.$nextTick(() => {
this.initHlsPlayer(this.mediaUrl);
this.videoFeviewList();
});
}
}
}
};
</script>
<style scoped lang="scss">
.my_data {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.media-box {
width: 100%;
height: 400px;
text-align: center;
overflow: hidden;
img {
height: 100%;
max-width: 100%;
}
.preview-video {
width: 100% !important;
height: 100% !important;
border: none !important;
background: #000;
object-fit: contain;
}
}
</style>