更新:课程视频播放改成原生video组件
This commit is contained in:
131
components/video-player/composables/useVideoProgress.ts
Normal file
131
components/video-player/composables/useVideoProgress.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
// components/video-player/composables/useVideoProgress.ts
|
||||
import { ref } from 'vue'
|
||||
import { videoStorage } from '@/utils/videoStorage'
|
||||
import { videoApi } from '@/api/modules/video'
|
||||
import type { IVideoInfo } from '@/types/video'
|
||||
|
||||
/**
|
||||
* 视频播放进度管理
|
||||
*/
|
||||
export function useVideoProgress() {
|
||||
const currentTime = ref(0)
|
||||
const isSaving = ref(false)
|
||||
let saveTimer: any = null
|
||||
|
||||
/**
|
||||
* 获取初始播放位置
|
||||
* 合并本地和服务器的播放位置,取较大值
|
||||
* 如果视频已经看完(播放位置 >= 总时长 - 5秒),则从头开始
|
||||
*/
|
||||
const getInitialPosition = (videoInfo: IVideoInfo): number => {
|
||||
// 从服务器获取播放位置
|
||||
const serverPosition = videoInfo.userCourseVideoPositionEntity?.position || 0
|
||||
|
||||
// 从本地存储获取播放位置
|
||||
const localPosition = videoStorage.getVideoPosition(videoInfo.id) || 0
|
||||
|
||||
// 返回较大的值
|
||||
let position = Math.max(serverPosition, localPosition)
|
||||
|
||||
// 如果播放位置接近视频结尾(最后5秒内),则从头开始
|
||||
const videoDuration = videoInfo.duration || 0
|
||||
if (videoDuration > 0 && position >= videoDuration - 5) {
|
||||
position = 0
|
||||
console.log('Video already finished, reset to start')
|
||||
}
|
||||
|
||||
console.log('Initial position:', {
|
||||
server: serverPosition,
|
||||
local: localPosition,
|
||||
duration: videoDuration,
|
||||
final: position
|
||||
})
|
||||
|
||||
return position
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始保存进度
|
||||
* 每秒保存到本地
|
||||
*/
|
||||
const startSaving = (videoInfo: IVideoInfo) => {
|
||||
// 清除之前的定时器
|
||||
stopSaving()
|
||||
|
||||
// 每秒保存到本地
|
||||
saveTimer = setInterval(() => {
|
||||
if (currentTime.value > 0) {
|
||||
videoStorage.saveVideoPosition(
|
||||
videoInfo.id,
|
||||
Math.floor(currentTime.value),
|
||||
videoInfo
|
||||
)
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止保存进度
|
||||
*/
|
||||
const stopSaving = () => {
|
||||
if (saveTimer) {
|
||||
clearInterval(saveTimer)
|
||||
saveTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存进度到服务器
|
||||
*/
|
||||
const saveToServer = async (videoId: number, position: number) => {
|
||||
if (isSaving.value) return
|
||||
|
||||
try {
|
||||
isSaving.value = true
|
||||
await videoApi.saveCoursePosition({
|
||||
videoId,
|
||||
position
|
||||
})
|
||||
console.log('Progress saved to server:', { videoId, position })
|
||||
} catch (error) {
|
||||
console.error('Failed to save progress to server:', error)
|
||||
} finally {
|
||||
isSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 立即保存当前进度
|
||||
*/
|
||||
const saveNow = async (videoInfo: IVideoInfo) => {
|
||||
if (currentTime.value > 0) {
|
||||
// 保存到本地
|
||||
videoStorage.saveVideoPosition(
|
||||
videoInfo.id,
|
||||
Math.floor(currentTime.value),
|
||||
videoInfo
|
||||
)
|
||||
|
||||
// 保存到服务器
|
||||
await saveToServer(videoInfo.id, Math.floor(currentTime.value))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新当前播放时间
|
||||
*/
|
||||
const updateCurrentTime = (time: number) => {
|
||||
currentTime.value = time
|
||||
}
|
||||
|
||||
return {
|
||||
currentTime,
|
||||
isSaving,
|
||||
getInitialPosition,
|
||||
startSaving,
|
||||
stopSaving,
|
||||
saveToServer,
|
||||
saveNow,
|
||||
updateCurrentTime
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user