/** * 加载状态管理组合式函数 */ import { ref, computed } from 'vue' import { ElLoading } from 'element-plus' import type { LoadingInstance } from 'element-plus/es/components/loading/src/loading' // 全局加载状态 const globalLoading = ref(false) const loadingCount = ref(0) /** * 使用加载状态 */ export const useLoading = (initialState = false) => { const loading = ref(initialState) /** * 设置加载状态 */ const setLoading = (state: boolean) => { loading.value = state } /** * 开始加载 */ const startLoading = () => { loading.value = true } /** * 结束加载 */ const stopLoading = () => { loading.value = false } /** * 异步操作包装器 */ const withLoading = async (fn: () => Promise): Promise => { try { startLoading() return await fn() } finally { stopLoading() } } return { loading: computed(() => loading.value), setLoading, startLoading, stopLoading, withLoading } } /** * 使用全局加载状态 */ export const useGlobalLoading = () => { /** * 增加加载计数 */ const addLoading = () => { loadingCount.value++ globalLoading.value = true } /** * 减少加载计数 */ const removeLoading = () => { loadingCount.value = Math.max(0, loadingCount.value - 1) if (loadingCount.value === 0) { globalLoading.value = false } } /** * 重置加载状态 */ const resetLoading = () => { loadingCount.value = 0 globalLoading.value = false } /** * 全局异步操作包装器 */ const withGlobalLoading = async (fn: () => Promise): Promise => { try { addLoading() return await fn() } finally { removeLoading() } } return { globalLoading: computed(() => globalLoading.value), loadingCount: computed(() => loadingCount.value), addLoading, removeLoading, resetLoading, withGlobalLoading } } /** * 使用页面加载遮罩 */ export const usePageLoading = () => { let loadingInstance: LoadingInstance | null = null /** * 显示页面加载遮罩 */ const showPageLoading = (options?: { text?: string background?: string target?: string | HTMLElement }) => { const { text = '加载中...', background = 'rgba(0, 0, 0, 0.7)', target = 'body' } = options || {} loadingInstance = ElLoading.service({ lock: true, text, background, target }) } /** * 隐藏页面加载遮罩 */ const hidePageLoading = () => { if (loadingInstance) { loadingInstance.close() loadingInstance = null } } /** * 页面异步操作包装器 */ const withPageLoading = async ( fn: () => Promise, options?: { text?: string background?: string target?: string | HTMLElement } ): Promise => { try { showPageLoading(options) return await fn() } finally { hidePageLoading() } } return { showPageLoading, hidePageLoading, withPageLoading } } /** * 使用按钮加载状态 */ export const useButtonLoading = () => { const buttonLoadings = ref>({}) /** * 设置按钮加载状态 */ const setButtonLoading = (key: string, loading: boolean) => { buttonLoadings.value[key] = loading } /** * 获取按钮加载状态 */ const getButtonLoading = (key: string) => { return computed(() => buttonLoadings.value[key] || false) } /** * 按钮异步操作包装器 */ const withButtonLoading = async ( key: string, fn: () => Promise ): Promise => { try { setButtonLoading(key, true) return await fn() } finally { setButtonLoading(key, false) } } return { buttonLoadings: computed(() => buttonLoadings.value), setButtonLoading, getButtonLoading, withButtonLoading } } /** * 使用延迟加载 */ export const useDelayedLoading = (delay = 300) => { const loading = ref(false) const actualLoading = ref(false) let timer: NodeJS.Timeout | null = null /** * 设置加载状态(带延迟) */ const setLoading = (state: boolean) => { if (state) { // 立即设置实际加载状态 actualLoading.value = true // 延迟显示加载UI timer = setTimeout(() => { loading.value = true }, delay) } else { // 立即隐藏加载UI if (timer) { clearTimeout(timer) timer = null } loading.value = false actualLoading.value = false } } /** * 延迟异步操作包装器 */ const withDelayedLoading = async (fn: () => Promise): Promise => { try { setLoading(true) return await fn() } finally { setLoading(false) } } return { loading: computed(() => loading.value), actualLoading: computed(() => actualLoading.value), setLoading, withDelayedLoading } }