From 49dfd794c10256f470df630d51de8c924922ad27 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Fri, 19 Jun 2026 10:08:03 +0800 Subject: [PATCH] feat(notification): add support for grouped notification display and localization --- src/layouts/components/UserNotification.vue | 117 ++++++++++++++++---- src/locales/en-US.ts | 2 + src/locales/zh-CN.ts | 2 + src/locales/zh-TW.ts | 2 + 4 files changed, 104 insertions(+), 19 deletions(-) diff --git a/src/layouts/components/UserNotification.vue b/src/layouts/components/UserNotification.vue index ab12dffb..384379dd 100644 --- a/src/layouts/components/UserNotification.vue +++ b/src/layouts/components/UserNotification.vue @@ -8,6 +8,10 @@ import { useToast } from 'vue-toastification' import { useI18n } from 'vue-i18n' import { useConfirm } from '@/composables/useConfirm' +type NotificationDisplayItem = + | { kind: 'section'; key: string; title: string; count: number } + | { kind: 'notification'; key: string; notification: SystemNotification } + const { t } = useI18n() const { useDelayedSSE } = useBackground() const $toast = useToast() @@ -31,6 +35,7 @@ const notificationClearBefore = ref(readNotificationClearBefore()) const expandedNotificationKeys = ref(new Set()) const hasUnreadNotifications = computed(() => notificationList.value.some(item => item.read === false)) +const notificationDisplayList = computed(() => buildNotificationDisplayList(notificationList.value)) /** 从本地存储读取通知清理时间戳,用于过滤已清理的历史通知。 */ function readNotificationClearBefore() { @@ -342,6 +347,37 @@ function isMediaNotification(item: SystemNotification) { return Boolean(item.image) } +/** 按系统类消息和媒体消息生成带分组标题的虚拟列表数据。 */ +function buildNotificationDisplayList(items: SystemNotification[]) { + const systemItems = items.filter(item => !isMediaNotification(item)) + const mediaItems = items.filter(isMediaNotification) + const sections = [ + { key: 'system', title: t('notification.systemMessages'), items: systemItems }, + { key: 'media', title: t('notification.mediaMessages'), items: mediaItems }, + ] + const displayItems: NotificationDisplayItem[] = [] + + sections.forEach(section => { + if (section.items.length === 0) return + + displayItems.push({ + kind: 'section', + key: `section:${section.key}`, + title: section.title, + count: section.items.length, + }) + section.items.forEach(item => { + displayItems.push({ + kind: 'notification', + key: `notification:${getNotificationKey(item)}`, + notification: item, + }) + }) + }) + + return displayItems +} + /** 判断通知正文是否已经展开。 */ function isNotificationExpanded(item: SystemNotification) { return expandedNotificationKeys.value.has(getNotificationExpansionKey(item)) @@ -457,50 +493,65 @@ useDelayedSSE(