refactor: refactored multi-language modules to support lazy loading and remote loading

This commit is contained in:
Vben 2021-02-27 23:08:12 +08:00
parent f57eb944ed
commit f6cef1088d
47 changed files with 353 additions and 284 deletions

View File

@ -21,3 +21,4 @@ ignore:
- dist - dist
- .local - .local
- .husky - .husky
- src/locales/lang

View File

@ -1,5 +1,9 @@
## Wip ## Wip
### ✨ Refactor
- 重构多语言模块,支持懒加载及远程加载
### ✨ Features ### ✨ Features
- axios 支持 form-data 格式请求 - axios 支持 form-data 格式请求

View File

@ -28,7 +28,7 @@
"@iconify/iconify": "^2.0.0-rc.6", "@iconify/iconify": "^2.0.0-rc.6",
"@vueuse/core": "^4.3.0", "@vueuse/core": "^4.3.0",
"@zxcvbn-ts/core": "^0.2.0", "@zxcvbn-ts/core": "^0.2.0",
"ant-design-vue": "2.0.0", "ant-design-vue": "2.0.1",
"apexcharts": "^3.25.0", "apexcharts": "^3.25.0",
"axios": "^0.21.1", "axios": "^0.21.1",
"crypto-js": "^4.0.0", "crypto-js": "^4.0.0",
@ -106,7 +106,7 @@
"vite-plugin-pwa": "^0.5.5", "vite-plugin-pwa": "^0.5.5",
"vite-plugin-style-import": "^0.7.5", "vite-plugin-style-import": "^0.7.5",
"vite-plugin-theme": "^0.4.8", "vite-plugin-theme": "^0.4.8",
"vite-plugin-windicss": "0.5.4", "vite-plugin-windicss": "0.6.0",
"vue-eslint-parser": "^7.5.0", "vue-eslint-parser": "^7.5.0",
"yargs": "^16.2.0" "yargs": "^16.2.0"
}, },

View File

@ -1,5 +1,5 @@
<template> <template>
<ConfigProvider v-bind="lockEvent" :locale="antConfigLocale"> <ConfigProvider v-bind="lockEvent" :locale="getAntdLocale">
<AppProvider> <AppProvider>
<RouterView /> <RouterView />
</AppProvider> </AppProvider>
@ -21,9 +21,7 @@
components: { ConfigProvider, AppProvider }, components: { ConfigProvider, AppProvider },
setup() { setup() {
// support Multi-language // support Multi-language
const { antConfigLocale, setLocale } = useLocale(); const { getAntdLocale } = useLocale();
setLocale();
// Initialize vuex internal system configuration // Initialize vuex internal system configuration
initAppConfigStore(); initAppConfigStore();
@ -31,10 +29,7 @@
// Create a lock screen monitor // Create a lock screen monitor
const lockEvent = useLockPage(); const lockEvent = useLockPage();
return { return { getAntdLocale, lockEvent };
antConfigLocale,
lockEvent,
};
}, },
}); });
</script> </script>

View File

@ -18,7 +18,7 @@
</Dropdown> </Dropdown>
</template> </template>
<script lang="ts"> <script lang="ts">
import type { LocaleType } from '/@/locales/types'; import type { LocaleType } from '/#/config';
import type { DropMenu } from '/@/components/Dropdown'; import type { DropMenu } from '/@/components/Dropdown';
import { defineComponent, ref, watchEffect, unref, computed } from 'vue'; import { defineComponent, ref, watchEffect, unref, computed } from 'vue';
@ -26,7 +26,7 @@
import Icon from '/@/components/Icon'; import Icon from '/@/components/Icon';
import { useLocale } from '/@/locales/useLocale'; import { useLocale } from '/@/locales/useLocale';
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting'; import { localeList } from '/@/settings/localeSetting';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
@ -44,9 +44,7 @@
const { prefixCls } = useDesign('app-locale-picker'); const { prefixCls } = useDesign('app-locale-picker');
const { localeList } = useLocaleSetting(); const { changeLocale, getLocale } = useLocale();
const { changeLocale, getLang } = useLocale();
const getLangText = computed(() => { const getLangText = computed(() => {
const key = selectedKeys.value[0]; const key = selectedKeys.value[0];
@ -55,17 +53,17 @@
}); });
watchEffect(() => { watchEffect(() => {
selectedKeys.value = [unref(getLang)]; selectedKeys.value = [unref(getLocale)];
}); });
function toggleLocale(lang: LocaleType | string) { async function toggleLocale(lang: LocaleType | string) {
changeLocale(lang as LocaleType); await changeLocale(lang as LocaleType);
selectedKeys.value = [lang as string]; selectedKeys.value = [lang as string];
props.reload && location.reload(); props.reload && location.reload();
} }
function handleMenuEvent(menu: DropMenu) { function handleMenuEvent(menu: DropMenu) {
if (unref(getLang) === menu.event) return; if (unref(getLocale) === menu.event) return;
toggleLocale(menu.event as string); toggleLocale(menu.event as string);
} }

View File

@ -34,13 +34,13 @@
const modalFn = useModalContext(); const modalFn = useModalContext();
const { getLang } = useLocale(); const { getLocale } = useLocale();
watchEffect(() => {}); watchEffect(() => {});
const getCurrentLang = computed((): 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' => { const getCurrentLang = computed((): 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' => {
let lang: Lang; let lang: Lang;
switch (unref(getLang)) { switch (unref(getLocale)) {
case 'en': case 'en':
lang = 'en_US'; lang = 'en_US';
break; break;

View File

@ -52,7 +52,6 @@
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
const { t } = useI18n();
export default defineComponent({ export default defineComponent({
name: 'SimpleSubMenu', name: 'SimpleSubMenu',
@ -73,6 +72,7 @@
theme: propTypes.oneOf(['dark', 'light']), theme: propTypes.oneOf(['dark', 'light']),
}, },
setup(props) { setup(props) {
const { t } = useI18n();
const { prefixCls } = useDesign('simple-menu'); const { prefixCls } = useDesign('simple-menu');
const getShowMenu = computed(() => { const getShowMenu = computed(() => {

View File

@ -1,6 +1,8 @@
// token key // token key
export const TOKEN_KEY = 'TOKEN__'; export const TOKEN_KEY = 'TOKEN__';
export const LOCALE_KEY = 'LOCALE__';
// user info key // user info key
export const USER_INFO_KEY = 'USER__INFO__'; 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__'; export const LOCK_INFO_KEY = 'LOCK__INFO__KEY__';
// base global local 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 // base global session key
export const BASE_SESSION_CACHE_KEY = 'SESSION__CACHE__KEY__'; export const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__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 enum CacheTypeEnum { export enum CacheTypeEnum {
SESSION, SESSION,

View File

@ -1,26 +1,16 @@
import type { ProjectConfig, GlobConfig, GlobEnvConfig } from '/#/config'; import type { GlobConfig } from '/#/config';
import { getConfigFileName } from '../../../build/getConfigFileName';
import getProjectSetting from '/@/settings/projectSetting';
import { warn } from '/@/utils/log'; import { warn } from '/@/utils/log';
import { getGlobEnvConfig, isDevMode } from '/@/utils/env'; import { getAppEnvConfig } from '/@/utils/env';
export const useGlobSetting = (): Readonly<GlobConfig> => { 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 { const {
VITE_GLOB_APP_TITLE, VITE_GLOB_APP_TITLE,
VITE_GLOB_API_URL, VITE_GLOB_API_URL,
VITE_GLOB_APP_SHORT_NAME, VITE_GLOB_APP_SHORT_NAME,
VITE_GLOB_API_URL_PREFIX, VITE_GLOB_API_URL_PREFIX,
VITE_GLOB_UPLOAD_URL, VITE_GLOB_UPLOAD_URL,
} = ENV; } = getAppEnvConfig();
if (!/[a-zA-Z\_]*/.test(VITE_GLOB_APP_SHORT_NAME)) { if (!/[a-zA-Z\_]*/.test(VITE_GLOB_APP_SHORT_NAME)) {
warn( warn(
@ -38,8 +28,3 @@ export const useGlobSetting = (): Readonly<GlobConfig> => {
}; };
return glob as Readonly<GlobConfig>; return glob as Readonly<GlobConfig>;
}; };
export const useProjectSetting = (): ProjectConfig => {
// TODO computed
return getProjectSetting;
};

View File

@ -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,
};
}

View File

@ -40,6 +40,7 @@ export function useI18n(
const tFn: I18nGlobalTranslation = (key: string, ...arg: any[]) => { const tFn: I18nGlobalTranslation = (key: string, ...arg: any[]) => {
if (!key) return ''; if (!key) return '';
if (!key.includes('.')) return key;
return t(getKey(namespace, key), ...(arg as I18nTranslationRestParameters)); return t(getKey(namespace, key), ...(arg as I18nTranslationRestParameters));
}; };
return { return {

View File

@ -58,7 +58,7 @@ export function usePermission() {
return def; return def;
} }
if (!isArray(value)) { 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; return (intersection(value, userStore.getRoleListState) as RoleEnum[]).length > 0;
} }

View File

@ -18,7 +18,6 @@
import { defineComponent, ref, toRaw, watchEffect } from 'vue'; import { defineComponent, ref, toRaw, watchEffect } from 'vue';
import { Breadcrumb } from 'ant-design-vue'; import { Breadcrumb } from 'ant-design-vue';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { filter } from '/@/utils/helper/treeHelper'; import { filter } from '/@/utils/helper/treeHelper';
@ -33,6 +32,7 @@
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { useGo } from '/@/hooks/web/usePage'; import { useGo } from '/@/hooks/web/usePage';
import { isString } from '/@/utils/is'; import { isString } from '/@/utils/is';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({ export default defineComponent({
name: 'LayoutBreadcrumb', name: 'LayoutBreadcrumb',

View File

@ -17,7 +17,7 @@
icon="ion:document-text-outline" icon="ion:document-text-outline"
v-if="getShowDoc" v-if="getShowDoc"
/> />
<MenuDivider /> <MenuDivider v-if="getShowDoc" />
<MenuItem <MenuItem
key="lock" key="lock"
:text="t('layout.header.tooltipLock')" :text="t('layout.header.tooltipLock')"

View File

@ -42,7 +42,7 @@
<FullScreen v-if="getShowFullScreen" :class="`${prefixCls}-action__item fullscreen-item`" /> <FullScreen v-if="getShowFullScreen" :class="`${prefixCls}-action__item fullscreen-item`" />
<AppLocalePicker <AppLocalePicker
v-if="getShowLocale" v-if="getShowLocalePicker"
:reload="true" :reload="true"
:showText="false" :showText="false"
:class="`${prefixCls}-action__item`" :class="`${prefixCls}-action__item`"
@ -69,7 +69,6 @@
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'; import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum'; import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
import { SettingButtonPositionEnum } from '/@/enums/appEnum'; import { SettingButtonPositionEnum } from '/@/enums/appEnum';
@ -80,6 +79,7 @@
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import { useLocale } from '/@/locales/useLocale';
export default defineComponent({ export default defineComponent({
name: 'LayoutHeader', name: 'LayoutHeader',
@ -112,7 +112,6 @@
getMenuWidth, getMenuWidth,
getIsMixSidebar, getIsMixSidebar,
} = useMenuSetting(); } = useMenuSetting();
const { getShowLocale } = useLocaleSetting();
const { const {
getUseErrorHandle, getUseErrorHandle,
getShowSettingButton, getShowSettingButton,
@ -130,6 +129,8 @@
getShowHeader, getShowHeader,
} = useHeaderSetting(); } = useHeaderSetting();
const { getShowLocalePicker } = useLocale();
const { getIsMobile } = useAppInject(); const { getIsMobile } = useAppInject();
const getHeaderClass = computed(() => { const getHeaderClass = computed(() => {
@ -185,7 +186,7 @@
getSplit, getSplit,
getMenuMode, getMenuMode,
getShowTopMenu, getShowTopMenu,
getShowLocale, getShowLocalePicker,
getShowFullScreen, getShowFullScreen,
getShowNotice, getShowNotice,
getUseLockPage, getUseLockPage,

View File

@ -1,11 +1,11 @@
import { toRaw, ref, nextTick } from 'vue'; import { toRaw, ref, nextTick } from 'vue';
import { RouteLocationNormalized } from 'vue-router'; import { RouteLocationNormalized } from 'vue-router';
import { useProjectSetting } from '/@/hooks/setting';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useSortable } from '/@/hooks/web/useSortable'; import { useSortable } from '/@/hooks/web/useSortable';
import router from '/@/router'; import router from '/@/router';
import { tabStore } from '/@/store/modules/tab'; import { tabStore } from '/@/store/modules/tab';
import { isNullAndUnDef } from '/@/utils/is'; import { isNullAndUnDef } from '/@/utils/is';
import projectSetting from '/@/settings/projectSetting';
export function initAffixTabs(): string[] { export function initAffixTabs(): string[] {
const affixList = ref<RouteLocationNormalized[]>([]); const affixList = ref<RouteLocationNormalized[]>([]);
@ -47,7 +47,7 @@ export function initAffixTabs(): string[] {
} }
export function useTabsDrag(affixTextList: string[]) { export function useTabsDrag(affixTextList: string[]) {
const { multiTabsSetting } = useProjectSetting(); const { multiTabsSetting } = projectSetting;
const { prefixCls } = useDesign('multiple-tabs'); const { prefixCls } = useDesign('multiple-tabs');
nextTick(() => { nextTick(() => {

View File

@ -1,13 +0,0 @@
import type { DropMenu } from '/@/components/Dropdown';
// locale list
export const localeList: DropMenu[] = [
{
text: '简体中文',
event: 'zh_CN',
},
{
text: 'English',
event: 'en',
},
];

View File

@ -1,4 +0,0 @@
import { genMessage } from './helper';
const modules = import.meta.globEager('./lang/**/*.ts');
export default genMessage(modules);

View File

@ -4,16 +4,21 @@ export function genMessage(langs: Record<string, Record<string, any>>, prefix =
const obj: Recordable = {}; const obj: Recordable = {};
Object.keys(langs).forEach((key) => { Object.keys(langs).forEach((key) => {
const mod = langs[key].default; const langFileModule = langs[key].default;
let k = key.replace(`./${prefix}/`, '').replace(/^\.\//, ''); let fileName = key.replace(`./${prefix}/`, '').replace(/^\.\//, '');
const lastIndex = k.lastIndexOf('.'); const lastIndex = fileName.lastIndexOf('.');
k = k.substring(0, lastIndex); fileName = fileName.substring(0, lastIndex);
const keyList = k.split('/'); const keyList = fileName.split('/');
const lang = keyList.shift(); const moduleName = keyList.shift();
const objKey = keyList.join('.'); const objKey = keyList.join('.');
if (lang) {
set(obj, lang, obj[lang] || {}); if (moduleName) {
set(obj[lang], objKey, mod); if (objKey) {
set(obj, moduleName, obj[moduleName] || {});
set(obj[moduleName], objKey, langFileModule);
} else {
set(obj, moduleName, langFileModule || {});
}
} }
}); });
return obj; return obj;

13
src/locales/lang/en.ts Normal file
View 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',
};

View File

@ -1,5 +1,5 @@
export default { export default {
redo: 'Refresh current', reload: 'Refresh current',
close: 'Close current', close: 'Close current',
closeLeft: 'Close Left', closeLeft: 'Close Left',
closeRight: 'Close Right', closeRight: 'Close Right',

View File

@ -25,4 +25,6 @@ export default {
list: 'List page', list: 'List page',
listCard: 'Card list', listCard: 'Card list',
basic: 'Basic list', basic: 'Basic list',
listBasic: 'Basic list',
listSearch: 'Search list',
}; };

13
src/locales/lang/zh_CN.ts Normal file
View 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',
};

View File

@ -3,27 +3,36 @@ import type { I18n, I18nOptions } from 'vue-i18n';
import { createI18n } 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 = { async function createI18nOptions(): Promise<I18nOptions> {
const locale = localeStore.getLocale;
const defaultLocal = await import(`./lang/${locale}.ts`);
const message = defaultLocal.default?.message;
return {
legacy: false, legacy: false,
locale: lang, locale,
fallbackLocale: fallback, fallbackLocale: fallback,
messages, messages: {
[locale]: message,
},
availableLocales: availableLocales, availableLocales: availableLocales,
sync: true, //If you dont want to inherit locale from global scope, you need to set sync of i18n component option to false. sync: true, //If you dont want to inherit locale from global scope, you need to set sync of i18n component option to false.
silentTranslationWarn: true, // true - warning off silentTranslationWarn: true, // true - warning off
missingWarn: false, missingWarn: false,
silentFallbackWarn: true, silentFallbackWarn: true,
}; };
export let i18n: I18n; }
// setup i18n instance with glob // setup i18n instance with glob
export function setupI18n(app: App) { export async function setupI18n(app: App) {
i18n = createI18n(localeData) as I18n; const options = await createI18nOptions();
i18n = createI18n(options) as I18n;
app.use(i18n); app.use(i18n);
} }

View File

@ -1 +0,0 @@
export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja' | 'ko';

View File

@ -1,64 +1,73 @@
/** /**
* Multi-language related operations * Multi-language related operations
*/ */
import type { LocaleType } from '/@/locales/types'; import type { LocaleType } from '/#/config';
import type { Ref } from 'vue';
import { unref, ref } from 'vue'; import { ref } from 'vue';
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting'; import moment from 'moment';
import { computed } from 'vue';
import { i18n } from './setupI18n'; 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() { 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 // Switching the language will change the locale of useI18n
// And submit to configuration modification // And submit to configuration modification
function changeLocale(lang: LocaleType): void { async function changeLocale(locale: LocaleType) {
if (i18n.mode === 'legacy') { const globalI18n = i18n.global;
i18n.global.locale = lang; const currentLocale = unref(globalI18n.locale);
} else { if (currentLocale === locale) return locale;
((i18n.global.locale as unknown) as Ref<string>).value = lang;
if (loadLocalePool.includes(locale)) {
setI18nLanguage(locale);
return locale;
} }
setLocalSetting({ lang }); const langModule = ((await import(`./lang/${locale}.ts`)) as any).default as LangModule;
// i18n.global.setLocaleMessage(locale, messages); if (!langModule) return;
switch (lang) { const { message, momentLocale, momentLocaleName } = langModule;
// Simplified Chinese
case 'zh_CN':
import('ant-design-vue/es/locale/zh_CN').then((locale) => {
antConfigLocaleRef.value = locale.default;
});
break; globalI18n.setLocaleMessage(locale, message);
// English moment.updateLocale(momentLocaleName, momentLocale);
case 'en': loadLocalePool.push(locale);
import('ant-design-vue/es/locale/en_US').then((locale) => {
antConfigLocaleRef.value = locale.default;
});
break;
// other setI18nLanguage(locale);
default: return locale;
break;
}
}
// initialization
function setLocale() {
const lang = unref(getLang);
lang && changeLocale(lang);
} }
return { return {
setLocale,
getLocale, getLocale,
getLang, getShowLocalePicker,
changeLocale, changeLocale,
antConfigLocale: antConfigLocaleRef, antConfigLocale,
getAntdLocale,
}; };
} }

View File

@ -3,9 +3,9 @@
*/ */
import { errorStore, ErrorInfo } from '/@/store/modules/error'; import { errorStore, ErrorInfo } from '/@/store/modules/error';
import { useProjectSetting } from '/@/hooks/setting';
import { ErrorTypeEnum } from '/@/enums/exceptionEnum'; import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
import { App } from 'vue'; import { App } from 'vue';
import projectSetting from '/@/settings/projectSetting';
/** /**
* Handling error stack information * Handling error stack information
@ -160,7 +160,7 @@ function registerResourceErrorHandler() {
* @param app * @param app
*/ */
export function setupErrorHandle(app: App) { export function setupErrorHandle(app: App) {
const { useErrorHandle } = useProjectSetting(); const { useErrorHandle } = projectSetting;
if (!useErrorHandle) return; if (!useErrorHandle) return;
// Vue exception monitoring; // Vue exception monitoring;
app.config.errorHandler = vueErrorHandler; app.config.errorHandler = vueErrorHandler;

View File

@ -2,25 +2,22 @@
* Application configuration * Application configuration
*/ */
import type { ProjectConfig } from '/#/config';
import { PROJ_CFG_KEY } from '/@/enums/cacheEnum';
import projectSetting from '/@/settings/projectSetting'; import projectSetting from '/@/settings/projectSetting';
import { Persistent } from '/@/utils/cache/persistent';
import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground'; import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground';
import { updateColorWeak } from '/@/logics/theme/updateColorWeak'; import { updateColorWeak } from '/@/logics/theme/updateColorWeak';
import { updateGrayMode } from '/@/logics/theme/updateGrayMode'; import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
import { changeTheme } from '/@/logics/theme'; import { changeTheme } from '/@/logics/theme';
import { appStore } from '/@/store/modules/app'; 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'; import { primaryColor } from '../../build/config/themeConfig';
// Initial project configuration // Initial project configuration
export function initAppConfigStore() { export function initAppConfigStore() {
let projCfg: ProjectConfig = Persistent.getLocal(PROJ_CFG_KEY) as ProjectConfig;
projCfg = deepMerge(projectSetting, projCfg || {});
try { try {
const { const {
colorWeak, colorWeak,
@ -28,7 +25,7 @@ export function initAppConfigStore() {
themeColor, themeColor,
headerSetting: { bgColor: headerBgColor } = {}, headerSetting: { bgColor: headerBgColor } = {},
menuSetting: { bgColor } = {}, menuSetting: { bgColor } = {},
} = projCfg; } = projectSetting;
if (themeColor && themeColor !== primaryColor) { if (themeColor && themeColor !== primaryColor) {
changeTheme(themeColor); changeTheme(themeColor);
} }
@ -39,5 +36,27 @@ export function initAppConfigStore() {
} catch (error) { } catch (error) {
console.log(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);
}
});
});
} }

View File

@ -14,33 +14,36 @@ import { registerGlobComp } from '/@/components/registerGlobComp';
import { isDevMode } from '/@/utils/env'; import { isDevMode } from '/@/utils/env';
const app = createApp(App); (async () => {
const app = createApp(App);
// Register global components // Register global components
registerGlobComp(app); registerGlobComp(app);
// Multilingual configuration // Configure routing
setupI18n(app); setupRouter(app);
// Configure routing // Configure vuex store
setupRouter(app); setupStore(app);
// Configure vuex store // Register global directive
setupStore(app); setupGlobDirectives(app);
// Register global directive // Configure global error handling
setupGlobDirectives(app); setupErrorHandle(app);
// Configure global error handling await Promise.all([
setupErrorHandle(app); // 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); app.mount('#app', true);
});
// The development environment takes effect // The development environment takes effect
if (isDevMode()) { if (isDevMode()) {
app.config.performance = true; app.config.performance = true;
window.__APP__ = app; window.__APP__ = app;
} }
})();

View File

@ -1,13 +1,13 @@
import type { Router } from 'vue-router'; import type { Router } from 'vue-router';
import { useProjectSetting } from '/@/hooks/setting';
import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel'; 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 * The interface used to close the current page to complete the request when the route is switched
* @param router * @param router
*/ */
export function createHttpGuard(router: Router) { export function createHttpGuard(router: Router) {
const { removeAllHttpPending } = useProjectSetting(); const { removeAllHttpPending } = projectSetting;
let axiosCanceler: Nullable<AxiosCanceler>; let axiosCanceler: Nullable<AxiosCanceler>;
if (removeAllHttpPending) { if (removeAllHttpPending) {
axiosCanceler = new AxiosCanceler(); axiosCanceler = new AxiosCanceler();

View File

@ -1,7 +1,6 @@
import type { Router } from 'vue-router'; import type { Router } from 'vue-router';
import { useProjectSetting } from '/@/hooks/setting';
import { Modal, notification } from 'ant-design-vue'; import { Modal, notification } from 'ant-design-vue';
import projectSetting from '/@/settings/projectSetting';
import { warn } from '/@/utils/log'; import { warn } from '/@/utils/log';
/** /**
@ -9,7 +8,7 @@ import { warn } from '/@/utils/log';
* @param router * @param router
*/ */
export function createMessageGuard(router: Router) { export function createMessageGuard(router: Router) {
const { closeMessageOnSwitch } = useProjectSetting(); const { closeMessageOnSwitch } = projectSetting;
router.beforeEach(async () => { router.beforeEach(async () => {
try { try {

View File

@ -4,9 +4,11 @@ import type { App } from 'vue';
import { createRouter, createWebHashHistory } from 'vue-router'; import { createRouter, createWebHashHistory } from 'vue-router';
import { createGuard } from './guard'; import { createGuard } from './guard';
import { basicRoutes } from './routes'; import { basicRoutes, LoginRoute } from './routes';
import { REDIRECT_NAME } from './constant'; import { REDIRECT_NAME } from './constant';
const WHITE_NAME_LIST = [LoginRoute.name, REDIRECT_NAME];
// app router // app router
const router = createRouter({ const router = createRouter({
history: createWebHashHistory(), history: createWebHashHistory(),
@ -17,10 +19,9 @@ const router = createRouter({
// reset router // reset router
export function resetRouter() { export function resetRouter() {
const resetWhiteNameList = ['Login', REDIRECT_NAME];
router.getRoutes().forEach((route) => { router.getRoutes().forEach((route) => {
const { name } = 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); router.hasRoute(name) && router.removeRoute(name);
} }
}); });

View File

@ -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'; import type { AppRouteModule } from '/@/router/types';
// test // test

View 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,
},
];

View File

@ -1,5 +1,4 @@
import type { ProjectConfig } from '/#/config'; import type { ProjectConfig } from '/#/config';
import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum'; import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum';
import { CacheTypeEnum } from '/@/enums/cacheEnum'; import { CacheTypeEnum } from '/@/enums/cacheEnum';
import { import {
@ -26,8 +25,8 @@ const setting: ProjectConfig = {
permissionCacheType: CacheTypeEnum.LOCAL, permissionCacheType: CacheTypeEnum.LOCAL,
// color // color
// TODO Theme color
themeColor: primaryColor, themeColor: primaryColor,
// TODO dark theme // TODO dark theme
themeMode: themeMode, themeMode: themeMode,
@ -49,17 +48,6 @@ const setting: ProjectConfig = {
// Whether to show footer // Whether to show footer
showFooter: false, showFooter: false,
// locale setting
locale: {
show: true,
// Locale
lang: 'zh_CN',
// Default locale
fallback: 'zh_CN',
// available Locales
availableLocales: ['zh_CN', 'en'],
},
// Header configuration // Header configuration
headerSetting: { headerSetting: {
// header bg color // header bg color

View File

@ -4,7 +4,7 @@ import { VuexModule, getModule, Module, Mutation, Action } from 'vuex-module-dec
import { formatToDateTime } from '/@/utils/dateUtil'; import { formatToDateTime } from '/@/utils/dateUtil';
import { ErrorTypeEnum } from '/@/enums/exceptionEnum'; import { ErrorTypeEnum } from '/@/enums/exceptionEnum';
import { useProjectSetting } from '/@/hooks/setting'; import projectSetting from '/@/settings/projectSetting';
export interface ErrorInfo { export interface ErrorInfo {
type: ErrorTypeEnum; type: ErrorTypeEnum;
@ -57,7 +57,7 @@ class Error extends VuexModule implements ErrorState {
@Action @Action
setupErrorHandle(error: any) { setupErrorHandle(error: any) {
const { useErrorHandle } = useProjectSetting(); const { useErrorHandle } = projectSetting;
if (!useErrorHandle) return; if (!useErrorHandle) return;
const errInfo: Partial<ErrorInfo> = { const errInfo: Partial<ErrorInfo> = {

View 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);

View File

@ -88,7 +88,7 @@ class Permission extends VuexModule {
let routes: AppRouteRecordRaw[] = []; let routes: AppRouteRecordRaw[] = [];
const roleList = toRaw(userStore.getRoleListState); const roleList = toRaw(userStore.getRoleListState);
const { permissionMode } = appStore.getProjectConfig; const { permissionMode = PermissionModeEnum.ROLE } = appStore.getProjectConfig;
// role permissions // role permissions
if (permissionMode === PermissionModeEnum.ROLE) { if (permissionMode === PermissionModeEnum.ROLE) {

View File

@ -11,7 +11,6 @@ const createOptions = (storage: Storage, options: Options = {}): Options => {
hasEncrypt: enableStorageEncryption, hasEncrypt: enableStorageEncryption,
storage, storage,
prefixKey: getStorageShortName(), prefixKey: getStorageShortName(),
...options, ...options,
}; };
}; };
@ -22,11 +21,12 @@ export const createStorage = (storage: Storage = sessionStorage, options: Option
return create(createOptions(storage, options)); return create(createOptions(storage, options));
}; };
export const createPersistentStorage = ( export const createSessionStorage = (options: Options = {}) => {
storage: Storage = sessionStorage, return createStorage(sessionStorage, { ...options, timeout: DEFAULT_CACHE_TIME });
options: Options = {} };
) => {
return createStorage(storage, { ...options, timeout: DEFAULT_CACHE_TIME }); export const createLocalStorage = (options: Options = {}) => {
return createStorage(localStorage, { ...options, timeout: DEFAULT_CACHE_TIME });
}; };
export default WebStorage; export default WebStorage;

View File

@ -57,7 +57,7 @@ export class Memory<T = any, V = any> {
if (!expires) { if (!expires) {
return value; return value;
} }
item.time = new Date().getTime() + this.alive * 1000; item.time = new Date().getTime() + this.alive;
item.timeoutId = setTimeout(() => { item.timeoutId = setTimeout(() => {
this.remove(key); this.remove(key);
}, expires); }, expires);
@ -80,7 +80,7 @@ export class Memory<T = any, V = any> {
const item = cache[k]; const item = cache[k];
if (item && item.time) { if (item && item.time) {
const now = new Date().getTime(); const now = new Date().getTime();
const expire = now + item.time * 1000; const expire = item.time;
if (expire > now) { if (expire > now) {
this.set(k, item.value, expire); this.set(k, item.value, expire);
} }

View File

@ -1,4 +1,4 @@
import { createPersistentStorage } from '/@/utils/cache'; import { createLocalStorage, createSessionStorage } from '/@/utils/cache';
import { Memory } from './memory'; import { Memory } from './memory';
import { import {
TOKEN_KEY, TOKEN_KEY,
@ -28,19 +28,19 @@ export type BasicKeys = keyof BasicStore;
type LocalKeys = keyof LocalStore; type LocalKeys = keyof LocalStore;
type SessionKeys = keyof SessionStore; type SessionKeys = keyof SessionStore;
const ls = createPersistentStorage(localStorage); const ls = createLocalStorage();
const ss = createPersistentStorage(sessionStorage); const ss = createSessionStorage();
const localMemory = new Memory(DEFAULT_CACHE_TIME); const localMemory = new Memory(DEFAULT_CACHE_TIME);
const sessionMemory = 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 localCache = ls.get(APP_LOCAL_CACHE_KEY);
const sessionCache = ls.get(APP_SESSION_CACHE_KEY); const sessionCache = ls.get(APP_SESSION_CACHE_KEY);
localCache && localMemory.resetCache(localCache); localCache && localMemory.resetCache(localCache);
sessionCache && sessionMemory.resetCache(sessionCache); sessionCache && sessionMemory.resetCache(sessionCache);
} }
initMemory();
export class Persistent { export class Persistent {
static getLocal<T>(key: LocalKeys) { static getLocal<T>(key: LocalKeys) {
return localMemory.get(key)?.value as Nullable<T>; return localMemory.get(key)?.value as Nullable<T>;
@ -106,4 +106,4 @@ function storageChange(e: any) {
window.addEventListener('storage', storageChange); window.addEventListener('storage', storageChange);
export default {}; initPersistentMemory();

View File

@ -2,19 +2,26 @@ import type { GlobEnvConfig } from '/#/config';
import { useGlobSetting } from '/@/hooks/setting'; import { useGlobSetting } from '/@/hooks/setting';
import pkg from '../../package.json'; import pkg from '../../package.json';
import { getConfigFileName } from '../../build/getConfigFileName';
/** export function getCommonStoragePrefix() {
* Get the global configuration (the configuration will be extracted independently when packaging) const globSetting = useGlobSetting();
*/ return `${globSetting.shortName}__${getEnv()}`.toUpperCase();
export function getGlobEnvConfig(): GlobEnvConfig {
const env = import.meta.env;
return (env as unknown) as GlobEnvConfig;
} }
// Generate cache key according to version // Generate cache key according to version
export function getStorageShortName() { export function getStorageShortName() {
const globSetting = useGlobSetting(); return `${getCommonStoragePrefix()}${`__${pkg.version}`}__`.toUpperCase();
return `${globSetting.shortName}__${getEnv()}${`__${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;
} }
/** /**

View File

@ -1,11 +1,10 @@
import { dateUtil } from '/@/utils/dateUtil'; import { dateUtil } from '/@/utils/dateUtil';
import { reactive, toRefs } from 'vue'; import { reactive, toRefs } from 'vue';
import { tryOnMounted, tryOnUnmounted } from '/@/utils/helper/vueHelper'; import { tryOnMounted, tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting'; import { localeStore } from '/@/store/modules/locale';
export function useNow(immediate = true) { export function useNow(immediate = true) {
const { getLang } = useLocaleSetting(); const localData = dateUtil.localeData(localeStore.getLocale);
const localData = dateUtil.localeData(getLang.value);
let timer: IntervalHandle; let timer: IntervalHandle;
const state = reactive({ const state = reactive({

View File

@ -53,9 +53,10 @@
import MobileForm from './MobileForm.vue'; import MobileForm from './MobileForm.vue';
import QrCodeForm from './QrCodeForm.vue'; import QrCodeForm from './QrCodeForm.vue';
import { useGlobSetting, useProjectSetting } from '/@/hooks/setting'; import { useGlobSetting } from '/@/hooks/setting';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { localeStore } from '/@/store/modules/locale';
export default defineComponent({ export default defineComponent({
name: 'Login', name: 'Login',
@ -71,14 +72,13 @@
setup() { setup() {
const globSetting = useGlobSetting(); const globSetting = useGlobSetting();
const { prefixCls } = useDesign('login'); const { prefixCls } = useDesign('login');
const { locale } = useProjectSetting();
const { t } = useI18n(); const { t } = useI18n();
return { return {
t, t,
prefixCls, prefixCls,
title: computed(() => globSetting?.title ?? ''), title: computed(() => globSetting?.title ?? ''),
showLocale: computed(() => locale.show), showLocale: localeStore.getShowPicker,
}; };
}, },
}); });

9
types/config.d.ts vendored
View File

@ -8,9 +8,10 @@ import {
} from '/@/enums/appEnum'; } from '/@/enums/appEnum';
import { CacheTypeEnum } from '/@/enums/cacheEnum'; import { CacheTypeEnum } from '/@/enums/cacheEnum';
import type { LocaleType } from '/@/locales/types';
import { ThemeMode } from '../build/config/themeConfig'; import { ThemeMode } from '../build/config/themeConfig';
export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja' | 'ko';
export interface MenuSetting { export interface MenuSetting {
bgColor: string; bgColor: string;
fixed: boolean; fixed: boolean;
@ -57,9 +58,9 @@ export interface HeaderSetting {
} }
export interface LocaleSetting { export interface LocaleSetting {
show: boolean; showPicker: boolean;
// Current language // Current language
lang: LocaleType; locale: LocaleType;
// default language // default language
fallback: LocaleType; fallback: LocaleType;
// available Locales // available Locales
@ -78,8 +79,6 @@ export interface TransitionSetting {
} }
export interface ProjectConfig { export interface ProjectConfig {
// Multilingual configuration
locale: LocaleSetting;
// Storage location of permission related information // Storage location of permission related information
permissionCacheType: CacheTypeEnum; permissionCacheType: CacheTypeEnum;
// Whether to show the configuration button // Whether to show the configuration button

2
types/module.d.ts vendored
View File

@ -4,7 +4,7 @@ declare module 'ant-design-vue/es/locale/*' {
export default locale as Locale & ReadonlyRecordable; export default locale as Locale & ReadonlyRecordable;
} }
declare module 'moment/locale/*' { declare module 'moment/dist/locale/*' {
import { LocaleSpecification } from 'moment'; import { LocaleSpecification } from 'moment';
const locale: LocaleSpecification & ReadonlyRecordable; const locale: LocaleSpecification & ReadonlyRecordable;
export default locale; export default locale;

View File

@ -1718,10 +1718,10 @@
dependencies: dependencies:
vue-demi latest vue-demi latest
"@windicss/plugin-utils@0.5.4": "@windicss/plugin-utils@0.6.0":
version "0.5.4" version "0.6.0"
resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.5.4.tgz#69476a9d1fee92046695766bf7fbfe48e48809a7" resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.6.0.tgz#34eb852b7ff338bb933b0079112318a30d2aee00"
integrity sha512-zxpHdTsVZl7TF8A3uAymJCqMRlG83dMRAXf//fXonluoLDSJCuGBJyxN3NdkAyNZZR1L1DvoUUtkZLYOba+ElQ== integrity sha512-CpXn3CRrAaDrpTjenidVfBz0JONLuGTFP6qjrwZ2tmhsKOuvTWw8Ic9JQ2a9L0AkYBH33lTso1qk70/PjnE6WQ==
dependencies: dependencies:
esbuild "^0.8.52" esbuild "^0.8.52"
esbuild-register "^2.0.0" esbuild-register "^2.0.0"
@ -1849,10 +1849,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies: dependencies:
color-convert "^2.0.1" color-convert "^2.0.1"
ant-design-vue@2.0.0: ant-design-vue@2.0.1:
version "2.0.0" version "2.0.1"
resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.0.0.tgz#d30ec06938dc3b43b08a117818fab91d7b083e5f" resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.0.1.tgz#3a5964523aac10fd2b16d84d651145cd2b65f1d5"
integrity sha512-Uv35Z9V+8iT1PBO0QOqWHaVE4Gju94UfikL8NGxtAqy/yZDnTn8K2gz5n7PfQbB5oBqkEyn2O0mtOpUBUEXZ+g== integrity sha512-CFIF+srTui4ZwdKPBXNoFA9/0fkSpypanQeOts0PAq1vEuMLxUoZHapDDn7wzsxZH3sYLF+mvMp8gYMRkaNn+w==
dependencies: dependencies:
"@ant-design-vue/use" "^0.0.1-0" "@ant-design-vue/use" "^0.0.1-0"
"@ant-design/icons-vue" "^6.0.0" "@ant-design/icons-vue" "^6.0.0"
@ -8968,12 +8968,12 @@ vite-plugin-theme@^0.4.8:
es-module-lexer "^0.3.26" es-module-lexer "^0.3.26"
tinycolor2 "^1.4.2" tinycolor2 "^1.4.2"
vite-plugin-windicss@0.5.4: vite-plugin-windicss@0.6.0:
version "0.5.4" version "0.6.0"
resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.5.4.tgz#35764e91536d596ac2c9266c3e16c546915d8b3e" resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.6.0.tgz#ac8f24e70439904b67adc1f133e692fb6257ecaf"
integrity sha512-iPLoqfpZdnRIY1AzweumpdE8ILQQnyhywZwJDqFpj8SZ3h43e5tfQFnJb5nS6FLccOsBcCV9JFugD2w6pGyfqg== integrity sha512-PSFdm0hrAGaKFzkFOiz31+dODoKNbh9wo/3m/7/012WwV9oJ1mX/9OxDxACykW7hMR0YvWHFmC0UwtvMra+InQ==
dependencies: dependencies:
"@windicss/plugin-utils" "0.5.4" "@windicss/plugin-utils" "0.6.0"
windicss "^2.2.0" windicss "^2.2.0"
vite@2.0.4: vite@2.0.4: