// 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) // 采用服务器记录的播放位置 let position = serverPosition // 如果播放位置接近视频结尾(最后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 } }