Commit f6cef1088d499acd7d5124d8e1a83d454ba648cb

Authored by Vben
1 parent f57eb944

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

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