feat: 完善视频学习进度缓存

完善新手导航和三大创作模块的视频完成缓存、未完成提示与学习进度计算,确保进度按实际学习资源完成情况更新。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
zhongyidianandClaude Opus 4.7 committed 2026-05-11 09:05:29 +08:00
1 parent 1f8723aabd
commit 6f289959be
63 files changed
+3139 -1126

No files matched your search

+147
View File
@@ -0,0 +1,147 @@
<script lang="ts" setup>
import { ref, computed } from 'vue'
import type { Component } from 'vue'
import { Overlay } from '@/components/Overlay'
import { ImgButton } from '@/components/Button'
import { Video } from '@/components/Video'
import { GuideSteps, type GuideStep } from '@/components/Guide'
import { getBackgroundImage, getStaticImage, IMAGE_PATHS } from '@/utils'
interface CompositionBtn {
key: string
name: string
btnImage: string
images: string[]
desc: string
}
withDefaults(
defineProps<{
visible: boolean
bgImage: string
btnList: CompositionBtn[]
knowledgeCardComponent: Component
videoSrc: string
guideSteps?: GuideStep[]
showInternalGuide?: boolean
}>(),
{
guideSteps: () => [],
showInternalGuide: false,
},
)
const emit = defineEmits<{
close: []
}>()
const showKnowledgeCard = ref(false)
const showVideo = ref(false)
const currentItem = ref<CompositionBtn>({
key: '',
name: '',
btnImage: '',
images: [],
desc: '',
})
const currentCompositionKey = computed(() => {
const k = currentItem.value.key
if (k === '1' || k === '2' || k === '3') return k
return '1'
})
const handleClose = () => {
emit('close')
}
const handleItemClick = (item: CompositionBtn) => {
currentItem.value = item
showKnowledgeCard.value = true
}
</script>
<template>
<Overlay
:visible="visible"
:clickable="false"
:customStyle="{ backgroundImage: getBackgroundImage(bgImage) }"
customClass="inset-0 bg-cover bg-center bg-no-repeat"
contentClass="relative w-full h-full"
>
<ImgButton
class="absolute right-0 top-0 z-10"
:image="IMAGE_PATHS.COMPONENTS.BACK"
@click="handleClose"
/>
<ImgButton
class="absolute left-0 top-0 z-10"
image="shooting/标题-构图指南"
/>
<div class="absolute left-28 top-[calc(50%-40px)] -translate-y-1/2">
<ImgButton
image="shooting/新手导航-视频回顾"
@click="showVideo = true"
/>
<div
class="absolute left-[38%] top-[50%] -translate-x-1/2 -translate-y-1/2 z-10 animate-bounce pointer-events-none"
>
<img
class="w-40"
:src="getStaticImage('work/小手')"
alt=""
/>
</div>
</div>
<div class="absolute top-[30%] right-10">
<ImgButton
v-for="item in btnList"
:key="item.key"
:class="`btn-item-${item.key}`"
:image="item.btnImage"
@click="handleItemClick(item)"
/>
</div>
<GuideSteps
v-if="showInternalGuide && guideSteps.length > 0"
:visible="showInternalGuide"
:steps="guideSteps"
:keyboard-navigation="true"
:highlight-padding="12"
:highlight-radius="16"
position-offset-y="85%"
/>
<component
:is="knowledgeCardComponent"
v-if="showKnowledgeCard && currentItem.key"
:visible="showKnowledgeCard"
:title="currentItem.name"
:desc="currentItem.desc"
:images="currentItem.images"
:compositionKey="currentCompositionKey"
@close="showKnowledgeCard = false"
/>
<Overlay
:visible="showVideo"
:clickable="false"
>
<Video
:src="videoSrc"
controls
:volume="1"
:muted="false"
/>
<ImgButton
class="absolute right-0 top-0 z-10"
:image="IMAGE_PATHS.COMPONENTS.CLOSE"
@click="showVideo = false"
/>
</Overlay>
</Overlay>
</template>