import { createVNode, render, type AppContext } from 'vue' import MessageComponent from '@/components/Message.vue' export interface MessageOptions { type?: 'info' | 'success' | 'warning' | 'error' title?: string message?: string duration?: number closable?: boolean ctx?: AppContext onClose?: () => void } export type MessageTypeOptions = Omit export interface MessageIntance { id: string close: () => void } export type MessageFn = (message: string, options?: MessageTypeOptions) => MessageIntance export interface Message { (options: MessageOptions): MessageIntance info: MessageFn success: MessageFn error: MessageFn warning: MessageFn closeAll: () => void _context?: AppContext | null } const instances: MessageIntance[] = [] let wrap: HTMLDivElement | null = null let seed = 0 const defaultOptions: MessageOptions = { duration: 3000, } const message: Message = (options: MessageOptions) => { const id = 'message-' + seed++ const props = { ...defaultOptions, ...options, id, } if (!wrap) { wrap = document.createElement('div') wrap.className = 'message-wrap' wrap.style.cssText = ` width: 100%; position: fixed; top: 0; left: 0; z-index: 6000; pointer-events: none; display: flex; flex-direction: column; box-sizing: border-box; padding: 15px; background-color: rgba(255, 255, 255, 0); transition: all 1s ease-in-out; align-items: center; ` document.body.appendChild(wrap) } const vm = createVNode(MessageComponent, props, null) const div = document.createElement('div') vm.appContext = options.ctx || message._context || null vm.props!.onClose = options.onClose vm.props!.onDestroy = () => { if (wrap && wrap.childNodes.length <= 1) { wrap.remove() wrap = null } render(null, div) } render(vm, div) wrap.appendChild(div.firstElementChild!) const instance = { id, close: () => vm?.component?.exposed?.close(), } instances.push(instance) return instance } message.success = (msg: string, options?: MessageTypeOptions) => message({ ...options, type: 'success', message: msg }) message.info = (msg: string, options?: MessageTypeOptions) => message({ ...options, type: 'info', message: msg }) message.warning = (msg: string, options?: MessageTypeOptions) => message({ ...options, type: 'warning', message: msg }) message.error = (msg: string, options?: MessageTypeOptions) => message({ ...options, type: 'error', message: msg }) message.closeAll = function() { for (let i = instances.length - 1; i >= 0; i--) { instances[i].close() } } export default message