feat: 完善课程学习与技能树体验

完善课程资源、学习进度与技能树解锁体验,统一视频播放与引导相关交互。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
zhongyidianandClaude Opus 4.7 committed 2026-05-24 10:30:18 +08:00
1 parent 6f289959be
commit 3e258b87d9
314 files changed
+7020 -3386

No files matched your search

+67 -24
View File
@@ -5,7 +5,7 @@ import { ImgButton } from '@/components/Button'
import { StarRating } from '@/components/Rating'
import { useRouter } from 'vue-router'
import BackToTopIcon from '@/assets/images/components/置顶.png'
import { GuideSteps, GuideStepsItem } from '@/components/Guide'
import { GuideSteps, type GuideStep } from '@/components/Guide'
import { useFilmStore } from '@/stores/modules/film'
const router = useRouter()
@@ -40,22 +40,67 @@ const showSittingPerson = computed<boolean>(() => {
const visible = ref<boolean>(false)
const guideKeyPrefix = 'film-practice-page'
//每一页的引导词
const steps = ref([
'欢迎来到实战操作台! 这里的内容很丰富,滚动鼠标就能浏览到全部内容啦~',
'点击【我的创作笔记】,编写创作思路~',
'点击【查看】按钮,欣赏他人实战作品~',
])
const pageGuideSteps: Record<number, GuideStep[]> = {
0: [
{
id: 'film-practice-page-0-2',
content: '这里可以查看任务描述。',
highlightSelector: '.desc-img',
positionOffsetY: '87%',
audioSrc: '/audio/py_6_002.MP3',
},
{
id: 'film-practice-page-0-3',
content: '这里可以查看任务具体要求。',
highlightSelector: '.task-btn',
positionOffsetY: '50%',
audioSrc: '/audio/py_6_003.MP3',
},
{
id: 'film-practice-page-0-4',
content: '点击下滑箭头,可查看更多学习与实践内容。',
highlightSelector: '.down-scroll-hint',
audioSrc: '/audio/py_6_005.MP3',
},
],
1: [
{
id: 'film-practice-page-1-1',
content: '点击【我的创作笔记】,记录自己的创作思路与作品说明。',
highlightSelector: '.my-notes-btn',
audioSrc: '/audio/py_6_004.MP3',
},
],
2: [
{
id: 'film-practice-page-2-1',
content: '点击【查看】按钮,欣赏学长学姐们的优秀实践作品。',
highlightSelector: '.view-btn',
positionOffsetY: '50%',
audioSrc: '/audio/py_6_006.MP3',
},
{
id: 'film-practice-page-2-3',
content: '点击向上按钮,可快速返回实战操作台首页。',
highlightSelector: '.back-to-top-btn',
positionOffsetY: '50%',
audioSrc: '/audio/py_6_009.MP3',
},
],
}
const currentGuideKey = computed(() => `${guideKeyPrefix}-${currentPage.value}`)
const contentSteps = computed(() => {
return steps.value[currentPage.value]
})
const currentGuideSteps = computed(
() => pageGuideSteps[currentPage.value] ?? [],
)
const showPageGuide = (): void => {
if (filmStore.guideShown[currentGuideKey.value]) return
visible.value = true
}
const handlePageGuideComplete = (): void => {
visible.value = false
filmStore.markGuideShown(currentGuideKey.value)
}
@@ -76,8 +121,7 @@ const worksList = ref<WorkItem[]>([
title: '学生案例',
stars: 4,
path: '/video/film/practice/film_anli1.mp4',
description:
'作品简介作品简介作品简介作品简介作品简介作品简介作品简介作品简介作品简介作品简介作品简介作品简介作品简介作品简介作品简介作品简介作品简介',
description: '27084 施颖雯 杨可馨 胡悦莹 陆佳慧 雷鑫丽',
},
])
@@ -226,16 +270,16 @@ onUnmounted(() => {
:image="IMAGE_PATHS.COMPONENTS.BACK"
@click="handleClose"
/>
<!-- 实战操作台 -->
<!-- 操作描述 -->
<div class="w-full h-[1080px] bg-[#F5EFE6] relative">
<ImgButton
class="absolute left-40 bottom-14 z-10"
class="task-btn absolute left-40 bottom-14 z-10"
image="vlog/practice/查看任务要求"
@click="scrollToNextPage"
/>
<!-- img -->
<img
class="absolute left-0 top-0 z-10"
class="desc-img absolute left-0 top-0 z-10"
draggable="false"
:src="getStaticImage('film/practice/电影')"
alt=""
@@ -253,7 +297,7 @@ onUnmounted(() => {
:style="{ backgroundImage: getBackgroundImage('vlog/practice/背景2') }"
>
<ImgButton
class="absolute right-20 bottom-0 z-99"
class="my-notes-btn absolute right-20 bottom-0 z-99"
image="vlog/practice/我的创作笔记btn"
path="/film/practice/my-notes"
/>
@@ -298,7 +342,7 @@ onUnmounted(() => {
:style="{ transform: `translateX(-${worksScrollIndex * 509}px)` }"
>
<div
v-for="work in worksList"
v-for="(work, index) in worksList"
:key="work.id"
class="w-[503px] h-[722px] flex-shrink-0 rounded-[40px] overflow-hidden bg-[#FFF8F0] py-8 px-6"
>
@@ -329,6 +373,7 @@ onUnmounted(() => {
</p>
<!-- 查看按钮 -->
<ImgButton
:class="index === 0 ? 'view-btn' : ''"
image="vlog/practice/查看"
:path="`/film/practice/video/${encodeURIComponent(work.path)}`"
/>
@@ -372,7 +417,7 @@ onUnmounted(() => {
<!-- 回到顶部按钮 - 最后一页显示 -->
<img
v-show="isLastPage"
class="absolute bottom-10 left-1/2 -translate-x-1/2 cursor-pointer transition-all duration-300 hover:scale-105"
class="back-to-top-btn absolute bottom-10 left-1/2 -translate-x-1/2 cursor-pointer transition-all duration-300 hover:scale-105"
:src="BackToTopIcon"
@click="scrollToTop"
/>
@@ -406,11 +451,9 @@ onUnmounted(() => {
<GuideSteps
v-if="visible"
position-offset-y="70%"
@complete="visible = false"
>
<GuideStepsItem>{{ contentSteps }}</GuideStepsItem>
</GuideSteps>
:steps="currentGuideSteps"
@complete="handlePageGuideComplete"
/>
</div>
</template>