fucai-claim/src/components/loading.ts

174 lines
4.1 KiB
TypeScript
Raw Normal View History

import { createApp, h } from 'vue'
import Loading from './Loading.vue'
// 加载组件配置接口
export interface LoadingOptions {
// 加载动画类型
type?: 'spinner' | 'dots' | 'pulse' | 'ring'
// 加载动画大小
size?: number | string
// 加载动画颜色
color?: string
// 是否全屏显示
fullscreen?: boolean
// 加载文本
text?: string
// 遮罩层背景色
background?: string
// 遮罩层透明度
opacity?: number
// 线条宽度仅适用于spinner和ring类型
strokeWidth?: number
// 线条末端样式仅适用于spinner类型
strokeLinecap?: 'round' | 'butt' | 'square'
}
// Loading 实例接口
interface LoadingInstance {
show: () => void
hide: () => void
close: () => void
}
// 当前活动的Loading实例
let activeInstance: LoadingInstance | null = null
/**
*
* @param options
* @returns
*/
export function showLoading(options: LoadingOptions = {}): LoadingInstance {
// 如果已经有一个活动的全屏Loading实例先隐藏它
if (activeInstance && options.fullscreen !== false) {
activeInstance.hide()
}
// 默认配置
const defaultOptions: LoadingOptions = {
type: 'spinner',
size: 40,
color: '#1890ff',
fullscreen: true,
text: '',
background: 'rgba(0, 0, 0, 0.3)',
opacity: 1,
strokeWidth: 3,
strokeLinecap: 'round'
}
// 合并配置
const mergedOptions = { ...defaultOptions, ...options }
// 创建一个容器元素
const container = document.createElement('div')
// 加载组件状态
let visible = true
// 创建应用实例
const app = createApp({
render() {
return h(Loading, {
visible,
type: mergedOptions.type,
size: mergedOptions.size,
color: mergedOptions.color,
fullscreen: mergedOptions.fullscreen,
text: mergedOptions.text,
background: mergedOptions.background,
opacity: mergedOptions.opacity,
strokeWidth: mergedOptions.strokeWidth,
strokeLinecap: mergedOptions.strokeLinecap
})
}
})
// 隐藏加载组件
function hideLoading() {
visible = false
// 卸载组件
setTimeout(() => {
app.unmount()
if (container.parentNode) {
container.parentNode.removeChild(container)
}
// 如果当前实例是活动实例,清除活动实例引用
if (activeInstance === instance) {
activeInstance = null
}
}, 300)
}
// 显示加载组件(默认为显示状态)
function showLoadingComp() {
visible = true
}
// 挂载组件
app.mount(container)
document.body.appendChild(container)
// 创建实例对象
const instance: LoadingInstance = {
show: showLoadingComp,
hide: hideLoading,
close: hideLoading
}
// 如果是全屏Loading保存为活动实例
if (mergedOptions.fullscreen) {
activeInstance = instance
}
// 返回控制方法
return instance
}
/**
*
*/
export function hideLoading() {
if (activeInstance) {
activeInstance.hide()
activeInstance = null
}
}
/**
*
* @param text
* @param color
* @returns
*/
export function showLoadingWithText(text: string, color: string = '#1890ff'): LoadingInstance {
return showLoading({
text,
color,
fullscreen: true
})
}
/**
*
* @param size
* @param color
* @param type
* @returns
*/
export function showInlineLoading(size: number = 24, color: string = '#1890ff', type: 'spinner' | 'dots' | 'pulse' | 'ring' = 'spinner'): LoadingInstance {
return showLoading({
size,
color,
type,
fullscreen: false
})
}
// 默认导出
export default {
show: showLoading,
hide: hideLoading,
showWithText: showLoadingWithText,
showInline: showInlineLoading
}