|
@@ -1,41 +1,45 @@
|
|
-<script lang="ts" setup>
|
|
|
|
-interface Notification {
|
|
|
|
- id: number
|
|
|
|
- name: string
|
|
|
|
- time: string
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-interface Props {
|
|
|
|
- notifications?: Notification[]
|
|
|
|
- interval?: number
|
|
|
|
- top?: string
|
|
|
|
-}
|
|
|
|
|
|
+<script setup>
|
|
|
|
+import { t } from '@/locale'
|
|
|
|
|
|
-const props = withDefaults(defineProps<Props>(), {
|
|
|
|
- notifications: () => [
|
|
|
|
- { id: 1, name: 'Aamir Khan', time: '10s' },
|
|
|
|
- { id: 2, name: 'John Smith', time: '30s' },
|
|
|
|
- { id: 3, name: 'Maria Garcia', time: '1m' },
|
|
|
|
- ],
|
|
|
|
- interval: 3000,
|
|
|
|
- top: '0px',
|
|
|
|
|
|
+const props = defineProps({
|
|
|
|
+ notifications: {
|
|
|
|
+ type: Array,
|
|
|
|
+ default: () => [],
|
|
|
|
+ },
|
|
|
|
+ interval: {
|
|
|
|
+ type: Number,
|
|
|
|
+ default: 3000,
|
|
|
|
+ },
|
|
|
|
+ top: {
|
|
|
|
+ type: String,
|
|
|
|
+ default: '0px',
|
|
|
|
+ },
|
|
})
|
|
})
|
|
|
|
|
|
const notificationIndex = ref(0)
|
|
const notificationIndex = ref(0)
|
|
const prevNotificationIndex = ref(0)
|
|
const prevNotificationIndex = ref(0)
|
|
-let notificationTimer: number | null = null
|
|
|
|
|
|
+const isAnimating = ref(false)
|
|
|
|
+let notificationTimer = null
|
|
|
|
|
|
// 启动通知轮播
|
|
// 启动通知轮播
|
|
function startNotificationCarousel() {
|
|
function startNotificationCarousel() {
|
|
- if (props.notifications.length <= 1)
|
|
|
|
|
|
+ if (props.notifications.length === 0)
|
|
return
|
|
return
|
|
|
|
|
|
notificationTimer = setInterval(() => {
|
|
notificationTimer = setInterval(() => {
|
|
|
|
+ // 触发动画效果
|
|
|
|
+ isAnimating.value = true
|
|
|
|
+
|
|
// 保存当前索引
|
|
// 保存当前索引
|
|
prevNotificationIndex.value = notificationIndex.value
|
|
prevNotificationIndex.value = notificationIndex.value
|
|
|
|
|
|
// 更新为下一个索引
|
|
// 更新为下一个索引
|
|
notificationIndex.value = (notificationIndex.value + 1) % props.notifications.length
|
|
notificationIndex.value = (notificationIndex.value + 1) % props.notifications.length
|
|
|
|
+
|
|
|
|
+ // 动画结束后重置状态
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ isAnimating.value = false
|
|
|
|
+ }, 300) // 动画持续300ms
|
|
}, props.interval)
|
|
}, props.interval)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -90,10 +94,16 @@ defineExpose({
|
|
v-for="(notification, index) in notifications"
|
|
v-for="(notification, index) in notifications"
|
|
:key="notification.id"
|
|
:key="notification.id"
|
|
class="flex items-center rounded-full bg-#000000/60 py-8rpx pl-8rpx pr-14rpx transition-all duration-500 ease-in-out"
|
|
class="flex items-center rounded-full bg-#000000/60 py-8rpx pl-8rpx pr-14rpx transition-all duration-500 ease-in-out"
|
|
|
|
+ :class="{
|
|
|
|
+ 'animate-pulse': notifications.length === 1 && isAnimating,
|
|
|
|
+ 'animate-bounce': notifications.length === 1 && isAnimating,
|
|
|
|
+ }"
|
|
:style="{
|
|
:style="{
|
|
opacity: index === notificationIndex ? 1 : 0,
|
|
opacity: index === notificationIndex ? 1 : 0,
|
|
- transform: index === notificationIndex ? 'translateY(0)'
|
|
|
|
- : (index === prevNotificationIndex ? 'translateY(-100%)' : 'translateY(100%)'),
|
|
|
|
|
|
+ transform: notifications.length === 1
|
|
|
|
+ ? (isAnimating ? 'translateY(0) scale(1.05)' : 'translateY(0) scale(1)')
|
|
|
|
+ : (index === notificationIndex ? 'translateY(0)'
|
|
|
|
+ : (index === prevNotificationIndex ? 'translateY(-100%)' : 'translateY(100%)')),
|
|
position: 'absolute',
|
|
position: 'absolute',
|
|
top: 0,
|
|
top: 0,
|
|
left: 0,
|
|
left: 0,
|
|
@@ -101,9 +111,13 @@ defineExpose({
|
|
zIndex: index === notificationIndex ? 2 : 1,
|
|
zIndex: index === notificationIndex ? 2 : 1,
|
|
}"
|
|
}"
|
|
>
|
|
>
|
|
- <wd-img width="40rpx" round height="40rpx" src="/static/images/avatar.jpg" />
|
|
|
|
|
|
+ <wd-img width="40rpx" round height="40rpx" :src="notification.headPic" />
|
|
<text class="ml-12rpx truncate text-24rpx text-white">
|
|
<text class="ml-12rpx truncate text-24rpx text-white">
|
|
- {{ notification.name }} joined this group {{ notification.time }} ago!
|
|
|
|
|
|
+ {{ t('productDetail.notification.message', {
|
|
|
|
+ name: notification.name,
|
|
|
|
+ action: notification.kId === 0 ? t('productDetail.notification.opened') : t('productDetail.notification.joined'),
|
|
|
|
+ time: notification.time,
|
|
|
|
+ }) }}
|
|
</text>
|
|
</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|