|
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<MessageOptions, 'type' | 'message'> |
|
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 |