|
@@ -11,6 +11,7 @@
|
|
|
ref="videoPlayDom"
|
|
|
@ended="handleChangeCourseware(1)"
|
|
|
@playbackRate="showController"
|
|
|
+ :autoPlay="videoIsAutoPlay"
|
|
|
:disableEvents="true"
|
|
|
:isShowController="isShowController"
|
|
|
/>
|
|
@@ -22,40 +23,47 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="leftTools posTools">
|
|
|
- <div v-if="activeCoursewareIndex > 0" class="posBtn" @click="handleChangeCourseware(-1)">
|
|
|
- <img src="@/img/coursewarePlay/shang.png" />
|
|
|
- <div>上一个</div>
|
|
|
+ <div class="posBtn" @click="handleToolClick('menu')">
|
|
|
+ <img src="@/img/coursewarePlay/menu.png" />
|
|
|
+ <!-- <div>课程类型</div> -->
|
|
|
</div>
|
|
|
- <div v-if="activeCoursewareIndex < flattenCoursewareList.length - 1" class="posBtn" @click="handleChangeCourseware(1)">
|
|
|
- <img src="@/img/coursewarePlay/xia.png" />
|
|
|
- <div>下一个</div>
|
|
|
+ <div class="posBtn" @click="handleToolClick('point')">
|
|
|
+ <img src="@/img/coursewarePlay/zhishidian.png" />
|
|
|
+ <!-- <div>知识点</div> -->
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div class="rightTools posTools">
|
|
|
<div
|
|
|
- class="posBtn"
|
|
|
+ :class="['posBtn', activeCoursewareIndex > 0 ? '' : 'disabled']"
|
|
|
@click="
|
|
|
() => {
|
|
|
- handleVideoPause()
|
|
|
- whitePenShow = true
|
|
|
+ if (activeCoursewareIndex > 0) {
|
|
|
+ handleChangeCourseware(-1)
|
|
|
+ }
|
|
|
}
|
|
|
"
|
|
|
>
|
|
|
- <img src="@/img/coursewarePlay/baiban.png" />
|
|
|
- <div>白板</div>
|
|
|
+ <img src="@/img/coursewarePlay/shang.png" />
|
|
|
+ <!-- <div>上一个</div> -->
|
|
|
</div>
|
|
|
<div
|
|
|
- class="posBtn"
|
|
|
+ :class="['posBtn', activeCoursewareIndex < flattenCoursewareList.length - 1 ? '' : 'disabled']"
|
|
|
@click="
|
|
|
() => {
|
|
|
- handleVideoPause()
|
|
|
- penShow = true
|
|
|
+ if (activeCoursewareIndex < flattenCoursewareList.length - 1) {
|
|
|
+ handleChangeCourseware(1)
|
|
|
+ }
|
|
|
}
|
|
|
"
|
|
|
>
|
|
|
- <img src="@/img/coursewarePlay/pizhu.png" />
|
|
|
- <div>批注</div>
|
|
|
+ <img src="@/img/coursewarePlay/xia.png" />
|
|
|
+ <!-- <div>下一个</div> -->
|
|
|
</div>
|
|
|
+
|
|
|
+ <!-- <div class="posBtn" @click="handleCoursewareEnd">
|
|
|
+ <img src="@/img/coursewarePlay/jieshu.png" />
|
|
|
+ <div>结束</div>
|
|
|
+ </div> -->
|
|
|
+ </div>
|
|
|
+ <!-- <div class="rightTools posTools">
|
|
|
<div class="posBtn" @click="drawerShow = true">
|
|
|
<img src="@/img/coursewarePlay/zhishidian.png" />
|
|
|
<div>知识点</div>
|
|
@@ -64,7 +72,7 @@
|
|
|
<img src="@/img/coursewarePlay/jieshu.png" />
|
|
|
<div>结束</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
<div
|
|
|
v-if="activeCoursewareResourceId"
|
|
|
@click="
|
|
@@ -78,14 +86,29 @@
|
|
|
<div class="topTools">
|
|
|
<div class="leftMenu">
|
|
|
<img @click="handleGoBack" class="backImg" src="@/img/coursewarePlay/back.png" />
|
|
|
+
|
|
|
+ <div class="title-section">
|
|
|
+ <div class="title">{{ activeCourseware?.parentData.name || "" }}</div>
|
|
|
+ <div class="content">
|
|
|
+ {{ activeCourseware?.name || "" }}
|
|
|
+ <span v-if="activeCourseware?.phaseGoals" @click="onTitleTip('phaseGoals', activeCourseware?.phaseGoals)">阶段目标</span>
|
|
|
+ <span v-if="activeCourseware?.checkItem" @click="onTitleTip('checkItem', activeCourseware?.checkItem)">检查事项</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="midMenu">
|
|
|
<playRecordTime
|
|
|
v-if="route.query.modeId && coursewareTotalTime && userStoreHook.roles === 'GYT'"
|
|
|
:modeId="route.query.modeId as string"
|
|
|
+ :isCurrentCoursewareMenu="isCurrentCoursewareMenu"
|
|
|
:coursewareTotalTime="coursewareTotalTime"
|
|
|
/>
|
|
|
</div>
|
|
|
- <div class="midMenu">{{ activeCourseware?.parentData.name || "" }}</div>
|
|
|
- <div class="rightMenu"></div>
|
|
|
+ <div class="rightMenu">
|
|
|
+ <div class="posCloseBtn" @click="handleCoursewareEnd">
|
|
|
+ <img src="@/img/coursewarePlay/jieshu.png" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<el-drawer class="elDrawer" v-model="drawerShow" :show-close="false">
|
|
|
<template #header="{ close }">
|
|
@@ -97,23 +120,16 @@
|
|
|
<courseCollapse :activeCollapse="activeCourseware" :courseList="coursewareList" @handleClick="handleCourseClick" />
|
|
|
</ElScrollbar>
|
|
|
</el-drawer>
|
|
|
- <pen
|
|
|
- :close="
|
|
|
- () => {
|
|
|
- penShow = false
|
|
|
- }
|
|
|
- "
|
|
|
- v-model="penShow"
|
|
|
- />
|
|
|
- <pen
|
|
|
- :is-white="true"
|
|
|
- :close="
|
|
|
- () => {
|
|
|
- whitePenShow = false
|
|
|
- }
|
|
|
- "
|
|
|
- v-model="whitePenShow"
|
|
|
- />
|
|
|
+ <el-drawer class="elDrawer elCourseMenu" v-model="drawerMenuShow" :show-close="false">
|
|
|
+ <template #header="{ close }">
|
|
|
+ <img class="directory" src="@/img/coursewarePlay/menuActive.png" />
|
|
|
+ <div class="tit">课程类型</div>
|
|
|
+ <img class="close" @click="close" src="@/img/coursewarePlay/close.png" />
|
|
|
+ </template>
|
|
|
+ <ElScrollbar class="elScrollbar">
|
|
|
+ <courseMenuCollapse :courseMenuList="coursewareMenuList" @handleClick="handleCourseMenuClick" />
|
|
|
+ </ElScrollbar>
|
|
|
+ </el-drawer>
|
|
|
<practiceForm v-model="isPracticeShow" :practiceUrl="practiceUrl" @close="handlePracticeClose" />
|
|
|
</div>
|
|
|
</template>
|
|
@@ -121,33 +137,34 @@
|
|
|
<script setup lang="ts">
|
|
|
import videoPlay from "./videoPlay"
|
|
|
import { getLessonCourseDetail_gym, getLessonCoursewareDetail_gyt, getLessonCourseDetail_klx } from "@/api/cloudTextbooks.api"
|
|
|
-import { checkWebCourse_gyt } from "@/api/coursewarePlay.api"
|
|
|
+import { checkWebCourse_gyt, refLevel_gym, refLevel_gyt, refLevel_klx } from "@/api/coursewarePlay.api"
|
|
|
import { httpAjaxErrMsg, httpAjaxLoadingErrMsg } from "@/plugin/httpAjax"
|
|
|
import userStore from "@/store/modules/user"
|
|
|
import { useRoute, useRouter } from "vue-router"
|
|
|
import { shallowRef, ref, computed, onUnmounted, onMounted, watch, nextTick } from "vue"
|
|
|
import { ElMessageBox } from "element-plus"
|
|
|
import courseCollapse from "./components/courseCollapse"
|
|
|
-import pen from "./components/pen"
|
|
|
+import courseMenuCollapse from "./components/courseMenuCollapse"
|
|
|
import playRecordTime from "./components/playRecordTime"
|
|
|
import practiceForm from "@/businessComponents/practiceForm"
|
|
|
-import useDialogConfirm from "@/hooks/useDialogConfirm"
|
|
|
import { getRecentCourseSchedule_gym } from "@/api/homePage.api"
|
|
|
import { getToken } from "@/libs/auth"
|
|
|
import { URL_TEACH_GYT, URL_TEACH_GYM, URL_TEACH_KLX } from "@/config"
|
|
|
import { handleFullscreen } from "@/libs/fullscreen"
|
|
|
+import useCoursewarePlayTip from "./components/useCoursewarePlayTip"
|
|
|
+import useDialogConfirm from "@/hooks/useDialogConfirm"
|
|
|
+import LoadingBar from "@/plugin/loadingBar"
|
|
|
+import { isPlay, penShow, toolOpen, whitePenShow } from "@/businessComponents/globalTools/globalTools"
|
|
|
|
|
|
const route = useRoute()
|
|
|
const router = useRouter()
|
|
|
const userStoreHook = userStore()
|
|
|
-// 批注
|
|
|
-const penShow = ref(false)
|
|
|
-// 白板
|
|
|
-const whitePenShow = ref(false)
|
|
|
/* 获取资源 */
|
|
|
const videoPlayDom = ref<InstanceType<typeof videoPlay>>()
|
|
|
+const coursewareMenuList = shallowRef<any[]>([]) // 课程类型
|
|
|
const coursewareList = shallowRef<any[]>([]) // 知识点
|
|
|
-const flattenCoursewareList = shallowRef<any[]>([]) // 扁平化coursewareList
|
|
|
+const flattenCoursewareList = ref<any[]>([]) // 扁平化coursewareList
|
|
|
+const isCurrentCoursewareMenu = shallowRef(true) // 是否为当前选的课程类型
|
|
|
// 选中的知识点
|
|
|
const activeCourseware = computed<undefined | Record<string, any>>(() => {
|
|
|
return flattenCoursewareList.value[activeCoursewareIndex.value]
|
|
@@ -172,13 +189,22 @@ const songPlaySrc = computed<string>(() => {
|
|
|
}
|
|
|
return urlObj[userStoreHook.roles!]
|
|
|
})
|
|
|
+// 视频是否自动播放
|
|
|
+const videoIsAutoPlay = computed<boolean>(() => {
|
|
|
+ // 如果为视频且有阶段目前则不自动播放
|
|
|
+ return fileType.value === "VIDEO" && activeCourseware.value?.phaseGoals ? false : true
|
|
|
+})
|
|
|
const activeCoursewareIndex = ref(0)
|
|
|
const drawerShow = ref(false)
|
|
|
+const drawerMenuShow = ref(false)
|
|
|
// 课程总时间
|
|
|
const coursewareTotalTime = ref(0)
|
|
|
// 监控播放
|
|
|
watch(activeCourseware, () => {
|
|
|
handleVideoPause()
|
|
|
+ if (activeCourseware.value?.phaseGoals) {
|
|
|
+ onTitleTip("phaseGoals", activeCourseware.value?.phaseGoals)
|
|
|
+ }
|
|
|
fileType.value === "VIDEO" &&
|
|
|
nextTick(() => {
|
|
|
handlePlayVideo({
|
|
@@ -189,14 +215,14 @@ watch(activeCourseware, () => {
|
|
|
showController()
|
|
|
})
|
|
|
getCoursewareList()
|
|
|
-function getCoursewareList() {
|
|
|
+async function getCoursewareList(id?: string) {
|
|
|
// GYM,GYT,KLX 区分 查询接口
|
|
|
const LessonCoursewareDetailApi = {
|
|
|
GYT: getLessonCoursewareDetail_gyt,
|
|
|
GYM: getLessonCourseDetail_gym,
|
|
|
KLX: getLessonCourseDetail_klx
|
|
|
}
|
|
|
- httpAjaxErrMsg(LessonCoursewareDetailApi[userStoreHook.roles!], route.params.id as string).then(res => {
|
|
|
+ await httpAjaxErrMsg(LessonCoursewareDetailApi[userStoreHook.roles!], id || (route.params.id as string)).then(res => {
|
|
|
if (res.code === 200) {
|
|
|
const { lockFlag, knowledgePointList } = res.data || {}
|
|
|
if (lockFlag) {
|
|
@@ -230,6 +256,24 @@ function getCoursewareList() {
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
+getCoursewareMenuList()
|
|
|
+function getCoursewareMenuList(id?: string) {
|
|
|
+ // GYM,GYT,KLX 区分 查询接口
|
|
|
+ const LessonCoursewareMenuDetailApi = {
|
|
|
+ GYT: refLevel_gyt,
|
|
|
+ GYM: refLevel_gym,
|
|
|
+ KLX: refLevel_klx
|
|
|
+ }
|
|
|
+
|
|
|
+ httpAjaxErrMsg(LessonCoursewareMenuDetailApi[userStoreHook.roles!], {
|
|
|
+ lessonCoursewareDetailId: id || route.params.id
|
|
|
+ // courseScheduleId: "1844948199117283329"
|
|
|
+ } as any).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ coursewareMenuList.value = res.data || []
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
let flattenCoursewareListData: any = [] // 临时扁平化数据
|
|
|
function handlePointList(pointList: any[]) {
|
|
|
coursewareList.value = filterPointList(pointList)
|
|
@@ -275,7 +319,25 @@ function handleCourseClick(value: any) {
|
|
|
activeCoursewareIndex.value = flattenCoursewareList.value.findIndex((item: any) => {
|
|
|
return value.id === item.id && value.knowledgePointId === item.knowledgePointId
|
|
|
})
|
|
|
+ drawerShow.value = false
|
|
|
}
|
|
|
+async function handleCourseMenuClick(value: any) {
|
|
|
+ LoadingBar.loading(true)
|
|
|
+ flattenCoursewareListData = []
|
|
|
+ activeCoursewareIndex.value = -1
|
|
|
+ if (value.id === route.params.id) {
|
|
|
+ isCurrentCoursewareMenu.value = true
|
|
|
+ } else {
|
|
|
+ isCurrentCoursewareMenu.value = false
|
|
|
+ }
|
|
|
+ await getCoursewareList(value.id)
|
|
|
+ getCoursewareMenuList(value.id)
|
|
|
+ drawerMenuShow.value = false
|
|
|
+ activeCoursewareIndex.value = 0
|
|
|
+
|
|
|
+ LoadingBar.loading(false)
|
|
|
+}
|
|
|
+
|
|
|
/* 播放器相关 */
|
|
|
// 视频播放或者暂停
|
|
|
function handleVideoPlay() {
|
|
@@ -333,6 +395,14 @@ function handleKeydown(e: KeyboardEvent) {
|
|
|
handleChangeCourseware(-1)
|
|
|
}
|
|
|
}
|
|
|
+function handleToolClick(type: string) {
|
|
|
+ fileType.value === "VIDEO" && handleVideoPause()
|
|
|
+ if (type === "menu") {
|
|
|
+ drawerMenuShow.value = true
|
|
|
+ } else if (type === "point") {
|
|
|
+ drawerShow.value = true
|
|
|
+ }
|
|
|
+}
|
|
|
function handleMousemove() {
|
|
|
showController()
|
|
|
}
|
|
@@ -401,7 +471,27 @@ function handleCoursewareEnd() {
|
|
|
handleGoBack()
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+// 是否收起
|
|
|
+watch(
|
|
|
+ () => isShowController.value,
|
|
|
+ () => {
|
|
|
+ if (isShowController.value) {
|
|
|
+ isPlay.value = false
|
|
|
+ } else {
|
|
|
+ isPlay.value = true
|
|
|
+ toolOpen.value = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+)
|
|
|
+// 白板的批注打开时暂停播放
|
|
|
+watch(
|
|
|
+ () => [whitePenShow.value, penShow.value],
|
|
|
+ () => {
|
|
|
+ if (whitePenShow.value || penShow.value) {
|
|
|
+ handleVideoPause()
|
|
|
+ }
|
|
|
+ }
|
|
|
+)
|
|
|
// 去练习
|
|
|
const activeCoursewareResourceId = computed<string | undefined>(() => {
|
|
|
const materialRefs = activeCourseware.value?.materialRefs
|
|
@@ -424,6 +514,15 @@ function handlePracticeClose() {
|
|
|
isPracticeShow.value = false
|
|
|
practiceUrl.value = ""
|
|
|
}
|
|
|
+
|
|
|
+function onTitleTip(type: "phaseGoals" | "checkItem", text: string) {
|
|
|
+ useCoursewarePlayTip({
|
|
|
+ headImg: require(`@/img/coursewarePlay/${type ? "ts3" : "ts4"}.png`),
|
|
|
+ text,
|
|
|
+ btnShow: [false, false]
|
|
|
+ })
|
|
|
+ handleVideoPause()
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
@@ -446,7 +545,7 @@ function handlePracticeClose() {
|
|
|
transform: translateY(-100%);
|
|
|
}
|
|
|
.goPracticeBtn {
|
|
|
- transform: translatex(-135px);
|
|
|
+ transform: translateY(74px);
|
|
|
}
|
|
|
}
|
|
|
&.fileType_song.hideController {
|
|
@@ -492,27 +591,65 @@ function handlePracticeClose() {
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
- background: linear-gradient(180deg, rgba(0, 0, 0, 0.6), transparent);
|
|
|
+ background: linear-gradient(180deg, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0) 100%);
|
|
|
transition: all 0.5s;
|
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
+ align-items: flex-start;
|
|
|
justify-content: space-between;
|
|
|
- padding: 20px 30px;
|
|
|
+ padding: 20px 30px 40px;
|
|
|
.leftMenu {
|
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
+ align-items: flex-start;
|
|
|
.backImg {
|
|
|
cursor: pointer;
|
|
|
width: 22px;
|
|
|
+ padding-top: 5px;
|
|
|
&:hover {
|
|
|
opacity: $opacity-hover;
|
|
|
}
|
|
|
}
|
|
|
+ .title-section {
|
|
|
+ font-weight: 500;
|
|
|
+ font-size: 22px;
|
|
|
+ color: #ffffff;
|
|
|
+ line-height: 30px;
|
|
|
+ padding-left: 20px;
|
|
|
+ .content {
|
|
|
+ padding-top: 6px;
|
|
|
+ font-weight: 500;
|
|
|
+ font-size: 18px;
|
|
|
+ color: #ffffff;
|
|
|
+ line-height: 26px;
|
|
|
+
|
|
|
+ span {
|
|
|
+ background: rgba(0, 0, 0, 0.1);
|
|
|
+ border-radius: 11px;
|
|
|
+ border: 1px solid rgba(255, 255, 255, 0.7);
|
|
|
+ font-size: 14px;
|
|
|
+ color: #ffffff;
|
|
|
+ line-height: 22px;
|
|
|
+ padding: 1px 8px;
|
|
|
+ margin-left: 6px;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
.midMenu {
|
|
|
- font-weight: 500;
|
|
|
- font-size: 20px;
|
|
|
- color: #ffffff;
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ top: 23px;
|
|
|
+ // transform: translate(-50%, -50%);
|
|
|
+ transform: translateX(-50%);
|
|
|
+ }
|
|
|
+ .rightMenu {
|
|
|
+ .posCloseBtn {
|
|
|
+ cursor: pointer;
|
|
|
+ img {
|
|
|
+ width: 34px;
|
|
|
+ height: 34px;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
.posTools {
|
|
@@ -521,15 +658,17 @@ function handlePracticeClose() {
|
|
|
transform: translateY(-50%);
|
|
|
transition: all 0.5s;
|
|
|
&.leftTools {
|
|
|
- left: 12px;
|
|
|
+ background: rgba(0, 0, 0, 0.4);
|
|
|
+ border-radius: 8px;
|
|
|
+ left: 32px;
|
|
|
}
|
|
|
&.rightTools {
|
|
|
right: 12px;
|
|
|
}
|
|
|
.posBtn {
|
|
|
- background: rgba(0, 0, 0, 0.3);
|
|
|
- border-radius: 8px;
|
|
|
- padding: 12px 6px;
|
|
|
+ // background: rgba(0, 0, 0, 0.3);
|
|
|
+ // border-radius: 8px;
|
|
|
+ padding: 20px 12px;
|
|
|
font-weight: 500;
|
|
|
font-size: 16px;
|
|
|
color: #ffffff;
|
|
@@ -537,15 +676,13 @@ function handlePracticeClose() {
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
cursor: pointer;
|
|
|
- margin-bottom: 12px;
|
|
|
&:hover {
|
|
|
opacity: $opacity-hover;
|
|
|
}
|
|
|
- &:last-child {
|
|
|
- margin-bottom: 0;
|
|
|
+ &.disabled {
|
|
|
+ opacity: $opacity-disabled;
|
|
|
}
|
|
|
> img {
|
|
|
- margin-bottom: 5px;
|
|
|
width: 34px;
|
|
|
height: 34px;
|
|
|
}
|
|
@@ -553,10 +690,10 @@ function handlePracticeClose() {
|
|
|
}
|
|
|
.goPracticeBtn {
|
|
|
position: absolute;
|
|
|
- left: 30px;
|
|
|
- bottom: 124px;
|
|
|
- width: 178px;
|
|
|
- height: 64px;
|
|
|
+ right: 32px;
|
|
|
+ bottom: 24px;
|
|
|
+ width: 143px;
|
|
|
+ height: 50px;
|
|
|
background: url("@/img/coursewarePlay/goPracticeBtn.png") no-repeat;
|
|
|
background-size: 100% 100%;
|
|
|
cursor: pointer;
|
|
@@ -566,7 +703,7 @@ function handlePracticeClose() {
|
|
|
}
|
|
|
}
|
|
|
&:deep(.elDrawer.el-drawer) {
|
|
|
- width: 346px !important;
|
|
|
+ width: 348px !important;
|
|
|
.el-drawer__header {
|
|
|
height: 54px;
|
|
|
background: #ededed;
|
|
@@ -608,5 +745,16 @@ function handlePracticeClose() {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ &:deep(.elCourseMenu.el-drawer) {
|
|
|
+ width: 363px !important;
|
|
|
+ .el-drawer__body {
|
|
|
+ & > .elScrollbar {
|
|
|
+ .el-scrollbar__view {
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|