| 6 | import Logger from './logger.js'; |
| 7 | |
| 8 | class NotificationManager { |
| 9 | constructor() { |
| 10 | this.container = null; |
| 11 | this.notifications = new Map(); |
| 12 | this.init(); |
| 13 | } |
| 14 | |
| 15 | /** |
| 16 | * 初始化通知容器 |
| 17 | */ |
| 18 | init() { |
| 19 | if (this.container) return; |
| 20 | |
| 21 | this.container = document.createElement('div'); |
| 22 | this.container.className = 'notification-container'; |
| 23 | this.container.setAttribute('aria-live', 'polite'); |
| 24 | this.container.setAttribute('aria-atomic', 'true'); |
| 25 | document.body.appendChild(this.container); |
| 26 | } |
| 27 | |
| 28 | /** |
| 29 | * 显示通知 |
| 30 | * @param {Object} options - 通知配置 |
| 31 | * @param {string} options.message - 通知消息 |
| 32 | * @param {string} options.type - 通知类型 (success|warning|error|info) |
| 33 | * @param {number} options.duration - 持续时间(ms),0表示不自动关闭 |
| 34 | * @param {boolean} options.closable - 是否可手动关闭 |
| 35 | */ |
| 36 | show({ message, type = 'info', duration = 5000, closable = true }) { |
| 37 | const id = `notification-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; |
| 38 | const notification = this.createNotification(id, message, type, closable); |
| 39 | |
| 40 | this.container.appendChild(notification); |
| 41 | this.notifications.set(id, notification); |
| 42 | |
| 43 | // 触发入场动画 |
| 44 | requestAnimationFrame(() => { |
| 45 | notification.classList.add('show'); |
| 46 | }); |
| 47 | |
| 48 | // 自动关闭 |
| 49 | if (duration > 0) { |
| 50 | setTimeout(() => this.hide(id), duration); |
| 51 | } |
| 52 | |
| 53 | Logger.log(`[Notification] ${type}: ${message}`); |
| 54 | return id; |
| 55 | } |
| 56 | |
| 57 | /** |
| 58 | * 创建通知元素 |
| 59 | */ |
| 60 | createNotification(id, message, type, closable) { |
| 61 | const notification = document.createElement('div'); |
| 62 | notification.className = `notification notification-${type}`; |
| 63 | notification.setAttribute('role', 'alert'); |
| 64 | notification.setAttribute('data-id', id); |
| 65 |
nothing calls this directly
no outgoing calls
no test coverage detected