UNPKG

@ithinkdt/core

Version:

iThinkDT Core

143 lines (127 loc) 4.49 kB
import { onBeforeUnmount, watch, shallowReactive, inject } from 'vue' // eslint-disable-next-line vue/prefer-import-from-vue import { hyphenate } from '@vue/shared' import { useEventListener } from '@vueuse/core' import { useAuth } from '../auth' import { initThemeInfo } from './service' import { setTitle, config } from './page-tab/set-title' import { getRouteKey } from './page-tab/get-route-key' export const PageTabInjection = Symbol() export let theme export let useTheme = () => { throw new Error('未初始化 Theme 模块,不能调用 useTheme') } export function initTheme({ vars, titlePrefix, ...init }) { config.prefix = titlePrefix const _useTheme = initThemeInfo({ ...init, vars: {} }) useTheme = (effect, restoreKeys) => { const store = _useTheme() if (effect === 'scoped') { const state = restoreKeys?.length ? Object.fromEntries(restoreKeys.map((key) => [key, store.$state[key]])) : { ...store.$state } onBeforeUnmount(() => { store.$patch(state) }) useEventListener('beforeunload', () => { store.$patch(state) }) } return store } function _init() { theme = useTheme() const auth = useAuth() useEventListener('beforeunload', () => { document.body.remove() }) watch( () => theme.multiTab, () => { theme.pages = [] }, ) const { router } = init let currTabIndex router.beforeResolve(() => { currTabIndex = theme.currentPageIndex }) router.afterEach((to) => { const route = to.matched?.find((it) => !it.meta?.abstract && (it.components || it.component)) if (!route) return const keepAliveKey = getRouteKey(route.meta.keepAlive, { name: route.name, path: to.path, fullPath: to.fullPath, }) const tabKey = route.meta.tabKey ? getRouteKey(route.meta.tabKey, { name: route.name, path: to.path, fullPath: to.fullPath, }) : keepAliveKey let tab = theme.pages.find((tab) => tab.key === tabKey) if (tab) { tab.path = to.fullPath tab.error = to.__DT_ROUTE_ERROR router.currentRoute.value._tab = tab return } const module = auth.activedModulePath.at(-1) const title = module?._label || module?.label || '' tab = shallowReactive({ key: tabKey, keepAliveKey, path: to.fullPath, title, _title: title, href: to.href, keepAlive: to.meta.keepAlive ?? 'path', moduleKey: module?.key, error: to.__DT_ROUTE_ERROR, }) router.currentRoute.value._tab = tab const pages = [...theme.pages] pages.splice(Math.max(currTabIndex, 0) + 1, 0, tab) theme.pages = pages console.debug(`[router] afterEach, title change to '${title}'.`) setTitle(title, auth) }) watch( () => theme.isDark, (isDark) => { theme.vars = vars(isDark) }, { immediate: true }, ) let style watch( () => theme.vars, (vars) => { const cssvars = Object.entries(vars).map(([key, value]) => `--dt-${hyphenate(key)}: ${value};`) style?.remove() style = document.createElement('style') style.id = 'dt-global-cssvars' style.textContent = `body { ${cssvars.join(';')} }` document.body.append(style) }, { immediate: true }, ) } return { install(app) { if (!theme) _init() app.mixin({ computed: { $page() { return this.__tab?.value ?? {} }, }, beforeCreate() { this.__tab = inject(PageTabInjection, () => {}, true) }, }) }, } }