黄琪勇 1 年之前
父節點
當前提交
1352369887
共有 5 個文件被更改,包括 173 次插入33 次删除
  1. 6 0
      .env.development
  2. 5 0
      .env.production
  3. 4 0
      src/config/index.ts
  4. 141 29
      src/views/coursewarePlay/coursewarePlay.vue
  5. 17 4
      src/views/coursewarePlay/videoPlay/videoPlay.vue

+ 6 - 0
.env.development

@@ -6,3 +6,9 @@ VUE_APP_URL_GYT = "/gyt"
 
 # 标注画板地址
 VUE_APP_WHITEBOARD = "https://test.lexiaoya.cn/whiteboard-noCollab"
+
+#管乐团 云教练
+VUE_APP_TEACH_GYT = "https://test.lexiaoya.cn/orchestra-music-score/"
+
+#管乐迷 云教练
+VUE_APP_TEACH_GYM ="https://mantest.dayaedu.com/accompany/"

+ 5 - 0
.env.production

@@ -6,3 +6,8 @@ VUE_APP_URL_GYT = "https://dev.lexiaoya.cn"
 # 标注画板地址
 VUE_APP_WHITEBOARD = "https://test.lexiaoya.cn/whiteboard-noCollab"
 
+#管乐团 云教练
+VUE_APP_TEACH_GYT = "https://test.lexiaoya.cn/orchestra-music-score/"
+
+#管乐迷 云教练
+VUE_APP_TEACH_GYM ="https://mantest.dayaedu.com/accompany/"

+ 4 - 0
src/config/index.ts

@@ -9,3 +9,7 @@ export const URL_WHITEBOARD = process.env.VUE_APP_WHITEBOARD as string
 export const URL_MAC_GYM_SECUREANTH = process.env.VUE_APP_MAC_GYM_SECUREANTH as string
 export const URL_MAC_GYT_SECUREANTH = process.env.VUE_APP_MAC_GYT_SECUREANTH as string
 export const URL_WIN_SECUREANTH = process.env.VUE_APP_WIN_SECUREANTH as string
+
+// 云教练地址
+export const URL_TEACH_GYT = process.env.VUE_APP_TEACH_GYT as string
+export const URL_TEACH_GYM = process.env.VUE_APP_TEACH_GYM as string

+ 141 - 29
src/views/coursewarePlay/coursewarePlay.vue

@@ -4,8 +4,22 @@
 * @Date:2024-04-03 17:31:41
 -->
 <template>
-   <div class="coursewarePlay">
-      <videoPlay ref="videoPlayDom" @ended="handleChangeCourseware(1)" :disableEvents="true" />
+   <div class="coursewarePlay" :class="{ hideController: !isShowController }">
+      <div class="coursewarePlayCon" @mousemove="handleMousemove" @click="handleClick">
+         <videoPlay
+            v-show="fileType === 'VIDEO'"
+            ref="videoPlayDom"
+            @ended="handleChangeCourseware(1)"
+            :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 class="songIframe" @mousemove="handleMousemove" :src="songPlaySrc" frameborder="0"></iframe>
+         </div>
+      </div>
       <div class="leftTools posTools">
          <div v-if="activeCoursewareIndex > 0" class="posBtn" @click="handleChangeCourseware(-1)">
             <img src="@/img/coursewarePlay/shang.png" />
@@ -21,7 +35,7 @@
             class="posBtn"
             @click="
                () => {
-                  videoPlayDom?.pauseVideo()
+                  handleVideoPause()
                   whitePenShow = true
                }
             "
@@ -33,7 +47,7 @@
             class="posBtn"
             @click="
                () => {
-                  videoPlayDom?.pauseVideo()
+                  handleVideoPause()
                   penShow = true
                }
             "
@@ -99,13 +113,15 @@ import { checkWebCourse_gyt } from "@/api/coursewarePlay.api"
 import { httpAjaxErrMsg, httpAjaxLoadingErrMsg } from "@/plugin/httpAjax"
 import userStore from "@/store/modules/user"
 import { useRoute } from "vue-router"
-import { shallowRef, ref, computed, onUnmounted, onMounted, watch } from "vue"
+import { shallowRef, ref, computed, onUnmounted, onMounted, watch, nextTick } from "vue"
 import { ElMessageBox } from "element-plus"
 import courseCollapse from "./components/courseCollapse"
 import pen from "./components/pen"
 import playRecordTime from "./components/playRecordTime"
 import useDialogConfirm from "@/hooks/useDialogConfirm"
 import { getRecentCourseSchedule_gym } from "@/api/homePage.api"
+import { getToken } from "@/libs/auth"
+import { URL_TEACH_GYT, URL_TEACH_GYM } from "@/config"
 
 const route = useRoute()
 const userStoreHook = userStore()
@@ -121,16 +137,33 @@ const flattenCoursewareList = shallowRef<any[]>([]) // 扁平化coursewareList
 const activeCourseware = computed<undefined | Record<string, any>>(() => {
    return flattenCoursewareList.value[activeCoursewareIndex.value]
 })
+// 文件类型
+const fileType = computed<"VIDEO" | "IMG" | "SONG">(() => {
+   return activeCourseware.value?.type || activeCourseware.value?.typeCode
+})
+const songPlaySrc = computed<string>(() => {
+   if (fileType.value !== "SONG") {
+      return ""
+   }
+   return userStoreHook.roles === "GYM"
+      ? `${URL_TEACH_GYM}?Authorization=${getToken()}&platform=web&isOpenMetronome=0#/detail/${activeCourseware.value?.content}?part-index=0`
+      : `${URL_TEACH_GYT}?id=${activeCourseware.value?.content}&modelType=practice&modeType=json&Authorization=${getToken()}`
+})
 const activeCoursewareIndex = ref(0)
 const drawerShow = ref(false)
 // 课程总时间
 const coursewareTotalTime = ref(0)
+// 监控播放
 watch(activeCourseware, () => {
-   activeCourseware.value &&
-      videoPlayDom.value?.playVideo({
-         src: activeCourseware.value.content,
-         name: activeCourseware.value.name
+   handleVideoPause()
+   fileType.value === "VIDEO" &&
+      nextTick(() => {
+         handlePlayVideo({
+            src: activeCourseware.value?.content,
+            name: activeCourseware.value?.name
+         })
       })
+   showController()
 })
 getCoursewareList()
 function getCoursewareList() {
@@ -214,23 +247,76 @@ function handleCourseClick(value: any) {
       return value.id === item.id
    })
 }
-
+/* 播放器相关 */
+// 视频播放或者暂停
+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()
+}
 /* 按键事件相关 */
 onMounted(() => {
-   document.addEventListener("keydown", handleVideoKeydown)
+   document.addEventListener("keydown", handleKeydown)
+   showController()
 })
 onUnmounted(() => {
-   document.removeEventListener("keydown", handleVideoKeydown)
+   document.removeEventListener("keydown", handleKeydown)
 })
-function handleVideoKeydown(e: KeyboardEvent) {
+function handleKeydown(e: KeyboardEvent) {
    const key = e.key
-   if (key === "ArrowDown") {
+   if (key === " ") {
+      // 视频类型的时候才触发
+      fileType.value === "VIDEO" && handleVideoPlay()
+   } else if (key === "ArrowLeft") {
+      // 视频类型的时候才触发
+      fileType.value === "VIDEO" && handleVideoSpeedCurrentTime("slow")
+   } else if (key === "ArrowRight") {
+      // 视频类型的时候才触发
+      fileType.value === "VIDEO" && handleVideoSpeedCurrentTime("fast")
+   } else if (key === "ArrowDown") {
       handleChangeCourseware(1)
    } else if (key === "ArrowUp") {
       handleChangeCourseware(-1)
    }
 }
-
+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")
@@ -284,6 +370,46 @@ function handleCoursewareEnd() {
    width: 100%;
    height: 100%;
    position: relative;
+   overflow: hidden;
+   &.hideController {
+      .leftTools {
+         opacity: 0;
+         transform: translate(-100%, -50%);
+      }
+      .rightTools {
+         opacity: 0;
+         transform: translate(100%, -50%);
+      }
+      .topTools {
+         opacity: 0;
+         transform: translateY(-100%);
+      }
+   }
+   .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;
@@ -348,20 +474,6 @@ function handleCoursewareEnd() {
          }
       }
    }
-   &:deep(.videoPlay.isHideController) {
-      .leftTools {
-         opacity: 0;
-         transform: translate(-100%, -50%);
-      }
-      .rightTools {
-         opacity: 0;
-         transform: translate(100%, -50%);
-      }
-      .topTools {
-         opacity: 0;
-         transform: translateY(-100%);
-      }
-   }
    &:deep(.elDrawer.el-drawer) {
       width: 346px !important;
       .el-drawer__header {

+ 17 - 4
src/views/coursewarePlay/videoPlay/videoPlay.vue

@@ -7,11 +7,12 @@
    <div
       @keydown="handleVideoKeydown"
       @mousemove="handleVideoMousemove"
+      @click="handleVideoClick"
       class="videoPlay"
       :class="{ isHideController: !isShowController }"
       tabindex="-1"
    >
-      <video class="videoPlayBox" @click="handlePlay" :id="videoId" preload="auto" playsinline webkit-playsinline></video>
+      <video class="videoPlayBox" :id="videoId" preload="auto" playsinline webkit-playsinline></video>
       <div class="videoController" @click.stop>
          <div class="timeController">{{ `${formatTime(timeController.currentTime)} / ${formatTime(timeController.duration)}` }}</div>
          <n-slider
@@ -75,13 +76,14 @@
 <script setup lang="ts">
 import TCPlayer from "tcplayer.js"
 import "tcplayer.js/dist/tcplayer.min.css"
-import { onMounted, onUnmounted, ref, reactive, watch } from "vue"
+import { onMounted, onUnmounted, ref, reactive, watch, toRef, watchEffect } from "vue"
 import { UUID } from "@/libs/tools"
 import { formatTime } from "./tools"
 import { NSlider } from "naive-ui"
 
 const props = defineProps<{
    disableEvents?: boolean
+   isShowController?: boolean
 }>()
 const emits = defineEmits<{
    (e: "ready"): void //播放器初始化完成
@@ -134,6 +136,9 @@ watch(
 )
 /* 是否显示控制器 */
 const isShowController = ref(true)
+watchEffect(() => {
+   isShowController.value = props.isShowController
+})
 let _showTimer: any
 onMounted(() => {
    initVideo()
@@ -254,6 +259,10 @@ function handlePalySpeed(value: number) {
    }
    handlePalySpeedChange(palySpeed)
 }
+function handleVideoClick() {
+   if (props.disableEvents) return
+   handlePlay()
+}
 function handleVideoKeydown(e: KeyboardEvent) {
    if (props.disableEvents) return
    const key = e.key
@@ -265,12 +274,13 @@ function handleVideoKeydown(e: KeyboardEvent) {
       speedCurrentTime("fast")
    }
 }
-/* 是否显示控制器 */
 function handleVideoMousemove() {
    if (props.disableEvents) return
    showController()
 }
+/* 是否显示控制器 */
 function showController() {
+   if (props.disableEvents) return
    isShowController.value = true
    _showTimer && clearTimeout(_showTimer)
    _showTimer = setTimeout(tryHideController, 3000)
@@ -282,7 +292,10 @@ function tryHideController() {
 }
 defineExpose({
    playVideo,
-   pauseVideo
+   pauseVideo,
+   handlePlay,
+   speedCurrentTime,
+   playType: toRef(playController, "type")
 })
 </script>