|
@@ -1,19 +1,5 @@
|
|
|
-import {
|
|
|
- Icon,
|
|
|
- showConfirmDialog,
|
|
|
- Slider,
|
|
|
- Swipe,
|
|
|
- SwipeItem
|
|
|
-} from 'vant'
|
|
|
-import {
|
|
|
- defineComponent,
|
|
|
- onMounted,
|
|
|
- reactive,
|
|
|
- onUnmounted,
|
|
|
- ref,
|
|
|
- watch,
|
|
|
- Transition,
|
|
|
-} from 'vue'
|
|
|
+import { Icon, showConfirmDialog, Slider, Swipe, SwipeItem } from 'vant'
|
|
|
+import { defineComponent, onMounted, reactive, onUnmounted, ref, watch, Transition } from 'vue'
|
|
|
import styles from './index.module.less'
|
|
|
import 'plyr/dist/plyr.css'
|
|
|
import request from '@/helpers/request'
|
|
@@ -38,7 +24,23 @@ const materialType = {
|
|
|
export default defineComponent({
|
|
|
name: 'exercise-after-class',
|
|
|
setup() {
|
|
|
+ /** 设置播放容器 16:9 */
|
|
|
+ const parentContainer = reactive({
|
|
|
+ width: '100vw'
|
|
|
+ })
|
|
|
+ const setContainer = () => {
|
|
|
+ let min = Math.min(screen.width, screen.height)
|
|
|
+ let max = Math.max(screen.width, screen.height)
|
|
|
+ let width = min * (16 / 9)
|
|
|
+ if (width > max) {
|
|
|
+ parentContainer.width = '100vw'
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ parentContainer.width = width + 'px'
|
|
|
+ }
|
|
|
+ }
|
|
|
const handleInit = (type = 0) => {
|
|
|
+ setContainer()
|
|
|
// 横屏
|
|
|
postMessage({
|
|
|
api: 'setRequestedOrientation',
|
|
@@ -98,7 +100,10 @@ export default defineComponent({
|
|
|
let details = []
|
|
|
try {
|
|
|
const res: any = await request.get(
|
|
|
- state.platformApi + `/lessonTraining/courseSchedule/${route.query.courseScheduleId}`
|
|
|
+ state.platformApi + `/lessonTraining/courseSchedule/${route.query.courseScheduleId}`,
|
|
|
+ {
|
|
|
+ hideLoading: true
|
|
|
+ }
|
|
|
)
|
|
|
if (Array.isArray(res?.data)) {
|
|
|
const studentLevel = state.user?.data?.studentLevel || 1
|
|
@@ -124,7 +129,7 @@ export default defineComponent({
|
|
|
videoEle: null,
|
|
|
timer: null,
|
|
|
muted: true, // 静音
|
|
|
- autoplay: true, //自动播放
|
|
|
+ autoplay: true //自动播放
|
|
|
})
|
|
|
popupData.itemActive = videoData.id
|
|
|
popupData.tabName = videoData.materialName
|
|
@@ -147,7 +152,10 @@ export default defineComponent({
|
|
|
try {
|
|
|
const res: any = await request.post(
|
|
|
state.platformApi +
|
|
|
- `/studentLessonTraining/trainingRecord/${query.courseScheduleId}?userId=${state.user?.data?.id}`
|
|
|
+ `/studentLessonTraining/trainingRecord/${query.courseScheduleId}?userId=${state.user?.data?.id}`,
|
|
|
+ {
|
|
|
+ hideLoading: true
|
|
|
+ }
|
|
|
)
|
|
|
if (res?.data) {
|
|
|
getTrainingTimes(res.data)
|
|
@@ -197,7 +205,8 @@ export default defineComponent({
|
|
|
const res: any = await request.post(
|
|
|
state.platformApi + '/studentLessonTraining/lessonTrainingRecord',
|
|
|
{
|
|
|
- data: body
|
|
|
+ data: body,
|
|
|
+ hideLoading: true
|
|
|
}
|
|
|
)
|
|
|
trainingRecord()
|
|
@@ -235,7 +244,7 @@ export default defineComponent({
|
|
|
if (nextItem?.type === materialType.视频) {
|
|
|
const searchUrl = qs.stringify({
|
|
|
...query,
|
|
|
- materialId: nextItem.materialId
|
|
|
+ materialId: nextItem.materialId
|
|
|
})
|
|
|
// console.log('下一题视频', data.details[itemIndex].materialId, nextItem.materialId)
|
|
|
location.href = `${location.origin}${location.pathname}#/exerciseAfterClass?${searchUrl}`
|
|
@@ -271,131 +280,133 @@ export default defineComponent({
|
|
|
}
|
|
|
|
|
|
return () => (
|
|
|
- <div class={styles.coursewarePlay}>
|
|
|
- <Swipe
|
|
|
- style={{ height: '100vh' }}
|
|
|
- ref={swipeRef}
|
|
|
- showIndicators={false}
|
|
|
- loop={false}
|
|
|
- vertical
|
|
|
- lazyRender={true}
|
|
|
- touchable={false}
|
|
|
- >
|
|
|
- {data.itemList.map((m: any, mIndex: number) => {
|
|
|
- return (
|
|
|
- <SwipeItem>
|
|
|
- <>
|
|
|
- <div
|
|
|
- class={styles.itemDiv}
|
|
|
- onClick={() => {
|
|
|
- clearTimeout(m.timer)
|
|
|
- activeData.model = !activeData.model
|
|
|
- }}
|
|
|
- >
|
|
|
- <video
|
|
|
- playsinline="false"
|
|
|
- preload="auto"
|
|
|
- class="player"
|
|
|
- poster={iconVideobg}
|
|
|
- data-vid={m.id}
|
|
|
- src={m.content}
|
|
|
- loop={m.loop}
|
|
|
- autoplay={m.autoplay}
|
|
|
- muted={m.muted}
|
|
|
- onLoadedmetadata={async (e: Event) => {
|
|
|
- const videoEle = e.target as unknown as HTMLVideoElement
|
|
|
- m.duration = videoEle.duration
|
|
|
- m.videoEle = videoEle
|
|
|
- }}
|
|
|
- onTimeupdate={(e: Event) => {
|
|
|
- const videoEle = e.target as unknown as HTMLVideoElement
|
|
|
- m.currentTime = videoEle.currentTime
|
|
|
- }}
|
|
|
- onPlay={() => {
|
|
|
- // 播放
|
|
|
- m.paused = false
|
|
|
- if (m.muted){
|
|
|
- m.muted = false
|
|
|
- m.videoEle.pause()
|
|
|
- }
|
|
|
+ <div class={styles.playContent}>
|
|
|
+ <div class={styles.coursewarePlay} style={{ width: parentContainer.width }}>
|
|
|
+ <Swipe
|
|
|
+ style={{ height: '100%' }}
|
|
|
+ ref={swipeRef}
|
|
|
+ showIndicators={false}
|
|
|
+ loop={false}
|
|
|
+ vertical
|
|
|
+ lazyRender={true}
|
|
|
+ touchable={false}
|
|
|
+ >
|
|
|
+ {data.itemList.map((m: any, mIndex: number) => {
|
|
|
+ return (
|
|
|
+ <SwipeItem>
|
|
|
+ <>
|
|
|
+ <div
|
|
|
+ class={styles.itemDiv}
|
|
|
+ onClick={() => {
|
|
|
+ clearTimeout(m.timer)
|
|
|
+ activeData.model = !activeData.model
|
|
|
}}
|
|
|
- onPause={() => {
|
|
|
- //暂停
|
|
|
- m.paused = true
|
|
|
- }}
|
|
|
- onEnded={() => addTrainingRecord(m)}
|
|
|
>
|
|
|
- <source src={m.content} type="video/mp4" />
|
|
|
- </video>
|
|
|
- </div>
|
|
|
- <Transition name="bottom">
|
|
|
- {activeData.model && (
|
|
|
- <div class={styles.bottomFixedContainer}>
|
|
|
- <div class={styles.time}>
|
|
|
- <span>{getSecondRPM(m.currentTime)}</span>
|
|
|
- <span>{getSecondRPM(m.duration)}</span>
|
|
|
- </div>
|
|
|
- <div class={styles.slider}>
|
|
|
- {m.duration && (
|
|
|
- <Slider
|
|
|
- buttonSize={16}
|
|
|
- modelValue={m.currentTime}
|
|
|
- min={0}
|
|
|
- max={m.duration}
|
|
|
- />
|
|
|
- )}
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class={styles.actions}>
|
|
|
- <div class={styles.actionBtn}>
|
|
|
- {m.paused ? (
|
|
|
- <img
|
|
|
- src={iconplay}
|
|
|
- onClick={(e: Event) => {
|
|
|
- clearTimeout(m.timer)
|
|
|
- m.videoEle?.play()
|
|
|
- m.paused = false
|
|
|
- m.timer = setTimeout(() => {
|
|
|
- activeData.model = false
|
|
|
- }, 4000)
|
|
|
- }}
|
|
|
- />
|
|
|
- ) : (
|
|
|
- <img
|
|
|
- src={iconpause}
|
|
|
- onClick={(e: Event) => {
|
|
|
- clearTimeout(m.timer)
|
|
|
- m.videoEle?.pause()
|
|
|
- m.paused = true
|
|
|
- }}
|
|
|
+ <video
|
|
|
+ playsinline="false"
|
|
|
+ preload="auto"
|
|
|
+ class="player"
|
|
|
+ poster={iconVideobg}
|
|
|
+ data-vid={m.id}
|
|
|
+ src={m.content}
|
|
|
+ loop={m.loop}
|
|
|
+ autoplay={m.autoplay}
|
|
|
+ muted={m.muted}
|
|
|
+ onLoadedmetadata={async (e: Event) => {
|
|
|
+ const videoEle = e.target as unknown as HTMLVideoElement
|
|
|
+ m.duration = videoEle.duration
|
|
|
+ m.videoEle = videoEle
|
|
|
+ }}
|
|
|
+ onTimeupdate={(e: Event) => {
|
|
|
+ const videoEle = e.target as unknown as HTMLVideoElement
|
|
|
+ m.currentTime = videoEle.currentTime
|
|
|
+ }}
|
|
|
+ onPlay={() => {
|
|
|
+ // 播放
|
|
|
+ m.paused = false
|
|
|
+ if (m.muted) {
|
|
|
+ m.muted = false
|
|
|
+ m.videoEle.pause()
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ onPause={() => {
|
|
|
+ //暂停
|
|
|
+ m.paused = true
|
|
|
+ }}
|
|
|
+ onEnded={() => addTrainingRecord(m)}
|
|
|
+ >
|
|
|
+ <source src={m.content} type="video/mp4" />
|
|
|
+ </video>
|
|
|
+ </div>
|
|
|
+ <Transition name="bottom">
|
|
|
+ {activeData.model && (
|
|
|
+ <div class={styles.bottomFixedContainer}>
|
|
|
+ <div class={styles.time}>
|
|
|
+ <span>{getSecondRPM(m.currentTime)}</span>
|
|
|
+ <span>{getSecondRPM(m.duration)}</span>
|
|
|
+ </div>
|
|
|
+ <div class={styles.slider}>
|
|
|
+ {m.duration && (
|
|
|
+ <Slider
|
|
|
+ buttonSize={16}
|
|
|
+ modelValue={m.currentTime}
|
|
|
+ min={0}
|
|
|
+ max={m.duration}
|
|
|
/>
|
|
|
)}
|
|
|
</div>
|
|
|
+
|
|
|
+ <div class={styles.actions}>
|
|
|
+ <div class={styles.actionBtn}>
|
|
|
+ {m.paused ? (
|
|
|
+ <img
|
|
|
+ src={iconplay}
|
|
|
+ onClick={(e: Event) => {
|
|
|
+ clearTimeout(m.timer)
|
|
|
+ m.videoEle?.play()
|
|
|
+ m.paused = false
|
|
|
+ m.timer = setTimeout(() => {
|
|
|
+ activeData.model = false
|
|
|
+ }, 4000)
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ ) : (
|
|
|
+ <img
|
|
|
+ src={iconpause}
|
|
|
+ onClick={(e: Event) => {
|
|
|
+ clearTimeout(m.timer)
|
|
|
+ m.videoEle?.pause()
|
|
|
+ m.paused = true
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- </Transition>
|
|
|
- </>
|
|
|
- </SwipeItem>
|
|
|
- )
|
|
|
- })}
|
|
|
- </Swipe>
|
|
|
+ )}
|
|
|
+ </Transition>
|
|
|
+ </>
|
|
|
+ </SwipeItem>
|
|
|
+ )
|
|
|
+ })}
|
|
|
+ </Swipe>
|
|
|
|
|
|
- <Transition name="top">
|
|
|
- {activeData.model && (
|
|
|
- <div class={styles.headerContainer} ref={headeRef}>
|
|
|
- <div class={styles.backBtn} onClick={() => goback()}>
|
|
|
- <Icon name={iconBack} />
|
|
|
- 返回
|
|
|
- </div>
|
|
|
- <div class={styles.menu}>{popupData.tabName}</div>
|
|
|
- <div class={styles.nums}>
|
|
|
- 练习次数:{data.trainingTimes}/
|
|
|
- {(data.videoData as any)?.training?.practiceTimes || 0}
|
|
|
+ <Transition name="top">
|
|
|
+ {activeData.model && (
|
|
|
+ <div class={styles.headerContainer} ref={headeRef}>
|
|
|
+ <div class={styles.backBtn} onClick={() => goback()}>
|
|
|
+ <Icon name={iconBack} />
|
|
|
+ 返回
|
|
|
+ </div>
|
|
|
+ <div class={styles.menu}>{popupData.tabName}</div>
|
|
|
+ <div class={styles.nums}>
|
|
|
+ 练习次数:{data.trainingTimes}/
|
|
|
+ {(data.videoData as any)?.training?.practiceTimes || 0}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- </Transition>
|
|
|
+ )}
|
|
|
+ </Transition>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
)
|
|
|
}
|