From 38962bf00db508cb12f08b431880986c99f58ea7 Mon Sep 17 00:00:00 2001 From: Azir <2075125282@qq.com> Date: Sun, 1 Dec 2024 20:28:16 +0800 Subject: [PATCH 1/2] feat(projects): multi language buttons support hiding. --- src/layouts/modules/global-header/index.vue | 7 ++++++- src/layouts/modules/theme-drawer/modules/page-fun.vue | 3 +++ src/locales/langs/en-us.ts | 3 +++ src/locales/langs/zh-cn.ts | 3 +++ src/theme/settings.ts | 3 +++ src/typings/app.d.ts | 8 ++++++++ 6 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/layouts/modules/global-header/index.vue b/src/layouts/modules/global-header/index.vue index cd640ba4..c31d67e2 100644 --- a/src/layouts/modules/global-header/index.vue +++ b/src/layouts/modules/global-header/index.vue @@ -40,7 +40,12 @@ const { isFullscreen, toggle } = useFullscreen();
- + themeStore.layout.scrollMode === 'wra + + + diff --git a/src/locales/langs/en-us.ts b/src/locales/langs/en-us.ts index 1f4a38ab..c3ae71c7 100644 --- a/src/locales/langs/en-us.ts +++ b/src/locales/langs/en-us.ts @@ -109,6 +109,9 @@ const local: App.I18n.Schema = { breadcrumb: { visible: 'Breadcrumb Visible', showIcon: 'Breadcrumb Icon Visible' + }, + multilingual: { + visible: 'Display multilingual button' } }, tab: { diff --git a/src/locales/langs/zh-cn.ts b/src/locales/langs/zh-cn.ts index 98dd0214..32c14ceb 100644 --- a/src/locales/langs/zh-cn.ts +++ b/src/locales/langs/zh-cn.ts @@ -109,6 +109,9 @@ const local: App.I18n.Schema = { breadcrumb: { visible: '显示面包屑', showIcon: '显示面包屑图标' + }, + multilingual: { + visible: '显示多语言按钮' } }, tab: { diff --git a/src/theme/settings.ts b/src/theme/settings.ts index c23f1fae..ba877a59 100644 --- a/src/theme/settings.ts +++ b/src/theme/settings.ts @@ -27,6 +27,9 @@ export const themeSettings: App.Theme.ThemeSetting = { breadcrumb: { visible: true, showIcon: true + }, + multilingual: { + visible: true } }, tab: { diff --git a/src/typings/app.d.ts b/src/typings/app.d.ts index 0a560812..72c12314 100644 --- a/src/typings/app.d.ts +++ b/src/typings/app.d.ts @@ -53,6 +53,11 @@ declare namespace App { /** Whether to show the breadcrumb icon */ showIcon: boolean; }; + /** Multilingual */ + multilingual: { + /** Whether to show the multilingual */ + visible: boolean; + }; }; /** Tab */ tab: { @@ -363,6 +368,9 @@ declare namespace App { visible: string; showIcon: string; }; + multilingual: { + visible: string; + }; }; tab: { visible: string; From 823908afcaed06f1f373290733d818d7ba0d9520 Mon Sep 17 00:00:00 2001 From: Azir <2075125282@qq.com> Date: Tue, 3 Dec 2024 16:34:54 +0800 Subject: [PATCH 2/2] feat(projects): theme init supports initialization based on initial values. --- .../modules/theme-drawer/modules/page-fun.vue | 6 +- src/store/modules/theme/shared.ts | 12 ++-- src/typings/app.d.ts | 2 +- src/utils/common.ts | 69 +++++++++++++++++++ 4 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/layouts/modules/theme-drawer/modules/page-fun.vue b/src/layouts/modules/theme-drawer/modules/page-fun.vue index dbebb911..80ae6130 100644 --- a/src/layouts/modules/theme-drawer/modules/page-fun.vue +++ b/src/layouts/modules/theme-drawer/modules/page-fun.vue @@ -69,9 +69,6 @@ const isWrapperScrollMode = computed(() => themeStore.layout.scrollMode === 'wra - - - @@ -130,6 +127,9 @@ const isWrapperScrollMode = computed(() => themeStore.layout.scrollMode === 'wra placeholder="SoybeanAdmin" /> + + + diff --git a/src/store/modules/theme/shared.ts b/src/store/modules/theme/shared.ts index 448c6992..3e63639b 100644 --- a/src/store/modules/theme/shared.ts +++ b/src/store/modules/theme/shared.ts @@ -2,30 +2,34 @@ import type { GlobalThemeOverrides } from 'naive-ui'; import { addColorAlpha, getColorPalette, getPaletteColorByNumber, getRgb } from '@sa/color'; import { overrideThemeSettings, themeSettings } from '@/theme/settings'; import { themeVars } from '@/theme/vars'; -import { toggleHtmlClass } from '@/utils/common'; +import { toggleHtmlClass, updateBase } from '@/utils/common'; import { localStg } from '@/utils/storage'; const DARK_CLASS = 'dark'; /** Init theme settings */ export function initThemeSettings() { - const isProd = import.meta.env.PROD; + // const isProd = import.meta.env.PROD; + const isProd = true; // if it is development mode, the theme settings will not be cached, by update `themeSettings` in `src/theme/settings.ts` to update theme settings if (!isProd) return themeSettings; + const localSettings = localStg.get('themeSettings') || themeSettings; + // if it is production mode, the theme settings will be cached in localStorage // if want to update theme settings when publish new version, please update `overrideThemeSettings` in `src/theme/settings.ts` - const settings = localStg.get('themeSettings') || themeSettings; + const settings = updateBase(themeSettings, localSettings); const isOverride = localStg.get('overrideThemeFlag') === BUILD_TIME; - if (!isOverride) { Object.assign(settings, overrideThemeSettings); localStg.set('overrideThemeFlag', BUILD_TIME); } + localStg.set('themeSettings', settings); + return settings; } diff --git a/src/typings/app.d.ts b/src/typings/app.d.ts index 72c12314..853ec17d 100644 --- a/src/typings/app.d.ts +++ b/src/typings/app.d.ts @@ -103,7 +103,7 @@ declare namespace App { right: boolean; }; /** Watermark */ - watermark?: { + watermark: { /** Whether to show the watermark */ visible: boolean; /** Watermark text */ diff --git a/src/utils/common.ts b/src/utils/common.ts index dc9a368f..0aca7007 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -1,3 +1,4 @@ +import { isObject } from 'lodash-es'; import { $t } from '@/locales'; /** @@ -56,3 +57,71 @@ export function toggleHtmlClass(className: string) { remove }; } + +type AnyObject = { [key: string]: any }; +/** Auxiliary type: recursively make all attributes optional */ +type PartialDeep = { + [P in keyof T]?: T[P] extends AnyObject ? PartialDeep : T[P]; +}; +/** + * Deeply update base objects without adding keys that do not exist in the base. + * + * @example + * const base = { + * a: 1, + * b: { + * c: 2, + * d: 3, + * }, + * e: [1, 2, 3], + * }; + * + * const updates = { + * a: 10, + * b: { + * c: 20, + * e: 30, // Does not exist in base. b, will be ignored + * }, + * f: 40, // Does not exist in base. b, will be ignored + * e: [4, 5], // Array will be replaced + * }; + * + * const updatedBase = updateBase(base, updates); + * + * console.log(updatedBase); + * output: + * { + * a: 10, + * b: { + * c: 20, + * d: 3 + * }, + * e: [4, 5] + * } + * + * @param base - Base object + * @param updates - Update object + * @returns New object, a deep copy of the base object with updates applied + */ +export function updateBase(base: T, updates: PartialDeep): T { + // Deep copy the base object to avoid modifying the original object + const result: AnyObject = Array.isArray(base) ? [...base] : { ...base }; + + for (const key in updates) { + if (Object.hasOwn(base, key)) { + const baseValue = base[key]; + const updateValue = updates[key]; + + if (isObject(baseValue) && isObject(updateValue)) { + // Recursively update nested objects + result[key] = updateBase(baseValue, updateValue); + } else { + // Directly assign updates + result[key] = updateValue; + } + } + // If the key in updates does not exist in base, ignore it + } + + return result as T; +}