|
@@ -1,996 +1,1105 @@
|
|
|
-<!--
|
|
|
-* @FileDescription: 教程播放
|
|
|
-* @Author: 黄琪勇
|
|
|
-* @Date:2024-04-03 17:31:41
|
|
|
--->
|
|
|
-<template>
|
|
|
- <div class="coursewarePlay" :class="[!isShowController && 'hideController', fileType === 'SONG' && 'fileType_song']">
|
|
|
- <div class="coursewarePlayCon" @mousemove="handleMousemove" @click="handleClick" @touchstart="handleClick">
|
|
|
- <videoPlay
|
|
|
- v-show="fileType === 'VIDEO'"
|
|
|
- ref="videoPlayDom"
|
|
|
- @ended="handleChangeCourseware(1)"
|
|
|
- @loadedmetadata="
|
|
|
- () => {
|
|
|
- isTempAutoPlay = false
|
|
|
- }
|
|
|
- "
|
|
|
- :autoPlay="true"
|
|
|
- @playbackRate="showController"
|
|
|
- :disableEvents="true"
|
|
|
- :isShowController="isShowController"
|
|
|
- />
|
|
|
- <div class="imgPlayBox" v-if="fileType === 'IMG'">
|
|
|
- <ElImage :hide-on-click-modal="true" fit="contain" :src="activeCourseware?.content" class="imgPlay" />
|
|
|
- </div>
|
|
|
- <div class="songPlayBox" v-if="fileType === 'SONG'">
|
|
|
- <iframe
|
|
|
- ref="songPlayDom"
|
|
|
- :key="activeCourseware?.content"
|
|
|
- class="songIframe"
|
|
|
- @mousemove="handleMousemove"
|
|
|
- :src="songPlaySrc"
|
|
|
- frameborder="0"
|
|
|
- ></iframe>
|
|
|
- <!-- <span></span> -->
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="leftTools posTools">
|
|
|
- <div class="posBtn" @click="handleToolClick('menu')" v-if="searchObj.source !== 'search'">
|
|
|
- <img src="@/img/coursewarePlay/menu.png" />
|
|
|
- <!-- <div>课程类型</div> -->
|
|
|
- </div>
|
|
|
- <div class="posBtn" @click="handleToolClick('point')">
|
|
|
- <img src="@/img/coursewarePlay/zhishidian.png" v-if="searchObj.source !== 'search'" />
|
|
|
- <img src="@/img/coursewarePlay/sousuo.png" v-else />
|
|
|
- <!-- <div>知识点</div> -->
|
|
|
- </div>
|
|
|
- <div
|
|
|
- :class="['posBtn', activeCoursewareIndex > 0 ? '' : 'disabled']"
|
|
|
- @click="
|
|
|
- () => {
|
|
|
- if (activeCoursewareIndex > 0) {
|
|
|
- handleChangeCourseware(-1)
|
|
|
- }
|
|
|
- }
|
|
|
- "
|
|
|
- >
|
|
|
- <img src="@/img/coursewarePlay/shang.png" />
|
|
|
- <!-- <div>上一个</div> -->
|
|
|
- </div>
|
|
|
- <div
|
|
|
- :class="['posBtn', activeCoursewareIndex < flattenCoursewareList.length - 1 ? '' : 'disabled']"
|
|
|
- @click="
|
|
|
- () => {
|
|
|
- if (activeCoursewareIndex < flattenCoursewareList.length - 1) {
|
|
|
- handleChangeCourseware(1)
|
|
|
- }
|
|
|
- }
|
|
|
- "
|
|
|
- >
|
|
|
- <img src="@/img/coursewarePlay/xia.png" />
|
|
|
- <!-- <div>下一个</div> -->
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div
|
|
|
- v-if="activeCoursewareResourceId"
|
|
|
- @click="
|
|
|
- () => {
|
|
|
- handleVideoPause()
|
|
|
- handleGoPracticeBtn(activeCoursewareResourceId!)
|
|
|
- }
|
|
|
- "
|
|
|
- class="goPracticeBtn"
|
|
|
- ></div>
|
|
|
- <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">
|
|
|
- <p>{{ activeCourseware?.name || "" }}</p>
|
|
|
- <!-- <span v-if="activeCourseware?.phaseGoals" @click="onTitleTip('phaseGoals', activeCourseware?.phaseGoals)">阶段目标</span> -->
|
|
|
- <span v-if="lessonTargetDetail" @click="onTitleTip('phaseGoals', lessonTargetDetail)">阶段目标</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="rightMenu">
|
|
|
- <div class="posCloseBtn" @click="handleCoursewareEnd">
|
|
|
- <img src="@/img/coursewarePlay/jieshu.png" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <el-drawer class="elDrawer" :class="{ elDrawerHeader: searchObj.source === 'search' }" direction="ltr" v-model="drawerShow" :show-close="false">
|
|
|
- <template #header="{ close }">
|
|
|
- <template v-if="searchObj.source === 'search'">
|
|
|
- <myInput
|
|
|
- class="queryIpt"
|
|
|
- v-model="searchObj.queryStr"
|
|
|
- :height="36"
|
|
|
- placeholder="请输入素材关键词"
|
|
|
- clearable
|
|
|
- @handleQuery="handleQuery"
|
|
|
- @keyup.enter="handleQuery"
|
|
|
- />
|
|
|
- </template>
|
|
|
- <template v-else>
|
|
|
- <img class="directory" src="@/img/coursewarePlay/kcml.png" />
|
|
|
- <div class="tit">知识点目录</div>
|
|
|
- </template>
|
|
|
- <img class="close" @click="close" src="@/img/coursewarePlay/close.png" />
|
|
|
- </template>
|
|
|
- <ElScrollbar class="elScrollbar" v-loading="searchObj.loading">
|
|
|
- <!-- <tempCoursewareList -->
|
|
|
- <el-empty
|
|
|
- class="empty"
|
|
|
- v-if="!tempCoursewareList.length && !searchObj.loading"
|
|
|
- :image="require('@/img/layout/empty.png')"
|
|
|
- description="暂无搜索结果"
|
|
|
- />
|
|
|
- <courseCollapse
|
|
|
- :activeCollapse="tempActiveCourseware || activeCourseware"
|
|
|
- :search="searchObj.tempSearch || searchObj.search"
|
|
|
- :courseList="tempCoursewareList"
|
|
|
- @handleClick="handleCourseClick"
|
|
|
- />
|
|
|
- </ElScrollbar>
|
|
|
- </el-drawer>
|
|
|
- <el-drawer class="elDrawer elCourseMenu" direction="ltr" 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>
|
|
|
-
|
|
|
-<script setup lang="ts">
|
|
|
-import videoPlay from "./videoPlay"
|
|
|
-import {
|
|
|
- getLessonCourseDetail_gym,
|
|
|
- getLessonCoursewareDetail_gyt,
|
|
|
- getLessonCourseDetail_klx,
|
|
|
- getLessonCoursewareCourseList_gym,
|
|
|
- getMyCoursewareDetail_gyt,
|
|
|
- getLessonCoursewareCourseList_klx
|
|
|
-} from "@/api/cloudTextbooks.api"
|
|
|
-import myInput from "@/components/myInput"
|
|
|
-import { checkWebCourse_gyt, refLevel_gym, refLevel_gyt, refLevel_klx } from "@/api/coursewarePlay.api"
|
|
|
-import { httpAjax, 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, reactive } from "vue"
|
|
|
-import { ElMessageBox } from "element-plus"
|
|
|
-import courseCollapse from "./components/courseCollapse"
|
|
|
-import courseMenuCollapse from "./components/courseMenuCollapse"
|
|
|
-import playRecordTime from "./components/playRecordTime"
|
|
|
-import practiceForm from "@/businessComponents/practiceForm"
|
|
|
-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"
|
|
|
-import { closeAllModalFrame } from "@/plugin/modalFrame"
|
|
|
-import { deepCopy } from "@/libs/tools"
|
|
|
-
|
|
|
-const route = useRoute()
|
|
|
-const router = useRouter()
|
|
|
-const userStoreHook = userStore()
|
|
|
-/* 获取资源 */
|
|
|
-const videoPlayDom = ref<InstanceType<typeof videoPlay>>()
|
|
|
-const songPlayDom = ref<any>() // 曲谱对象
|
|
|
-const lessonTargetDetail = ref<string>("") // 阶段目标
|
|
|
-const coursewareMenuList = shallowRef<any[]>([]) // 课程类型
|
|
|
-const coursewareList = shallowRef<any[]>([]) // 知识点
|
|
|
-const tempCoursewareList = shallowRef<any[]>([]) // 临时知识点
|
|
|
-const flattenCoursewareList = ref<any[]>([]) // 扁平化coursewareList
|
|
|
-const tempFlattenCoursewareList = ref<any[]>([]) // 临时 扁平化coursewareList
|
|
|
-const isCurrentCoursewareMenu = shallowRef(true) // 是否为当前选的课程类型
|
|
|
-const currentId = ref<any>(route.params.id)
|
|
|
-const isTempAutoPlay = ref(false)
|
|
|
-let coursewareDetailController: AbortController
|
|
|
-const searchObj = reactive({
|
|
|
- loading: false,
|
|
|
- isSearch: false, // 是否搜索 标识
|
|
|
- queryStr: route.query.search as any,
|
|
|
- source: route.query.source as any, // 从哪里来的
|
|
|
- search: route.query.search as any, // 默认的搜索条件 -
|
|
|
- tempSearch: route.query.search as any
|
|
|
-})
|
|
|
-
|
|
|
-// 选中的知识点
|
|
|
-const tempActiveCourseware: any = ref() // 临时数据
|
|
|
-const activeCourseware = computed<undefined | Record<string, any>>(() => {
|
|
|
- return flattenCoursewareList.value[activeCoursewareIndex.value]
|
|
|
-})
|
|
|
-// 文件类型
|
|
|
-const fileType = computed<"VIDEO" | "IMG" | "SONG">(() => {
|
|
|
- return activeCourseware.value?.typeCode || activeCourseware.value?.type
|
|
|
-})
|
|
|
-const songPlaySrc = computed<string>(() => {
|
|
|
- if (fileType.value !== "SONG") {
|
|
|
- return ""
|
|
|
- }
|
|
|
- // GYM,GYT,KLX 区分 云教练
|
|
|
- const urlObj = {
|
|
|
- GYT: `${URL_TEACH_GYT}?id=${activeCourseware.value?.content}&modelType=practice&modeType=json&Authorization=${getToken()}&isYjt=1`,
|
|
|
- GYM: `${URL_TEACH_GYM}#/?id=${
|
|
|
- activeCourseware.value?.content
|
|
|
- }&Authorization=${getToken()}&platform=pc&isHideBack=true&isHideMusicList=true&isYjt=1&systemType=teacher`,
|
|
|
- KLX: `${URL_TEACH_KLX}#/?id=${
|
|
|
- activeCourseware.value?.content
|
|
|
- }&Authorization=${getToken()}&platform=pc&isHideBack=true&isHideMusicList=true&isYjt=1&systemType=teacher`
|
|
|
- }
|
|
|
-
|
|
|
- // const iframeRef = document.querySelector("#songPlayDom") as any
|
|
|
- // iframeRef?.contentWindow.location.replace(urlObj[userStoreHook.roles!])
|
|
|
- // console.log(iframeRef, "iframeRef")
|
|
|
-
|
|
|
- return urlObj[userStoreHook.roles!]
|
|
|
-})
|
|
|
-// 视频是否自动播放
|
|
|
-// const videoIsAutoPlay = computed<boolean>(() => {
|
|
|
-// // 如果为视频且有阶段目前则不自动播放
|
|
|
-// console.log(fileType.value, isTempAutoPlay.value, "isTempAutoPlay")
|
|
|
-// return (fileType.value === "VIDEO" && activeCourseware.value?.phaseGoals) || isTempAutoPlay.value ? false : true
|
|
|
-// })
|
|
|
-
|
|
|
-const activeCoursewareIndex = ref(0)
|
|
|
-const drawerShow = ref(false)
|
|
|
-const drawerMenuShow = ref(false)
|
|
|
-// 课程总时间
|
|
|
-const coursewareTotalTime = ref(0)
|
|
|
-// 监控播放
|
|
|
-watch(activeCourseware, () => {
|
|
|
- fileType.value === "VIDEO" &&
|
|
|
- nextTick(() => {
|
|
|
- handlePlayVideo({
|
|
|
- src: activeCourseware.value?.content,
|
|
|
- name: activeCourseware.value?.name
|
|
|
- })
|
|
|
- })
|
|
|
- showController()
|
|
|
-})
|
|
|
-async function getCoursewareList(id?: string) {
|
|
|
- // GYM,GYT,KLX 区分 查询接口
|
|
|
- const LessonCoursewareDetailApi = {
|
|
|
- GYT: getLessonCoursewareDetail_gyt,
|
|
|
- GYM: getLessonCourseDetail_gym,
|
|
|
- KLX: getLessonCourseDetail_klx
|
|
|
- }
|
|
|
- await httpAjaxErrMsg(LessonCoursewareDetailApi[userStoreHook.roles!], id || (route.params.id as string)).then(res => {
|
|
|
- if (res.code === 200) {
|
|
|
- const { lockFlag, knowledgePointList, lessonTargetDesc } = res.data || {}
|
|
|
- if (lockFlag) {
|
|
|
- ElMessageBox.alert("课件已锁定", "温馨提示", {
|
|
|
- confirmButtonText: "退出",
|
|
|
- type: "error"
|
|
|
- })
|
|
|
- .then(() => {
|
|
|
- handleGoBack()
|
|
|
- })
|
|
|
- .catch(() => {
|
|
|
- handleGoBack()
|
|
|
- })
|
|
|
- return
|
|
|
- }
|
|
|
- if ((knowledgePointList || []).length < 1) {
|
|
|
- ElMessageBox.alert("没有找到课件", "温馨提示", {
|
|
|
- confirmButtonText: "退出",
|
|
|
- type: "error"
|
|
|
- })
|
|
|
- .then(() => {
|
|
|
- handleGoBack()
|
|
|
- })
|
|
|
- .catch(() => {
|
|
|
- handleGoBack()
|
|
|
- })
|
|
|
- return
|
|
|
- }
|
|
|
- lessonTargetDetail.value = lessonTargetDesc ? lessonTargetDesc.replace(/\n/g, "<br />") : ""
|
|
|
- // 处理返回的数据
|
|
|
- handlePointList(knowledgePointList)
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-async function getLessCoursewareList(id?: string) {
|
|
|
- // GYM,GYT,KLX 区分 查询接口
|
|
|
- const LessonCoursewareDetailApi = {
|
|
|
- GYT: getMyCoursewareDetail_gyt,
|
|
|
- GYM: getLessonCoursewareCourseList_gym,
|
|
|
- KLX: getLessonCoursewareCourseList_klx
|
|
|
- }
|
|
|
- if (coursewareDetailController) {
|
|
|
- coursewareDetailController.abort()
|
|
|
- }
|
|
|
- coursewareDetailController = new AbortController()
|
|
|
- searchObj.loading = true
|
|
|
- await httpAjax(LessonCoursewareDetailApi[userStoreHook.roles!], {
|
|
|
- id: id || (route.params.id as string),
|
|
|
- data: {
|
|
|
- search: searchObj.queryStr,
|
|
|
- detailFlag: "1"
|
|
|
- },
|
|
|
- abortController: coursewareDetailController
|
|
|
- }).then(res => {
|
|
|
- searchObj.loading = false
|
|
|
- if (res.code === 200) {
|
|
|
- const result = res.data || []
|
|
|
- for (let i = 0; i < result.length; i++) {
|
|
|
- const itemResult = result[i]
|
|
|
- itemResult.name = itemResult.coursewareDetailName
|
|
|
- itemResult.id = itemResult.coursewareDetailId || itemResult.lessonCoursewareDetailId
|
|
|
- itemResult.lessonTargetDesc = itemResult.lessonTargetDesc ? itemResult.lessonTargetDesc.replace(/\n/g, "<br />") : ""
|
|
|
- itemResult.children = itemResult.knowledgePointList || []
|
|
|
- itemResult.knowledgePointList = []
|
|
|
- }
|
|
|
- handlePointList(result, searchObj.isSearch)
|
|
|
-
|
|
|
- // 初始化检查事项
|
|
|
- const item = flattenCoursewareList.value[activeCoursewareIndex.value]
|
|
|
- const parentId = item ? item.parentData.ids[0] : ""
|
|
|
- if (parentId) {
|
|
|
- const parentItem = coursewareList.value.find((item: any) => item.id === parentId)
|
|
|
- if (parentItem) {
|
|
|
- lessonTargetDetail.value = parentItem.lessonTargetDesc
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 标识
|
|
|
- searchObj.isSearch = false
|
|
|
- })
|
|
|
-}
|
|
|
-
|
|
|
-// 处理是从搜索过来的,还是
|
|
|
-if (route.query.source === "search") {
|
|
|
- getLessCoursewareList()
|
|
|
-} else {
|
|
|
- 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: route.query.modeId as any
|
|
|
- } as any).then(res => {
|
|
|
- if (res.code === 200) {
|
|
|
- coursewareMenuList.value = res.data || []
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-let flattenCoursewareListData: any = [] // 临时扁平化数据
|
|
|
-function handlePointList(pointList: any[], isSearch?: boolean) {
|
|
|
- flattenCoursewareListData = []
|
|
|
- const list = filterPointList(pointList)
|
|
|
- if (!isSearch) {
|
|
|
- // 重置数据
|
|
|
- coursewareTotalTime.value = 0
|
|
|
- coursewareList.value = list
|
|
|
- // 如果url里面有materialId 代表指定资料播放
|
|
|
- if (route.query.materialId) {
|
|
|
- const index = flattenCoursewareListData.findIndex((item: any) => {
|
|
|
- return route.query.materialId === item.id + "" && route.query.knowledgePointId === item.knowledgePointId + ""
|
|
|
- })
|
|
|
- index > -1 && (activeCoursewareIndex.value = index)
|
|
|
- }
|
|
|
- flattenCoursewareList.value = deepCopy(flattenCoursewareListData)
|
|
|
- } else {
|
|
|
- if (flattenCoursewareListData[0]) {
|
|
|
- // 默认展开第一个
|
|
|
- tempActiveCourseware.value = {
|
|
|
- ...flattenCoursewareListData[0],
|
|
|
- id: null
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- tempCoursewareList.value = list
|
|
|
- tempFlattenCoursewareList.value = deepCopy(flattenCoursewareListData)
|
|
|
-}
|
|
|
-function filterPointList(pointList: any[], parentData?: { ids: string[]; name: string }): any[] {
|
|
|
- // 设置父级及以上id数组和父级name
|
|
|
- return pointList.map(point => {
|
|
|
- if (point.children) {
|
|
|
- return Object.assign(point, {
|
|
|
- children: filterPointList(point.children, { ids: [...(parentData?.ids || []), point.id], name: point.name })
|
|
|
- })
|
|
|
- } else {
|
|
|
- // coursewareTotalTime.value += point.totalMaterialTimeSecond
|
|
|
- return Object.assign(point, {
|
|
|
- materialList: point.materialList.map((item: any) => {
|
|
|
- item.parentData = {
|
|
|
- ids: [...(parentData?.ids || []), point.id],
|
|
|
- name: point.name
|
|
|
- }
|
|
|
- flattenCoursewareListData.push(item)
|
|
|
- return item
|
|
|
- })
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
-}
|
|
|
-function handleChangeCourseware(index: -1 | 1) {
|
|
|
- handleVideoPause()
|
|
|
- handleSongPause()
|
|
|
- const newIndex = index + activeCoursewareIndex.value
|
|
|
- if (newIndex < 0 || newIndex > flattenCoursewareList.value.length - 1) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- if (searchObj.source === "search") {
|
|
|
- const newItem = flattenCoursewareList.value[newIndex]
|
|
|
- const newParentId = newItem ? newItem.parentData?.ids[0] : ""
|
|
|
- if (newParentId) {
|
|
|
- const parentItem = coursewareList.value.find((item: any) => item.id === newParentId)
|
|
|
- if (parentItem) {
|
|
|
- lessonTargetDetail.value = parentItem.lessonTargetDesc
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- activeCoursewareIndex.value = newIndex
|
|
|
-}
|
|
|
-function handleCourseClick(value: any) {
|
|
|
- // 选择之后初始化数据
|
|
|
- searchObj.search = searchObj.tempSearch ? JSON.parse(JSON.stringify(searchObj.tempSearch)) : ""
|
|
|
- coursewareList.value = deepCopy(tempCoursewareList.value)
|
|
|
- flattenCoursewareList.value = deepCopy(tempFlattenCoursewareList.value)
|
|
|
-
|
|
|
- const newIndex = flattenCoursewareList.value.findIndex((item: any) => {
|
|
|
- return value.id === item.id && value.knowledgePointId === item.knowledgePointId
|
|
|
- })
|
|
|
-
|
|
|
- if (searchObj.source === "search") {
|
|
|
- const newItem = flattenCoursewareList.value[newIndex]
|
|
|
- const newParentId = newItem ? newItem.parentData?.ids[0] : ""
|
|
|
-
|
|
|
- if (newParentId) {
|
|
|
- const parentItem = coursewareList.value.find((item: any) => item.id === newParentId)
|
|
|
- if (parentItem) {
|
|
|
- lessonTargetDetail.value = parentItem.lessonTargetDesc
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- activeCoursewareIndex.value = newIndex
|
|
|
- drawerShow.value = false
|
|
|
-}
|
|
|
-async function handleCourseMenuClick(value: any) {
|
|
|
- // 判断是否为当前课程类型
|
|
|
- if (currentId.value === value.id) {
|
|
|
- return
|
|
|
- }
|
|
|
- LoadingBar.loading(true)
|
|
|
- currentId.value = value.id
|
|
|
- isCurrentCoursewareMenu.value = value.id === route.params.id ? true : false
|
|
|
- flattenCoursewareListData = [] // 重置数据
|
|
|
- isTempAutoPlay.value = true
|
|
|
- await getCoursewareList(value.id)
|
|
|
- getCoursewareMenuList(value.id)
|
|
|
- drawerMenuShow.value = false
|
|
|
- activeCoursewareIndex.value = 0
|
|
|
- nextTick(() => {
|
|
|
- // if (!activeCourseware.value?.phaseGoals) {
|
|
|
- // 切换之后默认打开课程目录
|
|
|
- drawerShow.value = true
|
|
|
- // }
|
|
|
- })
|
|
|
- LoadingBar.loading(false)
|
|
|
-}
|
|
|
-
|
|
|
-/** 曲目相关 */
|
|
|
-// 暂停曲目播放
|
|
|
-function handleSongPause() {
|
|
|
- songPlayDom.value?.contentWindow?.postMessage({ api: "setPlayState" }, "*")
|
|
|
- showController()
|
|
|
-}
|
|
|
-
|
|
|
-/* 播放器相关 */
|
|
|
-// 视频播放或者暂停
|
|
|
-function handleVideoPlay() {
|
|
|
- videoPlayDom.value?.handlePlay()
|
|
|
- showController()
|
|
|
-}
|
|
|
-// 视频快进快退
|
|
|
-function handleVideoSpeedCurrentTime(type: "fast" | "slow") {
|
|
|
- videoPlayDom.value?.speedCurrentTime(type)
|
|
|
- showController()
|
|
|
-}
|
|
|
-// 视频暂停
|
|
|
-function handleVideoPause() {
|
|
|
- videoPlayDom.value?.pauseVideo()
|
|
|
- showController()
|
|
|
-}
|
|
|
-// 播放视频
|
|
|
-function handlePlayVideo({ src, name }: { src: string; name: string }) {
|
|
|
- videoPlayDom.value?.playVideo({
|
|
|
- src,
|
|
|
- name
|
|
|
- })
|
|
|
- showController()
|
|
|
-}
|
|
|
-
|
|
|
-// 全屏显示
|
|
|
-handleFullscreen(true, false)
|
|
|
-/* 按键事件相关 */
|
|
|
-onMounted(() => {
|
|
|
- document.addEventListener("keydown", handleKeydown)
|
|
|
- document.addEventListener("contextmenu", preventDefaultContextmenu)
|
|
|
- showController()
|
|
|
-})
|
|
|
-onUnmounted(() => {
|
|
|
- document.removeEventListener("keydown", handleKeydown)
|
|
|
- document.removeEventListener("contextmenu", preventDefaultContextmenu)
|
|
|
-})
|
|
|
-function preventDefaultContextmenu(event: MouseEvent) {
|
|
|
- event.preventDefault()
|
|
|
-}
|
|
|
-function handleKeydown(e: KeyboardEvent) {
|
|
|
- const key = e.key
|
|
|
- // 打开弹窗之后快捷键失效
|
|
|
- if (drawerShow.value || drawerMenuShow.value) {
|
|
|
- return
|
|
|
- }
|
|
|
- if (key === " ") {
|
|
|
- closeAllModalFrame()
|
|
|
- drawerShow.value = false
|
|
|
- // 视频类型的时候才触发
|
|
|
- fileType.value === "VIDEO" && handleVideoPlay()
|
|
|
- } else if (key === "ArrowLeft") {
|
|
|
- closeAllModalFrame()
|
|
|
- drawerShow.value = false
|
|
|
- // 视频类型的时候才触发
|
|
|
- fileType.value === "VIDEO" && handleVideoSpeedCurrentTime("slow")
|
|
|
- } else if (key === "ArrowRight") {
|
|
|
- closeAllModalFrame()
|
|
|
- drawerShow.value = false
|
|
|
- // 视频类型的时候才触发
|
|
|
- fileType.value === "VIDEO" && handleVideoSpeedCurrentTime("fast")
|
|
|
- } else if (key === "ArrowDown") {
|
|
|
- closeAllModalFrame()
|
|
|
- drawerShow.value = false
|
|
|
- handleChangeCourseware(1)
|
|
|
- } else if (key === "ArrowUp") {
|
|
|
- closeAllModalFrame()
|
|
|
- drawerShow.value = false
|
|
|
- handleChangeCourseware(-1)
|
|
|
- }
|
|
|
-}
|
|
|
-function handleToolClick(type: string) {
|
|
|
- fileType.value === "VIDEO" && handleVideoPause()
|
|
|
- if (type === "menu") {
|
|
|
- drawerMenuShow.value = true
|
|
|
- } else if (type === "point") {
|
|
|
- tempCoursewareList.value = deepCopy(coursewareList.value)
|
|
|
- searchObj.queryStr = searchObj.search ? JSON.parse(JSON.stringify(searchObj.search)) : ""
|
|
|
-
|
|
|
- tempActiveCourseware.value = null
|
|
|
- drawerShow.value = true
|
|
|
- }
|
|
|
-}
|
|
|
-function handleMousemove() {
|
|
|
- showController()
|
|
|
-}
|
|
|
-function handleClick() {
|
|
|
- fileType.value === "VIDEO" && isShowController.value && handleVideoPlay()
|
|
|
- showController()
|
|
|
-}
|
|
|
-// 是否显示控制器
|
|
|
-const isShowController = ref(true)
|
|
|
-let _showTimer: any
|
|
|
-function showController() {
|
|
|
- isShowController.value = true
|
|
|
- _showTimer && clearTimeout(_showTimer)
|
|
|
- _showTimer = setTimeout(hideController, 3000)
|
|
|
-}
|
|
|
-function hideController() {
|
|
|
- // 取消暂停的时候收起
|
|
|
- // if (fileType.value === "VIDEO" && videoPlayDom.value?.playType === "pause") {
|
|
|
- // return
|
|
|
- // }
|
|
|
- isShowController.value = false
|
|
|
-}
|
|
|
-/* 结束课程 */
|
|
|
-function handleGoBack() {
|
|
|
- // window.open("about:blank", "_self")
|
|
|
- // window.close()
|
|
|
- router.go(-1)
|
|
|
-}
|
|
|
-function handleCoursewareEnd() {
|
|
|
- if (route.query.modeId) {
|
|
|
- if (userStoreHook.roles === "GYM") {
|
|
|
- httpAjaxLoadingErrMsg(getRecentCourseSchedule_gym, route.query.modeId as string).then(res => {
|
|
|
- if (res.code === 200) {
|
|
|
- if (res.data?.signOutStatusEnum === 3) {
|
|
|
- useDialogConfirm({
|
|
|
- headImg: require("@/img/coursewarePlay/ts.png"),
|
|
|
- text: `请确认是否结束课程,结束后请到APP进行签退。`,
|
|
|
- btnShow: [true, true],
|
|
|
- onOk() {
|
|
|
- handleGoBack()
|
|
|
- }
|
|
|
- })
|
|
|
- } else {
|
|
|
- handleGoBack()
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- } else if (userStoreHook.roles === "GYT") {
|
|
|
- httpAjaxLoadingErrMsg(checkWebCourse_gyt, route.query.modeId as string).then(res => {
|
|
|
- if (res.code === 200) {
|
|
|
- if (res.data?.signOut === false) {
|
|
|
- useDialogConfirm({
|
|
|
- headImg: require("@/img/coursewarePlay/ts.png"),
|
|
|
- text: `请确认是否结束课程,结束后请到APP进行签退。`,
|
|
|
- btnShow: [true, true],
|
|
|
- onOk() {
|
|
|
- handleGoBack()
|
|
|
- }
|
|
|
- })
|
|
|
- } else {
|
|
|
- handleGoBack()
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- } else {
|
|
|
- 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()
|
|
|
- handleSongPause()
|
|
|
- }
|
|
|
- }
|
|
|
-)
|
|
|
-// 去练习
|
|
|
-const activeCoursewareResourceId = computed<string | undefined>(() => {
|
|
|
- const materialRefs = activeCourseware.value?.materialRefs
|
|
|
- return materialRefs ? (["GYM", "KLX"].includes(userStoreHook.roles!) ? materialRefs[0]?.resourceIdStr : materialRefs[0]?.resourceId) : undefined
|
|
|
-})
|
|
|
-const isPracticeShow = ref(false)
|
|
|
-const practiceUrl = ref("")
|
|
|
-function handleGoPracticeBtn(activeCoursewareResourceId: string) {
|
|
|
- // GYM,GYT,KLX 区分 云教练
|
|
|
- const urlObj = {
|
|
|
- GYT: `${URL_TEACH_GYT}?id=${activeCoursewareResourceId}&modelType=practice&modeType=json&Authorization=${getToken()}&isYjt=1&&isHideBack=false`,
|
|
|
- GYM: `${URL_TEACH_GYM}#/?id=${activeCoursewareResourceId}&Authorization=${getToken()}&platform=pc&isYjt=1&systemType=teacher&isHideMusicList=true`,
|
|
|
- KLX: `${URL_TEACH_KLX}#/?id=${activeCoursewareResourceId}&Authorization=${getToken()}&platform=pc&isYjt=1&systemType=teacher&isHideMusicList=true`
|
|
|
- }
|
|
|
- isPracticeShow.value = true
|
|
|
- practiceUrl.value = urlObj[userStoreHook.roles!]
|
|
|
- //window.open(urlObj[userStoreHook.roles!], "_blank")
|
|
|
-}
|
|
|
-function handlePracticeClose() {
|
|
|
- isPracticeShow.value = false
|
|
|
- practiceUrl.value = ""
|
|
|
-}
|
|
|
-
|
|
|
-function onTitleTip(type: "phaseGoals" | "checkItem", text: string) {
|
|
|
- useCoursewarePlayTip({
|
|
|
- headImg: require(`@/img/coursewarePlay/${type === "phaseGoals" ? "ts3" : "ts4"}.png`),
|
|
|
- text,
|
|
|
- btnShow: [false, false]
|
|
|
- })
|
|
|
- handleVideoPause()
|
|
|
-}
|
|
|
-
|
|
|
-function handleQuery() {
|
|
|
- //
|
|
|
- searchObj.isSearch = true
|
|
|
- searchObj.tempSearch = searchObj.queryStr ? JSON.parse(JSON.stringify(searchObj.queryStr)) : ""
|
|
|
- getLessCoursewareList()
|
|
|
-}
|
|
|
-</script>
|
|
|
-
|
|
|
-<style lang="scss" scoped>
|
|
|
-.coursewarePlay {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- position: relative;
|
|
|
- overflow: hidden;
|
|
|
- &.hideController {
|
|
|
- .leftTools {
|
|
|
- opacity: 0;
|
|
|
- transform: translate(-100%, -50%);
|
|
|
- }
|
|
|
- .topTools {
|
|
|
- opacity: 0;
|
|
|
- transform: translateY(-100%);
|
|
|
- }
|
|
|
- .goPracticeBtn {
|
|
|
- transform: translateY(74px);
|
|
|
- }
|
|
|
- }
|
|
|
- &.fileType_song.hideController {
|
|
|
- .leftTools {
|
|
|
- opacity: initial;
|
|
|
- transform: translateY(-50%);
|
|
|
- }
|
|
|
- .goPracticeBtn {
|
|
|
- transform: initial;
|
|
|
- }
|
|
|
- }
|
|
|
- .coursewarePlayCon {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- overflow: hidden;
|
|
|
- .imgPlayBox {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
- align-items: center;
|
|
|
- .imgPlay {
|
|
|
- width: 84%;
|
|
|
- height: 100%;
|
|
|
- }
|
|
|
- }
|
|
|
- .songPlayBox {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- .songIframe {
|
|
|
- display: block;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- .topTools {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- width: 100%;
|
|
|
- background: linear-gradient(180deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);
|
|
|
- transition: all 0.5s;
|
|
|
- display: flex;
|
|
|
- align-items: flex-start;
|
|
|
- justify-content: space-between;
|
|
|
- padding: 20px 30px 40px;
|
|
|
- .leftMenu {
|
|
|
- display: flex;
|
|
|
- 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;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- p {
|
|
|
- line-height: 1;
|
|
|
- padding-top: 1px;
|
|
|
- }
|
|
|
-
|
|
|
- span {
|
|
|
- background: rgba(0, 0, 0, 0.1);
|
|
|
- border-radius: 16px;
|
|
|
- border: 1px solid rgba(255, 255, 255, 0.7);
|
|
|
- font-size: 14px;
|
|
|
- color: #ffffff;
|
|
|
- line-height: 22px;
|
|
|
- padding: 2px 10px;
|
|
|
- margin-left: 10px;
|
|
|
- cursor: pointer;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- .midMenu {
|
|
|
- position: absolute;
|
|
|
- left: 50%;
|
|
|
- top: 23px;
|
|
|
- // transform: translate(-50%, -50%);
|
|
|
- transform: translateX(-50%);
|
|
|
- }
|
|
|
- .rightMenu {
|
|
|
- .posCloseBtn {
|
|
|
- cursor: pointer;
|
|
|
- img {
|
|
|
- width: 34px;
|
|
|
- height: 34px;
|
|
|
- padding: 6px;
|
|
|
- box-sizing: content-box;
|
|
|
- &:hover {
|
|
|
- background-color: rgba(255, 255, 255, 0.2);
|
|
|
- border-radius: 6px;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- .posTools {
|
|
|
- position: absolute;
|
|
|
- top: 50%;
|
|
|
- transform: translateY(-50%);
|
|
|
- transition: all 0.5s;
|
|
|
- &.leftTools {
|
|
|
- background: rgba(0, 0, 0, 0.4);
|
|
|
- border-radius: 8px;
|
|
|
- left: 32px;
|
|
|
- }
|
|
|
- .posBtn {
|
|
|
- padding: 14px 6px;
|
|
|
- font-weight: 500;
|
|
|
- font-size: 16px;
|
|
|
- color: #ffffff;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- cursor: pointer;
|
|
|
- // &:hover {
|
|
|
- // opacity: $opacity-hover;
|
|
|
- // }
|
|
|
- &.disabled {
|
|
|
- opacity: $opacity-disabled;
|
|
|
- }
|
|
|
- > img {
|
|
|
- width: 34px;
|
|
|
- height: 34px;
|
|
|
- padding: 6px;
|
|
|
- box-sizing: content-box;
|
|
|
- &:hover {
|
|
|
- background-color: rgba(255, 255, 255, 0.2);
|
|
|
- border-radius: 6px;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- .goPracticeBtn {
|
|
|
- position: absolute;
|
|
|
- right: 32px;
|
|
|
- bottom: 24px;
|
|
|
- width: 143px;
|
|
|
- height: 50px;
|
|
|
- background: url("@/img/coursewarePlay/goPracticeBtn.png") no-repeat;
|
|
|
- background-size: 100% 100%;
|
|
|
- cursor: pointer;
|
|
|
- transition: all 0.5s;
|
|
|
- &:hover {
|
|
|
- opacity: $opacity-hover;
|
|
|
- }
|
|
|
- }
|
|
|
- &:deep(.elDrawer.el-drawer) {
|
|
|
- width: 348px !important;
|
|
|
- .el-drawer__header {
|
|
|
- height: 54px;
|
|
|
- background: #ededed;
|
|
|
- padding: 0 20px;
|
|
|
- margin-bottom: 0;
|
|
|
- .directory {
|
|
|
- flex-grow: 0;
|
|
|
- flex-shrink: 0;
|
|
|
- width: 24px;
|
|
|
- height: 24px;
|
|
|
- }
|
|
|
- .tit {
|
|
|
- flex-grow: 1;
|
|
|
- margin-left: 10px;
|
|
|
- font-weight: 600;
|
|
|
- font-size: 18px;
|
|
|
- color: #333333;
|
|
|
- }
|
|
|
- .close {
|
|
|
- cursor: pointer;
|
|
|
- width: 14px;
|
|
|
- flex-shrink: 0;
|
|
|
- &:hover {
|
|
|
- opacity: $opacity-hover;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .el-input {
|
|
|
- margin-right: 10px;
|
|
|
- font-size: 14px;
|
|
|
- }
|
|
|
-
|
|
|
- .btnSelect {
|
|
|
- width: 56px;
|
|
|
- height: 26px;
|
|
|
- line-height: 26px;
|
|
|
- font-size: 14px;
|
|
|
- }
|
|
|
- }
|
|
|
- .el-drawer__body {
|
|
|
- padding: 0;
|
|
|
- overflow: hidden;
|
|
|
- & > .elScrollbar {
|
|
|
- .el-scrollbar__view {
|
|
|
- padding: 0 22px;
|
|
|
- width: 100%;
|
|
|
- }
|
|
|
- .el-scrollbar__wrap {
|
|
|
- overflow-x: hidden;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- &:deep(.elDrawerHeader.el-drawer) {
|
|
|
- .el-drawer__header {
|
|
|
- padding: 0 10px;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &:deep(.elCourseMenu.el-drawer) {
|
|
|
- width: 363px !important;
|
|
|
- .el-drawer__body {
|
|
|
- & > .elScrollbar {
|
|
|
- .el-scrollbar__view {
|
|
|
- padding: 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-.empty {
|
|
|
- height: calc(100vh - 54px);
|
|
|
- :deep(.el-empty__image) {
|
|
|
- width: 228px;
|
|
|
- }
|
|
|
-
|
|
|
- :deep(.el-empty__description) {
|
|
|
- color: #aaa;
|
|
|
- p {
|
|
|
- font-size: 18px;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|
|
|
+<!--
|
|
|
+* @FileDescription: 教程播放
|
|
|
+* @Author: 黄琪勇
|
|
|
+* @Date:2024-04-03 17:31:41
|
|
|
+-->
|
|
|
+<template>
|
|
|
+ <div class="coursewarePlay" :class="[!isShowController && 'hideController', fileType === 'SONG' && 'fileType_song']">
|
|
|
+ <div class="coursewarePlayCon" @mousemove="handleMousemove" @click="handleClick" @touchstart="handleClick">
|
|
|
+ <videoPlay
|
|
|
+ v-show="fileType === 'VIDEO'"
|
|
|
+ ref="videoPlayDom"
|
|
|
+ @ended="handleChangeCourseware(1)"
|
|
|
+ @loadedmetadata="
|
|
|
+ () => {
|
|
|
+ isTempAutoPlay = false
|
|
|
+ }
|
|
|
+ "
|
|
|
+ :autoPlay="true"
|
|
|
+ @playbackRate="showController"
|
|
|
+ :disableEvents="true"
|
|
|
+ :isShowController="isShowController"
|
|
|
+ />
|
|
|
+ <div class="imgPlayBox" v-if="fileType === 'IMG'">
|
|
|
+ <ElImage :hide-on-click-modal="true" fit="contain" :src="activeCourseware?.content" class="imgPlay" />
|
|
|
+ </div>
|
|
|
+ <div class="songPlayBox" v-if="fileType === 'SONG'">
|
|
|
+ <iframe
|
|
|
+ ref="songPlayDom"
|
|
|
+ :key="activeCourseware?.content"
|
|
|
+ class="songIframe"
|
|
|
+ @mousemove="handleMousemove"
|
|
|
+ :src="songPlaySrc"
|
|
|
+ frameborder="0"
|
|
|
+ ></iframe>
|
|
|
+ <!-- <span></span> -->
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="leftTools posTools">
|
|
|
+ <div class="posBtn" @click="handleToolClick('menu')" v-if="searchObj.source !== 'search'">
|
|
|
+ <img src="@/img/coursewarePlay/menu.png" />
|
|
|
+ <!-- <div>课程类型</div> -->
|
|
|
+ </div>
|
|
|
+ <!-- 有没有搜索都展示 -->
|
|
|
+ <div class="posBtn" @click="handleToolClick('search')">
|
|
|
+ <img src="@/img/coursewarePlay/sousuo.png" />
|
|
|
+ <!-- <div>知识点</div> -->
|
|
|
+ </div>
|
|
|
+ <div class="posBtn" @click="handleToolClick('point')" v-if="searchObj.source !== 'search'">
|
|
|
+ <img src="@/img/coursewarePlay/zhishidian.png" />
|
|
|
+ <!-- <div>知识点</div> -->
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ :class="['posBtn', activeCoursewareIndex > 0 ? '' : 'disabled']"
|
|
|
+ @click="
|
|
|
+ () => {
|
|
|
+ if (activeCoursewareIndex > 0) {
|
|
|
+ handleChangeCourseware(-1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <img src="@/img/coursewarePlay/shang.png" />
|
|
|
+ <!-- <div>上一个</div> -->
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ :class="['posBtn', activeCoursewareIndex < flattenCoursewareList.length - 1 ? '' : 'disabled']"
|
|
|
+ @click="
|
|
|
+ () => {
|
|
|
+ if (activeCoursewareIndex < flattenCoursewareList.length - 1) {
|
|
|
+ handleChangeCourseware(1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <img src="@/img/coursewarePlay/xia.png" />
|
|
|
+ <!-- <div>下一个</div> -->
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ v-if="activeCoursewareResourceId"
|
|
|
+ @click="
|
|
|
+ () => {
|
|
|
+ handleVideoPause()
|
|
|
+ handleGoPracticeBtn(activeCoursewareResourceId!)
|
|
|
+ }
|
|
|
+ "
|
|
|
+ class="goPracticeBtn"
|
|
|
+ ></div>
|
|
|
+ <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">
|
|
|
+ <p>{{ activeCourseware?.name || "" }}</p>
|
|
|
+ <!-- <span v-if="activeCourseware?.phaseGoals" @click="onTitleTip('phaseGoals', activeCourseware?.phaseGoals)">阶段目标</span> -->
|
|
|
+ <span v-if="lessonTargetDetail" @click="onTitleTip('phaseGoals', lessonTargetDetail)">阶段目标</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="rightMenu">
|
|
|
+ <div class="posCloseBtn" @click="handleCoursewareEnd">
|
|
|
+ <img src="@/img/coursewarePlay/jieshu.png" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-drawer class="elDrawer elDrawerHeader" direction="ltr" v-model="drawerSearchShow" :show-close="false">
|
|
|
+ <template #header="{ close }">
|
|
|
+ <myInput
|
|
|
+ class="queryIpt"
|
|
|
+ v-model="searchObj.queryStr"
|
|
|
+ :height="36"
|
|
|
+ placeholder="请输入素材关键词"
|
|
|
+ clearable
|
|
|
+ @handleQuery="handleQuery"
|
|
|
+ @keyup.enter="handleQuery"
|
|
|
+ />
|
|
|
+ <img class="close" @click="close" src="@/img/coursewarePlay/close.png" />
|
|
|
+ </template>
|
|
|
+ <ElScrollbar class="elScrollbar" v-loading="searchObj.loading">
|
|
|
+ <el-empty
|
|
|
+ class="empty"
|
|
|
+ v-if="!tempCoursewareList.length && !searchObj.loading"
|
|
|
+ :image="require('@/img/layout/empty.png')"
|
|
|
+ description="暂无搜索结果"
|
|
|
+ />
|
|
|
+ <courseCollapse
|
|
|
+ :activeCollapse="tempActiveCourseware || activeCourseware"
|
|
|
+ :search="searchObj.tempSearch || searchObj.search"
|
|
|
+ :courseList="tempCoursewareList"
|
|
|
+ @handleClick="handleCourseSearchClick"
|
|
|
+ />
|
|
|
+ </ElScrollbar>
|
|
|
+ </el-drawer>
|
|
|
+ <el-drawer class="elDrawer" direction="ltr" v-model="drawerShow" :show-close="false">
|
|
|
+ <template #header="{ close }">
|
|
|
+ <img class="directory" src="@/img/coursewarePlay/kcml.png" />
|
|
|
+ <div class="tit">知识点目录</div>
|
|
|
+
|
|
|
+ <img class="close" @click="close" src="@/img/coursewarePlay/close.png" />
|
|
|
+ </template>
|
|
|
+ <ElScrollbar class="elScrollbar" v-loading="searchObj.loading">
|
|
|
+ <el-empty
|
|
|
+ class="empty"
|
|
|
+ v-if="!tempCoursewareList.length && !searchObj.loading"
|
|
|
+ :image="require('@/img/layout/empty.png')"
|
|
|
+ description="暂无搜索结果"
|
|
|
+ />
|
|
|
+ <courseCollapse
|
|
|
+ :activeCollapse="tempActiveCourseware || activeCourseware"
|
|
|
+ :search="searchObj.tempSearch || searchObj.search"
|
|
|
+ :courseList="tempCoursewareList"
|
|
|
+ @handleClick="handleCourseClick"
|
|
|
+ />
|
|
|
+ </ElScrollbar>
|
|
|
+ </el-drawer>
|
|
|
+ <el-drawer class="elDrawer elCourseMenu" direction="ltr" 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>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import videoPlay from "./videoPlay"
|
|
|
+import {
|
|
|
+ getLessonCourseDetail_gym,
|
|
|
+ getLessonCoursewareDetail_gyt,
|
|
|
+ getLessonCourseDetail_klx,
|
|
|
+ getLessonCoursewareCourseList_gym,
|
|
|
+ getMyCoursewareDetail_gyt,
|
|
|
+ getLessonCoursewareCourseList_klx
|
|
|
+} from "@/api/cloudTextbooks.api"
|
|
|
+import myInput from "@/components/myInput"
|
|
|
+import { checkWebCourse_gyt, refLevel_gym, refLevel_gyt, refLevel_klx } from "@/api/coursewarePlay.api"
|
|
|
+import { httpAjax, 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, reactive } from "vue"
|
|
|
+import { ElMessageBox } from "element-plus"
|
|
|
+import courseCollapse from "./components/courseCollapse"
|
|
|
+import courseMenuCollapse from "./components/courseMenuCollapse"
|
|
|
+import playRecordTime from "./components/playRecordTime"
|
|
|
+import practiceForm from "@/businessComponents/practiceForm"
|
|
|
+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"
|
|
|
+import { closeAllModalFrame } from "@/plugin/modalFrame"
|
|
|
+import { deepCopy } from "@/libs/tools"
|
|
|
+
|
|
|
+const route = useRoute()
|
|
|
+const router = useRouter()
|
|
|
+const userStoreHook = userStore()
|
|
|
+/* 获取资源 */
|
|
|
+const videoPlayDom = ref<InstanceType<typeof videoPlay>>()
|
|
|
+const songPlayDom = ref<any>() // 曲谱对象
|
|
|
+const lessonTargetDetail = ref<string>("") // 阶段目标
|
|
|
+const coursewareMenuList = shallowRef<any[]>([]) // 课程类型
|
|
|
+const coursewareList = shallowRef<any[]>([]) // 知识点
|
|
|
+const coursewareSearchList = shallowRef<any[]>([]) // 搜索的知识点
|
|
|
+const tempCoursewareList = shallowRef<any[]>([]) // 临时知识点
|
|
|
+const flattenCoursewareList = ref<any[]>([]) // 扁平化coursewareList
|
|
|
+const tempFlattenCoursewareList = ref<any[]>([]) // 临时 扁平化coursewareList
|
|
|
+const isCurrentCoursewareMenu = shallowRef(true) // 是否为当前选的课程类型
|
|
|
+const currentId = ref<any>(route.params.id)
|
|
|
+const isTempAutoPlay = ref(false)
|
|
|
+let coursewareDetailController: AbortController
|
|
|
+const searchObj = reactive({
|
|
|
+ loading: false,
|
|
|
+ isSearch: false, // 是否搜索 标识
|
|
|
+ lessonCoursewareId: null as any, // 课程id,
|
|
|
+ queryStr: route.query.search as any,
|
|
|
+ source: route.query.source as any, // 从哪里来的
|
|
|
+ search: route.query.search as any, // 默认的搜索条件 -
|
|
|
+ tempSearch: route.query.search as any
|
|
|
+})
|
|
|
+
|
|
|
+// 选中的知识点
|
|
|
+const tempActiveCourseware: any = ref() // 临时数据
|
|
|
+const activeCourseware = computed<undefined | Record<string, any>>(() => {
|
|
|
+ return flattenCoursewareList.value[activeCoursewareIndex.value]
|
|
|
+})
|
|
|
+// 文件类型
|
|
|
+const fileType = computed<"VIDEO" | "IMG" | "SONG">(() => {
|
|
|
+ return activeCourseware.value?.typeCode || activeCourseware.value?.type
|
|
|
+})
|
|
|
+const songPlaySrc = computed<string>(() => {
|
|
|
+ if (fileType.value !== "SONG") {
|
|
|
+ return ""
|
|
|
+ }
|
|
|
+ // GYM,GYT,KLX 区分 云教练
|
|
|
+ const urlObj = {
|
|
|
+ GYT: `${URL_TEACH_GYT}?id=${activeCourseware.value?.content}&modelType=practice&modeType=json&Authorization=${getToken()}&isYjt=1`,
|
|
|
+ GYM: `${URL_TEACH_GYM}#/?id=${
|
|
|
+ activeCourseware.value?.content
|
|
|
+ }&Authorization=${getToken()}&platform=pc&isHideBack=true&isHideMusicList=true&isYjt=1&systemType=teacher`,
|
|
|
+ KLX: `${URL_TEACH_KLX}#/?id=${
|
|
|
+ activeCourseware.value?.content
|
|
|
+ }&Authorization=${getToken()}&platform=pc&isHideBack=true&isHideMusicList=true&isYjt=1&systemType=teacher`
|
|
|
+ }
|
|
|
+
|
|
|
+ // const iframeRef = document.querySelector("#songPlayDom") as any
|
|
|
+ // iframeRef?.contentWindow.location.replace(urlObj[userStoreHook.roles!])
|
|
|
+ // console.log(iframeRef, "iframeRef")
|
|
|
+
|
|
|
+ return urlObj[userStoreHook.roles!]
|
|
|
+})
|
|
|
+// 视频是否自动播放
|
|
|
+// const videoIsAutoPlay = computed<boolean>(() => {
|
|
|
+// // 如果为视频且有阶段目前则不自动播放
|
|
|
+// console.log(fileType.value, isTempAutoPlay.value, "isTempAutoPlay")
|
|
|
+// return (fileType.value === "VIDEO" && activeCourseware.value?.phaseGoals) || isTempAutoPlay.value ? false : true
|
|
|
+// })
|
|
|
+
|
|
|
+const activeCoursewareIndex = ref(0)
|
|
|
+const drawerSearchShow = ref(false) // 弹窗带搜索条件的
|
|
|
+const drawerShow = ref(false)
|
|
|
+const drawerMenuShow = ref(false)
|
|
|
+// 课程总时间
|
|
|
+const coursewareTotalTime = ref(0)
|
|
|
+// 监控播放
|
|
|
+watch(activeCourseware, () => {
|
|
|
+ fileType.value === "VIDEO" &&
|
|
|
+ nextTick(() => {
|
|
|
+ handlePlayVideo({
|
|
|
+ src: activeCourseware.value?.content,
|
|
|
+ name: activeCourseware.value?.name
|
|
|
+ })
|
|
|
+ })
|
|
|
+ showController()
|
|
|
+})
|
|
|
+async function getCoursewareList(id?: string) {
|
|
|
+ // GYM,GYT,KLX 区分 查询接口
|
|
|
+ const LessonCoursewareDetailApi = {
|
|
|
+ GYT: getLessonCoursewareDetail_gyt,
|
|
|
+ GYM: getLessonCourseDetail_gym,
|
|
|
+ KLX: getLessonCourseDetail_klx
|
|
|
+ }
|
|
|
+ await httpAjaxErrMsg(LessonCoursewareDetailApi[userStoreHook.roles!], id || (route.params.id as string)).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ const { lockFlag, knowledgePointList, lessonTargetDesc, lessonCoursewareId } = res.data || {}
|
|
|
+ if (lockFlag) {
|
|
|
+ ElMessageBox.alert("课件已锁定", "温馨提示", {
|
|
|
+ confirmButtonText: "退出",
|
|
|
+ type: "error"
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ handleGoBack()
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ handleGoBack()
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if ((knowledgePointList || []).length < 1) {
|
|
|
+ ElMessageBox.alert("没有找到课件", "温馨提示", {
|
|
|
+ confirmButtonText: "退出",
|
|
|
+ type: "error"
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ handleGoBack()
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ handleGoBack()
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ lessonTargetDetail.value = lessonTargetDesc ? lessonTargetDesc.replace(/\n/g, "<br />") : ""
|
|
|
+
|
|
|
+ searchObj.lessonCoursewareId = lessonCoursewareId
|
|
|
+ // 处理返回的数据
|
|
|
+ handlePointList(knowledgePointList)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 请求带搜索条件数据
|
|
|
+ searchObj.lessonCoursewareId && getLessCoursewareList("onlySearch", searchObj.lessonCoursewareId)
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 带搜索条件的
|
|
|
+ * @param type onlySearch 只搜索 展示
|
|
|
+ */
|
|
|
+async function getLessCoursewareList(type?: string, id?: string) {
|
|
|
+ // GYM,GYT,KLX 区分 查询接口
|
|
|
+ const LessonCoursewareDetailApi = {
|
|
|
+ GYT: getMyCoursewareDetail_gyt,
|
|
|
+ GYM: getLessonCoursewareCourseList_gym,
|
|
|
+ KLX: getLessonCoursewareCourseList_klx
|
|
|
+ }
|
|
|
+ if (coursewareDetailController) {
|
|
|
+ coursewareDetailController.abort()
|
|
|
+ }
|
|
|
+ coursewareDetailController = new AbortController()
|
|
|
+ searchObj.loading = true
|
|
|
+ await httpAjax(LessonCoursewareDetailApi[userStoreHook.roles!], {
|
|
|
+ id: id || (route.params.id as string),
|
|
|
+ data: {
|
|
|
+ search: searchObj.queryStr,
|
|
|
+ detailFlag: "1"
|
|
|
+ },
|
|
|
+ abortController: coursewareDetailController
|
|
|
+ }).then(res => {
|
|
|
+ searchObj.loading = false
|
|
|
+ if (res.code === 200) {
|
|
|
+ const result = res.data || []
|
|
|
+ for (let i = 0; i < result.length; i++) {
|
|
|
+ const itemResult = result[i]
|
|
|
+ itemResult.name = itemResult.coursewareDetailName
|
|
|
+ itemResult.id = itemResult.coursewareDetailId || itemResult.lessonCoursewareDetailId
|
|
|
+ itemResult.lessonTargetDesc = itemResult.lessonTargetDesc ? itemResult.lessonTargetDesc.replace(/\n/g, "<br />") : ""
|
|
|
+ itemResult.children = itemResult.knowledgePointList || []
|
|
|
+ itemResult.knowledgePointList = []
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type === "onlySearch") {
|
|
|
+ handlePointListOnlySearch(result)
|
|
|
+ } else {
|
|
|
+ handlePointList(result, searchObj.isSearch)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化检查事项
|
|
|
+ const item = flattenCoursewareList.value[activeCoursewareIndex.value]
|
|
|
+ const parentId = item ? item.parentData.ids[0] : ""
|
|
|
+ if (parentId) {
|
|
|
+ const parentItem = coursewareList.value.find((item: any) => item.id === parentId)
|
|
|
+ if (parentItem) {
|
|
|
+ lessonTargetDetail.value = parentItem.lessonTargetDesc
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 标识
|
|
|
+ searchObj.isSearch = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// 处理是从搜索过来的,还是
|
|
|
+if (route.query.source === "search") {
|
|
|
+ getLessCoursewareList()
|
|
|
+} else {
|
|
|
+ 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: route.query.modeId as any
|
|
|
+ } as any).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ coursewareMenuList.value = res.data || []
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+let flattenCoursewareListData: any = [] // 临时扁平化数据
|
|
|
+function handlePointList(pointList: any[], isSearch?: boolean) {
|
|
|
+ flattenCoursewareListData = []
|
|
|
+ const list = filterPointList(pointList)
|
|
|
+ if (!isSearch) {
|
|
|
+ // 重置数据
|
|
|
+ coursewareTotalTime.value = 0
|
|
|
+ coursewareList.value = list
|
|
|
+ // 如果url里面有materialId 代表指定资料播放
|
|
|
+ if (route.query.materialId) {
|
|
|
+ const index = flattenCoursewareListData.findIndex((item: any) => {
|
|
|
+ return route.query.materialId === item.id + "" && route.query.knowledgePointId === item.knowledgePointId + ""
|
|
|
+ })
|
|
|
+ index > -1 && (activeCoursewareIndex.value = index)
|
|
|
+ }
|
|
|
+ flattenCoursewareList.value = deepCopy(flattenCoursewareListData)
|
|
|
+ } else {
|
|
|
+ if (flattenCoursewareListData[0]) {
|
|
|
+ // 默认展开第一个
|
|
|
+ tempActiveCourseware.value = {
|
|
|
+ ...flattenCoursewareListData[0],
|
|
|
+ id: null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tempCoursewareList.value = list
|
|
|
+ tempFlattenCoursewareList.value = deepCopy(flattenCoursewareListData)
|
|
|
+}
|
|
|
+
|
|
|
+function handlePointListOnlySearch(pointList: any[]) {
|
|
|
+ flattenCoursewareListData = []
|
|
|
+ const list = filterPointList(pointList)
|
|
|
+ if (flattenCoursewareListData[0]) {
|
|
|
+ // 默认展开第一个
|
|
|
+ tempActiveCourseware.value = {
|
|
|
+ ...flattenCoursewareListData[0],
|
|
|
+ id: null
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!searchObj.isSearch) {
|
|
|
+ coursewareSearchList.value = list
|
|
|
+ }
|
|
|
+ tempCoursewareList.value = list
|
|
|
+}
|
|
|
+function filterPointList(pointList: any[], parentData?: { ids: string[]; name: string }): any[] {
|
|
|
+ // 设置父级及以上id数组和父级name
|
|
|
+ return pointList.map(point => {
|
|
|
+ if (point.children) {
|
|
|
+ return Object.assign(point, {
|
|
|
+ children: filterPointList(point.children, { ids: [...(parentData?.ids || []), point.id], name: point.name })
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // coursewareTotalTime.value += point.totalMaterialTimeSecond
|
|
|
+ return Object.assign(point, {
|
|
|
+ materialList: point.materialList.map((item: any) => {
|
|
|
+ item.parentData = {
|
|
|
+ ids: [...(parentData?.ids || []), point.id],
|
|
|
+ name: point.name
|
|
|
+ }
|
|
|
+ flattenCoursewareListData.push(item)
|
|
|
+ return item
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+function handleChangeCourseware(index: -1 | 1) {
|
|
|
+ handleVideoPause()
|
|
|
+ handleSongPause()
|
|
|
+ const newIndex = index + activeCoursewareIndex.value
|
|
|
+ if (newIndex < 0 || newIndex > flattenCoursewareList.value.length - 1) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (searchObj.source === "search") {
|
|
|
+ const newItem = flattenCoursewareList.value[newIndex]
|
|
|
+ const newParentId = newItem ? newItem.parentData?.ids[0] : ""
|
|
|
+ if (newParentId) {
|
|
|
+ const parentItem = coursewareList.value.find((item: any) => item.id === newParentId)
|
|
|
+ if (parentItem) {
|
|
|
+ lessonTargetDetail.value = parentItem.lessonTargetDesc
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ activeCoursewareIndex.value = newIndex
|
|
|
+}
|
|
|
+function handleCourseSearchClick(value: any) {
|
|
|
+ if (searchObj.source === "search") {
|
|
|
+ searchObj.search = searchObj.tempSearch ? JSON.parse(JSON.stringify(searchObj.tempSearch)) : ""
|
|
|
+ coursewareList.value = deepCopy(tempCoursewareList.value)
|
|
|
+ flattenCoursewareList.value = deepCopy(tempFlattenCoursewareList.value)
|
|
|
+
|
|
|
+ const newIndex = flattenCoursewareList.value.findIndex((item: any) => {
|
|
|
+ return value.id === item.id && value.knowledgePointId === item.knowledgePointId
|
|
|
+ })
|
|
|
+ const newItem = flattenCoursewareList.value[newIndex]
|
|
|
+ const newParentId = newItem ? newItem.parentData?.ids[0] : ""
|
|
|
+
|
|
|
+ if (newParentId) {
|
|
|
+ const parentItem = coursewareList.value.find((item: any) => item.id === newParentId)
|
|
|
+ if (parentItem) {
|
|
|
+ lessonTargetDetail.value = parentItem.lessonTargetDesc
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ activeCoursewareIndex.value = newIndex
|
|
|
+ drawerSearchShow.value = false
|
|
|
+ } else {
|
|
|
+ const urls = router.resolve({
|
|
|
+ path: `/coursewarePlay/${searchObj.lessonCoursewareId}`,
|
|
|
+ query: {
|
|
|
+ materialId: value.id,
|
|
|
+ source: "search",
|
|
|
+ knowledgePointId: value.knowledgePointId,
|
|
|
+ search: searchObj.tempSearch ? JSON.parse(JSON.stringify(searchObj.tempSearch)) : ""
|
|
|
+ }
|
|
|
+ })
|
|
|
+ console.log(urls, "urls")
|
|
|
+
|
|
|
+ const url = window.location.origin + window.location.pathname + urls.href
|
|
|
+ window.open(url)
|
|
|
+ }
|
|
|
+}
|
|
|
+function handleCourseClick(value: any) {
|
|
|
+ searchObj.search = searchObj.tempSearch ? JSON.parse(JSON.stringify(searchObj.tempSearch)) : ""
|
|
|
+ coursewareList.value = deepCopy(tempCoursewareList.value)
|
|
|
+ flattenCoursewareList.value = deepCopy(tempFlattenCoursewareList.value)
|
|
|
+
|
|
|
+ const newIndex = flattenCoursewareList.value.findIndex((item: any) => {
|
|
|
+ return value.id === item.id && value.knowledgePointId === item.knowledgePointId
|
|
|
+ })
|
|
|
+
|
|
|
+ if (searchObj.source === "search") {
|
|
|
+ const newItem = flattenCoursewareList.value[newIndex]
|
|
|
+ const newParentId = newItem ? newItem.parentData?.ids[0] : ""
|
|
|
+
|
|
|
+ if (newParentId) {
|
|
|
+ const parentItem = coursewareList.value.find((item: any) => item.id === newParentId)
|
|
|
+ if (parentItem) {
|
|
|
+ lessonTargetDetail.value = parentItem.lessonTargetDesc
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ activeCoursewareIndex.value = newIndex
|
|
|
+ drawerShow.value = false
|
|
|
+}
|
|
|
+async function handleCourseMenuClick(value: any) {
|
|
|
+ // 判断是否为当前课程类型
|
|
|
+ if (currentId.value === value.id) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ LoadingBar.loading(true)
|
|
|
+ currentId.value = value.id
|
|
|
+ isCurrentCoursewareMenu.value = value.id === route.params.id ? true : false
|
|
|
+ flattenCoursewareListData = [] // 重置数据
|
|
|
+ isTempAutoPlay.value = true
|
|
|
+ await getCoursewareList(value.id)
|
|
|
+ getCoursewareMenuList(value.id)
|
|
|
+ drawerMenuShow.value = false
|
|
|
+ activeCoursewareIndex.value = 0
|
|
|
+ nextTick(() => {
|
|
|
+ // if (!activeCourseware.value?.phaseGoals) {
|
|
|
+ // 切换之后默认打开课程目录
|
|
|
+ drawerShow.value = true
|
|
|
+ // }
|
|
|
+ })
|
|
|
+ LoadingBar.loading(false)
|
|
|
+}
|
|
|
+
|
|
|
+/** 曲目相关 */
|
|
|
+// 暂停曲目播放
|
|
|
+function handleSongPause() {
|
|
|
+ songPlayDom.value?.contentWindow?.postMessage({ api: "setPlayState" }, "*")
|
|
|
+ showController()
|
|
|
+}
|
|
|
+
|
|
|
+/* 播放器相关 */
|
|
|
+// 视频播放或者暂停
|
|
|
+function handleVideoPlay() {
|
|
|
+ videoPlayDom.value?.handlePlay()
|
|
|
+ showController()
|
|
|
+}
|
|
|
+// 视频快进快退
|
|
|
+function handleVideoSpeedCurrentTime(type: "fast" | "slow") {
|
|
|
+ videoPlayDom.value?.speedCurrentTime(type)
|
|
|
+ showController()
|
|
|
+}
|
|
|
+// 视频暂停
|
|
|
+function handleVideoPause() {
|
|
|
+ videoPlayDom.value?.pauseVideo()
|
|
|
+ showController()
|
|
|
+}
|
|
|
+// 播放视频
|
|
|
+function handlePlayVideo({ src, name }: { src: string; name: string }) {
|
|
|
+ videoPlayDom.value?.playVideo({
|
|
|
+ src,
|
|
|
+ name
|
|
|
+ })
|
|
|
+ showController()
|
|
|
+}
|
|
|
+
|
|
|
+// 全屏显示
|
|
|
+handleFullscreen(true, false)
|
|
|
+/* 按键事件相关 */
|
|
|
+onMounted(() => {
|
|
|
+ document.addEventListener("keydown", handleKeydown)
|
|
|
+ document.addEventListener("contextmenu", preventDefaultContextmenu)
|
|
|
+ showController()
|
|
|
+})
|
|
|
+onUnmounted(() => {
|
|
|
+ document.removeEventListener("keydown", handleKeydown)
|
|
|
+ document.removeEventListener("contextmenu", preventDefaultContextmenu)
|
|
|
+})
|
|
|
+function preventDefaultContextmenu(event: MouseEvent) {
|
|
|
+ event.preventDefault()
|
|
|
+}
|
|
|
+function handleKeydown(e: KeyboardEvent) {
|
|
|
+ const key = e.key
|
|
|
+ // 打开弹窗之后快捷键失效
|
|
|
+ if (drawerShow.value || drawerMenuShow.value || drawerSearchShow.value) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (key === " ") {
|
|
|
+ closeAllModalFrame()
|
|
|
+ drawerShow.value = false
|
|
|
+ // 视频类型的时候才触发
|
|
|
+ fileType.value === "VIDEO" && handleVideoPlay()
|
|
|
+ } else if (key === "ArrowLeft") {
|
|
|
+ closeAllModalFrame()
|
|
|
+ drawerShow.value = false
|
|
|
+ // 视频类型的时候才触发
|
|
|
+ fileType.value === "VIDEO" && handleVideoSpeedCurrentTime("slow")
|
|
|
+ } else if (key === "ArrowRight") {
|
|
|
+ closeAllModalFrame()
|
|
|
+ drawerShow.value = false
|
|
|
+ // 视频类型的时候才触发
|
|
|
+ fileType.value === "VIDEO" && handleVideoSpeedCurrentTime("fast")
|
|
|
+ } else if (key === "ArrowDown") {
|
|
|
+ closeAllModalFrame()
|
|
|
+ drawerShow.value = false
|
|
|
+ handleChangeCourseware(1)
|
|
|
+ } else if (key === "ArrowUp") {
|
|
|
+ closeAllModalFrame()
|
|
|
+ drawerShow.value = false
|
|
|
+ handleChangeCourseware(-1)
|
|
|
+ }
|
|
|
+}
|
|
|
+function handleToolClick(type: string) {
|
|
|
+ fileType.value === "VIDEO" && handleVideoPause()
|
|
|
+ if (type === "menu") {
|
|
|
+ drawerMenuShow.value = true
|
|
|
+ } else if (type === "point") {
|
|
|
+ tempCoursewareList.value = deepCopy(coursewareList.value)
|
|
|
+ searchObj.queryStr = searchObj.search ? JSON.parse(JSON.stringify(searchObj.search)) : ""
|
|
|
+
|
|
|
+ tempActiveCourseware.value = null
|
|
|
+ drawerShow.value = true
|
|
|
+ } else if (type === "search") {
|
|
|
+ if (searchObj.source === "search") {
|
|
|
+ tempCoursewareList.value = deepCopy(coursewareList.value)
|
|
|
+ tempActiveCourseware.value = null
|
|
|
+ } else {
|
|
|
+ tempCoursewareList.value = deepCopy(coursewareSearchList.value)
|
|
|
+ tempActiveCourseware.value = {}
|
|
|
+ }
|
|
|
+
|
|
|
+ searchObj.queryStr = searchObj.search ? JSON.parse(JSON.stringify(searchObj.search)) : ""
|
|
|
+
|
|
|
+ drawerSearchShow.value = true
|
|
|
+ }
|
|
|
+}
|
|
|
+function handleMousemove() {
|
|
|
+ showController()
|
|
|
+}
|
|
|
+function handleClick() {
|
|
|
+ fileType.value === "VIDEO" && isShowController.value && handleVideoPlay()
|
|
|
+ showController()
|
|
|
+}
|
|
|
+// 是否显示控制器
|
|
|
+const isShowController = ref(true)
|
|
|
+let _showTimer: any
|
|
|
+function showController() {
|
|
|
+ isShowController.value = true
|
|
|
+ _showTimer && clearTimeout(_showTimer)
|
|
|
+ _showTimer = setTimeout(hideController, 3000)
|
|
|
+}
|
|
|
+function hideController() {
|
|
|
+ // 取消暂停的时候收起
|
|
|
+ // if (fileType.value === "VIDEO" && videoPlayDom.value?.playType === "pause") {
|
|
|
+ // return
|
|
|
+ // }
|
|
|
+ isShowController.value = false
|
|
|
+}
|
|
|
+/* 结束课程 */
|
|
|
+function handleGoBack() {
|
|
|
+ // window.open("about:blank", "_self")
|
|
|
+ // window.close()
|
|
|
+ // 如果从课件列表进来的,直接关闭
|
|
|
+ if (!router.options.history.state?.back) {
|
|
|
+ window.close()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ router.go(-1)
|
|
|
+}
|
|
|
+function handleCoursewareEnd() {
|
|
|
+ if (route.query.modeId) {
|
|
|
+ if (userStoreHook.roles === "GYM") {
|
|
|
+ httpAjaxLoadingErrMsg(getRecentCourseSchedule_gym, route.query.modeId as string).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ if (res.data?.signOutStatusEnum === 3) {
|
|
|
+ useDialogConfirm({
|
|
|
+ headImg: require("@/img/coursewarePlay/ts.png"),
|
|
|
+ text: `请确认是否结束课程,结束后请到APP进行签退。`,
|
|
|
+ btnShow: [true, true],
|
|
|
+ onOk() {
|
|
|
+ handleGoBack()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ handleGoBack()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else if (userStoreHook.roles === "GYT") {
|
|
|
+ httpAjaxLoadingErrMsg(checkWebCourse_gyt, route.query.modeId as string).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ if (res.data?.signOut === false) {
|
|
|
+ useDialogConfirm({
|
|
|
+ headImg: require("@/img/coursewarePlay/ts.png"),
|
|
|
+ text: `请确认是否结束课程,结束后请到APP进行签退。`,
|
|
|
+ btnShow: [true, true],
|
|
|
+ onOk() {
|
|
|
+ handleGoBack()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ handleGoBack()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ 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()
|
|
|
+ handleSongPause()
|
|
|
+ }
|
|
|
+ }
|
|
|
+)
|
|
|
+// 去练习
|
|
|
+const activeCoursewareResourceId = computed<string | undefined>(() => {
|
|
|
+ const materialRefs = activeCourseware.value?.materialRefs
|
|
|
+ return materialRefs ? (["GYM", "KLX"].includes(userStoreHook.roles!) ? materialRefs[0]?.resourceIdStr : materialRefs[0]?.resourceId) : undefined
|
|
|
+})
|
|
|
+const isPracticeShow = ref(false)
|
|
|
+const practiceUrl = ref("")
|
|
|
+function handleGoPracticeBtn(activeCoursewareResourceId: string) {
|
|
|
+ // GYM,GYT,KLX 区分 云教练
|
|
|
+ const urlObj = {
|
|
|
+ GYT: `${URL_TEACH_GYT}?id=${activeCoursewareResourceId}&modelType=practice&modeType=json&Authorization=${getToken()}&isYjt=1&&isHideBack=false`,
|
|
|
+ GYM: `${URL_TEACH_GYM}#/?id=${activeCoursewareResourceId}&Authorization=${getToken()}&platform=pc&isYjt=1&systemType=teacher&isHideMusicList=true`,
|
|
|
+ KLX: `${URL_TEACH_KLX}#/?id=${activeCoursewareResourceId}&Authorization=${getToken()}&platform=pc&isYjt=1&systemType=teacher&isHideMusicList=true`
|
|
|
+ }
|
|
|
+ isPracticeShow.value = true
|
|
|
+ practiceUrl.value = urlObj[userStoreHook.roles!]
|
|
|
+ //window.open(urlObj[userStoreHook.roles!], "_blank")
|
|
|
+}
|
|
|
+function handlePracticeClose() {
|
|
|
+ isPracticeShow.value = false
|
|
|
+ practiceUrl.value = ""
|
|
|
+}
|
|
|
+
|
|
|
+function onTitleTip(type: "phaseGoals" | "checkItem", text: string) {
|
|
|
+ useCoursewarePlayTip({
|
|
|
+ headImg: require(`@/img/coursewarePlay/${type === "phaseGoals" ? "ts3" : "ts4"}.png`),
|
|
|
+ text,
|
|
|
+ btnShow: [false, false]
|
|
|
+ })
|
|
|
+ handleVideoPause()
|
|
|
+}
|
|
|
+
|
|
|
+function handleQuery() {
|
|
|
+ //
|
|
|
+ searchObj.isSearch = true
|
|
|
+ searchObj.tempSearch = searchObj.queryStr ? JSON.parse(JSON.stringify(searchObj.queryStr)) : ""
|
|
|
+ if (searchObj.source === "search") {
|
|
|
+ getLessCoursewareList()
|
|
|
+ } else {
|
|
|
+ getLessCoursewareList("onlySearch", searchObj.lessonCoursewareId)
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.coursewarePlay {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+ &.hideController {
|
|
|
+ .leftTools {
|
|
|
+ opacity: 0;
|
|
|
+ transform: translate(-100%, -50%);
|
|
|
+ }
|
|
|
+ .topTools {
|
|
|
+ opacity: 0;
|
|
|
+ transform: translateY(-100%);
|
|
|
+ }
|
|
|
+ .goPracticeBtn {
|
|
|
+ transform: translateY(74px);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &.fileType_song.hideController {
|
|
|
+ .leftTools {
|
|
|
+ opacity: initial;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ }
|
|
|
+ .goPracticeBtn {
|
|
|
+ transform: initial;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .coursewarePlayCon {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ overflow: hidden;
|
|
|
+ .imgPlayBox {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ .imgPlay {
|
|
|
+ width: 84%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .songPlayBox {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ .songIframe {
|
|
|
+ display: block;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .topTools {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ background: linear-gradient(180deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);
|
|
|
+ transition: all 0.5s;
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 20px 30px 40px;
|
|
|
+ .leftMenu {
|
|
|
+ display: flex;
|
|
|
+ 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;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ p {
|
|
|
+ line-height: 1;
|
|
|
+ padding-top: 1px;
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ background: rgba(0, 0, 0, 0.1);
|
|
|
+ border-radius: 16px;
|
|
|
+ border: 1px solid rgba(255, 255, 255, 0.7);
|
|
|
+ font-size: 14px;
|
|
|
+ color: #ffffff;
|
|
|
+ line-height: 22px;
|
|
|
+ padding: 2px 10px;
|
|
|
+ margin-left: 10px;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .midMenu {
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ top: 23px;
|
|
|
+ // transform: translate(-50%, -50%);
|
|
|
+ transform: translateX(-50%);
|
|
|
+ }
|
|
|
+ .rightMenu {
|
|
|
+ .posCloseBtn {
|
|
|
+ cursor: pointer;
|
|
|
+ img {
|
|
|
+ width: 34px;
|
|
|
+ height: 34px;
|
|
|
+ padding: 6px;
|
|
|
+ box-sizing: content-box;
|
|
|
+ &:hover {
|
|
|
+ background-color: rgba(255, 255, 255, 0.2);
|
|
|
+ border-radius: 6px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .posTools {
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ transition: all 0.5s;
|
|
|
+ &.leftTools {
|
|
|
+ background: rgba(0, 0, 0, 0.4);
|
|
|
+ border-radius: 8px;
|
|
|
+ left: 32px;
|
|
|
+ }
|
|
|
+ .posBtn {
|
|
|
+ padding: 14px 6px;
|
|
|
+ font-weight: 500;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #ffffff;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ cursor: pointer;
|
|
|
+ // &:hover {
|
|
|
+ // opacity: $opacity-hover;
|
|
|
+ // }
|
|
|
+ &.disabled {
|
|
|
+ opacity: $opacity-disabled;
|
|
|
+ }
|
|
|
+ > img {
|
|
|
+ width: 34px;
|
|
|
+ height: 34px;
|
|
|
+ padding: 6px;
|
|
|
+ box-sizing: content-box;
|
|
|
+ &:hover {
|
|
|
+ background-color: rgba(255, 255, 255, 0.2);
|
|
|
+ border-radius: 6px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .goPracticeBtn {
|
|
|
+ position: absolute;
|
|
|
+ right: 32px;
|
|
|
+ bottom: 24px;
|
|
|
+ width: 143px;
|
|
|
+ height: 50px;
|
|
|
+ background: url("@/img/coursewarePlay/goPracticeBtn.png") no-repeat;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.5s;
|
|
|
+ &:hover {
|
|
|
+ opacity: $opacity-hover;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &:deep(.elDrawer.el-drawer) {
|
|
|
+ width: 348px !important;
|
|
|
+ .el-drawer__header {
|
|
|
+ height: 54px;
|
|
|
+ background: #ededed;
|
|
|
+ padding: 0 20px;
|
|
|
+ margin-bottom: 0;
|
|
|
+ .directory {
|
|
|
+ flex-grow: 0;
|
|
|
+ flex-shrink: 0;
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ }
|
|
|
+ .tit {
|
|
|
+ flex-grow: 1;
|
|
|
+ margin-left: 10px;
|
|
|
+ font-weight: 600;
|
|
|
+ font-size: 18px;
|
|
|
+ color: #333333;
|
|
|
+ }
|
|
|
+ .close {
|
|
|
+ cursor: pointer;
|
|
|
+ width: 14px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ &:hover {
|
|
|
+ opacity: $opacity-hover;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-input {
|
|
|
+ margin-right: 10px;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btnSelect {
|
|
|
+ width: 56px;
|
|
|
+ height: 26px;
|
|
|
+ line-height: 26px;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .el-drawer__body {
|
|
|
+ padding: 0;
|
|
|
+ overflow: hidden;
|
|
|
+ & > .elScrollbar {
|
|
|
+ .el-scrollbar__view {
|
|
|
+ padding: 0 22px;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ .el-scrollbar__wrap {
|
|
|
+ overflow-x: hidden;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &:deep(.elDrawerHeader.el-drawer) {
|
|
|
+ .el-drawer__header {
|
|
|
+ padding: 0 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &:deep(.elCourseMenu.el-drawer) {
|
|
|
+ width: 363px !important;
|
|
|
+ .el-drawer__body {
|
|
|
+ & > .elScrollbar {
|
|
|
+ .el-scrollbar__view {
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.empty {
|
|
|
+ height: calc(100vh - 54px);
|
|
|
+ :deep(.el-empty__image) {
|
|
|
+ width: 228px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-empty__description) {
|
|
|
+ color: #aaa;
|
|
|
+ p {
|
|
|
+ font-size: 18px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|