From 0054b7741d3bc3ca229f8e40fbc2d31cf8337747 Mon Sep 17 00:00:00 2001 From: king <2229249788@qq.com> Date: Wed, 26 Jul 2023 15:41:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A4=E6=96=AD=E8=A7=86=E9=A2=91=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=AE=8C=E6=88=90=EF=BC=8C=E8=87=AA=E5=8A=A8=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E4=B8=8B=E4=B8=80=E4=B8=AA=E8=A7=86=E9=A2=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/curriculum.ts | 2 +- src/api/request.ts | 21 +++-- src/api/user.ts | 15 ++- src/app.tsx | 5 +- src/components/video/video.tsx | 2 +- src/hooks/unique_ident.ts | 7 +- src/pages/business/curHistory/curHistory.tsx | 94 ++++++++++++------- src/pages/business/userInfo/userInfo.tsx | 4 +- .../videoInfo/components/catalogue.tsx | 3 +- .../business/videoInfo/components/course.tsx | 4 +- src/pages/business/videoInfo/videoInfo.tsx | 58 +++++++++++- src/pages/manage/depAdmin/depAdmin.tsx | 23 +++-- 12 files changed, 178 insertions(+), 60 deletions(-) diff --git a/src/api/curriculum.ts b/src/api/curriculum.ts index 9b887b4..4a7221e 100644 --- a/src/api/curriculum.ts +++ b/src/api/curriculum.ts @@ -85,7 +85,7 @@ export const curriculum = { delCur(dep_id: number, course_id: number) { return request(`/api/v1/department/assign/${dep_id}?course_id=${course_id}`, "DELETE") }, - /** 部门课程进度 */ + /** 课程进度 */ course() { return request(`/api/v1/user/courses`, "GET") }, diff --git a/src/api/request.ts b/src/api/request.ts index 9a78e8b..2c15aa8 100644 --- a/src/api/request.ts +++ b/src/api/request.ts @@ -43,6 +43,7 @@ export const ERROR_STATUS: Record = { 'INVALID_DATA': '服务器响应异常~', 'OVERSTEP': '请求越界~' } +let isOverdue = false export function request( url: string, @@ -70,6 +71,9 @@ export function request( }) option.url += parameter } + if (isOverdue) { + isOverdue = false + } data && (option.data = data) return new Promise((resolve, reject) => { Taro.request({ @@ -80,13 +84,16 @@ export function request( if (data?.code === 0 && res.statusCode === 200) { resolve(data.data || []) } else if (res.statusCode === 401) { - Taro.showModal({ - title: "登录过期,需重新登陆", - showCancel: false, - success({confirm}) { - confirm && Taro.reLaunch({url: '/pages/login/login'}) - } - }) + if (!isOverdue) { + isOverdue = true + Taro.showModal({ + title: "登录过期,需重新登陆", + showCancel: false, + success({confirm}) { + confirm && Taro.reLaunch({url: '/pages/login/login'}) + } + }) + } } else { Taro.showToast({title: data.msg || ERROR_STATUS[res.statusCode] || '请求错误~', icon: 'error'}) reject(null) diff --git a/src/api/user.ts b/src/api/user.ts index 98404c5..d08e9cb 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -35,6 +35,16 @@ interface LearningRecord { user_course_records: LearnRecord[] } +interface CourseRecord { + course: Curriculum + data: Record +} + +interface HourCourse{ + courseHour:Record, + date:Record + duration:Record +} export const userApi = { login(code: string) { @@ -64,6 +74,9 @@ export const userApi = { return request>(`/api/v1/course/${category_id}/record`, "GET") }, courseRecord(course_id: number) { - return request>(`/api/v1/course/${course_id}/info`, "GET") + return request(`/api/v1/course/${course_id}/info`, "GET") + }, + hourCourse(course_id: number, unique_ident: number) { + return request(`/api/v1/course/${course_id}/info/${unique_ident}`, "GET") } } diff --git a/src/app.tsx b/src/app.tsx index b350ed5..fcb7a41 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,6 +1,7 @@ import Taro, {useDidShow, useDidHide} from '@tarojs/taro' import './app.scss' import {CustomWrapper} from "@tarojs/components"; +import unique_ident from "@/hooks/unique_ident"; function updateApp() { if (Taro.canIUse('getUpdateManager')) { @@ -32,12 +33,14 @@ function updateApp() { function App(props) { // 可以使用所有的 React Hooks - Taro.useLaunch(()=>{ + Taro.useLaunch(() => { updateApp() const token = JSON.parse(Taro.getStorageSync('profile') || '{}')?.token if (!token) { Taro.reLaunch({url: '/pages/login/login'}) } + unique_ident.put() + unique_ident.del() }) diff --git a/src/components/video/video.tsx b/src/components/video/video.tsx index 2cb9e12..d66dc1f 100644 --- a/src/components/video/video.tsx +++ b/src/components/video/video.tsx @@ -35,8 +35,8 @@ const HVideo: FC = (opt: HVideoOptions) => { } opt.setTime((time: number) => { - video.stop() video.seek(time) + video.play() }) function onEnded() { diff --git a/src/hooks/unique_ident.ts b/src/hooks/unique_ident.ts index dc88d4b..a45172d 100644 --- a/src/hooks/unique_ident.ts +++ b/src/hooks/unique_ident.ts @@ -31,8 +31,13 @@ function put(duration?: number, start_date?: number, upload = true) { } } +function del() { + Taro.removeStorageSync(KEY) +} + export default { set, - put + put, + del } diff --git a/src/pages/business/curHistory/curHistory.tsx b/src/pages/business/curHistory/curHistory.tsx index b949740..3613c92 100644 --- a/src/pages/business/curHistory/curHistory.tsx +++ b/src/pages/business/curHistory/curHistory.tsx @@ -9,44 +9,66 @@ const CurHistory = () => { const [show, setShow] = useState(false) const {course_id, name} = Taro.getCurrentInstance().preloadData as { course_id: number, name: string } const [data, setData] = useState([]) + const [course, setCourse] = useState(null) + const [hours, setHours] = useState(null) + const [durations, setDuration] = useState | null>(null) + const [time, setTime] = useState | null>(null) Taro.useLoad(() => { Taro.setNavigationBarTitle({title: name}) userApi.courseRecord(course_id).then(res => { - setData(Object.values(res)) + setData(Object.values(res.data)) + setCourse(res.course) }) }) - function setHour() { + async function setHour(unique_ident: number) { + const res = await userApi.hourCourse(course_id, unique_ident) + setHours(Object.values(res.courseHour)) + setDuration(res.duration) + setTime(res.date) setShow(true) } + function percent(duration: number): number { + if (!course?.course_duration) return 0 + return Number((duration / course.course_duration * 100).toFixed(2)) + } + + function getTime(id: number): string { + const start = formatDateTime(new Date(time?.[id].start || 0), 'MM/dd HH:mm') + const end = formatDateTime(new Date(time?.[id].end || 0), 'MM/dd HH:mm') + return `${start} - ${end}` + } + + function hourPercent(id: number, duration: number): number { + const viewingTime = durations?.[id] || 0 + console.log(viewingTime,duration) + return Number((viewingTime / duration * 100).toFixed(2)) + } + return ( - + {name} - - { - data.map(d => setHour()} className={styles.recordItem}> - {formatDateTime(new Date(d.start_at), "MM-dd HH:ss")} - {formatDateTime(new Date(d.end_at), "MM-dd HH:ss")} - 观看:{formatMinute(d.duration)} - - ) - } - - + {data.map(d => setHour(d.unique_ident)} className={styles.recordItem}> + {formatDateTime(new Date(d.start_at), "MM/dd HH:ss")} - {formatDateTime(new Date(d.end_at), "MM/dd HH:ss")} + 观看视频:{formatMinute(d.duration)} + + )} { round onAfterLeave={() => setShow(false)}> {show && - - setHour()} className={styles.recordItem}> - 2023-6-19 - - - + + { + hours?.map(d => + + {d.title} + {getTime(d.id)} + + + + ) + } } diff --git a/src/pages/business/userInfo/userInfo.tsx b/src/pages/business/userInfo/userInfo.tsx index 709b422..7c25715 100644 --- a/src/pages/business/userInfo/userInfo.tsx +++ b/src/pages/business/userInfo/userInfo.tsx @@ -2,7 +2,7 @@ import {FC, useState} from "react"; import {Profile} from '@/store' import avatar from "@/static/img/avatar.png" import PopPut from "@/components/popPut/popPut"; -import {Button, CustomWrapper, Input, View} from "@tarojs/components"; +import {Button, Input, View} from "@tarojs/components"; import Taro from "@tarojs/taro"; import {userApi} from "@/api"; import styles from './userInfo.module.scss' @@ -70,11 +70,9 @@ const List = () => { const userInfo: FC = () => { return ( - - ) } diff --git a/src/pages/business/videoInfo/components/catalogue.tsx b/src/pages/business/videoInfo/components/catalogue.tsx index 4998dfe..12aceed 100644 --- a/src/pages/business/videoInfo/components/catalogue.tsx +++ b/src/pages/business/videoInfo/components/catalogue.tsx @@ -23,7 +23,8 @@ const Catalogue: FC = ({data, setHors, id}) => { const [current, setCurrent] = useState(1) function jumCurHistory() { - Taro.navigateTo({url: `/pages/business/curHistory/curHistory?id=${id}&name=${data?.course.title}`}) + Taro.preload({course_id: id, name: data?.course.title}) + Taro.navigateTo({url: `/pages/business/curHistory/curHistory`}) } function tabChange({tab}: OnChangOpt) { diff --git a/src/pages/business/videoInfo/components/course.tsx b/src/pages/business/videoInfo/components/course.tsx index 66b7c39..cf45e06 100644 --- a/src/pages/business/videoInfo/components/course.tsx +++ b/src/pages/business/videoInfo/components/course.tsx @@ -55,7 +55,6 @@ const Course: FC = ({id, courseId, preview, curEnd}: Props) => { /** 进入断点 */ function onBreakpoint(breakpoint: number) { - console.log(breakpoint) if (breakpoint !== time) { setFrequency(count?.[breakpoint] || 1) } @@ -162,7 +161,8 @@ const Course: FC = ({id, courseId, preview, curEnd}: Props) => { const index = old.indexOf(time) old.splice(index, 1) setBreakpoint(old) - Taro.showToast({title: '全部通过'}) + Taro.showToast({title: '答题正确', duration: 1000}) + seek(time) init() } else { Taro.showToast({title: '错误', icon: 'error'}) diff --git a/src/pages/business/videoInfo/videoInfo.tsx b/src/pages/business/videoInfo/videoInfo.tsx index 560f379..7b9a109 100644 --- a/src/pages/business/videoInfo/videoInfo.tsx +++ b/src/pages/business/videoInfo/videoInfo.tsx @@ -6,6 +6,8 @@ import {Profile} from '@/store' import Catalogue from "./components/catalogue"; import Course from "./components/course"; import Taro from "@tarojs/taro"; +import unique_ident from "@/hooks/unique_ident"; + const VideoInfo: FC = () => { const {id, depId} = Taro.getCurrentInstance().preloadData as { id: number, depId: number | null } @@ -18,6 +20,10 @@ const VideoInfo: FC = () => { if (res) { setData(res) } + /** 用于自动播放 判断当前课程是否完成 */ + if (playId) { + currentVideo() + } } function setHors(is_complete: boolean, play_id: number) { @@ -29,12 +35,62 @@ const VideoInfo: FC = () => { getData() }) + /** 播放下一个视频 */ + function playNext() { + const flats: Hour[] = Object.values(data?.hours || {}).flat(Infinity) as Hour[] + if (playId === flats.at(-1)?.id) { + 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 + } + } + } + + /** + * 判断当前课程是否完成 + */ + function currentVideo() { + const courseHourRecordsFinish = data?.learn_hour_records.find(d => d.id === playId)?.courseHourRecordsFinish + if (typeof courseHourRecordsFinish === 'number') { + if (courseHourRecordsFinish === 1) { + playNext() + } else { + Taro.showModal({ + title: '有考卷还未完成', + content: '未完成考卷不能播放下一个视频', + confirmText: '考试', + success({confirm}) { + confirm && Taro.navigateTo({url: `/pages/business/test/test?testId=${playId}`}) + } + }) + } + } + } + Taro.useDidShow(() => { if (data) { - getData() + getData().then() } }) + Taro.useUnload(unique_ident.put) + + return ( diff --git a/src/pages/manage/depAdmin/depAdmin.tsx b/src/pages/manage/depAdmin/depAdmin.tsx index b7fe5eb..c2349d4 100644 --- a/src/pages/manage/depAdmin/depAdmin.tsx +++ b/src/pages/manage/depAdmin/depAdmin.tsx @@ -156,13 +156,19 @@ const DepAdmin: FC = () => { } function userManagesSheet(user: User) { + const itemList = [ + '修改', + '删除', + "日学习记录", + ] + if (user.role_type === 1) { + itemList.push('取消管理员') + } else if (user.role_type === 0) { + itemList.push('设置为管理员') + } + Taro.showActionSheet({ - itemList: [ - '修改', - '删除', - '设置为管理员', - "日学习记录" - ], + itemList, success({tapIndex}) { switch (tapIndex) { case 0: @@ -172,10 +178,10 @@ const DepAdmin: FC = () => { delUser(user.id) break case 2: - setRoleType(user) + Taro.navigateTo({url: `/pages/manage/college/college?id=${user.id}&name=${user.name}`}) break case 3: - Taro.navigateTo({url: `/pages/manage/college/college?id=${user.id}&name=${user.name}`}) + setRoleType(user) break } } @@ -235,6 +241,7 @@ const DepAdmin: FC = () => { leftImage={d.avatar} title={d.name} onClick={() => userManagesSheet(d)} + content={['学员', '管理员', '超级管理员'][d.role_type]} />) }