Files
threeonecheck_web/node_modules/wot-design-uni/components/wd-toast/index.ts
2026-06-03 10:16:37 +08:00

106 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { inject, provide, ref } from 'vue'
import type { Toast, ToastOptions } from './types'
import { deepMerge } from '../common/util'
/**
* useToast 用到的key
*/
const toastDefaultOptionKey = '__TOAST_OPTION__'
// 默认模板
export const defaultOptions: ToastOptions = {
duration: 2000,
show: false
}
const None = Symbol('None')
// 使用map存储定时器避免先前的定时器覆盖后续的定时器
// 如果同一个 selector 多次调用 toast则会清除之前的定时器重新计时
const toastTimerMap = new Map<string, ReturnType<typeof setTimeout>>()
export function useToast(selector: string = ''): Toast {
const toastOptionKey = getToastOptionKey(selector)
const toastOption = inject(toastOptionKey, ref<ToastOptions | typeof None>(None)) // toast选项
if (toastOption.value === None) {
toastOption.value = defaultOptions
provide(toastOptionKey, toastOption)
}
const createMethod = (toastOptions: ToastOptions) => {
return (options: ToastOptions | string) => {
return show(deepMerge(toastOptions, typeof options === 'string' ? { msg: options } : options) as ToastOptions)
}
}
const show = (option: ToastOptions | string) => {
const options = deepMerge(defaultOptions, typeof option === 'string' ? { msg: option } : option) as ToastOptions
toastOption.value = deepMerge(options, {
show: true
}) as ToastOptions
// 开始渲染,并在 duration ms之后执行清除
const prevTimer = toastTimerMap.get(toastOptionKey)
if (prevTimer) {
clearTimeout(prevTimer)
toastTimerMap.delete(toastOptionKey)
}
if (options.duration && options.duration > 0) {
const nextTimer = setTimeout(() => {
toastTimerMap.delete(toastOptionKey)
close()
}, options.duration)
toastTimerMap.set(toastOptionKey, nextTimer)
}
}
const loading = createMethod({
iconName: 'loading',
duration: 0,
cover: true
})
const success = createMethod({
iconName: 'success',
duration: 1500
})
const error = createMethod({ iconName: 'error' })
const warning = createMethod({ iconName: 'warning' })
const info = createMethod({ iconName: 'info' })
const close = () => {
const timer = toastTimerMap.get(toastOptionKey)
if (timer) {
clearTimeout(timer)
toastTimerMap.delete(toastOptionKey)
}
toastOption.value = { show: false }
}
return {
show,
loading,
success,
error,
warning,
info,
close
}
}
export const getToastOptionKey = (selector: string) => {
return selector ? `${toastDefaultOptionKey}${selector}` : toastDefaultOptionKey
}
export const toastIcon = {
success() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="2 2 44 44" width="48" height="48"><circle cx="24" cy="26" r="22" fill="#000" opacity=".1"/><circle cx="24" cy="24" r="20" fill="#34D19D" opacity=".4"/><circle cx="24" cy="24" r="16" fill="#34D19D"/><path d="M19 24l4 4 8-8" stroke="#FFF" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg>'
},
warning() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="2 2 44 44" width="48" height="48"><circle cx="24" cy="26" r="22" fill="#000" opacity=".1"/><circle cx="24" cy="24" r="20" fill="#F0883A" opacity=".4"/><circle cx="24" cy="24" r="16" fill="#F0883A"/><rect x="22.5" y="14" width="3" height="12" fill="#FFF" rx="1.5"/><circle cx="24" cy="30" r="2" fill="#FFF"/></svg>'
},
info() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="2 2 44 44" width="48" height="48"><circle cx="24" cy="26" r="22" fill="#000" opacity=".1"/><circle cx="24" cy="24" r="20" fill="#909CB7" opacity=".4"/><circle cx="24" cy="24" r="16" fill="#909CB7"/><circle cx="24" cy="18" r="2" fill="#FFF"/><rect x="22.5" y="22" width="3" height="12" fill="#FFF" rx="1.5"/></svg>'
},
error() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="2 2 44 44" width="48" height="48"><circle cx="24" cy="26" r="22" fill="#000" opacity=".1"/><circle cx="24" cy="24" r="20" fill="#fa4350" opacity=".4"/><circle cx="24" cy="24" r="16" fill="#fa4350"/><path d="M18 18l12 12M30 18L18 30" stroke="#FFF" stroke-width="2.5" stroke-linecap="round"/></svg>'
}
}