Browse Source

添加课件播放搜索

lex-xin 2 months ago
parent
commit
0145ac97d7

+ 287 - 287
src/views/coursewarePlay/components/courseCollapse/courseCollapse.vue

@@ -1,287 +1,287 @@
-<!--
-* @FileDescription: 折叠菜单
-* @Author: 黄琪勇
-* @Date:2024-04-01 18:40:50
--->
-<template>
-   <el-collapse class="courseCollapse" accordion v-model="activeCollapseId">
-      <el-collapse-item v-for="item in props.courseList" :key="item.id" :name="item.id" :class="{ isChild: props.isChild }">
-         <template #title>
-            <div class="courseCollapseHead">
-               <div class="courseCollapseHeadArrow">
-                  <div class="headArrow"></div>
-                  <div class="headArrowActive"></div>
-               </div>
-               <div class="courseCollapseHeadTit">
-                  <ellipsisScroll :title="item.name" />
-               </div>
-            </div>
-         </template>
-         <div class="courseCollapseCon" :class="{ courseListCon: item.materialList }">
-            <template v-if="item.materialList">
-               <div
-                  class="courseList"
-                  :class="{ isActive: activeCollapse?.id === i.id && activeCollapse?.knowledgePointId === i.knowledgePointId }"
-                  v-for="i in item.materialList"
-                  :key="i.id"
-                  @click="handleClick(i)"
-               >
-                  <div class="courseTitleCon" :class="i.typeCode || i.type">
-                     <div class="imgIcon"></div>
-                     <div class="ellipsisBox">
-                        <!-- <ellipsisScroll :title="i.name" /> -->
-                        <span v-html="formatName(i.name)"></span>
-                     </div>
-                  </div>
-                  <div class="iconArrow">
-                     <img
-                        v-if="activeCollapse?.id === i.id && activeCollapse?.knowledgePointId === i.knowledgePointId"
-                        src="@/img/coursewarePlay/icon-load.gif"
-                     />
-                  </div>
-               </div>
-            </template>
-            <courseCollapse
-               v-else
-               :isChild="true"
-               :search="searchStr"
-               :courseList="item.children || []"
-               :activeCollapse="activeCollapse"
-               @handleClick="handleClick"
-            />
-         </div>
-      </el-collapse-item>
-   </el-collapse>
-</template>
-
-<script setup lang="ts">
-import ellipsisScroll from "@/components/ellipsisScroll"
-import { ref, watch } from "vue"
-
-type materialListType = {
-   id: string
-   type: string
-   typeCode?: string
-   name: string
-   knowledgePointId: string
-}
-type courseListType = {
-   id: string
-   name: string
-   materialList: materialListType[] | null
-   children: courseListType | null
-}[]
-
-const props = defineProps<{
-   activeCollapse: undefined | Record<string, any>
-   courseList: courseListType
-   search?: string
-   isChild?: boolean
-}>()
-const searchStr = ref(props.search)
-
-const emits = defineEmits<{
-   (e: "handleClick", value: any): void
-}>()
-watch(
-   () => props.activeCollapse,
-   () => {
-      activeCollapseId.value = filterActiveId()
-   }
-)
-watch(
-   () => props.search,
-   () => {
-      searchStr.value = props.search
-   }
-)
-
-const activeCollapseId = ref(filterActiveId())
-
-function filterActiveId() {
-   const course = props.courseList.find(item => {
-      return (props.activeCollapse?.parentData.ids || []).includes(item.id)
-   })
-   return course?.id || ""
-}
-function handleClick(value: any) {
-   emits("handleClick", value)
-}
-
-function formatName(name: string) {
-   // console.log(name, searchStr.value, "searchStr")
-   if (!name || !searchStr.value) return name
-   const search: any = searchStr.value
-   return name.replace(search, `<span style="color: #F67146;">${search}</span>`)
-}
-</script>
-
-<style lang="scss" scoped>
-.courseCollapse.el-collapse {
-   --el-collapse-border-color: #f2f2f2;
-   --el-collapse-header-height: 56px;
-   border: none;
-   & > :deep(.el-collapse-item) {
-      > .el-collapse-item__wrap > .el-collapse-item__content {
-         padding-bottom: 0px;
-      }
-      &:last-child {
-         > .el-collapse-item__wrap {
-            border-bottom: none;
-         }
-         > .el-collapse-item__header {
-            border-bottom: none;
-         }
-      }
-      .el-collapse-item__arrow {
-         display: none;
-      }
-      &.is-active > .el-collapse-item__header {
-         > .courseCollapseHead {
-            .courseCollapseHeadTit {
-               color: #333333;
-               font-weight: 600;
-            }
-            .courseCollapseHeadArrow {
-               > .headArrow {
-                  display: none;
-               }
-               > .headArrowActive {
-                  display: block;
-               }
-            }
-         }
-      }
-      &.isChild {
-         .el-collapse-item__wrap {
-            border-bottom: none;
-         }
-         .el-collapse-item__header {
-            border-bottom: none;
-         }
-         .courseCollapseHead {
-            .courseCollapseHeadTit {
-               color: #333333;
-               font-size: 15px;
-            }
-            .courseCollapseHeadArrow {
-               .headArrow {
-                  background: url("@/img/coursewarePlay/jtr1.png") no-repeat;
-                  background-size: 100% 100%;
-               }
-            }
-         }
-      }
-   }
-   .courseCollapseHead {
-      width: 100%;
-      height: 100%;
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
-      .courseCollapseHeadTit {
-         text-align: left;
-         margin-left: 10px;
-         flex-grow: 1;
-         font-weight: 400;
-         font-size: 16px;
-         color: #777777;
-         overflow: hidden;
-      }
-      .courseCollapseHeadArrow {
-         flex-shrink: 0;
-         .headArrow,
-         .headArrowActive {
-            width: 14px;
-            height: 14px;
-         }
-         .headArrow {
-            background: url("@/img/coursewarePlay/jtr.png") no-repeat;
-            background-size: 100% 100%;
-         }
-         .headArrowActive {
-            display: none;
-            background: url("@/img/coursewarePlay/jtb.png") no-repeat;
-            background-size: 100% 100%;
-         }
-      }
-   }
-   .courseCollapseCon {
-      padding-left: 20px;
-      &.courseListCon {
-         padding-left: 0;
-      }
-      .courseList {
-         display: flex;
-         justify-content: space-between;
-         align-items: center;
-         padding: 0 10px 0 24px;
-         margin-bottom: 6px;
-         cursor: pointer;
-         &.isActive {
-            background: #f0f0f0;
-            border-radius: 7px;
-            .courseTitleCon {
-               color: #f67146;
-               font-weight: 600;
-               &.VIDEO .imgIcon {
-                  background: url("@/img/coursewarePlay/VIDEO.png") no-repeat;
-                  background-size: 100% 100%;
-               }
-               &.IMG .imgIcon {
-                  background: url("@/img/coursewarePlay/IMG.png") no-repeat;
-                  background-size: 100% 100%;
-               }
-               &.SONG .imgIcon {
-                  background: url("@/img/coursewarePlay/SONG.png") no-repeat;
-                  background-size: 100% 100%;
-               }
-            }
-         }
-         .courseTitleCon {
-            padding: 6px 0;
-            flex-grow: 1;
-            overflow: hidden;
-            margin-right: 8px;
-            display: flex;
-            align-items: center;
-            font-weight: 400;
-            font-size: 14px;
-            color: #333333;
-            > .ellipsisBox {
-               flex-grow: 1;
-               overflow: hidden;
-            }
-            > .imgIcon {
-               flex-shrink: 0;
-               width: 15px;
-               height: 15px;
-               margin-right: 10px;
-            }
-            &.VIDEO .imgIcon {
-               background: url("@/img/coursewarePlay/VIDEO1.png") no-repeat;
-               background-size: 100% 100%;
-            }
-            &.IMG .imgIcon {
-               background: url("@/img/coursewarePlay/IMG1.png") no-repeat;
-               background-size: 100% 100%;
-            }
-            &.SONG .imgIcon {
-               background: url("@/img/coursewarePlay/SONG1.png") no-repeat;
-               background-size: 100% 100%;
-            }
-         }
-         .iconArrow {
-            display: flex;
-            flex-shrink: 0;
-            width: 13px;
-            height: 13px;
-            > img {
-               width: 100%;
-               height: 100%;
-            }
-         }
-      }
-   }
-}
-</style>
+<!--
+* @FileDescription: 折叠菜单
+* @Author: 黄琪勇
+* @Date:2024-04-01 18:40:50
+-->
+<template>
+   <el-collapse class="courseCollapse" accordion v-model="activeCollapseId">
+      <el-collapse-item v-for="item in props.courseList" :key="item.id" :name="item.id" :class="{ isChild: props.isChild }">
+         <template #title>
+            <div class="courseCollapseHead">
+               <div class="courseCollapseHeadArrow">
+                  <div class="headArrow"></div>
+                  <div class="headArrowActive"></div>
+               </div>
+               <div class="courseCollapseHeadTit">
+                  <ellipsisScroll :title="item.name" />
+               </div>
+            </div>
+         </template>
+         <div class="courseCollapseCon" :class="{ courseListCon: item.materialList }">
+            <template v-if="item.materialList">
+               <div
+                  class="courseList"
+                  :class="{ isActive: activeCollapse?.id === i.id && activeCollapse?.knowledgePointId === i.knowledgePointId }"
+                  v-for="i in item.materialList"
+                  :key="i.id"
+                  @click="handleClick(i)"
+               >
+                  <div class="courseTitleCon" :class="i.typeCode || i.type">
+                     <div class="imgIcon"></div>
+                     <div class="ellipsisBox">
+                        <!-- <ellipsisScroll :title="i.name" /> -->
+                        <span v-html="formatName(i.name)"></span>
+                     </div>
+                  </div>
+                  <div class="iconArrow">
+                     <img
+                        v-if="activeCollapse?.id === i.id && activeCollapse?.knowledgePointId === i.knowledgePointId"
+                        src="@/img/coursewarePlay/icon-load.gif"
+                     />
+                  </div>
+               </div>
+            </template>
+            <courseCollapse
+               v-else
+               :isChild="true"
+               :search="searchStr"
+               :courseList="item.children || []"
+               :activeCollapse="activeCollapse"
+               @handleClick="handleClick"
+            />
+         </div>
+      </el-collapse-item>
+   </el-collapse>
+</template>
+
+<script setup lang="ts">
+import ellipsisScroll from "@/components/ellipsisScroll"
+import { ref, watch } from "vue"
+
+type materialListType = {
+   id: string
+   type: string
+   typeCode?: string
+   name: string
+   knowledgePointId: string
+}
+type courseListType = {
+   id: string
+   name: string
+   materialList: materialListType[] | null
+   children: courseListType | null
+}[]
+
+const props = defineProps<{
+   activeCollapse: undefined | Record<string, any>
+   courseList: courseListType
+   search?: string
+   isChild?: boolean
+}>()
+const searchStr = ref(props.search)
+
+const emits = defineEmits<{
+   (e: "handleClick", value: any): void
+}>()
+watch(
+   () => props.activeCollapse,
+   () => {
+      activeCollapseId.value = filterActiveId()
+   }
+)
+watch(
+   () => props.search,
+   () => {
+      searchStr.value = props.search
+   }
+)
+
+const activeCollapseId = ref(filterActiveId())
+
+function filterActiveId() {
+   const course = props.courseList.find(item => {
+      return (props.activeCollapse?.parentData?.ids || []).includes(item.id)
+   })
+   return course?.id || ""
+}
+function handleClick(value: any) {
+   emits("handleClick", value)
+}
+
+function formatName(name: string) {
+   // console.log(name, searchStr.value, "searchStr")
+   if (!name || !searchStr.value) return name
+   const search: any = searchStr.value
+   return name.replace(search, `<span style="color: #F67146;">${search}</span>`)
+}
+</script>
+
+<style lang="scss" scoped>
+.courseCollapse.el-collapse {
+   --el-collapse-border-color: #f2f2f2;
+   --el-collapse-header-height: 56px;
+   border: none;
+   & > :deep(.el-collapse-item) {
+      > .el-collapse-item__wrap > .el-collapse-item__content {
+         padding-bottom: 0px;
+      }
+      &:last-child {
+         > .el-collapse-item__wrap {
+            border-bottom: none;
+         }
+         > .el-collapse-item__header {
+            border-bottom: none;
+         }
+      }
+      .el-collapse-item__arrow {
+         display: none;
+      }
+      &.is-active > .el-collapse-item__header {
+         > .courseCollapseHead {
+            .courseCollapseHeadTit {
+               color: #333333;
+               font-weight: 600;
+            }
+            .courseCollapseHeadArrow {
+               > .headArrow {
+                  display: none;
+               }
+               > .headArrowActive {
+                  display: block;
+               }
+            }
+         }
+      }
+      &.isChild {
+         .el-collapse-item__wrap {
+            border-bottom: none;
+         }
+         .el-collapse-item__header {
+            border-bottom: none;
+         }
+         .courseCollapseHead {
+            .courseCollapseHeadTit {
+               color: #333333;
+               font-size: 15px;
+            }
+            .courseCollapseHeadArrow {
+               .headArrow {
+                  background: url("@/img/coursewarePlay/jtr1.png") no-repeat;
+                  background-size: 100% 100%;
+               }
+            }
+         }
+      }
+   }
+   .courseCollapseHead {
+      width: 100%;
+      height: 100%;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .courseCollapseHeadTit {
+         text-align: left;
+         margin-left: 10px;
+         flex-grow: 1;
+         font-weight: 400;
+         font-size: 16px;
+         color: #777777;
+         overflow: hidden;
+      }
+      .courseCollapseHeadArrow {
+         flex-shrink: 0;
+         .headArrow,
+         .headArrowActive {
+            width: 14px;
+            height: 14px;
+         }
+         .headArrow {
+            background: url("@/img/coursewarePlay/jtr.png") no-repeat;
+            background-size: 100% 100%;
+         }
+         .headArrowActive {
+            display: none;
+            background: url("@/img/coursewarePlay/jtb.png") no-repeat;
+            background-size: 100% 100%;
+         }
+      }
+   }
+   .courseCollapseCon {
+      padding-left: 20px;
+      &.courseListCon {
+         padding-left: 0;
+      }
+      .courseList {
+         display: flex;
+         justify-content: space-between;
+         align-items: center;
+         padding: 0 10px 0 24px;
+         margin-bottom: 6px;
+         cursor: pointer;
+         &.isActive {
+            background: #f0f0f0;
+            border-radius: 7px;
+            .courseTitleCon {
+               color: #f67146;
+               font-weight: 600;
+               &.VIDEO .imgIcon {
+                  background: url("@/img/coursewarePlay/VIDEO.png") no-repeat;
+                  background-size: 100% 100%;
+               }
+               &.IMG .imgIcon {
+                  background: url("@/img/coursewarePlay/IMG.png") no-repeat;
+                  background-size: 100% 100%;
+               }
+               &.SONG .imgIcon {
+                  background: url("@/img/coursewarePlay/SONG.png") no-repeat;
+                  background-size: 100% 100%;
+               }
+            }
+         }
+         .courseTitleCon {
+            padding: 6px 0;
+            flex-grow: 1;
+            overflow: hidden;
+            margin-right: 8px;
+            display: flex;
+            align-items: center;
+            font-weight: 400;
+            font-size: 14px;
+            color: #333333;
+            > .ellipsisBox {
+               flex-grow: 1;
+               overflow: hidden;
+            }
+            > .imgIcon {
+               flex-shrink: 0;
+               width: 15px;
+               height: 15px;
+               margin-right: 10px;
+            }
+            &.VIDEO .imgIcon {
+               background: url("@/img/coursewarePlay/VIDEO1.png") no-repeat;
+               background-size: 100% 100%;
+            }
+            &.IMG .imgIcon {
+               background: url("@/img/coursewarePlay/IMG1.png") no-repeat;
+               background-size: 100% 100%;
+            }
+            &.SONG .imgIcon {
+               background: url("@/img/coursewarePlay/SONG1.png") no-repeat;
+               background-size: 100% 100%;
+            }
+         }
+         .iconArrow {
+            display: flex;
+            flex-shrink: 0;
+            width: 13px;
+            height: 13px;
+            > img {
+               width: 100%;
+               height: 100%;
+            }
+         }
+      }
+   }
+}
+</style>

+ 1105 - 996
src/views/coursewarePlay/coursewarePlay.vue

@@ -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>