BaseLoading.vue 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. <template>
  2. <view class="base-loading" :class="{ 'base-loading--overlay': overlay }" v-if="loading">
  3. <view class="base-loading__spinner" v-if="type === 'spinner'">
  4. <view class="base-loading__dot" v-for="i in 3" :key="i"></view>
  5. </view>
  6. <text class="base-loading__text" v-if="text">{{ text }}</text>
  7. </view>
  8. </template>
  9. <script>
  10. export default {
  11. name: 'BaseLoading',
  12. props: {
  13. loading: { type: Boolean, default: false },
  14. type: { type: String, default: 'spinner' },
  15. // 'spinner' | 'skeleton'
  16. text: { type: String, default: '' },
  17. overlay: { type: Boolean, default: false }
  18. }
  19. }
  20. </script>
  21. <style scoped>
  22. .base-loading {
  23. display: flex;
  24. flex-direction: column;
  25. align-items: center;
  26. justify-content: center;
  27. padding: 48rpx;
  28. }
  29. .base-loading--overlay {
  30. position: fixed;
  31. top: 0;
  32. left: 0;
  33. right: 0;
  34. bottom: 0;
  35. background: rgba(255, 255, 255, 0.8);
  36. z-index: 999;
  37. padding: 0;
  38. }
  39. /* Spinner dots */
  40. .base-loading__spinner {
  41. display: flex;
  42. align-items: center;
  43. gap: 12rpx;
  44. margin-bottom: 16rpx;
  45. }
  46. .base-loading__dot {
  47. width: 16rpx;
  48. height: 16rpx;
  49. border-radius: 50%;
  50. background: var(--color-primary, #F97316);
  51. animation: dot-bounce 1.2s ease-in-out infinite;
  52. }
  53. .base-loading__dot:nth-child(2) { animation-delay: 0.2s; }
  54. .base-loading__dot:nth-child(3) { animation-delay: 0.4s; }
  55. .base-loading__text {
  56. font-size: 24rpx;
  57. color: var(--muted, #94A3B8);
  58. }
  59. @keyframes dot-bounce {
  60. 0%, 80%, 100% {
  61. transform: scale(0.6);
  62. opacity: 0.4;
  63. }
  64. 40% {
  65. transform: scale(1);
  66. opacity: 1;
  67. }
  68. }
  69. </style>