You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

103 lines
2.7 KiB

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