perf: Improve the use of store in the app
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
import { beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import { useAccessStore } from './access';
|
||||
import { useCoreAccessStore } from './access';
|
||||
|
||||
describe('useAccessStore', () => {
|
||||
describe('useCoreAccessStore', () => {
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia());
|
||||
});
|
||||
|
||||
it('updates accessMenus state', () => {
|
||||
const store = useAccessStore();
|
||||
const store = useCoreAccessStore();
|
||||
expect(store.accessMenus).toEqual([]);
|
||||
store.setAccessMenus([{ name: 'Dashboard', path: '/dashboard' }]);
|
||||
expect(store.accessMenus).toEqual([
|
||||
@@ -18,7 +18,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('updates userInfo and userRoles state', () => {
|
||||
const store = useAccessStore();
|
||||
const store = useCoreAccessStore();
|
||||
expect(store.userInfo).toBeNull();
|
||||
expect(store.userRoles).toEqual([]);
|
||||
|
||||
@@ -30,14 +30,14 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('returns correct userInfo', () => {
|
||||
const store = useAccessStore();
|
||||
const store = useCoreAccessStore();
|
||||
const userInfo: any = { name: 'Jane Doe', roles: [{ value: 'user' }] };
|
||||
store.setUserInfo(userInfo);
|
||||
expect(store.getUserInfo).toEqual(userInfo);
|
||||
});
|
||||
|
||||
it('updates accessToken state correctly', () => {
|
||||
const store = useAccessStore();
|
||||
const store = useCoreAccessStore();
|
||||
expect(store.accessToken).toBeNull(); // 初始状态
|
||||
store.setAccessToken('abc123');
|
||||
expect(store.accessToken).toBe('abc123');
|
||||
@@ -45,7 +45,7 @@ describe('useAccessStore', () => {
|
||||
|
||||
// 测试重置用户信息时的行为
|
||||
it('clears userInfo and userRoles when setting null userInfo', () => {
|
||||
const store = useAccessStore();
|
||||
const store = useCoreAccessStore();
|
||||
store.setUserInfo({
|
||||
roles: [{ roleName: 'User', value: 'user' }],
|
||||
} as any);
|
||||
@@ -58,27 +58,27 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('returns the correct accessToken', () => {
|
||||
const store = useAccessStore();
|
||||
const store = useCoreAccessStore();
|
||||
store.setAccessToken('xyz789');
|
||||
expect(store.getAccessToken).toBe('xyz789');
|
||||
});
|
||||
|
||||
// 测试在没有用户角色时返回空数组
|
||||
it('returns an empty array for userRoles if not set', () => {
|
||||
const store = useAccessStore();
|
||||
const store = useCoreAccessStore();
|
||||
expect(store.getUserRoles).toEqual([]);
|
||||
});
|
||||
|
||||
// 测试设置空的访问菜单列表
|
||||
it('handles empty accessMenus correctly', () => {
|
||||
const store = useAccessStore();
|
||||
const store = useCoreAccessStore();
|
||||
store.setAccessMenus([]);
|
||||
expect(store.accessMenus).toEqual([]);
|
||||
});
|
||||
|
||||
// 测试设置空的访问路由列表
|
||||
it('handles empty accessRoutes correctly', () => {
|
||||
const store = useAccessStore();
|
||||
const store = useCoreAccessStore();
|
||||
store.setAccessRoutes([]);
|
||||
expect(store.accessRoutes).toEqual([]);
|
||||
});
|
||||
|
@@ -58,7 +58,7 @@ interface AccessState {
|
||||
/**
|
||||
* @zh_CN 访问权限相关
|
||||
*/
|
||||
const useAccessStore = defineStore('access', {
|
||||
const useCoreAccessStore = defineStore('core-access', {
|
||||
actions: {
|
||||
setAccessMenus(menus: MenuRecordRaw[]) {
|
||||
this.accessMenus = menus;
|
||||
@@ -72,7 +72,7 @@ const useAccessStore = defineStore('access', {
|
||||
setRefreshToken(token: AccessToken) {
|
||||
this.refreshToken = token;
|
||||
},
|
||||
setUserInfo(userInfo: BasicUserInfo) {
|
||||
setUserInfo(userInfo: BasicUserInfo | null) {
|
||||
// 设置用户信息
|
||||
this.userInfo = userInfo;
|
||||
// 设置角色信息
|
||||
@@ -105,7 +105,7 @@ const useAccessStore = defineStore('access', {
|
||||
},
|
||||
persist: {
|
||||
// 持久化
|
||||
paths: ['accessToken', 'refreshToken', 'userRoles', 'userInfo'],
|
||||
paths: ['accessToken', 'refreshToken'],
|
||||
},
|
||||
state: (): AccessState => ({
|
||||
accessMenus: [],
|
||||
@@ -120,7 +120,7 @@ const useAccessStore = defineStore('access', {
|
||||
// 解决热更新问题
|
||||
const hot = import.meta.hot;
|
||||
if (hot) {
|
||||
hot.accept(acceptHMRUpdate(useAccessStore, hot));
|
||||
hot.accept(acceptHMRUpdate(useCoreAccessStore, hot));
|
||||
}
|
||||
|
||||
export { useAccessStore };
|
||||
export { useCoreAccessStore };
|
||||
|
@@ -3,9 +3,9 @@ import { createRouter, createWebHistory } from 'vue-router';
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { useTabbarStore } from './tabbar';
|
||||
import { useCoreTabbarStore } from './tabbar';
|
||||
|
||||
describe('useAccessStore', () => {
|
||||
describe('useCoreAccessStore', () => {
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [],
|
||||
@@ -18,7 +18,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('adds a new tab', () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
const tab: any = {
|
||||
fullPath: '/home',
|
||||
meta: {},
|
||||
@@ -31,7 +31,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('adds a new tab if it does not exist', () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
const newTab: any = {
|
||||
fullPath: '/new',
|
||||
meta: {},
|
||||
@@ -43,7 +43,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('updates an existing tab instead of adding a new one', () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
const initialTab: any = {
|
||||
fullPath: '/existing',
|
||||
meta: {},
|
||||
@@ -59,7 +59,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('closes all tabs', async () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
store.tabs = [
|
||||
{ fullPath: '/home', meta: {}, name: 'Home', path: '/home' },
|
||||
] as any;
|
||||
@@ -72,7 +72,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('returns all tabs including affix tabs', () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
store.tabs = [
|
||||
{ fullPath: '/home', meta: {}, name: 'Home', path: '/home' },
|
||||
] as any;
|
||||
@@ -86,7 +86,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('closes a non-affix tab', () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
const tab: any = {
|
||||
fullPath: '/closable',
|
||||
meta: {},
|
||||
@@ -99,7 +99,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('does not close an affix tab', () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
const affixTab: any = {
|
||||
fullPath: '/affix',
|
||||
meta: { affixTab: true },
|
||||
@@ -112,14 +112,14 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('returns all cache tabs', () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
store.cacheTabs.add('Home');
|
||||
store.cacheTabs.add('About');
|
||||
expect(store.getCacheTabs).toEqual(['Home', 'About']);
|
||||
});
|
||||
|
||||
it('returns all tabs, including affix tabs', () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
const normalTab: any = {
|
||||
fullPath: '/normal',
|
||||
meta: {},
|
||||
@@ -139,7 +139,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('navigates to a specific tab', async () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
const tab: any = { meta: {}, name: 'Dashboard', path: '/dashboard' };
|
||||
|
||||
await store._goToTab(tab, router);
|
||||
@@ -152,7 +152,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('closes multiple tabs by paths', async () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
store.addTab({
|
||||
fullPath: '/home',
|
||||
meta: {},
|
||||
@@ -179,7 +179,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('closes all tabs to the left of the specified tab', async () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
store.addTab({
|
||||
fullPath: '/home',
|
||||
meta: {},
|
||||
@@ -207,7 +207,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('closes all tabs except the specified tab', async () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
store.addTab({
|
||||
fullPath: '/home',
|
||||
meta: {},
|
||||
@@ -235,7 +235,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('closes all tabs to the right of the specified tab', async () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
const targetTab: any = {
|
||||
fullPath: '/home',
|
||||
meta: {},
|
||||
@@ -263,7 +263,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('closes the tab with the specified key', async () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
const keyToClose = '/about';
|
||||
store.addTab({
|
||||
fullPath: '/home',
|
||||
@@ -293,7 +293,7 @@ describe('useAccessStore', () => {
|
||||
});
|
||||
|
||||
it('refreshes the current tab', async () => {
|
||||
const store = useTabbarStore();
|
||||
const store = useCoreTabbarStore();
|
||||
const currentTab: any = {
|
||||
fullPath: '/dashboard',
|
||||
meta: { name: 'Dashboard' },
|
||||
@@ -302,7 +302,7 @@ describe('useAccessStore', () => {
|
||||
};
|
||||
router.currentRoute.value = currentTab;
|
||||
|
||||
await store.refreshTab(router);
|
||||
await store.refresh(router);
|
||||
|
||||
expect(store.excludeCacheTabs.has('Dashboard')).toBe(false);
|
||||
expect(store.renderRouteView).toBe(true);
|
||||
|
@@ -62,7 +62,7 @@ interface TabsState {
|
||||
/**
|
||||
* @zh_CN 访问权限相关
|
||||
*/
|
||||
const useTabbarStore = defineStore('tabbar', {
|
||||
const useCoreTabbarStore = defineStore('core-tabbar', {
|
||||
actions: {
|
||||
/**
|
||||
* Close tabs in bulk
|
||||
@@ -290,7 +290,7 @@ const useTabbarStore = defineStore('tabbar', {
|
||||
/**
|
||||
* 刷新标签页
|
||||
*/
|
||||
async refreshTab(router: Router) {
|
||||
async refresh(router: Router) {
|
||||
const { currentRoute } = router;
|
||||
const { name } = currentRoute.value;
|
||||
|
||||
@@ -395,7 +395,7 @@ const useTabbarStore = defineStore('tabbar', {
|
||||
// 解决热更新问题
|
||||
const hot = import.meta.hot;
|
||||
if (hot) {
|
||||
hot.accept(acceptHMRUpdate(useTabbarStore, hot));
|
||||
hot.accept(acceptHMRUpdate(useCoreTabbarStore, hot));
|
||||
}
|
||||
|
||||
export { useTabbarStore };
|
||||
export { useCoreTabbarStore };
|
||||
|
@@ -39,10 +39,12 @@
|
||||
"@vue/shared": "^3.4.31",
|
||||
"clsx": "2.1.1",
|
||||
"defu": "^6.1.4",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"tailwind-merge": "^2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash.clonedeep": "^4.5.9",
|
||||
"@types/nprogress": "^0.2.3"
|
||||
}
|
||||
}
|
||||
|
@@ -10,3 +10,4 @@ export * from './tree';
|
||||
export * from './unique';
|
||||
export * from './update-css-variables';
|
||||
export * from './window';
|
||||
export { default as cloneDepp } from 'lodash.clonedeep';
|
||||
|
@@ -3,6 +3,8 @@ import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import type { GeneratorMenuAndRoutesOptions } from '../types';
|
||||
|
||||
import { cloneDepp } from '@vben-core/toolkit';
|
||||
|
||||
import { generateMenus } from './generate-menus';
|
||||
import { generateRoutesByBackend } from './generate-routes-backend';
|
||||
import { generateRoutesByFrontend } from './generate-routes-frontend';
|
||||
@@ -12,6 +14,8 @@ async function generateMenusAndRoutes(
|
||||
options: GeneratorMenuAndRoutesOptions,
|
||||
) {
|
||||
const { router } = options;
|
||||
|
||||
options.routes = cloneDepp(options.routes);
|
||||
// 生成路由
|
||||
const accessibleRoutes = await generateRoutes(mode, options);
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
export { default as Authority } from './authority.vue';
|
||||
export * from './generate-menu-and-routes';
|
||||
export { default as RoleAuthority } from './role-authority.vue';
|
||||
export type * from './types';
|
||||
export * from './use-access';
|
||||
|
@@ -9,15 +9,15 @@ interface Props {
|
||||
* - When the permission mode is 'backend', the value can be a code permission value.
|
||||
* @default ''
|
||||
*/
|
||||
value?: string[];
|
||||
roles?: string[];
|
||||
}
|
||||
|
||||
defineOptions({
|
||||
name: 'Authority',
|
||||
name: 'FrontendAuthority',
|
||||
});
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
value: undefined,
|
||||
roles: undefined,
|
||||
});
|
||||
</script>
|
||||
|
@@ -1,28 +1,13 @@
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { preferences } from '@vben-core/preferences';
|
||||
import { useAccessStore } from '@vben-core/stores';
|
||||
|
||||
function useAccess() {
|
||||
const accessStore = useAccessStore();
|
||||
const currentAccessMode = computed(() => {
|
||||
const accessMode = computed(() => {
|
||||
return preferences.app.accessMode;
|
||||
});
|
||||
|
||||
/**
|
||||
* 更改账号角色
|
||||
* @param roles
|
||||
*/
|
||||
async function changeRoles(roles: string[]): Promise<void> {
|
||||
if (preferences.app.accessMode !== 'frontend') {
|
||||
throw new Error(
|
||||
'The current access mode is not frontend, so the role cannot be changed',
|
||||
);
|
||||
}
|
||||
accessStore.setUserRoles(roles);
|
||||
}
|
||||
|
||||
return { changeRoles, currentAccessMode };
|
||||
return { accessMode };
|
||||
}
|
||||
|
||||
export { useAccess };
|
||||
|
@@ -3,14 +3,14 @@ import type { RouteLocationNormalizedLoaded } from 'vue-router';
|
||||
|
||||
import { preferences, usePreferences } from '@vben-core/preferences';
|
||||
import { Spinner } from '@vben-core/shadcn-ui';
|
||||
import { storeToRefs, useTabbarStore } from '@vben-core/stores';
|
||||
import { storeToRefs, useCoreTabbarStore } from '@vben-core/stores';
|
||||
|
||||
import { IFrameRouterView } from '../../iframe';
|
||||
import { useContentSpinner } from './use-content-spinner';
|
||||
|
||||
defineOptions({ name: 'LayoutContent' });
|
||||
|
||||
const tabsStore = useTabbarStore();
|
||||
const tabsStore = useCoreTabbarStore();
|
||||
const { keepAlive } = usePreferences();
|
||||
const { spinning } = useContentSpinner();
|
||||
|
||||
@@ -64,7 +64,11 @@ function getTransitionName(route: RouteLocationNormalizedLoaded) {
|
||||
:key="route.fullPath"
|
||||
/>
|
||||
</KeepAlive>
|
||||
<component :is="Component" v-else :key="route.fullPath" />
|
||||
<component
|
||||
:is="Component"
|
||||
v-else-if="renderRouteView"
|
||||
:key="route.fullPath"
|
||||
/>
|
||||
</Transition>
|
||||
</RouterView>
|
||||
</div>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
import { GlobalSearch, LanguageToggle, ThemeToggle } from '@vben/widgets';
|
||||
import { usePreferences } from '@vben-core/preferences';
|
||||
import { VbenFullScreen } from '@vben-core/shadcn-ui';
|
||||
import { useAccessStore } from '@vben-core/stores';
|
||||
import { useCoreAccessStore } from '@vben-core/stores';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
@@ -19,7 +19,7 @@ withDefaults(defineProps<Props>(), {
|
||||
theme: 'light',
|
||||
});
|
||||
|
||||
const accessStore = useAccessStore();
|
||||
const accessStore = useCoreAccessStore();
|
||||
const { globalSearchShortcutKey } = usePreferences();
|
||||
</script>
|
||||
|
||||
|
@@ -5,12 +5,12 @@ import { useRoute } from 'vue-router';
|
||||
|
||||
import { findRootMenuByPath } from '@vben-core/helpers';
|
||||
import { preferences } from '@vben-core/preferences';
|
||||
import { useAccessStore } from '@vben-core/stores';
|
||||
import { useCoreAccessStore } from '@vben-core/stores';
|
||||
|
||||
import { useNavigation } from './use-navigation';
|
||||
|
||||
function useExtraMenu() {
|
||||
const accessStore = useAccessStore();
|
||||
const accessStore = useCoreAccessStore();
|
||||
const { navigation } = useNavigation();
|
||||
|
||||
const menus = computed(() => accessStore.getAccessMenus);
|
||||
|
@@ -5,12 +5,12 @@ import { useRoute } from 'vue-router';
|
||||
|
||||
import { findRootMenuByPath } from '@vben-core/helpers';
|
||||
import { preferences, usePreferences } from '@vben-core/preferences';
|
||||
import { useAccessStore } from '@vben-core/stores';
|
||||
import { useCoreAccessStore } from '@vben-core/stores';
|
||||
|
||||
import { useNavigation } from './use-navigation';
|
||||
|
||||
function useMixedMenu() {
|
||||
const accessStore = useAccessStore();
|
||||
const accessStore = useCoreAccessStore();
|
||||
const { navigation } = useNavigation();
|
||||
const route = useRoute();
|
||||
const splitSideMenus = ref<MenuRecordRaw[]>([]);
|
||||
|
@@ -19,14 +19,18 @@ import {
|
||||
MdiPin,
|
||||
MdiPinOff,
|
||||
} from '@vben-core/iconify';
|
||||
import { storeToRefs, useAccessStore, useTabbarStore } from '@vben-core/stores';
|
||||
import {
|
||||
storeToRefs,
|
||||
useCoreAccessStore,
|
||||
useCoreTabbarStore,
|
||||
} from '@vben-core/stores';
|
||||
import { filterTree } from '@vben-core/toolkit';
|
||||
|
||||
function useTabs() {
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const accessStore = useAccessStore();
|
||||
const tabsStore = useTabbarStore();
|
||||
const accessStore = useCoreAccessStore();
|
||||
const tabbarStore = useCoreTabbarStore();
|
||||
const { accessMenus } = storeToRefs(accessStore);
|
||||
|
||||
const currentActive = computed(() => {
|
||||
@@ -35,7 +39,7 @@ function useTabs() {
|
||||
|
||||
const { locale } = useI18n();
|
||||
const currentTabs = ref<RouteLocationNormalizedGeneric[]>();
|
||||
watch([() => tabsStore.getTabs, () => locale.value], ([tabs, _]) => {
|
||||
watch([() => tabbarStore.getTabs, () => locale.value], ([tabs, _]) => {
|
||||
currentTabs.value = tabs.map((item) => wrapperTabLocale(item));
|
||||
});
|
||||
|
||||
@@ -46,7 +50,7 @@ function useTabs() {
|
||||
const affixTabs = filterTree(router.getRoutes(), (route) => {
|
||||
return !!route.meta?.affixTab;
|
||||
});
|
||||
tabsStore.setAffixTabs(affixTabs);
|
||||
tabbarStore.setAffixTabs(affixTabs);
|
||||
};
|
||||
|
||||
// 点击tab,跳转路由
|
||||
@@ -56,7 +60,7 @@ function useTabs() {
|
||||
|
||||
// 关闭tab
|
||||
const handleClose = async (key: string) => {
|
||||
await tabsStore.closeTabByKey(key, router);
|
||||
await tabbarStore.closeTabByKey(key, router);
|
||||
};
|
||||
|
||||
function wrapperTabLocale(tab: RouteLocationNormalizedGeneric) {
|
||||
@@ -80,14 +84,14 @@ function useTabs() {
|
||||
watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
tabsStore.addTab(route as RouteLocationNormalized);
|
||||
tabbarStore.addTab(route as RouteLocationNormalized);
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
const createContextMenus = (tab: TabItem) => {
|
||||
const tabs = tabsStore.getTabs;
|
||||
const affixTabs = tabsStore.affixTabs;
|
||||
const tabs = tabbarStore.getTabs;
|
||||
const affixTabs = tabbarStore.affixTabs;
|
||||
const index = tabs.findIndex((item) => item.path === tab.path);
|
||||
|
||||
const disabled = tabs.length <= 1;
|
||||
@@ -109,7 +113,7 @@ function useTabs() {
|
||||
{
|
||||
disabled: !isCurrentTab,
|
||||
handler: async () => {
|
||||
await tabsStore.refreshTab(router);
|
||||
await tabbarStore.refresh(router);
|
||||
},
|
||||
icon: IcRoundRefresh,
|
||||
key: 'reload',
|
||||
@@ -118,7 +122,7 @@ function useTabs() {
|
||||
{
|
||||
disabled: !!affixTab || disabled,
|
||||
handler: async () => {
|
||||
await tabsStore.closeTab(tab, router);
|
||||
await tabbarStore.closeTab(tab, router);
|
||||
},
|
||||
icon: IcRoundClose,
|
||||
key: 'close',
|
||||
@@ -127,8 +131,8 @@ function useTabs() {
|
||||
{
|
||||
handler: async () => {
|
||||
await (affixTab
|
||||
? tabsStore.unPushPinTab(tab)
|
||||
: tabsStore.pushPinTab(tab));
|
||||
? tabbarStore.unPushPinTab(tab)
|
||||
: tabbarStore.pushPinTab(tab));
|
||||
},
|
||||
icon: affixTab ? MdiPinOff : MdiPin,
|
||||
key: 'affix',
|
||||
@@ -140,7 +144,7 @@ function useTabs() {
|
||||
{
|
||||
disabled: closeLeftDisabled,
|
||||
handler: async () => {
|
||||
await tabsStore.closeLeftTabs(tab);
|
||||
await tabbarStore.closeLeftTabs(tab);
|
||||
},
|
||||
icon: MdiFormatHorizontalAlignLeft,
|
||||
key: 'close-left',
|
||||
@@ -149,7 +153,7 @@ function useTabs() {
|
||||
{
|
||||
disabled: closeRightDisabled,
|
||||
handler: async () => {
|
||||
await tabsStore.closeRightTabs(tab);
|
||||
await tabbarStore.closeRightTabs(tab);
|
||||
},
|
||||
icon: MdiFormatHorizontalAlignRight,
|
||||
key: 'close-right',
|
||||
@@ -159,7 +163,7 @@ function useTabs() {
|
||||
{
|
||||
disabled: closeOtherDisabled,
|
||||
handler: async () => {
|
||||
await tabsStore.closeOtherTabs(tab);
|
||||
await tabbarStore.closeOtherTabs(tab);
|
||||
},
|
||||
icon: MdiArrowExpandHorizontal,
|
||||
key: 'close-other',
|
||||
@@ -168,7 +172,7 @@ function useTabs() {
|
||||
{
|
||||
disabled,
|
||||
handler: async () => {
|
||||
await tabsStore.closeAllTabs(router);
|
||||
await tabbarStore.closeAllTabs(router);
|
||||
},
|
||||
icon: IcRoundMultipleStop,
|
||||
key: 'close-all',
|
||||
@@ -187,7 +191,7 @@ function useTabs() {
|
||||
* 取消固定标签页
|
||||
*/
|
||||
const handleUnPushPin = async (tab: TabItem) => {
|
||||
await tabsStore.unPushPinTab(tab);
|
||||
await tabbarStore.unPushPinTab(tab);
|
||||
};
|
||||
|
||||
return {
|
||||
|
@@ -6,12 +6,12 @@ import { useRoute } from 'vue-router';
|
||||
|
||||
import { preferences } from '@vben-core/preferences';
|
||||
import { Spinner } from '@vben-core/shadcn-ui';
|
||||
import { useTabbarStore } from '@vben-core/stores';
|
||||
import { useCoreTabbarStore } from '@vben-core/stores';
|
||||
|
||||
defineOptions({ name: 'IFrameRouterView' });
|
||||
|
||||
const spinningList = ref<boolean[]>([]);
|
||||
const tabsStore = useTabbarStore();
|
||||
const tabsStore = useCoreTabbarStore();
|
||||
const route = useRoute();
|
||||
|
||||
const enableTabbar = computed(() => preferences.tabbar.enable);
|
||||
|
@@ -43,6 +43,7 @@
|
||||
"@vben-core/design": "workspace:*",
|
||||
"@vben-core/iconify": "workspace:*",
|
||||
"@vben-core/shadcn-ui": "workspace:*",
|
||||
"@vben/constants": "workspace:*",
|
||||
"@vben/locales": "workspace:*",
|
||||
"@vben/types": "workspace:*",
|
||||
"@vueuse/integrations": "^10.11.0",
|
||||
|
@@ -4,6 +4,7 @@ import type { LoginCodeEmits } from './typings';
|
||||
import { computed, onBeforeUnmount, reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
import { $t } from '@vben/locales';
|
||||
import { VbenButton, VbenInput, VbenPinInput } from '@vben-core/shadcn-ui';
|
||||
|
||||
@@ -26,7 +27,7 @@ defineOptions({
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
loading: false,
|
||||
loginPath: '/auth/login',
|
||||
loginPath: LOGIN_PATH,
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@@ -2,6 +2,7 @@
|
||||
import { computed, reactive } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
import { $t } from '@vben/locales';
|
||||
import { VbenButton, VbenInput } from '@vben-core/shadcn-ui';
|
||||
|
||||
@@ -24,7 +25,7 @@ defineOptions({
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
loading: false,
|
||||
loginPath: '/auth/login',
|
||||
loginPath: LOGIN_PATH,
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@@ -2,6 +2,7 @@
|
||||
import { ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
import { $t } from '@vben/locales';
|
||||
import { VbenButton } from '@vben-core/shadcn-ui';
|
||||
|
||||
@@ -26,7 +27,7 @@ defineOptions({
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
loading: false,
|
||||
loginPath: '/auth/login',
|
||||
loginPath: LOGIN_PATH,
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
|
@@ -4,6 +4,7 @@ import type { RegisterEmits } from './typings';
|
||||
import { computed, reactive } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
import { $t } from '@vben/locales';
|
||||
import {
|
||||
VbenButton,
|
||||
@@ -31,7 +32,7 @@ defineOptions({
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
loading: false,
|
||||
loginPath: '/auth/login',
|
||||
loginPath: LOGIN_PATH,
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@@ -9,8 +9,9 @@ page:
|
||||
page: Page visit
|
||||
button: Button control
|
||||
loading-menu: In the loading menu
|
||||
access-test-1: Access test page 1
|
||||
access-test-2: Access test page 2
|
||||
access-test-1: Admin visit
|
||||
access-test-2: User visit
|
||||
access-test-3: Super visit
|
||||
nested:
|
||||
title: Nested Menu
|
||||
menu1: Menu 1
|
||||
|
@@ -8,8 +8,9 @@ page:
|
||||
backend-control: 后端控制
|
||||
page: 页面访问
|
||||
button: 按钮控制
|
||||
access-test-1: 权限测试页1
|
||||
access-test-2: 权限测试页2
|
||||
access-test-1: Admin 角色可见
|
||||
access-test-2: User 角色可见
|
||||
access-test-3: Super 角色可见
|
||||
|
||||
nested:
|
||||
title: 嵌套菜单
|
||||
|
Reference in New Issue
Block a user