feat: 进度查看界面添加了按照进度排序功能

This commit is contained in:
huertian 2025-01-05 19:55:57 +08:00
parent 4406934444
commit e0995a9132
2 changed files with 81 additions and 31 deletions

1
components.d.ts vendored
View File

@ -27,6 +27,7 @@ declare module 'vue' {
WdProgress: typeof import('wot-design-uni/components/wd-progress/wd-progress.vue')['default'] WdProgress: typeof import('wot-design-uni/components/wd-progress/wd-progress.vue')['default']
WdRadio: typeof import('wot-design-uni/components/wd-radio/wd-radio.vue')['default'] WdRadio: typeof import('wot-design-uni/components/wd-radio/wd-radio.vue')['default']
WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default'] WdRadioGroup: typeof import('wot-design-uni/components/wd-radio-group/wd-radio-group.vue')['default']
WdSortButton: typeof import('wot-design-uni/components/wd-sort-button/wd-sort-button.vue')['default']
WdStatusTip: typeof import('wot-design-uni/components/wd-status-tip/wd-status-tip.vue')['default'] WdStatusTip: typeof import('wot-design-uni/components/wd-status-tip/wd-status-tip.vue')['default']
WdStep: typeof import('wot-design-uni/components/wd-step/wd-step.vue')['default'] WdStep: typeof import('wot-design-uni/components/wd-step/wd-step.vue')['default']
WdSteps: typeof import('wot-design-uni/components/wd-steps/wd-steps.vue')['default'] WdSteps: typeof import('wot-design-uni/components/wd-steps/wd-steps.vue')['default']

View File

@ -54,6 +54,7 @@ const handleBeforeToggle: DropMenuItemBeforeToggle = ({ status, resolve }) => {
const expandedCourse = ref(['lesson']) const expandedCourse = ref(['lesson'])
const groupedLessons = ref<{ [key: string]: LessonTask[] }>({}) const groupedLessons = ref<{ [key: string]: LessonTask[] }>({})
const refreshKey = ref(0)
const openLessonDetail = (courseId: number) => { const openLessonDetail = (courseId: number) => {
router.push({ router.push({
@ -97,22 +98,47 @@ const loadLessons = async () => {
return return
} }
const groupData = res.data.content // id
.sort((a: LessonTask, b: LessonTask) => a.id - b.id) let sortedContent = [...res.data.content].sort((a: LessonTask, b: LessonTask) => a.id - b.id)
.reduce((acc: { [key: string]: LessonTask[] }, cur: LessonTask) => {
if (!acc[cur.courseName]) {
acc[cur.courseName] = []
}
acc[cur.courseName].push(cur)
return acc
}, {})
//
const groupData = sortedContent.reduce((acc: { [key: string]: LessonTask[] }, cur: LessonTask) => {
if (!acc[cur.courseName]) {
acc[cur.courseName] = []
}
acc[cur.courseName].push(cur)
return acc
}, {})
//
if (value.value !== 0) {
Object.keys(groupData).forEach(courseName => {
groupData[courseName].sort((a: LessonTask, b: LessonTask) => {
const progressA = calcLessonProgress(a)
const progressB = calcLessonProgress(b)
return value.value === 1
? progressB - progressA //
: progressA - progressB //
})
})
}
console.log('分组后的课程数据:', JSON.stringify(groupData, null, 2))
groupedLessons.value = groupData groupedLessons.value = groupData
expandedCourse.value = Object.keys(groupData).filter(courseName => {
return groupData[courseName].filter((lesson: LessonTask) => const expandedGroups = Object.keys(groupData).filter(courseName => {
calcLessonProgress(lesson) !== 0 && calcLessonProgress(lesson) !== 100 const courses = groupData[courseName]
).length > 0 const hasCompleted = courses.some(lesson => calcLessonProgress(lesson) === 100)
const hasNotStarted = courses.some(lesson => calcLessonProgress(lesson) === 0)
const hasInProgress = courses.some(lesson => {
const progress = calcLessonProgress(lesson)
return progress > 0 && progress < 100
})
return (hasCompleted && hasNotStarted) || hasInProgress
}) })
//
expandedCourse.value = expandedGroups
} catch (err: unknown) { } catch (err: unknown) {
if (err instanceof Error) { if (err instanceof Error) {
toast.error({ msg: err.message }) toast.error({ msg: err.message })
@ -163,19 +189,35 @@ onLoad(() => {
loadLessons() loadLessons()
}) })
const value = ref<number>(0)
//
const handleChange = ({ value: newValue }: { value: number }) => {
console.log('排序值:', newValue)
value.value = newValue
loadLessons().then(() => {
//
refreshKey.value++
})
}
</script> </script>
<template> <template>
<page-wrapper> <page-wrapper>
<div> <div>
<wd-drop-menu v-if="!user.hasRole('teacher')"> <div v-if="!user.hasRole('teacher')" class="flex items-center justify-around gap-4 px-4">
<wd-drop-menu-item v-model="teacherFilterValue" :options="teacherFilterOptions" <wd-drop-menu>
:before-toggle="handleBeforeToggle" /> <wd-drop-menu-item v-model="teacherFilterValue" :options="teacherFilterOptions"
</wd-drop-menu> :before-toggle="handleBeforeToggle" />
</wd-drop-menu>
<view>
<wd-sort-button title="进度" allow-reset v-model="value" @change="handleChange" />
</view>
</div>
<wd-collapse v-model="expandedCourse"> <wd-collapse v-model="expandedCourse">
<wd-status-tip v-if="Object.keys(groupedLessons).length === 0" image="content" tip="当前账号没有分配微课" /> <wd-status-tip v-if="Object.keys(groupedLessons).length === 0" image="content" tip="当前账号没有分配微课" />
<wd-collapse-item v-else v-for="(courses, courseName) in groupedLessons" :name="`${courseName}`" <wd-collapse-item v-else v-for="(courses, courseName) in groupedLessons" :name="`${courseName}`"
:key="courseName"> :key="`${courseName}-${refreshKey}`">
<template #title="{ expanded, disabled, isFirst }"> <template #title="{ expanded, disabled, isFirst }">
<div class="w-full flex justify-between items-center"> <div class="w-full flex justify-between items-center">
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
@ -184,25 +226,31 @@ onLoad(() => {
</p> </p>
<div class="flex items-center gap-1"> <div class="flex items-center gap-1">
<wd-tag v-if="(() => { <wd-tag v-if="(() => {
//
const hasCompleted = courses.some(lesson => calcLessonProgress(lesson) === 100)
const hasNotStarted = courses.some(lesson => calcLessonProgress(lesson) === 0)
if (hasCompleted && hasNotStarted) return true
// 0-100
const hasInProgress = courses.some(lesson => { const hasInProgress = courses.some(lesson => {
const progress = calcLessonProgress(lesson); const progress = calcLessonProgress(lesson)
return progress > 0 && progress < 100; return progress > 0 && progress < 100
}); })
return hasInProgress; return hasInProgress
})()" custom-class="w-fit" type="primary">进行中</wd-tag> })()" custom-class="w-fit" type="primary">进行中</wd-tag>
<wd-tag v-if="(() => { <wd-tag v-if="(() => {
const allCompleted = courses.every(lesson => { const allCompleted = courses.every(lesson => {
const progress = calcLessonProgress(lesson); const progress = calcLessonProgress(lesson)
return progress === 100; return progress === 100
}); })
return allCompleted; return allCompleted
})()" custom-class="w-fit" type="success">已完成</wd-tag> })()" custom-class="w-fit" type="success">已完成</wd-tag>
<wd-tag v-if="(() => { <wd-tag v-if="(() => {
const allNotStarted = courses.every(lesson => { const allNotStarted = courses.every(lesson => {
const progress = calcLessonProgress(lesson); const progress = calcLessonProgress(lesson)
return progress === 0; return progress === 0
}); })
return allNotStarted; return allNotStarted
})()" custom-class="w-fit" type="default">未开始</wd-tag> })()" custom-class="w-fit" type="default">未开始</wd-tag>
<wd-tag custom-class="op-60" plain> <wd-tag custom-class="op-60" plain>
{{ courses.length }}节微课 {{ courses.length }}节微课
@ -238,7 +286,8 @@ onLoad(() => {
</template> </template>
<div class="w-full"> <div class="w-full">
<wd-status-tip v-if="courses.length === 0" image="content" tip="没有课程小节" /> <wd-status-tip v-if="courses.length === 0" image="content" tip="没有课程小节" />
<div v-else v-for="(lesson, i) in courses" :key="i" @click="openLessonDetail(lesson.id)" <div v-else v-for="(lesson, i) in courses" :key="`${lesson.id}-${refreshKey}`"
@click="openLessonDetail(lesson.id)"
class="w-full py-2 gap-12 flex justify-between items-center border-b border-b-solid border-neutral-100 last:border-b-0 first:pt-0 last:pb-0"> class="w-full py-2 gap-12 flex justify-between items-center border-b border-b-solid border-neutral-100 last:border-b-0 first:pt-0 last:pb-0">
<div class="flex items-center gap-1 self-center"> <div class="flex items-center gap-1 self-center">
<wd-badge is-dot hidden> <wd-badge is-dot hidden>