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

+46 -19
View File
@@ -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>