diff --git a/src/enum/common/storage.ts b/src/enum/common/storage.ts index 05c1be83..0d386edc 100644 --- a/src/enum/common/storage.ts +++ b/src/enum/common/storage.ts @@ -4,5 +4,7 @@ export enum EnumStorageKey { /** 用户刷新token */ 'refresh-koken' = '__REFRESH_TOKEN__', /** 用户信息 */ - 'user-info' = '__USER_INFO__' + 'user-info' = '__USER_INFO__', + /** 多页签路由信息 */ + 'tab-route' = '__TAB_ROUTE__' } diff --git a/src/interface/common/system.ts b/src/interface/common/system.ts index cc34f83a..44b2cd0e 100644 --- a/src/interface/common/system.ts +++ b/src/interface/common/system.ts @@ -1,3 +1,4 @@ +import type { RouteLocationNormalizedLoaded } from 'vue-router'; import type { MenuOption } from 'naive-ui'; import { EnumLoginModule } from '@/enum'; @@ -7,6 +8,16 @@ export type GlobalMenuOption = MenuOption & { routePath: string; }; +/** 多页签 */ +export interface MultiTab { + routes: MultiTabRoute[]; + activeRoute: string; +} +export type MultiTabRoute = Partial & { + path: string; + fullPath: string; +}; + /** 登录模块 */ export type LoginModuleType = keyof typeof EnumLoginModule; diff --git a/src/interface/theme/index.ts b/src/interface/theme/index.ts index c5f07478..418660b7 100644 --- a/src/interface/theme/index.ts +++ b/src/interface/theme/index.ts @@ -96,6 +96,8 @@ interface MultiTabStyle { bgColor: string; /** 多页签模式 */ mode: MultiTabMode; + /** 开启多页签缓存 */ + isCache: boolean; /** 多页签模式列表 */ modeList: MultiTabModeList[]; } diff --git a/src/layouts/BasicLayout/components/common/GlobalTab/components/MultiTab/index.vue b/src/layouts/BasicLayout/components/common/GlobalTab/components/MultiTab/index.vue index 6b664afb..33f5ebfb 100644 --- a/src/layouts/BasicLayout/components/common/GlobalTab/components/MultiTab/index.vue +++ b/src/layouts/BasicLayout/components/common/GlobalTab/components/MultiTab/index.vue @@ -40,10 +40,12 @@ diff --git a/src/layouts/BasicLayout/components/common/SettingDrawer/components/PageFunc/index.vue b/src/layouts/BasicLayout/components/common/SettingDrawer/components/PageFunc/index.vue index 2860f27a..741ffde6 100644 --- a/src/layouts/BasicLayout/components/common/SettingDrawer/components/PageFunc/index.vue +++ b/src/layouts/BasicLayout/components/common/SettingDrawer/components/PageFunc/index.vue @@ -51,13 +51,25 @@ @update:value="handleMultiTabHeight" /> + + + + + + + 确定要清空多页签缓存吗? + + diff --git a/src/settings/theme.json b/src/settings/theme.json index 415a5dc3..9cb25250 100644 --- a/src/settings/theme.json +++ b/src/settings/theme.json @@ -61,6 +61,7 @@ "visible": true, "bgColor": "#fff", "mode": "chrome", + "isCache": true, "modeList": [ { "value": "button", diff --git a/src/settings/theme.ts b/src/settings/theme.ts index 78d9f586..a12ee8e1 100644 --- a/src/settings/theme.ts +++ b/src/settings/theme.ts @@ -58,6 +58,7 @@ const defaultThemeSettings: ThemeSettings = { visible: true, bgColor: '#fff', mode: 'chrome', + isCache: true, modeList: [ { value: 'button', label: EnumMultiTabMode.button }, { value: 'chrome', label: EnumMultiTabMode.chrome } diff --git a/src/store/modules/app/helpers.ts b/src/store/modules/app/helpers.ts index 20c57821..76d25e6c 100644 --- a/src/store/modules/app/helpers.ts +++ b/src/store/modules/app/helpers.ts @@ -1,4 +1,7 @@ +import type { RouteLocationNormalizedLoaded } from 'vue-router'; +import { ROUTE_HOME } from '@/router'; import { brightenColor, darkenColor } from '@/utils'; +import type { MultiTabRoute } from '@/interface'; export function getHoverAndPressedColor(color: string) { return { @@ -6,3 +9,37 @@ export function getHoverAndPressedColor(color: string) { pressed: darkenColor(color) }; } + +/** 获取路由首页信息 */ +export function getHomeTabRoute(route: RouteLocationNormalizedLoaded) { + const { name, path, meta } = ROUTE_HOME; + const isHome = route.name === ROUTE_HOME.name; + const home: MultiTabRoute = { + name, + path, + fullPath: path, + meta + }; + if (isHome) { + Object.assign(home, route); + } + return home; +} + +/** + * 获取该页签在多页签数据中的索引 + * @param routes - 多页签数据 + * @param fullPath - 该页签的路径 + */ +export function getIndexInTabRoutes(routes: MultiTabRoute[], fullPath: string) { + return routes.findIndex(route => route.fullPath === fullPath); +} + +/** + * 判断该页签是否在多页签数据中 + * @param routes - 多页签数据 + * @param fullPath - 该页签的路径 + */ +export function isInTabRoutes(routes: MultiTabRoute[], fullPath: string) { + return getIndexInTabRoutes(routes, fullPath) > -1; +} diff --git a/src/store/modules/app/index.ts b/src/store/modules/app/index.ts index 8c380b25..9808a966 100644 --- a/src/store/modules/app/index.ts +++ b/src/store/modules/app/index.ts @@ -2,8 +2,11 @@ import { nextTick } from 'vue'; import type { RouteLocationNormalizedLoaded } from 'vue-router'; import type { ScrollbarInst } from 'naive-ui'; import { defineStore } from 'pinia'; -import { store } from '@/store'; import { router, ROUTE_HOME } from '@/router'; +import { store, useThemeStore } from '@/store'; +import { getTabRouteStorage } from '@/utils'; +import type { MultiTab, MultiTabRoute } from '@/interface'; +import { getHomeTabRoute, isInTabRoutes } from './helpers'; /** app状态 */ interface AppState { @@ -28,16 +31,6 @@ interface MenuState { fixedMix: boolean; } -/** 多页签 */ -interface MultiTab { - routes: MultiTabRoute[]; - activeRoute: string; -} -type MultiTabRoute = Partial & { - path: string; - fullPath: string; -}; - /** 项目配置抽屉的状态 */ interface SettingDrawer { /** 设置抽屉可见性 */ @@ -74,9 +67,7 @@ const appStore = defineStore({ setScrollbarInstance(scrollbar: ScrollbarInst) { this.layout.scrollbar = scrollbar; }, - /** - * 重置滚动条行为 - */ + /** 重置滚动条行为 */ resetScrollBehavior() { const { scrollbar } = this.layout; setTimeout(() => { @@ -95,14 +86,10 @@ const appStore = defineStore({ toggleMenu() { this.menu.collapsed = !this.menu.collapsed; }, - /** 判断页签路由是否存在某个路由 */ - getIndexInTabRoutes(fullPath: string) { - return this.multiTab.routes.findIndex(item => item.fullPath === fullPath); - }, /** 添加多页签的数据 */ addMultiTab(route: RouteLocationNormalizedLoaded) { const { fullPath } = route; - const isExist = this.getIndexInTabRoutes(fullPath) > -1; + const isExist = isInTabRoutes(this.multiTab.routes, fullPath); if (!isExist) { this.multiTab.routes.push({ ...route }); } @@ -174,28 +161,19 @@ const appStore = defineStore({ setActiveMultiTab(fullPath: string) { this.multiTab.activeRoute = fullPath; }, - /** 获取路由首页信息 */ - getHomeTabRoute(route: RouteLocationNormalizedLoaded) { - const { name, path, meta } = ROUTE_HOME; - const isHome = route.name === ROUTE_HOME.name; - const home: MultiTabRoute = { - name, - path, - fullPath: path, - meta - }; - if (isHome) { - Object.assign(home, route); - } - return home; - }, /** 初始化多页签数据 */ initMultiTab() { + const theme = useThemeStore(); const { currentRoute } = router; const isHome = currentRoute.value.name === ROUTE_HOME.name; - const home = this.getHomeTabRoute(currentRoute.value); - const routes = [home]; - if (!isHome) { + const home = getHomeTabRoute(currentRoute.value); + const routes: MultiTabRoute[] = theme.multiTabStyle.isCache ? getTabRouteStorage() : []; + const hasHome = isInTabRoutes(routes, home.fullPath); + const hasCurrent = isInTabRoutes(routes, currentRoute.value.fullPath); + if (!hasHome) { + routes.unshift(home); + } + if (!isHome && !hasCurrent) { routes.push(currentRoute.value); } this.multiTab.routes = routes; diff --git a/src/store/modules/theme/index.ts b/src/store/modules/theme/index.ts index 9b5fa596..98ea149a 100644 --- a/src/store/modules/theme/index.ts +++ b/src/store/modules/theme/index.ts @@ -104,6 +104,10 @@ const themeStore = defineStore({ handleMultiTabMode(mode: MultiTabMode) { this.multiTabStyle.mode = mode; }, + /** 设置多页签缓存 */ + handleSetMultiTabCache(isCache: boolean) { + this.multiTabStyle.isCache = isCache; + }, /** 设置面包屑的显示 */ handleCrumbsVisible(visible: boolean) { this.crumbsStyle.visible = visible; diff --git a/src/utils/router/index.ts b/src/utils/router/index.ts index b633603a..36e852d2 100644 --- a/src/utils/router/index.ts +++ b/src/utils/router/index.ts @@ -1,3 +1,4 @@ export * from './helpers'; export * from './cache'; export * from './menus'; +export * from './tab'; diff --git a/src/utils/router/menus.ts b/src/utils/router/menus.ts index 69d4563f..d9149d28 100644 --- a/src/utils/router/menus.ts +++ b/src/utils/router/menus.ts @@ -18,6 +18,7 @@ function addPartialProps(menuItem: GlobalMenuOption, icon?: string, children?: G return item; } +/** 将路由转换成菜单 */ export function transformRouteToMenu(routes: CustomRoute[]) { const globalMenu: GlobalMenuOption[] = []; routes.forEach(route => { diff --git a/src/utils/router/tab.ts b/src/utils/router/tab.ts new file mode 100644 index 00000000..aa37f9ee --- /dev/null +++ b/src/utils/router/tab.ts @@ -0,0 +1,23 @@ +import { EnumStorageKey } from '@/enum'; +import type { MultiTabRoute } from '@/interface'; +import { setLocal, getLocal } from '../storage'; + +/** 缓存多页签数据 */ +export function setTabRouteStorage(data: MultiTabRoute[]) { + setLocal(EnumStorageKey['tab-route'], data); +} + +/** 获取缓存的多页签数据 */ +export function getTabRouteStorage() { + const routes: MultiTabRoute[] = []; + const data = getLocal(EnumStorageKey['tab-route']); + if (data) { + routes.push(...data); + } + return routes; +} + +/** 清空多页签数据 */ +export function clearTabRoutes() { + setTabRouteStorage([]); +} diff --git a/src/utils/storage/local.ts b/src/utils/storage/local.ts index 037cb6f0..c042eac3 100644 --- a/src/utils/storage/local.ts +++ b/src/utils/storage/local.ts @@ -8,7 +8,7 @@ export function getLocal(key: string) { if (json) { return JSON.parse(json) as T; } - return json; + return null; } export function removeLocal(key: string) { diff --git a/src/utils/storage/session.ts b/src/utils/storage/session.ts index fd24465d..24faf0ca 100644 --- a/src/utils/storage/session.ts +++ b/src/utils/storage/session.ts @@ -8,7 +8,7 @@ export function getSession(key: string) { if (json) { return JSON.parse(json) as T; } - return json; + return null; } export function removeSession(key: string) {