|
@@ -1,6 +1,7 @@
|
|
|
<template>
|
|
<template>
|
|
|
<!-- AI发展历程 -->
|
|
<!-- AI发展历程 -->
|
|
|
<div class="home-container">
|
|
<div class="home-container">
|
|
|
|
|
+
|
|
|
<!-- 展开收起侧边栏 -->
|
|
<!-- 展开收起侧边栏 -->
|
|
|
<div
|
|
<div
|
|
|
class="icon-expand"
|
|
class="icon-expand"
|
|
@@ -112,6 +113,7 @@
|
|
|
controls
|
|
controls
|
|
|
@timeupdate="handleTimeUpdate"
|
|
@timeupdate="handleTimeUpdate"
|
|
|
@play="checkVideoPermission"
|
|
@play="checkVideoPermission"
|
|
|
|
|
+ @seeked="handleSeeked"
|
|
|
ref="videoRef"
|
|
ref="videoRef"
|
|
|
>
|
|
>
|
|
|
<source :src="course.courseVideoPath" type="video/mp4" />
|
|
<source :src="course.courseVideoPath" type="video/mp4" />
|
|
@@ -131,7 +133,7 @@
|
|
|
<!-- 下一个视频 -->
|
|
<!-- 下一个视频 -->
|
|
|
<div class="caret-right" @click="playNextVideo">
|
|
<div class="caret-right" @click="playNextVideo">
|
|
|
<el-button type="warning" round
|
|
<el-button type="warning" round
|
|
|
- >下一节
|
|
|
|
|
|
|
+ >下一节
|
|
|
<img :src="rightImg" alt="Right" />
|
|
<img :src="rightImg" alt="Right" />
|
|
|
</el-button>
|
|
</el-button>
|
|
|
</div>
|
|
</div>
|
|
@@ -255,6 +257,12 @@
|
|
|
<script setup>
|
|
<script setup>
|
|
|
import { ref, onMounted, onUnmounted, onBeforeUnmount,computed} from 'vue'
|
|
import { ref, onMounted, onUnmounted, onBeforeUnmount,computed} from 'vue'
|
|
|
import { useRouter } from 'vue-router'
|
|
import { useRouter } from 'vue-router'
|
|
|
|
|
+import videojs from 'video.js';
|
|
|
|
|
+import 'video.js/dist/video-js.css';
|
|
|
|
|
+import '@videojs/http-streaming'; // 支持HLS分片
|
|
|
|
|
+const videoPlayer = ref(null);
|
|
|
|
|
+let player = null;
|
|
|
|
|
+
|
|
|
import {
|
|
import {
|
|
|
Expand,
|
|
Expand,
|
|
|
Fold,
|
|
Fold,
|
|
@@ -288,6 +296,7 @@ const toggleDrawer = () => {
|
|
|
drawerVisible.value = !drawerVisible.value
|
|
drawerVisible.value = !drawerVisible.value
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
// 返回上一页
|
|
// 返回上一页
|
|
|
const goBack = () => {
|
|
const goBack = () => {
|
|
|
router.go(-1)
|
|
router.go(-1)
|
|
@@ -328,6 +337,7 @@ onMounted(async () => {
|
|
|
let menuIndex = courseTemp.courseLabel + '-' + (index+1);
|
|
let menuIndex = courseTemp.courseLabel + '-' + (index+1);
|
|
|
//填充大纲小节
|
|
//填充大纲小节
|
|
|
let menu = menuItems.value.find(menu => courseTemp.courseLabel === menu.index);
|
|
let menu = menuItems.value.find(menu => courseTemp.courseLabel === menu.index);
|
|
|
|
|
+
|
|
|
if (menu){//小节
|
|
if (menu){//小节
|
|
|
menu.children = menu.children || [];
|
|
menu.children = menu.children || [];
|
|
|
menu.children.push({
|
|
menu.children.push({
|
|
@@ -336,16 +346,25 @@ onMounted(async () => {
|
|
|
title: courseTemp.courseName
|
|
title: courseTemp.courseName
|
|
|
})
|
|
})
|
|
|
}else {//大节
|
|
}else {//大节
|
|
|
- menuItems.value.push({
|
|
|
|
|
|
|
+ let temp = {
|
|
|
key: menuIndex,
|
|
key: menuIndex,
|
|
|
index: courseTemp.courseLabel,
|
|
index: courseTemp.courseLabel,
|
|
|
title: menuDict.value[courseTemp.courseLabel]
|
|
title: menuDict.value[courseTemp.courseLabel]
|
|
|
- })
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ if (courseTemp.courseLabel === "3"){
|
|
|
|
|
+ temp.children = [{
|
|
|
|
|
+ key: menuIndex,
|
|
|
|
|
+ index: menuIndex,
|
|
|
|
|
+ title: courseTemp.courseName
|
|
|
|
|
+ }]
|
|
|
|
|
+ }
|
|
|
|
|
+ menuItems.value.push(temp)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
courseTemp["key"] = menuIndex;
|
|
courseTemp["key"] = menuIndex;
|
|
|
videoPathMap.value[menuIndex] = courseTemp
|
|
videoPathMap.value[menuIndex] = courseTemp
|
|
|
|
|
|
|
|
|
|
+
|
|
|
//确定默认课程
|
|
//确定默认课程
|
|
|
if (index === 0) {
|
|
if (index === 0) {
|
|
|
course.value = courseTemp;
|
|
course.value = courseTemp;
|
|
@@ -363,16 +382,10 @@ onMounted(async () => {
|
|
|
}
|
|
}
|
|
|
// 在视频元素上添加时间更新事件监听
|
|
// 在视频元素上添加时间更新事件监听
|
|
|
if (videoRef.value) {
|
|
if (videoRef.value) {
|
|
|
- // videoRef.value.addEventListener('timeupdate', onTimeUpdate)
|
|
|
|
|
|
|
+ videoRef.value.addEventListener('timeupdate', handleTimeUpdate)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
-onUnmounted(() => {
|
|
|
|
|
- if (player) {
|
|
|
|
|
- player.dispose();
|
|
|
|
|
- }
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
// 菜单打开和关闭的处理函数
|
|
// 菜单打开和关闭的处理函数
|
|
|
const handleOpen = () => {}
|
|
const handleOpen = () => {}
|
|
|
const handleClose = () => {}
|
|
const handleClose = () => {}
|
|
@@ -380,7 +393,7 @@ const handleClose = () => {}
|
|
|
// 菜单选择的处理函数
|
|
// 菜单选择的处理函数
|
|
|
const handleSelect = index => {
|
|
const handleSelect = index => {
|
|
|
//测试账号禁用视频
|
|
//测试账号禁用视频
|
|
|
- if (disableVideo(index)) return
|
|
|
|
|
|
|
+ if (disableVideo(index))return;
|
|
|
|
|
|
|
|
const findTitle = items => {
|
|
const findTitle = items => {
|
|
|
for (const item of items) {
|
|
for (const item of items) {
|
|
@@ -401,9 +414,9 @@ const handleSelect = index => {
|
|
|
course.value = videoPathMap.value[index]
|
|
course.value = videoPathMap.value[index]
|
|
|
// 切换标题后,关闭抽屉
|
|
// 切换标题后,关闭抽屉
|
|
|
drawerVisible.value = false
|
|
drawerVisible.value = false
|
|
|
- } else {
|
|
|
|
|
|
|
+ }else {
|
|
|
//视频不存在
|
|
//视频不存在
|
|
|
- Message().notifyWarning('视频不存在!', true)
|
|
|
|
|
|
|
+ Message().notifyWarning('视频不存在!', true);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//测试账号禁用视频
|
|
//测试账号禁用视频
|
|
@@ -429,7 +442,7 @@ const flattenMenuItems = () => {
|
|
|
// 播放下一个视频
|
|
// 播放下一个视频
|
|
|
const playNextVideo = () => {
|
|
const playNextVideo = () => {
|
|
|
//测试账号禁用视频
|
|
//测试账号禁用视频
|
|
|
- if (disableVideo()) return
|
|
|
|
|
|
|
+ if (disableVideo())return;
|
|
|
|
|
|
|
|
const allIndices = flattenMenuItems()
|
|
const allIndices = flattenMenuItems()
|
|
|
const currentIndexInList = allIndices.indexOf(course.value.key)
|
|
const currentIndexInList = allIndices.indexOf(course.value.key)
|
|
@@ -445,16 +458,16 @@ const playNextVideo = () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 重置
|
|
// 重置
|
|
|
- pausedIndices = ref({ time: [], newTime: [] })
|
|
|
|
|
- userMessage = ref('')
|
|
|
|
|
- messageHistory = ref([])
|
|
|
|
|
|
|
+ pausedIndices.value = [];
|
|
|
|
|
+ userMessage.value = ''
|
|
|
|
|
+ messageHistory.value = []
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 切换视频
|
|
// 切换视频
|
|
|
// 播放上一个视频
|
|
// 播放上一个视频
|
|
|
const playPreviousVideo = () => {
|
|
const playPreviousVideo = () => {
|
|
|
//测试账号禁用视频
|
|
//测试账号禁用视频
|
|
|
- if (disableVideo()) return
|
|
|
|
|
|
|
+ if (disableVideo())return;
|
|
|
|
|
|
|
|
const allIndices = flattenMenuItems()
|
|
const allIndices = flattenMenuItems()
|
|
|
const currentIndexInList = allIndices.indexOf(course.value.key)
|
|
const currentIndexInList = allIndices.indexOf(course.value.key)
|
|
@@ -473,7 +486,7 @@ const playPreviousVideo = () => {
|
|
|
// 尝试播放视频,处理浏览器自动播放限制
|
|
// 尝试播放视频,处理浏览器自动播放限制
|
|
|
const tryPlayVideo = () => {
|
|
const tryPlayVideo = () => {
|
|
|
//测试账号禁用视频
|
|
//测试账号禁用视频
|
|
|
- if (disableVideo()) return
|
|
|
|
|
|
|
+ if (disableVideo())return;
|
|
|
|
|
|
|
|
const playPromise = videoRef.value.play()
|
|
const playPromise = videoRef.value.play()
|
|
|
if (playPromise !== undefined) {
|
|
if (playPromise !== undefined) {
|
|
@@ -500,9 +513,7 @@ const checkVideoPermission = () => {
|
|
|
videoRef.value.pause()
|
|
videoRef.value.pause()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- //记录已暂停的内容
|
|
|
|
|
- setVideoStop()
|
|
|
|
|
-}
|
|
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
//禁用视频
|
|
//禁用视频
|
|
|
const disableVideo = (index = course.value.key) => {
|
|
const disableVideo = (index = course.value.key) => {
|
|
@@ -526,7 +537,7 @@ const disableVideo = (index = course.value.key) => {
|
|
|
// 视频 ref
|
|
// 视频 ref
|
|
|
const videoRef = ref(null)
|
|
const videoRef = ref(null)
|
|
|
// 记录已经暂停过的时间点索引
|
|
// 记录已经暂停过的时间点索引
|
|
|
-let pausedIndices = ref({ time: [], newTime: [] })
|
|
|
|
|
|
|
+let pausedIndices = ref([])
|
|
|
// 试题弹框显示状态
|
|
// 试题弹框显示状态
|
|
|
const questionDialogVisible = ref(false)
|
|
const questionDialogVisible = ref(false)
|
|
|
// 当前显示的试题
|
|
// 当前显示的试题
|
|
@@ -554,11 +565,11 @@ const handleTimeUpdate = () => {
|
|
|
//暂停时间
|
|
//暂停时间
|
|
|
let time = courseCofig.ccTime
|
|
let time = courseCofig.ccTime
|
|
|
// 检查是否到达时间点且还未暂停过
|
|
// 检查是否到达时间点且还未暂停过
|
|
|
- let timeIndex = pausedIndices.value.time.indexOf(time);
|
|
|
|
|
-
|
|
|
|
|
- if (currentTime === time && (timeIndex === -1 || Date.now() - pausedIndices.value.newTime[timeIndex] > 1000) ) {
|
|
|
|
|
|
|
+ if (currentTime === time && !pausedIndices.value.includes(time) ) {
|
|
|
|
|
|
|
|
videoRef.value.pause()
|
|
videoRef.value.pause()
|
|
|
|
|
+ //记录暂停时间
|
|
|
|
|
+ pausedIndices.value.push(currentTime)
|
|
|
|
|
|
|
|
// 显示对应的问题
|
|
// 显示对应的问题
|
|
|
if (courseCofig.ccQuestContent) {
|
|
if (courseCofig.ccQuestContent) {
|
|
@@ -574,27 +585,16 @@ const handleTimeUpdate = () => {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// 视频完成拖动进度条时触发的方法
|
|
|
|
|
+const handleSeeked = () => {
|
|
|
|
|
+ pausedIndices.value = [];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 关闭试题弹框
|
|
// 关闭试题弹框
|
|
|
const handleCloseQuestionDialog = () => {
|
|
const handleCloseQuestionDialog = () => {
|
|
|
questionDialogVisible.value = false
|
|
questionDialogVisible.value = false
|
|
|
// 继续播放视频
|
|
// 继续播放视频
|
|
|
videoRef.value.play()
|
|
videoRef.value.play()
|
|
|
-
|
|
|
|
|
- //记录已暂停的内容
|
|
|
|
|
- setVideoStop()
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//记录已暂停的内容
|
|
|
|
|
-const setVideoStop = () => {
|
|
|
|
|
- const currentTime = parseInt(videoRef.value.currentTime)
|
|
|
|
|
- let timeIndex = pausedIndices.value.indexOf(currentTime);
|
|
|
|
|
- if (timeIndex === -1) {
|
|
|
|
|
- pausedIndices.value.time.push(currentTime)
|
|
|
|
|
- pausedIndices.value.newTime.push(Date.now())
|
|
|
|
|
- }else{
|
|
|
|
|
- pausedIndices.value.time[timeIndex] = currentTime
|
|
|
|
|
- pausedIndices.value.newTime[timeIndex] = Date.now()
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 提交答案
|
|
// 提交答案
|
|
@@ -604,9 +604,6 @@ const handleSubmitAnswer = () => {
|
|
|
// 继续播放视频
|
|
// 继续播放视频
|
|
|
videoRef.value.play()
|
|
videoRef.value.play()
|
|
|
selectedOption.value = null
|
|
selectedOption.value = null
|
|
|
-
|
|
|
|
|
- //记录已暂停的内容
|
|
|
|
|
- setVideoStop()
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 发送消息
|
|
// 发送消息
|
|
@@ -818,6 +815,9 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
|
|
|
.el-menu ::v-deep(.el-sub-menu__title:hover .el-sub-menu__icon-arrow) {
|
|
.el-menu ::v-deep(.el-sub-menu__title:hover .el-sub-menu__icon-arrow) {
|
|
|
color: black; // 与悬停状态的文字颜色保持一致
|
|
color: black; // 与悬停状态的文字颜色保持一致
|
|
|
}
|
|
}
|
|
|
|
|
+.el-menu ::v-deep(.el-icon svg) {
|
|
|
|
|
+ font-size: rpx(9);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
.mb-2 {
|
|
.mb-2 {
|
|
|
color: white;
|
|
color: white;
|
|
@@ -1074,9 +1074,9 @@ video::-webkit-media-controls-panel {
|
|
|
border: none;
|
|
border: none;
|
|
|
border-radius: rpx(20);
|
|
border-radius: rpx(20);
|
|
|
background: linear-gradient(
|
|
background: linear-gradient(
|
|
|
- 135deg,
|
|
|
|
|
- $light-color,
|
|
|
|
|
- #d8bfd8
|
|
|
|
|
|
|
+ 135deg,
|
|
|
|
|
+ $light-color,
|
|
|
|
|
+ #d8bfd8
|
|
|
); // 柔和的蓝紫色渐变
|
|
); // 柔和的蓝紫色渐变
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
display: flex; // 添加 flex 布局
|
|
display: flex; // 添加 flex 布局
|