liuyun 1df44fd57e feat: complete multi-tab (fixed home, neighbor nav, right-click close)
- 首页 tab 固定不可关闭,tab 持久化(刷新保留)
- 关闭激活 tab 跳转到相邻 tab(而非最后一个)
- 自定义 tab 条 + 右键菜单:关闭其他/左侧/右侧/全部

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-11 10:04:06 +08:00

58 lines
1.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ref } from 'vue'
import { defineStore } from 'pinia'
export interface TabItem {
path: string
title: string
closable: boolean
}
export const HOME_PATH = '/'
/** 多页签状态(持久化,刷新保留)。 */
export const useTabsStore = defineStore(
'tabsStore',
() => {
const tabs = ref<TabItem[]>([{ 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 {
const tab = tabs.value.find((t) => t.path === path)
if (!tab || !tab.closable) return
tabs.value = tabs.value.filter((t) => t.path !== path)
}
/** 关闭其他(保留首页与指定 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 },
)