<script setup>
|
import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue'
|
import videojs from 'video.js'
|
|
const props = defineProps({
|
width: {
|
type: String,
|
default: '800',
|
},
|
modelValue: {
|
type: Boolean,
|
default: false,
|
},
|
playUrl: {
|
type: String,
|
default: '',
|
},
|
title: {
|
type: String,
|
default: '视频播放',
|
},
|
})
|
|
const emit = defineEmits(['update:modelValue'])
|
const videoRefs = ref(null)
|
let player = null
|
|
const dialogVisible = computed({
|
get: () => props.modelValue,
|
set: value => emit('update:modelValue', value),
|
})
|
|
function getVideoType(url) {
|
const path = (url || '').split('?')[0].toLowerCase()
|
if (path.endsWith('.m3u8')) return 'application/x-mpegURL'
|
if (path.endsWith('.mp4')) return 'video/mp4'
|
if (path.endsWith('.webm')) return 'video/webm'
|
if (path.endsWith('.ogg') || path.endsWith('.ogv')) return 'video/ogg'
|
if (path.endsWith('.mov')) return 'video/quicktime'
|
return ''
|
}
|
|
function destroyPlayer() {
|
if (!player) return
|
player.dispose()
|
player = null
|
}
|
|
function getSource() {
|
const type = getVideoType(props.playUrl)
|
return {
|
src: props.playUrl,
|
...(type ? { type } : {}),
|
}
|
}
|
|
async function initPlayer() {
|
if (!props.modelValue || !props.playUrl) return
|
await nextTick()
|
if (!videoRefs.value) return
|
|
if (player) {
|
player.src(getSource())
|
player.load()
|
return
|
}
|
|
player = videojs(videoRefs.value, {
|
controls: true,
|
preload: 'auto',
|
autoplay: false,
|
fluid: false,
|
width: '100%',
|
height: '600px',
|
sources: [getSource()],
|
})
|
player.on('error', () => {
|
console.error('视频播放失败:', player?.error(), props.playUrl)
|
})
|
}
|
|
watch(
|
() => props.playUrl,
|
() => {
|
if (!props.modelValue || !props.playUrl) return
|
initPlayer()
|
}
|
)
|
|
onBeforeUnmount(destroyPlayer)
|
</script>
|
|
<template>
|
<el-dialog
|
class="gd-dialog video-dialog"
|
:title="props.title"
|
append-to-body
|
v-model="dialogVisible"
|
width="60%"
|
destroy-on-close
|
:close-on-click-modal="false"
|
@opened="initPlayer"
|
@closed="destroyPlayer"
|
>
|
<video
|
ref="videoRefs"
|
id="videoPlayDialogPlayer"
|
class="video-js vjs-default-skin vjs-big-play-centered"
|
controls
|
preload="auto"
|
playsinline
|
></video>
|
</el-dialog>
|
</template>
|
|
<style lang="scss">
|
.video-dialog {
|
.video-js {
|
height: 600px;
|
width: 100%;
|
}
|
}
|
</style>
|
|
<style scoped lang="scss">
|
:deep(.video-js .vjs-tech) {
|
height: 100%;
|
width: 100%;
|
}
|
</style>
|