Files
JoyD/AutoRobot/Windows/Robot/Web/src/store/dockPanelStore.js

1036 lines
32 KiB
JavaScript
Raw Normal View History

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { LayoutCoordinator } from '../components/LayoutCoordinator.js'
// 生成唯一ID
export function generateUniqueId() {
return 'panel-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9)
}
export const useDockPanelStore = defineStore('dockPanel', () => {
// 布局协调器实例
const minSizes = { panelWidth: 150, panelHeight: 100 }
const layoutCoordinator = new LayoutCoordinator(minSizes)
// 面板位置分组
const leftPanelArea = ref({
panels: [],
width: 300,
height: 0, // 将在updatePanelsSize中被正确设置
heightRatios: []
})
const rightPanelArea = ref({
panels: [],
width: 250,
height: 0, // 将在updatePanelsSize中被正确设置
heightRatios: []
})
const topPanelArea = ref({
panels: [],
height: 150,
width: 0, // 将在updatePanelsSize中被正确设置
widthRatios: []
})
const bottomPanelArea = ref({
panels: [],
height: 200,
width: 0, // 将在updatePanelsSize中被正确设置
widthRatios: []
})
const centerPanelArea = ref({
panels: [],
width: 0, // 将在updatePanelsSize中被正确设置
height: 0, // 将在updatePanelsSize中被正确设置
widthRatios: [],
heightRatios: []
})
const floatingWindows = ref([])
const minimizedWindows = ref([])
const closedPanelHistory = ref([]) // 关闭历史记录
// 激活的标签页
const activeCenterTab = ref(0)
// 计算属性
const leftPanels = computed(() => leftPanelArea.value.panels)
const rightPanels = computed(() => rightPanelArea.value.panels)
const topPanels = computed(() => topPanelArea.value.panels)
const bottomPanels = computed(() => bottomPanelArea.value.panels)
const centerPanels = computed(() => centerPanelArea.value.panels)
const leftPanelWidth = computed({
get: () => leftPanelArea.value.width,
set: (value) => leftPanelArea.value.width = value
})
const rightPanelWidth = computed({
get: () => rightPanelArea.value.width,
set: (value) => rightPanelArea.value.width = value
})
const topPanelHeight = computed({
get: () => topPanelArea.value.height,
set: (value) => topPanelArea.value.height = value
})
const bottomPanelHeight = computed({
get: () => bottomPanelArea.value.height,
set: (value) => bottomPanelArea.value.height = value
})
// 调整大小状态
const isResizing = ref(false)
const resizeTarget = ref('')
const resizeStartPos = ref({ x: 0, y: 0 })
const resizeContext = ref(null)
// 拖拽状态
const dragState = ref({
active: false,
panelId: null,
startX: 0,
startY: 0,
originalPosition: null,
isPanelDrag: false
})
// 停靠预览
const dockPreview = ref({
visible: false,
position: { top: 0, left: 0, width: 0, height: 0 },
color: '#3b82f6',
targetPosition: ''
})
// 右键菜单
const contextMenu = ref({
visible: false,
position: { x: 0, y: 0 },
items: [],
panelId: null
})
// 面板大小影响关系
const panelSizeInfluence = {
influence: {
left: ref([]),
right: ref([]),
top: ref([]),
bottom: ref([]),
center: ref([])
},
influencedBy: {
left: ref([]),
right: ref([]),
top: ref([]),
bottom: ref([]),
center: ref([])
}
}
// 根据面板ID获取面板位置
function getPanelPositionById(panelId) {
// 检查左侧面板
for (let i = 0; i < leftPanels.value.length; i++) {
if (leftPanels.value[i].id === panelId) {
return { position: 'left', index: i }
}
}
// 检查右侧面板
for (let i = 0; i < rightPanels.value.length; i++) {
if (rightPanels.value[i].id === panelId) {
return { position: 'right', index: i }
}
}
// 检查顶部面板
for (let i = 0; i < topPanels.value.length; i++) {
if (topPanels.value[i].id === panelId) {
return { position: 'top', index: i }
}
}
// 检查底部面板
for (let i = 0; i < bottomPanels.value.length; i++) {
if (bottomPanels.value[i].id === panelId) {
return { position: 'bottom', index: i }
}
}
// 检查中心面板
for (let i = 0; i < centerPanelArea.value.panels.length; i++) {
if (centerPanelArea.value.panels[i].id === panelId) {
return { position: 'center', index: i }
}
}
return null
}
// 添加面板
function addPanel(panel, minSizes = { panelWidth: 150, panelHeight: 100 }) {
const panelData = {
...panel,
collapsed: panel.collapsed || false,
lastPosition: panel.position,
lastSize: panel.lastSize || {
width: panel.width || 300,
height: panel.height || 200
},
width: panel.width || 300
}
// 获取全局容器元素只查询一次DOM
const container = document.querySelector('.dock-panel-container');
switch (panel.position) {
case 'left':
const isLeftFirst = leftPanels.value.length === 0
leftPanelArea.value.panels.push(panelData)
resetPanelsSizeRatios('left')
// 使用全局容器元素更新面板尺寸
if (container) {
updatePanelsSize('left', leftPanelArea.value, container, minSizes);
}
if (isLeftFirst) {
// 触发左侧面板的尺寸影响处理,传入容器引用避免重复查询
handlePanelSizeInfluence('left', container)
}
break
case 'right':
const isRightFirst = rightPanels.value.length === 0
rightPanelArea.value.panels.push(panelData)
resetPanelsSizeRatios('right')
// 使用全局容器元素更新面板尺寸
if (container) {
updatePanelsSize('right', rightPanelArea.value, container, minSizes);
}
if (isRightFirst) {
// 触发右侧面板的尺寸影响处理,传入容器引用避免重复查询
handlePanelSizeInfluence('right', container)
}
break
case 'top':
const isTopFirst = topPanels.value.length === 0
topPanelArea.value.panels.push(panelData)
resetPanelsSizeRatios('top')
// 使用全局容器元素更新面板尺寸
if (container) {
updatePanelsSize('top', topPanelArea.value, container, minSizes);
}
if (isTopFirst) {
// 触发顶部面板的尺寸影响处理,传入容器引用避免重复查询
handlePanelSizeInfluence('top', container)
}
break
case 'bottom':
const isBottomFirst = bottomPanels.value.length === 0
bottomPanelArea.value.panels.push(panelData)
resetPanelsSizeRatios('bottom')
// 使用全局容器元素更新面板尺寸
if (container) {
updatePanelsSize('bottom', bottomPanelArea.value, container, minSizes);
}
if (isBottomFirst) {
// 触发底部面板的尺寸影响处理,传入容器引用避免重复查询
handlePanelSizeInfluence('bottom', container)
}
break
case 'center':
default:
centerPanelArea.value.panels.push(panelData)
resetPanelsSizeRatios('center')
// 使用全局容器元素更新中心面板尺寸
if (container) {
updatePanelsSize('center', centerPanelArea.value, container, minSizes);
}
if (centerPanelArea.value.panels.length === 1) {
activeCenterTab.value = 0
}
}
}
// 重置面板尺寸比例
function resetPanelsSizeRatios(position) {
let panelArea
switch (position) {
case 'top':
panelArea = topPanelArea.value
break
case 'bottom':
panelArea = bottomPanelArea.value
break
case 'left':
panelArea = leftPanelArea.value
break
case 'right':
panelArea = rightPanelArea.value
break
case 'center':
panelArea = centerPanelArea.value
break
default:
return
}
if (!panelArea.panels || panelArea.panels.length === 0) return
const panelCount = panelArea.panels.length
const ratios = Array(panelCount).fill(1 / panelCount)
if (position === 'top' || position === 'bottom') {
panelArea.widthRatios = ratios
} else if (position === 'left' || position === 'right') {
panelArea.heightRatios = ratios
} else if (position === 'center') {
// 中心面板通常是标签页形式,不需要宽高比例
panelArea.widthRatios = ratios
panelArea.heightRatios = ratios
}
return ratios
}
// 关闭面板
function closePanel(panelId, container = null) {
const panelPosition = getPanelPositionById(panelId)
if (!panelPosition) return
const { position, index } = panelPosition
let panel, panels
let panelArea = null
switch (position) {
case 'left':
panelArea = leftPanelArea.value
panels = panelArea.panels
break
case 'right':
panelArea = rightPanelArea.value
panels = panelArea.panels
break
case 'top':
panelArea = topPanelArea.value
panels = panelArea.panels
break
case 'bottom':
panelArea = bottomPanelArea.value
panels = panelArea.panels
break
case 'center':
panelArea = centerPanelArea.value
panels = panelArea.panels
break
default:
return
}
panel = panels[index]
// 保存到历史记录
if (closedPanelHistory.value.length >= 20) {
closedPanelHistory.value.shift()
}
closedPanelHistory.value.push(panel)
// 从数组中移除面板
panels.splice(index, 1)
// 处理所有位置面板的通用逻辑
if (panels.length > 0) {
resetPanelsSizeRatios(position)
2025-10-20 10:59:56 +08:00
// 无论是否提供container参数都应该更新面板区内的子面板尺寸
if (container) {
updatePanelsSize(position, panelArea, container, { panelWidth: 150, panelHeight: 100 });
}
}
// 如果面板区域变为空,触发尺寸影响处理以更新其他区域
2025-10-20 10:59:56 +08:00
if (panels.length === 0) {
handlePanelSizeInfluence(position, container);
}
// 处理中心面板的特殊逻辑
if (position === 'center') {
if (index === activeCenterTab.value && panels.length > 0) {
activeCenterTab.value = Math.min(index, panels.length - 1)
}
}
}
// 添加浮动窗口
function addFloatingWindow(window) {
floatingWindows.value.push({
...window,
minimized: false,
maximized: false,
lastPosition: { x: window.x, y: window.y },
lastSize: { width: window.width, height: window.height }
})
}
// 关闭浮动窗口
function closeFloatingWindow(windowId) {
const index = floatingWindows.value.findIndex(w => w.id === windowId)
if (index !== -1) {
const minimizedIndex = minimizedWindows.value.findIndex(w => w.id === windowId)
if (minimizedIndex !== -1) {
minimizedWindows.value.splice(minimizedIndex, 1)
}
floatingWindows.value.splice(index, 1)
}
}
// 将面板转换为浮动窗口
function floatPanel(panelId) {
const panelPosition = getPanelPositionById(panelId)
if (!panelPosition) return
const { position, index } = panelPosition
let panel, panels, panelArea
switch (position) {
case 'left':
panelArea = leftPanelArea.value
panels = panelArea.panels
break
case 'right':
panelArea = rightPanelArea.value
panels = panelArea.panels
break
case 'top':
panelArea = topPanelArea.value
panels = panelArea.panels
break
case 'bottom':
panelArea = bottomPanelArea.value
panels = panelArea.panels
break
case 'center':
panelArea = centerPanelArea.value
panels = panelArea.panels
break
default:
return
}
panel = panels[index]
// 从原位置移除
panels.splice(index, 1)
// 处理不同位置面板的特殊逻辑
if (position !== 'center') {
if (panelArea.panels.length > 0) {
resetPanelsSizeRatios(position)
}
} else {
if (index === activeCenterTab.value && panels.length > 0) {
activeCenterTab.value = Math.min(index, panels.length - 1)
}
}
// 创建浮动窗口
addFloatingWindow({
...panel,
x: 100,
y: 100,
width: 400,
height: 300,
floating: true
})
}
// 停靠面板
function dockPanel(panelId, position) {
const index = floatingWindows.value.findIndex(w => w.id === panelId)
if (index !== -1) {
const window = floatingWindows.value[index]
// 从浮动窗口移除
floatingWindows.value.splice(index, 1)
// 添加到新位置
addPanel({
...window,
position: position || window.lastPosition || 'center',
floating: false
})
}
}
// 最小化浮动窗口
function minimizeFloatingWindow(windowId) {
const window = floatingWindows.value.find(w => w.id === windowId)
if (window) {
window.minimized = true
minimizedWindows.value.push(window)
// 记录最小化前的状态
if (!window.maximized) {
window.lastPosition = { x: window.x, y: window.y }
window.lastSize = { width: window.width, height: window.height }
}
}
}
// 恢复最小化窗口
function restoreMinimizedWindow(windowId) {
const windowIndex = floatingWindows.value.findIndex(w => w.id === windowId)
const minimizedIndex = minimizedWindows.value.findIndex(w => w.id === windowId)
if (windowIndex !== -1 && minimizedIndex !== -1) {
const window = floatingWindows.value[windowIndex]
// 移除最小化状态
window.minimized = false
// 从最小化窗口列表中移除
minimizedWindows.value.splice(minimizedIndex, 1)
// 如果窗口是最大化状态,则保持最大化
// 否则恢复到最小化前的位置和大小
}
}
// 最大化浮动窗口
function maximizeFloatingWindow(windowId) {
const window = floatingWindows.value.find(w => w.id === windowId)
if (window) {
if (window.maximized) {
// 还原
window.maximized = false
window.width = window.lastSize.width
window.height = window.lastSize.height
window.x = window.lastPosition.x
window.y = window.lastPosition.y
} else {
// 最大化
window.maximized = true
window.lastPosition = { x: window.x, y: window.y }
window.lastSize = { width: window.width, height: window.height }
// 获取当前窗口的尺寸逻辑
}
}
}
// 折叠/展开面板
function toggleCollapse(panelId, minSizes = { panelWidth: 150, panelHeight: 100 }) {
const panelPosition = getPanelPositionById(panelId)
if (!panelPosition) return
const { position, index } = panelPosition
let panel, panelArea
const isWidth = position === 'left' || position === 'right'
switch (position) {
case 'left':
panelArea = leftPanelArea.value
panel = panelArea.panels[index]
break
case 'right':
panelArea = rightPanelArea.value
panel = panelArea.panels[index]
break
case 'top':
panelArea = topPanelArea.value
panel = panelArea.panels[index]
break
case 'bottom':
panelArea = bottomPanelArea.value
panel = panelArea.panels[index]
break
case 'center':
panelArea = centerPanelArea.value
panel = panelArea.panels[index]
panel.collapsed = !panel.collapsed
return
default:
return
}
// 处理非中心面板的折叠逻辑
if (position !== 'center') {
if (!panel.collapsed) {
// 保存原始尺寸
panel.originalSize = isWidth ? panelArea.width : panelArea.height
// 对于左右面板设置为30px宽度
if (isWidth) {
panelArea.width = 30
}
} else {
// 恢复原始尺寸
if (panel.originalSize) {
if (isWidth) {
panelArea.width = Math.max(minSizes.panelWidth, panel.originalSize)
} else {
panelArea.height = Math.max(minSizes.panelHeight, panel.originalSize)
}
delete panel.originalSize
} else {
if (isWidth) {
panelArea.width = minSizes.panelWidth
} else {
panelArea.height = minSizes.panelHeight
}
}
}
}
// 切换折叠状态
panel.collapsed = !panel.collapsed
}
// 隐藏右键菜单
function hideContextMenu() {
contextMenu.value.visible = false
}
// 初始化面板
function initializePanels(panels) {
panels.forEach(panel => {
if (panel.floating) {
addFloatingWindow({
...panel,
id: panel.id || generateUniqueId(),
width: panel.width || 400,
height: panel.height || 300,
x: panel.x || 100,
y: panel.y || 100
})
} else {
addPanel({
...panel,
id: panel.id || generateUniqueId(),
position: panel.position || 'center'
})
}
})
}
// 重置所有面板状态
function resetLayout() {
// 重置面板区对象确保每个面板区域都包含width和height属性
leftPanelArea.value = {
panels: [],
width: 300,
height: 0, // 初始高度为0将在updatePanelsSize中被正确设置
heightRatios: []
}
rightPanelArea.value = {
panels: [],
width: 250,
height: 0, // 初始高度为0将在updatePanelsSize中被正确设置
heightRatios: []
}
topPanelArea.value = {
panels: [],
height: 150,
width: 0, // 初始宽度为0将在updatePanelsSize中被正确设置
widthRatios: []
}
bottomPanelArea.value = {
panels: [],
height: 200,
width: 0, // 初始宽度为0将在updatePanelsSize中被正确设置
widthRatios: []
}
// 清空其他面板集合
centerPanelArea.value.panels = []
floatingWindows.value = []
minimizedWindows.value = []
}
2025-10-20 10:59:56 +08:00
// 刷新所有面板区域的大小信息
function refreshPanelSizes(container = null) {
// 对于每个面板区域调用updatePanelsSize来刷新大小信息
// 只有当容器存在时才调用updatePanelsSize
if (container) {
updatePanelsSize('left', leftPanelArea.value, container);
updatePanelsSize('right', rightPanelArea.value, container);
updatePanelsSize('top', topPanelArea.value, container);
updatePanelsSize('bottom', bottomPanelArea.value, container);
updatePanelsSize('center', centerPanelArea.value, container);
}
// 触发响应式更新
// 重新赋值整个对象来确保Vue能够检测到变化
leftPanelArea.value = { ...leftPanelArea.value };
rightPanelArea.value = { ...rightPanelArea.value };
topPanelArea.value = { ...topPanelArea.value };
bottomPanelArea.value = { ...bottomPanelArea.value };
centerPanelArea.value = { ...centerPanelArea.value };
}
// 初始化面板大小影响关系和受影响关系
function initializePanelSizeInfluence() {
// 初始化影响关系数据
['left', 'right', 'top', 'bottom','center'].forEach(position => {
panelSizeInfluence.influence[position].value = []
panelSizeInfluence.influencedBy[position].value = []
})
// 使用LayoutCoordinator初始化影响关系
const influenceData = layoutCoordinator.initializePanelSizeInfluence()
// 应用影响关系数据
if (influenceData && influenceData.influence) {
['left', 'right', 'top', 'bottom','center'].forEach(position => {
if (influenceData.influence[position]) {
panelSizeInfluence.influence[position].value = influenceData.influence[position]
}
if (influenceData.influencedBy && influenceData.influencedBy[position]) {
panelSizeInfluence.influencedBy[position].value = influenceData.influencedBy[position]
}
})
}
}
// 处理面板大小变化对其他面板的影响
function handlePanelSizeInfluence(position, externalContainer) {
// 确保position是有效的面板位置
if (!['left', 'right', 'top', 'bottom', 'center'].includes(position)) {
return
}
// 准备面板数据对象 - 包含所有位置的面板数据
const panelData = {
left: leftPanelArea.value,
right: rightPanelArea.value,
top: topPanelArea.value,
bottom: bottomPanelArea.value,
center: centerPanelArea.value
};
if (!externalContainer) return;
// 调用布局协调器处理面板大小影响
const updatedPanels = layoutCoordinator.handlePanelSizeInfluence(
position,
{
influence: panelSizeInfluence.influence,
influencedBy: panelSizeInfluence.influencedBy
},
panelData,
externalContainer
);
// 更新面板数据包括面板区域本身的尺寸和内部的panels数组
// 为每个位置定义对应的面板区域变量
const panelAreaMap = {
left: leftPanelArea.value,
right: rightPanelArea.value,
top: topPanelArea.value,
bottom: bottomPanelArea.value,
center: centerPanelArea.value
};
const positions = ['left', 'right', 'top', 'bottom', 'center'];
positions.forEach(pos => {
if (updatedPanels && updatedPanels[pos]) {
const panelArea = panelAreaMap[pos];
// 首先更新面板区域本身的宽高属性(如果有)
if (updatedPanels[pos].width !== undefined) {
panelArea.width = updatedPanels[pos].width;
}
if (updatedPanels[pos].height !== undefined) {
panelArea.height = updatedPanels[pos].height;
}
// 更新panels数组
if (updatedPanels[pos].panels) {
panelArea.panels = updatedPanels[pos].panels;
}
// 更新比例数据
if (updatedPanels[pos].widthRatios) {
panelArea.widthRatios = updatedPanels[pos].widthRatios;
}
if (updatedPanels[pos].heightRatios) {
panelArea.heightRatios = updatedPanels[pos].heightRatios;
}
}
});
// 显式调用updatePanelsSize来更新所有面板区域的子面板尺寸确保子面板大小随面板区域变化
if (leftPanelArea.value && leftPanelArea.value.panels && leftPanelArea.value.panels.length > 0) {
updatePanelsSize('left', leftPanelArea.value, externalContainer);
}
if (rightPanelArea.value && rightPanelArea.value.panels && rightPanelArea.value.panels.length > 0) {
updatePanelsSize('right', rightPanelArea.value, externalContainer);
}
if (topPanelArea.value && topPanelArea.value.panels && topPanelArea.value.panels.length > 0) {
updatePanelsSize('top', topPanelArea.value, externalContainer);
}
if (bottomPanelArea.value && bottomPanelArea.value.panels && bottomPanelArea.value.panels.length > 0) {
updatePanelsSize('bottom', bottomPanelArea.value, externalContainer);
}
if (centerPanelArea.value && centerPanelArea.value.panels && centerPanelArea.value.panels.length > 0) {
updatePanelsSize('center', centerPanelArea.value, externalContainer);
}
}
// 更新面板尺寸
function updatePanelsSize(position, panelArea, container, minSizes = { panelWidth: 150, panelHeight: 100 }) {
if (!container) return;
// 确保面板区域存在且有面板
if (!panelArea || !panelArea.panels || panelArea.panels.length === 0) return
// 获取容器尺寸
const containerWidth = container.clientWidth;
const containerHeight = container.clientHeight;
// 准备面板区域数据,用于计算可用空间
const panelAreas = {
top: topPanelArea.value,
bottom: bottomPanelArea.value,
left: leftPanelArea.value,
right: rightPanelArea.value,
center: centerPanelArea.value
};
// 处理不同位置的面板尺寸更新
if (position === 'top' || position === 'bottom') {
// 顶部和底部面板 - 水平排列
// 更新面板区域的完整宽高信息
panelArea.width = layoutCoordinator.calculateAvailableWidth(
position,
panelSizeInfluence,
panelAreas,
containerWidth,
minSizes
);
// 使用当前面板区域的实际高度(已通过分割条调整后的高度)
panelArea.height = position === 'top' ? topPanelArea.value.height : bottomPanelArea.value.height;
// 确保有宽度比例数组,并且长度与面板数量匹配
if (!panelArea.widthRatios || panelArea.widthRatios.length !== panelArea.panels.length) {
panelArea.widthRatios = resetPanelsSizeRatios(panelArea.panels.length);
}
// 应用面板宽度比例
panelArea.panels.forEach((panel, index) => {
// 计算面板宽度,确保不小于最小宽度
const calculatedWidth = panelArea.width * panelArea.widthRatios[index]
panel.width = Math.max(minSizes.panelWidth || 150, calculatedWidth)
panel.height = panelArea.height
})
} else if (position === 'left' || position === 'right') {
// 左侧和右侧面板 - 垂直排列
// 计算左侧/右侧面板区域的可用高度(考虑顶底面板占用的空间)
const availableHeight = layoutCoordinator.calculateAvailableHeight(
position,
panelSizeInfluence,
panelAreas,
containerHeight,
minSizes
);
// 更新面板区域的完整宽高信息
panelArea.height = availableHeight; // 设置面板区域高度为可用高度
panelArea.width = position === 'left' ? leftPanelArea.value.width : rightPanelArea.value.width; // 保持原有宽度
// 确保有高度比例数组,并且长度与面板数量匹配
if (!panelArea.heightRatios || panelArea.heightRatios.length !== panelArea.panels.length) {
panelArea.heightRatios = resetPanelsSizeRatios(panelArea.panels.length);
}
// 应用面板高度比例
panelArea.panels.forEach((panel, index) => {
// 计算面板高度,确保不小于最小高度
const calculatedHeight = panelArea.height * panelArea.heightRatios[index]
panel.height = Math.max(minSizes.panelHeight || 100, calculatedHeight)
panel.width = panelArea.width
})
}
// 新增中心面板的处理逻辑
else if (position === 'center') {
// 中心面板的尺寸计算(考虑其他面板占用的空间)
const availableWidth = layoutCoordinator.calculateAvailableWidth(
position,
panelSizeInfluence,
panelAreas,
containerWidth,
minSizes
);
const availableHeight = layoutCoordinator.calculateAvailableHeight(
position,
panelSizeInfluence,
panelAreas,
containerHeight,
minSizes
);
// 更新面板区域的宽高信息
panelArea.width = availableWidth;
panelArea.height = availableHeight;
// 确保有宽高比例数组,并且长度与面板数量匹配
if (!panelArea.widthRatios || panelArea.widthRatios.length !== panelArea.panels.length) {
panelArea.widthRatios = resetPanelsSizeRatios(panelArea.panels.length);
}
if (!panelArea.heightRatios || panelArea.heightRatios.length !== panelArea.panels.length) {
panelArea.heightRatios = resetPanelsSizeRatios(panelArea.panels.length);
}
// 应用面板宽高(中心面板通常是标签页形式,所有面板共享相同的宽高)
panelArea.panels.forEach((panel, index) => {
panel.width = panelArea.width;
panel.height = panelArea.height;
});
}
// 应用更新后的面板数据,触发响应式更新
if (position === 'top') {
topPanelArea.value = { ...panelArea };
} else if (position === 'bottom') {
bottomPanelArea.value = { ...panelArea };
} else if (position === 'left') {
leftPanelArea.value = { ...panelArea };
} else if (position === 'right') {
rightPanelArea.value = { ...panelArea };
} else if (position === 'center') {
centerPanelArea.value = { ...panelArea };
}
}
// 包装LayoutCoordinator的adjustAdjacentPanels方法
function adjustAdjacentPanels(position, panelIndex, delta, originalSizes, availableWidth) {
const panelArea = position === 'top' ? topPanelArea.value : bottomPanelArea.value
const panels = panelArea.panels
const updatedPanels = layoutCoordinator.adjustAdjacentPanels(
panels, panelIndex, delta, originalSizes, availableWidth
)
if (updatedPanels !== panels) {
panelArea.panels = updatedPanels
return updatedPanels
}
return panels
}
// 包装LayoutCoordinator的adjustAdjacentPanelsVertical方法
function adjustAdjacentPanelsVertical(position, panelIndex, delta, originalSizes, availableHeight) {
const panelArea = position === 'left' ? leftPanelArea.value : rightPanelArea.value
const panels = panelArea.panels
const updatedPanels = layoutCoordinator.adjustAdjacentPanelsVertical(
panels, panelIndex, delta, originalSizes, availableHeight
)
if (updatedPanels !== panels) {
panelArea.panels = updatedPanels
return updatedPanels
}
return panels
}
// 包装LayoutCoordinator的adjustRegionSize方法
function adjustRegionSize(target, delta, container = null) {
const panelAreas = {
top: topPanelArea.value,
bottom: bottomPanelArea.value,
left: leftPanelArea.value,
right: rightPanelArea.value
}
let containerHeight = null
if (container) {
containerHeight = container.clientHeight
}
let newSize
switch (target) {
case 'left':
newSize = layoutCoordinator.adjustRegionSize('left', panelAreas.left.width, delta)
panelAreas.left.width = newSize
break
case 'right':
newSize = layoutCoordinator.adjustRegionSize('right', panelAreas.right.width, -delta)
panelAreas.right.width = newSize
break
case 'top':
newSize = layoutCoordinator.adjustRegionSize('top', panelAreas.top.height, delta, panelAreas, containerHeight)
panelAreas.top.height = newSize
2025-10-20 10:59:56 +08:00
break
case 'bottom':
newSize = layoutCoordinator.adjustRegionSize('bottom', panelAreas.bottom.height, -delta, panelAreas, containerHeight)
panelAreas.bottom.height = newSize
break
}
}
return {
// 面板数据
leftPanelArea,
rightPanelArea,
topPanelArea,
bottomPanelArea,
centerPanelArea,
floatingWindows,
minimizedWindows,
closedPanelHistory,
// 计算属性
leftPanels,
rightPanels,
topPanels,
bottomPanels,
centerPanels,
leftPanelWidth,
rightPanelWidth,
topPanelHeight,
bottomPanelHeight,
// 状态
activeCenterTab,
isResizing,
resizeTarget,
resizeStartPos,
resizeContext,
dragState,
dockPreview,
contextMenu,
panelSizeInfluence,
// 方法
getPanelPositionById,
addPanel,
closePanel,
floatPanel,
dockPanel,
addFloatingWindow,
closeFloatingWindow,
minimizeFloatingWindow,
restoreMinimizedWindow,
maximizeFloatingWindow,
toggleCollapse,
hideContextMenu,
initializePanels,
resetLayout,
resetPanelsSizeRatios,
initializePanelSizeInfluence,
2025-10-20 10:59:56 +08:00
refreshPanelSizes,
updatePanelsSize,
handlePanelSizeInfluence,
adjustAdjacentPanels,
adjustAdjacentPanelsVertical,
adjustRegionSize
}
})