perf: enable strict ts type checking (#4045)

pull/48/MERGE
Vben 2024-08-05 21:12:22 +08:00 committed by GitHub
parent e5ec8e6b51
commit 4f5783d00b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 124 additions and 76 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -58,9 +58,11 @@ async function loadI18nMessages(lang: SupportedLanguagesType) {
return setI18nLanguage(lang); 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); loadedLanguages.add(lang);
return setI18nLanguage(lang); return setI18nLanguage(lang);
} }

View File

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

View File

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

View File

@ -1,11 +1,11 @@
import type { RouteRecordRaw } from 'vue-router'; import type {
import { mapTree } from '@vben-core/shared';
import {
ComponentRecordType, ComponentRecordType,
GenerateMenuAndRoutesOptions, GenerateMenuAndRoutesOptions,
RouteRecordStringComponent, RouteRecordStringComponent,
} from '@vben-core/typings'; } from '@vben-core/typings';
import type { RouteRecordRaw } from 'vue-router';
import { mapTree } from '@vben-core/shared';
/** /**
* - * -