diff --git a/src/api/manage.ts b/src/api/manage.ts index 712e3b3..a9e3fd5 100644 --- a/src/api/manage.ts +++ b/src/api/manage.ts @@ -105,8 +105,8 @@ export const ManageApi = { return request(`/api/v1/department/${data.id}/courses?page=${data.page}&size=${data.size}`, "GET") }, /** 未添加课程 */ - optionalCur(dep_id: number, category_id: number) { - return request(`/api/v1/department/${dep_id}/optional?category_id=${category_id}`, "GET") + optionalCur(dep_id: number) { + return request(`/api/v1//choose/${dep_id}/index`, "GET") }, addCur(data: AddCurProps) { return request('/api/v1/course/user', "POST", data) diff --git a/src/api/user.ts b/src/api/user.ts index 25cdf06..fd2a121 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -26,10 +26,6 @@ interface CheckoutData { company: Company } -interface DepListData { - departments: Department[] - user: User -} interface LearningRecord { user_course_records: LearnRecord[] @@ -64,10 +60,6 @@ export const userApi = { putName(id: number, name: string) { return request(`/api/v1/auth/login/${id}`, "PUT", {name}) }, - /** 所属部门 */ - depList() { - return request(`/api/v1/user/detail`, "GET") - }, code(catch_key: string) { return request<{ code: Code }>(`/api/v1/auth/login/code`, "POST", {openid: catch_key}) }, @@ -75,8 +67,8 @@ export const userApi = { return request(`/api/v1/user/record/course`, "GET", courseId ? {courseId} : {}) }, /** 学习记录 */ - record(category_id: number) { - return request>(`/api/v1/course/${category_id}/record`, "GET") + record() { + return request<{course:HourHistory[],durations:Record}>(`/api/v1/category/history`, "GET") }, courseRecord(course_id: string) { return request(`/api/v1/course/${course_id}/info`, "GET") @@ -92,6 +84,8 @@ export const userApi = { }, /**获取指定学员指定时间学习记录 */ statistics(user_id: string, data: StatisticsParam) { - return request<{data:Record}>(`/api/v1/statistics/statistics/${user_id}?start_time=${data.start_time}&end_time=${data.end_time}`, "GET") + return request<{ + data: Record + }>(`/api/v1/statistics/statistics/${user_id}?start_time=${data.start_time}&end_time=${data.end_time}`, "GET") } } diff --git a/src/components/lineChart/lineChart.module.scss b/src/components/lineChart/lineChart.module.scss index e8f31d7..553911a 100644 --- a/src/components/lineChart/lineChart.module.scss +++ b/src/components/lineChart/lineChart.module.scss @@ -4,6 +4,22 @@ justify-content: left; flex-wrap: nowrap; height: 420px; + position: relative; + margin-top: 30rpx; +} + +.empty { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + border-radius: 10rpx; + color: #00D6AC; + display: flex; + justify-content: center; + align-items: center; + background: rgba(#fff, .9); } .columnBox { diff --git a/src/components/lineChart/lineChart.tsx b/src/components/lineChart/lineChart.tsx index 9dac5bf..c5d9521 100644 --- a/src/components/lineChart/lineChart.tsx +++ b/src/components/lineChart/lineChart.tsx @@ -13,31 +13,39 @@ interface Props { const height = 180 const LineChart: FC = ({data}) => { - const [maxHeight, setMaxHeight] = useState(0) + const [maxHeight, setMaxHeight] = useState({time: '', value: 0}) const [lineChartList, setLineChartList] = useState(data) useEffect(() => { setLineChartList(data) setMaxHeight(data.reduce((pre, cur) => { - return Math.max(pre, cur.value) - }, 0)) + if (cur.value > pre.value) { + return cur + } + return pre + }, maxHeight)) }, [data]) return ( - - - { - lineChartList.map(d => - - - {d.value} - - {d.time} - - ) - } - - + <> + + {maxHeight.time}日最努力,学习了{maxHeight.value}分钟 + + {!maxHeight.value && 暂无数据} + { + lineChartList.map(d => + + + {d.value} + + {d.time} + + ) + } + + + ) } diff --git a/src/components/video/video.tsx b/src/components/video/video.tsx index 4afa044..cdf0056 100644 --- a/src/components/video/video.tsx +++ b/src/components/video/video.tsx @@ -13,7 +13,8 @@ const HVideo: FC = (opt: HVideoOptions) => { try { video = Taro.createVideoContext('myVideo') - } catch (e) {} + } catch (e) { + } function onTimeUpdate(event: BaseEventOrig) { // if (opt.preview) return; @@ -57,10 +58,12 @@ const HVideo: FC = (opt: HVideoOptions) => { unique_ident.put(Number(currentTime.toFixed(2)), Date.now()) }) - Taro.useDidShow(()=>{ - if(!video){ + Taro.useDidShow(() => { + if (!video) { video = Taro.createVideoContext('myVideo') - video.play() + if (currentTime && currentTime < opt.duration - deviation) { + video.play() + } } }) diff --git a/src/pages/business/history/components/CategoryTabs.tsx b/src/pages/business/history/components/CategoryTabs.tsx deleted file mode 100644 index 27d452a..0000000 --- a/src/pages/business/history/components/CategoryTabs.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import {FC, useState} from "react"; -import {View} from "@tarojs/components"; -import {publicApi} from "@/api/public"; -import Taro from "@tarojs/taro"; -import Tabs, {OnChangOpt, TabList} from "@/components/tabs/tabs"; - -interface Props { - changeTabs: (id: number) => void -} - -const CategoryTabs: FC = ({changeTabs}) => { - const [tabs, setTabs] = useState([]) - - async function getData() { - const res = await publicApi.category() - const data = Object.values(res.categories).reduce((pre, cur) => { - pre.push(...cur) - return pre - }, []).map(d => ({title: d.name, value: d.id})) - setTabs(data) - changeTabs(data[0].value as number) - } - - function onChange(data: OnChangOpt) { - changeTabs(data.tab?.value as number) - } - - Taro.useLoad(getData) - return ( - - - - ) -} -export default CategoryTabs diff --git a/src/pages/business/history/history.tsx b/src/pages/business/history/history.tsx index 284c539..76245e4 100644 --- a/src/pages/business/history/history.tsx +++ b/src/pages/business/history/history.tsx @@ -1,40 +1,44 @@ import {Image, Text, View} from "@tarojs/components"; -import CategoryTabs from "@/pages/business/history/components/CategoryTabs"; import styles from './history.module.scss' import Taro from "@tarojs/taro"; -import {userApi} from "@/api"; -import {useState} from "react"; +import {useEffect, useState} from "react"; import {formatMinute} from "@/utils/time"; import Empty from "@/components/empty/empty"; +import {userApi} from "@/api"; const History = () => { const [data, setData] = useState([]) + const [durations, setDurations] = useState>({}) - async function getData(id: number) { - const res = await userApi.record(id) - setData(Object.values(res)) + async function getData() { + const res = await userApi.record() + setData(res.course) + setDurations(res.durations) } function jump(course_id: number) { Taro.navigateTo({url: `/pages/business/curHistory/curHistory?course_id=${course_id}`}) } + useEffect(() => { + getData() + }, []) + return ( - - {data.length ? data.map((d, index) => - jump(d.course_id)}> + jump(d.userCourseRecord.course_id)}> - - 共{d.total_hour_count}节/已学{d.finished_count}节 + + 共{d.userCourseRecord.hour_count}节/已学{d.userCourseRecord.finished_count}节 - {d.course.title} + {d.title} - 观看{formatMinute(d.duration)} - 学习进度:{(d.finished_count / d.total_hour_count * 100).toFixed(0)}% + 观看{formatMinute(durations[d.id])} + 学习进度:{(d.userCourseRecord.finished_count / d.userCourseRecord.hour_count * 100).toFixed(0)}% ) : } diff --git a/src/pages/business/videoInfo/components/course.tsx b/src/pages/business/videoInfo/components/course.tsx index 10c6425..b6d7d46 100644 --- a/src/pages/business/videoInfo/components/course.tsx +++ b/src/pages/business/videoInfo/components/course.tsx @@ -107,14 +107,7 @@ const Course: FC = ({id, courseId, preview, curEnd}: Props) => { setValidate(false) setNewRecord([]) setTime(0) - - if (process.env.TARO_ENV === 'h5') { - setTimeout(() => { - setIndex(0) - }, 200) - } else { - setIndex(0) - } + setIndex(0) } /** 再来一次 */ @@ -219,7 +212,7 @@ const Course: FC = ({id, courseId, preview, curEnd}: Props) => { style={{height: "60vh"}} snapToEdge current={index} - onChange={(e) => setIndex(e.detail.current)}> + onChange={(e) => setIndex(e.detail.current ?? index)}> {examAll?.[time]?.map((d) => diff --git a/src/pages/business/videoInfo/videoInfo.tsx b/src/pages/business/videoInfo/videoInfo.tsx index 3130cd4..5d5286f 100644 --- a/src/pages/business/videoInfo/videoInfo.tsx +++ b/src/pages/business/videoInfo/videoInfo.tsx @@ -7,6 +7,7 @@ import Course from "./components/course"; import Taro from "@tarojs/taro"; import eventsIndex from "@/hooks/eventsIndex"; import {formatMinute} from "@/utils/time"; +import unique_ident from "@/hooks/unique_ident"; const VideoInfo: FC = () => { const {id, depId} = Taro.getCurrentInstance()?.router?.params as any @@ -15,20 +16,20 @@ const VideoInfo: FC = () => { const [preview, setPreview] = useState(false) const [playing, setPlaying] = useState(false) - const getData = useCallback(async () => { + const getData = useCallback(async (playing: boolean) => { const res = await curriculum.courseDep(id, depId) if (res) { setData(res) } - if (playId) { // 用于自动播放 判断当前课程是否完成 - currentVideo(res) + if (playId != null) { // 用于自动播放 判断当前课程是否完成 + currentVideo(res, playing) } - }, [playing]) + }, [playing, playId]) - const curEnd = useCallback(() => { + const curEnd = () => { setPlaying(false) - getData().then() - }, [data, playing, playId]) + getData(false).then() + } function setHors(is_complete: boolean, play_id: number) { setPlaying(true) @@ -37,7 +38,7 @@ const VideoInfo: FC = () => { } useEffect(() => { - getData() + getData(false) }, [id]) @@ -71,7 +72,7 @@ const VideoInfo: FC = () => { /** * 判断当前课程是否完成 */ - const currentVideo = useCallback((data: CourseDepData) => { + 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) { @@ -89,12 +90,16 @@ const VideoInfo: FC = () => { }) } } - }, [playId, data]) + }, [playId, data, playing]) Taro.useDidShow(() => { - data && getData() + data && getData(playing) }) + + Taro.useUnload(() => { + unique_ident.del() + }) return ( <> diff --git a/src/pages/manage/addCur/addCur.tsx b/src/pages/manage/addCur/addCur.tsx index 1260efe..0e5a50d 100644 --- a/src/pages/manage/addCur/addCur.tsx +++ b/src/pages/manage/addCur/addCur.tsx @@ -1,9 +1,7 @@ -import {CustomWrapper, View} from "@tarojs/components"; +import {View} from "@tarojs/components"; import {getCurrentInstance} from "@tarojs/runtime"; import {ManageApi} from "@/api/manage"; import React, {FC, useEffect, useState} from "react"; -import Tabs, {TabList} from "@/components/tabs/tabs"; -import {Category, publicApi} from "@/api/public"; import Taro from "@tarojs/taro"; import VideoCover from "@/components/videoCover/videoCover"; import Empty from "@/components/empty/empty"; @@ -16,50 +14,24 @@ interface AddProps { const AddCur = () => { const {id} = getCurrentInstance()?.router?.params as { id: string } - const [category, setCategory] = useState([]) - const [categoryId, setCategoryId] = useState(0) - const [dataMap, setDataMap] = useState>(new Map()) + const [data, setData] = useState([]) - async function getCategory() { + async function getData() { try { - const data: (TabList)[] = [] - const {categories} = await publicApi.category() - Object.values(categories).map(d => { - data.push(...d.map>(c => ({title: c.name, value: c.id}))) - }) - setCategory(data) - setCategoryId(data[0].value as number) + const res = await ManageApi.optionalCur(Number(id)) + if (res.length) { + setData(res) + } } catch (e) { - } - } - - async function getData() { - if (categoryId !== null) { - const res = await ManageApi.optionalCur(Number(id), categoryId) - const map = new Map(dataMap) - const data = map.get(categoryId) - if (!data) { - map.delete(categoryId) - map.set(categoryId, res) - setDataMap(map) - } else { - res.forEach(d => { - const index = data.findIndex(c => c.id === d.id) - if (index === -1) { - data.push(d) - } else { - data.splice(index, 1, d) - } - }) - map.delete(categoryId) - map.set(categoryId, data) - setDataMap(map) - } } } + useEffect(() => { + getData() + }, []) + const Add: FC = ({cur_id, name, index}) => { function addCur() { Taro.showModal({ @@ -71,14 +43,9 @@ const AddCur = () => { const is_required = confirm ? 1 : 0 Taro.showLoading() await ManageApi.addCur({course_id: [cur_id], dep_id: [Number(id)], is_required}) - const map = new Map(dataMap) - const data = map.get(categoryId!) || [] - if (data) { - data.splice(index, 1) - } - map.delete(categoryId!) - map.set(categoryId!, data) - setDataMap(map) + const oldData: Curriculum[] = JSON.parse(JSON.stringify(data)) + oldData.splice(index, 1) + setData(oldData) Taro.showToast({title: "添加成功"}) } catch (e) { } @@ -92,22 +59,12 @@ const AddCur = () => { ) } - useEffect(() => { - getCategory().then() - }, []) - - useEffect(() => { - getData().then() - }, [categoryId]) return ( - - - setCategoryId(data.tab?.value as number)} current={categoryId}/> - + <> { - (categoryId && dataMap.get(categoryId)?.length) ? + data.length ? - {dataMap.get(categoryId)?.map((d, index) => ( + {data?.map((d, index) => ( { : } - + ) } diff --git a/src/pages/manage/addStudent/addStudent.tsx b/src/pages/manage/addStudent/addStudent.tsx index e2ae87c..4f017e2 100644 --- a/src/pages/manage/addStudent/addStudent.tsx +++ b/src/pages/manage/addStudent/addStudent.tsx @@ -37,6 +37,12 @@ const AddStudent = () => { return } } + + if (!depIds.length) { + Taro.showToast({title: "请选择部门", icon: 'error'}) + return + } + Taro.showLoading() try { if (params.id) { @@ -80,7 +86,7 @@ const AddStudent = () => { Taro.useDidShow(() => { const newDepIds = storageDep.get() - setDepIds( newDepIds.length ?newDepIds: depIds) + setDepIds(newDepIds.length ? newDepIds : depIds) }) return ( @@ -113,7 +119,7 @@ const AddStudent = () => { - + ) diff --git a/src/pages/manage/depAdmin/depAdmin.tsx b/src/pages/manage/depAdmin/depAdmin.tsx index ecb4849..f15061c 100644 --- a/src/pages/manage/depAdmin/depAdmin.tsx +++ b/src/pages/manage/depAdmin/depAdmin.tsx @@ -109,6 +109,7 @@ const DepAdmin: FC = () => { sort: manages.length, }) } + getData() setShow(false) } catch (e) { Taro.showToast({title: '操作失败', icon: 'error'}) @@ -131,7 +132,6 @@ const DepAdmin: FC = () => { return ( <> - {manages.map(d => { Taro.navigateTo({url: "/pages/manage/addCur/addCur?id=" + id}) } - Taro.useDidShow(() => getData()) + useEffect(() => { + getData() + }, []) + useReachBottom(() => { if (data.length < total) { getData(true) @@ -79,7 +82,7 @@ const DepCur: FC = () => { { data.length ? - data.map(d => + data.map(d => {d.title} diff --git a/src/pages/manage/meetings/meetings.tsx b/src/pages/manage/meetings/meetings.tsx index 4fb31f0..a416bda 100644 --- a/src/pages/manage/meetings/meetings.tsx +++ b/src/pages/manage/meetings/meetings.tsx @@ -61,10 +61,9 @@ const MeetingsConfig: FC = () => { { meeting.length ? meeting.map((d, index) => - jumpInfo(d.id)}> + Date.now() < d.estimate_end_time && jumpInfo(d.id)}> {d.name} {formatDate(new Date(d.estimate_start_time), "MM-dd")} 至 {formatDate(new Date(d.estimate_start_time), "MM-dd")} - {Date.now() > d.estimate_end_time && 已过期} del(d.id, index)}>删除 diff --git a/src/pages/manage/selectDep/selectDep.tsx b/src/pages/manage/selectDep/selectDep.tsx index 0b0e997..eb7597a 100644 --- a/src/pages/manage/selectDep/selectDep.tsx +++ b/src/pages/manage/selectDep/selectDep.tsx @@ -16,15 +16,21 @@ const SelectDep: FC = () => { curriculum.department().then(res => { setDeps(res.data) }) - setIds(JSON.parse(depIds)) }, []) const onChange = useCallback((id: number) => { - setIds([ - ...ids, - id - ]) + const index = ids.indexOf(id) + if (index === -1) { + setIds([ + ...ids, + id + ]) + } else { + const oldIds: number[] = JSON.parse(JSON.stringify(ids)) + oldIds.splice(index, 1) + setIds(oldIds) + } }, [ids]) function ok() { @@ -38,7 +44,7 @@ const SelectDep: FC = () => { return ( - {deps.map(d => onChange(d.id)}> + {deps.map(d => onChange(d.id)}> { const path = encodeURIComponent("/pages/meeting/meeting") const params = Taro.getCurrentInstance().router?.params as { id: string | undefined } const [manages, setManages] = useState([]) - const [start, setStart] = useState(formatDate(new Date(), "YY-MM-dd hh:00:00")) - const [end, setEnd] = useState(formatDate(new Date(), "YY-MM-dd 18:00:00")) + const [start, setStart] = useState(formatDate(new Date(new Date().getTime() + 24 * 60 * 60 * 1000), "YY-MM-dd hh:00:00")) + const [end, setEnd] = useState(formatDate(new Date(new Date().getTime() + 24 * 60 * 60 * 1000), "YY-MM-dd 18:00:00")) const [depid, setDepid] = useState(null) const [imgUrl, setImgUrl] = useState('') const [name, setName] = useState('') @@ -277,7 +277,8 @@ const SpotMeeting: FC = () => { - {!params.id && 历史列表 } + {!params.id && 历史列表 } diff --git a/src/pages/manage/userInfo/userInfo.tsx b/src/pages/manage/userInfo/userInfo.tsx index 21a910b..2157018 100644 --- a/src/pages/manage/userInfo/userInfo.tsx +++ b/src/pages/manage/userInfo/userInfo.tsx @@ -37,6 +37,7 @@ const UserInfo: FC = () => { const {userId} = Taro.getCurrentInstance().router?.params as { userId: string } const [data, setData] = useState(null) const [lineData, setLineData] = useState([]) + const router = Taro.useRouter() const {user} = Profile.useContainer() function setRoleType() { @@ -69,9 +70,11 @@ const UserInfo: FC = () => { title: '是否确认删除', async success({confirm}) { if (confirm) { - await ManageApi.del(userId) - Taro.showToast({title: '删除成功'}) - Taro.navigateBack() + try { + await ManageApi.del(userId) + Taro.showToast({title: '删除成功'}) + Taro.navigateBack() + } catch (e) {} } } }) @@ -98,6 +101,14 @@ const UserInfo: FC = () => { }) }, []) + Taro.useDidShow(() => { + if (data) { + userApi.info(router.params.userId!).then(res => { + setData(res) + }) + } + }) + return ( @@ -106,7 +117,7 @@ const UserInfo: FC = () => { 总共学习 - {lineData.reduce((pre, cur) => pre + cur.value, 0)} + {lineData.reduce((pre, cur) => pre + cur.value, 0)} 分钟 diff --git a/types/user.d.ts b/types/user.d.ts index df569f7..9231255 100644 --- a/types/user.d.ts +++ b/types/user.d.ts @@ -78,19 +78,20 @@ interface CueStats { /** 课时学习记录 */ -interface HourHistory { - id: number; - duration: number; - course: Curriculum; - user_id: number; - created_date: string; - start_at: string; - end_at: string; - course_id: number; - hour_id: number; - unique_ident: number; - total_hour_count: number; - finished_count: number; +interface HourHistory extends Curriculum { + userCourseRecord: { + id: number; + duration: number; + user_id: number; + created_date: string; + start_at: string; + end_at: string; + course_id: number; + hour_id: number; + unique_ident: number; + hour_count: number; + finished_count: number; + } } @@ -98,5 +99,5 @@ interface Offline { depid: number start_time: number end_time: number - path:string + path: string }