黄琪勇 1 rok temu
rodzic
commit
cfe87f2ec5

+ 27 - 0
src/api/coursewarePlay.api.ts

@@ -0,0 +1,27 @@
+import { httpAxios_gyt } from "@/api/ApiInstance"
+
+/**
+ * 管乐团
+ */
+
+// 获取当前播放的时间
+export const getCoursewarePlayTime_gyt = (id: string) => {
+   return httpAxios_gyt.axioseRquest({
+      method: "post",
+      url: "/api-teacher/courseSchedule/getCoursewarePlayTime?courseScheduleId=" + id
+   })
+}
+// 记录时间
+export const coursewarePlayTime_gyt = (id: string, time: number) => {
+   return httpAxios_gyt.axioseRquest({
+      method: "post",
+      url: `/api-teacher/courseSchedule/coursewarePlayTime?courseScheduleId=${id}&playTime=${time}`
+   })
+}
+// 判断是否签退
+export const checkWebCourse_gyt = (id: string) => {
+   return httpAxios_gyt.axioseRquest({
+      method: "post",
+      url: `/api-teacher/courseSchedule/checkWebCourse/` + id
+   })
+}

BIN
src/img/coursewarePlay/ts.png


+ 1 - 1
src/plugin/loadingBar/loadingBar.vue

@@ -74,7 +74,7 @@ body.h-loadingBarBody {
    cursor: wait;
    width: 100%;
    height: 100%;
-   background: rgba(255, 255, 255, 0.6);
+   background: rgba(255, 255, 255, 0.4);
    .loading-bar-content {
       position: absolute;
       top: 50%;

+ 2 - 0
src/views/coursewarePlay/components/playRecordTime/index.ts

@@ -0,0 +1,2 @@
+import playRecordTime from "./playRecordTime.vue"
+export default playRecordTime

+ 92 - 0
src/views/coursewarePlay/components/playRecordTime/playRecordTime.vue

@@ -0,0 +1,92 @@
+<!--
+* @FileDescription:播放记时
+* @Author: 黄琪勇
+* @Date:2024-04-07 16:49:23
+-->
+<template>
+   <div class="playRecordTime">
+      <div class="drop"></div>
+      <div class="time">{{ `${formatTime(playTime)}/${formatTime(props.coursewareTotalTIme)}` }}</div>
+   </div>
+</template>
+
+<script setup lang="ts">
+import { formatTime } from "../../videoPlay/tools"
+import { getCoursewarePlayTime_gyt, coursewarePlayTime_gyt } from "@/api/coursewarePlay.api"
+import { httpAjax } from "@/plugin/httpAjax"
+import { ref, onUnmounted } from "vue"
+const props = defineProps<{
+   coursewareTotalTIme: number
+   modeId: string
+}>()
+
+let _time: any
+const timeNum = 5
+const playTime = ref(0)
+let timeRecord = 0
+onUnmounted(() => {
+   _time && clearInterval(_time)
+})
+getCoursewarePlayTime()
+function getCoursewarePlayTime() {
+   httpAjax(getCoursewarePlayTime_gyt, props.modeId).then(res => {
+      if (res.code === 200) {
+         playTime.value += res.data || 0
+      }
+   })
+}
+_time = setInterval(() => {
+   // 播放时间大于总时间
+   if (playTime.value >= props.coursewareTotalTIme) {
+      _time && clearInterval(_time)
+      timeRecord > 0 && handleCoursewarePlayTime(props.modeId, timeRecord)
+      return
+   }
+   timeRecord++
+   playTime.value++
+   if (timeRecord === timeNum) {
+      handleCoursewarePlayTime(props.modeId, timeRecord)
+      timeRecord = 0
+   }
+}, 1000)
+function handleCoursewarePlayTime(id: string, time: number) {
+   httpAjax(coursewarePlayTime_gyt, id, time).then(() => {})
+}
+</script>
+
+<style lang="scss" scoped>
+.playRecordTime {
+   margin-left: 20px;
+   display: flex;
+   align-items: center;
+   padding: 14px 16px;
+   background: rgba(100, 100, 100, 0.5);
+   border-radius: 20px;
+   .drop {
+      margin-right: 12px;
+      width: 8px;
+      height: 8px;
+      background: #f73434;
+      animation: loadFade 1s ease-in-out infinite;
+      border-radius: 50%;
+      @keyframes loadFade {
+         0% {
+            opacity: 0;
+         }
+
+         50% {
+            opacity: 0.5;
+         }
+
+         100% {
+            opacity: 1;
+         }
+      }
+   }
+   .time {
+      font-weight: 400;
+      font-size: 22px;
+      color: #ffffff;
+   }
+}
+</style>

+ 62 - 4
src/views/coursewarePlay/coursewarePlay.vue

@@ -5,7 +5,7 @@
 -->
 <template>
    <div class="coursewarePlay">
-      <videoPlay ref="videoPlayDom" @ready="handleVideoReady" @keydown="handleVideoKeydown">
+      <videoPlay ref="videoPlayDom" @ready="handleVideoReady" :listen-win-events="true">
          <div class="leftTools posTools">
             <div v-if="activeCoursewareIndex > 0" class="posBtn" @click="handleChangeCourseware(-1)">
                <img src="@/img/coursewarePlay/shang.png" />
@@ -29,7 +29,7 @@
                <img src="@/img/coursewarePlay/zhishidian.png" />
                <div>知识点</div>
             </div>
-            <div class="posBtn" @click="handleGoBack">
+            <div class="posBtn" @click="handleCoursewareEnd">
                <img src="@/img/coursewarePlay/jieshu.png" />
                <div>结束</div>
             </div>
@@ -37,6 +37,11 @@
          <div class="topTools">
             <div class="leftMenu">
                <img @click="handleGoBack" class="backImg" src="@/img/coursewarePlay/back.png" />
+               <playRecordTime
+                  v-if="route.query.modeId && coursewareTotalTIme && !(userStoreHook.roles === 'GYM')"
+                  :modeId="route.query.modeId as string"
+                  :coursewareTotalTIme="coursewareTotalTIme"
+               />
             </div>
             <div class="midMenu">{{ activeCourseware?.parentData.name || "" }}</div>
             <div class="rightMenu"></div>
@@ -78,13 +83,17 @@
 <script setup lang="ts">
 import videoPlay from "./videoPlay"
 import { getLessonCourseDetail_gym, getLessonCoursewareDetail_gyt } from "@/api/cloudTextbooks.api"
+import { checkWebCourse_gyt } from "@/api/coursewarePlay.api"
 import { httpAjaxErrMsg } from "@/plugin/httpAjax"
 import userStore from "@/store/modules/user"
 import { useRoute } from "vue-router"
-import { shallowRef, ref, computed, watchEffect } from "vue"
+import { shallowRef, ref, computed, watchEffect, onUnmounted, onMounted } 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"
 
 // 批注
 const penShow = ref(false)
@@ -108,7 +117,12 @@ const coursewareTotalTIme = ref(0)
 watchEffect(() => {
    activeCourseware.value && videoPlayDom.value?.playVideo({ src: activeCourseware.value.content })
 })
-
+onMounted(() => {
+   document.addEventListener("keydown", handleVideoKeydown)
+})
+onUnmounted(() => {
+   document.removeEventListener("keydown", handleVideoKeydown)
+})
 function getCoursewareList() {
    httpAjaxErrMsg(userStoreHook.roles === "GYM" ? getLessonCourseDetail_gym : getLessonCoursewareDetail_gyt, route.params.id as string).then(res => {
       if (res.code === 200) {
@@ -165,6 +179,7 @@ function filterPointList(pointList: any[], parentData?: { ids: string[]; name: s
             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 = {
@@ -207,6 +222,47 @@ function handleGoBack() {
    window.open("about:blank", "_self")
    window.close()
 }
+function handleCoursewareEnd() {
+   if (route.query.modeId) {
+      if (userStoreHook.roles === "GYM") {
+         httpAjaxErrMsg(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 {
+         httpAjaxErrMsg(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()
+   }
+}
 </script>
 
 <style lang="scss" scoped>
@@ -239,6 +295,8 @@ function handleGoBack() {
       justify-content: space-between;
       padding: 20px 30px;
       .leftMenu {
+         display: flex;
+         align-items: center;
          .backImg {
             cursor: pointer;
             width: 22px;

+ 15 - 1
src/views/coursewarePlay/videoPlay/videoPlay.vue

@@ -5,7 +5,7 @@
 -->
 <template>
    <div
-      @keydown="handleVideoKeydown"
+      @keydown="props.listenWinEvents || handleVideoKeydown"
       @mousemove="handleVideoMousemove"
       class="videoPlay"
       :class="{ isHideController: !isShowController }"
@@ -63,6 +63,9 @@ import { onMounted, onUnmounted, ref, reactive } from "vue"
 import { UUID } from "@/libs/tools"
 import { formatTime } from "./tools"
 
+const props = defineProps<{
+   listenWinEvents?: boolean
+}>()
 const emits = defineEmits<{
    (e: "ready"): void //播放器初始化完成
 }>()
@@ -98,8 +101,14 @@ const isShowController = ref(true)
 let _showTimer: any
 onMounted(() => {
    initVideo()
+   if (props.listenWinEvents) {
+      document.addEventListener("keydown", handleVideoKeydown)
+   }
 })
 onUnmounted(() => {
+   if (props.listenWinEvents) {
+      document.removeEventListener("keydown", handleVideoKeydown)
+   }
    playerVm?.dispose()
 })
 /**
@@ -210,6 +219,11 @@ defineExpose({
    height: 100%;
    position: relative;
    overflow: hidden;
+   :deep(.videoPlayBox) {
+      &.tcp-skin .tcp-right-click-popup-menu {
+         display: none;
+      }
+   }
    .videoPlayBox {
       width: 100%;
       height: 100%;