NotificationSlider.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <template>
  2. <div class="notification-container">
  3. <img src="@/assets/images/notification.png" alt="" class="warning-icon" />
  4. <div v-if="notifications.length > 0" class="notification-content">
  5. <el-carousel
  6. ref="carousel"
  7. height="30px"
  8. direction="vertical"
  9. indicator-position="none"
  10. :autoplay="true"
  11. :interval="5000"
  12. @change="updateCurrentIndex"
  13. >
  14. <el-carousel-item
  15. v-for="notification in notifications"
  16. :key="notification.id"
  17. class="notification-item"
  18. @click="handleClick(notification)"
  19. >
  20. <span class="title">{{ notification.title }}</span>
  21. <span>{{ notification.time }}</span>
  22. </el-carousel-item>
  23. </el-carousel>
  24. </div>
  25. <div v-if="notifications.length > 0" class="arrow-controls">
  26. <button class="custom-arrow up" :disabled="currentIndex === 0" @click="scrollUp">
  27. <span class="arrow"></span>
  28. </button>
  29. <button class="custom-arrow down" :disabled="currentIndex === notifications.length - 1" @click="scrollDown">
  30. <span class="arrow"></span>
  31. </button>
  32. </div>
  33. <div v-else class="no-notifications">
  34. <p>暂无通知</p>
  35. </div>
  36. </div>
  37. </template>
  38. <script setup lang="ts">
  39. import { ref } from 'vue';
  40. export interface Notification {
  41. id: number;
  42. title: string;
  43. time: string;
  44. }
  45. defineProps<{ notifications: Notification[] }>();
  46. const emit = defineEmits<{
  47. (e: 'remove-notification', id: number): void;
  48. }>();
  49. const carousel = ref<HTMLFormElement>();
  50. const currentIndex = ref(0);
  51. const updateCurrentIndex = (current: number) => {
  52. currentIndex.value = current;
  53. };
  54. const scrollUp = () => {
  55. currentIndex.value--;
  56. carousel.value?.setActiveItem(currentIndex.value);
  57. };
  58. const scrollDown = () => {
  59. currentIndex.value++;
  60. carousel.value?.setActiveItem(currentIndex.value);
  61. };
  62. const handleClick = (notification: Notification) => {
  63. emit('remove-notification', notification.id);
  64. };
  65. </script>
  66. <style scoped lang="scss">
  67. .notification-container {
  68. width: 100%;
  69. height: 30px;
  70. display: flex;
  71. align-items: center;
  72. overflow: hidden;
  73. }
  74. .warning-icon {
  75. width: 14px;
  76. height: 14px;
  77. margin: 0 13px;
  78. }
  79. .notification-content {
  80. width: 100%;
  81. line-height: 38px;
  82. .notification-item {
  83. display: flex;
  84. align-items: center;
  85. font-size: 14px;
  86. color: rgba(0, 0, 0, 0.88);
  87. cursor: pointer;
  88. .title {
  89. margin-right: 30px;
  90. }
  91. }
  92. }
  93. .arrow-controls {
  94. display: flex;
  95. flex-direction: column;
  96. margin-left: auto;
  97. margin-right: 10px;
  98. .custom-arrow {
  99. width: 18px;
  100. height: 18px;
  101. background: #fffbe6;
  102. border: none;
  103. cursor: pointer;
  104. display: flex;
  105. align-items: center;
  106. justify-content: center;
  107. transition: all 0.3s ease;
  108. }
  109. .arrow {
  110. display: inline-block;
  111. width: 0;
  112. height: 0;
  113. border-style: solid;
  114. border-width: 6px 7px 10px 7px;
  115. border-color: transparent transparent #fae697 transparent;
  116. transition: all 0.2s ease;
  117. }
  118. .custom-arrow.down .arrow {
  119. transform: rotate(180deg);
  120. }
  121. .custom-arrow:hover {
  122. .arrow {
  123. border-color: transparent transparent #faad14 transparent;
  124. }
  125. }
  126. .custom-arrow[disabled] {
  127. opacity: 0.4;
  128. cursor: not-allowed;
  129. .arrow {
  130. border-color: transparent transparent #fae697 transparent;
  131. }
  132. }
  133. }
  134. .no-notifications {
  135. font-size: 14px;
  136. color: rgba(0, 0, 0, 0.88);
  137. }
  138. </style>