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-09 09:53:06 +08:00
1 parent 6f8252472f
commit 1f8723aabd
122 files changed
+2595 -1325

No files matched your search

+82 -20
View File
@@ -1,30 +1,47 @@
import { defineComponent, ref } from 'vue'
import { getBackgroundImage, getPublicPath, getStaticImage, IMAGE_PATHS } from '@/utils'
import { computed, defineComponent, ref } from 'vue'
import {
getBackgroundImage,
getPublicPath,
getStaticImage,
IMAGE_PATHS,
} from '@/utils'
import { ImgButton } from '@/components/Button'
import { GuideSteps, ImagePreview } from '@/components'
import { GuideSteps, ImagePreview, Video } from '@/components'
import { useScale } from '@/composables/useScale'
import { useBasicElementsStore } from '@/stores/modules/basic-elements'
const CourseFrameGuide = () => (
<div class="flex items-center justify-start">
点击
<img class="w-20" src={getStaticImage(IMAGE_PATHS.BUTTONS.COURSE_FRAME)} alt="" />
<img
class="w-40"
src={getStaticImage(IMAGE_PATHS.BUTTONS.COURSE_FRAME)}
alt=""
/>
查看课程结构,快速了解每个模块的学习内容。
</div>
)
const OperateGuide = () => (
<div class="flex items-center justify-start">
<img class="w-20 inline" src={getStaticImage(IMAGE_PATHS.BUTTONS.OPERATE_GUIDE)} alt="" />
包含课程介绍和操作指南,观看指引视频,轻松上手课程。(资源建设中...)
<img
class="w-40 inline"
src={getStaticImage(IMAGE_PATHS.BUTTONS.OPERATE_GUIDE)}
alt=""
/>
包含课程介绍和操作指南,点击即可查看!
</div>
)
const StartFilmingGuide = () => (
<div class="flex items-center justify-start">
点击
<img class="w-20" src={getStaticImage(IMAGE_PATHS.BUTTONS.START_FILMING)} alt="" />
正式进入课程,开启你的短视频拍摄之旅。
<img
class="w-40"
src={getStaticImage(IMAGE_PATHS.BUTTONS.START_FILMING)}
alt=""
/>
,一起我们的短视频学习之旅吧!
</div>
)
@@ -38,7 +55,7 @@ export default defineComponent({
content: '欢迎来到《短视频达人养成记》网络课程的学习!',
highlightSelector: null,
audioSrc: getPublicPath('audio/py_0_001.MP3'),
positionOffsetY: '80%'
positionOffsetY: '80%',
},
{
id: 'step-2',
@@ -46,7 +63,7 @@ export default defineComponent({
content: CourseFrameGuide,
highlightSelector: '.kecheng-wrapper',
audioSrc: getPublicPath('audio/py_0_002.MP3'),
positionOffsetY: '40%'
positionOffsetY: '40%',
},
{
id: 'step-3',
@@ -54,7 +71,7 @@ export default defineComponent({
content: OperateGuide,
highlightSelector: '.zhiying-wrapper',
audioSrc: getPublicPath('audio/py_0_003.MP3'),
positionOffsetY: '40%'
positionOffsetY: '40%',
},
{
id: 'step-4',
@@ -62,15 +79,27 @@ export default defineComponent({
content: StartFilmingGuide,
highlightSelector: '.start-filming-wrapper',
audioSrc: getPublicPath('audio/py_0_004.MP3'),
positionOffsetY: '40%'
}
positionOffsetY: '40%',
},
])
const basicElementsStore = useBasicElementsStore()
const guideKey = 'home-intro'
const showGuide = ref(!basicElementsStore.guideShown[guideKey])
const isFirstVisit = !basicElementsStore.guideShown[guideKey]
const showGuide = ref(isFirstVisit)
const { scale, offsetX, offsetY } = useScale()
if (showGuide.value) {
// 首次进入的视频播放序列
const introVideos = computed(() => [
getPublicPath('video/campus life.mp4'),
getPublicPath('video/new/xsdh_CapCut_Tutorial.mp4'),
])
const introVideoIndex = ref(0)
const showIntroVideo = ref(isFirstVisit)
const currentIntroSrc = computed(
() => introVideos.value[introVideoIndex.value] ?? '',
)
if (isFirstVisit) {
basicElementsStore.markGuideShown(guideKey)
}
@@ -78,11 +107,24 @@ export default defineComponent({
showGuide.value = false
}
const handleIntroVideoEnded = () => {
if (introVideoIndex.value < introVideos.value.length - 1) {
introVideoIndex.value++
} else {
showIntroVideo.value = false
// 引导步骤在视频播放结束后出现
}
}
const openMindMap = () => {
ImagePreview({
images: [getStaticImage('maps/dt')],
maskClosable: true,
getScaleMetrics: () => ({ scale: scale.value, offsetX: offsetX.value, offsetY: offsetY.value })
getScaleMetrics: () => ({
scale: scale.value,
offsetX: offsetX.value,
offsetY: offsetY.value,
}),
})
}
@@ -94,19 +136,39 @@ export default defineComponent({
/>
<div class="absolute right-[420px] bottom-[200px] start-filming-wrapper">
<ImgButton image="home/action-btn" path={{ name: 'Action' }} />
<ImgButton
image="home/action-btn"
path={{ name: 'Action' }}
/>
</div>
<div class="absolute right-20 bottom-36 kecheng-wrapper">
<ImgButton image={IMAGE_PATHS.BUTTONS.COURSE_FRAME} onClick={openMindMap} />
<ImgButton
image={IMAGE_PATHS.BUTTONS.COURSE_FRAME}
onClick={openMindMap}
/>
</div>
<div class="absolute right-20 bottom-10 zhiying-wrapper">
<ImgButton image={IMAGE_PATHS.BUTTONS.OPERATE_GUIDE} />
</div>
{showIntroVideo.value && (
<div class="absolute inset-0 z-[10000] bg-black flex items-center justify-center">
<Video
src={currentIntroSrc.value}
autoplay={true}
muted={false}
controls={true}
volume={1}
fit="contain"
onEnded={handleIntroVideoEnded}
/>
</div>
)}
<GuideSteps
visible={showGuide.value}
visible={showGuide.value && !showIntroVideo.value}
steps={guideSteps.value}
highlightPadding={12}
highlightRadius={16}
@@ -116,5 +178,5 @@ export default defineComponent({
/>
</div>
)
}
},
})