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

@@ -1,29 +1,15 @@
<script lang="ts" setup>
import { ref, computed } from 'vue'
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { GuideSteps } from '@/components/Guide'
import { Overlay } from '@/components/Overlay'
import { GuideSteps, type GuideStep } from '@/components/Guide'
import { ImgButton } from '@/components/Button'
import {
getBackgroundImage,
getPublicPath,
getStaticImage,
IMAGE_PATHS,
} from '@/utils'
import { getBackgroundImage, getPublicPath } from '@/utils'
import shootingtitle from '@/assets/images/shooting/标题-实地取景.png'
import videoSrc from '/video/new/composition/xsdh_jzgtf_batch.mp4'
import KnowledgeCard from '@/components/KnowledgeCard/FilmKnowledgeCard.vue'
import { Video } from '@/components'
import CompositionGuide from '@/components/CompositionGuide.vue'
import { useFilmStore } from '@/stores/modules/film'
type Btn = {
key: string
name: string
btnImage: string
images: string[]
desc: string
}
const router = useRouter()
const filmStore = useFilmStore()
const introGuideKey = 'film-shooting-intro'
@@ -35,7 +21,7 @@ if (showIntroGuide.value) {
filmStore.markGuideShown(introGuideKey)
}
const steps = ref([
const steps = ref<GuideStep[]>([
{
id: '1',
audioSrc: getPublicPath('audio/py_4_015.MP3'),
@@ -44,7 +30,7 @@ const steps = ref([
},
])
const guideSteps = ref([
const guideSteps = ref<GuideStep[]>([
{
id: '1',
content: '点击框架构图,查看构图方法',
@@ -63,17 +49,7 @@ const guideSteps = ref([
])
const showModal = ref(false)
const showModal2 = ref(false)
const showModal3 = ref(false)
const currentItem = ref<Btn>({
key: '',
name: '',
btnImage: '',
images: [],
desc: '',
})
const btnList = ref<Btn[]>([
const btnList = ref([
{
key: '1',
name: '框架构图',
@@ -100,10 +76,6 @@ const btnList = ref<Btn[]>([
},
])
const handleModalClose = () => {
showModal.value = false
}
const openCompositionGuide = () => {
showModal.value = true
if (showCompositionGuide.value) {
@@ -111,26 +83,13 @@ const openCompositionGuide = () => {
}
}
const handleClick = (item: any) => {
currentItem.value = item
showModal2.value = true
}
const currentCompositionKey = computed(() => {
const k = currentItem.value.key
if (k === '1' || k === '2' || k === '3') return k
return '1'
})
const handleClickA = () => {
// 跳转设备准备
router.push({ name: 'FilmFilmingLocationA' })
}
const handleClickB = () => {
// 跳转设备准备
router.push({ name: 'FilmFilmingLocationB' })
}
const back = () => {
// 跳转设备准备
router.back()
}
</script>
@@ -142,13 +101,13 @@ const back = () => {
:style="{ backgroundImage: getBackgroundImage('film/shooting/底图') }"
></div>
<div class="shooting-title">
<div class="absolute top-0 left-0">
<img
:src="shootingtitle"
alt=""
/>
</div>
<div class="shooting-return">
<div class="absolute top-0 right-0">
<ImgButton
image="shooting/返回.png"
@click="back"
@@ -168,7 +127,7 @@ const back = () => {
@click="handleClickB"
/>
</div>
<div class="shooting-composition btn-1">
<div class="absolute bottom-4 left-4 btn-1">
<ImgButton
image="shooting/构图指南.png"
@click="openCompositionGuide"
@@ -184,127 +143,16 @@ const back = () => {
position-offset-y="20%"
/>
<!-- 保存图片弹窗 -->
<Overlay
<!-- 构图指南弹窗 -->
<CompositionGuide
:visible="showModal"
:clickable="false"
:customStyle="{
backgroundImage: getBackgroundImage('film/shooting/构图指南底图'),
}"
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="handleModalClose"
/>
<!-- 构图指南 -->
<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="showModal3 = true"
/>
<div
class="absolute left-[40%] top-[42%] -translate-x-1/2 -translate-y-1/2 z-10 animate-bounce pointer-events-none"
>
<img
class="w-32"
:src="getStaticImage('work/小手')"
alt=""
/>
<span class="text-white text-2xl font-bold ml-5">点击进入</span>
</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="handleClick(item)"
/>
</div>
<GuideSteps
:visible="showCompositionGuide"
:steps="guideSteps"
:keyboard-navigation="true"
:highlight-padding="12"
:highlight-radius="16"
position-offset-y="85%"
/>
<!-- 知识卡片 -->
<KnowledgeCard
v-if="showModal2 && currentItem.key"
:visible="showModal2"
:title="currentItem.name"
:desc="currentItem.desc"
:images="currentItem.images"
:compositionKey="currentCompositionKey"
@close="showModal2 = false"
/>
<!-- 视频 -->
<Overlay
:visible="showModal3"
:clickable="false"
>
<Video
:src="videoSrc"
controls
:volume="1"
:muted="false"
></Video>
<!-- 返回 -->
<ImgButton
class="absolute right-0 top-0 z-10"
:image="IMAGE_PATHS.COMPONENTS.CLOSE"
@click="showModal3 = false"
/>
</Overlay>
</Overlay>
bg-image="film/shooting/构图指南底图"
:btn-list="btnList"
:knowledge-card-component="KnowledgeCard"
:video-src="videoSrc"
:guide-steps="guideSteps"
:show-internal-guide="showCompositionGuide"
@close="showModal = false"
/>
</div>
</template>
<style lang="less" scoped>
.shooting-title {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.shooting-return {
position: absolute;
right: 0;
top: 0;
}
.shooting-left {
position: absolute;
left: 16%;
top: 50%;
}
.shooting-right {
position: absolute;
right: 16%;
top: 50%;
}
.shooting-composition {
position: absolute;
left: 2rem;
bottom: 1rem;
}
</style>