main
king 1 year ago
parent ae9de5d810
commit b0cf7f4496
  1. 2
      src/components/lineChart/lineChart.module.scss
  2. 7
      src/components/lineChart/lineChart.tsx
  3. 2
      src/components/topic/topic.scss
  4. 3
      src/pages/business/curHistory/curHistory.config.ts
  5. 16
      src/pages/business/curHistory/curHistory.tsx
  6. 28
      src/pages/business/videoInfo/components/catalogue.tsx
  7. 2
      src/pages/business/videoInfo/components/hours.tsx
  8. 3
      src/pages/business/videoInfo/videoInfo.scss
  9. 4
      src/pages/manage/addCur/addCur.module.scss
  10. 4
      src/pages/manage/addCur/addCur.tsx
  11. 3
      src/pages/manage/addStudent/addStudent.scss
  12. 6
      src/pages/manage/addStudent/addStudent.tsx
  13. 11
      src/pages/manage/courseAdmin/components/search.tsx
  14. 6
      src/pages/manage/courseAdmin/courseAdmin.module.scss
  15. 5
      src/pages/manage/courseAdmin/courseAdmin.tsx
  16. 7
      src/pages/manage/selectDep/selectDep.tsx
  17. 2
      src/static/css/module.scss

@ -39,7 +39,7 @@
.line {
width: 1rpx;
background: #ddd;
background: #F2F8F6;
height: 100%;
margin-bottom: 10px;
}

@ -30,15 +30,14 @@ const LineChart: FC<Props> = ({data}) => {
return (
<>
<ScrollView scrollX={!!maxHeight.value}>
<View style={{marginBottom: '30px'}}>{maxHeight.time}{formatMinute(maxHeight.value)}</View>
<View style={{marginBottom: '30px'}}>{maxHeight.time}{formatMinute(maxHeight.value)}</View>
<View className={style.lineChart}>
{!maxHeight.value && <View className={style.empty}></View>}
{
!!maxHeight.value && lineChartList.map(d => <View key={d.time}>
<View className={style.columnBox} style={{width: "100px"}}>
<View className={style.line}
style={{height: height - 10 - (d.value / maxHeight.value * height) + "px"}}></View>
<View>{formatMinute(d.value)}</View>
<View className={style.line} style={{height: height - 10 - (d.value / maxHeight.value * height) + "px"}}></View>
{d.value > 0 && <View>{formatMinute(d.value)}</View>}
<View className={style.column} style={{height: d.value / maxHeight.value * height + "px"}}> </View>
<View>{d.time}</View>
</View>

@ -9,7 +9,7 @@
background: #45D4A8;
border-radius: 10rpx;
color: #fff;
padding: 0 10rpx;
padding: 3rpx 10rpx;
font-size: 26rpx;
margin-right: 20rpx;
}

@ -1,3 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '课程学习记录'
navigationBarTitleText: '课程学习记录',
onReachBottomDistance: 30
})

@ -11,19 +11,33 @@ const CurHistory = () => {
const [show, setShow] = useState(false)
const {course_id} = Taro.getCurrentInstance().router?.params as unknown as { course_id: string }
const [data, setData] = useState<HourHistory[]>([])
const [DataAll, setDataAll] = useState<HourHistory[]>([])
const [course, setCourse] = useState<Curriculum | null>(null)
const [hours, setHours] = useState<Hour[] | null>(null)
const [durations, setDuration] = useState<Record<number, number> | null>(null)
const [time, setTime] = useState<Record<number, { start: number, end: number }> | null>(null)
const [page, setPage] = useState(1)
Taro.useLoad(() => {
userApi.courseRecord(course_id).then(res => {
Taro.setNavigationBarTitle({title: res.course.title})
setData(Object.values(res.data))
setDataAll(Object.values(res.data))
setData(Object.values(res.data).slice(0, 10))
setCourse(res.course)
})
})
Taro.useReachBottom(() => {
if (data.length < DataAll.length) {
const page_size = page * 10
setData([
...data,
...DataAll.slice(page_size, page_size + 10)
])
setPage(page + 1)
}
})
async function setHour(unique_ident: number) {
try {
const res = await userApi.hourCourse(course_id, unique_ident)

@ -1,7 +1,7 @@
import {FC, useState} from "react";
import Tabs, {OnChangOpt} from "@/components/tabs/tabs";
import {Image, View} from "@tarojs/components";
import {CourseDepData} from "@/api";
import {CourseDepData, curriculum} from "@/api";
import Collapse from "@/components/collapse/collapse";
import Hours from "@/pages/business/videoInfo/components/hours";
import Taro from "@tarojs/taro";
@ -95,6 +95,7 @@ const Catalogue: FC<Props> = ({data, setHors, id, playId}) => {
function learning() {
const flats: Hour[] = Object.values(data?.hours || {}).flat(Infinity) as Hour[]
if ((data?.learn_hour_records?.length || undefined) == data?.learn_record?.hour_count && flats.length) {
if (flats[0].id === playId) {
videoEvents.setVideoState('play')
@ -106,9 +107,28 @@ const Catalogue: FC<Props> = ({data, setHors, id, playId}) => {
if (data?.learn_hour_records.length) {
const lastTimeId = data.learn_hour_records[data.learn_hour_records.length - 1].id
const lastHours = data.learn_hour_records[data.learn_hour_records.length - 1]
if (lastHours.courseHourRecordsFinish < 1) {
Taro.showModal({
title: '考卷未完成,是否前往',
content: '考卷未完成不能播放下一个视频',
confirmText: '前往考试',
cancelText: '观看视频',
async success({confirm}) {
if (confirm) {
const {hour_test} = await curriculum.hourPlay(lastHours.course_id, lastHours.id)
Taro.navigateTo({url: `/pages/business/test/test?testId=${hour_test?.id}`})
} else {
setHors(true, lastHours.id)
}
}
})
return;
}
for (const [index, flat] of flats.entries()) {
if (flat.id === lastTimeId) {
if (flat.id === lastHours.id) {
const next = flats[index + 1]
if (next) {
if (next.id === playId) {
@ -119,8 +139,6 @@ const Catalogue: FC<Props> = ({data, setHors, id, playId}) => {
}
}
}
} else {
Taro.showToast({title: "无播放视频", icon: 'error'})
}
}

@ -77,7 +77,7 @@ const Hours: FC<Props> = ({data, click, learn_hour_records, playId}) => {
{complete(d.id) === 0 && <View className='font-26 text-danger'></View>}
</View>
{
complete(data?.[index - 1]?.id) == null
complete(data?.[index - 1]?.id) !== 1
&& index !== 0
&& <Image className='lock' src={lock} mode='aspectFit'/>
}

@ -54,7 +54,7 @@
display: flex;
justify-content: space-between;
box-sizing: border-box;
border-bottom: 1px solid #ddd;
border-bottom: 1px solid #F5F8F7;
.text {
width: 600rpx;
@ -63,6 +63,7 @@
.lock {
width: 30rpx;
height: 30rpx;
margin-left: 10rpx;
margin-top: 10rpx;
}

@ -1,7 +1,7 @@
.curBox {
display: flex;
align-items: center;
padding: 30rpx 0;
padding: 30rpx 20rpx;
width: 100%;
border-bottom: 1px solid #F5F8F7;
}
@ -15,7 +15,7 @@
.fixed {
position: fixed;
bottom: 0;
bottom: env(safe-area-inset-bottom);
left: 0;
background: #f1f8f6;
width: 100%;

@ -87,9 +87,9 @@ const AddCur: FC = () => {
<View className='flex flex-wrap bg-white'>
{data?.map((d) =>
<View key={d.id} className={styles.curBox} onClick={() => addCur(d.id)}>
<Radio checked={courseId.includes(d.id)} onClick={() => addCur(d.id)}/>
<Radio checked={courseId.includes(d.id)} onClick={() => addCur(d.id)} color='#45d4a8'/>
<View className='flex'>
<Image src={d.thumb} className={styles.image}/>
<Image fadeIn lazyLoad src={d.thumb} className={styles.image}/>
<View>{d.title}</View>
</View>
</View>

@ -12,6 +12,5 @@
.add {
position: fixed;
width: 710rpx;
bottom: env(safe-area-inset-bottom);
margin-bottom: 30px;
margin-top: 10px;
}

@ -90,7 +90,7 @@ const AddStudent = () => {
})
return (
<View className='bg-white px-2'>
<View className='bg-white px-2 mt-2'>
<Form className='form' onSubmit={submit}>
<View className='item'>
<View></View>
@ -113,13 +113,13 @@ const AddStudent = () => {
<View></View>
<View className='flex align-center' onClick={jumSetDep}>
<View>
{depIds.length ? formatDep() : '选择'}
{depIds.length ? formatDep() : '选择部门'}
</View>
<Icon name='chevron-right'/>
</View>
</View>
<Button className='add button' formType='submit'>{params.id ? '修改' : "新建"}</Button>
<Button className='add button' formType='submit'>{params.id ? '修改学员' : "添加学员"}</Button>
</Form>
</View>
)

@ -70,10 +70,19 @@ export const Search: FC<Props> = ({param, setParam}) => {
<View onClick={() => setShow(true)}>
<Text></Text>
<Image src={screen}
style={{display: 'inline-block', width: '15px', verticalAlign: 'middle', marginLeft: '5px'}}/>
mode='aspectFit'
style={{
display: 'inline-block',
width: '15px',
height: '15px',
verticalAlign: 'middle',
marginLeft: '5px'
}}/>
</View>
</View>
{param.dep_id > 0 && <View className='mt-2'>{deps.find(d => d.id === param.dep_id)?.name}</View>}
<CustomPageContainer show={show} position='top' onClickOverlay={() => setShow(false)}>
<View className={styles.custom}>
{deps.length ?

@ -3,7 +3,6 @@
padding: 24rpx 30rpx;
display: flex;
justify-content: space-between;
align-items: top;
}
.searchInput {
@ -44,7 +43,7 @@
width: 280rpx;
height: 164rpx;
border-radius: 10rpx;
margin: 0 20px;
margin: 0 20px 0 0;
background: #eee;
}
@ -52,7 +51,8 @@
display: flex;
justify-content: space-around;
taro-view-core {
taro-view-core,
View {
padding: 20rpx 0;
flex: 1;
width: 100%;

@ -72,6 +72,7 @@ const CourseAdmin: FC = () => {
Taro.showModal({
title: '删除警告',
content: "删除后所有部门不可查看",
confirmText:'删除',
async success({confirm}) {
if (confirm) {
try {
@ -173,13 +174,13 @@ const CourseAdmin: FC = () => {
{
!batch
&& data.length > 0
&& <View style={{margin: 'auto', padding: '15px'}} onClick={() => setBatch(true)}></View>
&& <View style={{margin: 'auto', padding: '15px'}} onClick={() => setBatch(true)}></View>
}
{
batch && <View className={styles.addBatch}>
<Radio onClick={all} checked={data.length === curs.length}> </Radio>
<Text onClick={() => setBatch(false)}></Text>
<MyButton size='mini' onClick={() => batchChangDep(curs)}>{curs.length}</MyButton>
<MyButton size='mini' onClick={() => batchChangDep(curs)}>{curs.length}</MyButton>
</View>
}
</View>

@ -50,10 +50,6 @@ const SelectDep: FC = () => {
}, [ids])
function ok() {
if (!ids.length) {
Taro.showToast({title: '请选择部门', icon: "error"})
return
}
storageDep.set(ids)
storageDep.setRequired(required)
Taro.navigateBack({delta: 1})
@ -84,7 +80,7 @@ const SelectDep: FC = () => {
return (
<View className='px-2 bg-white'>
{deps.map((d) => <View className='flex align-center' key={d.id} onClick={() => onChange(d.id)}>
<Checkbox value={d.id + ''} checked={ids.includes(d.id)}/>
<Checkbox value={d.id + ''} checked={ids.includes(d.id)} color='#45d4a8'/>
<View style={{flex: 1}}>
<PopPut
key={d.id}
@ -95,6 +91,7 @@ const SelectDep: FC = () => {
params?.required ?
<View className='flex align-center'>
<Switch
color='#45d4a8'
onClick={() => event?.stopImmediatePropagation()}
checked={isRequired(d.id)}
onChange={(e) => requiredChange(d.id, e.detail.value)}/>

@ -32,7 +32,7 @@ taro-button-core::after {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #ddd;
border-bottom: 1px solid #F5F8F7;
height: 80px;
}

Loading…
Cancel
Save