Vue 视频 / 文档预览学习页面开发实战

张开发
2026/4/9 9:55:18 15 分钟阅读

分享文章

Vue 视频 / 文档预览学习页面开发实战
在线教育系统中视频 / 文档预览学习页面是核心模块之一需要实现视频播放、进度记录、文档预览、学时统计等关键功能。本文基于实际项目代码拆解 Vue 视频学习页面的核心开发知识点和实现思路。一、页面核心功能概述该页面主要实现以下核心功能多类型资源预览支持视频 (MP4)、图片、PDF、PPT (转 PDF) 预览学习进度记录实时保存视频播放进度、文档查看状态学时统计根据学习内容自动计算已完成学时防挂机检测无操作时弹出确认框防止刷课资源下载支持学习资源的下载功能课程信息展示展示课程名称、讲师、学时等信息二、核心技术点拆解1. 页面布局与组件结构采用 Flex 布局实现左右分栏结构左侧为播放 / 预览区 课程列表右侧为课程信息展示区。template div classvideo-preview div classcontainer !-- 头部 -- div classsection-header h3学习内容/h3 /div !-- 核心内容区 -- div classcontent !-- 左侧播放/预览区 -- div classvideo-section !-- 视频播放 -- div classvideo-player v-ifSrcLx0 video refvideoPlayer1 controls timeupdateupdateTime endedhandleVideoEnded source :srcvideoSrc typevideo/mp4 /video /div !-- 图片/PDF/PPT预览 -- div classfile-viewer v-else-if[1,2,3].includes(SrcLx) iframe v-if[2,3].includes(SrcLx) :srcfileSrc width100% height550px/iframe img v-else-ifSrcLx1 :srcfileSrc alt图片预览 stylewidth: 100%; height: 550px; object-fit: contain; /div !-- 课程列表 -- div classvideo-info div classinfo-table !-- 课程列表渲染 -- div classtable-row v-for(course, index) in courseList :keyindex div classtable-cell{{ course.name }}/div div classtable-cell{{ getVideoProgress(course.id) 100 ? 已观看完成 : 未观看 }}/div div classtable-cell el-button clickljgk(course, index)立即观看/el-button el-button clickdownloadFile(course)下载/el-button /div /div /div /div /div !-- 右侧课程信息 -- div classcourse-outline div classcourse-info-section h3 classcourse-name课程名称{{ kcname }}/h3 div classteacher-info img src/assets/logo.png alt讲师头像 classteacher-avatar div classteacher-details div classlabel主讲老师/div div classname{{ jsname }}/div /div /div /div /div /div !-- 防挂机弹窗 -- el-dialog title提示 :visible.syncpauseDialogVisible span您是否在观看此视频/span span slotfooter el-button clickcontinuePlaying确 定/el-button /span /el-dialog /div /div /template2. 视频播放与进度管理2.1 进度实时更新监听视频timeupdate事件定时保存播放进度避免频繁请求接口updateTime() { const video this.$refs.videoPlayer1; if (video) { const currentTime video.currentTime; const totalTime video.duration; this.playedTime currentTime; this.totalTime totalTime; // 30秒更新一次进度 const now new Date().getTime(); if (!this.lastUpdateTime || (now - this.lastUpdateTime) 30000) { this.lastUpdateTime now; this.saveProgress(this.currentCourseId, Math.floor(currentTime), Math.floor(totalTime)); } } }2.2 进度保存逻辑saveProgress(courseId, playedTime, totalTime) { // 防重复提交30秒内仅一次 const now new Date().getTime(); if (now - this.lastSaveTime 30000) return; this.lastSaveTime now; // 计算进度 let gkjd Math.floor((playedTime / totalTime) * 100); this.$set(this.progressMap, courseId, gkjd); // 学时统计 if (playedTime totalTime !this.completedCourses.has(courseId)) { const course this.courseList.find(c c.id courseId); if (course?.sptype 0) { this.completedHours Math.ceil(totalTime / 60); this.completedCourses.add(courseId); } } // 提交后端保存 updateAllxx({ studyid: this.Studyid, videoid: courseId, progress: gkjd, gktime: playedTime, xxsc: Math.min(this.completedHours, this.kcxs), status: gkjd 100 ? 1 : 0 }).then(response { console.log(进度保存成功); }); }3. 多类型资源处理3.1 PPT 转 PDF 预览// 转换PPT路径为PDF路径 convertPptToPdfPath(path) { if (!path) return ; return path.replace(/\.(ppt|pptx)$/i, .pdf); }3.2 资源下载功能downloadFile(course) { if (!course || !course.path) { this.$message.warning(文件路径不存在无法下载); return; } const downloadUrl window.location.origin course.path; const link document.createElement(a); link.href downloadUrl; link.download course.name || 文件下载; document.body.appendChild(link); link.click(); document.body.removeChild(link); this.$message.success(开始下载文件); }4. 防挂机检测实现通过监听鼠标移动事件超时无操作则暂停视频并弹出确认框handleMouseMovement() { this.resetInactivityTimer(); }, resetInactivityTimer() { clearTimeout(this.inactivityTimer); this.inactivityTimer setTimeout(() { const video this.$refs.videoPlayer1; if (!video.paused) { video.pause(); this.pauseDialogVisible true; } }, 1000 * 60 * 5); // 5分钟无操作触发 }, continuePlaying() { this.pauseDialogVisible false; this.$refs.videoPlayer1.play(); this.resetInactivityTimer(); }5. 组件生命周期管理mounted() { // 绑定视频事件 const video this.$refs.videoPlayer1; if (video) { video.addEventListener(timeupdate, this.updateTime); video.addEventListener(ended, this.handleVideoEnded); } // 监听鼠标移动 window.addEventListener(mousemove, this.handleMouseMovement); }, beforeDestroy() { // 组件销毁前保存最后进度 if (this.currentCourseId) { const video this.$refs.videoPlayer1; if (video) { this.saveProgress(this.currentCourseId, Math.floor(video.currentTime), Math.floor(video.duration)); } } // 移除事件监听 const video this.$refs.videoPlayer1; if (video) { video.removeEventListener(timeupdate, this.updateTime); video.removeEventListener(ended, this.handleVideoEnded); } clearInterval(this.updateInterval); window.removeEventListener(mousemove, this.handleMouseMovement); }三、开发注意事项响应式处理使用 Vue 的$nextTick确保 DOM 渲染完成后操作视频元素防抖处理进度保存添加 30 秒防抖避免频繁请求后端资源清理组件销毁时及时移除事件监听、清除定时器防止内存泄漏边界处理视频播放完成、切换课程、组件卸载等场景都要保证进度正确保存兼容性PPT 预览转换为 PDF保证不同浏览器的兼容性四、总结该页面整合了 Vue 的核心特性响应式数据、事件监听、生命周期和前端开发的通用技巧防抖、DOM 操作、资源处理实现了一个完整的在线学习解决方案。核心思路是分离不同类型资源的展示逻辑保证代码可维护性实时记录学习进度兼顾用户体验和后端性能完善的异常处理和资源清理保证页面稳定性防挂机机制保证学习数据的真实性通过这个案例可以看出实际项目开发中不仅要实现功能还要考虑性能、用户体验、兼容性等多方面因素合理运用 Vue 的生命周期和事件处理机制是实现高质量前端页面的关键。

更多文章