@ithinkdt/core
Version:
iThinkDT Core
143 lines (127 loc) • 4.49 kB
JavaScript
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)
},
})
},
}
}