forked from zhongyidian/super_video
feat: 完善课程引导与实战评价体验
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6f8252472f
commit
1f8723aabd
122 files changed
+2595
-1325
No files matched your search
@@ -1,14 +1,20 @@
|
||||
<template>
|
||||
<teleport to="body">
|
||||
<div class="guide-steps-container" v-if="show">
|
||||
<div
|
||||
class="guide-steps-container"
|
||||
v-if="show"
|
||||
>
|
||||
<SpotlightOverlay
|
||||
:visible="Boolean(currentHighlightSelector)"
|
||||
:visible="show"
|
||||
:target-selector="currentHighlightSelector"
|
||||
:padding="currentHighlightPadding"
|
||||
:border-radius="currentHighlightRadius"
|
||||
:highlight-mode="currentHighlightMode"
|
||||
/>
|
||||
<div class="guide-align" :style="alignStyle">
|
||||
<div
|
||||
class="guide-align"
|
||||
:style="alignStyle"
|
||||
>
|
||||
<GuideDragon
|
||||
:show-skip="currentStep < totalSteps"
|
||||
:current-step="currentStep"
|
||||
@@ -44,9 +50,15 @@
|
||||
@continue="handleNext"
|
||||
>
|
||||
<!-- 支持组件形式的 content -->
|
||||
<component v-if="isCurrentStepComponent" :is="currentStepContentComponent" />
|
||||
<component
|
||||
v-if="isCurrentStepComponent"
|
||||
:is="currentStepContentComponent"
|
||||
/>
|
||||
<!-- 支持字符串形式的 content -->
|
||||
<div v-else v-html="currentStepContent"></div>
|
||||
<div
|
||||
v-else
|
||||
v-html="currentStepContent"
|
||||
></div>
|
||||
</GuideStepsItem>
|
||||
</template>
|
||||
</GuideDragon>
|
||||
@@ -101,7 +113,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
highlightRadius: 16,
|
||||
highlightMode: 'border',
|
||||
positionOffsetY: '50%',
|
||||
visible: true
|
||||
visible: true,
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emits>()
|
||||
@@ -126,7 +138,7 @@ const alignStyle = reactive<{
|
||||
top: '0px',
|
||||
transform: 'scale(1)',
|
||||
width: '1920px',
|
||||
height: '1080px'
|
||||
height: '1080px',
|
||||
})
|
||||
const normalizeSelector = (selector?: string | null) => {
|
||||
if (!selector) return null
|
||||
@@ -157,21 +169,25 @@ const currentStepData = computed(() => {
|
||||
return props.steps[currentStepIndex.value] || null
|
||||
})
|
||||
|
||||
const currentStepConfig = computed(() => props.steps[currentStepIndex.value] || null)
|
||||
const currentStepConfig = computed(
|
||||
() => props.steps[currentStepIndex.value] || null,
|
||||
)
|
||||
const currentHighlightSelector = computed(() => {
|
||||
return normalizeSelector(currentStepConfig.value?.highlightSelector ?? props.highlightSelector)
|
||||
return normalizeSelector(
|
||||
currentStepConfig.value?.highlightSelector ?? props.highlightSelector,
|
||||
)
|
||||
})
|
||||
const currentHighlightPadding = computed(
|
||||
() => currentStepConfig.value?.highlightPadding ?? props.highlightPadding
|
||||
() => currentStepConfig.value?.highlightPadding ?? props.highlightPadding,
|
||||
)
|
||||
const currentHighlightRadius = computed(
|
||||
() => currentStepConfig.value?.highlightRadius ?? props.highlightRadius
|
||||
() => currentStepConfig.value?.highlightRadius ?? props.highlightRadius,
|
||||
)
|
||||
const currentHighlightMode = computed(
|
||||
() => currentStepConfig.value?.highlightMode ?? props.highlightMode
|
||||
() => currentStepConfig.value?.highlightMode ?? props.highlightMode,
|
||||
)
|
||||
const currentPositionOffsetY = computed(
|
||||
() => currentStepConfig.value?.positionOffsetY ?? props.positionOffsetY
|
||||
() => currentStepConfig.value?.positionOffsetY ?? props.positionOffsetY,
|
||||
)
|
||||
|
||||
const currentStepComponent = computed(() => {
|
||||
@@ -210,7 +226,9 @@ const currentStepContentComponent = computed(() => {
|
||||
})
|
||||
|
||||
const handleNext = () => {
|
||||
const maxSteps = useSlotMode.value ? slotSteps.value.length : props.steps.length
|
||||
const maxSteps = useSlotMode.value
|
||||
? slotSteps.value.length
|
||||
: props.steps.length
|
||||
if (maxSteps === 0) {
|
||||
handleComplete()
|
||||
return
|
||||
@@ -234,7 +252,9 @@ const handleComplete = () => {
|
||||
}
|
||||
|
||||
const goToStep = (index: number) => {
|
||||
const maxSteps = useSlotMode.value ? slotSteps.value.length : props.steps.length
|
||||
const maxSteps = useSlotMode.value
|
||||
? slotSteps.value.length
|
||||
: props.steps.length
|
||||
if (maxSteps === 0) {
|
||||
console.warn('GuideSteps goToStep: No steps available')
|
||||
return
|
||||
@@ -244,7 +264,12 @@ const goToStep = (index: number) => {
|
||||
currentStepIndex.value = index
|
||||
emit('step-change', currentStepData.value, currentStepIndex.value)
|
||||
} else {
|
||||
console.warn('GuideSteps goToStep: Invalid step index', index, 'max:', maxSteps - 1)
|
||||
console.warn(
|
||||
'GuideSteps goToStep: Invalid step index',
|
||||
index,
|
||||
'max:',
|
||||
maxSteps - 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +308,9 @@ let autoPlayTimer: number | null = null
|
||||
const startAutoPlay = () => {
|
||||
if (props.autoPlayInterval > 0) {
|
||||
autoPlayTimer = window.setInterval(() => {
|
||||
const maxSteps = useSlotMode.value ? slotSteps.value.length : props.steps.length
|
||||
const maxSteps = useSlotMode.value
|
||||
? slotSteps.value.length
|
||||
: props.steps.length
|
||||
if (currentStepIndex.value < maxSteps - 1) {
|
||||
handleNext()
|
||||
} else {
|
||||
@@ -317,7 +344,7 @@ onMounted(() => {
|
||||
if (transform && transform !== 'none') {
|
||||
const match = transform.match(/matrix\(([^)]+)\)/)
|
||||
if (match) {
|
||||
const parts = match[1].split(',').map(s => parseFloat(s.trim()))
|
||||
const parts = match[1].split(',').map((s) => parseFloat(s.trim()))
|
||||
if (!Number.isNaN(parts[0])) scale = parts[0]
|
||||
}
|
||||
}
|
||||
@@ -343,7 +370,7 @@ defineExpose({
|
||||
currentStep,
|
||||
totalSteps,
|
||||
startAutoPlay,
|
||||
stopAutoPlay
|
||||
stopAutoPlay,
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in new issue
Block a user