import { defineStore } from 'pinia' import { ref, watch, computed } from 'vue' import type { LayoutConfig, TabItem, Panel } from '../types' import { materialList, getMaterialInfo } from '../materials' // 生成唯一ID const generateId = () => Math.random().toString(36).substring(2, 9) // 默认配置 const getDefaultLayout = (): LayoutConfig => ({ leftPanel: { id: 'left', tabs: [], activeTabId: null }, centerPanel: { id: 'center', tabs: [], activeTabId: null }, rightPanel: { id: 'right', tabs: [], activeTabId: null } }) // 初始化每个面板的activeTabId const initActiveTabIds = (layout: LayoutConfig): LayoutConfig => { const panels: (keyof LayoutConfig)[] = ['leftPanel', 'centerPanel', 'rightPanel'] panels.forEach(key => { const panel = layout[key] if (panel.tabs.length > 0 && !panel.activeTabId) { panel.activeTabId = panel.tabs[0].id } }) return layout } export const usePanelStore = defineStore('panel', () => { // 布局配置 const layout = ref(initActiveTabIds(getDefaultLayout())) // 物料组件状态独立存储 (materialId -> state) const materialStates = ref>>({}) // 是否已加载配置 const isLoaded = ref(false) // 获取所有已打开的物料组件ID const openedMaterialIds = computed(() => { const allTabs = [ ...layout.value.leftPanel.tabs, ...layout.value.centerPanel.tabs, ...layout.value.rightPanel.tabs ] return allTabs .filter(tab => tab.materialId) .map(tab => tab.materialId as string) }) // 获取可用的物料组件列表(未打开的) const availableMaterials = computed(() => { return materialList.filter(m => !openedMaterialIds.value.includes(m.id)) }) // 检查物料组件是否已打开 const isMaterialOpened = (materialId: string) => { return openedMaterialIds.value.includes(materialId) } // 加载配置 const loadConfig = async () => { try { // 加载布局配置 const response = await fetch('/api/config') if (response.ok) { const config = await response.json() if (config && config.layout) { layout.value = initActiveTabIds(config.layout) } } // 加载物料组件状态 const statesResponse = await fetch('/api/material-states') if (statesResponse.ok) { const states = await statesResponse.json() if (states && typeof states === 'object') { materialStates.value = states } } } catch (error) { console.log('使用默认配置') } isLoaded.value = true } // 保存配置 const saveConfig = async () => { try { await fetch('/api/config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ layout: layout.value, lastUpdated: new Date().toISOString() }) }) } catch (error) { console.error('保存配置失败:', error) } } // 保存物料组件状态 const saveMaterialStates = async () => { try { await fetch('/api/material-states', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(materialStates.value) }) } catch (error) { console.error('保存物料状态失败:', error) } } // 获取物料组件状态 const getMaterialState = (materialId: string): Record | undefined => { return materialStates.value[materialId] } // 更新物料组件状态 const updateMaterialState = (materialId: string, state: Record) => { materialStates.value[materialId] = { ...materialStates.value[materialId], ...state } saveMaterialStates() } // 监听变化并自动保存 watch(layout, () => { if (isLoaded.value) { saveConfig() } }, { deep: true }) // 获取面板 const getPanel = (panelId: string): Panel | undefined => { const panels = [layout.value.leftPanel, layout.value.centerPanel, layout.value.rightPanel] return panels.find(p => p.id === panelId) } // 添加新Tab const addTab = (panelId: string, tab?: Partial) => { const panel = getPanel(panelId) if (panel) { // 检查物料组件是否已打开 if (tab?.materialId && isMaterialOpened(tab.materialId)) { console.warn('该物料组件已打开') return } const newTab: TabItem = { id: generateId(), title: tab?.title || `新窗口 ${panel.tabs.length + 1}`, content: tab?.content || '新窗口内容', materialId: tab?.materialId } panel.tabs.push(newTab) panel.activeTabId = newTab.id } } // 打开物料组件 const openMaterial = (materialId: string, panelId: string = 'center') => { if (isMaterialOpened(materialId)) { console.warn('该物料组件已打开') return } const materialInfo = getMaterialInfo(materialId) if (materialInfo) { addTab(panelId, { title: materialInfo.name, materialId: materialId }) } } // 关闭Tab const closeTab = (panelId: string, tabId: string) => { const panel = getPanel(panelId) if (panel) { const index = panel.tabs.findIndex(t => t.id === tabId) if (index > -1) { // 物料组件状态已经在 materialStates 中独立存储,不需要额外处理 panel.tabs.splice(index, 1) // 更新激活的Tab if (panel.activeTabId === tabId) { panel.activeTabId = panel.tabs.length > 0 ? panel.tabs[Math.max(0, index - 1)].id : null } } } } // 设置激活的Tab const setActiveTab = (panelId: string, tabId: string) => { const panel = getPanel(panelId) if (panel) { panel.activeTabId = tabId } } // 移动Tab到另一个面板 const moveTab = (fromPanelId: string, toPanelId: string, tabId: string, toIndex?: number) => { const fromPanel = getPanel(fromPanelId) const toPanel = getPanel(toPanelId) if (fromPanel && toPanel) { const tabIndex = fromPanel.tabs.findIndex(t => t.id === tabId) if (tabIndex > -1) { const [tab] = fromPanel.tabs.splice(tabIndex, 1) if (toIndex !== undefined) { toPanel.tabs.splice(toIndex, 0, tab) } else { toPanel.tabs.push(tab) } // 更新激活状态 toPanel.activeTabId = tab.id if (fromPanel.activeTabId === tabId && fromPanel.tabs.length > 0) { fromPanel.activeTabId = fromPanel.tabs[0].id } else if (fromPanel.tabs.length === 0) { fromPanel.activeTabId = null } } } } // 在默认面板添加新窗口 const addNewWindow = () => { addTab('center') } return { layout, materialStates, isLoaded, openedMaterialIds, availableMaterials, isMaterialOpened, loadConfig, saveConfig, getMaterialState, updateMaterialState, addTab, openMaterial, closeTab, setActiveTab, moveTab, addNewWindow } })