Browse Source

perf: enable strict ts type checking (#4045)

Vben 7 months ago
parent
commit
4f5783d00b
41 changed files with 125 additions and 77 deletions
  1. 2 1
      apps/web-antd/src/layouts/basic.vue
  2. 2 2
      apps/web-antd/src/locales/index.ts
  3. 5 3
      apps/web-antd/src/views/demos/access/button-control.vue
  4. 8 3
      apps/web-antd/src/views/demos/access/index.vue
  5. 2 1
      apps/web-ele/src/layouts/basic.vue
  6. 3 3
      apps/web-ele/src/locales/index.ts
  7. 2 1
      apps/web-naive/src/app.vue
  8. 2 1
      apps/web-naive/src/layouts/basic.vue
  9. 2 2
      apps/web-naive/src/locales/index.ts
  10. 0 2
      docs/src/guide/essentials/icons.md
  11. 3 0
      internal/tsconfig/base.json
  12. 11 9
      packages/@core/base/shared/src/colorful/generator.ts
  13. 3 4
      packages/@core/preferences/src/update-css-variables.ts
  14. 2 1
      packages/@core/ui-kit/layout-ui/src/vben-layout.vue
  15. 4 2
      packages/@core/ui-kit/menu-ui/src/components/menu.vue
  16. 2 1
      packages/@core/ui-kit/menu-ui/src/hooks/use-menu.ts
  17. 2 1
      packages/@core/ui-kit/menu-ui/src/menu.vue
  18. 2 1
      packages/@core/ui-kit/shadcn-ui/src/components/button/icon-button.vue
  19. 1 1
      packages/@core/ui-kit/shadcn-ui/src/components/count-to-animator/count-to-animator.vue
  20. 8 3
      packages/@core/ui-kit/shadcn-ui/src/components/hover-card/hover-card.vue
  21. 2 1
      packages/@core/ui-kit/shadcn-ui/src/components/popover/popover.vue
  22. 4 1
      packages/@core/ui-kit/shadcn-ui/src/components/render-content/render-content.vue
  23. 2 2
      packages/@core/ui-kit/shadcn-ui/src/components/tooltip/tooltip.vue
  24. 3 2
      packages/@core/ui-kit/tabs-ui/src/components/tabs/tabs.vue
  25. 2 1
      packages/@core/ui-kit/tabs-ui/src/tabs-view.vue
  26. 1 1
      packages/effects/access/src/accessible.ts
  27. 2 1
      packages/effects/common-ui/src/authentication/login-expired-modal.vue
  28. 2 1
      packages/effects/common-ui/src/authentication/login.vue
  29. 1 1
      packages/effects/common-ui/src/dashboard/analysis/analysis-charts-tabs.vue
  30. 2 1
      packages/effects/layouts/src/basic/layout.vue
  31. 2 1
      packages/effects/layouts/src/basic/menu/extra-menu.vue
  32. 2 1
      packages/effects/layouts/src/basic/menu/menu.vue
  33. 1 1
      packages/effects/layouts/src/widgets/global-search/global-search.vue
  34. 6 4
      packages/effects/layouts/src/widgets/global-search/search-panel.vue
  35. 2 1
      packages/effects/layouts/src/widgets/preferences/blocks/layout/tabbar.vue
  36. 3 3
      packages/effects/layouts/src/widgets/user-dropdown/user-dropdown.vue
  37. 2 2
      packages/effects/request/src/request-client/modules/interceptor.ts
  38. 4 2
      packages/locales/src/i18n.ts
  39. 1 1
      packages/locales/src/typing.ts
  40. 11 3
      packages/stores/src/modules/tabbar.ts
  41. 4 4
      packages/utils/src/helpers/generate-routes-backend.ts

+ 2 - 1
apps/web-antd/src/layouts/basic.vue

@@ -1,4 +1,6 @@
 <script lang="ts" setup>
+import type { NotificationItem } from '@vben/layouts';
+
 import { computed, ref } from 'vue';
 import { useRouter } from 'vue-router';
 
@@ -9,7 +11,6 @@ import {
   BasicLayout,
   LockScreen,
   Notification,
-  NotificationItem,
   UserDropdown,
 } from '@vben/layouts';
 import { preferences } from '@vben/preferences';

+ 2 - 2
apps/web-antd/src/locales/index.ts

@@ -24,10 +24,10 @@ const localesMap = loadLocalesMap(modules);
  */
 async function loadMessages(lang: SupportedLanguagesType) {
   const [appLocaleMessages] = await Promise.all([
-    localesMap[lang](),
+    localesMap[lang]?.(),
     loadThirdPartyMessage(lang),
   ]);
-  return appLocaleMessages.default;
+  return appLocaleMessages?.default;
 }
 
 /**

+ 5 - 3
apps/web-antd/src/views/demos/access/button-control.vue

@@ -41,9 +41,11 @@ async function changeAccount(role: string) {
 
   const account = accounts[role];
   resetAllStores();
-  await authStore.authLogin(account, async () => {
-    router.go(0);
-  });
+  if (account) {
+    await authStore.authLogin(account, async () => {
+      router.go(0);
+    });
+  }
 }
 </script>
 

+ 8 - 3
apps/web-antd/src/views/demos/access/index.vue

@@ -41,12 +41,17 @@ async function changeAccount(role: string) {
 
   const account = accounts[role];
   resetAllStores();
-  await accessStore.authLogin(account, async () => {
-    router.go(0);
-  });
+  if (account) {
+    await accessStore.authLogin(account, async () => {
+      router.go(0);
+    });
+  }
 }
 
 async function handleToggleAccessMode() {
+  if (!accounts.super) {
+    return;
+  }
   await toggleAccessMode();
   resetAllStores();
 

+ 2 - 1
apps/web-ele/src/layouts/basic.vue

@@ -1,4 +1,6 @@
 <script lang="ts" setup>
+import type { NotificationItem } from '@vben/layouts';
+
 import { computed, ref } from 'vue';
 import { useRouter } from 'vue-router';
 
@@ -9,7 +11,6 @@ import {
   BasicLayout,
   LockScreen,
   Notification,
-  NotificationItem,
   UserDropdown,
 } from '@vben/layouts';
 import { preferences } from '@vben/preferences';

+ 3 - 3
apps/web-ele/src/locales/index.ts

@@ -1,4 +1,5 @@
 import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales';
+import type { Language } from 'element-plus/es/locale';
 
 import type { App } from 'vue';
 import { ref } from 'vue';
@@ -7,7 +8,6 @@ import { $t, setupI18n as coreSetup, loadLocalesMap } from '@vben/locales';
 import { preferences } from '@vben/preferences';
 
 import dayjs from 'dayjs';
-import { Language } from 'element-plus/es/locale';
 import enLocale from 'element-plus/es/locale/lang/en';
 import defaultLocale from 'element-plus/es/locale/lang/zh-cn';
 
@@ -24,10 +24,10 @@ const localesMap = loadLocalesMap(modules);
  */
 async function loadMessages(lang: SupportedLanguagesType) {
   const [appLocaleMessages] = await Promise.all([
-    localesMap[lang](),
+    localesMap[lang]?.(),
     loadThirdPartyMessage(lang),
   ]);
-  return appLocaleMessages.default;
+  return appLocaleMessages?.default;
 }
 
 /**

+ 2 - 1
apps/web-naive/src/app.vue

@@ -1,4 +1,6 @@
 <script lang="ts" setup>
+import type { GlobalThemeOverrides } from 'naive-ui';
+
 import { computed } from 'vue';
 
 import { useNaiveDesignTokens } from '@vben/hooks';
@@ -9,7 +11,6 @@ import {
   dateEnUS,
   dateZhCN,
   enUS,
-  GlobalThemeOverrides,
   lightTheme,
   NConfigProvider,
   NMessageProvider,

+ 2 - 1
apps/web-naive/src/layouts/basic.vue

@@ -1,4 +1,6 @@
 <script lang="ts" setup>
+import type { NotificationItem } from '@vben/layouts';
+
 import { computed, ref } from 'vue';
 import { useRouter } from 'vue-router';
 
@@ -9,7 +11,6 @@ import {
   BasicLayout,
   LockScreen,
   Notification,
-  NotificationItem,
   UserDropdown,
 } from '@vben/layouts';
 import { preferences } from '@vben/preferences';

+ 2 - 2
apps/web-naive/src/locales/index.ts

@@ -15,8 +15,8 @@ const localesMap = loadLocalesMap(modules);
  * @param lang
  */
 async function loadMessages(lang: SupportedLanguagesType) {
-  const appLocaleMessages = await localesMap[lang]();
-  return appLocaleMessages.default;
+  const appLocaleMessages = await localesMap[lang]?.();
+  return appLocaleMessages?.default;
 }
 
 async function setupI18n(app: App, options: LocaleSetupOptions = {}) {

+ 0 - 2
docs/src/guide/essentials/icons.md

@@ -74,7 +74,5 @@ import { SvgTestIcon } from '@vben/icons';
 直接添加 Tailwind CSS 的图标类名即可使用,图标类名可查看 [iconify](https://github.com/iconify/iconify) :
 
 ```vue
-
 <span class="icon-[mdi--ab-testing]"></span>
-
 ```

+ 3 - 0
internal/tsconfig/base.json

@@ -5,6 +5,7 @@
     "composite": false,
     "target": "ESNext",
 
+    "moduleDetection": "force",
     "experimentalDecorators": true,
 
     "baseUrl": ".",
@@ -19,6 +20,7 @@
     "noImplicitAny": true,
     "noImplicitOverride": true,
     "noImplicitThis": true,
+    "noUncheckedIndexedAccess": true,
     "noUnusedLocals": true,
     "noUnusedParameters": true,
 
@@ -30,6 +32,7 @@
     "esModuleInterop": true,
     "forceConsistentCasingInFileNames": true,
     "isolatedModules": true,
+    "verbatimModuleSyntax": true,
     "skipLibCheck": true,
     "preserveWatchOutput": true
   },

+ 11 - 9
packages/@core/base/shared/src/colorful/generator.ts

@@ -22,17 +22,19 @@ function generatorColorVariables(colorItems: ColorItem[]) {
       colorKeys.forEach((key) => {
         const colorValue = colorsMap[key];
 
-        const hslColor = convertToHslCssVar(colorValue);
-        colorVariables[`--${name}-${key}`] = hslColor;
-        if (alias) {
-          colorVariables[`--${alias}-${key}`] = hslColor;
-        }
-
-        if (key === '500') {
-          mainColor = hslColor;
+        if (colorValue) {
+          const hslColor = convertToHslCssVar(colorValue);
+          colorVariables[`--${name}-${key}`] = hslColor;
+          if (alias) {
+            colorVariables[`--${alias}-${key}`] = hslColor;
+          }
+
+          if (key === '500') {
+            mainColor = hslColor;
+          }
         }
       });
-      if (alias) {
+      if (alias && mainColor) {
         colorVariables[`--${alias}`] = mainColor;
       }
     }

+ 3 - 4
packages/@core/preferences/src/update-css-variables.ts

@@ -89,10 +89,9 @@ function updateMainColorVariables(preference: Preferences) {
   ]);
 
   if (colorPrimary) {
-    document.documentElement.style.setProperty(
-      '--primary',
-      colorVariables['--primary-500'],
-    );
+    const mainColor = colorVariables['--primary-500'];
+    mainColor &&
+      document.documentElement.style.setProperty('--primary', mainColor);
   }
 
   if (colorVariables['--green-500']) {

+ 2 - 1
packages/@core/ui-kit/layout-ui/src/vben-layout.vue

@@ -1,4 +1,6 @@
 <script setup lang="ts">
+import type { VbenLayoutProps } from './vben-layout';
+
 import type { CSSProperties } from 'vue';
 import { computed, ref, watch } from 'vue';
 
@@ -11,7 +13,6 @@ import {
   LayoutSidebar,
   LayoutTabbar,
 } from './components';
-import { VbenLayoutProps } from './vben-layout';
 
 interface Props extends VbenLayoutProps {}
 

+ 4 - 2
packages/@core/ui-kit/menu-ui/src/components/menu.vue

@@ -1,4 +1,6 @@
 <script lang="ts" setup>
+import type { UseResizeObserverReturn } from '@vueuse/core';
+
 import type {
   MenuItemClicked,
   MenuItemRegistered,
@@ -22,7 +24,7 @@ import { useNamespace } from '@vben-core/composables';
 import { Ellipsis } from '@vben-core/icons';
 import { isHttpUrl } from '@vben-core/shared';
 
-import { useResizeObserver, UseResizeObserverReturn } from '@vueuse/core';
+import { useResizeObserver } from '@vueuse/core';
 
 import {
   createMenuContext,
@@ -273,7 +275,7 @@ function close(path: string) {
  */
 function closeMenu(path: string, parentPaths: string[]) {
   if (props.accordion) {
-    openedMenus.value = subMenus.value[path]?.parentPaths;
+    openedMenus.value = subMenus.value[path]?.parentPaths ?? [];
   }
 
   close(path);

+ 2 - 1
packages/@core/ui-kit/menu-ui/src/hooks/use-menu.ts

@@ -1,6 +1,7 @@
+import type { SubMenuProvider } from '../interface';
+
 import { computed, getCurrentInstance } from 'vue';
 
-import { SubMenuProvider } from '../interface';
 import { findComponentUpward } from '../utils';
 
 function useMenu() {

+ 2 - 1
packages/@core/ui-kit/menu-ui/src/menu.vue

@@ -1,10 +1,11 @@
 <script setup lang="ts">
 import type { MenuRecordRaw } from '@vben-core/typings';
 
+import type { MenuProps } from './interface';
+
 import { useForwardProps } from '@vben-core/composables';
 
 import { Menu } from './components';
-import { MenuProps } from './interface';
 import SubMenu from './sub-menu.vue';
 
 interface Props extends MenuProps {

+ 2 - 1
packages/@core/ui-kit/shadcn-ui/src/components/button/icon-button.vue

@@ -1,8 +1,9 @@
 <script setup lang="ts">
+import type { ButtonVariants } from '@vben-core/shadcn-ui/components/ui/button';
+
 import { computed, type HTMLAttributes, useSlots } from 'vue';
 
 import { VbenTooltip } from '@vben-core/shadcn-ui/components/tooltip';
-import { ButtonVariants } from '@vben-core/shadcn-ui/components/ui/button';
 import { cn } from '@vben-core/shared';
 
 import { type PrimitiveProps } from 'radix-vue';

+ 1 - 1
packages/@core/ui-kit/shadcn-ui/src/components/count-to-animator/count-to-animator.vue

@@ -94,7 +94,7 @@ function formatNumber(num: number | string) {
   const x2 = x.length > 1 ? decimal + x[1] : '';
 
   const rgx = /(\d+)(\d{3})/;
-  if (separator && !isNumber(separator)) {
+  if (separator && !isNumber(separator) && x1) {
     while (rgx.test(x1)) {
       x1 = x1.replace(rgx, `$1${separator}$2`);
     }

+ 8 - 3
packages/@core/ui-kit/shadcn-ui/src/components/hover-card/hover-card.vue

@@ -1,7 +1,12 @@
 <script setup lang="ts">
-import type { HoverCardRootEmits, HoverCardRootProps } from 'radix-vue';
+import type {
+  HoverCardContentProps,
+  HoverCardRootEmits,
+  HoverCardRootProps,
+} from 'radix-vue';
 
-import { computed, HTMLAttributes } from 'vue';
+import type { HTMLAttributes } from 'vue';
+import { computed } from 'vue';
 
 import {
   HoverCard,
@@ -9,7 +14,7 @@ import {
   HoverCardTrigger,
 } from '@vben-core/shadcn-ui/components/ui/hover-card';
 
-import { HoverCardContentProps, useForwardPropsEmits } from 'radix-vue';
+import { useForwardPropsEmits } from 'radix-vue';
 
 const props = defineProps<
   {

+ 2 - 1
packages/@core/ui-kit/shadcn-ui/src/components/popover/popover.vue

@@ -5,7 +5,8 @@ import type {
   PopoverRootProps,
 } from 'radix-vue';
 
-import { computed, HTMLAttributes } from 'vue';
+import type { HTMLAttributes } from 'vue';
+import { computed } from 'vue';
 
 import {
   PopoverContent,

+ 4 - 1
packages/@core/ui-kit/shadcn-ui/src/components/render-content/render-content.vue

@@ -6,7 +6,10 @@ defineOptions({
 });
 
 const props = withDefaults(
-  defineProps<{ content: Component | string; props?: Record<string, any> }>(),
+  defineProps<{
+    content: Component | string | undefined;
+    props?: Record<string, any>;
+  }>(),
   {
     props: () => ({}),
   },

+ 2 - 2
packages/@core/ui-kit/shadcn-ui/src/components/tooltip/tooltip.vue

@@ -1,4 +1,6 @@
 <script setup lang="ts">
+import type { TooltipContentProps } from 'radix-vue';
+
 import type { HTMLAttributes } from 'vue';
 
 import {
@@ -8,8 +10,6 @@ import {
   TooltipTrigger,
 } from '@vben-core/shadcn-ui/components/ui/tooltip';
 
-import { TooltipContentProps } from 'radix-vue';
-
 interface Props {
   contentClass?: HTMLAttributes['class'];
   delayDuration?: number;

+ 3 - 2
packages/@core/ui-kit/tabs-ui/src/components/tabs/tabs.vue

@@ -1,11 +1,12 @@
 <script lang="ts" setup>
+import type { TabDefinition } from '@vben-core/typings';
+
 import type { TabConfig, TabsProps } from '../../types';
 
 import { computed, watch } from 'vue';
 
 import { MdiPin, X } from '@vben-core/icons';
 import { VbenContextMenu, VbenIcon, VbenScrollbar } from '@vben-core/shadcn-ui';
-import { TabDefinition } from '@vben-core/typings';
 
 interface Props extends TabsProps {}
 
@@ -37,7 +38,7 @@ const typeWithClass = computed(() => {
     },
   };
 
-  return typeClasses[props.styleType || 'plain'];
+  return typeClasses[props.styleType || 'plain'] || { content: '' };
 });
 
 const tabsView = computed((): TabConfig[] => {

+ 2 - 1
packages/@core/ui-kit/tabs-ui/src/tabs-view.vue

@@ -2,12 +2,13 @@
 import type { Sortable } from '@vben-core/composables';
 import type { TabDefinition } from '@vben-core/typings';
 
+import type { TabsProps } from './types';
+
 import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
 
 import { useForwardPropsEmits, useSortable } from '@vben-core/composables';
 
 import { Tabs, TabsChrome } from './components';
-import { TabsProps } from './types';
 
 interface Props extends TabsProps {}
 

+ 1 - 1
packages/effects/access/src/accessible.ts

@@ -71,7 +71,7 @@ async function generateRoutes(
     const firstChild = route.children[0];
 
     // 如果子路由不是以/开头,则直接返回,这种情况需要计算全部父级的path才能得出正确的path,这里不做处理
-    if (!firstChild.path || !firstChild.path.startsWith('/')) {
+    if (!firstChild?.path || !firstChild.path.startsWith('/')) {
       return route;
     }
 

+ 2 - 1
packages/effects/common-ui/src/authentication/login-expired-modal.vue

@@ -1,4 +1,6 @@
 <script setup lang="ts">
+import type { AuthenticationProps, LoginAndRegisterParams } from './typings';
+
 import { useForwardPropsEmits } from '@vben/hooks';
 import {
   Dialog,
@@ -10,7 +12,6 @@ import {
 } from '@vben-core/shadcn-ui';
 
 import AuthenticationLogin from './login.vue';
-import { AuthenticationProps, LoginAndRegisterParams } from './typings';
 
 interface Props extends AuthenticationProps {
   avatar?: string;

+ 2 - 1
packages/effects/common-ui/src/authentication/login.vue

@@ -1,4 +1,6 @@
 <script setup lang="ts">
+import type { AuthenticationProps, LoginEmits } from './typings';
+
 import { computed, reactive } from 'vue';
 import { useRouter } from 'vue-router';
 
@@ -12,7 +14,6 @@ import {
 
 import Title from './auth-title.vue';
 import ThirdPartyLogin from './third-party-login.vue';
-import { AuthenticationProps, LoginEmits } from './typings';
 
 interface Props extends AuthenticationProps {}
 

+ 1 - 1
packages/effects/common-ui/src/dashboard/analysis/analysis-charts-tabs.vue

@@ -18,7 +18,7 @@ const props = withDefaults(defineProps<Props>(), {
 });
 
 const defaultValue = computed(() => {
-  return props.tabs?.[0].value;
+  return props.tabs?.[0]?.value;
 });
 </script>
 

+ 2 - 1
packages/effects/layouts/src/basic/layout.vue

@@ -1,4 +1,6 @@
 <script lang="ts" setup>
+import type { MenuRecordRaw } from '@vben/types';
+
 import { computed, watch } from 'vue';
 
 import { useWatermark } from '@vben/hooks';
@@ -9,7 +11,6 @@ import {
   usePreferences,
 } from '@vben/preferences';
 import { useLockStore, useUserStore } from '@vben/stores';
-import { MenuRecordRaw } from '@vben/types';
 import { mapTree } from '@vben/utils';
 import { VbenAdminLayout } from '@vben-core/layout-ui';
 import { Toaster, VbenBackTop, VbenLogo } from '@vben-core/shadcn-ui';

+ 2 - 1
packages/effects/layouts/src/basic/menu/extra-menu.vue

@@ -1,9 +1,10 @@
 <script lang="ts" setup>
 import type { MenuRecordRaw } from '@vben/types';
+import type { MenuProps } from '@vben-core/menu-ui';
 
 import { useRoute } from 'vue-router';
 
-import { Menu, MenuProps } from '@vben-core/menu-ui';
+import { Menu } from '@vben-core/menu-ui';
 
 import { useNavigation } from './use-navigation';
 

+ 2 - 1
packages/effects/layouts/src/basic/menu/menu.vue

@@ -1,7 +1,8 @@
 <script lang="ts" setup>
 import type { MenuRecordRaw } from '@vben/types';
+import type { MenuProps } from '@vben-core/menu-ui';
 
-import { Menu, MenuProps } from '@vben-core/menu-ui';
+import { Menu } from '@vben-core/menu-ui';
 
 interface Props extends MenuProps {
   menus?: MenuRecordRaw[];

+ 1 - 1
packages/effects/layouts/src/widgets/global-search/global-search.vue

@@ -49,7 +49,7 @@ function handleClose() {
 
 const keys = useMagicKeys();
 const cmd = isWindowsOs() ? keys['ctrl+k'] : keys['cmd+k'];
-whenever(cmd, () => {
+whenever(cmd!, () => {
   if (props.enableShortcutKey) {
     open.value = true;
   }

+ 6 - 4
packages/effects/layouts/src/widgets/global-search/search-panel.vue

@@ -95,10 +95,12 @@ async function handleEnter() {
     return;
   }
   const to = result[index];
-  searchHistory.value.push(to);
-  handleClose();
-  await nextTick();
-  router.push(to.path);
+  if (to) {
+    searchHistory.value.push(to);
+    handleClose();
+    await nextTick();
+    router.push(to.path);
+  }
 }
 
 // Arrow key up

+ 2 - 1
packages/effects/layouts/src/widgets/preferences/blocks/layout/tabbar.vue

@@ -1,8 +1,9 @@
 <script setup lang="ts">
+import type { SelectOption } from '@vben/types';
+
 import { computed } from 'vue';
 
 import { $t } from '@vben/locales';
-import { SelectOption } from '@vben/types';
 
 import SelectItem from '../select-item.vue';
 import SwitchItem from '../switch-item.vue';

+ 3 - 3
packages/effects/layouts/src/widgets/user-dropdown/user-dropdown.vue

@@ -126,19 +126,19 @@ function handleSubmitLogout() {
 
 if (enableShortcutKey.value) {
   const keys = useMagicKeys();
-  whenever(keys['Alt+KeyQ'], () => {
+  whenever(keys['Alt+KeyQ']!, () => {
     if (enableLogoutShortcutKey.value) {
       handleLogout();
     }
   });
 
-  whenever(keys['Alt+Comma'], () => {
+  whenever(keys['Alt+Comma']!, () => {
     if (enablePreferencesShortcutKey.value) {
       handleOpenPreference();
     }
   });
 
-  whenever(keys['Alt+KeyL'], () => {
+  whenever(keys['Alt+KeyL']!, () => {
     if (enableLockScreenShortcutKey.value) {
       handleOpenLock();
     }

+ 2 - 2
packages/effects/request/src/request-client/modules/interceptor.ts

@@ -1,7 +1,7 @@
-import {
+import type {
   AxiosInstance,
   AxiosResponse,
-  type InternalAxiosRequestConfig,
+  InternalAxiosRequestConfig,
 } from 'axios';
 
 const errorHandler = (res: Error) => Promise.reject(res);

+ 4 - 2
packages/locales/src/i18n.ts

@@ -58,9 +58,11 @@ async function loadI18nMessages(lang: SupportedLanguagesType) {
     return setI18nLanguage(lang);
   }
 
-  const message = await localesMap[lang]();
+  const message = await localesMap[lang]?.();
 
-  i18n.global.setLocaleMessage(lang, message.default);
+  if (message?.default) {
+    i18n.global.setLocaleMessage(lang, message.default);
+  }
   loadedLanguages.add(lang);
   return setI18nLanguage(lang);
 }

+ 1 - 1
packages/locales/src/typing.ts

@@ -4,7 +4,7 @@ export type ImportLocaleFn = () => Promise<{ default: Record<string, string> }>;
 
 export type LoadMessageFn = (
   lang: SupportedLanguagesType,
-) => Promise<Record<string, string>>;
+) => Promise<Record<string, string> | undefined>;
 
 export interface LocaleSetupOptions {
   /**

+ 11 - 3
packages/stores/src/modules/tabbar.ts

@@ -70,7 +70,9 @@ export const useTabbarStore = defineStore('core-tabbar', {
         return;
       }
       const firstTab = this.getTabs[0];
-      await this._goToTab(firstTab, router);
+      if (firstTab) {
+        await this._goToTab(firstTab, router);
+      }
     },
     /**
      * @zh_CN 跳转到标签页
@@ -122,7 +124,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
         // 页面已经存在,不重复添加选项卡,只更新选项卡参数
         const currentTab = toRaw(this.tabs)[tabIndex];
         const mergedTab = { ...currentTab, ...tab };
-        if (Reflect.has(currentTab.meta, 'affixTab')) {
+        if (currentTab && Reflect.has(currentTab.meta, 'affixTab')) {
           mergedTab.meta.affixTab = currentTab.meta.affixTab;
         }
         this.tabs.splice(tabIndex, 1, mergedTab);
@@ -248,7 +250,10 @@ export const useTabbarStore = defineStore('core-tabbar', {
         return;
       }
 
-      await this.closeTab(this.tabs[index], router);
+      const tab = this.tabs[index];
+      if (tab) {
+        await this.closeTab(tab, router);
+      }
     },
 
     /**
@@ -359,6 +364,9 @@ export const useTabbarStore = defineStore('core-tabbar', {
      */
     async sortTabs(oldIndex: number, newIndex: number) {
       const currentTab = this.tabs[oldIndex];
+      if (!currentTab) {
+        return;
+      }
       this.tabs.splice(oldIndex, 1);
       this.tabs.splice(newIndex, 0, currentTab);
       this.dragEndIndex = this.dragEndIndex + 1;

+ 4 - 4
packages/utils/src/helpers/generate-routes-backend.ts

@@ -1,11 +1,11 @@
-import type { RouteRecordRaw } from 'vue-router';
-
-import { mapTree } from '@vben-core/shared';
-import {
+import type {
   ComponentRecordType,
   GenerateMenuAndRoutesOptions,
   RouteRecordStringComponent,
 } from '@vben-core/typings';
+import type { RouteRecordRaw } from 'vue-router';
+
+import { mapTree } from '@vben-core/shared';
 
 /**
  * 动态生成路由 - 后端方式