Commit 26b6109ca08a28c37355474bf8593f2e2b741ef6

Authored by vben
1 parent 6e03e050

feat: add permissionCacheType setting

src/enums/cacheEnum.ts
@@ -18,3 +18,8 @@ export const BASE_LOCAL_CACHE_KEY = 'LOCAL__CACHE__KEY__'; @@ -18,3 +18,8 @@ export const BASE_LOCAL_CACHE_KEY = 'LOCAL__CACHE__KEY__';
18 18
19 // base global session key 19 // base global session key
20 export const BASE_SESSION_CACHE_KEY = 'SESSION__CACHE__KEY__'; 20 export const BASE_SESSION_CACHE_KEY = 'SESSION__CACHE__KEY__';
  21 +
  22 +export enum CacheTypeEnum {
  23 + SESSION,
  24 + LOCAL,
  25 +}
src/hooks/core/useTimeout.ts
@@ -23,7 +23,7 @@ export function useTimeoutFn(handle: Fn<any>, wait: number) { @@ -23,7 +23,7 @@ export function useTimeoutFn(handle: Fn<any>, wait: number) {
23 export function useTimeoutRef(wait: number) { 23 export function useTimeoutRef(wait: number) {
24 const readyRef = ref(false); 24 const readyRef = ref(false);
25 25
26 - let timer: ReturnType<typeof setTimeout> | undefined; 26 + let timer: TimeoutHandle;
27 function stop(): void { 27 function stop(): void {
28 readyRef.value = false; 28 readyRef.value = false;
29 timer && window.clearTimeout(timer); 29 timer && window.clearTimeout(timer);
src/hooks/setting/useTransitionSetting.ts
@@ -7,7 +7,7 @@ import { appStore } from &#39;/@/store/modules/app&#39;; @@ -7,7 +7,7 @@ import { appStore } from &#39;/@/store/modules/app&#39;;
7 export function useTransitionSetting() { 7 export function useTransitionSetting() {
8 const getTransitionSetting = computed(() => appStore.getProjectConfig.transitionSetting); 8 const getTransitionSetting = computed(() => appStore.getProjectConfig.transitionSetting);
9 9
10 - const getEnableTransition = computed(() => unref(getTransitionSetting).enable); 10 + const getEnableTransition = computed(() => unref(getTransitionSetting)?.enable);
11 11
12 const getOpenNProgress = computed(() => unref(getTransitionSetting)?.openNProgress); 12 const getOpenNProgress = computed(() => unref(getTransitionSetting)?.openNProgress);
13 13
src/hooks/web/useLockPage.ts
@@ -5,7 +5,7 @@ import { appStore } from &#39;/@/store/modules/app&#39;; @@ -5,7 +5,7 @@ import { appStore } from &#39;/@/store/modules/app&#39;;
5 import { userStore } from '/@/store/modules/user'; 5 import { userStore } from '/@/store/modules/user';
6 6
7 export function useLockPage() { 7 export function useLockPage() {
8 - let timeId: ReturnType<typeof setTimeout>; 8 + let timeId: TimeoutHandle;
9 9
10 function clear(): void { 10 function clear(): void {
11 window.clearTimeout(timeId); 11 window.clearTimeout(timeId);
src/layouts/default/multitabs/index.less
@@ -40,12 +40,9 @@ @@ -40,12 +40,9 @@
40 height: 12px; 40 height: 12px;
41 font-size: 12px; 41 font-size: 12px;
42 color: inherit; 42 color: inherit;
43 - visibility: hidden;  
44 transition: none; 43 transition: none;
45 44
46 &:hover { 45 &:hover {
47 - visibility: visible;  
48 -  
49 svg { 46 svg {
50 width: 0.8em; 47 width: 0.8em;
51 } 48 }
@@ -72,10 +69,6 @@ @@ -72,10 +69,6 @@
72 display: none; 69 display: none;
73 } 70 }
74 71
75 - .ant-tabs-close-x {  
76 - visibility: visible;  
77 - }  
78 -  
79 svg { 72 svg {
80 width: 0.7em; 73 width: 0.7em;
81 fill: @white; 74 fill: @white;
src/layouts/default/multitabs/index.tsx
  1 +import './index.less';
  2 +
1 import type { TabContentProps } from './tab.data'; 3 import type { TabContentProps } from './tab.data';
2 import type { TabItem } from '/@/store/modules/tab'; 4 import type { TabItem } from '/@/store/modules/tab';
3 import type { AppRouteRecordRaw } from '/@/router/types'; 5 import type { AppRouteRecordRaw } from '/@/router/types';
4 6
5 -import { defineComponent, watch, computed, unref, toRaw } from 'vue'; 7 +import { defineComponent, watch, computed, unref } from 'vue';
6 import { useRouter } from 'vue-router'; 8 import { useRouter } from 'vue-router';
7 -import router from '/@/router';  
8 9
9 import { Tabs } from 'ant-design-vue'; 10 import { Tabs } from 'ant-design-vue';
10 import TabContent from './TabContent'; 11 import TabContent from './TabContent';
@@ -18,12 +19,12 @@ import { userStore } from &#39;/@/store/modules/user&#39;; @@ -18,12 +19,12 @@ import { userStore } from &#39;/@/store/modules/user&#39;;
18 19
19 import { closeTab } from './useTabDropdown'; 20 import { closeTab } from './useTabDropdown';
20 import { useTabs } from '/@/hooks/web/useTabs'; 21 import { useTabs } from '/@/hooks/web/useTabs';
  22 +import { initAffixTabs } from './useAffixTabs';
21 23
22 -import './index.less';  
23 export default defineComponent({ 24 export default defineComponent({
24 - name: 'MultiTabs', 25 + name: 'MultipleTabs',
25 setup() { 26 setup() {
26 - let isAddAffix = false; 27 + initAffixTabs();
27 28
28 const go = useGo(); 29 const go = useGo();
29 30
@@ -36,11 +37,6 @@ export default defineComponent({ @@ -36,11 +37,6 @@ export default defineComponent({
36 watch( 37 watch(
37 () => tabStore.getLastChangeRouteState, 38 () => tabStore.getLastChangeRouteState,
38 () => { 39 () => {
39 - if (!isAddAffix) {  
40 - addAffixTabs();  
41 - isAddAffix = true;  
42 - }  
43 -  
44 const lastChangeRoute = unref(tabStore.getLastChangeRouteState); 40 const lastChangeRoute = unref(tabStore.getLastChangeRouteState);
45 41
46 if (!lastChangeRoute || !userStore.getTokenState) return; 42 if (!lastChangeRoute || !userStore.getTokenState) return;
@@ -56,39 +52,15 @@ export default defineComponent({ @@ -56,39 +52,15 @@ export default defineComponent({
56 } 52 }
57 ); 53 );
58 54
59 - /**  
60 - * @description: 过滤所有固定路由  
61 - */  
62 - function filterAffixTabs(routes: AppRouteRecordRaw[]) {  
63 - const tabs: TabItem[] = [];  
64 - routes &&  
65 - routes.forEach((route) => {  
66 - if (route.meta && route.meta.affix) {  
67 - tabs.push(toRaw(route) as TabItem);  
68 - }  
69 - });  
70 - return tabs;  
71 - }  
72 -  
73 - /**  
74 - * @description: 设置固定tabs  
75 - */  
76 - function addAffixTabs(): void {  
77 - const affixTabs = filterAffixTabs((router.getRoutes() as unknown) as AppRouteRecordRaw[]);  
78 - for (const tab of affixTabs) {  
79 - tabStore.commitAddTab(tab);  
80 - }  
81 - }  
82 -  
83 // tab切换 55 // tab切换
84 function handleChange(activeKey: any) { 56 function handleChange(activeKey: any) {
85 activeKeyRef.value = activeKey; 57 activeKeyRef.value = activeKey;
86 go(activeKey, false); 58 go(activeKey, false);
87 } 59 }
88 60
89 - // 关闭当前ab 61 + // 关闭当前tab
90 function handleEdit(targetKey: string) { 62 function handleEdit(targetKey: string) {
91 - // 新增操作隐藏,目前只使用删除操作 63 + // Added operation to hide, currently only use delete operation
92 const index = unref(getTabsState).findIndex( 64 const index = unref(getTabsState).findIndex(
93 (item) => (item.fullPath || item.path) === targetKey 65 (item) => (item.fullPath || item.path) === targetKey
94 ); 66 );
@@ -107,12 +79,13 @@ export default defineComponent({ @@ -107,12 +79,13 @@ export default defineComponent({
107 </span> 79 </span>
108 ); 80 );
109 } 81 }
  82 +
110 function renderTabs() { 83 function renderTabs() {
111 return unref(getTabsState).map((item: TabItem) => { 84 return unref(getTabsState).map((item: TabItem) => {
112 const key = item.query ? item.fullPath : item.path; 85 const key = item.query ? item.fullPath : item.path;
113 - 86 + const closable = !(item && item.meta && item.meta.affix);
114 return ( 87 return (
115 - <Tabs.TabPane key={key} closable={!(item && item.meta && item.meta.affix)}> 88 + <Tabs.TabPane key={key} closable={closable}>
116 {{ 89 {{
117 tab: () => <TabContent tabItem={item} />, 90 tab: () => <TabContent tabItem={item} />,
118 }} 91 }}
src/layouts/default/multitabs/useAffixTabs.ts 0 → 100644
  1 +import { toRaw } from 'vue';
  2 +import router from '/@/router';
  3 +import { AppRouteRecordRaw } from '/@/router/types';
  4 +import { TabItem, tabStore } from '/@/store/modules/tab';
  5 +
  6 +export function initAffixTabs() {
  7 + /**
  8 + * @description: Filter all fixed routes
  9 + */
  10 + function filterAffixTabs(routes: AppRouteRecordRaw[]) {
  11 + const tabs: TabItem[] = [];
  12 + routes &&
  13 + routes.forEach((route) => {
  14 + if (route.meta && route.meta.affix) {
  15 + tabs.push(toRaw(route) as TabItem);
  16 + }
  17 + });
  18 + return tabs;
  19 + }
  20 +
  21 + /**
  22 + * @description: Set fixed tabs
  23 + */
  24 + function addAffixTabs(): void {
  25 + const affixTabs = filterAffixTabs((router.getRoutes() as unknown) as AppRouteRecordRaw[]);
  26 + for (const tab of affixTabs) {
  27 + tabStore.commitAddTab(tab);
  28 + }
  29 + }
  30 + let isAddAffix = false;
  31 + if (!isAddAffix) {
  32 + addAffixTabs();
  33 + isAddAffix = true;
  34 + }
  35 +}
src/layouts/default/multitabs/useTabDropdown.ts
@@ -203,6 +203,7 @@ export function closeTab(closedTab: TabItem | AppRouteRecordRaw) { @@ -203,6 +203,7 @@ export function closeTab(closedTab: TabItem | AppRouteRecordRaw) {
203 const getTabsState = computed(() => { 203 const getTabsState = computed(() => {
204 return tabStore.getTabsState; 204 return tabStore.getTabsState;
205 }); 205 });
  206 +
206 const { path } = unref(currentRoute); 207 const { path } = unref(currentRoute);
207 if (path !== closedTab.path) { 208 if (path !== closedTab.path) {
208 // 关闭的不是激活tab 209 // 关闭的不是激活tab
src/router/guard/index.ts
@@ -14,9 +14,9 @@ import { AxiosCanceler } from &#39;/@/utils/http/axios/axiosCancel&#39;; @@ -14,9 +14,9 @@ import { AxiosCanceler } from &#39;/@/utils/http/axios/axiosCancel&#39;;
14 14
15 import { tabStore } from '/@/store/modules/tab'; 15 import { tabStore } from '/@/store/modules/tab';
16 16
  17 +const { closeMessageOnSwitch, removeAllHttpPending } = useProjectSetting();
17 const globSetting = useGlobSetting(); 18 const globSetting = useGlobSetting();
18 export function createGuard(router: Router) { 19 export function createGuard(router: Router) {
19 - const { closeMessageOnSwitch, removeAllHttpPending } = useProjectSetting();  
20 let axiosCanceler: AxiosCanceler | null; 20 let axiosCanceler: AxiosCanceler | null;
21 if (removeAllHttpPending) { 21 if (removeAllHttpPending) {
22 axiosCanceler = new AxiosCanceler(); 22 axiosCanceler = new AxiosCanceler();
src/settings/projectSetting.ts
1 import type { ProjectConfig } from '/@/types/config'; 1 import type { ProjectConfig } from '/@/types/config';
2 2
3 import { MenuTypeEnum, MenuModeEnum, TriggerEnum } from '/@/enums/menuEnum'; 3 import { MenuTypeEnum, MenuModeEnum, TriggerEnum } from '/@/enums/menuEnum';
  4 +import { CacheTypeEnum } from '/@/enums/cacheEnum';
4 import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from '/@/enums/appEnum'; 5 import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from '/@/enums/appEnum';
5 import { primaryColor } from '../../build/config/lessModifyVars'; 6 import { primaryColor } from '../../build/config/lessModifyVars';
6 import { isProdMode } from '/@/utils/env'; 7 import { isProdMode } from '/@/utils/env';
@@ -13,6 +14,9 @@ const setting: ProjectConfig = { @@ -13,6 +14,9 @@ const setting: ProjectConfig = {
13 // Permission mode 14 // Permission mode
14 permissionMode: PermissionModeEnum.ROLE, 15 permissionMode: PermissionModeEnum.ROLE,
15 16
  17 + // Permission-related cache is stored in sessionStorage or localStorage
  18 + permissionCacheType: CacheTypeEnum.LOCAL,
  19 +
16 // color 20 // color
17 // TODO Theme color 21 // TODO Theme color
18 themeColor: primaryColor, 22 themeColor: primaryColor,
@@ -130,7 +134,7 @@ const setting: ProjectConfig = { @@ -130,7 +134,7 @@ const setting: ProjectConfig = {
130 openPageLoading: true, 134 openPageLoading: true,
131 135
132 // Whether to open the top progress bar 136 // Whether to open the top progress bar
133 - openNProgress: true, 137 + openNProgress: false,
134 }, 138 },
135 139
136 // Whether to enable KeepAlive cache is best to close during development, otherwise the cache needs to be cleared every time 140 // Whether to enable KeepAlive cache is best to close during development, otherwise the cache needs to be cleared every time
src/setup/App.ts
@@ -20,6 +20,7 @@ import { @@ -20,6 +20,7 @@ import {
20 } from '/@/setup/theme'; 20 } from '/@/setup/theme';
21 21
22 import { appStore } from '/@/store/modules/app'; 22 import { appStore } from '/@/store/modules/app';
  23 +import { deepMerge } from '../utils/index';
23 24
24 // Used to share global app instances 25 // Used to share global app instances
25 let app: App; 26 let app: App;
@@ -50,16 +51,15 @@ export function useThemeMode(mode: ThemeModeEnum) { @@ -50,16 +51,15 @@ export function useThemeMode(mode: ThemeModeEnum) {
50 // Initial project configuration 51 // Initial project configuration
51 export function initAppConfigStore() { 52 export function initAppConfigStore() {
52 let projCfg: ProjectConfig = getLocal(PROJ_CFG_KEY) as ProjectConfig; 53 let projCfg: ProjectConfig = getLocal(PROJ_CFG_KEY) as ProjectConfig;
53 - if (!projCfg) {  
54 - projCfg = projectSetting;  
55 - }  
56 - const {  
57 - colorWeak,  
58 - grayMode,  
59 - headerSetting: { bgColor: headerBgColor },  
60 - menuSetting: { bgColor },  
61 - } = projCfg; 54 + projCfg = deepMerge(projectSetting, projCfg || {});
  55 +
62 try { 56 try {
  57 + const {
  58 + colorWeak,
  59 + grayMode,
  60 + headerSetting: { bgColor: headerBgColor } = {},
  61 + menuSetting: { bgColor } = {},
  62 + } = projCfg;
63 // if ( 63 // if (
64 // themeColor !== primaryColor && 64 // themeColor !== primaryColor &&
65 // themeColor && 65 // themeColor &&
src/store/modules/app.ts
@@ -26,7 +26,7 @@ export interface LockInfo { @@ -26,7 +26,7 @@ export interface LockInfo {
26 isLock: boolean; 26 isLock: boolean;
27 } 27 }
28 28
29 -let timeId: ReturnType<typeof setTimeout>; 29 +let timeId: TimeoutHandle;
30 const NAME = 'app'; 30 const NAME = 'app';
31 hotModuleUnregisterModule(NAME); 31 hotModuleUnregisterModule(NAME);
32 @Module({ dynamic: true, namespaced: true, store, name: NAME }) 32 @Module({ dynamic: true, namespaced: true, store, name: NAME })
src/store/modules/user.ts
@@ -11,7 +11,7 @@ import { hotModuleUnregisterModule } from &#39;/@/utils/helper/vuexHelper&#39;; @@ -11,7 +11,7 @@ import { hotModuleUnregisterModule } from &#39;/@/utils/helper/vuexHelper&#39;;
11 11
12 import { PageEnum } from '/@/enums/pageEnum'; 12 import { PageEnum } from '/@/enums/pageEnum';
13 import { RoleEnum } from '/@/enums/roleEnum'; 13 import { RoleEnum } from '/@/enums/roleEnum';
14 -import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '/@/enums/cacheEnum'; 14 +import { CacheTypeEnum, ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '/@/enums/cacheEnum';
15 15
16 import { useMessage } from '/@/hooks/web/useMessage'; 16 import { useMessage } from '/@/hooks/web/useMessage';
17 17
@@ -19,13 +19,29 @@ import router from &#39;/@/router&#39;; @@ -19,13 +19,29 @@ import router from &#39;/@/router&#39;;
19 19
20 import { loginApi, getUserInfoById } from '/@/api/sys/user'; 20 import { loginApi, getUserInfoById } from '/@/api/sys/user';
21 21
22 -import { setLocal, getLocal } from '/@/utils/helper/persistent';  
23 -// import { FULL_PAGE_NOT_FOUND_ROUTE } from '/@/router/constant'; 22 +import { setLocal, getLocal, getSession, setSession } from '/@/utils/helper/persistent';
  23 +import { useProjectSetting } from '/@/hooks/setting';
24 24
25 export type UserInfo = Omit<GetUserInfoByUserIdModel, 'roles'>; 25 export type UserInfo = Omit<GetUserInfoByUserIdModel, 'roles'>;
26 26
27 const NAME = 'user'; 27 const NAME = 'user';
28 hotModuleUnregisterModule(NAME); 28 hotModuleUnregisterModule(NAME);
  29 +
  30 +const { permissionCacheType } = useProjectSetting();
  31 +
  32 +function getCache<T>(key: string) {
  33 + const fn = permissionCacheType === CacheTypeEnum.LOCAL ? getLocal : getSession;
  34 + return fn(key) as T;
  35 +}
  36 +
  37 +function setCache(USER_INFO_KEY: string, info: any) {
  38 + if (!info) return;
  39 + // const fn = permissionCacheType === CacheTypeEnum.LOCAL ? setLocal : setSession;
  40 + setLocal(USER_INFO_KEY, info, true);
  41 + // TODO
  42 + setSession(USER_INFO_KEY, info, true);
  43 +}
  44 +
29 @Module({ namespaced: true, name: NAME, dynamic: true, store }) 45 @Module({ namespaced: true, name: NAME, dynamic: true, store })
30 class User extends VuexModule { 46 class User extends VuexModule {
31 // user info 47 // user info
@@ -38,15 +54,15 @@ class User extends VuexModule { @@ -38,15 +54,15 @@ class User extends VuexModule {
38 private roleListState: RoleEnum[] = []; 54 private roleListState: RoleEnum[] = [];
39 55
40 get getUserInfoState(): UserInfo { 56 get getUserInfoState(): UserInfo {
41 - return this.userInfoState || (getLocal(USER_INFO_KEY) as UserInfo) || {}; 57 + return this.userInfoState || getCache<UserInfo>(USER_INFO_KEY) || {};
42 } 58 }
43 59
44 get getTokenState(): string { 60 get getTokenState(): string {
45 - return this.tokenState || (getLocal(TOKEN_KEY) as string); 61 + return this.tokenState || getCache<string>(TOKEN_KEY);
46 } 62 }
47 63
48 get getRoleListState(): RoleEnum[] { 64 get getRoleListState(): RoleEnum[] {
49 - return this.roleListState.length > 0 ? this.roleListState : (getLocal(ROLES_KEY) as RoleEnum[]); 65 + return this.roleListState.length > 0 ? this.roleListState : getCache<RoleEnum[]>(ROLES_KEY);
50 } 66 }
51 67
52 @Mutation 68 @Mutation
@@ -59,25 +75,19 @@ class User extends VuexModule { @@ -59,25 +75,19 @@ class User extends VuexModule {
59 @Mutation 75 @Mutation
60 commitUserInfoState(info: UserInfo): void { 76 commitUserInfoState(info: UserInfo): void {
61 this.userInfoState = info; 77 this.userInfoState = info;
62 - if (info) {  
63 - setLocal(USER_INFO_KEY, info, true);  
64 - } 78 + setCache(USER_INFO_KEY, info);
65 } 79 }
66 80
67 @Mutation 81 @Mutation
68 commitRoleListState(roleList: RoleEnum[]): void { 82 commitRoleListState(roleList: RoleEnum[]): void {
69 this.roleListState = roleList; 83 this.roleListState = roleList;
70 - if (roleList) {  
71 - setLocal(ROLES_KEY, roleList, true);  
72 - } 84 + setCache(ROLES_KEY, roleList);
73 } 85 }
74 86
75 @Mutation 87 @Mutation
76 commitTokenState(info: string): void { 88 commitTokenState(info: string): void {
77 this.tokenState = info; 89 this.tokenState = info;
78 - if (info) {  
79 - setLocal(TOKEN_KEY, info, true);  
80 - } 90 + setCache(TOKEN_KEY, info);
81 } 91 }
82 92
83 /** 93 /**
src/types/config.d.ts
1 -// 左侧菜单, 顶部菜单  
2 import { MenuTypeEnum, MenuModeEnum, TriggerEnum } from '/@/enums/menuEnum'; 1 import { MenuTypeEnum, MenuModeEnum, TriggerEnum } from '/@/enums/menuEnum';
3 import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from '/@/enums/appEnum'; 2 import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from '/@/enums/appEnum';
  3 +import { CacheTypeEnum } from '/@/enums/cacheEnum';
4 import type { LocaleType } from '/@/locales/types'; 4 import type { LocaleType } from '/@/locales/types';
5 5
6 export interface MenuSetting { 6 export interface MenuSetting {
@@ -76,6 +76,8 @@ export interface TransitionSetting { @@ -76,6 +76,8 @@ export interface TransitionSetting {
76 export interface ProjectConfig { 76 export interface ProjectConfig {
77 locale: LocaleSetting; 77 locale: LocaleSetting;
78 78
  79 + permissionCacheType: CacheTypeEnum;
  80 +
79 // 是否显示配置按钮 81 // 是否显示配置按钮
80 showSettingButton: boolean; 82 showSettingButton: boolean;
81 // 权限模式 83 // 权限模式
src/utils/helper/persistent.ts
@@ -29,8 +29,12 @@ function initCache() { @@ -29,8 +29,12 @@ function initCache() {
29 initCache(); 29 initCache();
30 30
31 export function setLocal(key: string, value: any, immediate = false) { 31 export function setLocal(key: string, value: any, immediate = false) {
32 - cacheStore.local[BASE_LOCAL_CACHE_KEY] = cacheStore.local[BASE_LOCAL_CACHE_KEY] || {}; 32 + const local = ls.get(BASE_LOCAL_CACHE_KEY)?.[BASE_LOCAL_CACHE_KEY] || {};
  33 +
  34 + cacheStore.local[BASE_LOCAL_CACHE_KEY] =
  35 + { ...local, ...cacheStore.local[BASE_LOCAL_CACHE_KEY] } || {};
33 cacheStore.local[BASE_LOCAL_CACHE_KEY][key] = value; 36 cacheStore.local[BASE_LOCAL_CACHE_KEY][key] = value;
  37 +
34 if (immediate) { 38 if (immediate) {
35 ls.set(BASE_LOCAL_CACHE_KEY, cacheStore.local); 39 ls.set(BASE_LOCAL_CACHE_KEY, cacheStore.local);
36 } 40 }
@@ -50,16 +54,21 @@ export function removeLocal(key: string) { @@ -50,16 +54,21 @@ export function removeLocal(key: string) {
50 } 54 }
51 } 55 }
52 56
53 -export function clearLocal() { 57 +export function clearLocal(immediate = false) {
54 cacheStore.local = {}; 58 cacheStore.local = {};
  59 + immediate && ls.remove(BASE_LOCAL_CACHE_KEY);
55 } 60 }
56 61
57 export function setSession(key: string, value: any, immediate = false) { 62 export function setSession(key: string, value: any, immediate = false) {
58 - cacheStore.session[BASE_SESSION_CACHE_KEY] = cacheStore.session[BASE_SESSION_CACHE_KEY] || {}; 63 + const session = ss.get(BASE_SESSION_CACHE_KEY)?.[BASE_SESSION_CACHE_KEY] || {};
  64 +
  65 + cacheStore.session[BASE_SESSION_CACHE_KEY] =
  66 + { ...session, ...cacheStore.session[BASE_SESSION_CACHE_KEY] } || {};
  67 +
59 cacheStore.session[BASE_SESSION_CACHE_KEY][key] = value; 68 cacheStore.session[BASE_SESSION_CACHE_KEY][key] = value;
  69 +
60 if (immediate) { 70 if (immediate) {
61 - const cache = cacheStore.session;  
62 - ss.set(BASE_SESSION_CACHE_KEY, cache); 71 + ss.set(BASE_SESSION_CACHE_KEY, cacheStore.session);
63 } 72 }
64 } 73 }
65 74
@@ -77,8 +86,9 @@ export function getSession&lt;T&gt;(key: string): T | null { @@ -77,8 +86,9 @@ export function getSession&lt;T&gt;(key: string): T | null {
77 } 86 }
78 } 87 }
79 88
80 -export function clearSession() { 89 +export function clearSession(immediate = false) {
81 cacheStore.session = {}; 90 cacheStore.session = {};
  91 + immediate && ss.remove(BASE_SESSION_CACHE_KEY);
82 } 92 }
83 93
84 export function clearAll() { 94 export function clearAll() {
@@ -86,14 +96,17 @@ export function clearAll() { @@ -86,14 +96,17 @@ export function clearAll() {
86 clearSession(); 96 clearSession();
87 } 97 }
88 98
  99 +export function persistentCache() {
  100 + const localCache = cacheStore.local;
  101 + const sessionCache = cacheStore.session;
  102 + ls.set(BASE_LOCAL_CACHE_KEY, localCache);
  103 + ss.set(BASE_SESSION_CACHE_KEY, sessionCache);
  104 +}
  105 +
89 (() => { 106 (() => {
90 // /** Write to local before closing window */ 107 // /** Write to local before closing window */
91 window.addEventListener('beforeunload', () => { 108 window.addEventListener('beforeunload', () => {
92 - const localCache = cacheStore.local;  
93 - const sessionCache = cacheStore.session;  
94 -  
95 - ls.set(BASE_LOCAL_CACHE_KEY, localCache);  
96 - ss.set(BASE_SESSION_CACHE_KEY, sessionCache); 109 + persistentCache();
97 }); 110 });
98 111
99 function storageChange(e: any) { 112 function storageChange(e: any) {