hookehuyr

feat(课程学习): 添加课程详情页和课程学习页的滚动位置同步功能

在课程详情页跳转至学习页时传递课程ID,并在学习页中监听课程ID变化时同步滚动位置
...@@ -125,6 +125,9 @@ import CheckInDialog from '@/components/checkin/CheckInDialog.vue'; ...@@ -125,6 +125,9 @@ import CheckInDialog from '@/components/checkin/CheckInDialog.vue';
125 import { getCourseDetailAPI } from '@/api/course'; 125 import { getCourseDetailAPI } from '@/api/course';
126 126
127 const router = useRouter(); 127 const router = useRouter();
128 +const course_id = computed(() => {
129 + return router.currentRoute.value.params.id || '';
130 +});
128 131
129 // 页面标题 132 // 页面标题
130 useTitle('课程详情'); 133 useTitle('课程详情');
...@@ -265,8 +268,7 @@ const timeout_task_list = ref([]); ...@@ -265,8 +268,7 @@ const timeout_task_list = ref([]);
265 */ 268 */
266 269
267 const get_scroll_store_key = () => { 270 const get_scroll_store_key = () => {
268 - const course_id = router.currentRoute.value.params.id || ''; 271 + return `study_course_scroll_${course_id.value}`;
269 - return `study_course_scroll_${course_id}`;
270 }; 272 };
271 273
272 /** 274 /**
...@@ -485,7 +487,7 @@ const handleTabChange = (name) => { ...@@ -485,7 +487,7 @@ const handleTabChange = (name) => {
485 487
486 const goToStudyDetail = (lessonId) => { 488 const goToStudyDetail = (lessonId) => {
487 save_scroll_state(lessonId); 489 save_scroll_state(lessonId);
488 - router.push(`/studyDetail/${lessonId}`); 490 + router.push({ path: `/studyDetail/${lessonId}`, query: { from_course_id: course_id.value } });
489 }; 491 };
490 492
491 // 打卡相关状态 493 // 打卡相关状态
......
...@@ -426,9 +426,51 @@ const handleScroll = () => { ...@@ -426,9 +426,51 @@ const handleScroll = () => {
426 426
427 const courseFile = ref({}); 427 const courseFile = ref({});
428 428
429 +/**
430 + * @function sync_study_course_back_position
431 + * @description 同步学习课程返回位置
432 + * @param {string} lesson_id - 当前课程目录项ID
433 + * @returns {void}
434 + * 注释:在用户点击目录项时调用,记录当前滚动位置和目录项ID
435 + */
436 +
437 +const sync_study_course_back_position = (lesson_id) => {
438 + const from_course_id = route.query.from_course_id || '';
439 + if (!from_course_id) return;
440 +
441 + const key = `study_course_scroll_${from_course_id}`;
442 + const raw = sessionStorage.getItem(key);
443 +
444 + let payload = null;
445 + try {
446 + payload = raw ? JSON.parse(raw) : null;
447 + } catch (e) {
448 + payload = null;
449 + }
450 +
451 + if (!payload || typeof payload !== 'object') {
452 + payload = { scroll_y: 0, lesson_id: '', saved_at: 0 };
453 + }
454 +
455 + payload.lesson_id = lesson_id || payload.lesson_id || '';
456 + payload.saved_at = Date.now();
457 +
458 + sessionStorage.setItem(key, JSON.stringify(payload));
459 +};
460 +
461 +watch(
462 + () => route.params.id,
463 + (val) => {
464 + sync_study_course_back_position(val || '');
465 + },
466 + { immediate: true }
467 +);
468 +
429 const handleLessonClick = async (lesson) => { 469 const handleLessonClick = async (lesson) => {
430 showCatalog.value = false; // 关闭目录弹窗 470 showCatalog.value = false; // 关闭目录弹窗
431 isPlaying.value = false; // 重置播放状态 471 isPlaying.value = false; // 重置播放状态
472 + // 同步学习课程返回位置
473 + sync_study_course_back_position(lesson.id);
432 474
433 // 更新URL地址,不触发页面重新加载 475 // 更新URL地址,不触发页面重新加载
434 router.replace({ params: { id: lesson.id } }); 476 router.replace({ params: { id: lesson.id } });
......