forked from zhongyidian/super_video
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
248 lines
6.4 KiB
Vue
248 lines
6.4 KiB
Vue
<script setup lang="ts">
|
|
import { computed, ref, watch } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import {
|
|
getBackgroundImage,
|
|
getPublicPath,
|
|
getStaticImage,
|
|
IMAGE_PATHS,
|
|
} from '@/utils'
|
|
import { ImgButton } from '@/components/Button'
|
|
import { GuideSteps, type GuideStep } from '@/components/Guide'
|
|
import { useFilmStore } from '@/stores'
|
|
|
|
const router = useRouter()
|
|
const film = useFilmStore()
|
|
|
|
const isEditingUnlocked = computed(
|
|
() => film.editingVideosWatched.start === true,
|
|
)
|
|
|
|
const isEditingItemLocked = (videoKey: string) =>
|
|
videoKey !== 'start' && !isEditingUnlocked.value
|
|
|
|
const completionIcon = (completed: boolean) =>
|
|
getStaticImage(`midterm/${completed ? '完成' : '未完成'}.png`)
|
|
|
|
const editingItems = computed(() => [
|
|
{
|
|
image: 'film/after-editing/剪辑初始',
|
|
videoKey: 'start',
|
|
onClick: goStart,
|
|
iconClass: 'right-14 top-9',
|
|
class:
|
|
'absolute left-[0px] bottom-[42%] translate-y-1/2 bg-cover bg-center bg-no-repeat',
|
|
},
|
|
{
|
|
image: 'film/after-editing/img/节奏型剪辑',
|
|
textImage: 'film/after-editing/text/节奏型剪辑',
|
|
videoKey: 'rhythm',
|
|
onClick: goRhythm,
|
|
class: 'absolute right-[215px] top-[170px] bg-cover bg-center bg-no-repeat',
|
|
},
|
|
{
|
|
image: 'film/after-editing/img/声音转场',
|
|
textImage: 'film/after-editing/text/声音转场',
|
|
videoKey: 'soundTransition',
|
|
onClick: goSoundTransition,
|
|
class: 'absolute right-[215px] top-[420px] bg-cover bg-center bg-no-repeat',
|
|
},
|
|
{
|
|
image: 'film/after-editing/img/快切',
|
|
textImage: 'film/after-editing/text/快切',
|
|
videoKey: 'cut',
|
|
onClick: goCut,
|
|
class: 'absolute right-[620px] top-[560px] bg-cover bg-center bg-no-repeat',
|
|
},
|
|
{
|
|
image: 'film/after-editing/img/关联剪辑',
|
|
textImage: 'film/after-editing/text/关联剪辑',
|
|
videoKey: 'association',
|
|
onClick: goAssociation,
|
|
class:
|
|
'absolute right-[215px] bottom-[290px] bg-cover bg-center bg-no-repeat',
|
|
},
|
|
{
|
|
image: 'film/after-editing/img/连续剪辑',
|
|
textImage: 'film/after-editing/text/连续剪辑',
|
|
videoKey: 'continuity',
|
|
onClick: goContinuity,
|
|
class:
|
|
'absolute right-[215px] bottom-[35px] bg-cover bg-center bg-no-repeat',
|
|
},
|
|
])
|
|
|
|
const handleClose = () => {
|
|
router.back()
|
|
}
|
|
|
|
const goStart = () => {
|
|
router.push({ name: 'FilmEditingStart' })
|
|
}
|
|
|
|
const goRhythm = () => {
|
|
router.push({ name: 'FilmEditingRhythm' })
|
|
}
|
|
|
|
const goSoundTransition = () => {
|
|
router.push({ name: 'FilmEditingSoundTransition' })
|
|
}
|
|
|
|
const goCut = () => {
|
|
router.push({ name: 'FilmEditingCut' })
|
|
}
|
|
|
|
const goAssociation = () => {
|
|
router.push({ name: 'FilmEditingAssociation' })
|
|
}
|
|
|
|
const goContinuity = () => {
|
|
router.push({ name: 'FilmEditingContinuity' })
|
|
}
|
|
|
|
const goEditingItem = (item: (typeof editingItems.value)[number]) => {
|
|
if (isEditingItemLocked(item.videoKey)) return
|
|
item.onClick()
|
|
}
|
|
|
|
// 6 个剪辑子视频学习完成后的一次性引导
|
|
const editingCompleteSteps: GuideStep[] = [
|
|
{
|
|
id: 'editing-complete-step1',
|
|
content:
|
|
'刚才我们提到的剪辑方式,并不是孤立存在的技巧,而是针对不同问题的解决方案。所以,理解剪辑逻辑才是最重要的!',
|
|
audioSrc: getPublicPath('audio/py_4_018.MP3'),
|
|
},
|
|
]
|
|
|
|
const showEditingCompleteGuide = ref(false)
|
|
|
|
watch(
|
|
() => film.allEditingVideosWatched,
|
|
(watched) => {
|
|
if (watched && film.isGuideFilmEditingComplete) {
|
|
showEditingCompleteGuide.value = true
|
|
}
|
|
},
|
|
{ immediate: true },
|
|
)
|
|
|
|
const handleEditingCompleteGuideDone = () => {
|
|
showEditingCompleteGuide.value = false
|
|
film.setIsGuideFilmEditingComplete(false)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="relative w-full h-full overflow-hidden">
|
|
<!-- 背景 -->
|
|
<div
|
|
class="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
|
:style="{
|
|
backgroundImage: getBackgroundImage(
|
|
isEditingUnlocked
|
|
? 'film/after-editing/剪辑底图亮'
|
|
: 'film/after-editing/剪辑底图灰',
|
|
),
|
|
}"
|
|
></div>
|
|
|
|
<!-- 标题 -->
|
|
<img
|
|
class="absolute left-0 top-6"
|
|
:src="getStaticImage('film/after-editing/剪辑标题')"
|
|
alt=""
|
|
/>
|
|
|
|
<div
|
|
v-for="item in editingItems"
|
|
:key="item.videoKey"
|
|
:class="item.class"
|
|
>
|
|
<div
|
|
:class="[
|
|
'relative transition-all duration-200',
|
|
isEditingItemLocked(item.videoKey)
|
|
? 'opacity-40 pointer-events-none'
|
|
: 'hover:scale-105 hover:cursor-pointer hover:brightness-125',
|
|
]"
|
|
@click="goEditingItem(item)"
|
|
>
|
|
<!-- img -->
|
|
<img :src="getStaticImage(item.image)" />
|
|
|
|
<!-- 点击提示 -->
|
|
<img
|
|
v-if="item.videoKey === 'start' && !isEditingUnlocked"
|
|
class="pointer-events-none absolute right-6 -bottom-40 z-20 start-click-hint"
|
|
:src="getStaticImage('film/after-editing/点击此处开始')"
|
|
alt=""
|
|
/>
|
|
|
|
<!-- 文本 -->
|
|
<img
|
|
class="absolute right-0 bottom-6 translate-x-[64%] translate-y-1/2 z-10"
|
|
:src="getStaticImage(item.textImage ?? '')"
|
|
alt=""
|
|
/>
|
|
|
|
<!-- 完成图标 -->
|
|
<img
|
|
:class="[
|
|
'pointer-events-none absolute z-10 w-16',
|
|
item.iconClass ?? '-right-6 -top-6',
|
|
]"
|
|
:src="
|
|
completionIcon(film.editingVideosWatched[item.videoKey] === true)
|
|
"
|
|
alt=""
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 关闭 -->
|
|
<ImgButton
|
|
class="absolute right-0 top-0 z-20"
|
|
:image="IMAGE_PATHS.COMPONENTS.BACK"
|
|
@click="handleClose"
|
|
/>
|
|
|
|
<!-- 6 个剪辑视频学完后的一次性引导 -->
|
|
<GuideSteps
|
|
v-if="showEditingCompleteGuide"
|
|
:steps="editingCompleteSteps"
|
|
position-offset-y="85%"
|
|
@complete="handleEditingCompleteGuideDone"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.start-click-hint {
|
|
animation: start-click-hint 1.2s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes start-click-hint {
|
|
0%,
|
|
100% {
|
|
transform: translateY(0) scale(1);
|
|
}
|
|
|
|
50% {
|
|
transform: translateY(-14px) scale(1.05);
|
|
}
|
|
}
|
|
|
|
.onsite-btn {
|
|
@apply relative flex flex-col items-start backdrop-blur-md rounded-2xl px-10 py-8 text-left bg-white/5 hover:bg-white/10 border border-white/10 hover:border-white/30 transition-all duration-200 cursor-pointer;
|
|
}
|
|
|
|
.onsite-btn-title {
|
|
@apply text-4xl font-bold mb-4;
|
|
}
|
|
|
|
.onsite-btn-desc {
|
|
@apply text-2xl leading-9 opacity-80;
|
|
}
|
|
</style>
|