医学道
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.
 
 
 
video/src/pages/business/videoInfo/components/course.tsx

171 lines
4.8 KiB

import {CoverView, ScrollView, Text, View} from "@tarojs/components";
import {FC, useEffect, useState} from "react";
import HVideo from "@/components/video/video";
import {curriculum, HourPlayData} from "@/api";
import {Profile} from '@/store'
import Taro from "@tarojs/taro";
import Judge from "@/components/topic/judge";
import unique_ident from "@/hooks/unique_ident";
import MyButton from "@/components/button/MyButton";
import {formatMinute} from "@/utils/time";
import CustomPageContainer from "@/components/custom-page-container/custom-page-container";
import Single from "@/components/topic/single";
interface Props {
id: number,
courseId: number
preview: boolean
curEnd: (test?: boolean) => void
}
let seek: (time: number) => void
const Course: FC<Props> = ({id, courseId, preview, curEnd}) => {
const [breakpoint, setBreakpoint] = useState<number[]>([]) // 断点
const [show, setShow] = useState(false) // 题
const [data, setData] = useState<HourPlayData | null>(null)
const [examAll, setExamAll] = useState<Record<number, (ShareSubject | Multi)[]>>([]) // 题库
const [time, setTime] = useState<number>(0) // 进入断点的时间
const [validate, setValidate] = useState(false) // 开启验证
const [record, setRecord] = useState<boolean[]>([]) // 考题记录
const [testId, setTestId] = useState<number | null>(null)
const {user} = Profile.useContainer()
async function onEnded() {
const startRecording = unique_ident.get()
startRecording && await curriculum.curEnd(courseId, id, {...startRecording, duration: data?.duration!}) // 结束
unique_ident.remove()
if (testId) {
if (preview) { // 预览
Taro.showModal({
title: "是否前往考试",
success({confirm}) {
if (confirm) {
curEnd(true)
Taro.navigateTo({url: `/pages/business/test/test?testId=${testId}`})
} else {
curEnd()
}
}
})
return
}
Taro.navigateTo({url: `/pages/business/test/test?testId=${testId}`})
curEnd(true)
} else {
curEnd()
}
}
/** 进入断点 */
function onBreakpoint(breakpoint: number) {
setTime(breakpoint)
setShow(true)
}
async function getData() {
unique_ident.put(id, Date.now())
const res = await curriculum.hourPlay(courseId, id)
if (res) {
setData(res)
setBreakpoint(res.timeList)
setExamAll(res.hourExamQuestions || [])
setTestId(res?.hour_test?.id || null)
}
}
useEffect(() => {
init()
getData()
}, [id])
function init(show = true) {
show && setShow(false)
setValidate(false)
setRecord([])
setTime(0)
}
useEffect(() => {
if (!record.length) return;
const pass = record.every(d => d)
/** 考题正确 */
const {id: question_id, question_type} = examAll?.[time]?.[0]
curriculum.answerRecord(id, {
is_pass: pass,
user_id: user?.id!,
time: time,
question_type,
question_id
}).then()
/** 删除断点 */
const old: number[] = JSON.parse(JSON.stringify(breakpoint))
const index = old.indexOf(time)
old.splice(index, 1)
setBreakpoint(old)
if (pass) {
seek(time)
init()
}
}, [record])
function videoSeek(fn: (time: number) => void) {
seek = fn
}
return (
<>
<HVideo
duration={data?.duration || 0}
preview={preview}
src={data?.url || ''}
onEnded={onEnded}
breakpoint={breakpoint}
onBreakpoint={onBreakpoint}
setTime={videoSeek}
>
{/*<CoverView className='single-cover'>*/}
{/* <Single/>*/}
{/*</CoverView>*/}
</HVideo>
<CustomPageContainer show={show} position='bottom'>
<View>
<View className='text-center mt-2 text-muted'>
<Text className='mr-2'>{formatMinute(time)}</Text>
</View>
{
examAll?.[time]?.slice(0, 1)?.map((d) =>
<ScrollView style='height:60vh' scrollY key={d.id}>
{d.question_type === 2 &&
<Judge
data={d as ShareSubject}
validate={validate}
onAnswer={(isAnswer) => setRecord([isAnswer])}
/>}
</ScrollView>)
}
<View>
<View className='statistics'>
{
record.length > 0
? <MyButton fillet onClick={() => {
init();
seek(time)
}}></MyButton>
: <MyButton fillet onClick={() => setValidate(true)}></MyButton>
}
</View>
</View>
</View>
</CustomPageContainer>
</>
)
}
export default Course