diff --git a/components.d.ts b/components.d.ts index d2909e3..820e77e 100644 --- a/components.d.ts +++ b/components.d.ts @@ -40,8 +40,6 @@ declare module 'vue' { ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] - ElTabPane: typeof import('element-plus/es')['ElTabPane'] - ElTabs: typeof import('element-plus/es')['ElTabs'] ElTag: typeof import('element-plus/es')['ElTag'] Icon: typeof import('./src/components/icon/icon.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] @@ -95,8 +93,6 @@ declare global { const ElSwitch: typeof import('element-plus/es')['ElSwitch'] const ElTable: typeof import('element-plus/es')['ElTable'] const ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] - const ElTabPane: typeof import('element-plus/es')['ElTabPane'] - const ElTabs: typeof import('element-plus/es')['ElTabs'] const ElTag: typeof import('element-plus/es')['ElTag'] const Icon: typeof import('./src/components/icon/icon.vue')['default'] const RouterLink: typeof import('vue-router')['RouterLink'] diff --git a/src/components/ty-tabs.vue b/src/components/ty-tabs.vue index fab66b0..b754ed0 100644 --- a/src/components/ty-tabs.vue +++ b/src/components/ty-tabs.vue @@ -1,23 +1,40 @@ diff --git a/src/layouts/default.vue b/src/layouts/default.vue index f235ff8..746acce 100644 --- a/src/layouts/default.vue +++ b/src/layouts/default.vue @@ -48,8 +48,12 @@ v-if="app.showTabs" :tabs="tabsStore.tabs" :active-path="activePath" - @click="handleNavigate" + @click="handleTabClick" @remove="handleTabRemove" + @close-others="handleCloseOthers" + @close-left="handleCloseLeft" + @close-right="handleCloseRight" + @close-all="handleCloseAll" />
@@ -66,7 +70,7 @@ import { computed, ref, watch } from 'vue' import { useRoute, useRouter } from 'vue-router' import { useAppStore } from '@/stores/modules/app' -import { useTabsStore } from '@/stores/modules/tabs' +import { HOME_PATH, useTabsStore } from '@/stores/modules/tabs' import { useAuthStore } from '@/stores/modules/auth' import { placeholderMenus } from '@/config/menu' import logo from '@/assets/images/logo.png' @@ -173,14 +177,39 @@ function handleTopSelect(code: string): void { if (target) router.push(target) } +function handleTabClick(path: string): void { + router.push(path) +} + function handleTabRemove(path: string): void { + const index = tabsStore.tabs.findIndex((t) => t.path === path) + const neighbor = tabsStore.tabs[index - 1] ?? tabsStore.tabs[index + 1] ?? tabsStore.tabs[0] tabsStore.removeTab(path) if (activePath.value === path) { - const last = tabsStore.tabs[tabsStore.tabs.length - 1] - router.push(last?.path ?? '/') + router.push(neighbor?.path ?? HOME_PATH) } } +function handleCloseOthers(path: string): void { + tabsStore.removeOthers(path) + router.push(path) +} + +function handleCloseLeft(path: string): void { + tabsStore.removeLeft(path) + if (!tabsStore.tabs.some((t) => t.path === activePath.value)) router.push(path) +} + +function handleCloseRight(path: string): void { + tabsStore.removeRight(path) + if (!tabsStore.tabs.some((t) => t.path === activePath.value)) router.push(path) +} + +function handleCloseAll(): void { + tabsStore.removeAll() + router.push(HOME_PATH) +} + async function handleLogout(): Promise { await auth.logout() router.push('/login') diff --git a/src/stores/modules/tabs.ts b/src/stores/modules/tabs.ts index 72c5f79..4defecf 100644 --- a/src/stores/modules/tabs.ts +++ b/src/stores/modules/tabs.ts @@ -7,19 +7,51 @@ export interface TabItem { closable: boolean } -/** 多页签状态(会话级,不持久化)。 */ -export const useTabsStore = defineStore('tabsStore', () => { - const tabs = ref([]) +export const HOME_PATH = '/' - function addTab(tab: TabItem): void { - if (!tabs.value.some((t) => t.path === tab.path)) { - tabs.value.push(tab) +/** 多页签状态(持久化,刷新保留)。 */ +export const useTabsStore = defineStore( + 'tabsStore', + () => { + const tabs = ref([{ path: HOME_PATH, title: '首页', closable: false }]) + + function addTab(tab: TabItem): void { + if (!tabs.value.some((t) => t.path === tab.path)) { + tabs.value.push(tab) + } } - } - function removeTab(path: string): void { - tabs.value = tabs.value.filter((t) => t.path !== path) - } + function removeTab(path: string): void { + const tab = tabs.value.find((t) => t.path === path) + if (!tab || !tab.closable) return + tabs.value = tabs.value.filter((t) => t.path !== path) + } - return { tabs, addTab, removeTab } -}) + /** 关闭其他(保留首页与指定 tab)。 */ + function removeOthers(path: string): void { + tabs.value = tabs.value.filter((t) => !t.closable || t.path === path) + } + + /** 关闭左侧(保留首页、指定 tab 及其右侧)。 */ + function removeLeft(path: string): void { + const index = tabs.value.findIndex((t) => t.path === path) + if (index < 0) return + tabs.value = tabs.value.filter((t, i) => !t.closable || i >= index) + } + + /** 关闭右侧(保留首页、指定 tab 及其左侧)。 */ + function removeRight(path: string): void { + const index = tabs.value.findIndex((t) => t.path === path) + if (index < 0) return + tabs.value = tabs.value.filter((t, i) => !t.closable || i <= index) + } + + /** 关闭全部(仅保留首页)。 */ + function removeAll(): void { + tabs.value = tabs.value.filter((t) => !t.closable) + } + + return { tabs, addTab, removeTab, removeOthers, removeLeft, removeRight, removeAll } + }, + { persist: true }, +) diff --git a/stats.html b/stats.html index d947c8e..1ac30b8 100644 --- a/stats.html +++ b/stats.html @@ -4930,7 +4930,7 @@ var drawChart = (function (exports) {