mirror of
https://github.com/vbenjs/gf-vben-admin.git
synced 2025-01-23 11:50:20 +08:00
refactor: refactored multi-language modules to support lazy loading and remote loading
This commit is contained in:
parent
f57eb944ed
commit
f6cef1088d
@ -21,3 +21,4 @@ ignore:
|
||||
- dist
|
||||
- .local
|
||||
- .husky
|
||||
- src/locales/lang
|
||||
|
@ -1,5 +1,9 @@
|
||||
## Wip
|
||||
|
||||
### ✨ Refactor
|
||||
|
||||
- 重构多语言模块,支持懒加载及远程加载
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- axios 支持 form-data 格式请求
|
||||
|
@ -28,7 +28,7 @@
|
||||
"@iconify/iconify": "^2.0.0-rc.6",
|
||||
"@vueuse/core": "^4.3.0",
|
||||
"@zxcvbn-ts/core": "^0.2.0",
|
||||
"ant-design-vue": "2.0.0",
|
||||
"ant-design-vue": "2.0.1",
|
||||
"apexcharts": "^3.25.0",
|
||||
"axios": "^0.21.1",
|
||||
"crypto-js": "^4.0.0",
|
||||
@ -106,7 +106,7 @@
|
||||
"vite-plugin-pwa": "^0.5.5",
|
||||
"vite-plugin-style-import": "^0.7.5",
|
||||
"vite-plugin-theme": "^0.4.8",
|
||||
"vite-plugin-windicss": "0.5.4",
|
||||
"vite-plugin-windicss": "0.6.0",
|
||||
"vue-eslint-parser": "^7.5.0",
|
||||
"yargs": "^16.2.0"
|
||||
},
|
||||
|
11
src/App.vue
11
src/App.vue
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<ConfigProvider v-bind="lockEvent" :locale="antConfigLocale">
|
||||
<ConfigProvider v-bind="lockEvent" :locale="getAntdLocale">
|
||||
<AppProvider>
|
||||
<RouterView />
|
||||
</AppProvider>
|
||||
@ -21,9 +21,7 @@
|
||||
components: { ConfigProvider, AppProvider },
|
||||
setup() {
|
||||
// support Multi-language
|
||||
const { antConfigLocale, setLocale } = useLocale();
|
||||
|
||||
setLocale();
|
||||
const { getAntdLocale } = useLocale();
|
||||
|
||||
// Initialize vuex internal system configuration
|
||||
initAppConfigStore();
|
||||
@ -31,10 +29,7 @@
|
||||
// Create a lock screen monitor
|
||||
const lockEvent = useLockPage();
|
||||
|
||||
return {
|
||||
antConfigLocale,
|
||||
lockEvent,
|
||||
};
|
||||
return { getAntdLocale, lockEvent };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -18,7 +18,7 @@
|
||||
</Dropdown>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { LocaleType } from '/@/locales/types';
|
||||
import type { LocaleType } from '/#/config';
|
||||
import type { DropMenu } from '/@/components/Dropdown';
|
||||
|
||||
import { defineComponent, ref, watchEffect, unref, computed } from 'vue';
|
||||
@ -26,7 +26,7 @@
|
||||
import Icon from '/@/components/Icon';
|
||||
|
||||
import { useLocale } from '/@/locales/useLocale';
|
||||
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
|
||||
import { localeList } from '/@/settings/localeSetting';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
|
||||
@ -44,9 +44,7 @@
|
||||
|
||||
const { prefixCls } = useDesign('app-locale-picker');
|
||||
|
||||
const { localeList } = useLocaleSetting();
|
||||
|
||||
const { changeLocale, getLang } = useLocale();
|
||||
const { changeLocale, getLocale } = useLocale();
|
||||
|
||||
const getLangText = computed(() => {
|
||||
const key = selectedKeys.value[0];
|
||||
@ -55,17 +53,17 @@
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
selectedKeys.value = [unref(getLang)];
|
||||
selectedKeys.value = [unref(getLocale)];
|
||||
});
|
||||
|
||||
function toggleLocale(lang: LocaleType | string) {
|
||||
changeLocale(lang as LocaleType);
|
||||
async function toggleLocale(lang: LocaleType | string) {
|
||||
await changeLocale(lang as LocaleType);
|
||||
selectedKeys.value = [lang as string];
|
||||
props.reload && location.reload();
|
||||
}
|
||||
|
||||
function handleMenuEvent(menu: DropMenu) {
|
||||
if (unref(getLang) === menu.event) return;
|
||||
if (unref(getLocale) === menu.event) return;
|
||||
toggleLocale(menu.event as string);
|
||||
}
|
||||
|
||||
|
@ -34,13 +34,13 @@
|
||||
|
||||
const modalFn = useModalContext();
|
||||
|
||||
const { getLang } = useLocale();
|
||||
const { getLocale } = useLocale();
|
||||
|
||||
watchEffect(() => {});
|
||||
|
||||
const getCurrentLang = computed((): 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' => {
|
||||
let lang: Lang;
|
||||
switch (unref(getLang)) {
|
||||
switch (unref(getLocale)) {
|
||||
case 'en':
|
||||
lang = 'en_US';
|
||||
break;
|
||||
|
@ -52,7 +52,6 @@
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
const { t } = useI18n();
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SimpleSubMenu',
|
||||
@ -73,6 +72,7 @@
|
||||
theme: propTypes.oneOf(['dark', 'light']),
|
||||
},
|
||||
setup(props) {
|
||||
const { t } = useI18n();
|
||||
const { prefixCls } = useDesign('simple-menu');
|
||||
|
||||
const getShowMenu = computed(() => {
|
||||
|
@ -1,6 +1,8 @@
|
||||
// token key
|
||||
export const TOKEN_KEY = 'TOKEN__';
|
||||
|
||||
export const LOCALE_KEY = 'LOCALE__';
|
||||
|
||||
// user info key
|
||||
export const USER_INFO_KEY = 'USER__INFO__';
|
||||
|
||||
@ -14,16 +16,10 @@ export const PROJ_CFG_KEY = 'PROJ__CFG__KEY__';
|
||||
export const LOCK_INFO_KEY = 'LOCK__INFO__KEY__';
|
||||
|
||||
// base global local key
|
||||
export const BASE_LOCAL_CACHE_KEY = 'LOCAL__CACHE__KEY__';
|
||||
export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__';
|
||||
|
||||
// base global session key
|
||||
export const BASE_SESSION_CACHE_KEY = 'SESSION__CACHE__KEY__';
|
||||
|
||||
// base global local key
|
||||
export const APP_LOCAL_CACHE_KEY = 'LOCAL__CACHE__KEY__';
|
||||
|
||||
// base global session key
|
||||
export const APP_SESSION_CACHE_KEY = 'SESSION__CACHE__KEY__';
|
||||
export const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__KEY__';
|
||||
|
||||
export enum CacheTypeEnum {
|
||||
SESSION,
|
||||
|
@ -1,26 +1,16 @@
|
||||
import type { ProjectConfig, GlobConfig, GlobEnvConfig } from '/#/config';
|
||||
|
||||
import { getConfigFileName } from '../../../build/getConfigFileName';
|
||||
|
||||
import getProjectSetting from '/@/settings/projectSetting';
|
||||
import type { GlobConfig } from '/#/config';
|
||||
|
||||
import { warn } from '/@/utils/log';
|
||||
import { getGlobEnvConfig, isDevMode } from '/@/utils/env';
|
||||
import { getAppEnvConfig } from '/@/utils/env';
|
||||
|
||||
export const useGlobSetting = (): Readonly<GlobConfig> => {
|
||||
const ENV_NAME = getConfigFileName(import.meta.env);
|
||||
|
||||
const ENV = ((isDevMode()
|
||||
? getGlobEnvConfig()
|
||||
: window[ENV_NAME as any]) as unknown) as GlobEnvConfig;
|
||||
|
||||
const {
|
||||
VITE_GLOB_APP_TITLE,
|
||||
VITE_GLOB_API_URL,
|
||||
VITE_GLOB_APP_SHORT_NAME,
|
||||
VITE_GLOB_API_URL_PREFIX,
|
||||
VITE_GLOB_UPLOAD_URL,
|
||||
} = ENV;
|
||||
} = getAppEnvConfig();
|
||||
|
||||
if (!/[a-zA-Z\_]*/.test(VITE_GLOB_APP_SHORT_NAME)) {
|
||||
warn(
|
||||
@ -38,8 +28,3 @@ export const useGlobSetting = (): Readonly<GlobConfig> => {
|
||||
};
|
||||
return glob as Readonly<GlobConfig>;
|
||||
};
|
||||
|
||||
export const useProjectSetting = (): ProjectConfig => {
|
||||
// TODO computed
|
||||
return getProjectSetting;
|
||||
};
|
||||
|
@ -1,38 +0,0 @@
|
||||
import type { LocaleSetting } from '/#/config';
|
||||
|
||||
import { computed, unref } from 'vue';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
|
||||
import getProjectSetting from '/@/settings/projectSetting';
|
||||
import { localeList } from '/@/locales/constant';
|
||||
|
||||
// Get locale configuration
|
||||
const getLocale = computed(() => appStore.getProjectConfig.locale || getProjectSetting.locale);
|
||||
|
||||
// get current language
|
||||
const getLang = computed(() => unref(getLocale).lang);
|
||||
|
||||
// get Available Locales
|
||||
const getAvailableLocales = computed((): string[] => unref(getLocale).availableLocales);
|
||||
|
||||
// get Fallback Locales
|
||||
const getFallbackLocale = computed((): string => unref(getLocale).fallback);
|
||||
|
||||
const getShowLocale = computed(() => unref(getLocale).show);
|
||||
|
||||
// Set locale configuration
|
||||
function setLocale(locale: Partial<LocaleSetting>): void {
|
||||
appStore.commitProjectConfigState({ locale });
|
||||
}
|
||||
|
||||
export function useLocaleSetting() {
|
||||
return {
|
||||
getLocale,
|
||||
getLang,
|
||||
localeList,
|
||||
setLocale,
|
||||
getShowLocale,
|
||||
getAvailableLocales,
|
||||
getFallbackLocale,
|
||||
};
|
||||
}
|
@ -40,6 +40,7 @@ export function useI18n(
|
||||
|
||||
const tFn: I18nGlobalTranslation = (key: string, ...arg: any[]) => {
|
||||
if (!key) return '';
|
||||
if (!key.includes('.')) return key;
|
||||
return t(getKey(namespace, key), ...(arg as I18nTranslationRestParameters));
|
||||
};
|
||||
return {
|
||||
|
@ -58,7 +58,7 @@ export function usePermission() {
|
||||
return def;
|
||||
}
|
||||
if (!isArray(value)) {
|
||||
return userStore.getRoleListState.includes(value as RoleEnum);
|
||||
return userStore.getRoleListState?.includes(value as RoleEnum);
|
||||
}
|
||||
return (intersection(value, userStore.getRoleListState) as RoleEnum[]).length > 0;
|
||||
}
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
import { defineComponent, ref, toRaw, watchEffect } from 'vue';
|
||||
import { Breadcrumb } from 'ant-design-vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import { useRouter } from 'vue-router';
|
||||
import { filter } from '/@/utils/helper/treeHelper';
|
||||
@ -33,6 +32,7 @@
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useGo } from '/@/hooks/web/usePage';
|
||||
import { isString } from '/@/utils/is';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutBreadcrumb',
|
||||
|
@ -17,7 +17,7 @@
|
||||
icon="ion:document-text-outline"
|
||||
v-if="getShowDoc"
|
||||
/>
|
||||
<MenuDivider />
|
||||
<MenuDivider v-if="getShowDoc" />
|
||||
<MenuItem
|
||||
key="lock"
|
||||
:text="t('layout.header.tooltipLock')"
|
||||
|
@ -42,7 +42,7 @@
|
||||
<FullScreen v-if="getShowFullScreen" :class="`${prefixCls}-action__item fullscreen-item`" />
|
||||
|
||||
<AppLocalePicker
|
||||
v-if="getShowLocale"
|
||||
v-if="getShowLocalePicker"
|
||||
:reload="true"
|
||||
:showText="false"
|
||||
:class="`${prefixCls}-action__item`"
|
||||
@ -69,7 +69,6 @@
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
|
||||
|
||||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
||||
import { SettingButtonPositionEnum } from '/@/enums/appEnum';
|
||||
@ -80,6 +79,7 @@
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
import { useLocale } from '/@/locales/useLocale';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutHeader',
|
||||
@ -112,7 +112,6 @@
|
||||
getMenuWidth,
|
||||
getIsMixSidebar,
|
||||
} = useMenuSetting();
|
||||
const { getShowLocale } = useLocaleSetting();
|
||||
const {
|
||||
getUseErrorHandle,
|
||||
getShowSettingButton,
|
||||
@ -130,6 +129,8 @@
|
||||
getShowHeader,
|
||||
} = useHeaderSetting();
|
||||
|
||||
const { getShowLocalePicker } = useLocale();
|
||||
|
||||
const { getIsMobile } = useAppInject();
|
||||
|
||||
const getHeaderClass = computed(() => {
|
||||
@ -185,7 +186,7 @@
|
||||
getSplit,
|
||||
getMenuMode,
|
||||
getShowTopMenu,
|
||||
getShowLocale,
|
||||
getShowLocalePicker,
|
||||
getShowFullScreen,
|
||||
getShowNotice,
|
||||
getUseLockPage,
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { toRaw, ref, nextTick } from 'vue';
|
||||
import { RouteLocationNormalized } from 'vue-router';
|
||||
import { useProjectSetting } from '/@/hooks/setting';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { useSortable } from '/@/hooks/web/useSortable';
|
||||
import router from '/@/router';
|
||||
import { tabStore } from '/@/store/modules/tab';
|
||||
import { isNullAndUnDef } from '/@/utils/is';
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
|
||||
export function initAffixTabs(): string[] {
|
||||
const affixList = ref<RouteLocationNormalized[]>([]);
|
||||
@ -47,7 +47,7 @@ export function initAffixTabs(): string[] {
|
||||
}
|
||||
|
||||
export function useTabsDrag(affixTextList: string[]) {
|
||||
const { multiTabsSetting } = useProjectSetting();
|
||||
const { multiTabsSetting } = projectSetting;
|
||||
|
||||
const { prefixCls } = useDesign('multiple-tabs');
|
||||
nextTick(() => {
|
||||
|
@ -1,13 +0,0 @@
|
||||
import type { DropMenu } from '/@/components/Dropdown';
|
||||
|
||||
// locale list
|
||||
export const localeList: DropMenu[] = [
|
||||
{
|
||||
text: '简体中文',
|
||||
event: 'zh_CN',
|
||||
},
|
||||
{
|
||||
text: 'English',
|
||||
event: 'en',
|
||||
},
|
||||
];
|
@ -1,4 +0,0 @@
|
||||
import { genMessage } from './helper';
|
||||
const modules = import.meta.globEager('./lang/**/*.ts');
|
||||
|
||||
export default genMessage(modules);
|
@ -4,16 +4,21 @@ export function genMessage(langs: Record<string, Record<string, any>>, prefix =
|
||||
const obj: Recordable = {};
|
||||
|
||||
Object.keys(langs).forEach((key) => {
|
||||
const mod = langs[key].default;
|
||||
let k = key.replace(`./${prefix}/`, '').replace(/^\.\//, '');
|
||||
const lastIndex = k.lastIndexOf('.');
|
||||
k = k.substring(0, lastIndex);
|
||||
const keyList = k.split('/');
|
||||
const lang = keyList.shift();
|
||||
const langFileModule = langs[key].default;
|
||||
let fileName = key.replace(`./${prefix}/`, '').replace(/^\.\//, '');
|
||||
const lastIndex = fileName.lastIndexOf('.');
|
||||
fileName = fileName.substring(0, lastIndex);
|
||||
const keyList = fileName.split('/');
|
||||
const moduleName = keyList.shift();
|
||||
const objKey = keyList.join('.');
|
||||
if (lang) {
|
||||
set(obj, lang, obj[lang] || {});
|
||||
set(obj[lang], objKey, mod);
|
||||
|
||||
if (moduleName) {
|
||||
if (objKey) {
|
||||
set(obj, moduleName, obj[moduleName] || {});
|
||||
set(obj[moduleName], objKey, langFileModule);
|
||||
} else {
|
||||
set(obj, moduleName, langFileModule || {});
|
||||
}
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
|
13
src/locales/lang/en.ts
Normal file
13
src/locales/lang/en.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { genMessage } from '../helper';
|
||||
const modules = import.meta.globEager('./en/**/*.ts');
|
||||
import antdLocale from 'ant-design-vue/es/locale/en_US';
|
||||
import momentLocale from 'moment/dist/locale/eu';
|
||||
|
||||
export default {
|
||||
message: {
|
||||
...genMessage(modules, 'en'),
|
||||
antdLocale,
|
||||
},
|
||||
momentLocale,
|
||||
momentLocaleName: 'eu',
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
export default {
|
||||
redo: 'Refresh current',
|
||||
reload: 'Refresh current',
|
||||
close: 'Close current',
|
||||
closeLeft: 'Close Left',
|
||||
closeRight: 'Close Right',
|
||||
|
@ -25,4 +25,6 @@ export default {
|
||||
list: 'List page',
|
||||
listCard: 'Card list',
|
||||
basic: 'Basic list',
|
||||
listBasic: 'Basic list',
|
||||
listSearch: 'Search list',
|
||||
};
|
||||
|
13
src/locales/lang/zh_CN.ts
Normal file
13
src/locales/lang/zh_CN.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { genMessage } from '../helper';
|
||||
const modules = import.meta.globEager('./zh_CN/**/*.ts');
|
||||
import antdLocale from 'ant-design-vue/es/locale/zh_CN';
|
||||
import momentLocale from 'moment/dist/locale/zh-cn';
|
||||
|
||||
export default {
|
||||
message: {
|
||||
...genMessage(modules, 'zh_CN'),
|
||||
antdLocale,
|
||||
},
|
||||
momentLocale,
|
||||
momentLocaleName: 'zh-cn',
|
||||
};
|
@ -3,27 +3,36 @@ import type { I18n, I18nOptions } from 'vue-i18n';
|
||||
|
||||
import { createI18n } from 'vue-i18n';
|
||||
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
import { localeStore } from '/@/store/modules/locale';
|
||||
import { localeSetting } from '/@/settings/localeSetting';
|
||||
|
||||
import messages from './getMessage';
|
||||
const { fallback, availableLocales } = localeSetting;
|
||||
|
||||
const { lang, availableLocales, fallback } = projectSetting?.locale;
|
||||
export let i18n: ReturnType<typeof createI18n>;
|
||||
|
||||
const localeData: I18nOptions = {
|
||||
legacy: false,
|
||||
locale: lang,
|
||||
fallbackLocale: fallback,
|
||||
messages,
|
||||
availableLocales: availableLocales,
|
||||
sync: true, //If you don’t want to inherit locale from global scope, you need to set sync of i18n component option to false.
|
||||
silentTranslationWarn: true, // true - warning off
|
||||
missingWarn: false,
|
||||
silentFallbackWarn: true,
|
||||
};
|
||||
export let i18n: I18n;
|
||||
async function createI18nOptions(): Promise<I18nOptions> {
|
||||
const locale = localeStore.getLocale;
|
||||
const defaultLocal = await import(`./lang/${locale}.ts`);
|
||||
const message = defaultLocal.default?.message;
|
||||
|
||||
return {
|
||||
legacy: false,
|
||||
locale,
|
||||
fallbackLocale: fallback,
|
||||
messages: {
|
||||
[locale]: message,
|
||||
},
|
||||
availableLocales: availableLocales,
|
||||
sync: true, //If you don’t want to inherit locale from global scope, you need to set sync of i18n component option to false.
|
||||
silentTranslationWarn: true, // true - warning off
|
||||
missingWarn: false,
|
||||
silentFallbackWarn: true,
|
||||
};
|
||||
}
|
||||
|
||||
// setup i18n instance with glob
|
||||
export function setupI18n(app: App) {
|
||||
i18n = createI18n(localeData) as I18n;
|
||||
export async function setupI18n(app: App) {
|
||||
const options = await createI18nOptions();
|
||||
i18n = createI18n(options) as I18n;
|
||||
app.use(i18n);
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja' | 'ko';
|
@ -1,64 +1,73 @@
|
||||
/**
|
||||
* Multi-language related operations
|
||||
*/
|
||||
import type { LocaleType } from '/@/locales/types';
|
||||
import type { Ref } from 'vue';
|
||||
import type { LocaleType } from '/#/config';
|
||||
|
||||
import { unref, ref } from 'vue';
|
||||
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
|
||||
import { ref } from 'vue';
|
||||
import moment from 'moment';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { i18n } from './setupI18n';
|
||||
import { localeStore } from '/@/store/modules/locale';
|
||||
import { unref } from 'vue';
|
||||
|
||||
import 'moment/dist/locale/zh-cn';
|
||||
interface LangModule {
|
||||
message: Recordable;
|
||||
momentLocale: Recordable;
|
||||
momentLocaleName: string;
|
||||
}
|
||||
|
||||
const antConfigLocaleRef = ref<any>(null);
|
||||
const antConfigLocale = ref<Nullable<Recordable>>(null);
|
||||
|
||||
const loadLocalePool: LocaleType[] = [];
|
||||
|
||||
function setI18nLanguage(locale: LocaleType) {
|
||||
if (i18n.mode === 'legacy') {
|
||||
i18n.global.locale = locale;
|
||||
} else {
|
||||
(i18n.global.locale as any).value = locale;
|
||||
}
|
||||
localeStore.setLocaleInfo({ locale });
|
||||
document.querySelector('html')?.setAttribute('lang', locale);
|
||||
}
|
||||
|
||||
export function useLocale() {
|
||||
const { getLang, getLocale, setLocale: setLocalSetting } = useLocaleSetting();
|
||||
const getLocale = computed(() => localeStore.getLocale);
|
||||
const getShowLocalePicker = computed(() => localeStore.getShowPicker);
|
||||
|
||||
const getAntdLocale = computed(() => {
|
||||
return i18n.global.getLocaleMessage(unref(getLocale))?.antdLocale;
|
||||
});
|
||||
|
||||
// Switching the language will change the locale of useI18n
|
||||
// And submit to configuration modification
|
||||
function changeLocale(lang: LocaleType): void {
|
||||
if (i18n.mode === 'legacy') {
|
||||
i18n.global.locale = lang;
|
||||
} else {
|
||||
((i18n.global.locale as unknown) as Ref<string>).value = lang;
|
||||
async function changeLocale(locale: LocaleType) {
|
||||
const globalI18n = i18n.global;
|
||||
const currentLocale = unref(globalI18n.locale);
|
||||
if (currentLocale === locale) return locale;
|
||||
|
||||
if (loadLocalePool.includes(locale)) {
|
||||
setI18nLanguage(locale);
|
||||
return locale;
|
||||
}
|
||||
setLocalSetting({ lang });
|
||||
// i18n.global.setLocaleMessage(locale, messages);
|
||||
const langModule = ((await import(`./lang/${locale}.ts`)) as any).default as LangModule;
|
||||
if (!langModule) return;
|
||||
|
||||
switch (lang) {
|
||||
// Simplified Chinese
|
||||
case 'zh_CN':
|
||||
import('ant-design-vue/es/locale/zh_CN').then((locale) => {
|
||||
antConfigLocaleRef.value = locale.default;
|
||||
});
|
||||
const { message, momentLocale, momentLocaleName } = langModule;
|
||||
|
||||
break;
|
||||
// English
|
||||
case 'en':
|
||||
import('ant-design-vue/es/locale/en_US').then((locale) => {
|
||||
antConfigLocaleRef.value = locale.default;
|
||||
});
|
||||
break;
|
||||
globalI18n.setLocaleMessage(locale, message);
|
||||
moment.updateLocale(momentLocaleName, momentLocale);
|
||||
loadLocalePool.push(locale);
|
||||
|
||||
// other
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// initialization
|
||||
function setLocale() {
|
||||
const lang = unref(getLang);
|
||||
lang && changeLocale(lang);
|
||||
setI18nLanguage(locale);
|
||||
return locale;
|
||||
}
|
||||
|
||||
return {
|
||||
setLocale,
|
||||
getLocale,
|
||||
getLang,
|
||||
getShowLocalePicker,
|
||||
changeLocale,
|
||||
antConfigLocale: antConfigLocaleRef,
|
||||
antConfigLocale,
|
||||
getAntdLocale,
|
||||
};
|
||||
}
|
||||
|
@ -3,9 +3,9 @@
|
||||
*/
|
||||
|
||||
import { errorStore, ErrorInfo } from '/@/store/modules/error';
|
||||
import { useProjectSetting } from '/@/hooks/setting';
|
||||
import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
|
||||
import { App } from 'vue';
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
|
||||
/**
|
||||
* Handling error stack information
|
||||
@ -160,7 +160,7 @@ function registerResourceErrorHandler() {
|
||||
* @param app
|
||||
*/
|
||||
export function setupErrorHandle(app: App) {
|
||||
const { useErrorHandle } = useProjectSetting();
|
||||
const { useErrorHandle } = projectSetting;
|
||||
if (!useErrorHandle) return;
|
||||
// Vue exception monitoring;
|
||||
app.config.errorHandler = vueErrorHandler;
|
||||
|
@ -2,25 +2,22 @@
|
||||
* Application configuration
|
||||
*/
|
||||
|
||||
import type { ProjectConfig } from '/#/config';
|
||||
|
||||
import { PROJ_CFG_KEY } from '/@/enums/cacheEnum';
|
||||
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
import { Persistent } from '/@/utils/cache/persistent';
|
||||
|
||||
import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground';
|
||||
import { updateColorWeak } from '/@/logics/theme/updateColorWeak';
|
||||
import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
|
||||
import { changeTheme } from '/@/logics/theme';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { deepMerge } from '/@/utils';
|
||||
import { localeStore } from '/@/store/modules/locale';
|
||||
|
||||
import { getCommonStoragePrefix, getStorageShortName } from '/@/utils/env';
|
||||
|
||||
import { primaryColor } from '../../build/config/themeConfig';
|
||||
|
||||
// Initial project configuration
|
||||
export function initAppConfigStore() {
|
||||
let projCfg: ProjectConfig = Persistent.getLocal(PROJ_CFG_KEY) as ProjectConfig;
|
||||
projCfg = deepMerge(projectSetting, projCfg || {});
|
||||
try {
|
||||
const {
|
||||
colorWeak,
|
||||
@ -28,7 +25,7 @@ export function initAppConfigStore() {
|
||||
themeColor,
|
||||
headerSetting: { bgColor: headerBgColor } = {},
|
||||
menuSetting: { bgColor } = {},
|
||||
} = projCfg;
|
||||
} = projectSetting;
|
||||
if (themeColor && themeColor !== primaryColor) {
|
||||
changeTheme(themeColor);
|
||||
}
|
||||
@ -39,5 +36,27 @@ export function initAppConfigStore() {
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
appStore.commitProjectConfigState(projCfg);
|
||||
appStore.commitProjectConfigState(projectSetting);
|
||||
localeStore.initLocale();
|
||||
|
||||
setTimeout(() => {
|
||||
clearObsoleteStorage();
|
||||
}, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* As the version continues to iterate, there will be more and more cache keys stored in localStorage.
|
||||
* This method is used to delete useless keys
|
||||
*/
|
||||
export function clearObsoleteStorage() {
|
||||
const commonPrefix = getCommonStoragePrefix();
|
||||
const shortPrefix = getStorageShortName();
|
||||
|
||||
[localStorage, sessionStorage].forEach((item: Storage) => {
|
||||
Object.keys(item).forEach((key) => {
|
||||
if (key && key.startsWith(commonPrefix) && !key.startsWith(shortPrefix)) {
|
||||
item.removeItem(key);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
45
src/main.ts
45
src/main.ts
@ -14,33 +14,36 @@ import { registerGlobComp } from '/@/components/registerGlobComp';
|
||||
|
||||
import { isDevMode } from '/@/utils/env';
|
||||
|
||||
const app = createApp(App);
|
||||
(async () => {
|
||||
const app = createApp(App);
|
||||
|
||||
// Register global components
|
||||
registerGlobComp(app);
|
||||
// Register global components
|
||||
registerGlobComp(app);
|
||||
|
||||
// Multilingual configuration
|
||||
setupI18n(app);
|
||||
// Configure routing
|
||||
setupRouter(app);
|
||||
|
||||
// Configure routing
|
||||
setupRouter(app);
|
||||
// Configure vuex store
|
||||
setupStore(app);
|
||||
|
||||
// Configure vuex store
|
||||
setupStore(app);
|
||||
// Register global directive
|
||||
setupGlobDirectives(app);
|
||||
|
||||
// Register global directive
|
||||
setupGlobDirectives(app);
|
||||
// Configure global error handling
|
||||
setupErrorHandle(app);
|
||||
|
||||
// Configure global error handling
|
||||
setupErrorHandle(app);
|
||||
await Promise.all([
|
||||
// Multilingual configuration
|
||||
setupI18n(app),
|
||||
// Mount when the route is ready
|
||||
router.isReady(),
|
||||
]);
|
||||
|
||||
// Mount when the route is ready
|
||||
router.isReady().then(() => {
|
||||
app.mount('#app', true);
|
||||
});
|
||||
|
||||
// The development environment takes effect
|
||||
if (isDevMode()) {
|
||||
app.config.performance = true;
|
||||
window.__APP__ = app;
|
||||
}
|
||||
// The development environment takes effect
|
||||
if (isDevMode()) {
|
||||
app.config.performance = true;
|
||||
window.__APP__ = app;
|
||||
}
|
||||
})();
|
||||
|
@ -1,13 +1,13 @@
|
||||
import type { Router } from 'vue-router';
|
||||
import { useProjectSetting } from '/@/hooks/setting';
|
||||
import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel';
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
|
||||
/**
|
||||
* The interface used to close the current page to complete the request when the route is switched
|
||||
* @param router
|
||||
*/
|
||||
export function createHttpGuard(router: Router) {
|
||||
const { removeAllHttpPending } = useProjectSetting();
|
||||
const { removeAllHttpPending } = projectSetting;
|
||||
let axiosCanceler: Nullable<AxiosCanceler>;
|
||||
if (removeAllHttpPending) {
|
||||
axiosCanceler = new AxiosCanceler();
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type { Router } from 'vue-router';
|
||||
import { useProjectSetting } from '/@/hooks/setting';
|
||||
import { Modal, notification } from 'ant-design-vue';
|
||||
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
import { warn } from '/@/utils/log';
|
||||
|
||||
/**
|
||||
@ -9,7 +8,7 @@ import { warn } from '/@/utils/log';
|
||||
* @param router
|
||||
*/
|
||||
export function createMessageGuard(router: Router) {
|
||||
const { closeMessageOnSwitch } = useProjectSetting();
|
||||
const { closeMessageOnSwitch } = projectSetting;
|
||||
|
||||
router.beforeEach(async () => {
|
||||
try {
|
||||
|
@ -4,9 +4,11 @@ import type { App } from 'vue';
|
||||
import { createRouter, createWebHashHistory } from 'vue-router';
|
||||
|
||||
import { createGuard } from './guard';
|
||||
import { basicRoutes } from './routes';
|
||||
import { basicRoutes, LoginRoute } from './routes';
|
||||
import { REDIRECT_NAME } from './constant';
|
||||
|
||||
const WHITE_NAME_LIST = [LoginRoute.name, REDIRECT_NAME];
|
||||
|
||||
// app router
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
@ -17,10 +19,9 @@ const router = createRouter({
|
||||
|
||||
// reset router
|
||||
export function resetRouter() {
|
||||
const resetWhiteNameList = ['Login', REDIRECT_NAME];
|
||||
router.getRoutes().forEach((route) => {
|
||||
const { name } = route;
|
||||
if (name && !resetWhiteNameList.includes(name as string)) {
|
||||
if (name && !WHITE_NAME_LIST.includes(name as string)) {
|
||||
router.hasRoute(name) && router.removeRoute(name);
|
||||
}
|
||||
});
|
||||
|
@ -1,3 +1,8 @@
|
||||
/**
|
||||
The routing of this file will not show the layout.
|
||||
It is an independent new page.
|
||||
the contents of the file still need to log in to access
|
||||
*/
|
||||
import type { AppRouteModule } from '/@/router/types';
|
||||
|
||||
// test
|
||||
|
29
src/settings/localeSetting.ts
Normal file
29
src/settings/localeSetting.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import type { DropMenu } from '/@/components/Dropdown/src/types';
|
||||
import type { LocaleSetting, LocaleType } from '/#/config';
|
||||
|
||||
export const LOCALE: { [key: string]: LocaleType } = {
|
||||
ZH_CN: 'zh_CN',
|
||||
EN_US: 'en',
|
||||
};
|
||||
|
||||
export const localeSetting: LocaleSetting = {
|
||||
showPicker: true,
|
||||
// Locale
|
||||
locale: LOCALE.ZH_CN,
|
||||
// Default locale
|
||||
fallback: LOCALE.ZH_CN,
|
||||
// available Locales
|
||||
availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US],
|
||||
};
|
||||
|
||||
// locale list
|
||||
export const localeList: DropMenu[] = [
|
||||
{
|
||||
text: '简体中文',
|
||||
event: LOCALE.ZH_CN,
|
||||
},
|
||||
{
|
||||
text: 'English',
|
||||
event: LOCALE.EN_US,
|
||||
},
|
||||
];
|
@ -1,5 +1,4 @@
|
||||
import type { ProjectConfig } from '/#/config';
|
||||
|
||||
import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum';
|
||||
import { CacheTypeEnum } from '/@/enums/cacheEnum';
|
||||
import {
|
||||
@ -26,8 +25,8 @@ const setting: ProjectConfig = {
|
||||
permissionCacheType: CacheTypeEnum.LOCAL,
|
||||
|
||||
// color
|
||||
// TODO Theme color
|
||||
themeColor: primaryColor,
|
||||
|
||||
// TODO dark theme
|
||||
themeMode: themeMode,
|
||||
|
||||
@ -49,17 +48,6 @@ const setting: ProjectConfig = {
|
||||
// Whether to show footer
|
||||
showFooter: false,
|
||||
|
||||
// locale setting
|
||||
locale: {
|
||||
show: true,
|
||||
// Locale
|
||||
lang: 'zh_CN',
|
||||
// Default locale
|
||||
fallback: 'zh_CN',
|
||||
// available Locales
|
||||
availableLocales: ['zh_CN', 'en'],
|
||||
},
|
||||
|
||||
// Header configuration
|
||||
headerSetting: {
|
||||
// header bg color
|
||||
|
@ -4,7 +4,7 @@ import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-dec
|
||||
|
||||
import { formatToDateTime } from '/@/utils/dateUtil';
|
||||
import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
|
||||
import { useProjectSetting } from '/@/hooks/setting';
|
||||
import projectSetting from '/@/settings/projectSetting';
|
||||
|
||||
export interface ErrorInfo {
|
||||
type: ErrorTypeEnum;
|
||||
@ -57,7 +57,7 @@ class Error extends VuexModule implements ErrorState {
|
||||
|
||||
@Action
|
||||
setupErrorHandle(error: any) {
|
||||
const { useErrorHandle } = useProjectSetting();
|
||||
const { useErrorHandle } = projectSetting;
|
||||
if (!useErrorHandle) return;
|
||||
|
||||
const errInfo: Partial<ErrorInfo> = {
|
||||
|
44
src/store/modules/locale.ts
Normal file
44
src/store/modules/locale.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import store from '/@/store';
|
||||
|
||||
import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-decorators';
|
||||
|
||||
import { LOCALE_KEY } from '/@/enums/cacheEnum';
|
||||
|
||||
import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
|
||||
import { LocaleSetting, LocaleType } from '/#/config';
|
||||
import { createLocalStorage } from '/@/utils/cache';
|
||||
import { localeSetting } from '/@/settings/localeSetting';
|
||||
|
||||
const ls = createLocalStorage();
|
||||
|
||||
const lsSetting = (ls.get(LOCALE_KEY) || localeSetting) as LocaleSetting;
|
||||
|
||||
const NAME = 'locale';
|
||||
hotModuleUnregisterModule(NAME);
|
||||
@Module({ dynamic: true, namespaced: true, store, name: NAME })
|
||||
class Locale extends VuexModule {
|
||||
private info: LocaleSetting = lsSetting;
|
||||
|
||||
get getShowPicker(): boolean {
|
||||
return !!this.info?.showPicker;
|
||||
}
|
||||
|
||||
get getLocale(): LocaleType {
|
||||
return this.info?.locale;
|
||||
}
|
||||
|
||||
@Mutation
|
||||
setLocaleInfo(info: Partial<LocaleSetting>): void {
|
||||
this.info = { ...this.info, ...info };
|
||||
ls.set(LOCALE_KEY, this.info);
|
||||
}
|
||||
|
||||
@Action
|
||||
initLocale(): void {
|
||||
this.setLocaleInfo({
|
||||
...localeSetting,
|
||||
...this.info,
|
||||
});
|
||||
}
|
||||
}
|
||||
export const localeStore = getModule<Locale>(Locale);
|
@ -88,7 +88,7 @@ class Permission extends VuexModule {
|
||||
let routes: AppRouteRecordRaw[] = [];
|
||||
const roleList = toRaw(userStore.getRoleListState);
|
||||
|
||||
const { permissionMode } = appStore.getProjectConfig;
|
||||
const { permissionMode = PermissionModeEnum.ROLE } = appStore.getProjectConfig;
|
||||
|
||||
// role permissions
|
||||
if (permissionMode === PermissionModeEnum.ROLE) {
|
||||
|
12
src/utils/cache/index.ts
vendored
12
src/utils/cache/index.ts
vendored
@ -11,7 +11,6 @@ const createOptions = (storage: Storage, options: Options = {}): Options => {
|
||||
hasEncrypt: enableStorageEncryption,
|
||||
storage,
|
||||
prefixKey: getStorageShortName(),
|
||||
|
||||
...options,
|
||||
};
|
||||
};
|
||||
@ -22,11 +21,12 @@ export const createStorage = (storage: Storage = sessionStorage, options: Option
|
||||
return create(createOptions(storage, options));
|
||||
};
|
||||
|
||||
export const createPersistentStorage = (
|
||||
storage: Storage = sessionStorage,
|
||||
options: Options = {}
|
||||
) => {
|
||||
return createStorage(storage, { ...options, timeout: DEFAULT_CACHE_TIME });
|
||||
export const createSessionStorage = (options: Options = {}) => {
|
||||
return createStorage(sessionStorage, { ...options, timeout: DEFAULT_CACHE_TIME });
|
||||
};
|
||||
|
||||
export const createLocalStorage = (options: Options = {}) => {
|
||||
return createStorage(localStorage, { ...options, timeout: DEFAULT_CACHE_TIME });
|
||||
};
|
||||
|
||||
export default WebStorage;
|
||||
|
4
src/utils/cache/memory.ts
vendored
4
src/utils/cache/memory.ts
vendored
@ -57,7 +57,7 @@ export class Memory<T = any, V = any> {
|
||||
if (!expires) {
|
||||
return value;
|
||||
}
|
||||
item.time = new Date().getTime() + this.alive * 1000;
|
||||
item.time = new Date().getTime() + this.alive;
|
||||
item.timeoutId = setTimeout(() => {
|
||||
this.remove(key);
|
||||
}, expires);
|
||||
@ -80,7 +80,7 @@ export class Memory<T = any, V = any> {
|
||||
const item = cache[k];
|
||||
if (item && item.time) {
|
||||
const now = new Date().getTime();
|
||||
const expire = now + item.time * 1000;
|
||||
const expire = item.time;
|
||||
if (expire > now) {
|
||||
this.set(k, item.value, expire);
|
||||
}
|
||||
|
12
src/utils/cache/persistent.ts
vendored
12
src/utils/cache/persistent.ts
vendored
@ -1,4 +1,4 @@
|
||||
import { createPersistentStorage } from '/@/utils/cache';
|
||||
import { createLocalStorage, createSessionStorage } from '/@/utils/cache';
|
||||
import { Memory } from './memory';
|
||||
import {
|
||||
TOKEN_KEY,
|
||||
@ -28,19 +28,19 @@ export type BasicKeys = keyof BasicStore;
|
||||
type LocalKeys = keyof LocalStore;
|
||||
type SessionKeys = keyof SessionStore;
|
||||
|
||||
const ls = createPersistentStorage(localStorage);
|
||||
const ss = createPersistentStorage(sessionStorage);
|
||||
const ls = createLocalStorage();
|
||||
const ss = createSessionStorage();
|
||||
|
||||
const localMemory = new Memory(DEFAULT_CACHE_TIME);
|
||||
const sessionMemory = new Memory(DEFAULT_CACHE_TIME);
|
||||
|
||||
function initMemory() {
|
||||
function initPersistentMemory() {
|
||||
const localCache = ls.get(APP_LOCAL_CACHE_KEY);
|
||||
const sessionCache = ls.get(APP_SESSION_CACHE_KEY);
|
||||
localCache && localMemory.resetCache(localCache);
|
||||
sessionCache && sessionMemory.resetCache(sessionCache);
|
||||
}
|
||||
initMemory();
|
||||
|
||||
export class Persistent {
|
||||
static getLocal<T>(key: LocalKeys) {
|
||||
return localMemory.get(key)?.value as Nullable<T>;
|
||||
@ -106,4 +106,4 @@ function storageChange(e: any) {
|
||||
|
||||
window.addEventListener('storage', storageChange);
|
||||
|
||||
export default {};
|
||||
initPersistentMemory();
|
||||
|
@ -2,19 +2,26 @@ import type { GlobEnvConfig } from '/#/config';
|
||||
|
||||
import { useGlobSetting } from '/@/hooks/setting';
|
||||
import pkg from '../../package.json';
|
||||
import { getConfigFileName } from '../../build/getConfigFileName';
|
||||
|
||||
/**
|
||||
* Get the global configuration (the configuration will be extracted independently when packaging)
|
||||
*/
|
||||
export function getGlobEnvConfig(): GlobEnvConfig {
|
||||
const env = import.meta.env;
|
||||
return (env as unknown) as GlobEnvConfig;
|
||||
export function getCommonStoragePrefix() {
|
||||
const globSetting = useGlobSetting();
|
||||
return `${globSetting.shortName}__${getEnv()}`.toUpperCase();
|
||||
}
|
||||
|
||||
// Generate cache key according to version
|
||||
export function getStorageShortName() {
|
||||
const globSetting = useGlobSetting();
|
||||
return `${globSetting.shortName}__${getEnv()}${`__${pkg.version}`}__`.toUpperCase();
|
||||
return `${getCommonStoragePrefix()}${`__${pkg.version}`}__`.toUpperCase();
|
||||
}
|
||||
|
||||
export function getAppEnvConfig() {
|
||||
const ENV_NAME = getConfigFileName(import.meta.env);
|
||||
|
||||
const ENV = ((isDevMode()
|
||||
? // Get the global configuration (the configuration will be extracted independently when packaging)
|
||||
((import.meta.env as unknown) as GlobEnvConfig)
|
||||
: window[ENV_NAME as any]) as unknown) as GlobEnvConfig;
|
||||
return ENV;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { dateUtil } from '/@/utils/dateUtil';
|
||||
import { reactive, toRefs } from 'vue';
|
||||
import { tryOnMounted, tryOnUnmounted } from '/@/utils/helper/vueHelper';
|
||||
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
|
||||
import { localeStore } from '/@/store/modules/locale';
|
||||
|
||||
export function useNow(immediate = true) {
|
||||
const { getLang } = useLocaleSetting();
|
||||
const localData = dateUtil.localeData(getLang.value);
|
||||
const localData = dateUtil.localeData(localeStore.getLocale);
|
||||
let timer: IntervalHandle;
|
||||
|
||||
const state = reactive({
|
||||
|
@ -53,9 +53,10 @@
|
||||
import MobileForm from './MobileForm.vue';
|
||||
import QrCodeForm from './QrCodeForm.vue';
|
||||
|
||||
import { useGlobSetting, useProjectSetting } from '/@/hooks/setting';
|
||||
import { useGlobSetting } from '/@/hooks/setting';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { localeStore } from '/@/store/modules/locale';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Login',
|
||||
@ -71,14 +72,13 @@
|
||||
setup() {
|
||||
const globSetting = useGlobSetting();
|
||||
const { prefixCls } = useDesign('login');
|
||||
const { locale } = useProjectSetting();
|
||||
const { t } = useI18n();
|
||||
|
||||
return {
|
||||
t,
|
||||
prefixCls,
|
||||
title: computed(() => globSetting?.title ?? ''),
|
||||
showLocale: computed(() => locale.show),
|
||||
showLocale: localeStore.getShowPicker,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
9
types/config.d.ts
vendored
9
types/config.d.ts
vendored
@ -8,9 +8,10 @@ import {
|
||||
} from '/@/enums/appEnum';
|
||||
|
||||
import { CacheTypeEnum } from '/@/enums/cacheEnum';
|
||||
import type { LocaleType } from '/@/locales/types';
|
||||
import { ThemeMode } from '../build/config/themeConfig';
|
||||
|
||||
export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja' | 'ko';
|
||||
|
||||
export interface MenuSetting {
|
||||
bgColor: string;
|
||||
fixed: boolean;
|
||||
@ -57,9 +58,9 @@ export interface HeaderSetting {
|
||||
}
|
||||
|
||||
export interface LocaleSetting {
|
||||
show: boolean;
|
||||
showPicker: boolean;
|
||||
// Current language
|
||||
lang: LocaleType;
|
||||
locale: LocaleType;
|
||||
// default language
|
||||
fallback: LocaleType;
|
||||
// available Locales
|
||||
@ -78,8 +79,6 @@ export interface TransitionSetting {
|
||||
}
|
||||
|
||||
export interface ProjectConfig {
|
||||
// Multilingual configuration
|
||||
locale: LocaleSetting;
|
||||
// Storage location of permission related information
|
||||
permissionCacheType: CacheTypeEnum;
|
||||
// Whether to show the configuration button
|
||||
|
2
types/module.d.ts
vendored
2
types/module.d.ts
vendored
@ -4,7 +4,7 @@ declare module 'ant-design-vue/es/locale/*' {
|
||||
export default locale as Locale & ReadonlyRecordable;
|
||||
}
|
||||
|
||||
declare module 'moment/locale/*' {
|
||||
declare module 'moment/dist/locale/*' {
|
||||
import { LocaleSpecification } from 'moment';
|
||||
const locale: LocaleSpecification & ReadonlyRecordable;
|
||||
export default locale;
|
||||
|
26
yarn.lock
26
yarn.lock
@ -1718,10 +1718,10 @@
|
||||
dependencies:
|
||||
vue-demi latest
|
||||
|
||||
"@windicss/plugin-utils@0.5.4":
|
||||
version "0.5.4"
|
||||
resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.5.4.tgz#69476a9d1fee92046695766bf7fbfe48e48809a7"
|
||||
integrity sha512-zxpHdTsVZl7TF8A3uAymJCqMRlG83dMRAXf//fXonluoLDSJCuGBJyxN3NdkAyNZZR1L1DvoUUtkZLYOba+ElQ==
|
||||
"@windicss/plugin-utils@0.6.0":
|
||||
version "0.6.0"
|
||||
resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.6.0.tgz#34eb852b7ff338bb933b0079112318a30d2aee00"
|
||||
integrity sha512-CpXn3CRrAaDrpTjenidVfBz0JONLuGTFP6qjrwZ2tmhsKOuvTWw8Ic9JQ2a9L0AkYBH33lTso1qk70/PjnE6WQ==
|
||||
dependencies:
|
||||
esbuild "^0.8.52"
|
||||
esbuild-register "^2.0.0"
|
||||
@ -1849,10 +1849,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
ant-design-vue@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.0.0.tgz#d30ec06938dc3b43b08a117818fab91d7b083e5f"
|
||||
integrity sha512-Uv35Z9V+8iT1PBO0QOqWHaVE4Gju94UfikL8NGxtAqy/yZDnTn8K2gz5n7PfQbB5oBqkEyn2O0mtOpUBUEXZ+g==
|
||||
ant-design-vue@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.0.1.tgz#3a5964523aac10fd2b16d84d651145cd2b65f1d5"
|
||||
integrity sha512-CFIF+srTui4ZwdKPBXNoFA9/0fkSpypanQeOts0PAq1vEuMLxUoZHapDDn7wzsxZH3sYLF+mvMp8gYMRkaNn+w==
|
||||
dependencies:
|
||||
"@ant-design-vue/use" "^0.0.1-0"
|
||||
"@ant-design/icons-vue" "^6.0.0"
|
||||
@ -8968,12 +8968,12 @@ vite-plugin-theme@^0.4.8:
|
||||
es-module-lexer "^0.3.26"
|
||||
tinycolor2 "^1.4.2"
|
||||
|
||||
vite-plugin-windicss@0.5.4:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.5.4.tgz#35764e91536d596ac2c9266c3e16c546915d8b3e"
|
||||
integrity sha512-iPLoqfpZdnRIY1AzweumpdE8ILQQnyhywZwJDqFpj8SZ3h43e5tfQFnJb5nS6FLccOsBcCV9JFugD2w6pGyfqg==
|
||||
vite-plugin-windicss@0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.6.0.tgz#ac8f24e70439904b67adc1f133e692fb6257ecaf"
|
||||
integrity sha512-PSFdm0hrAGaKFzkFOiz31+dODoKNbh9wo/3m/7/012WwV9oJ1mX/9OxDxACykW7hMR0YvWHFmC0UwtvMra+InQ==
|
||||
dependencies:
|
||||
"@windicss/plugin-utils" "0.5.4"
|
||||
"@windicss/plugin-utils" "0.6.0"
|
||||
windicss "^2.2.0"
|
||||
|
||||
vite@2.0.4:
|
||||
|
Loading…
Reference in New Issue
Block a user