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 @@
-
-
-
+
+
+ {{ tab.title }}
+
+
+
+
+
+
+
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) {