143 lines
4.2 KiB
TypeScript
143 lines
4.2 KiB
TypeScript
import { defineStore } from 'pinia'
|
||
import { ref } from 'vue'
|
||
import {
|
||
PROJECT_TAB_ID,
|
||
QUICK_CONTRACT_TAB_ID,
|
||
QUICK_TAB_ID,
|
||
readWorkspaceMode
|
||
} from '@/lib/workspace'
|
||
|
||
export interface TabItem<TProps = Record<string, unknown>> {
|
||
id: string
|
||
title: string
|
||
componentName: string
|
||
props?: TProps
|
||
}
|
||
|
||
const DEFAULT_PROJECT_TAB: TabItem = {
|
||
id: PROJECT_TAB_ID,
|
||
title: '项目卡片',
|
||
componentName: 'ProjectCalcView'
|
||
}
|
||
|
||
/** 根据当前 workspace mode 返回受保护的 tab ID 集合 */
|
||
const getProtectedIds = (): Set<string> => {
|
||
return readWorkspaceMode() === 'quick'
|
||
? new Set([QUICK_TAB_ID, QUICK_CONTRACT_TAB_ID])
|
||
: new Set([PROJECT_TAB_ID, QUICK_CONTRACT_TAB_ID])
|
||
}
|
||
|
||
/** 根据当前 workspace mode 返回首个 tab 的 fallback ID */
|
||
const getFallbackTabId = (): string => {
|
||
return readWorkspaceMode() === 'quick' ? QUICK_TAB_ID : PROJECT_TAB_ID
|
||
}
|
||
|
||
export const useTabStore = defineStore(
|
||
'tabs',
|
||
() => {
|
||
const tabs = ref<TabItem[]>([{ ...DEFAULT_PROJECT_TAB }])
|
||
const activeTabId = ref()
|
||
const hasCompletedSetup = ref(false)
|
||
|
||
const ensureHomeTab = () => {
|
||
const fallbackId = getFallbackTabId()
|
||
if (tabs.value.some(tab => tab.id === fallbackId)) return
|
||
// quick 模式下不自动插入默认 tab,由 enterWorkspace 控制
|
||
if (readWorkspaceMode() === 'quick') return
|
||
tabs.value = [{ ...DEFAULT_PROJECT_TAB }, ...tabs.value]
|
||
}
|
||
|
||
const ensureActiveValid = () => {
|
||
ensureHomeTab()
|
||
if (tabs.value.length === 0) tabs.value = [{ ...DEFAULT_PROJECT_TAB }]
|
||
if (!tabs.value.some(tab => tab.id === activeTabId.value)) {
|
||
activeTabId.value = tabs.value[0]?.id ?? getFallbackTabId()
|
||
}
|
||
}
|
||
|
||
const enterWorkspace = (config: TabItem) => {
|
||
tabs.value = [{ ...config }]
|
||
activeTabId.value = config.id
|
||
}
|
||
|
||
const openTab = (config: TabItem) => {
|
||
if (!tabs.value.some(tab => tab.id === config.id)) {
|
||
tabs.value = [...tabs.value, config]
|
||
}
|
||
activeTabId.value = config.id
|
||
}
|
||
|
||
const removeTab = (id: string) => {
|
||
if (getProtectedIds().has(id)) return
|
||
|
||
const index = tabs.value.findIndex(tab => tab.id === id)
|
||
if (index < 0) return
|
||
|
||
const wasActive = activeTabId.value === id
|
||
tabs.value = tabs.value.filter(tab => tab.id !== id)
|
||
ensureHomeTab()
|
||
|
||
if (wasActive) {
|
||
const fallbackIndex = Math.max(0, Math.min(index - 1, tabs.value.length - 1))
|
||
activeTabId.value = tabs.value[fallbackIndex]?.id ?? getFallbackTabId()
|
||
return
|
||
}
|
||
|
||
ensureActiveValid()
|
||
}
|
||
|
||
const closeAllTabs = () => {
|
||
const protectedIds = getProtectedIds()
|
||
const protectedTabs = tabs.value.filter(tab => protectedIds.has(tab.id))
|
||
tabs.value = protectedTabs.length > 0 ? protectedTabs : [{ ...DEFAULT_PROJECT_TAB }]
|
||
activeTabId.value = tabs.value[0]?.id ?? getFallbackTabId()
|
||
}
|
||
|
||
const closeLeftTabs = (targetId: string) => {
|
||
const targetIndex = tabs.value.findIndex(tab => tab.id === targetId)
|
||
if (targetIndex < 0) return
|
||
const protectedIds = getProtectedIds()
|
||
tabs.value = tabs.value.filter((tab, index) => protectedIds.has(tab.id) || index >= targetIndex)
|
||
ensureActiveValid()
|
||
}
|
||
|
||
const closeRightTabs = (targetId: string) => {
|
||
const targetIndex = tabs.value.findIndex(tab => tab.id === targetId)
|
||
if (targetIndex < 0) return
|
||
const protectedIds = getProtectedIds()
|
||
tabs.value = tabs.value.filter((tab, index) => protectedIds.has(tab.id) || index <= targetIndex)
|
||
ensureActiveValid()
|
||
}
|
||
|
||
const closeOtherTabs = (targetId: string) => {
|
||
const protectedIds = getProtectedIds()
|
||
tabs.value = tabs.value.filter(tab => protectedIds.has(tab.id) || tab.id === targetId)
|
||
ensureHomeTab()
|
||
activeTabId.value = tabs.value.some(tab => tab.id === targetId) ? targetId : getFallbackTabId()
|
||
}
|
||
|
||
const resetTabs = () => {
|
||
tabs.value = [{ ...DEFAULT_PROJECT_TAB }]
|
||
activeTabId.value = PROJECT_TAB_ID
|
||
hasCompletedSetup.value = false
|
||
}
|
||
|
||
return {
|
||
tabs,
|
||
activeTabId,
|
||
hasCompletedSetup,
|
||
enterWorkspace,
|
||
openTab,
|
||
removeTab,
|
||
closeAllTabs,
|
||
closeLeftTabs,
|
||
closeRightTabs,
|
||
closeOtherTabs,
|
||
resetTabs
|
||
}
|
||
},
|
||
{
|
||
persist: true
|
||
}
|
||
)
|