返回 AiToEarn
notification.ts
根目录 / project / aitoearn-web / src / utils / ui / notification.ts
1 /**
2 * notification - 全局通知工具
3 * 支持 success/error/warning/info 四种类型
4 */
5
6 type NotificationType = 'success' | 'error' | 'warning' | 'info' | 'loading'
7
8 interface NotificationOptions {
9 key?: string
10 id?: string
11 duration?: number
12 content?: React.ReactNode
13 }
14
15 interface NotificationPayload {
16 key?: string
17 id?: string
18 content?: React.ReactNode
19 duration?: number
20 type?: NotificationType
21 _uid?: string
22 }
23
24 function emit(payload: NotificationPayload) {
25 if (typeof window === 'undefined') {
26 // server-side fallback: no-op
27 return
28 }
29 try {
30 window.dispatchEvent(new CustomEvent('aito:notification', { detail: payload }))
31 }
32 catch {
33 // ignore
34 }
35 }
36
37 function removeEmit(payload: { key?: string, id?: string, _uid?: string }) {
38 if (typeof window === 'undefined')
39 return
40 try {
41 window.dispatchEvent(new CustomEvent('aito:notification-remove', { detail: payload }))
42 }
43 catch {
44 // ignore
45 }
46 }
47
48 function createNotification(type: NotificationType) {
49 return (content: React.ReactNode | NotificationOptions, options?: NotificationOptions) => {
50 const payload
51 = typeof content === 'object' && content !== null && 'content' in content
52 ? {
53 key: (content as NotificationOptions).key,
54 id: (content as NotificationOptions).id,
55 content: (content as NotificationOptions).content,
56 duration: (content as NotificationOptions).duration,
57 }
58 : {
59 key: options?.key,
60 id: options?.id,
61 content: content as React.ReactNode,
62 duration: options?.duration,
63 }
64 const uid = `${Date.now()}-${Math.floor(Math.random() * 100000)}`
65 emit({ ...payload, type, _uid: uid })
66 return uid
67 }
68 }
69
70 export const notification = {
71 success: createNotification('success'),
72 error: createNotification('error'),
73 warning: createNotification('warning'),
74 info: createNotification('info'),
75 loading: createNotification('loading'),
76
77 open(options: {
78 key?: string
79 type?: NotificationType
80 content: React.ReactNode
81 duration?: number
82 }) {
83 const uid = `${Date.now()}-${Math.floor(Math.random() * 100000)}`
84 const payload: NotificationPayload = {
85 key: options.key,
86 id: options.key,
87 content: options.content,
88 duration: options.duration,
89 type: options.type || 'info',
90 _uid: uid,
91 }
92 emit(payload)
93 return uid
94 },
95
96 destroy(key?: string) {
97 if (!key)
98 return
99 // try remove by uid first
100 removeEmit({ _uid: key, key })
101 },
102 }
103
104 export default notification
105
105 lines TYPESCRIPT