motion-knowledge and ContactFloatingButton optimize

This commit is contained in:
WindowBird 2025-10-27 13:39:43 +08:00
parent 58b3e14e8e
commit a27e168865
4 changed files with 22 additions and 106 deletions

View File

@ -1,97 +1,22 @@
<!-- components/ContactFloatingButton.vue -->
<template>
<div class="fixed right-6 top-1/2 transform -translate-y-1/2 z-50 flex items-center">
<!-- 二维码面板 -->
<Transition name="fade-slide">
<div v-if="showQR" class="w-64 overflow-hidden transition-all duration-300 ease-out;">
<img
:alt="qrAltText"
:src="qrImage"
class="w-full h-auto border-4 border-white rounded-lg shadow-xl"
>
</div>
</Transition>
<UPopover mode="hover">
<UButton
<!-- 客服按钮 -->
<button
:class="{ 'ml-2': showQR }"
class="bg-green-500 hover:bg-green-600 text-white px-4 py-3 rounded-l-lg shadow-lg transition-all duration-300"
@click="onButtonClick"
@mouseenter="showQR = true"
@mouseleave="onMouseLeave"
>
<span class="button-text">{{ buttonText }}</span>
</button>
class="bg-green-500 hover:bg-green-600 text-white px-4 py-3 rounded-l-lg shadow-lg transition-all duration-300"
color="neutral" label="联系客服"
variant="subtle"/>
<template #content>
<div class="w-64 overflow-hidden transition-all duration-300 ease-out;">
<img
alt="QRCode"
class="w-full h-auto border-4 border-white rounded-lg shadow-xl"
src="/img/QRCode.png"
>
</div>
</template>
</UPopover>
</div>
</template>
<script setup>
import {ref} from 'vue'
const props = defineProps({
qrImage: {
type: String,
default: '/img/img.png'
},
qrAltText: {
type: String,
default: '客服二维码'
},
buttonText: {
type: String,
default: '联系客服'
},
hoverDelay: {
type: Number,
default: 300 // (ms)
}
})
const emit = defineEmits(['click'])
const showQR = ref(false)
let hideTimer = null
const onMouseLeave = () => {
hideTimer = setTimeout(() => {
showQR.value = false
}, props.hoverDelay)
}
const cancelHide = () => {
if (hideTimer) {
clearTimeout(hideTimer)
hideTimer = null
}
}
const onButtonClick = () => {
emit('click')
//
cancelHide()
showQR.value = true
}
</script>
<style scoped>
/* 按钮样式 */
.writing-mode-vertical {
writing-mode: vertical-rl;
text-orientation: mixed;
}
/* 动画效果 */
.fade-slide-enter-active,
.fade-slide-leave-active {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.fade-slide-enter-from,
.fade-slide-leave-to {
opacity: 0;
transform: translateX(10px);
}
</style>

View File

@ -93,22 +93,13 @@ const cardItems = ref([
class="shadow-lg hover:shadow-2xl transition-shadow duration-300 h-full"
reverse
>
<Motion
:initial="{ scale: 0.9, opacity: 0.7 }"
:transition="{ duration: 0.4, delay: 0.2 + 0.1 * index }"
:while-hover="{
scale: 1.1,
rotate: 2,
transition: { duration: 0.3 }
}"
:while-in-view="{ scale: 1, opacity: 1 }"
<img
:src="item.image"
alt="Illustration"
class="w-full shadow-2xl rounded-2xl"
>
<img
:src="item.image"
alt="Illustration"
class="w-full shadow-2xl rounded-2xl"
>
</Motion>
</UPageCTA>
</Motion>
</view>
@ -120,7 +111,7 @@ const cardItems = ref([
:transition="{
duration: 0.8,
delay: 0.3,
type: 'spring',
stiffness: 100,
damping: 15
}"

BIN
public/img/QRCode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 MiB