174 lines
4.1 KiB
TypeScript
174 lines
4.1 KiB
TypeScript
|
|
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
|
|||
|
|
}
|