forked from zhongyidian/super_video
feat: 完善课程学习与技能树体验
完善课程资源、学习进度与技能树解锁体验,统一视频播放与引导相关交互。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
1 parent
6f289959be
commit
3e258b87d9
314 files changed
+7020
-3386
No files matched your search
@@ -14,6 +14,13 @@ 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`)
|
||||
|
||||
@@ -22,40 +29,46 @@ 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/节奏型剪辑',
|
||||
image: 'film/after-editing/img/节奏型剪辑',
|
||||
textImage: 'film/after-editing/text/节奏型剪辑',
|
||||
videoKey: 'rhythm',
|
||||
onClick: goRhythm,
|
||||
class: 'absolute right-[0px] top-[160px] bg-cover bg-center bg-no-repeat',
|
||||
class: 'absolute right-[215px] top-[170px] bg-cover bg-center bg-no-repeat',
|
||||
},
|
||||
{
|
||||
image: 'film/after-editing/声音转场',
|
||||
image: 'film/after-editing/img/声音转场',
|
||||
textImage: 'film/after-editing/text/声音转场',
|
||||
videoKey: 'soundTransition',
|
||||
onClick: goSoundTransition,
|
||||
class: 'absolute right-[42px] top-[410px] bg-cover bg-center bg-no-repeat',
|
||||
class: 'absolute right-[215px] top-[420px] bg-cover bg-center bg-no-repeat',
|
||||
},
|
||||
{
|
||||
image: 'film/after-editing/快切',
|
||||
image: 'film/after-editing/img/快切',
|
||||
textImage: 'film/after-editing/text/快切',
|
||||
videoKey: 'cut',
|
||||
onClick: goCut,
|
||||
class: 'absolute right-[520px] top-[580px] bg-cover bg-center bg-no-repeat',
|
||||
class: 'absolute right-[620px] top-[560px] bg-cover bg-center bg-no-repeat',
|
||||
},
|
||||
{
|
||||
image: 'film/after-editing/关联剪辑',
|
||||
image: 'film/after-editing/img/关联剪辑',
|
||||
textImage: 'film/after-editing/text/关联剪辑',
|
||||
videoKey: 'association',
|
||||
onClick: goAssociation,
|
||||
class:
|
||||
'absolute right-[42px] bottom-[270px] bg-cover bg-center bg-no-repeat',
|
||||
'absolute right-[215px] bottom-[290px] bg-cover bg-center bg-no-repeat',
|
||||
},
|
||||
{
|
||||
image: 'film/after-editing/连续剪辑',
|
||||
image: 'film/after-editing/img/连续剪辑',
|
||||
textImage: 'film/after-editing/text/连续剪辑',
|
||||
videoKey: 'continuity',
|
||||
onClick: goContinuity,
|
||||
class:
|
||||
'absolute right-[42px] bottom-[16px] bg-cover bg-center bg-no-repeat',
|
||||
'absolute right-[215px] bottom-[35px] bg-cover bg-center bg-no-repeat',
|
||||
},
|
||||
])
|
||||
|
||||
@@ -87,6 +100,11 @@ const goContinuity = () => {
|
||||
router.push({ name: 'FilmEditingContinuity' })
|
||||
}
|
||||
|
||||
const goEditingItem = (item: (typeof editingItems.value)[number]) => {
|
||||
if (isEditingItemLocked(item.videoKey)) return
|
||||
item.onClick()
|
||||
}
|
||||
|
||||
// 6 个剪辑子视频学习完成后的一次性引导
|
||||
const editingCompleteSteps: GuideStep[] = [
|
||||
{
|
||||
@@ -121,7 +139,11 @@ const handleEditingCompleteGuideDone = () => {
|
||||
<div
|
||||
class="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||||
:style="{
|
||||
backgroundImage: getBackgroundImage('film/after-editing/剪辑底图'),
|
||||
backgroundImage: getBackgroundImage(
|
||||
isEditingUnlocked
|
||||
? 'film/after-editing/剪辑底图亮'
|
||||
: 'film/after-editing/剪辑底图灰',
|
||||
),
|
||||
}"
|
||||
></div>
|
||||
|
||||
@@ -137,15 +159,45 @@ const handleEditingCompleteGuideDone = () => {
|
||||
:key="item.videoKey"
|
||||
:class="item.class"
|
||||
>
|
||||
<ImgButton
|
||||
:image="item.image"
|
||||
@click="item.onClick"
|
||||
/>
|
||||
<img
|
||||
class="pointer-events-none absolute left-0 top-0 z-10 h-12 w-12"
|
||||
:src="completionIcon(film.editingVideosWatched[item.videoKey] === true)"
|
||||
alt=""
|
||||
/>
|
||||
<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>
|
||||
|
||||
<!-- 关闭 -->
|
||||
@@ -167,6 +219,21 @@ const handleEditingCompleteGuideDone = () => {
|
||||
</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;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user