医学道
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/index/components/videoList.tsx

141 lines
4.5 KiB

import {FC, useEffect, useMemo, useState} from "react";
import Taro, {useDidShow} from "@tarojs/taro";
import {ScrollView, Swiper, SwiperItem, View} from "@tarojs/components";
import {Courses, CoursesKey, publicApi} from "@/api/public";
import VideoCover from "@/components/videoCover/videoCover";
import {formatMinute} from "@/utils/time";
import {userApi} from "@/api";
import Empty from "@/components/empty/empty";
import {Profile} from "@/store";
import LoginView from "@/components/loginView";
interface Props {
categoryKey: CoursesKey
setCategoryKey: (categoryKey: CoursesKey) => void
}
export const VideoList: FC<Props> = ({categoryKey, setCategoryKey}) => {
const [data, setData] = useState<Courses>({
is_required: [],
is_not_required: [],
})
const [page, setPage] = useState(1)
const [records, setRecords] = useState<LearnRecord[]>([])
const {token} = Profile.useContainer()
const {windowHeight, textBarHeight, statusBarHeight} = Taro.getApp().globalData
const pageHeight = windowHeight - textBarHeight - statusBarHeight
function screen(oldData: Curriculum[], data: Curriculum[]): Curriculum[] {
return data.reduce((pre, cur) => {
const index = pre.findIndex(d => d.id === cur.id)
if (index === -1) {
pre.push(cur)
} else {
pre.splice(index, 1, cur)
}
return pre
}, oldData)
}
async function getData() {
try {
const res = await publicApi.course({page: page, pageSize: 10})
const old: Courses = JSON.parse(JSON.stringify(data))
setData({
is_required: screen(old.is_required, res.is_required || []),
is_not_required: screen(old.is_not_required, res.is_not_required || []),
})
} catch (e) {
}
}
async function getRecords() {
try {
const {user_course_records} = await userApi.learningRecord()
setRecords(user_course_records)
} catch (e) {
}
}
function rateOfLearning(id: number, class_hour: number): JSX.Element {
const find = records.find(d => d?.course_id === id)
if (find) {
if (class_hour === find.finished_count) {
return <View></View>
}
return (<View>{`${class_hour}节/已学${find.finished_count}`}</View>)
}
return (<View>{`${class_hour}节/已学0节`}</View>)
}
function rateOfPercent(id: number, class_hour: number): string {
const find = records.find(d => d?.course_id === id)
if (find) {
if (class_hour === find.finished_count) {
return '100%'
}
return ` ${((find.finished_count / class_hour) * 100).toFixed(0)}%`
}
return '0%'
}
const fetchData = () => {
getData().then()
getRecords().then()
}
useDidShow(fetchData)
useEffect(fetchData, [page])
function changeSwiper(e) {
const index = e.detail.current
const categoryKeys: CoursesKey[] = Object.keys(data) as CoursesKey[]
setCategoryKey(categoryKeys[index])
}
const categoryIndex = useMemo(() => {
const index = Object.keys(data).findIndex(d => d === categoryKey)
return index < 0 ? 0 : index
}, [data, categoryKey])
return (
<Swiper style={{height: pageHeight}}
onChange={changeSwiper}
current={categoryIndex}>
{
Object.entries(data).map(([key, value]) => <SwiperItem>
<ScrollView scrollY style={{height: pageHeight}} onScrollToLower={() => setPage(page + 1)} enhanced
showScrollbar={false}>
{
!token && key === 'is_required'
? <LoginView onSuccess={fetchData}/> : value?.length ?
<>
<View className='py-2 flex justify-between flex-wrap'>
{
value?.map(c =>
<VideoCover
thumb={c.thumb}
title={c.title}
id={c.id}
depId={c.id}
key={c.id}
time={formatMinute(c.course_duration)}
content={rateOfLearning(c.id, c.class_hour)}
schedule={`学习进度${rateOfPercent(c.id, c.class_hour)}`}
/>)
}
</View>
<View className='text-center text-muted'></View>
</>
: <Empty name='暂无课程'/>
}
</ScrollView>
</SwiperItem>)
}
</Swiper>
)
}