164 lines
4.0 KiB
TypeScript
164 lines
4.0 KiB
TypeScript
// 通知类型
|
|
export type NotificationType = "success" | "error" | "warning" | "info";
|
|
|
|
export interface AppNotification {
|
|
id: string;
|
|
type: NotificationType;
|
|
title: string;
|
|
message: string;
|
|
duration?: number;
|
|
timestamp: Date;
|
|
}
|
|
|
|
// 通知管理器
|
|
class NotificationManager {
|
|
private notifications: AppNotification[] = [];
|
|
private listeners: ((notifications: AppNotification[]) => void)[] = [];
|
|
|
|
// 添加通知
|
|
addNotification(
|
|
type: NotificationType,
|
|
title: string,
|
|
message: string,
|
|
duration: number = 5000
|
|
): string {
|
|
const id = `notification-${Date.now()}-${Math.random()}`;
|
|
const notification: AppNotification = {
|
|
id,
|
|
type,
|
|
title,
|
|
message,
|
|
duration,
|
|
timestamp: new Date(),
|
|
};
|
|
|
|
this.notifications.push(notification);
|
|
this.notifyListeners();
|
|
|
|
// 自动移除通知
|
|
if (duration > 0) {
|
|
setTimeout(() => {
|
|
this.removeNotification(id);
|
|
}, duration);
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
// 移除通知
|
|
removeNotification(id: string): void {
|
|
this.notifications = this.notifications.filter((n) => n.id !== id);
|
|
this.notifyListeners();
|
|
}
|
|
|
|
// 清空所有通知
|
|
clearAll(): void {
|
|
this.notifications = [];
|
|
this.notifyListeners();
|
|
}
|
|
|
|
// 获取所有通知
|
|
getNotifications(): AppNotification[] {
|
|
return [...this.notifications];
|
|
}
|
|
|
|
// 添加监听器
|
|
addListener(listener: (notifications: AppNotification[]) => void): void {
|
|
this.listeners.push(listener);
|
|
}
|
|
|
|
// 移除监听器
|
|
removeListener(listener: (notifications: AppNotification[]) => void): void {
|
|
this.listeners = this.listeners.filter((l) => l !== listener);
|
|
}
|
|
|
|
// 通知所有监听器
|
|
private notifyListeners(): void {
|
|
this.listeners.forEach((listener) => listener(this.notifications));
|
|
}
|
|
|
|
// 便捷方法
|
|
success(title: string, message: string, duration?: number): string {
|
|
return this.addNotification("success", title, message, duration);
|
|
}
|
|
|
|
error(title: string, message: string, duration?: number): string {
|
|
return this.addNotification("error", title, message, duration);
|
|
}
|
|
|
|
warning(title: string, message: string, duration?: number): string {
|
|
return this.addNotification("warning", title, message, duration);
|
|
}
|
|
|
|
info(title: string, message: string, duration?: number): string {
|
|
return this.addNotification("info", title, message, duration);
|
|
}
|
|
}
|
|
|
|
// 创建全局通知管理器实例
|
|
export const notificationManager = new NotificationManager();
|
|
|
|
// 浏览器通知 API
|
|
export class BrowserNotifications {
|
|
static async requestPermission(): Promise<boolean> {
|
|
if (!("Notification" in window)) {
|
|
console.warn("此浏览器不支持通知");
|
|
return false;
|
|
}
|
|
|
|
if (Notification.permission === "granted") {
|
|
return true;
|
|
}
|
|
|
|
if (Notification.permission === "denied") {
|
|
return false;
|
|
}
|
|
|
|
const permission = await Notification.requestPermission();
|
|
return permission === "granted";
|
|
}
|
|
|
|
static async showNotification(
|
|
title: string,
|
|
options?: NotificationOptions
|
|
): Promise<globalThis.Notification | null> {
|
|
if (!("Notification" in window)) {
|
|
return null;
|
|
}
|
|
|
|
if (Notification.permission !== "granted") {
|
|
const granted = await this.requestPermission();
|
|
if (!granted) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return new globalThis.Notification(title, {
|
|
icon: "/favicon.ico",
|
|
badge: "/favicon.ico",
|
|
...options,
|
|
});
|
|
}
|
|
|
|
static async showRecordingComplete(): Promise<void> {
|
|
await this.showNotification("录音完成", {
|
|
body: "您的录音已成功保存",
|
|
tag: "recording-complete",
|
|
});
|
|
}
|
|
|
|
static async showUploadComplete(): Promise<void> {
|
|
await this.showNotification("上传完成", {
|
|
body: "录音文件已成功上传到服务器",
|
|
tag: "upload-complete",
|
|
});
|
|
}
|
|
|
|
static async showUploadError(): Promise<void> {
|
|
await this.showNotification("上传失败", {
|
|
body: "录音文件上传失败,请重试",
|
|
tag: "upload-error",
|
|
});
|
|
}
|
|
}
|