feat: 顶部通知铃铛与站内通知中心
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m7s

This commit is contained in:
luo
2026-07-24 17:12:29 +08:00
parent 4c6d871c35
commit d1ff4d5f6c
18 changed files with 1101 additions and 519 deletions

View File

@@ -0,0 +1,90 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { NotificationService } from '@/api/modules/notification'
import type { NotificationSummary } from '@/types/api'
const getCountValue = (data: number | { count?: number; unread_count?: number } | undefined) => {
if (typeof data === 'number') return Math.max(0, data)
return Math.max(0, data?.unread_count ?? data?.count ?? 0)
}
export const useNotificationStore = defineStore('notificationStore', () => {
const unreadCount = ref(0)
const summary = ref<NotificationSummary>({ items: [], categories: {}, total_unread: 0 })
const loading = ref(false)
const refreshUnreadCount = async () => {
const response = await NotificationService.getUnreadCount()
if (response.code === 0) {
unreadCount.value = getCountValue(response.data)
}
return unreadCount.value
}
const refreshSummary = async () => {
loading.value = true
try {
const response = await NotificationService.getUnreadSummary()
if (response.code === 0 && response.data) {
summary.value = {
...response.data,
items: (response.data.items || []).slice(0, 10)
}
if (response.data.total_unread !== undefined) {
unreadCount.value = Math.max(0, response.data.total_unread)
}
}
await refreshUnreadCount()
return summary.value
} finally {
loading.value = false
}
}
const markRead = async (id: number | string) => {
const response = await NotificationService.markRead(id)
if (response.code === 0) {
unreadCount.value = Math.max(0, unreadCount.value - 1)
summary.value = {
...summary.value,
items: summary.value.items.map((item) =>
item.id === id ? { ...item, read: true, is_read: true, read_status: 'read' } : item
)
}
await refreshUnreadCount()
}
return response
}
const markAllRead = async () => {
const response = await NotificationService.markAllRead()
if (response.code === 0) {
unreadCount.value = 0
summary.value = {
...summary.value,
total_unread: 0,
categories: Object.fromEntries(
Object.keys(summary.value.categories || {}).map((key) => [key, 0])
),
items: summary.value.items.map((item) => ({
...item,
read: true,
is_read: true,
read_status: 'read'
}))
}
await refreshUnreadCount()
}
return response
}
return {
unreadCount,
summary,
loading,
refreshUnreadCount,
refreshSummary,
markRead,
markAllRead
}
})