diff --git a/reading-platform-frontend/src/api/generated/model/lessonDetailResponse.ts b/reading-platform-frontend/src/api/generated/model/lessonDetailResponse.ts index 3ff466e..881bb8b 100644 --- a/reading-platform-frontend/src/api/generated/model/lessonDetailResponse.ts +++ b/reading-platform-frontend/src/api/generated/model/lessonDetailResponse.ts @@ -16,4 +16,6 @@ export interface LessonDetailResponse { lesson?: LessonResponse; course?: CourseResponse; class?: ClassResponse; + /** 排课选择的课程类型(子课程模式时用于直接进入对应子课程) */ + lessonType?: string; } diff --git a/reading-platform-frontend/src/views/teacher/lessons/LessonView.vue b/reading-platform-frontend/src/views/teacher/lessons/LessonView.vue index 334244a..70b5847 100644 --- a/reading-platform-frontend/src/views/teacher/lessons/LessonView.vue +++ b/reading-platform-frontend/src/views/teacher/lessons/LessonView.vue @@ -49,10 +49,10 @@ - -
+ +
- @@ -218,6 +218,19 @@
+ +
+
+ + 课程类型 +
+
+ + {{ getLessonTypeName(currentLesson.lessonType) }} + +
+
+
@@ -412,6 +425,7 @@ import { import { message, Modal } from 'ant-design-vue'; import * as teacherApi from '@/api/teacher'; import FilePreviewModal from '@/components/FilePreviewModal.vue'; +import { getLessonTypeName, getLessonTagStyle } from '@/utils/tagMaps'; const router = useRouter(); const route = useRoute(); @@ -434,6 +448,8 @@ let timerInterval: number | null = null; const course = ref({}); const classInfo = ref({}); const lessons = ref([]); +/** 排课选择的课程类型(子课程模式:仅展示该子课程,子课程结束即上课结束) */ +const scheduleLessonType = ref(undefined); const studentEvaluation = ref({ overall: 0, @@ -449,8 +465,37 @@ const lessonRecord = ref({ completionNote: '', }); +/** 判断排课 lessonType 与课程 lessonType 是否匹配(兼容 INTRODUCTION/INTRO、LANGUAGE/DOMAIN_LANGUAGE 等变体) */ +const lessonTypeMatches = (scheduleType: string, lessonType: string): boolean => { + if (!scheduleType || !lessonType) return false; + const s = scheduleType.toUpperCase(); + const l = lessonType.toUpperCase(); + if (s === l) return true; + const pairs: [string, string][] = [ + ['INTRODUCTION', 'INTRO'], + ['LANGUAGE', 'DOMAIN_LANGUAGE'], + ['HEALTH', 'DOMAIN_HEALTH'], + ['SCIENCE', 'DOMAIN_SCIENCE'], + ['SOCIAL', 'DOMAIN_SOCIAL'], + ['SOCIETY', 'DOMAIN_SOCIAL'], + ['ART', 'DOMAIN_ART'], + ]; + for (const [a, b] of pairs) { + if ((s === a || s === b) && (l === a || l === b)) return true; + } + return false; +}; + +/** 展示的课程列表:子课程模式时仅包含排课选中的子课程,否则为全部 */ +const displayLessons = computed(() => { + const type = scheduleLessonType.value; + if (!type || lessons.value.length === 0) return lessons.value; + const matched = lessons.value.filter((l) => lessonTypeMatches(type, l.lessonType || '')); + return matched.length > 0 ? matched : lessons.value; +}); + // 当前课程 -const currentLesson = computed(() => lessons.value[currentLessonIndex.value] || null); +const currentLesson = computed(() => displayLessons.value[currentLessonIndex.value] || null); // 当前环节 const currentStep = computed(() => { @@ -467,9 +512,9 @@ const stepProgressPercent = computed(() => { // 是否有上一个课程 const hasPreviousLesson = computed(() => currentLessonIndex.value > 0); -// 是否是最后一个课程的最后一个环节 +// 是否是最后一个课程的最后一个环节(子课程模式下,当前子课程最后一环节即视为最后) const isLastStepOfLastLesson = computed(() => { - if (currentLessonIndex.value < lessons.value.length - 1) return false; + if (currentLessonIndex.value < displayLessons.value.length - 1) return false; const totalSteps = currentLesson.value?.steps?.length || 1; return currentStepIndex.value >= totalSteps - 1; }); @@ -648,6 +693,9 @@ const loadLessonData = async () => { course.value = data.course || {}; classInfo.value = data.class || {}; + // 排课选择的课程类型(子课程模式:直接进入该子课程,子课程结束即上课结束) + scheduleLessonType.value = data.lessonType || undefined; + // 获取课程列表 // 如果授课记录包含多个课程,使用该列表;否则使用课程包的所有课程 if (data.lessonCourses && data.lessonCourses.length > 0) { @@ -701,50 +749,61 @@ const loadLessonData = async () => { }]; } + // 子课程模式:根据排课 lessonType 直接进入对应子课程(优先于进度恢复和 URL 参数) + const matchedLessons = scheduleLessonType.value + ? lessons.value.filter((l) => lessonTypeMatches(scheduleLessonType.value!, l.lessonType || '')) + : []; + if (matchedLessons.length > 0) { + currentLessonIndex.value = 0; + currentStepIndex.value = 0; + } + // 尝试恢复进度 try { const progress = await teacherApi.getLessonProgress(lessonId.value); - if (progress && (progress.currentLessonId || progress.currentStepId)) { - // 有保存的进度,询问用户是否恢复 + if (progress && (progress.currentLessonId !== undefined || progress.currentStepId !== undefined)) { + const isSub = matchedLessons.length > 0; + const matchedLesson = matchedLessons[0]; + const progressIsForMatched = isSub && progress.currentLessonId !== undefined + && matchedLesson && progress.currentLessonId === matchedLesson.id; + Modal.confirm({ title: '检测到上次上课进度', content: `上次上课到:${getProgressDescription(progress)},是否继续?`, okText: '继续上课', cancelText: '重新开始', onOk: () => { - // 恢复进度 - if (progress.currentLessonId !== undefined) { - const lessonIndex = lessons.value.findIndex((l) => l.id === progress.currentLessonId); - if (lessonIndex >= 0) { - currentLessonIndex.value = lessonIndex; - } - } - if (progress.currentStepId !== undefined) { + if (isSub && progressIsForMatched && progress.currentStepId !== undefined) { + // 子课程模式:仅恢复环节进度 + currentLessonIndex.value = 0; currentStepIndex.value = progress.currentStepId; + } else if (!isSub) { + // 非子课程模式:恢复课程和环节进度 + if (progress.currentLessonId !== undefined) { + const lessonIndex = lessons.value.findIndex((l) => l.id === progress.currentLessonId); + if (lessonIndex >= 0) currentLessonIndex.value = lessonIndex; + } + if (progress.currentStepId !== undefined) currentStepIndex.value = progress.currentStepId; } }, - onCancel: () => { - // 清除进度,从头开始 - clearProgress(); - }, + onCancel: () => clearProgress(), }); } } catch (progressError) { - // 没有保存的进度或获取失败,忽略 console.log('No saved progress found'); } - // 如果URL指定了课程索引,跳转到该课程(优先级高于恢复的进度) - const queryLessonIndex = route.query.lessonIndex ? parseInt(route.query.lessonIndex as string) : 0; - if (queryLessonIndex >= 0 && queryLessonIndex < lessons.value.length) { - currentLessonIndex.value = queryLessonIndex; - } - - // 如果URL指定了环节索引,跳转到该环节(优先级高于恢复的进度) - const queryStepIndex = route.query.stepIndex ? parseInt(route.query.stepIndex as string) : 0; - const totalSteps = lessons.value[currentLessonIndex.value]?.steps?.length || 0; - if (queryStepIndex >= 0 && queryStepIndex < totalSteps) { - currentStepIndex.value = queryStepIndex; + // 非子课程模式时,URL 参数可覆盖 + if (matchedLessons.length === 0) { + const queryLessonIndex = route.query.lessonIndex ? parseInt(route.query.lessonIndex as string) : 0; + if (queryLessonIndex >= 0 && queryLessonIndex < lessons.value.length) { + currentLessonIndex.value = queryLessonIndex; + } + const queryStepIndex = route.query.stepIndex ? parseInt(route.query.stepIndex as string) : 0; + const totalSteps = lessons.value[currentLessonIndex.value]?.steps?.length || 0; + if (queryStepIndex >= 0 && queryStepIndex < totalSteps) { + currentStepIndex.value = queryStepIndex; + } } // 启动计时器 @@ -770,10 +829,11 @@ const getProgressDescription = (progress: any): string => { // 保存进度 const saveProgress = async () => { try { + const list = displayLessons.value; await teacherApi.saveLessonProgress(lessonId.value, { - lessonIds: lessons.value.map((l) => l.id), - completedLessonIds: lessons.value.slice(0, currentLessonIndex.value).map((l) => l.id), - currentLessonId: lessons.value[currentLessonIndex.value]?.id, + lessonIds: list.map((l) => l.id), + completedLessonIds: list.slice(0, currentLessonIndex.value).map((l) => l.id), + currentLessonId: list[currentLessonIndex.value]?.id, currentStepId: currentStepIndex.value, progressData: { timerSeconds: timerSeconds.value, @@ -1559,6 +1619,19 @@ onUnmounted(() => { } } +.lesson-type-card { + .panel-header { + background: #F5F5F5; + color: #666; + } + + .lesson-type-tag { + font-size: 14px; + padding: 6px 14px; + border-radius: 8px; + } +} + .materials-card { .panel-header { background: #FFF5EB; diff --git a/reading-platform-frontend/src/views/teacher/schedule/ScheduleView.vue b/reading-platform-frontend/src/views/teacher/schedule/ScheduleView.vue index 6345344..50a5c08 100644 --- a/reading-platform-frontend/src/views/teacher/schedule/ScheduleView.vue +++ b/reading-platform-frontend/src/views/teacher/schedule/ScheduleView.vue @@ -4,7 +4,9 @@

我的课表

- + 预约上课 @@ -12,7 +14,9 @@
-

今日课程

+

+ 今日课程 +

@@ -21,31 +25,20 @@
{{ schedule.courseName || schedule.coursePackageName || '-' }}
{{ schedule.className || '-' }}
- + {{ getLessonTypeName(schedule.lessonType) }}
- + 开始上课 - + 继续上课 - + 创建课堂
@@ -58,13 +51,17 @@
- + 上一周 本周 下一周 - + {{ weekRangeText }} @@ -74,12 +71,7 @@
-
+
{{ day.dayName }}
{{ day.dateDisplay }}
@@ -87,27 +79,17 @@
-
-
+
+
{{ schedule.scheduledTime || '待定' }}
{{ schedule.courseName || schedule.coursePackageName || '-' }}
{{ schedule.className || '-' }}
- + {{ getLessonTypeName(schedule.lessonType) }}
@@ -133,18 +115,15 @@ - +