FeedbackToast.vue 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. <template>
  2. <view class="feedback-overlay" v-if="visible" @touchmove.stop.prevent>
  3. <view class="feedback-toast" :class="{ 'feedback-enter': animating, 'feedback-leave': !animating }">
  4. <view class="feedback-icon">{{ icon }}</view>
  5. <text class="feedback-text">{{ text }}</text>
  6. </view>
  7. </view>
  8. </template>
  9. <script>
  10. export default {
  11. props: {
  12. visible: { type: Boolean, default: false },
  13. text: { type: String, default: '' },
  14. icon: { type: String, default: '✅' },
  15. animating: { type: Boolean, default: false }
  16. }
  17. }
  18. </script>
  19. <style scoped>
  20. .feedback-overlay {
  21. position: fixed;
  22. top: 0;
  23. left: 0;
  24. right: 0;
  25. bottom: 0;
  26. z-index: 9999;
  27. pointer-events: none;
  28. display: flex;
  29. align-items: center;
  30. justify-content: center;
  31. }
  32. .feedback-toast {
  33. display: flex;
  34. flex-direction: column;
  35. align-items: center;
  36. gap: 12rpx;
  37. background: rgba(0,0,0,0.75);
  38. border-radius: 24rpx;
  39. padding: 40rpx 60rpx;
  40. backdrop-filter: blur(4px);
  41. }
  42. .feedback-icon { font-size: 80rpx; }
  43. .feedback-text {
  44. font-size: 32rpx;
  45. color: #fff;
  46. font-weight: 600;
  47. text-align: center;
  48. }
  49. .feedback-enter {
  50. animation: feedbackPopIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
  51. }
  52. .feedback-leave {
  53. animation: feedbackFadeOut 0.3s ease forwards;
  54. }
  55. </style>
  56. <style>
  57. @keyframes feedbackPopIn {
  58. 0% { transform: scale(0.3); opacity: 0; }
  59. 100% { transform: scale(1); opacity: 1; }
  60. }
  61. @keyframes feedbackFadeOut {
  62. 0% { opacity: 1; }
  63. 100% { opacity: 0; }
  64. }
  65. </style>