提交 e22f07ca authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 e0e05750
......@@ -3,8 +3,8 @@ const DEFAULT_OPTIONS = {
controls: true,
autoplay: false,
// fluid: true,
playbackRates: [0.5, 1, 1.5, 2],
restoreEl: true
responsive: true,
playbackRates: [0.5, 1, 1.5, 2]
}
const DEFAULT_EVENTS = [
'abort',
......@@ -101,3 +101,9 @@ onUnmounted(() => {
<template>
<video class="video-js vjs-default-skin vjs-big-play-centered" ref="videoRef"></video>
</template>
<style>
.video-js {
font-size: 12px;
}
</style>
......@@ -30,6 +30,39 @@ watchEffect(() => {
semesterId = route.query.semester_id as string
})
const skipTime = $ref<number>(6)
/**
* 视频播放器相关
*/
let src = $ref<{ src: string; type: string }>()
// 跳过片头
const isSkip = $ref(useStorage('isSkip', false))
// 连续播放
const isAutoPlayNext = $ref(useStorage('isAutoPlayNext', false))
// 播放器ready
let isReady = $ref<boolean>(false)
let videoJsPlayer = $ref<VideoJsPlayer | null>()
const onReady = (player: VideoJsPlayer) => {
isReady = true
videoJsPlayer = player
}
function changeSrc(data: PlayItemType) {
// src = { src: data.PlayURL, type: 'application/x-mpegURL' }
src = { src: data.PlayURL, type: 'video/mp4' }
}
// 切换视频清晰度
function changeDefinition(data: PlayItemType) {
changeSrc(data)
}
// 切换视频资源
function changeResource(data: CourseResourceType) {
throttledFn && throttledFn.flush()
resourceId = data.resource_id
videoJsPlayer && videoJsPlayer.pause()
}
// 当前章
const chapter = $computed(() => {
return props.chapterList.find(item => item.id === chapterId)
......@@ -44,15 +77,15 @@ const resource = $computed(() => {
return section?.resources.find(item => item.resource_id === resourceId && item.resource_type === 2)
})
// 资源视频列表
const videoList = $computed<CourseResourceType[]>(() => {
const resourceVideoList = $computed<CourseResourceType[]>(() => {
const list = section?.resources ?? []
return list.filter(item => item.resource_type === 2)
})
watchEffect(() => {
if (videoList.length) {
const found = videoList.find(item => item.resource_id === resourceId)
resourceId = found ? resourceId : videoList[0]?.resource_id
if (resourceVideoList.length) {
const found = resourceVideoList.find(item => item.resource_id === resourceId)
resourceId = found ? resourceId : resourceVideoList[0]?.resource_id
}
})
......@@ -66,7 +99,13 @@ const progress = reactive<VideoRecordType>({
let playList = $ref<PlayItemType[]>([])
const currentPlayList = $computed<PlayItemType[]>(() => {
return playList.filter(item => item.StreamType === 'video' && item.Format === 'mp4')
return playList
.filter(item => item.StreamType === 'video' && item.Format === 'mp4')
.map(item => {
const DefinitionMap: Record<string, string> = { FD: '流畅', LD: '标清', SD: '高清', HD: '超清' }
const DefinitionName = DefinitionMap[item.Definition] || item.Definition
return { ...item, DefinitionName }
})
})
// 获取视频信息
......@@ -90,19 +129,36 @@ async function fetchVideoRecords() {
progress.max_playing_time = detail.max_playing_time ? parseFloat(detail.max_playing_time) : 0
progress.valid_playing_time = detail.valid_playing_time ? parseFloat(detail.valid_playing_time) : 0
progress.watchedTimePoint = []
console.log('info', progress.current_playing_time)
}
watchEffect(async () => {
if (!resource) return
await fetchVideoRecords()
await fetchInfo()
console.log('watch', progress.current_playing_time)
changeSrc(currentPlayList[0])
nextTick(() => {
if (videoJsPlayer && progress.current_playing_time) {
})
function setVideoInfo() {
if (!videoJsPlayer) return
// 统计,增加默认时间10秒
progress.valid_playing_time = progress.valid_playing_time || 10
// 跳过片头
if (isSkip) {
// 跳过片头
if (progress.current_playing_time < skipTime) {
progress.current_playing_time = skipTime
}
// 有效时间增加跳过片头的时间
if (!progress.valid_playing_time) {
progress.valid_playing_time = skipTime + 10
}
}
// 初始化跳转到上次观看的时间点
videoJsPlayer.currentTime(progress.current_playing_time)
console.log('seek', progress.current_playing_time)
}
})
})
videoJsPlayer.play()
}
const throttledFn = throttle(
() => {
uploadVideoRecords({
......@@ -122,20 +178,19 @@ const throttledFn = throttle(
5000
// { leading: false }
)
// 视频加载完成
function onLoadedData() {
console.log('onLoadedData')
setVideoInfo()
}
// 进度更新
function onTimeUpdate() {
if (!videoJsPlayer) return
const time = Math.floor(videoJsPlayer.currentTime() ?? 0)
if (!time) return
const time = Math.floor(videoJsPlayer?.currentTime() ?? 0)
if (!time || videoJsPlayer?.paused()) return
console.log('onTimeUpdate', time)
// 更新观看累计时长
if (time !== progress.current_playing_time) {
// // 增加跳过片头时间
// if (this.isSkip && !this.progress.pt) {
// this.progress.pt = this.skipTime + 20
// }
// 默认增加时间
progress.valid_playing_time = progress.valid_playing_time || 20
progress.valid_playing_time++
}
// 更新当前播放时间
......@@ -148,31 +203,15 @@ function onTimeUpdate() {
throttledFn()
}
/**
* 视频播放器相关
*/
let src = $ref<{ src: string; type: string }>()
// 跳过片头
const isSkip = useStorage('isSkip', false)
// 连续播放
const isAutoPlayNext = useStorage('isAutoPlayNext', false)
// 播放器ready
let isReady = $ref<boolean>(false)
let videoJsPlayer = $ref<VideoJsPlayer | null>()
const onReady = (player: VideoJsPlayer) => {
isReady = true
videoJsPlayer = player
videoJsPlayer.currentTime(progress.current_playing_time)
console.log('seek', progress.current_playing_time)
}
function changeSrc(data: PlayItemType) {
// src = { src: data.PlayURL, type: 'application/x-mpegURL' }
src = { src: data.PlayURL, type: 'video/mp4' }
}
function changeResource(data: CourseResourceType) {
throttledFn && throttledFn.flush()
resourceId = data.resource_id
// 播放结束
function onEnded() {
console.log('onEnd')
// 自动播放下一个视频
if (isAutoPlayNext) {
const currentIndex = resourceVideoList.findIndex(item => item.resource_id === resourceId)
const next = resourceVideoList[currentIndex + 1]
next && changeResource(next)
}
}
</script>
......@@ -182,36 +221,46 @@ function changeResource(data: CourseResourceType) {
:src="src"
@ready="onReady"
@timeupdate="onTimeUpdate"
style="width: 100%; height: 510px"
@ended="onEnded"
@loadeddata="onLoadedData"
height="510"
style="width: 100%"
v-if="src"
></AppVideoPlayer>
<!-- 设置 -->
<teleport to=".vjs-control-bar" v-if="isReady">
<el-popover trigger="hover" effect="dark" placement="top" :teleported="false">
<el-popover trigger="hover" effect="dark" placement="top" :teleported="false" width="40px">
<template #reference>
<button class="vjs-hd-control vjs-control vjs-button" type="button">
<span class="vjs-icon-hd"></span>
</button>
</template>
<ul>
<li v-for="(item, index) in currentPlayList" :key="index" @click="changeSrc(item)">{{ item.Definition }}</li>
<ul class="video-definition">
<li
v-for="(item, index) in currentPlayList"
:key="index"
:class="{ 'is-active': item.PlayURL === src.src }"
@click="changeDefinition(item)"
>
{{ item.DefinitionName }}
</li>
</ul>
</el-popover>
<el-popover trigger="hover" effect="dark" placement="top" :teleported="false">
<el-popover trigger="hover" effect="dark" placement="top" :teleported="false" width="140px">
<template #reference>
<button class="vjs-cog-control vjs-control vjs-button" type="button">
<span class="vjs-icon-cog"></span>
</button>
</template>
<ul>
<li>始终跳过片头 <el-switch v-model="isSkip"></el-switch></li>
<li>连续播放 <el-switch v-model="isAutoPlayNext"></el-switch></li>
<ul class="video-actions">
<li>始终跳过片头 <el-switch size="small" v-model="isSkip"></el-switch></li>
<li>连续播放 <el-switch size="small" v-model="isAutoPlayNext"></el-switch></li>
</ul>
</el-popover>
</teleport>
<swiper :slidesPerView="'auto'" :spaceBetween="30">
<swiper-slide
v-for="item in videoList"
v-for="item in resourceVideoList"
:key="item.id"
class="video-item"
:class="{ 'is-active': item.resource_id === resourceId }"
......@@ -261,4 +310,41 @@ function changeResource(data: CourseResourceType) {
border: 2px solid var(--main-color);
}
}
.video-definition {
font-size: 12px;
li {
display: flex;
align-items: center;
justify-content: center;
padding: 0.2em 0;
font-size: 1.2em;
line-height: 1.4em;
&.is-active {
color: #2b333f;
background-color: #fff;
}
}
}
.video-actions {
font-size: 12px;
li {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.2em 5px;
font-size: 1.2em;
line-height: 1.4em;
}
}
:deep(.el-popover) {
min-width: auto;
background-color: rgba(43, 51, 63, 0.7);
border: 0;
border-radius: 0;
padding: 0;
margin-bottom: -12px !important;
.el-popper__arrow {
display: none;
}
}
</style>
......@@ -82,4 +82,5 @@ export interface PlayItemType {
Status: string
StreamType: string
Width: number
DefinitionName: string
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论