264 lines
7.1 KiB
TypeScript
264 lines
7.1 KiB
TypeScript
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<LayoutConfig>(initActiveTabIds(getDefaultLayout()))
|
|
|
|
// 物料组件状态独立存储 (materialId -> state)
|
|
const materialStates = ref<Record<string, Record<string, any>>>({})
|
|
|
|
// 是否已加载配置
|
|
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<string, any> | undefined => {
|
|
return materialStates.value[materialId]
|
|
}
|
|
|
|
// 更新物料组件状态
|
|
const updateMaterialState = (materialId: string, state: Record<string, any>) => {
|
|
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<TabItem>) => {
|
|
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
|
|
}
|
|
})
|