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

1036 lines
32 KiB
JavaScript
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 { 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)
// 无论是否提供container参数都应该更新面板区内的子面板尺寸
if (container) {
updatePanelsSize(position, panelArea, container, { panelWidth: 150, panelHeight: 100 });
}
}
// 如果面板区域变为空,触发尺寸影响处理以更新其他区域
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 = []
}
// 刷新所有面板区域的大小信息
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
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,
refreshPanelSizes,
updatePanelsSize,
handlePanelSizeInfluence,
adjustAdjacentPanels,
adjustAdjacentPanelsVertical,
adjustRegionSize
}
})