Files
rating/components/SuccessPopup/SuccessPopup.vue
2026-05-25 00:01:32 +08:00

183 lines
4.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="success-popup" v-if="visible" @touchmove.stop.prevent>
<view class="mask" :class="{ 'mask-show': showAnim }" @tap="close"></view>
<view class="popup-content" :class="{ 'content-show': showAnim }">
<view class="icon-wrap">
<text class="emoji">{{ actionData?.emoji || '✨' }}</text>
<!-- 环形扩散特效 -->
<view class="ring ring-1"></view>
<view class="ring ring-2"></view>
<!-- 星星点缀 -->
<view class="sparkle s-1"></view>
<view class="sparkle s-2"></view>
<view class="sparkle s-3"></view>
</view>
<text class="title">评分成功</text>
<text class="subtitle">你已将TA评价为{{ actionData?.label || '...' }}</text>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
const visible = ref(false);
const showAnim = ref(false);
const actionData = ref(null);
let timer = null;
const show = (action) => {
actionData.value = action;
visible.value = true;
// 留一点时间让DOM渲染然后添加动画类
setTimeout(() => {
showAnim.value = true;
}, 50);
if (timer) clearTimeout(timer);
// 2秒后自动关闭
timer = setTimeout(() => {
close();
}, 2000);
};
const close = () => {
showAnim.value = false;
setTimeout(() => {
visible.value = false;
}, 300); // 等待淡出动画结束
};
defineExpose({
show,
close
});
</script>
<style lang="scss" scoped>
.success-popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
}
.mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(4px);
opacity: 0;
transition: opacity 0.3s ease;
}
.mask.mask-show {
opacity: 1;
}
.popup-content {
position: relative;
width: 460rpx;
background-color: #ffffff;
border-radius: 40rpx;
padding: 64rpx 40rpx;
display: flex;
flex-direction: column;
align-items: center;
opacity: 0;
transform: scale(0.8) translateY(20rpx);
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.15);
}
.popup-content.content-show {
opacity: 1;
transform: scale(1) translateY(0);
}
.icon-wrap {
position: relative;
width: 160rpx;
height: 160rpx;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 40rpx;
}
.emoji {
font-size: 100rpx;
position: relative;
z-index: 10;
animation: emojiBounce 1.2s infinite alternate ease-in-out;
}
@keyframes emojiBounce {
0% { transform: translateY(0) scale(1); }
100% { transform: translateY(-12rpx) scale(1.05); }
}
.ring {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
border: 4rpx solid #4d44f1;
opacity: 0;
}
.ring-1 {
animation: ripple 1.6s cubic-bezier(0.21, 0.53, 0.56, 0.8) infinite;
}
.ring-2 {
animation: ripple 1.6s cubic-bezier(0.21, 0.53, 0.56, 0.8) infinite 0.8s;
}
@keyframes ripple {
0% { width: 100rpx; height: 100rpx; opacity: 0.8; }
100% { width: 260rpx; height: 260rpx; opacity: 0; }
}
.sparkle {
position: absolute;
font-size: 32rpx;
opacity: 0;
z-index: 11;
}
.s-1 { top: -10rpx; right: -20rpx; animation: popStar 1.4s ease-out infinite 0.1s; }
.s-2 { bottom: 10rpx; left: -30rpx; animation: popStar 1.4s ease-out infinite 0.6s; font-size: 24rpx; }
.s-3 { top: 60rpx; left: -40rpx; animation: popStar 1.4s ease-out infinite 1.1s; font-size: 28rpx; }
@keyframes popStar {
0% { transform: scale(0) rotate(0deg); opacity: 0; }
30% { transform: scale(1.2) rotate(45deg); opacity: 1; }
80% { transform: scale(0) rotate(90deg); opacity: 0; }
100% { transform: scale(0) rotate(90deg); opacity: 0; }
}
.title {
font-size: 40rpx;
font-weight: 800;
color: #111;
margin-bottom: 16rpx;
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
}
.subtitle {
font-size: 28rpx;
color: #666;
text-align: center;
}
</style>