Files
AgentCoord/frontend/src/composables/useNotification.ts
2026-01-26 17:25:23 +08:00

164 lines
3.9 KiB
TypeScript

import { ref } from 'vue'
export interface NotificationItem {
id: string
title: string
message?: string
type?: 'success' | 'warning' | 'info' | 'error'
duration?: number
showProgress?: boolean
progress?: number
zIndex?: number
onClose?: () => void
// 详细进度信息
detailTitle?: string
detailMessage?: string
}
const notifications = ref<NotificationItem[]>([])
let notificationIdCounter = 0
let zIndexCounter = 1000
export function useNotification() {
const addNotification = (notification: Omit<NotificationItem, 'id' | 'zIndex'>) => {
const id = `notification-${notificationIdCounter++}`
const newNotification: NotificationItem = {
...notification,
id,
zIndex: ++zIndexCounter,
}
notifications.value.push(newNotification)
// 自动关闭
if (notification.duration && notification.duration > 0) {
setTimeout(() => {
removeNotification(id)
}, notification.duration)
}
return id
}
const removeNotification = (id: string) => {
const index = notifications.value.findIndex((n) => n.id === id)
if (index !== -1) {
const notification = notifications.value[index]
notifications.value.splice(index, 1)
notification.onClose?.()
}
}
const success = (title: string, message?: string, options?: Partial<NotificationItem>) => {
return addNotification({
title,
message,
type: 'success',
duration: 3000,
...options,
})
}
const warning = (title: string, message?: string, options?: Partial<NotificationItem>) => {
return addNotification({
title,
message,
type: 'warning',
duration: 3000,
...options,
})
}
const info = (title: string, message?: string, options?: Partial<NotificationItem>) => {
return addNotification({
title,
message,
type: 'info',
duration: 3000,
...options,
})
}
const error = (title: string, message?: string, options?: Partial<NotificationItem>) => {
return addNotification({
title,
message,
type: 'error',
duration: 5000,
...options,
})
}
const progress = (
title: string,
current: number,
total: number,
options?: Partial<NotificationItem>,
) => {
const progressPercent = Math.round((current / total) * 100)
return addNotification({
title,
message: `${current}/${total}`,
type: 'info',
showProgress: true,
progress: progressPercent,
duration: 0, // 不自动关闭
...options,
})
}
const updateProgress = (id: string, current: number, total: number) => {
const notification = notifications.value.find((n) => n.id === id)
if (notification) {
notification.progress = Math.round((current / total) * 100)
notification.message = `${current}/${total}`
}
}
const updateProgressDetail = (
id: string,
detailTitle: string,
detailMessage: string,
current?: number,
total?: number
) => {
const notification = notifications.value.find((n) => n.id === id)
if (notification) {
notification.detailTitle = detailTitle
notification.detailMessage = detailMessage
if (current !== undefined && total !== undefined) {
notification.progress = Math.round((current / total) * 100)
notification.message = `${current}/${total}`
}
}
}
// 更新通知的主标题
const updateNotificationTitle = (id: string, title: string) => {
const notification = notifications.value.find((n) => n.id === id)
if (notification) {
notification.title = title
}
}
const clear = () => {
notifications.value.forEach((n) => n.onClose?.())
notifications.value = []
}
return {
notifications,
addNotification,
removeNotification,
success,
warning,
info,
error,
progress,
updateProgress,
updateProgressDetail,
updateNotificationTitle,
clear,
}
}