From 26b6109ca08a28c37355474bf8593f2e2b741ef6 Mon Sep 17 00:00:00 2001 From: vben <anncwb@126.com> Date: 星期三, 25 十一月 2020 21:26:10 +0800 Subject: [PATCH] feat: add permissionCacheType setting --- src/settings/projectSetting.ts | 6 + src/store/modules/app.ts | 2 src/utils/helper/persistent.ts | 35 ++++++-- src/layouts/default/multitabs/useAffixTabs.ts | 35 ++++++++ src/store/modules/user.ts | 40 ++++++--- src/hooks/web/useLockPage.ts | 2 src/hooks/setting/useTransitionSetting.ts | 2 src/types/config.d.ts | 4 src/hooks/core/useTimeout.ts | 2 src/enums/cacheEnum.ts | 5 + src/layouts/default/multitabs/useTabDropdown.ts | 1 src/layouts/default/multitabs/index.tsx | 49 ++--------- src/router/guard/index.ts | 2 src/layouts/default/multitabs/index.less | 7 - src/setup/App.ts | 18 ++-- 15 files changed, 123 insertions(+), 87 deletions(-) diff --git a/src/enums/cacheEnum.ts b/src/enums/cacheEnum.ts index 77cfdbd..4e6f43e 100644 --- a/src/enums/cacheEnum.ts +++ b/src/enums/cacheEnum.ts @@ -18,3 +18,8 @@ // base global session key export const BASE_SESSION_CACHE_KEY = 'SESSION__CACHE__KEY__'; + +export enum CacheTypeEnum { + SESSION, + LOCAL, +} diff --git a/src/hooks/core/useTimeout.ts b/src/hooks/core/useTimeout.ts index 4fcc19a..119cbe7 100644 --- a/src/hooks/core/useTimeout.ts +++ b/src/hooks/core/useTimeout.ts @@ -23,7 +23,7 @@ export function useTimeoutRef(wait: number) { const readyRef = ref(false); - let timer: ReturnType<typeof setTimeout> | undefined; + let timer: TimeoutHandle; function stop(): void { readyRef.value = false; timer && window.clearTimeout(timer); diff --git a/src/hooks/setting/useTransitionSetting.ts b/src/hooks/setting/useTransitionSetting.ts index 17039f8..ce7f759 100644 --- a/src/hooks/setting/useTransitionSetting.ts +++ b/src/hooks/setting/useTransitionSetting.ts @@ -7,7 +7,7 @@ export function useTransitionSetting() { const getTransitionSetting = computed(() => appStore.getProjectConfig.transitionSetting); - const getEnableTransition = computed(() => unref(getTransitionSetting).enable); + const getEnableTransition = computed(() => unref(getTransitionSetting)?.enable); const getOpenNProgress = computed(() => unref(getTransitionSetting)?.openNProgress); diff --git a/src/hooks/web/useLockPage.ts b/src/hooks/web/useLockPage.ts index 1988b4e..c315e67 100644 --- a/src/hooks/web/useLockPage.ts +++ b/src/hooks/web/useLockPage.ts @@ -5,7 +5,7 @@ import { userStore } from '/@/store/modules/user'; export function useLockPage() { - let timeId: ReturnType<typeof setTimeout>; + let timeId: TimeoutHandle; function clear(): void { window.clearTimeout(timeId); diff --git a/src/layouts/default/multitabs/index.less b/src/layouts/default/multitabs/index.less index 1e052ab..ff636b0 100644 --- a/src/layouts/default/multitabs/index.less +++ b/src/layouts/default/multitabs/index.less @@ -40,12 +40,9 @@ height: 12px; font-size: 12px; color: inherit; - visibility: hidden; transition: none; &:hover { - visibility: visible; - svg { width: 0.8em; } @@ -70,10 +67,6 @@ &::before { display: none; - } - - .ant-tabs-close-x { - visibility: visible; } svg { diff --git a/src/layouts/default/multitabs/index.tsx b/src/layouts/default/multitabs/index.tsx index 8b00f61..4defffd 100644 --- a/src/layouts/default/multitabs/index.tsx +++ b/src/layouts/default/multitabs/index.tsx @@ -1,10 +1,11 @@ +import './index.less'; + import type { TabContentProps } from './tab.data'; import type { TabItem } from '/@/store/modules/tab'; import type { AppRouteRecordRaw } from '/@/router/types'; -import { defineComponent, watch, computed, unref, toRaw } from 'vue'; +import { defineComponent, watch, computed, unref } from 'vue'; import { useRouter } from 'vue-router'; -import router from '/@/router'; import { Tabs } from 'ant-design-vue'; import TabContent from './TabContent'; @@ -18,12 +19,12 @@ import { closeTab } from './useTabDropdown'; import { useTabs } from '/@/hooks/web/useTabs'; +import { initAffixTabs } from './useAffixTabs'; -import './index.less'; export default defineComponent({ - name: 'MultiTabs', + name: 'MultipleTabs', setup() { - let isAddAffix = false; + initAffixTabs(); const go = useGo(); @@ -36,11 +37,6 @@ watch( () => tabStore.getLastChangeRouteState, () => { - if (!isAddAffix) { - addAffixTabs(); - isAddAffix = true; - } - const lastChangeRoute = unref(tabStore.getLastChangeRouteState); if (!lastChangeRoute || !userStore.getTokenState) return; @@ -56,39 +52,15 @@ } ); - /** - * @description: 杩囨护鎵�鏈夊浐瀹氳矾鐢� - */ - function filterAffixTabs(routes: AppRouteRecordRaw[]) { - const tabs: TabItem[] = []; - routes && - routes.forEach((route) => { - if (route.meta && route.meta.affix) { - tabs.push(toRaw(route) as TabItem); - } - }); - return tabs; - } - - /** - * @description: 璁剧疆鍥哄畾tabs - */ - function addAffixTabs(): void { - const affixTabs = filterAffixTabs((router.getRoutes() as unknown) as AppRouteRecordRaw[]); - for (const tab of affixTabs) { - tabStore.commitAddTab(tab); - } - } - // tab鍒囨崲 function handleChange(activeKey: any) { activeKeyRef.value = activeKey; go(activeKey, false); } - // 鍏抽棴褰撳墠ab + // 鍏抽棴褰撳墠tab function handleEdit(targetKey: string) { - // 鏂板鎿嶄綔闅愯棌锛岀洰鍓嶅彧浣跨敤鍒犻櫎鎿嶄綔 + // Added operation to hide, currently only use delete operation const index = unref(getTabsState).findIndex( (item) => (item.fullPath || item.path) === targetKey ); @@ -107,12 +79,13 @@ </span> ); } + function renderTabs() { return unref(getTabsState).map((item: TabItem) => { const key = item.query ? item.fullPath : item.path; - + const closable = !(item && item.meta && item.meta.affix); return ( - <Tabs.TabPane key={key} closable={!(item && item.meta && item.meta.affix)}> + <Tabs.TabPane key={key} closable={closable}> {{ tab: () => <TabContent tabItem={item} />, }} diff --git a/src/layouts/default/multitabs/useAffixTabs.ts b/src/layouts/default/multitabs/useAffixTabs.ts new file mode 100644 index 0000000..24cb4ba --- /dev/null +++ b/src/layouts/default/multitabs/useAffixTabs.ts @@ -0,0 +1,35 @@ +import { toRaw } from 'vue'; +import router from '/@/router'; +import { AppRouteRecordRaw } from '/@/router/types'; +import { TabItem, tabStore } from '/@/store/modules/tab'; + +export function initAffixTabs() { + /** + * @description: Filter all fixed routes + */ + function filterAffixTabs(routes: AppRouteRecordRaw[]) { + const tabs: TabItem[] = []; + routes && + routes.forEach((route) => { + if (route.meta && route.meta.affix) { + tabs.push(toRaw(route) as TabItem); + } + }); + return tabs; + } + + /** + * @description: Set fixed tabs + */ + function addAffixTabs(): void { + const affixTabs = filterAffixTabs((router.getRoutes() as unknown) as AppRouteRecordRaw[]); + for (const tab of affixTabs) { + tabStore.commitAddTab(tab); + } + } + let isAddAffix = false; + if (!isAddAffix) { + addAffixTabs(); + isAddAffix = true; + } +} diff --git a/src/layouts/default/multitabs/useTabDropdown.ts b/src/layouts/default/multitabs/useTabDropdown.ts index bfa0350..7fb893b 100644 --- a/src/layouts/default/multitabs/useTabDropdown.ts +++ b/src/layouts/default/multitabs/useTabDropdown.ts @@ -203,6 +203,7 @@ const getTabsState = computed(() => { return tabStore.getTabsState; }); + const { path } = unref(currentRoute); if (path !== closedTab.path) { // 鍏抽棴鐨勪笉鏄縺娲籺ab diff --git a/src/router/guard/index.ts b/src/router/guard/index.ts index 6143d41..98bf617 100644 --- a/src/router/guard/index.ts +++ b/src/router/guard/index.ts @@ -14,9 +14,9 @@ import { tabStore } from '/@/store/modules/tab'; +const { closeMessageOnSwitch, removeAllHttpPending } = useProjectSetting(); const globSetting = useGlobSetting(); export function createGuard(router: Router) { - const { closeMessageOnSwitch, removeAllHttpPending } = useProjectSetting(); let axiosCanceler: AxiosCanceler | null; if (removeAllHttpPending) { axiosCanceler = new AxiosCanceler(); diff --git a/src/settings/projectSetting.ts b/src/settings/projectSetting.ts index 6562e72..9a4156d 100644 --- a/src/settings/projectSetting.ts +++ b/src/settings/projectSetting.ts @@ -1,6 +1,7 @@ import type { ProjectConfig } from '/@/types/config'; import { MenuTypeEnum, MenuModeEnum, TriggerEnum } from '/@/enums/menuEnum'; +import { CacheTypeEnum } from '/@/enums/cacheEnum'; import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from '/@/enums/appEnum'; import { primaryColor } from '../../build/config/lessModifyVars'; import { isProdMode } from '/@/utils/env'; @@ -12,6 +13,9 @@ // Permission mode permissionMode: PermissionModeEnum.ROLE, + + // Permission-related cache is stored in sessionStorage or localStorage + permissionCacheType: CacheTypeEnum.LOCAL, // color // TODO Theme color @@ -130,7 +134,7 @@ openPageLoading: true, // Whether to open the top progress bar - openNProgress: true, + openNProgress: false, }, // Whether to enable KeepAlive cache is best to close during development, otherwise the cache needs to be cleared every time diff --git a/src/setup/App.ts b/src/setup/App.ts index 1028159..3ab0db9 100644 --- a/src/setup/App.ts +++ b/src/setup/App.ts @@ -20,6 +20,7 @@ } from '/@/setup/theme'; import { appStore } from '/@/store/modules/app'; +import { deepMerge } from '../utils/index'; // Used to share global app instances let app: App; @@ -50,16 +51,15 @@ // Initial project configuration export function initAppConfigStore() { let projCfg: ProjectConfig = getLocal(PROJ_CFG_KEY) as ProjectConfig; - if (!projCfg) { - projCfg = projectSetting; - } - const { - colorWeak, - grayMode, - headerSetting: { bgColor: headerBgColor }, - menuSetting: { bgColor }, - } = projCfg; + projCfg = deepMerge(projectSetting, projCfg || {}); + try { + const { + colorWeak, + grayMode, + headerSetting: { bgColor: headerBgColor } = {}, + menuSetting: { bgColor } = {}, + } = projCfg; // if ( // themeColor !== primaryColor && // themeColor && diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts index 6be45f8..b4b6d61 100644 --- a/src/store/modules/app.ts +++ b/src/store/modules/app.ts @@ -26,7 +26,7 @@ isLock: boolean; } -let timeId: ReturnType<typeof setTimeout>; +let timeId: TimeoutHandle; const NAME = 'app'; hotModuleUnregisterModule(NAME); @Module({ dynamic: true, namespaced: true, store, name: NAME }) diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index c037681..fe4bc97 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -11,7 +11,7 @@ import { PageEnum } from '/@/enums/pageEnum'; import { RoleEnum } from '/@/enums/roleEnum'; -import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '/@/enums/cacheEnum'; +import { CacheTypeEnum, ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '/@/enums/cacheEnum'; import { useMessage } from '/@/hooks/web/useMessage'; @@ -19,13 +19,29 @@ import { loginApi, getUserInfoById } from '/@/api/sys/user'; -import { setLocal, getLocal } from '/@/utils/helper/persistent'; -// import { FULL_PAGE_NOT_FOUND_ROUTE } from '/@/router/constant'; +import { setLocal, getLocal, getSession, setSession } from '/@/utils/helper/persistent'; +import { useProjectSetting } from '/@/hooks/setting'; export type UserInfo = Omit<GetUserInfoByUserIdModel, 'roles'>; const NAME = 'user'; hotModuleUnregisterModule(NAME); + +const { permissionCacheType } = useProjectSetting(); + +function getCache<T>(key: string) { + const fn = permissionCacheType === CacheTypeEnum.LOCAL ? getLocal : getSession; + return fn(key) as T; +} + +function setCache(USER_INFO_KEY: string, info: any) { + if (!info) return; + // const fn = permissionCacheType === CacheTypeEnum.LOCAL ? setLocal : setSession; + setLocal(USER_INFO_KEY, info, true); + // TODO + setSession(USER_INFO_KEY, info, true); +} + @Module({ namespaced: true, name: NAME, dynamic: true, store }) class User extends VuexModule { // user info @@ -38,15 +54,15 @@ private roleListState: RoleEnum[] = []; get getUserInfoState(): UserInfo { - return this.userInfoState || (getLocal(USER_INFO_KEY) as UserInfo) || {}; + return this.userInfoState || getCache<UserInfo>(USER_INFO_KEY) || {}; } get getTokenState(): string { - return this.tokenState || (getLocal(TOKEN_KEY) as string); + return this.tokenState || getCache<string>(TOKEN_KEY); } get getRoleListState(): RoleEnum[] { - return this.roleListState.length > 0 ? this.roleListState : (getLocal(ROLES_KEY) as RoleEnum[]); + return this.roleListState.length > 0 ? this.roleListState : getCache<RoleEnum[]>(ROLES_KEY); } @Mutation @@ -59,25 +75,19 @@ @Mutation commitUserInfoState(info: UserInfo): void { this.userInfoState = info; - if (info) { - setLocal(USER_INFO_KEY, info, true); - } + setCache(USER_INFO_KEY, info); } @Mutation commitRoleListState(roleList: RoleEnum[]): void { this.roleListState = roleList; - if (roleList) { - setLocal(ROLES_KEY, roleList, true); - } + setCache(ROLES_KEY, roleList); } @Mutation commitTokenState(info: string): void { this.tokenState = info; - if (info) { - setLocal(TOKEN_KEY, info, true); - } + setCache(TOKEN_KEY, info); } /** diff --git a/src/types/config.d.ts b/src/types/config.d.ts index 2a80b23..43d465b 100644 --- a/src/types/config.d.ts +++ b/src/types/config.d.ts @@ -1,6 +1,6 @@ -// 宸︿晶鑿滃崟, 椤堕儴鑿滃崟 import { MenuTypeEnum, MenuModeEnum, TriggerEnum } from '/@/enums/menuEnum'; import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from '/@/enums/appEnum'; +import { CacheTypeEnum } from '/@/enums/cacheEnum'; import type { LocaleType } from '/@/locales/types'; export interface MenuSetting { @@ -76,6 +76,8 @@ export interface ProjectConfig { locale: LocaleSetting; + permissionCacheType: CacheTypeEnum; + // 鏄惁鏄剧ず閰嶇疆鎸夐挳 showSettingButton: boolean; // 鏉冮檺妯″紡 diff --git a/src/utils/helper/persistent.ts b/src/utils/helper/persistent.ts index 62449d1..46f99c8 100644 --- a/src/utils/helper/persistent.ts +++ b/src/utils/helper/persistent.ts @@ -29,8 +29,12 @@ initCache(); export function setLocal(key: string, value: any, immediate = false) { - cacheStore.local[BASE_LOCAL_CACHE_KEY] = cacheStore.local[BASE_LOCAL_CACHE_KEY] || {}; + const local = ls.get(BASE_LOCAL_CACHE_KEY)?.[BASE_LOCAL_CACHE_KEY] || {}; + + cacheStore.local[BASE_LOCAL_CACHE_KEY] = + { ...local, ...cacheStore.local[BASE_LOCAL_CACHE_KEY] } || {}; cacheStore.local[BASE_LOCAL_CACHE_KEY][key] = value; + if (immediate) { ls.set(BASE_LOCAL_CACHE_KEY, cacheStore.local); } @@ -50,16 +54,21 @@ } } -export function clearLocal() { +export function clearLocal(immediate = false) { cacheStore.local = {}; + immediate && ls.remove(BASE_LOCAL_CACHE_KEY); } export function setSession(key: string, value: any, immediate = false) { - cacheStore.session[BASE_SESSION_CACHE_KEY] = cacheStore.session[BASE_SESSION_CACHE_KEY] || {}; + const session = ss.get(BASE_SESSION_CACHE_KEY)?.[BASE_SESSION_CACHE_KEY] || {}; + + cacheStore.session[BASE_SESSION_CACHE_KEY] = + { ...session, ...cacheStore.session[BASE_SESSION_CACHE_KEY] } || {}; + cacheStore.session[BASE_SESSION_CACHE_KEY][key] = value; + if (immediate) { - const cache = cacheStore.session; - ss.set(BASE_SESSION_CACHE_KEY, cache); + ss.set(BASE_SESSION_CACHE_KEY, cacheStore.session); } } @@ -77,8 +86,9 @@ } } -export function clearSession() { +export function clearSession(immediate = false) { cacheStore.session = {}; + immediate && ss.remove(BASE_SESSION_CACHE_KEY); } export function clearAll() { @@ -86,14 +96,17 @@ clearSession(); } +export function persistentCache() { + const localCache = cacheStore.local; + const sessionCache = cacheStore.session; + ls.set(BASE_LOCAL_CACHE_KEY, localCache); + ss.set(BASE_SESSION_CACHE_KEY, sessionCache); +} + (() => { // /** Write to local before closing window */ window.addEventListener('beforeunload', () => { - const localCache = cacheStore.local; - const sessionCache = cacheStore.session; - - ls.set(BASE_LOCAL_CACHE_KEY, localCache); - ss.set(BASE_SESSION_CACHE_KEY, sessionCache); + persistentCache(); }); function storageChange(e: any) { -- Gitblit v1.8.0