/** * Message 消息通知组件 * 自动注入必要样式,无需额外引入 CSS * * 使用方式: * const message = new Message(); * message.create({ type: 'success', content: '操作成功' }); * * 快捷方法: * message.success('内容') * message.warning('内容') * message.danger('内容') * message.info('内容') * message.default('内容') * message.success('操作成功', {duration: 5000, showClose: false,showProgress: false,pale: false,html: false}); */ (function (global) { 'use strict'; const STYLE_ID = 'message-component-style'; const CSS = ` /* ==================== Message Component Styles ==================== */ .message-container { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 999999; display: flex; flex-direction: column; align-items: center; gap: 12px; pointer-events: none; } .message-item { pointer-events: auto; min-width: 320px; max-width: 600px; padding: 14px 18px; border-radius: 3px; background: #fff; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); display: flex; align-items: flex-start; gap: 12px; position: relative; transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1); opacity: 0; transform: translateY(-30px); } .message-item.message-enter { opacity: 1; transform: translateY(0); } .message-item.message-leave { opacity: 0; transform: translateY(-20px); margin-top: -58px; } .message-icon { width: 20px; height: 20px; flex-shrink: 0; margin-top: 2px; } .message-content { flex: 1; font-size: 14px; line-height: 1.6; color: #333; word-break: break-word; } .message-close { width: 18px; height: 18px; flex-shrink: 0; cursor: pointer; display: flex; align-items: center; justify-content: center; border-radius: 3px; transition: all 0.2s; margin-top: 2px; } .message-close:hover { background: rgba(0,0,0,0.06); } .message-close svg { width: 14px; height: 14px; } .message-item.message-default .message-icon { color: #6c757d; } .message-item.message-success .message-icon { color: #28a745; } .message-item.message-warning .message-icon { color: #e6a700; } .message-item.message-danger .message-icon { color: #dc3545; } .message-item.message-info .message-icon { color: #17a2b8; } .message-item.message-pale.message-default { background: #f8f9fa; border: 1px solid #e9ecef; } .message-item.message-pale.message-success { background: #f0f9f4; border: 1px solid #d4edda; } .message-item.message-pale.message-warning { background: #fffbf0; border: 1px solid #ffeeba; } .message-item.message-pale.message-danger { background: #fdf2f2; border: 1px solid #f5c6cb; } .message-item.message-pale.message-info { background: #f0f9fb; border: 1px solid #bee5eb; } .message-progress { position: absolute; bottom: 0; left: 0; height: 3px; border-radius: 0 0 0 3px; transition: width linear; } .message-default .message-progress { background: #6c757d; } .message-success .message-progress { background: #28a745; } .message-warning .message-progress { background: #ffc107; } .message-danger .message-progress { background: #dc3545; } .message-info .message-progress { background: #17a2b8; } `; function injectStyle() { if (document.getElementById(STYLE_ID)) return; const style = document.createElement('style'); style.id = STYLE_ID; style.textContent = CSS; document.head.appendChild(style); } const ICONS = { default: ``, success: ``, warning: ``, danger: ``, info: `` }; class Message { constructor(options = {}) { injectStyle(); this.container = null; this.messages = []; this.defaultOptions = { type: 'default', pale: false, duration: 3000, showClose: true, showProgress: true, content: '', html: false }; } _ensureContainer() { if (!this.container || !document.body.contains(this.container)) { this.container = document.createElement('div'); this.container.className = 'message-container'; this.container.id = 'messageContainer'; document.body.appendChild(this.container); } return this.container; } create(options) { const opts = { ...this.defaultOptions, ...options }; const id = 'msg_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); const container = this._ensureContainer(); const el = document.createElement('div'); el.className = `message-item message-${opts.type}`; if (opts.pale) el.classList.add('message-pale'); el.id = id; const iconEl = document.createElement('div'); iconEl.className = 'message-icon'; iconEl.innerHTML = ICONS[opts.type] || ICONS.default; const contentEl = document.createElement('div'); contentEl.className = 'message-content'; if (opts.html) { contentEl.innerHTML = opts.content; } else { contentEl.textContent = opts.content; } el.appendChild(iconEl); el.appendChild(contentEl); if (opts.showClose) { const closeEl = document.createElement('div'); closeEl.className = 'message-close'; closeEl.innerHTML = ``; closeEl.addEventListener('click', () => this.close(id)); el.appendChild(closeEl); } let progressEl = null; if (opts.duration > 0 && opts.showProgress) { progressEl = document.createElement('div'); progressEl.className = 'message-progress'; progressEl.style.width = '100%'; el.appendChild(progressEl); } container.appendChild(el); const msgInfo = { id, el, duration: opts.duration, timer: null, startTime: null }; this.messages.push(msgInfo); requestAnimationFrame(() => { requestAnimationFrame(() => { el.classList.add('message-enter'); }); }); if (opts.duration > 0) { msgInfo.startTime = Date.now(); if (progressEl) { requestAnimationFrame(() => { progressEl.style.transition = `width ${opts.duration}ms linear`; requestAnimationFrame(() => { progressEl.style.width = '0%'; }); }); } msgInfo.timer = setTimeout(() => { this.close(id); }, opts.duration); } return id; } close(id) { const index = this.messages.findIndex(m => m.id === id); if (index === -1) return; const msg = this.messages[index]; if (msg.timer) { clearTimeout(msg.timer); msg.timer = null; } msg.el.classList.remove('message-enter'); msg.el.classList.add('message-leave'); setTimeout(() => { if (msg.el.parentNode) { msg.el.parentNode.removeChild(msg.el); } const idx = this.messages.findIndex(m => m.id === id); if (idx !== -1) this.messages.splice(idx, 1); }, 350); } closeAll() { [...this.messages].forEach(msg => this.close(msg.id)); } success(content, options = {}) { return this.create({ ...options, type: 'success', content }); } warning(content, options = {}) { return this.create({ ...options, type: 'warning', content }); } danger(content, options = {}) { return this.create({ ...options, type: 'danger', content }); } error(content, options = {}) { return this.create({ ...options, type: 'danger', content }); } info(content, options = {}) { return this.create({ ...options, type: 'info', content }); } default(content, options = {}) { return this.create({ ...options, type: 'default', content }); } } global.Message = Message; })(typeof window !== 'undefined' ? window : this); const message = new Message();