diff --git a/README.md b/README.md
index 06fa86de8..8aae93e96 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,7 @@ Soybean Admin 是一个基于 Vue3、Vite、TypeScript、Naive UI 的免费中
- [x] 引入ECharts替换AntV G2Plot
- [x] 图表示例:ECharts、AntV G2
- [x] 多页签:支持query、hash等参数,同一页面支持多个Tab
-- [ ] 缓存主题配置
+- [x] 缓存主题配置
- [ ] 添加锁屏组件、全局Iframe组件
- [ ] 示例页面完善
- [ ] 表单、表格示例
diff --git a/src/App.vue b/src/App.vue
index eff8cb3a5..49b41aea5 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -15,10 +15,12 @@
diff --git a/src/composables/events.ts b/src/composables/events.ts
new file mode 100644
index 000000000..886ab305b
--- /dev/null
+++ b/src/composables/events.ts
@@ -0,0 +1,14 @@
+import { useEventListener } from '@vueuse/core';
+import { useThemeStore, useTabStore } from '@/store';
+
+/** 全局事件 */
+export function useGlobalEvents() {
+ const theme = useThemeStore();
+ const tab = useTabStore();
+
+ /** 页面离开时缓存多页签数据 */
+ useEventListener(window, 'beforeunload', () => {
+ theme.cacheThemeSettings();
+ tab.cacheTabRoutes();
+ });
+}
diff --git a/src/composables/index.ts b/src/composables/index.ts
index c5107972e..274f90e7d 100644
--- a/src/composables/index.ts
+++ b/src/composables/index.ts
@@ -1,4 +1,5 @@
export * from './system';
export * from './router';
export * from './layout';
+export * from './events';
export * from './echarts';
diff --git a/src/enum/common.ts b/src/enum/common.ts
index 49b3f7326..e33c896f8 100644
--- a/src/enum/common.ts
+++ b/src/enum/common.ts
@@ -15,6 +15,8 @@ export enum EnumStorageKey {
'refresh-token' = '__REFRESH_TOKEN__',
/** 用户信息 */
'user-info' = '__USER_INFO__',
+ /** 主题配置 */
+ 'theme-settings' = '__THEME_SETTINGS__',
/** 多页签路由信息 */
'multi-tab-routes' = '__MULTI_TAB_ROUTES__'
}
diff --git a/src/layouts/common/GlobalHeader/components/SettingButton.vue b/src/layouts/common/GlobalHeader/components/SettingButton.vue
new file mode 100644
index 000000000..22cf1d04f
--- /dev/null
+++ b/src/layouts/common/GlobalHeader/components/SettingButton.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/layouts/common/GlobalHeader/components/index.ts b/src/layouts/common/GlobalHeader/components/index.ts
index 3ddf1d03c..6eed72990 100644
--- a/src/layouts/common/GlobalHeader/components/index.ts
+++ b/src/layouts/common/GlobalHeader/components/index.ts
@@ -6,5 +6,16 @@ import FullScreen from './FullScreen.vue';
import ThemeMode from './ThemeMode.vue';
import UserAvatar from './UserAvatar.vue';
import SystemMessage from './SystemMessage.vue';
+import SettingButton from './SettingButton.vue';
-export { MenuCollapse, GlobalBreadcrumb, HeaderMenu, GithubSite, FullScreen, ThemeMode, UserAvatar, SystemMessage };
+export {
+ MenuCollapse,
+ GlobalBreadcrumb,
+ HeaderMenu,
+ GithubSite,
+ FullScreen,
+ ThemeMode,
+ UserAvatar,
+ SystemMessage,
+ SettingButton
+};
diff --git a/src/layouts/common/GlobalHeader/index.vue b/src/layouts/common/GlobalHeader/index.vue
index 2fdf0d76e..c25acdde5 100644
--- a/src/layouts/common/GlobalHeader/index.vue
+++ b/src/layouts/common/GlobalHeader/index.vue
@@ -12,6 +12,7 @@
+
@@ -29,7 +30,8 @@ import {
FullScreen,
ThemeMode,
UserAvatar,
- SystemMessage
+ SystemMessage,
+ SettingButton
} from './components';
interface Props {
@@ -44,6 +46,8 @@ interface Props {
defineProps();
const theme = useThemeStore();
+
+const isProd = import.meta.env.PROD;
diff --git a/src/layouts/common/SettingDrawer/index.vue b/src/layouts/common/SettingDrawer/index.vue
index 31657c31f..0e46a133a 100644
--- a/src/layouts/common/SettingDrawer/index.vue
+++ b/src/layouts/common/SettingDrawer/index.vue
@@ -9,7 +9,7 @@
-
+
diff --git a/src/store/modules/tab/helpers.ts b/src/store/modules/tab/helpers.ts
index 1eccf9a92..5347a2347 100644
--- a/src/store/modules/tab/helpers.ts
+++ b/src/store/modules/tab/helpers.ts
@@ -1,4 +1,6 @@
import type { RouteRecordNormalized, RouteLocationNormalizedLoaded } from 'vue-router';
+import { EnumStorageKey } from '@/enum';
+import { setLocal, getLocal } from '@/utils';
/**
* 根据vue路由获取tab路由
@@ -55,3 +57,30 @@ function hasFullPath(
): route is RouteLocationNormalizedLoaded {
return Boolean((route as RouteLocationNormalizedLoaded).fullPath);
}
+
+/** 缓存多页签数据 */
+export function setTabRoutes(data: GlobalTabRoute[]) {
+ setLocal(EnumStorageKey['multi-tab-routes'], data);
+}
+
+/** 获取缓存的多页签数据 */
+export function getTabRoutes() {
+ const routes: GlobalTabRoute[] = [];
+ const data = getLocal(EnumStorageKey['multi-tab-routes']);
+ if (data) {
+ const defaultTabRoutes = data.map(item => ({
+ ...item,
+ scrollPosition: {
+ left: 0,
+ top: 0
+ }
+ }));
+ routes.push(...defaultTabRoutes);
+ }
+ return routes;
+}
+
+/** 清空多页签数据 */
+export function clearTabRoutes() {
+ setTabRoutes([]);
+}
diff --git a/src/store/modules/tab/index.ts b/src/store/modules/tab/index.ts
index 118989444..ce8056e14 100644
--- a/src/store/modules/tab/index.ts
+++ b/src/store/modules/tab/index.ts
@@ -1,9 +1,16 @@
import type { Router, RouteLocationNormalizedLoaded } from 'vue-router';
import { defineStore } from 'pinia';
import { useRouterPush } from '@/composables';
-import { getTabRoutes, clearTabRoutes } from '@/utils';
import { useThemeStore } from '../theme';
-import { getTabRouteByVueRoute, isInTabRoutes, getIndexInTabRoutes, getIndexInTabRoutesByRouteName } from './helpers';
+import {
+ getTabRouteByVueRoute,
+ isInTabRoutes,
+ getIndexInTabRoutes,
+ getIndexInTabRoutesByRouteName,
+ setTabRoutes,
+ getTabRoutes,
+ clearTabRoutes
+} from './helpers';
interface TabState {
/** 多页签数据 */
@@ -43,6 +50,10 @@ export const useTabStore = defineStore('tab-store', {
clearTabRoutes();
this.$reset();
},
+ /** 缓存页签路由数据 */
+ cacheTabRoutes() {
+ setTabRoutes(this.tabs);
+ },
/**
* 设置当前路由对应的页签为激活状态
* @param fullPath - 路由fullPath
diff --git a/src/store/modules/theme/helpers.ts b/src/store/modules/theme/helpers.ts
index 1614c5780..ac0b9f737 100644
--- a/src/store/modules/theme/helpers.ts
+++ b/src/store/modules/theme/helpers.ts
@@ -1,10 +1,18 @@
import type { GlobalThemeOverrides } from 'naive-ui';
import { cloneDeep } from 'lodash-es';
import { themeSetting } from '@/settings';
-import { getThemeColor, getColorPalette, addColorAlpha } from '@/utils';
+import { EnumStorageKey } from '@/enum';
+import { getThemeColor, getColorPalette, addColorAlpha, setLocal, getLocal, removeLocal } from '@/utils';
+
+/** 初始化主题配置 */
+export function initThemeSettings() {
+ const isProd = import.meta.env.PROD;
+ // 生产环境才缓存主题配置,本地开发实时调整配置更改配置的json
+ const storageSettings = getThemeSettings();
+ if (isProd && storageSettings) {
+ return storageSettings;
+ }
-/** 获取主题配置 */
-export function getThemeSettings() {
const themeColor = getThemeColor() || themeSetting.themeColor;
const info = themeSetting.isCustomizeInfoColor ? themeSetting.otherColor.info : getColorPalette(themeColor, 7);
const otherColor = { ...themeSetting.otherColor, info };
@@ -70,3 +78,18 @@ export function getNaiveThemeOverrides(colors: Record): Globa
}
};
}
+
+/** 获取缓存中的主题配置 */
+function getThemeSettings() {
+ return getLocal(EnumStorageKey['theme-settings']);
+}
+
+/** 获取缓存中的主题配置 */
+export function setThemeSettings(settings: Theme.Setting) {
+ return setLocal(EnumStorageKey['theme-settings'], settings);
+}
+
+/** 清除缓存配置 */
+export function clearThemeSettings() {
+ removeLocal(EnumStorageKey['theme-settings']);
+}
diff --git a/src/store/modules/theme/index.ts b/src/store/modules/theme/index.ts
index 98849056d..70e3f8182 100644
--- a/src/store/modules/theme/index.ts
+++ b/src/store/modules/theme/index.ts
@@ -1,11 +1,11 @@
import { defineStore } from 'pinia';
import { darkTheme } from 'naive-ui';
-import { getThemeSettings, getNaiveThemeOverrides } from './helpers';
+import { initThemeSettings, getNaiveThemeOverrides, setThemeSettings, clearThemeSettings } from './helpers';
type ThemeState = Theme.Setting;
export const useThemeStore = defineStore('theme-store', {
- state: (): ThemeState => getThemeSettings(),
+ state: (): ThemeState => initThemeSettings(),
getters: {
/** naiveUI的主题配置 */
naiveThemeOverrides(state) {
@@ -24,8 +24,16 @@ export const useThemeStore = defineStore('theme-store', {
actions: {
/** 重置theme状态 */
resetThemeStore() {
+ clearThemeSettings();
this.$reset();
},
+ /** 缓存主题配置 */
+ cacheThemeSettings() {
+ const isProd = import.meta.env.PROD;
+ if (isProd) {
+ setThemeSettings(this.$state);
+ }
+ },
/** 设置暗黑模式 */
setDarkMode(darkMode: boolean) {
this.darkMode = darkMode;
diff --git a/src/utils/router/index.ts b/src/utils/router/index.ts
index 72b575bf2..f74f45384 100644
--- a/src/utils/router/index.ts
+++ b/src/utils/router/index.ts
@@ -4,5 +4,4 @@ export * from './cache';
export * from './auth';
export * from './menu';
export * from './breadcrumb';
-export * from './tab';
export * from './regexp';
diff --git a/src/utils/router/tab.ts b/src/utils/router/tab.ts
deleted file mode 100644
index 986cccc59..000000000
--- a/src/utils/router/tab.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { EnumStorageKey } from '@/enum';
-import { setLocal, getLocal } from '../storage';
-
-/** 缓存多页签数据 */
-export function setTabRoutes(data: GlobalTabRoute[]) {
- setLocal(EnumStorageKey['multi-tab-routes'], data);
-}
-
-/** 获取缓存的多页签数据 */
-export function getTabRoutes() {
- const routes: GlobalTabRoute[] = [];
- const data = getLocal(EnumStorageKey['multi-tab-routes']);
- if (data) {
- const defaultTabRoutes = data.map(item => ({
- ...item,
- scrollPosition: {
- left: 0,
- top: 0
- }
- }));
- routes.push(...defaultTabRoutes);
- }
- return routes;
-}
-
-/** 清空多页签数据 */
-export function clearTabRoutes() {
- setTabRoutes([]);
-}