mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2026-04-22 10:14:25 +08:00
Merge 823908afca into b93c2036ac
This commit is contained in:
@@ -40,7 +40,12 @@ const { isFullscreen, toggle } = useFullscreen();
|
|||||||
<div class="h-full flex-y-center justify-end">
|
<div class="h-full flex-y-center justify-end">
|
||||||
<GlobalSearch />
|
<GlobalSearch />
|
||||||
<FullScreen v-if="!appStore.isMobile" :full="isFullscreen" @click="toggle" />
|
<FullScreen v-if="!appStore.isMobile" :full="isFullscreen" @click="toggle" />
|
||||||
<LangSwitch :lang="appStore.locale" :lang-options="appStore.localeOptions" @change-lang="appStore.changeLocale" />
|
<LangSwitch
|
||||||
|
v-if="themeStore.header.multilingual.visible"
|
||||||
|
:lang="appStore.locale"
|
||||||
|
:lang-options="appStore.localeOptions"
|
||||||
|
@change-lang="appStore.changeLocale"
|
||||||
|
/>
|
||||||
<ThemeSchemaSwitch
|
<ThemeSchemaSwitch
|
||||||
:theme-schema="themeStore.themeScheme"
|
:theme-schema="themeStore.themeScheme"
|
||||||
:is-dark="themeStore.darkMode"
|
:is-dark="themeStore.darkMode"
|
||||||
|
|||||||
@@ -127,6 +127,9 @@ const isWrapperScrollMode = computed(() => themeStore.layout.scrollMode === 'wra
|
|||||||
placeholder="SoybeanAdmin"
|
placeholder="SoybeanAdmin"
|
||||||
/>
|
/>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
<SettingItem key="9" :label="$t('theme.header.multilingual.visible')">
|
||||||
|
<NSwitch v-model:value="themeStore.header.multilingual.visible" />
|
||||||
|
</SettingItem>
|
||||||
</TransitionGroup>
|
</TransitionGroup>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,9 @@ const local: App.I18n.Schema = {
|
|||||||
breadcrumb: {
|
breadcrumb: {
|
||||||
visible: 'Breadcrumb Visible',
|
visible: 'Breadcrumb Visible',
|
||||||
showIcon: 'Breadcrumb Icon Visible'
|
showIcon: 'Breadcrumb Icon Visible'
|
||||||
|
},
|
||||||
|
multilingual: {
|
||||||
|
visible: 'Display multilingual button'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tab: {
|
tab: {
|
||||||
|
|||||||
@@ -109,6 +109,9 @@ const local: App.I18n.Schema = {
|
|||||||
breadcrumb: {
|
breadcrumb: {
|
||||||
visible: '显示面包屑',
|
visible: '显示面包屑',
|
||||||
showIcon: '显示面包屑图标'
|
showIcon: '显示面包屑图标'
|
||||||
|
},
|
||||||
|
multilingual: {
|
||||||
|
visible: '显示多语言按钮'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tab: {
|
tab: {
|
||||||
|
|||||||
@@ -2,30 +2,34 @@ import type { GlobalThemeOverrides } from 'naive-ui';
|
|||||||
import { addColorAlpha, getColorPalette, getPaletteColorByNumber, getRgb } from '@sa/color';
|
import { addColorAlpha, getColorPalette, getPaletteColorByNumber, getRgb } from '@sa/color';
|
||||||
import { overrideThemeSettings, themeSettings } from '@/theme/settings';
|
import { overrideThemeSettings, themeSettings } from '@/theme/settings';
|
||||||
import { themeVars } from '@/theme/vars';
|
import { themeVars } from '@/theme/vars';
|
||||||
import { toggleHtmlClass } from '@/utils/common';
|
import { toggleHtmlClass, updateBase } from '@/utils/common';
|
||||||
import { localStg } from '@/utils/storage';
|
import { localStg } from '@/utils/storage';
|
||||||
|
|
||||||
const DARK_CLASS = 'dark';
|
const DARK_CLASS = 'dark';
|
||||||
|
|
||||||
/** Init theme settings */
|
/** Init theme settings */
|
||||||
export function initThemeSettings() {
|
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 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;
|
if (!isProd) return themeSettings;
|
||||||
|
|
||||||
|
const localSettings = localStg.get('themeSettings') || themeSettings;
|
||||||
|
|
||||||
// if it is production mode, the theme settings will be cached in localStorage
|
// 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`
|
// 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;
|
const isOverride = localStg.get('overrideThemeFlag') === BUILD_TIME;
|
||||||
|
|
||||||
if (!isOverride) {
|
if (!isOverride) {
|
||||||
Object.assign(settings, overrideThemeSettings);
|
Object.assign(settings, overrideThemeSettings);
|
||||||
localStg.set('overrideThemeFlag', BUILD_TIME);
|
localStg.set('overrideThemeFlag', BUILD_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
localStg.set('themeSettings', settings);
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ export const themeSettings: App.Theme.ThemeSetting = {
|
|||||||
breadcrumb: {
|
breadcrumb: {
|
||||||
visible: true,
|
visible: true,
|
||||||
showIcon: true
|
showIcon: true
|
||||||
|
},
|
||||||
|
multilingual: {
|
||||||
|
visible: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tab: {
|
tab: {
|
||||||
|
|||||||
10
src/typings/app.d.ts
vendored
10
src/typings/app.d.ts
vendored
@@ -53,6 +53,11 @@ declare namespace App {
|
|||||||
/** Whether to show the breadcrumb icon */
|
/** Whether to show the breadcrumb icon */
|
||||||
showIcon: boolean;
|
showIcon: boolean;
|
||||||
};
|
};
|
||||||
|
/** Multilingual */
|
||||||
|
multilingual: {
|
||||||
|
/** Whether to show the multilingual */
|
||||||
|
visible: boolean;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
/** Tab */
|
/** Tab */
|
||||||
tab: {
|
tab: {
|
||||||
@@ -98,7 +103,7 @@ declare namespace App {
|
|||||||
right: boolean;
|
right: boolean;
|
||||||
};
|
};
|
||||||
/** Watermark */
|
/** Watermark */
|
||||||
watermark?: {
|
watermark: {
|
||||||
/** Whether to show the watermark */
|
/** Whether to show the watermark */
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
/** Watermark text */
|
/** Watermark text */
|
||||||
@@ -363,6 +368,9 @@ declare namespace App {
|
|||||||
visible: string;
|
visible: string;
|
||||||
showIcon: string;
|
showIcon: string;
|
||||||
};
|
};
|
||||||
|
multilingual: {
|
||||||
|
visible: string;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
tab: {
|
tab: {
|
||||||
visible: string;
|
visible: string;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { isObject } from 'lodash-es';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,3 +57,71 @@ export function toggleHtmlClass(className: string) {
|
|||||||
remove
|
remove
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AnyObject = { [key: string]: any };
|
||||||
|
/** Auxiliary type: recursively make all attributes optional */
|
||||||
|
type PartialDeep<T> = {
|
||||||
|
[P in keyof T]?: T[P] extends AnyObject ? PartialDeep<T[P]> : 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<T extends AnyObject>(base: T, updates: PartialDeep<T>): 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;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user