我的和用户设置样式

main
king 1 year ago
parent d1d1dec42e
commit 33abea6a49
  1. 1
      src/api/curriculum.ts
  2. 8
      src/api/manage.ts
  3. 1
      src/api/public.ts
  4. 1
      src/app.config.ts
  5. 6
      src/pages/business/userInfo/userInfo.module.scss
  6. 6
      src/pages/business/userInfo/userInfo.tsx
  7. 75
      src/pages/business/videoInfo/components/ContainDeps.tsx
  8. 13
      src/pages/business/videoInfo/components/catalogue.tsx
  9. 1
      src/pages/business/videoInfo/videoInfo.scss
  10. 4
      src/pages/business/videoInfo/videoInfo.tsx
  11. 7
      src/pages/index/index.tsx
  12. 4
      src/pages/manage/studentRecord/studentRecord.config.ts
  13. 102
      src/pages/manage/studentRecord/studentRecord.tsx
  14. 11
      src/pages/my/components/header/time.tsx
  15. 1
      src/pages/my/my.tsx
  16. 7
      src/static/css/module.scss

@ -44,6 +44,7 @@ export const curriculum = {
courseDep(id: number, depId: number | null) { courseDep(id: number, depId: number | null) {
return request<CourseDepData>(`/api/v1/course/${id}${depId ? `/dep/${depId}` : ''}`, "GET") return request<CourseDepData>(`/api/v1/course/${id}${depId ? `/dep/${depId}` : ''}`, "GET")
}, },
/** 播放 */
hourPlay(courseId: number, id: number) { hourPlay(courseId: number, id: number) {
return request<HourPlayData>(`/api/v1/course/${courseId}/hour/${id}/play`, "GET") return request<HourPlayData>(`/api/v1/course/${courseId}/hour/${id}/play`, "GET")
}, },

@ -111,13 +111,5 @@ export const ManageApi = {
}, },
buy(data_list: number[]) { buy(data_list: number[]) {
return request(`/api/v1/course/buy?data_list=${data_list}`, "POST") return request(`/api/v1/course/buy?data_list=${data_list}`, "POST")
},
/** 课程绑定部门 */
bingDep(dep_id: number) {
return request<Curriculum & { department: Department[] }>(`/api/v1/course/all/bind/${dep_id}`, "GET")
},
/** 课程学员学习记录 */
curLearningRecord(cur_id: number | string,data:{page:number,size:number}) {
return request<CurLearningRecord>(`/api/v1/course/${cur_id}/user/index`, "GET", data)
} }
} }

@ -33,6 +33,7 @@ export type Cur = Category & {
export const publicApi = { export const publicApi = {
/** 分类 */
category() { category() {
return request<CategoryList>('/api/v1/category/all', "GET") return request<CategoryList>('/api/v1/category/all', "GET")
}, },

@ -45,7 +45,6 @@ export default defineAppConfig({
'addStudent/addStudent', 'addStudent/addStudent',
'depCur/depCur', 'depCur/depCur',
'addCur/addCur', 'addCur/addCur',
'studentRecord/studentRecord',
] ]
} }
] ]

@ -15,8 +15,12 @@
background: #45D4A8; background: #45D4A8;
border-radius: 40rpx; border-radius: 40rpx;
color: #fff; color: #fff;
font-size: 32rpx;
}
.buttonFixed{
position: fixed; position: fixed;
bottom:100px; bottom:100px;
left: 30rpx; left: 30rpx;
font-size: 32rpx;
} }

@ -48,20 +48,20 @@ const List = () => {
<PopPut title='手机号' content={user?.phone_number} chevron no_border/> <PopPut title='手机号' content={user?.phone_number} chevron no_border/>
<PopPut title='昵称' content={user?.name} isProp show={show} no_border> <PopPut title='昵称' content={user?.name} isProp show={show} no_border>
<View className='h-6 pt-4 px-3'> <View className='h-6 pt-4 px-3'>
<View className='text-center font-weight'>{name}</View> <View className='text-center font-weigh mb-3'></View>
<Input className='input' <Input className='input'
placeholder='请输入昵称' placeholder='请输入昵称'
onInput={(event) => setName(event.detail.value)} onInput={(event) => setName(event.detail.value)}
value={name} value={name}
/> />
<View className='text-muted mt-2 font-24'>4-20_-</View> <View className='text-muted my-3 font-24'>4-20_-</View>
<Button className={styles.button} onClick={putName}></Button> <Button className={styles.button} onClick={putName}></Button>
</View> </View>
</PopPut> </PopPut>
<PopPut title='解绑微信' onClick={unbind} no_border/> <PopPut title='解绑微信' onClick={unbind} no_border/>
</View> </View>
<Button className={styles.button} onClick={empty}>退</Button> <Button className={`${styles.button} ${styles.buttonFixed}`} onClick={empty}>退</Button>
</> </>
) )
} }

@ -1,75 +0,0 @@
import {FC, useState} from "react";
import {View} from "@tarojs/components";
import {ManageApi} from "@/api/manage";
import {Profile} from '@/store'
import PopPut from "@/components/popPut/popPut";
import Taro from "@tarojs/taro";
interface Props {
cur_id: number
name?: string
}
const Dep: FC<Props> = ({cur_id}: Props) => {
const [bindDep, setBindDep] = useState<Department[]>([])
async function getBind() {
try {
const res = await ManageApi.bingDep(cur_id)
setBindDep(res.department)
} catch (e) {
}
}
function jump(item: Department) {
Taro.showModal({
title: "是否查看" + item.name,
success({confirm}) {
confirm && Taro.navigateTo({url: `/pages/manage/depCur/depCur?id=${item.id}`})
}
})
}
Taro.useDidShow(() => {
getBind()
})
return (<>
{bindDep && <View className='header'>
<View className='font-weight font-26'></View>
{bindDep && bindDep.map(d => (
<PopPut title={d.name} height={40} content={'查看'} onClick={() => jump(d)}/>
))}
</View>
}
</>)
}
const StudentRecord: FC<Props> = ({cur_id, name}: Props) => {
function jump() {
Taro.navigateTo({url: `/pages/manage/studentRecord/studentRecord?cur_id=${cur_id}&name=${name}`})
}
return (
<View className='header'>
<PopPut title={'学员学习记录'} height={40} content={'查看'} onClick={jump}/>
</View>
)
}
const ContainDeps: FC<Props> = ({cur_id,name}: Props) => {
const {user} = Profile.useContainer()
return (
<>
{user?.role_type !== 0 ?
<View>
<Dep cur_id={cur_id}/>
<StudentRecord cur_id={cur_id} name={name}/>
</View>
: null}
</>
)
}
export default ContainDeps

@ -13,16 +13,19 @@ interface Props {
const Catalogue: FC<Props> = ({data}: Props) => { const Catalogue: FC<Props> = ({data}: Props) => {
const {user} = Profile.useContainer() const {user} = Profile.useContainer()
const [current, setCurrent] = useState(1) const [current, setCurrent] = useState(0)
const [tabList, setTabList] = useState<TabList[]>([ const [tabList, setTabList] = useState<TabList[]>([
{title: '介绍', value: 0}, {title: '介绍', value: 0},
{title: '目录', value: 1}, {title: '目录', value: 1},
{title: '评价', value: 2}, // {title: '评价', value: 2},
]) ])
useEffect(() => { useEffect(() => {
if (user?.role_type && user?.role_type > 0) { if (user?.role_type && user?.role_type > 0) {
setTabList([...tabList, {title: '学员管理', value: 3}]) setTabList([
...tabList,
// {title: '部门进度', value: 3}
])
} }
}, []) }, [])
@ -41,7 +44,7 @@ const Catalogue: FC<Props> = ({data}: Props) => {
function complete(id: number): boolean { function complete(id: number): boolean {
return !!data?.learn_hour_records[id]?.is_finished return !!data?.learn_hour_records?.[id]?.is_finished
} }
@ -56,7 +59,7 @@ const Catalogue: FC<Props> = ({data}: Props) => {
<View className='py-2'> <View className='py-2'>
{current === 0 && <View className='short_desc'>{data?.course.short_desc}</View>} {current === 0 && <View className='short_desc'>{data?.course.short_desc}</View>}
{current === 1 && <View> {current === 1 && <View>
<View className='font-weight'></View> <View className='font-weight mb-2'></View>
{data?.chapters.length ? Object.values(data?.chapters || {}).map((d, index) => <View> {data?.chapters.length ? Object.values(data?.chapters || {}).map((d, index) => <View>
<Collapse title={`${index + 1}.${d.name}`}> <Collapse title={`${index + 1}.${d.name}`}>
<> <>

@ -21,6 +21,7 @@
.short_desc { .short_desc {
color: #606563; color: #606563;
line-height: 1.75; line-height: 1.75;
word-break: break-word;
} }
} }

@ -26,11 +26,9 @@ const VideoInfo: FC = () => {
<View className='content'> <View className='content'>
<Image src={data?.course.thumb || ''} className='image' mode='scaleToFill'/> <Image src={data?.course.thumb || ''} className='image' mode='scaleToFill'/>
{/*<ContainDeps cur_id={id} name={data?.course.title}/>*/}
<View className='header'> <View className='header'>
<View className='flex justify-between text-muted'> <View className='flex justify-between text-muted'>
<Text className='font-34 text-warning'>{data?.is_required ? '必修' : '选'}</Text> <Text className='font-34 text-warning'>{data?.is_required ? '必修' : '选'}</Text>
<Text>{data?.course.class_hour}</Text> <Text>{data?.course.class_hour}</Text>
</View> </View>
<View className='font-weight font-40 my-4'>{data?.course.title}</View> <View className='font-weight font-40 my-4'>{data?.course.title}</View>

@ -10,6 +10,7 @@ import {CoursesKey} from "@/api/public";
const Index: FC = () => { const Index: FC = () => {
const globalData = Taro.getApp().globalData
const category: TabList[] = [ const category: TabList[] = [
{title: "必修", value: 'is_required'}, {title: "必修", value: 'is_required'},
{title: "选修", value: 'is_not_required'}, {title: "选修", value: 'is_not_required'},
@ -22,8 +23,12 @@ const Index: FC = () => {
setCategoryId(data.tab?.value as CoursesKey) setCategoryId(data.tab?.value as CoursesKey)
} }
// Taro.showActionSheet({
// alertText: '212',
// itemColor:'red',
// itemList:['删除']
// })
const globalData = Taro.getApp().globalData
return ( return (
<Profile.Provider> <Profile.Provider>
<View className={styles.content} style={`paddingTop:${globalData.statusBarHeight}px`}> <View className={styles.content} style={`paddingTop:${globalData.statusBarHeight}px`}>

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

@ -1,102 +0,0 @@
import {CustomWrapper, Image, Text, View} from "@tarojs/components";
import {FC, useEffect, useState} from "react";
import {getCurrentInstance} from "@tarojs/runtime";
import Taro, {useReachBottom} from "@tarojs/taro";
import {CurLearningRecord, ManageApi} from "@/api/manage";
import '@/pages/manage/studentAdmin/student.scss'
const StudentRecord: FC = () => {
const [page, setPage] = useState(1)
const {cur_id, name} = getCurrentInstance()?.router?.params as { cur_id: string, name: string }
const [data, setData] = useState<CurLearningRecord | null>(null)
const [total, setTotal] = useState(0)
async function getData() {
try {
const res = await ManageApi.curLearningRecord(cur_id, {page, size: 10})
if (!data) {
setData(res)
} else {
const oldData: CurLearningRecord = JSON.parse(JSON.stringify(data))
oldData.data.push(...res.data)
oldData.departments = res.departments
Object.entries(res.user_dep_ids).forEach(([key, value]) => {
oldData.user_dep_ids[key] = value
})
Object.entries(res.user_course_records).forEach(([key, value]) => {
oldData.user_course_records[key] = value
})
Object.entries(res.user_course_hour_user_first_at).forEach(([key, value]) => {
oldData.user_course_hour_user_first_at[key] = value
})
setData(oldData)
}
setTotal(res.total)
} catch (e) {
}
}
function getDep(user_id: number): string {
const cur_ids = data?.user_dep_ids[user_id]
if (cur_ids) {
return cur_ids.map(d => data?.departments[d]).join('、')
}
return ''
}
useReachBottom(() => {
if (data && data.data.length < total) {
setPage(page + 1)
}
})
useEffect(() => {
getData()
}, [page])
Taro.setNavigationBarTitle({title: name})
return (
<CustomWrapper>
{data?.data.map(d => (
<View className='bg-white user'>
<View className='flex mt-3 header p-2 justify-between'>
<View className='flex'>
<Text> {d.id}</Text>
</View>
</View>
<View className='p-2 flex info justify-between'>
<View>
<View className='font-weight my-3'>{d.name}</View>
<View className='flex mb-3'>
<View style='width:80px' className='text-muted'></View>
<View>{['学员', '管理员', '超级管理员'][d.role_type]}</View>
</View>
<View className='flex mb-3'>
<View style='width:80px' className='text-muted'></View>
<View>{d.phone_number}</View>
</View>
<View className='flex mb-3'>
<View style='width:80px' className='text-muted'></View>
<View>{d.email}</View>
</View>
<View className='flex mb-3'>
<View style='width:80px' className='text-muted'></View>
<View>{getDep(d.id)}</View>
</View>
<View className='flex mb-3'>
<View style='width:80px' className='text-muted'></View>
<View>{data?.user_course_records[d.id]?.finished_count || 0}/{data?.course.class_hour}</View>
</View>
</View>
<Image src={d.avatar} mode='widthFix'/>
</View>
<View className='flex justify-between p-2 operation'>
</View>
</View>
))}
</CustomWrapper>
)
}
export default StudentRecord

@ -4,7 +4,7 @@ import curriculum1 from '@/static/img/curriculum1.png'
import curriculum2 from '@/static/img/curriculum2.png' import curriculum2 from '@/static/img/curriculum2.png'
import Taro from "@tarojs/taro"; import Taro from "@tarojs/taro";
import {curriculum} from "@/api"; import {curriculum} from "@/api";
import {useState} from "react"; import {FC, useState} from "react";
import {formatMinute} from "@/utils/time"; import {formatMinute} from "@/utils/time";
import time1 from "@/static/img/time1.png"; import time1 from "@/static/img/time1.png";
import time2 from "@/static/img/time2.png"; import time2 from "@/static/img/time2.png";
@ -17,7 +17,7 @@ interface List {
src: string src: string
} }
const Time = () => { const Time:FC = () => {
const [list, setList] = useState<List[]>([ const [list, setList] = useState<List[]>([
{title: '今日时长', time: '00:00', src: time1}, {title: '今日时长', time: '00:00', src: time1},
{title: '累计时长', time: '00:00', src: time2}, {title: '累计时长', time: '00:00', src: time2},
@ -39,8 +39,7 @@ const Time = () => {
oldList[4].time = stats.required_finished_course_count + stats.nun_required_finished_course_count oldList[4].time = stats.required_finished_course_count + stats.nun_required_finished_course_count
oldList[5].time = stats.total_course_count - (stats.required_finished_course_count + stats.nun_required_finished_course_count) oldList[5].time = stats.total_course_count - (stats.required_finished_course_count + stats.nun_required_finished_course_count)
setList(oldList) setList(oldList)
} catch (e) { } catch (e) {}
}
}) })
@ -51,8 +50,8 @@ const Time = () => {
return ( return (
<View className={'flex justify-between ' + styles.timeBox} key={d.title}> <View className={'flex justify-between ' + styles.timeBox} key={d.title}>
<View> <View>
<View className='font-weight'>{d.title}</View> <View className='font-weight mb-2'>{d.title}</View>
<View className='text-muted'>{d.time}</View> <View className='text-muted font-26'>{d.time}</View>
</View> </View>
<Image src={d.src} mode='aspectFit' className={styles.timeImag}/> <Image src={d.src} mode='aspectFit' className={styles.timeImag}/>
</View> </View>

@ -15,7 +15,6 @@ const My: FC = () => {
<Profile.Provider> <Profile.Provider>
<View className={styles.content} style={`paddingTop:${globalData.statusBarHeight}px`}> <View className={styles.content} style={`paddingTop:${globalData.statusBarHeight}px`}>
<Header/> <Header/>
<View className={styles.ribbon}> <View className={styles.ribbon}>
<Time/> <Time/>
<Service/> <Service/>

@ -4,9 +4,10 @@ page {
} }
.input { .input {
height: 24px; height: 84rpx;
padding: 11px 15px; background: #F5F8F7;
border-bottom: 1px solid #ddd; border-radius:8px;
padding: 0 20px;
} }
.form { .form {

Loading…
Cancel
Save