You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
4.3 KiB
132 lines
4.3 KiB
import {Text, View} from "@tarojs/components";
|
|
import {FC, useCallback, useEffect, useState} from "react";
|
|
import {CourseDepData, curriculum} from "@/api";
|
|
import './videoInfo.scss'
|
|
import Catalogue from "./components/catalogue";
|
|
import Course from "./components/course";
|
|
import Taro from "@tarojs/taro";
|
|
import {formatMinute} from "@/utils/time";
|
|
import videoEvents from "@/hooks/videoEvents";
|
|
import unique_ident from "@/hooks/unique_ident";
|
|
import Img from "@/components/image/image";
|
|
|
|
const VideoInfo: FC = () => {
|
|
const {id, depId} = Taro.getCurrentInstance()?.router?.params as any
|
|
const [data, setData] = useState<CourseDepData | null>(null)
|
|
const [playId, setPlayId] = useState<number | null>(null)
|
|
const [preview, setPreview] = useState(false) // 预览
|
|
const [playing, setPlaying] = useState(false) // 学习中
|
|
|
|
const getData = useCallback(async (playing: boolean) => {
|
|
try {
|
|
const res = await curriculum.courseDep(id, depId)
|
|
res && setData(res)
|
|
playId != null && currentVideo(res, playing) // 用于自动播放 判断当前课程是否完成
|
|
} catch (e) {
|
|
}
|
|
}, [playing, playId])
|
|
|
|
function changeCollect(v: boolean){
|
|
let temp = data
|
|
temp!.course.collect = v
|
|
setData(temp)
|
|
}
|
|
|
|
const curEnd = (test?: boolean) => {
|
|
setPlaying(false)
|
|
if (!test) { // 没有考题才会请求
|
|
getData(false).then()
|
|
}
|
|
}
|
|
|
|
function setHors(preview: boolean, play_id: number) {
|
|
setPlaying(true)
|
|
setPreview(preview)
|
|
setPlayId(play_id)
|
|
}
|
|
|
|
useEffect(() => {
|
|
getData(false).then()
|
|
unique_ident.set(id)
|
|
}, [id])
|
|
|
|
|
|
/** 播放下一个视频 */
|
|
const playNext = useCallback(() => {
|
|
const flats: Hour[] = Object.values(data?.hours || {}).flat(Infinity) as Hour[]
|
|
if (playId === flats?.[flats.length - 1]?.id && !preview) {
|
|
Taro.showModal({title: '当前课程结束'})
|
|
return;
|
|
}
|
|
for (const [index, flat] of flats.entries()) {
|
|
if (flat.id === playId) {
|
|
const next = flats[index + 1]
|
|
if (next) {
|
|
Taro.showModal({
|
|
title: '继续播放下个视频',
|
|
success({confirm}) {
|
|
if (confirm) {
|
|
setPlayId(next.id)
|
|
setPreview(false)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
return
|
|
}
|
|
}
|
|
}, [playId, data, preview])
|
|
|
|
/** 判断当前课程是否完成 */
|
|
const currentVideo = useCallback((data: CourseDepData, playing: boolean) => {
|
|
const courseHourRecordsFinish = data?.learn_hour_records.find(d => d.id === playId)?.courseHourRecordsFinish
|
|
if (typeof courseHourRecordsFinish === 'number') {
|
|
if (courseHourRecordsFinish === 1) {
|
|
if (!playing) {
|
|
playNext()
|
|
}
|
|
} else {
|
|
Taro.showModal({
|
|
title: '有考卷还未完成',
|
|
content: '未完成考卷不能播放下一个视频',
|
|
confirmText: '考试',
|
|
success({confirm}) {
|
|
confirm && Taro.navigateTo({url: `/pages/business/test/test?testId=${playId}`})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}, [playId, data, playing])
|
|
|
|
Taro.useDidShow(() => {
|
|
data && getData(playing)
|
|
})
|
|
|
|
Taro.useUnload(() => {
|
|
videoEvents.videoOff()
|
|
})
|
|
return (
|
|
<View className='content'>
|
|
<View className='content-video'>
|
|
{playId
|
|
? <Course id={playId} courseId={id} curEnd={curEnd} preview={preview}/>
|
|
: <Img width={750} height={500} src={data?.course.thumb || ''} errorType='health'/>}
|
|
</View>
|
|
|
|
<View className='header'>
|
|
<View className='flex justify-between text-muted'>
|
|
<Text className='font-34 text-warning'>{data?.is_required ? '必修' : '选修'}</Text>
|
|
<Text className='font-24'>{data?.course.class_hour}课时</Text>
|
|
</View>
|
|
<View className='font-weight font-36 my-2'>{data?.course.title}</View>
|
|
<View className='text-muted font-26 mt-3'>
|
|
<Text className='mr-2'>时长:{formatMinute(data?.duration || 0)}</Text>
|
|
<Text>学习进度{((data?.learn_hour_records.length || 0) / (data?.course.class_hour || 1) * 100).toFixed(0)}%</Text>
|
|
</View>
|
|
</View>
|
|
<Catalogue data={data} setHors={setHors} id={id} playId={playId} collectUpdate={changeCollect} refresh={() => getData(false)}/>
|
|
</View>
|
|
)
|
|
}
|
|
|
|
export default VideoInfo
|
|
|