forked from zhongyidian/super_video
feat: 完善视频学习进度缓存
完善新手导航和三大创作模块的视频完成缓存、未完成提示与学习进度计算,确保进度按实际学习资源完成情况更新。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
1f8723aabd
commit
6f289959be
63 files changed
+3139
-1126
No files matched your search
@@ -1,8 +1,9 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, nextTick, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { onBeforeRouteLeave, useRouter } from 'vue-router'
|
||||
import ImgButton from '@/components/Button/ImgButton.vue'
|
||||
import StepNavigation from '@/components/Guide/StepNavigation.vue'
|
||||
import UnfinishedLearningPrompt from '@/components/UnfinishedLearningPrompt'
|
||||
import { Video } from '@/components'
|
||||
import { getPublicPath, getStaticImage, IMAGE_PATHS } from '@/utils'
|
||||
// 运镜初识 - 暂时用运镜的基本方式代替
|
||||
@@ -73,11 +74,35 @@ const navigationSteps = ref([
|
||||
|
||||
// 步骤导航相关状态
|
||||
const showStepNavigation = ref(false)
|
||||
const showUnfinishedPrompt = ref(false)
|
||||
const pendingLeavePath = ref<string | null>(null)
|
||||
const allowRouteLeave = ref(false)
|
||||
const currentNavigationStep = ref(0) // 对应视频索引,从0开始
|
||||
|
||||
// 视频列表
|
||||
const currentVideoIndex = ref(0)
|
||||
|
||||
const getLearningVideoKey = (index: number) =>
|
||||
`basic-camera-movement:${navigationSteps.value[index]?.id ?? index}`
|
||||
|
||||
const completedNavigationSteps = computed(() =>
|
||||
navigationSteps.value.map(
|
||||
(_, index) =>
|
||||
basicElementsStore.learningVideosWatched[getLearningVideoKey(index)] ===
|
||||
true,
|
||||
),
|
||||
)
|
||||
|
||||
const hasUnfinishedLearningVideos = computed(() =>
|
||||
completedNavigationSteps.value.some((completed) => !completed),
|
||||
)
|
||||
|
||||
const markCurrentLearningVideoWatched = () => {
|
||||
basicElementsStore.markLearningVideoWatched(
|
||||
getLearningVideoKey(currentVideoIndex.value),
|
||||
)
|
||||
}
|
||||
|
||||
//按顺序播放
|
||||
const currentVideo = computed(
|
||||
() => navigationSteps.value[currentVideoIndex.value].videoUrl,
|
||||
@@ -113,6 +138,7 @@ const label = computed(() => props.label as string)
|
||||
const handlePlay = () => {}
|
||||
|
||||
const onEnded = () => {
|
||||
markCurrentLearningVideoWatched()
|
||||
handleVideoChange()
|
||||
}
|
||||
|
||||
@@ -128,6 +154,25 @@ const handleStepClick = (index: number) => {
|
||||
const handleStepNavigationClose = () => {
|
||||
showStepNavigation.value = false
|
||||
}
|
||||
|
||||
const handleContinueLearning = () => {
|
||||
showUnfinishedPrompt.value = false
|
||||
pendingLeavePath.value = null
|
||||
}
|
||||
|
||||
const handleConfirmLeave = () => {
|
||||
if (!pendingLeavePath.value) return
|
||||
allowRouteLeave.value = true
|
||||
showUnfinishedPrompt.value = false
|
||||
router.push(pendingLeavePath.value)
|
||||
}
|
||||
|
||||
onBeforeRouteLeave((to) => {
|
||||
if (allowRouteLeave.value || !hasUnfinishedLearningVideos.value) return true
|
||||
pendingLeavePath.value = to.fullPath
|
||||
showUnfinishedPrompt.value = true
|
||||
return false
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -184,10 +229,17 @@ const handleStepNavigationClose = () => {
|
||||
:background-image="getStaticImage('work/vlog背景全屏待定')"
|
||||
:steps="navigationSteps"
|
||||
:current-step-index="currentNavigationStep"
|
||||
:completed-steps="completedNavigationSteps"
|
||||
@step-click="handleStepClick"
|
||||
@close="handleStepNavigationClose"
|
||||
/>
|
||||
|
||||
<UnfinishedLearningPrompt
|
||||
:visible="showUnfinishedPrompt"
|
||||
@continue="handleContinueLearning"
|
||||
@leave="handleConfirmLeave"
|
||||
/>
|
||||
|
||||
<GuideSteps
|
||||
:visible="showIntroGuide"
|
||||
position-offset-y="85%"
|
||||
|
||||
Reference in new issue
Block a user