import { defineStore } from 'pinia' import type { LocationQuery, RouteLocationNormalized, RouteParamsRaw, Router, RouteRecordName } from 'vue-router' import { PageEnum } from '@/enums/pageEnum' interface TabItem { name: RouteRecordName fullPath: string path: string title?: string query?: LocationQuery params?: RouteParamsRaw } interface TabsSate { cacheTabList: Set, tabList: TabItem[], indexRouteName: RouteRecordName } const getHasTabIndex = (path: string, tabList: TabItem[]) => { return tabList.findIndex((item) => item.path == path) } const getComponentName = (route: RouteLocationNormalized) => { return route.matched[route.matched.length - 1]?.components?.default?.__name } export const getRouteParams = (tabItem: TabItem) => { const { params, path, query } = tabItem return { params: params || {}, path, query: query || {} } } const useTabsStore = defineStore({ id: 'tabs', state: (): TabsSate => ({ cacheTabList: new Set(), tabList: [], indexRouteName: '' }), getters: { getTabList(): TabItem[] { return this.tabList }, getCacheTabList(): string[] { return Array.from(this.cacheTabList) } }, actions: { setRouteName(name: RouteRecordName) { this.indexRouteName = name }, addCache(componentName?: string) { if (componentName) this.cacheTabList.add(componentName) }, removeCache(componentName?: string) { if (componentName && this.cacheTabList.has(componentName)) { this.cacheTabList.delete(componentName) } }, resetState() { this.cacheTabList = new Set() this.tabList = [] }, addTab(router: Router) { const route = unref(router.currentRoute) const { name, query, meta, params, fullPath, path } = route // TODO const hasTabIndex = getHasTabIndex(path!, this.tabList) const componentName = getComponentName(route) const tabItem = { name: name!, path, fullPath, title: meta?.title, query, params } if (meta?.keepAlive) { this.addCache(componentName) } if (hasTabIndex != -1) { return } this.tabList.push(tabItem) }, removeTab(fullPath: string, router: Router) { const { currentRoute, push } = router const index = getHasTabIndex(fullPath, this.tabList) // 移除tab if (this.tabList.length > 1) { index !== -1 && this.tabList.splice(index, 1) } const componentName = getComponentName(currentRoute.value) this.removeCache(componentName) if (fullPath !== currentRoute.value.fullPath) { return } // 删除选中的tab let toTab: TabItem | null = null if (index === 0) { toTab = this.tabList[index] } else { toTab = this.tabList[index - 1] } const toRoute = getRouteParams(toTab) push(toRoute) }, removeOtherTab(route: RouteLocationNormalized) { this.tabList = this.tabList.filter((item) => item.fullPath == route.fullPath) const componentName = getComponentName(route) this.cacheTabList.forEach((name) => { if (componentName !== name) { this.removeCache(name) } }) }, removeAllTab(router: Router) { const { push, currentRoute } = router const { name } = unref(currentRoute) if (name == this.indexRouteName) { this.removeOtherTab(currentRoute.value) return } this.tabList = [] this.clearCache() push(PageEnum.INDEX) } } }) export default useTabsStore