feat: restore original admin shell quality
This commit is contained in:
@@ -27,6 +27,9 @@ const UserDropdown = defineAsyncComponent(() =>
|
|||||||
(module) => module.UserDropdown,
|
(module) => module.UserDropdown,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
const LockScreen = defineAsyncComponent(() =>
|
||||||
|
import('@vben/layouts/es/lock-screen').then((module) => module.LockScreen),
|
||||||
|
);
|
||||||
const NotificationPopup = defineAsyncComponent(
|
const NotificationPopup = defineAsyncComponent(
|
||||||
() => import('#/components/notification/NotificationPopup.vue'),
|
() => import('#/components/notification/NotificationPopup.vue'),
|
||||||
);
|
);
|
||||||
@@ -227,7 +230,7 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<BasicLayout>
|
<BasicLayout @clear-preferences-and-logout="handleLogout">
|
||||||
<template #user-dropdown>
|
<template #user-dropdown>
|
||||||
<UserDropdown
|
<UserDropdown
|
||||||
:avatar
|
:avatar
|
||||||
@@ -286,5 +289,8 @@ watch(
|
|||||||
<LoginForm />
|
<LoginForm />
|
||||||
</AuthenticationLoginExpiredModal>
|
</AuthenticationLoginExpiredModal>
|
||||||
</template>
|
</template>
|
||||||
|
<template #lock-screen>
|
||||||
|
<LockScreen :avatar @to-login="handleLogout" />
|
||||||
|
</template>
|
||||||
</BasicLayout>
|
</BasicLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ export const overridesPreferences = defineOverridesPreferences({
|
|||||||
layout: 'header-sidebar-nav',
|
layout: 'header-sidebar-nav',
|
||||||
},
|
},
|
||||||
shortcutKeys: {
|
shortcutKeys: {
|
||||||
enable: false,
|
enable: true,
|
||||||
globalLockScreen: false,
|
globalLockScreen: false,
|
||||||
globalLogout: true,
|
globalLogout: true,
|
||||||
globalPreferences: false,
|
globalPreferences: false,
|
||||||
globalSearch: false,
|
globalSearch: true,
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
mode: 'light',
|
mode: 'light',
|
||||||
@@ -46,6 +46,9 @@ export const overridesPreferences = defineOverridesPreferences({
|
|||||||
fit: 'contain',
|
fit: 'contain',
|
||||||
source: Logo,
|
source: Logo,
|
||||||
},
|
},
|
||||||
|
tabbar: {
|
||||||
|
persist: false,
|
||||||
|
},
|
||||||
widget: {
|
widget: {
|
||||||
fullscreen: true,
|
fullscreen: true,
|
||||||
globalSearch: true,
|
globalSearch: true,
|
||||||
|
|||||||
@@ -12,6 +12,16 @@ import { useAppContextStore } from '#/store/app-context';
|
|||||||
import { normalizeHomePath } from '#/utils/legacy-home';
|
import { normalizeHomePath } from '#/utils/legacy-home';
|
||||||
|
|
||||||
import { generateAccess } from './access';
|
import { generateAccess } from './access';
|
||||||
|
import { isLightTabRoute } from './light-menu';
|
||||||
|
|
||||||
|
function filterLightTabHistory<T extends { tabs?: unknown[] }>(history: T) {
|
||||||
|
const tabs = Array.isArray(history.tabs) ? history.tabs : [];
|
||||||
|
return {
|
||||||
|
...history,
|
||||||
|
cachedTabs: [],
|
||||||
|
tabs: tabs.filter((tab) => isLightTabRoute(tab as any)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用守卫配置
|
* 通用守卫配置
|
||||||
@@ -39,10 +49,10 @@ function setupCommonGuard(router: Router) {
|
|||||||
|
|
||||||
// 保存当前应用的 tab 历史到内存
|
// 保存当前应用的 tab 历史到内存
|
||||||
const currentAppKey = currentAppCode || 'main';
|
const currentAppKey = currentAppCode || 'main';
|
||||||
tabHistoryByApp.set(currentAppKey, {
|
tabHistoryByApp.set(currentAppKey, filterLightTabHistory({
|
||||||
tabs: [...tabbarStore.tabs],
|
tabs: [...tabbarStore.tabs],
|
||||||
cachedTabs: new Set(tabbarStore.cachedTabs),
|
cachedTabs: new Set(tabbarStore.cachedTabs),
|
||||||
});
|
}));
|
||||||
|
|
||||||
// 从 sessionStorage 加载新应用的 tab 历史
|
// 从 sessionStorage 加载新应用的 tab 历史
|
||||||
const storageKey = `vben-admin-tabs-${appKey}`;
|
const storageKey = `vben-admin-tabs-${appKey}`;
|
||||||
@@ -51,8 +61,9 @@ function setupCommonGuard(router: Router) {
|
|||||||
if (savedHistory) {
|
if (savedHistory) {
|
||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(savedHistory);
|
const parsed = JSON.parse(savedHistory);
|
||||||
tabbarStore.tabs = parsed.tabs || [];
|
const lightHistory = filterLightTabHistory(parsed);
|
||||||
tabbarStore.cachedTabs = new Set(parsed.cachedTabs || []);
|
tabbarStore.tabs = lightHistory.tabs || [];
|
||||||
|
tabbarStore.cachedTabs = new Set(lightHistory.cachedTabs || []);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to parse tab history:', error);
|
console.error('Failed to parse tab history:', error);
|
||||||
tabbarStore.tabs = [];
|
tabbarStore.tabs = [];
|
||||||
@@ -87,10 +98,12 @@ function setupCommonGuard(router: Router) {
|
|||||||
const storageKey = `vben-admin-tabs-${appKey}`;
|
const storageKey = `vben-admin-tabs-${appKey}`;
|
||||||
|
|
||||||
const tabbarStore = useTabbarStore();
|
const tabbarStore = useTabbarStore();
|
||||||
const tabHistory = {
|
const tabHistory = filterLightTabHistory({
|
||||||
tabs: tabbarStore.tabs,
|
tabs: tabbarStore.tabs,
|
||||||
cachedTabs: [...tabbarStore.cachedTabs],
|
cachedTabs: [...tabbarStore.cachedTabs],
|
||||||
};
|
});
|
||||||
|
tabbarStore.tabs = tabHistory.tabs as any;
|
||||||
|
tabbarStore.cachedTabs = new Set(tabHistory.cachedTabs as string[]);
|
||||||
sessionStorage.setItem(storageKey, JSON.stringify(tabHistory));
|
sessionStorage.setItem(storageKey, JSON.stringify(tabHistory));
|
||||||
|
|
||||||
// 关闭页面加载进度条
|
// 关闭页面加载进度条
|
||||||
|
|||||||
@@ -31,10 +31,65 @@ export const LIGHT_MENU_NAMES = new Set([
|
|||||||
'userSettings',
|
'userSettings',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const LIGHT_ROUTE_PATH_PREFIXES = [
|
||||||
|
'/account-settings',
|
||||||
|
'/ai-platform/agent',
|
||||||
|
'/ai-platform/knowledge',
|
||||||
|
'/ai-platform/model',
|
||||||
|
'/ai-platform/workflow',
|
||||||
|
'/ai-platform/workflow-runs',
|
||||||
|
'/announcement',
|
||||||
|
'/codex',
|
||||||
|
'/dept',
|
||||||
|
'/dict',
|
||||||
|
'/file-manager',
|
||||||
|
'/login-log',
|
||||||
|
'/menu',
|
||||||
|
'/message',
|
||||||
|
'/page-render/main_home',
|
||||||
|
'/permission',
|
||||||
|
'/post',
|
||||||
|
'/role',
|
||||||
|
'/server-monitor',
|
||||||
|
'/system-config',
|
||||||
|
'/ui-config',
|
||||||
|
'/user',
|
||||||
|
];
|
||||||
|
|
||||||
export function isLightMenuName(name?: string) {
|
export function isLightMenuName(name?: string) {
|
||||||
return !name || LIGHT_MENU_NAMES.has(name);
|
return !name || LIGHT_MENU_NAMES.has(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizePath(path?: string) {
|
||||||
|
if (!path) return '';
|
||||||
|
return path.split('?')[0]?.replace(/\/$/, '') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isLightTabRoute(route: {
|
||||||
|
fullPath?: string;
|
||||||
|
matched?: Array<{ name?: unknown; path?: string }>;
|
||||||
|
name?: unknown;
|
||||||
|
path?: string;
|
||||||
|
}) {
|
||||||
|
if (typeof route.name === 'string' && LIGHT_MENU_NAMES.has(route.name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
route.matched?.some(
|
||||||
|
(item) =>
|
||||||
|
typeof item.name === 'string' && LIGHT_MENU_NAMES.has(item.name),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = normalizePath(route.fullPath || route.path);
|
||||||
|
return LIGHT_ROUTE_PATH_PREFIXES.some(
|
||||||
|
(prefix) => path === prefix || path.startsWith(`${prefix}/`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function filterLightMenuTree<
|
export function filterLightMenuTree<
|
||||||
T extends { children?: T[]; name?: string },
|
T extends { children?: T[]; name?: string },
|
||||||
>(routes: T[]): T[] {
|
>(routes: T[]): T[] {
|
||||||
|
|||||||
@@ -111,6 +111,13 @@ class PreferenceManager {
|
|||||||
mergedPreference.widget,
|
mergedPreference.widget,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (overrides?.tabbar) {
|
||||||
|
mergedPreference.tabbar = merge(
|
||||||
|
{},
|
||||||
|
overrides.tabbar,
|
||||||
|
mergedPreference.tabbar,
|
||||||
|
);
|
||||||
|
}
|
||||||
if (overrides?.logo?.source) {
|
if (overrides?.logo?.source) {
|
||||||
mergedPreference.logo.source = overrides.logo.source;
|
mergedPreference.logo.source = overrides.logo.source;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, defineAsyncComponent, useSlots } from 'vue';
|
import { computed, useSlots } from 'vue';
|
||||||
|
|
||||||
import { preferences } from '@vben/preferences';
|
import { useRefresh } from '@vben/hooks';
|
||||||
|
import { RotateCw } from '@vben/icons';
|
||||||
|
import { preferences, usePreferences } from '@vben/preferences';
|
||||||
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
|
||||||
const ThemeToggle = defineAsyncComponent(
|
import { VbenFullScreen, VbenIconButton } from '@vben-core/shadcn-ui';
|
||||||
() => import('../../widgets/theme-toggle/theme-toggle.vue'),
|
|
||||||
);
|
import {
|
||||||
|
GlobalSearch,
|
||||||
|
LanguageToggle,
|
||||||
|
PreferencesButton,
|
||||||
|
ThemeToggle,
|
||||||
|
TimezoneButton,
|
||||||
|
} from '../../widgets';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/**
|
||||||
@@ -22,19 +31,55 @@ withDefaults(defineProps<Props>(), {
|
|||||||
theme: 'light',
|
theme: 'light',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{ clearPreferencesAndLogout: [] }>();
|
||||||
|
|
||||||
const REFERENCE_VALUE = 50;
|
const REFERENCE_VALUE = 50;
|
||||||
|
|
||||||
|
const accessStore = useAccessStore();
|
||||||
const slots = useSlots();
|
const slots = useSlots();
|
||||||
|
const { refresh } = useRefresh();
|
||||||
|
const { globalSearchShortcutKey, preferencesButtonPosition } =
|
||||||
|
usePreferences();
|
||||||
|
|
||||||
const rightSlots = computed(() => {
|
const rightSlots = computed(() => {
|
||||||
const list = [{ index: REFERENCE_VALUE + 100, name: 'user-dropdown' }];
|
const list = [{ index: REFERENCE_VALUE + 100, name: 'user-dropdown' }];
|
||||||
|
|
||||||
|
if (preferences.widget.globalSearch) {
|
||||||
|
list.push({
|
||||||
|
index: REFERENCE_VALUE,
|
||||||
|
name: 'global-search',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (preferencesButtonPosition.value.header) {
|
||||||
|
list.push({
|
||||||
|
index: REFERENCE_VALUE + 10,
|
||||||
|
name: 'preferences',
|
||||||
|
});
|
||||||
|
}
|
||||||
if (preferences.widget.themeToggle) {
|
if (preferences.widget.themeToggle) {
|
||||||
list.push({
|
list.push({
|
||||||
index: REFERENCE_VALUE + 20,
|
index: REFERENCE_VALUE + 20,
|
||||||
name: 'theme-toggle',
|
name: 'theme-toggle',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (preferences.widget.languageToggle) {
|
||||||
|
list.push({
|
||||||
|
index: REFERENCE_VALUE + 30,
|
||||||
|
name: 'language-toggle',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (preferences.widget.timezone) {
|
||||||
|
list.push({
|
||||||
|
index: REFERENCE_VALUE + 40,
|
||||||
|
name: 'timezone',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (preferences.widget.fullscreen) {
|
||||||
|
list.push({
|
||||||
|
index: REFERENCE_VALUE + 50,
|
||||||
|
name: 'fullscreen',
|
||||||
|
});
|
||||||
|
}
|
||||||
if (preferences.widget.notification) {
|
if (preferences.widget.notification) {
|
||||||
list.push({
|
list.push({
|
||||||
index: REFERENCE_VALUE + 60,
|
index: REFERENCE_VALUE + 60,
|
||||||
@@ -54,6 +99,13 @@ const rightSlots = computed(() => {
|
|||||||
const leftSlots = computed(() => {
|
const leftSlots = computed(() => {
|
||||||
const list: Array<{ index: number; name: string }> = [];
|
const list: Array<{ index: number; name: string }> = [];
|
||||||
|
|
||||||
|
if (preferences.widget.refresh) {
|
||||||
|
list.push({
|
||||||
|
index: 0,
|
||||||
|
name: 'refresh',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Object.keys(slots).forEach((key) => {
|
Object.keys(slots).forEach((key) => {
|
||||||
const name = key.split('-');
|
const name = key.split('-');
|
||||||
if (key.startsWith('header-left')) {
|
if (key.startsWith('header-left')) {
|
||||||
@@ -63,6 +115,9 @@ const leftSlots = computed(() => {
|
|||||||
return list.sort((a, b) => a.index - b.index);
|
return list.sort((a, b) => a.index - b.index);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function clearPreferencesAndLogout() {
|
||||||
|
emit('clearPreferencesAndLogout');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -71,6 +126,11 @@ const leftSlots = computed(() => {
|
|||||||
:key="slot.name"
|
:key="slot.name"
|
||||||
>
|
>
|
||||||
<slot :name="slot.name">
|
<slot :name="slot.name">
|
||||||
|
<template v-if="slot.name === 'refresh'">
|
||||||
|
<VbenIconButton class="my-0 mr-1 rounded-md" @click="refresh">
|
||||||
|
<RotateCw class="size-4" />
|
||||||
|
</VbenIconButton>
|
||||||
|
</template>
|
||||||
</slot>
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
<div class="flex-center hidden lg:block">
|
<div class="flex-center hidden lg:block">
|
||||||
@@ -91,9 +151,31 @@ const leftSlots = computed(() => {
|
|||||||
<div class="flex h-full min-w-0 flex-shrink-0 items-center">
|
<div class="flex h-full min-w-0 flex-shrink-0 items-center">
|
||||||
<template v-for="slot in rightSlots" :key="slot.name">
|
<template v-for="slot in rightSlots" :key="slot.name">
|
||||||
<slot :name="slot.name">
|
<slot :name="slot.name">
|
||||||
<template v-if="slot.name === 'theme-toggle'">
|
<template v-if="slot.name === 'global-search'">
|
||||||
|
<GlobalSearch
|
||||||
|
:enable-shortcut-key="globalSearchShortcutKey"
|
||||||
|
:menus="accessStore.accessMenus"
|
||||||
|
class="mr-1 sm:mr-4"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="slot.name === 'preferences'">
|
||||||
|
<PreferencesButton
|
||||||
|
class="mr-1"
|
||||||
|
@clear-preferences-and-logout="clearPreferencesAndLogout"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="slot.name === 'theme-toggle'">
|
||||||
<ThemeToggle class="mr-1 mt-[2px]" />
|
<ThemeToggle class="mr-1 mt-[2px]" />
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="slot.name === 'language-toggle'">
|
||||||
|
<LanguageToggle class="mr-1" />
|
||||||
|
</template>
|
||||||
|
<template v-else-if="slot.name === 'fullscreen'">
|
||||||
|
<VbenFullScreen class="mr-1" />
|
||||||
|
</template>
|
||||||
|
<template v-else-if="slot.name === 'timezone'">
|
||||||
|
<TimezoneButton class="mr-1 mt-[2px]" />
|
||||||
|
</template>
|
||||||
</slot>
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ import {
|
|||||||
updatePreferences,
|
updatePreferences,
|
||||||
usePreferences,
|
usePreferences,
|
||||||
} from '@vben/preferences';
|
} from '@vben/preferences';
|
||||||
|
import { useAccessStore } from '@vben/stores';
|
||||||
import { cloneDeep, mapTree } from '@vben/utils';
|
import { cloneDeep, mapTree } from '@vben/utils';
|
||||||
|
|
||||||
import { VbenAdminLayout } from '@vben-core/layout-ui';
|
import { VbenAdminLayout } from '@vben-core/layout-ui';
|
||||||
import { VbenBackTop, VbenLogo } from '@vben-core/shadcn-ui';
|
import { VbenBackTop, VbenLogo } from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
import Breadcrumb from '../widgets/breadcrumb.vue';
|
import { Breadcrumb, CheckUpdates, Preferences } from '../widgets';
|
||||||
import { LayoutContent, LayoutContentSpinner } from './content';
|
import { LayoutContent, LayoutContentSpinner } from './content';
|
||||||
import { Copyright } from './copyright';
|
import { Copyright } from './copyright';
|
||||||
import { LayoutFooter } from './footer';
|
import { LayoutFooter } from './footer';
|
||||||
@@ -35,7 +36,7 @@ import { LayoutTabbar } from './tabbar';
|
|||||||
|
|
||||||
defineOptions({ name: 'BasicLayout' });
|
defineOptions({ name: 'BasicLayout' });
|
||||||
|
|
||||||
const emit = defineEmits<{ clickLogo: [] }>();
|
const emit = defineEmits<{ clearPreferencesAndLogout: []; clickLogo: [] }>();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isDark,
|
isDark,
|
||||||
@@ -46,9 +47,11 @@ const {
|
|||||||
isHeaderMixedNav,
|
isHeaderMixedNav,
|
||||||
isHeaderSidebarNav,
|
isHeaderSidebarNav,
|
||||||
layout,
|
layout,
|
||||||
|
preferencesButtonPosition,
|
||||||
sidebarCollapsed,
|
sidebarCollapsed,
|
||||||
theme,
|
theme,
|
||||||
} = usePreferences();
|
} = usePreferences();
|
||||||
|
const accessStore = useAccessStore();
|
||||||
const { refresh } = useRefresh();
|
const { refresh } = useRefresh();
|
||||||
|
|
||||||
const sidebarTheme = computed(() => {
|
const sidebarTheme = computed(() => {
|
||||||
@@ -144,6 +147,10 @@ function toggleSidebar() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearPreferencesAndLogout() {
|
||||||
|
emit('clearPreferencesAndLogout');
|
||||||
|
}
|
||||||
|
|
||||||
function clickLogo() {
|
function clickLogo() {
|
||||||
emit('clickLogo');
|
emit('clickLogo');
|
||||||
}
|
}
|
||||||
@@ -264,7 +271,10 @@ const headerSlots = computed(() => {
|
|||||||
</template>
|
</template>
|
||||||
<!-- 头部区域 -->
|
<!-- 头部区域 -->
|
||||||
<template #header>
|
<template #header>
|
||||||
<LayoutHeader :theme="theme">
|
<LayoutHeader
|
||||||
|
:theme="theme"
|
||||||
|
@clear-preferences-and-logout="clearPreferencesAndLogout"
|
||||||
|
>
|
||||||
<template
|
<template
|
||||||
v-if="!showHeaderNav && preferences.breadcrumb.enable"
|
v-if="!showHeaderNav && preferences.breadcrumb.enable"
|
||||||
#breadcrumb
|
#breadcrumb
|
||||||
@@ -382,6 +392,21 @@ const headerSlots = computed(() => {
|
|||||||
|
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<slot name="extra"></slot>
|
<slot name="extra"></slot>
|
||||||
|
<CheckUpdates
|
||||||
|
v-if="preferences.app.enableCheckUpdates"
|
||||||
|
:check-updates-interval="preferences.app.checkUpdatesInterval"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Transition v-if="preferences.widget.lockScreen" name="slide-up">
|
||||||
|
<slot v-if="accessStore.isLockScreen" name="lock-screen"></slot>
|
||||||
|
</Transition>
|
||||||
|
|
||||||
|
<template v-if="preferencesButtonPosition.fixed">
|
||||||
|
<Preferences
|
||||||
|
class="z-100 fixed bottom-20 right-0"
|
||||||
|
@clear-preferences-and-logout="clearPreferencesAndLogout"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
<VbenBackTop />
|
<VbenBackTop />
|
||||||
</template>
|
</template>
|
||||||
</VbenAdminLayout>
|
</VbenAdminLayout>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue';
|
import { computed, nextTick } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { useContentMaximize, useTabs } from '@vben/hooks';
|
import { useContentMaximize, useTabs } from '@vben/hooks';
|
||||||
@@ -43,7 +43,7 @@ const menus = computed(() => {
|
|||||||
|
|
||||||
// 刷新后如果不保持tab状态,关闭其他tab
|
// 刷新后如果不保持tab状态,关闭其他tab
|
||||||
if (!preferences.tabbar.persist) {
|
if (!preferences.tabbar.persist) {
|
||||||
tabbarStore.closeOtherTabs(route);
|
nextTick(() => tabbarStore.closeOtherTabs(route));
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user