feat: 工作进度管理页面,优化用户资料更新,优化部分接口请求
This commit is contained in:
@ -1,8 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import BussApi from '@/api/BussApi';
|
||||
import pageWrapper from '@/components/page-wrapper.vue';
|
||||
import { useUser } from '@/stores/useUser';
|
||||
import type { Lesson } from '@/types/api/lesson';
|
||||
import { calcLessonProgress } from '@/utils/lesson';
|
||||
import { onPageShow } from '@dcloudio/uni-app';
|
||||
import { useRouter } from 'uni-mini-router';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useToast } from 'wot-design-uni';
|
||||
@ -12,6 +14,8 @@ import WdTag from 'wot-design-uni/components/wd-tag/wd-tag.vue';
|
||||
const toast = useToast()
|
||||
const router = useRouter()
|
||||
|
||||
const user = useUser()
|
||||
|
||||
const teacherFilterValue = ref<number>(0)
|
||||
|
||||
const teacherFilterOptions = ref<Record<string, any>[]>([
|
||||
@ -36,7 +40,7 @@ const openLessonDetail = (courseId: number) => {
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
onPageShow(() => {
|
||||
toast.loading({
|
||||
msg: '加载中...'
|
||||
})
|
||||
@ -52,8 +56,10 @@ onMounted(() => {
|
||||
return acc
|
||||
}, {})
|
||||
groupedLessons.value = groupData
|
||||
// auto expand all course
|
||||
// expandedCourse.value = Object.keys(groupData)
|
||||
// expand courses with lessons in progress
|
||||
expandedCourse.value = Object.keys(groupData).filter(courseName => {
|
||||
return groupData[courseName].filter((lesson: Lesson) => calcLessonProgress(lesson) !== 0 && calcLessonProgress(lesson) !== 100).length > 0
|
||||
})
|
||||
}).catch(err => {
|
||||
toast.error({ msg: err.message })
|
||||
})
|
||||
@ -64,11 +70,12 @@ onMounted(() => {
|
||||
<page-wrapper>
|
||||
<div>
|
||||
<!-- todo teacher filter [for role B] -->
|
||||
<wd-drop-menu>
|
||||
<wd-drop-menu-item v-model="teacherFilterValue" :options="teacherFilterOptions" :before-toggle="handleBeforeToggle" />
|
||||
<wd-drop-menu v-if="user.hasJobTag('B')">
|
||||
<wd-drop-menu-item v-model="teacherFilterValue" :options="teacherFilterOptions"
|
||||
:before-toggle="handleBeforeToggle" />
|
||||
</wd-drop-menu>
|
||||
<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}`"
|
||||
:key="courseName">
|
||||
<template #title="{ expanded, disabled, isFirst }">
|
||||
@ -97,7 +104,7 @@ onMounted(() => {
|
||||
<div class="w-1.5 aspect-square rounded-full bg-blue"></div>
|
||||
<span class="text-xs text-blue font-bold font-mono">
|
||||
{{ courses.filter(lesson => calcLessonProgress(lesson) !== 0 && calcLessonProgress(lesson) !==
|
||||
100).length }}
|
||||
100).length }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-0.5">
|
||||
|
@ -37,7 +37,7 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div :class="`pattern p-4 flex flex-col gap-6 relative ${lessonProgress === 100 ? 'bg-emerald' : 'bg-blue'}`">
|
||||
<div :class="`pattern p-4 flex flex-col gap-6 relative ${lessonProgress === 100 ? 'bg-emerald' : (lessonProgress === 0 ? 'bg-neutral' : 'bg-blue')}`">
|
||||
<div class="flex flex-col gap-0">
|
||||
<h2 class="text-sm text-white font-black op-50">{{ lesson?.course_name }}</h2>
|
||||
<h1 class="text-lg text-white font-bold">{{ lesson?.m_lesson_name }}</h1>
|
||||
|
155
src/pages/progress/index.vue
Normal file
155
src/pages/progress/index.vue
Normal file
@ -0,0 +1,155 @@
|
||||
<script lang="ts" setup>
|
||||
import BussApi from '@/api/BussApi';
|
||||
import { useDayjs } from '@/composables/useDayjs';
|
||||
import type { Lesson, ScriptFileDestination } from '@/types/api/lesson';
|
||||
import { extractLessonStage, getLessonSteps } from '@/utils/lesson';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { useMessage, useToast } from 'wot-design-uni';
|
||||
|
||||
const message = useMessage()
|
||||
const toast = useToast()
|
||||
const dayjs = useDayjs()
|
||||
|
||||
type GroupedLessons = { [key: string]: Lesson[] }
|
||||
|
||||
const groupedLessons = ref<GroupedLessons>({})
|
||||
|
||||
const pickerCourseColumns = ref<string[]>([])
|
||||
const pickerCourseValue = ref()
|
||||
|
||||
const pickerLessonColumns = computed(() => {
|
||||
return pickerCourseValue.value ? groupedLessons.value[pickerCourseValue.value].map((lesson: Lesson) => {
|
||||
return {
|
||||
label: (extractLessonStage(lesson).step === 4 ? '✅ ' : '') + lesson.m_lesson_name,
|
||||
value: lesson.id
|
||||
}
|
||||
}) : []
|
||||
})
|
||||
const pickerLessonValue = ref()
|
||||
|
||||
const selectedLesson = computed(() => {
|
||||
if (!pickerLessonValue.value) return null
|
||||
return groupedLessons.value[pickerCourseValue.value].find((lesson: Lesson) => lesson.id === pickerLessonValue.value)
|
||||
})
|
||||
|
||||
const selectedLessonStage = computed(() => {
|
||||
if (!selectedLesson.value) return null
|
||||
return extractLessonStage(selectedLesson.value)
|
||||
})
|
||||
|
||||
const onCoursePick = ({ value }: { value: string }) => {
|
||||
pickerCourseValue.value = value
|
||||
pickerLessonValue.value = void 0
|
||||
}
|
||||
|
||||
const onLessonPick = ({ value }: { value: number }) => {
|
||||
pickerLessonValue.value = value
|
||||
}
|
||||
|
||||
/**
|
||||
* lesson progress modifition steps
|
||||
*/
|
||||
|
||||
const script_file_destination = ref<ScriptFileDestination>('wechat')
|
||||
|
||||
const onStep0 = () => {
|
||||
message.confirm({
|
||||
title: '提交脚本',
|
||||
msg: '请确认已经通过微信或平台上传了脚本文件,再确认提交'
|
||||
}).then(() => {
|
||||
if (!selectedLesson.value?.id) {
|
||||
toast.error({
|
||||
msg: '参数错误'
|
||||
})
|
||||
return
|
||||
}
|
||||
toast.loading({
|
||||
msg: '正在提交...'
|
||||
})
|
||||
BussApi.editCourse(selectedLesson.value.id, {
|
||||
script_file: script_file_destination.value,
|
||||
script_upload_time: dayjs().unix()
|
||||
}).then(res => {
|
||||
toast.success({
|
||||
msg: '提交成功'
|
||||
})
|
||||
setTimeout(() => {
|
||||
updateLessons()
|
||||
}, 1500);
|
||||
}).catch(err => {
|
||||
toast.error({ msg: err.message })
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const updateLessons = () => {
|
||||
toast.loading({
|
||||
msg: '加载中...'
|
||||
})
|
||||
BussApi.lessons(1, 512).then(res => {
|
||||
toast.close()
|
||||
const groupData = res.data.sort((a: Lesson, b: Lesson) => {
|
||||
return a.id - b.id
|
||||
}).reduce((acc: any, cur: any) => {
|
||||
if (!acc[cur.course_name]) {
|
||||
acc[cur.course_name] = []
|
||||
}
|
||||
acc[cur.course_name].push(cur)
|
||||
return acc
|
||||
}, {})
|
||||
groupedLessons.value = groupData
|
||||
pickerCourseColumns.value = [
|
||||
...Object.keys(groupData)
|
||||
]
|
||||
}).catch(err => {
|
||||
toast.error({ msg: err.message })
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
updateLessons()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<page-wrapper>
|
||||
<div class="m-2 rounded-lg border border-solid border-neutral-100 shadow-md shadow-op-50 overflow-hidden">
|
||||
<wd-picker :columns="pickerCourseColumns" label="课程选择" v-model="pickerCourseValue" @confirm="onCoursePick"
|
||||
:columns-height="280" label-width="80px" safe-area-inset-bottom title="课程选择" />
|
||||
<wd-picker :columns="pickerLessonColumns" label="微课选择" v-model="pickerLessonValue" @confirm="onLessonPick"
|
||||
:columns-height="280" label-width="80px" safe-area-inset-bottom title="微课选择" :disabled="!pickerCourseValue" />
|
||||
</div>
|
||||
<div class="p-2 pt-4">
|
||||
<wd-status-tip v-if="!pickerLessonValue" image="search" tip="请先选择微课" />
|
||||
<div v-else class="space-y-6">
|
||||
<div>
|
||||
<wd-steps :active="selectedLessonStage?.step || 0" align-center>
|
||||
<wd-step v-for="(step, index) in getLessonSteps(selectedLesson!, true)" :key="index" :title="step.title"
|
||||
:description="(selectedLessonStage?.step || 0 <= index) ? step.description : undefined" />
|
||||
</wd-steps>
|
||||
</div>
|
||||
<div v-if="selectedLessonStage?.step === 0" class="px-2">
|
||||
<wd-cell-group>
|
||||
<wd-cell title="脚本提交途径" :title-width="'100px'" center custom-class="mb-4">
|
||||
<wd-radio-group v-model="script_file_destination" shape="button">
|
||||
<wd-radio value="wechat">微信</wd-radio>
|
||||
<wd-radio value="qq">QQ</wd-radio>
|
||||
<wd-radio value="platform">平台</wd-radio>
|
||||
</wd-radio-group>
|
||||
</wd-cell>
|
||||
</wd-cell-group>
|
||||
|
||||
<wd-button type="primary" block @click="onStep0" custom-class="w-full">提交脚本</wd-button>
|
||||
</div>
|
||||
<div v-if="selectedLessonStage?.step === 1"></div>
|
||||
<div v-if="selectedLessonStage?.step === 2"></div>
|
||||
<div v-if="selectedLessonStage?.step === 3"></div>
|
||||
<div v-else-if="selectedLessonStage?.step === 4">
|
||||
<wd-status-tip image="comment" tip="该微课已完成" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</page-wrapper>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
Reference in New Issue
Block a user