修改为绝对坐标面板
This commit is contained in:
@@ -1,65 +1,112 @@
|
|||||||
/**
|
/**
|
||||||
* 布局协调器类 - 负责管理和计算面板布局
|
* 布局协调器 - 用于管理和协调面板布局
|
||||||
|
* 采用基于绝对定位的面板布局系统,通过计算面板边界来实现灵活的布局管理
|
||||||
*/
|
*/
|
||||||
export class LayoutCoordinator {
|
export class LayoutCoordinator {
|
||||||
constructor(minSizes) {
|
/**
|
||||||
|
* 构造函数
|
||||||
|
* @param {Object} minSizes - 最小尺寸限制
|
||||||
|
*/
|
||||||
|
constructor(minSizes = {}) {
|
||||||
this.minSizes = minSizes;
|
this.minSizes = minSizes;
|
||||||
|
// 面板边界信息,存储每个面板区域的位置和尺寸
|
||||||
|
this.panelBounds = {
|
||||||
|
left: { x: 0, y: 0, width: 0, height: 0 },
|
||||||
|
right: { x: 0, y: 0, width: 0, height: 0 },
|
||||||
|
top: { x: 0, y: 0, width: 0, height: 0 },
|
||||||
|
bottom: { x: 0, y: 0, width: 0, height: 0 },
|
||||||
|
center: { x: 0, y: 0, width: 0, height: 0 }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 调整面板区域大小
|
* 调整面板区域大小
|
||||||
* @param {String} target - 调整目标 ('left', 'right', 'top', 'bottom')
|
* @param {string} target - 目标区域
|
||||||
* @param {Number} currentSize - 当前尺寸
|
* @param {number} delta - 变化量
|
||||||
* @param {Number} delta - 变化量
|
* @param {Object} panelAreas - 所有面板区域
|
||||||
* @param {Object} panelAreas - 面板区域对象集合(用于获取其他面板区域信息)
|
* @param {number} containerWidth - 容器宽度
|
||||||
* @param {Number} containerHeight - 容器高度(用于限制顶底面板总高度)
|
* @param {number} containerHeight - 容器高度
|
||||||
* @returns {Number} - 调整后的尺寸
|
* @returns {Object} 更新后的面板边界
|
||||||
*/
|
*/
|
||||||
adjustRegionSize(target, currentSize, delta, panelAreas = null, containerHeight = null) {
|
adjustRegionSize(target, delta, panelAreas, containerWidth, containerHeight) {
|
||||||
if (target === 'left' || target === 'right') {
|
// 创建面板区域的副本,避免直接修改原对象
|
||||||
return Math.max(this.minSizes.panelWidth, currentSize + delta);
|
const updatedPanelAreas = {
|
||||||
} else if (target === 'top' || target === 'bottom') {
|
left: { ...panelAreas.left },
|
||||||
// 计算调整后的尺寸
|
right: { ...panelAreas.right },
|
||||||
const newSize = currentSize + delta;
|
top: { ...panelAreas.top },
|
||||||
|
bottom: { ...panelAreas.bottom },
|
||||||
|
center: { ...panelAreas.center }
|
||||||
|
};
|
||||||
|
|
||||||
// 应用最小高度限制
|
// 根据目标区域调整尺寸
|
||||||
let adjustedSize = Math.max(this.minSizes.panelHeight, newSize);
|
if (target === 'left') {
|
||||||
|
// 调整左侧面板宽度,同时调整中心面板位置和宽度
|
||||||
|
const newLeftWidth = Math.max(0, (updatedPanelAreas.left?.width || 0) + delta);
|
||||||
|
updatedPanelAreas.left.width = newLeftWidth;
|
||||||
|
|
||||||
// 如果提供了面板区域对象和容器高度,应用总高度限制
|
// 中心面板需要调整x坐标和宽度
|
||||||
if (panelAreas && containerHeight && panelAreas.top && panelAreas.bottom) {
|
if (updatedPanelAreas.center) {
|
||||||
// 计算当前顶面板和底面板的总高度
|
updatedPanelAreas.center.x = newLeftWidth;
|
||||||
const otherPanelHeight = target === 'top'
|
updatedPanelAreas.center.width = containerWidth - newLeftWidth - (updatedPanelAreas.right?.width || 0);
|
||||||
? (panelAreas.bottom.height || 0)
|
}
|
||||||
: (panelAreas.top.height || 0);
|
} else if (target === 'right') {
|
||||||
|
// 调整右侧面板宽度,同时调整中心面板宽度
|
||||||
|
const newRightWidth = Math.max(0, (updatedPanelAreas.right?.width || 0) + delta);
|
||||||
|
updatedPanelAreas.right.width = newRightWidth;
|
||||||
|
|
||||||
// 计算左中右面板的最小高度总和
|
// 更新右侧面板x坐标
|
||||||
// 左侧面板区域最小高度(所有面板最小高度之和)
|
updatedPanelAreas.right.x = containerWidth - newRightWidth;
|
||||||
const leftPanelMinHeight = panelAreas.left && panelAreas.left.panels ?
|
|
||||||
panelAreas.left.panels.reduce((sum, panel) => sum + (panel.minHeight || this.minSizes.panelHeight), 0) :
|
|
||||||
this.minSizes.panelHeight;
|
|
||||||
|
|
||||||
// 中心面板最小高度
|
// 中心面板需要调整宽度
|
||||||
const centerPanelMinHeight = this.minSizes.panelHeight;
|
if (updatedPanelAreas.center) {
|
||||||
|
updatedPanelAreas.center.width = containerWidth - (updatedPanelAreas.left?.width || 0) - newRightWidth;
|
||||||
|
}
|
||||||
|
} else if (target === 'top') {
|
||||||
|
// 调整顶部面板高度,同时调整其他所有面板的y坐标
|
||||||
|
const newTopHeight = Math.max(0, (updatedPanelAreas.top?.height || 0) + delta);
|
||||||
|
updatedPanelAreas.top.height = newTopHeight;
|
||||||
|
|
||||||
// 右侧面板区域最小高度(所有面板最小高度之和)
|
// 更新左侧、右侧和中心面板的y坐标和高度
|
||||||
const rightPanelMinHeight = panelAreas.right && panelAreas.right.panels ?
|
const otherPanelsHeight = containerHeight - newTopHeight - (updatedPanelAreas.bottom?.height || 0);
|
||||||
panelAreas.right.panels.reduce((sum, panel) => sum + (panel.minHeight || this.minSizes.panelHeight), 0) :
|
|
||||||
this.minSizes.panelHeight;
|
|
||||||
|
|
||||||
// 计算左中右面板的最大最小高度要求
|
if (updatedPanelAreas.left) {
|
||||||
const maxPanelsMinHeight = Math.max(leftPanelMinHeight, centerPanelMinHeight, rightPanelMinHeight);
|
updatedPanelAreas.left.y = newTopHeight;
|
||||||
|
updatedPanelAreas.left.height = otherPanelsHeight;
|
||||||
// 计算最大允许的高度(容器高度减去其他面板的高度、安全边界和左中右面板的最大最小高度)
|
|
||||||
const safetyMargin = 40; // 为内容区域保留一些空间
|
|
||||||
const maxAllowedHeight = containerHeight - otherPanelHeight - safetyMargin - maxPanelsMinHeight;
|
|
||||||
|
|
||||||
// 应用最大高度限制
|
|
||||||
adjustedSize = Math.min(maxAllowedHeight, adjustedSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return adjustedSize;
|
if (updatedPanelAreas.right) {
|
||||||
|
updatedPanelAreas.right.y = newTopHeight;
|
||||||
|
updatedPanelAreas.right.height = otherPanelsHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedPanelAreas.center) {
|
||||||
|
updatedPanelAreas.center.y = newTopHeight;
|
||||||
|
updatedPanelAreas.center.height = otherPanelsHeight;
|
||||||
|
}
|
||||||
|
} else if (target === 'bottom') {
|
||||||
|
// 调整底部面板高度,同时调整其他所有面板的高度
|
||||||
|
const newBottomHeight = Math.max(0, (updatedPanelAreas.bottom?.height || 0) + delta);
|
||||||
|
updatedPanelAreas.bottom.height = newBottomHeight;
|
||||||
|
updatedPanelAreas.bottom.y = containerHeight - newBottomHeight;
|
||||||
|
|
||||||
|
// 更新左侧、右侧和中心面板的高度
|
||||||
|
const otherPanelsHeight = containerHeight - (updatedPanelAreas.top?.height || 0) - newBottomHeight;
|
||||||
|
|
||||||
|
if (updatedPanelAreas.left) {
|
||||||
|
updatedPanelAreas.left.height = otherPanelsHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedPanelAreas.right) {
|
||||||
|
updatedPanelAreas.right.height = otherPanelsHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedPanelAreas.center) {
|
||||||
|
updatedPanelAreas.center.height = otherPanelsHeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return currentSize;
|
|
||||||
|
// 使用更新后的面板区域重新计算面板边界
|
||||||
|
return this.calculatePanelBounds(updatedPanelAreas, containerWidth, containerHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,7 +115,7 @@ export class LayoutCoordinator {
|
|||||||
* @param {Number} panelIndex - 当前面板索引
|
* @param {Number} panelIndex - 当前面板索引
|
||||||
* @param {Number} delta - 变化量(X或Y方向)
|
* @param {Number} delta - 变化量(X或Y方向)
|
||||||
* @param {Array} originalSizes - 原始尺寸数组
|
* @param {Array} originalSizes - 原始尺寸数组
|
||||||
* @param {Number} regionSize - 面板区域总尺寸(可选)
|
* @param {Number} regionSize - 面板区域总尺寸
|
||||||
* @param {String} dimension - 调整维度('width'或'height')
|
* @param {String} dimension - 调整维度('width'或'height')
|
||||||
* @returns {Array} - 调整后的面板数组
|
* @returns {Array} - 调整后的面板数组
|
||||||
*/
|
*/
|
||||||
@@ -82,39 +129,26 @@ export class LayoutCoordinator {
|
|||||||
const currentPanel = updatedPanels[panelIndex];
|
const currentPanel = updatedPanels[panelIndex];
|
||||||
const nextPanel = updatedPanels[panelIndex + 1];
|
const nextPanel = updatedPanels[panelIndex + 1];
|
||||||
|
|
||||||
// 1. 计算总尺寸 - 统一使用传入的regionSize(来自DOM实际尺寸)
|
// 使用传入的regionSize作为总尺寸
|
||||||
let totalSize = 0;
|
let totalSize = regionSize > 0 ? regionSize : panels.length * minSize;
|
||||||
|
|
||||||
// 确保使用从DOM获取的实际尺寸作为唯一计算依据
|
// 计算当前面板和下一面板的原始尺寸
|
||||||
if (regionSize && regionSize > 0) {
|
|
||||||
totalSize = regionSize;
|
|
||||||
}
|
|
||||||
// 为了确保安全性,保留一个基本的默认值处理
|
|
||||||
else {
|
|
||||||
totalSize = panels.length * minSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 计算每个面板应占的比例
|
|
||||||
const panelCount = panels.length;
|
|
||||||
const baseSize = totalSize / panelCount;
|
|
||||||
|
|
||||||
// 3. 计算当前面板和下一面板的原始尺寸
|
|
||||||
const getOriginalSize = (index) => {
|
const getOriginalSize = (index) => {
|
||||||
if (originalSizes && originalSizes[index]) {
|
if (originalSizes && originalSizes[index]) {
|
||||||
return originalSizes[index][dimension] || baseSize;
|
return originalSizes[index][dimension] || totalSize / panels.length;
|
||||||
}
|
}
|
||||||
return baseSize;
|
return totalSize / panels.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentSize = getOriginalSize(panelIndex);
|
const currentSize = getOriginalSize(panelIndex);
|
||||||
const nextSize = getOriginalSize(panelIndex + 1);
|
const nextSize = getOriginalSize(panelIndex + 1);
|
||||||
|
|
||||||
// 4. 应用delta变化量,并确保不小于最小尺寸限制
|
// 应用delta变化量,并确保不小于最小尺寸限制
|
||||||
const newCurrentSize = Math.max(minSize, currentSize + delta);
|
const newCurrentSize = Math.max(minSize, currentSize + delta);
|
||||||
const actualDelta = newCurrentSize - currentSize; // 实际应用的变化量
|
const actualDelta = newCurrentSize - currentSize;
|
||||||
const newNextSize = Math.max(minSize, nextSize - actualDelta);
|
const newNextSize = Math.max(minSize, nextSize - actualDelta);
|
||||||
|
|
||||||
// 5. 创建新对象以触发Vue响应式更新,并设置相应的尺寸属性
|
// 更新面板尺寸
|
||||||
updatedPanels[panelIndex] = {
|
updatedPanels[panelIndex] = {
|
||||||
...updatedPanels[panelIndex],
|
...updatedPanels[panelIndex],
|
||||||
[dimension]: newCurrentSize
|
[dimension]: newCurrentSize
|
||||||
@@ -124,9 +158,9 @@ export class LayoutCoordinator {
|
|||||||
[dimension]: newNextSize
|
[dimension]: newNextSize
|
||||||
};
|
};
|
||||||
|
|
||||||
// 6. 更新其他面板的尺寸以保持总尺寸一致,并保持原有比例
|
// 处理剩余面板
|
||||||
const remainingSize = totalSize - newCurrentSize - newNextSize;
|
const remainingSize = totalSize - newCurrentSize - newNextSize;
|
||||||
const remainingPanelsCount = panelCount - 2;
|
const remainingPanelsCount = panels.length - 2;
|
||||||
|
|
||||||
if (remainingPanelsCount > 0) {
|
if (remainingPanelsCount > 0) {
|
||||||
// 计算非相邻面板的原始总尺寸
|
// 计算非相邻面板的原始总尺寸
|
||||||
@@ -139,7 +173,7 @@ export class LayoutCoordinator {
|
|||||||
originalRemainingSizes.push(originalPanelSize);
|
originalRemainingSizes.push(originalPanelSize);
|
||||||
originalRemainingTotalSize += originalPanelSize;
|
originalRemainingTotalSize += originalPanelSize;
|
||||||
} else {
|
} else {
|
||||||
originalRemainingSizes.push(null); // 标记为相邻面板
|
originalRemainingSizes.push(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,10 +182,8 @@ export class LayoutCoordinator {
|
|||||||
if (i !== panelIndex && i !== panelIndex + 1) {
|
if (i !== panelIndex && i !== panelIndex + 1) {
|
||||||
let newPanelSize;
|
let newPanelSize;
|
||||||
if (originalRemainingTotalSize > 0) {
|
if (originalRemainingTotalSize > 0) {
|
||||||
// 按原始比例分配
|
|
||||||
newPanelSize = (originalRemainingSizes[i] / originalRemainingTotalSize) * remainingSize;
|
newPanelSize = (originalRemainingSizes[i] / originalRemainingTotalSize) * remainingSize;
|
||||||
} else {
|
} else {
|
||||||
// 如果原始总尺寸为0,则平均分配
|
|
||||||
newPanelSize = remainingSize / remainingPanelsCount;
|
newPanelSize = remainingSize / remainingPanelsCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,12 +201,6 @@ export class LayoutCoordinator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 调整相邻面板的宽度(水平方向)
|
* 调整相邻面板的宽度(水平方向)
|
||||||
* @param {Array} panels - 面板数组
|
|
||||||
* @param {Number} panelIndex - 当前面板索引
|
|
||||||
* @param {Number} deltaX - X轴变化量
|
|
||||||
* @param {Array} originalSizes - 原始尺寸数组
|
|
||||||
* @param {Number} regionWidth - 面板区域总宽度(可选)
|
|
||||||
* @returns {Array} - 调整后的面板数组
|
|
||||||
*/
|
*/
|
||||||
adjustAdjacentPanelsHorizontal(panels, panelIndex, deltaX, originalSizes, regionWidth = null) {
|
adjustAdjacentPanelsHorizontal(panels, panelIndex, deltaX, originalSizes, regionWidth = null) {
|
||||||
return this.adjustAdjacentPanels(panels, panelIndex, deltaX, originalSizes, regionWidth, 'width');
|
return this.adjustAdjacentPanels(panels, panelIndex, deltaX, originalSizes, regionWidth, 'width');
|
||||||
@@ -182,12 +208,6 @@ export class LayoutCoordinator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 调整相邻面板的高度(垂直方向)
|
* 调整相邻面板的高度(垂直方向)
|
||||||
* @param {Array} panels - 面板数组
|
|
||||||
* @param {Number} panelIndex - 当前面板索引
|
|
||||||
* @param {Number} deltaY - Y轴变化量
|
|
||||||
* @param {Array} originalSizes - 原始尺寸数组
|
|
||||||
* @param {Number} regionHeight - 面板区域总高度(可选)
|
|
||||||
* @returns {Array} - 调整后的面板数组
|
|
||||||
*/
|
*/
|
||||||
adjustAdjacentPanelsVertical(panels, panelIndex, deltaY, originalSizes, regionHeight = null) {
|
adjustAdjacentPanelsVertical(panels, panelIndex, deltaY, originalSizes, regionHeight = null) {
|
||||||
return this.adjustAdjacentPanels(panels, panelIndex, deltaY, originalSizes, regionHeight, 'height');
|
return this.adjustAdjacentPanels(panels, panelIndex, deltaY, originalSizes, regionHeight, 'height');
|
||||||
@@ -195,30 +215,21 @@ export class LayoutCoordinator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证面板尺寸是否符合约束
|
* 验证面板尺寸是否符合约束
|
||||||
* @param {Object} panel - 面板对象
|
|
||||||
* @param {String} position - 面板位置
|
|
||||||
* @returns {Boolean} - 是否符合约束
|
|
||||||
*/
|
*/
|
||||||
validatePanelSize(panel, position) {
|
validatePanelSize(panel, position) {
|
||||||
if (position === 'left' || position === 'right' || position === 'top' || position === 'bottom') {
|
if (position === 'left' || position === 'right') {
|
||||||
if (panel.width && panel.width < this.minSizes.panelWidth) {
|
return !panel.width || panel.width >= this.minSizes.panelWidth;
|
||||||
return false;
|
} else if (position === 'top' || position === 'bottom') {
|
||||||
}
|
return !panel.height || panel.height >= this.minSizes.panelHeight;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化面板大小影响关系
|
* 初始化面板大小影响关系 - 兼容原有接口
|
||||||
* @returns {Object} - 面板大小影响关系对象
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* 初始化面板大小影响关系和受影响关系
|
|
||||||
* @returns {Object} - 包含影响关系数组和受影响关系数组的对象
|
|
||||||
*/
|
*/
|
||||||
initializePanelSizeInfluence() {
|
initializePanelSizeInfluence() {
|
||||||
return {
|
return {
|
||||||
// 影响数组:当某个面板大小变化时,会影响哪些其他面板
|
|
||||||
influence: {
|
influence: {
|
||||||
left: [
|
left: [
|
||||||
{ position: 'top', property: 'width', influence: true },
|
{ position: 'top', property: 'width', influence: true },
|
||||||
@@ -238,7 +249,6 @@ export class LayoutCoordinator {
|
|||||||
],
|
],
|
||||||
center: []
|
center: []
|
||||||
},
|
},
|
||||||
// 受影响数组:计算某个面板大小时,需要考虑哪些其他面板
|
|
||||||
influencedBy: {
|
influencedBy: {
|
||||||
left: [
|
left: [
|
||||||
{ position: 'center', property: 'width', influence: true },
|
{ position: 'center', property: 'width', influence: true },
|
||||||
@@ -271,254 +281,150 @@ export class LayoutCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理面板大小变化对其他面板的影响
|
* 更新面板尺寸
|
||||||
* @param {String} panelPosition - 触发影响的面板位置
|
* @param {string} position - 面板位置
|
||||||
* @param {Object} influenceData - 面板影响关系数据,包含influence和influencedBy
|
* @param {Object} panelArea - 面板区域
|
||||||
* @param {Object} panelData - 包含各位置面板数据的对象
|
* @param {number} containerWidth - 容器宽度
|
||||||
* @param {HTMLElement} container - 容器元素
|
* @param {number} containerHeight - 容器高度
|
||||||
* @returns {Object} - 包含更新后面板数据的对象
|
* @param {Object} panelAreas - 所有面板区域
|
||||||
|
* @param {Object} minSizes - 最小尺寸限制
|
||||||
|
* @returns {Object} 更新后的面板边界
|
||||||
*/
|
*/
|
||||||
handlePanelSizeInfluence(panelPosition, influenceData, panelData, container) {
|
updatePanelSize(position, panelArea, containerWidth, containerHeight, panelAreas, minSizes) {
|
||||||
const updatedPanels = { ...panelData };
|
// 首先计算所有面板区域的边界
|
||||||
const containerRect = container.getBoundingClientRect();
|
this.calculatePanelBounds(panelAreas, containerWidth, containerHeight);
|
||||||
|
|
||||||
// 存储已更新的面板位置,避免重复计算
|
// 对于存在的面板区域,使用计算出的边界更新
|
||||||
const updatedPositions = new Set();
|
if (panelArea && panelArea.panels && panelArea.panels.length > 0) {
|
||||||
|
// 返回指定位置的面板边界
|
||||||
// 预先计算所有位置的可用高度和宽度,避免重复计算
|
return this.panelBounds[position];
|
||||||
const availableHeights = {
|
|
||||||
left: this.calculateAvailableHeight('left', influenceData, updatedPanels, containerRect.height, this.minSizes),
|
|
||||||
right: this.calculateAvailableHeight('right', influenceData, updatedPanels, containerRect.height, this.minSizes),
|
|
||||||
top: this.calculateAvailableHeight('top', influenceData, updatedPanels, containerRect.height, this.minSizes),
|
|
||||||
bottom: this.calculateAvailableHeight('bottom', influenceData, updatedPanels, containerRect.height, this.minSizes),
|
|
||||||
center: this.calculateAvailableHeight('center', influenceData, updatedPanels, containerRect.height, this.minSizes)
|
|
||||||
};
|
|
||||||
|
|
||||||
const availableWidths = {
|
|
||||||
left: this.calculateAvailableWidth('left', influenceData, updatedPanels, containerRect.width, this.minSizes),
|
|
||||||
right: this.calculateAvailableWidth('right', influenceData, updatedPanels, containerRect.width, this.minSizes),
|
|
||||||
top: this.calculateAvailableWidth('top', influenceData, updatedPanels, containerRect.width, this.minSizes),
|
|
||||||
bottom: this.calculateAvailableWidth('bottom', influenceData, updatedPanels, containerRect.width, this.minSizes),
|
|
||||||
center: this.calculateAvailableWidth('center', influenceData, updatedPanels, containerRect.width, this.minSizes)
|
|
||||||
};
|
|
||||||
|
|
||||||
// 1. 处理influence数组:当某个面板大小变化时,会影响哪些其他面板
|
|
||||||
if (influenceData.influence && influenceData.influence[panelPosition]) {
|
|
||||||
const influenceArray = influenceData.influence[panelPosition].value !== undefined
|
|
||||||
? influenceData.influence[panelPosition].value
|
|
||||||
: influenceData.influence[panelPosition];
|
|
||||||
|
|
||||||
if (influenceArray && Array.isArray(influenceArray)) {
|
|
||||||
influenceArray.forEach(influence => {
|
|
||||||
if (influence.influence && updatedPanels[influence.position] &&
|
|
||||||
!updatedPositions.has(influence.position)) {
|
|
||||||
|
|
||||||
// 检查updatedPanels[influence.position]是否为数组或包含panels数组
|
|
||||||
const panelArea = updatedPanels[influence.position] || {};
|
|
||||||
const panels = panelArea.panels || [];
|
|
||||||
|
|
||||||
if (panels.length > 0) {
|
|
||||||
// 根据影响的属性执行相应操作
|
|
||||||
if (influence.property === 'width') {
|
|
||||||
const availableWidth = availableWidths[influence.position] || containerRect.width;
|
|
||||||
// 从面板对象内部获取比例数据
|
|
||||||
const widthRatios = panelArea.widthRatios || null;
|
|
||||||
|
|
||||||
const result = this.calculatePanelsWidth(
|
|
||||||
panels,
|
|
||||||
availableWidth,
|
|
||||||
this.minSizes,
|
|
||||||
widthRatios
|
|
||||||
);
|
|
||||||
|
|
||||||
// 更新原始数据结构,确保始终返回包含panels属性的对象
|
|
||||||
if (!updatedPanels[influence.position]) {
|
|
||||||
updatedPanels[influence.position] = {};
|
|
||||||
}
|
|
||||||
updatedPanels[influence.position].panels = result.panels;
|
|
||||||
// 将比例数据存储在面板对象内部
|
|
||||||
updatedPanels[influence.position].widthRatios = result.widthRatios;
|
|
||||||
} else if (influence.property === 'height') {
|
|
||||||
// 使用预先计算好的可用高度
|
|
||||||
const availableHeight = availableHeights[influence.position] || this.calculateAvailableHeight(
|
|
||||||
influence.position,
|
|
||||||
influenceData,
|
|
||||||
updatedPanels,
|
|
||||||
containerRect.height,
|
|
||||||
this.minSizes
|
|
||||||
);
|
|
||||||
// 从面板对象内部获取比例数据
|
|
||||||
const heightRatios = panelArea.heightRatios || null;
|
|
||||||
|
|
||||||
const result = this.calculatePanelsHeight(
|
|
||||||
panels,
|
|
||||||
availableHeight,
|
|
||||||
this.minSizes,
|
|
||||||
heightRatios
|
|
||||||
);
|
|
||||||
|
|
||||||
// 更新原始数据结构,确保始终返回包含panels属性的对象
|
|
||||||
if (!updatedPanels[influence.position]) {
|
|
||||||
updatedPanels[influence.position] = {};
|
|
||||||
}
|
|
||||||
updatedPanels[influence.position].panels = result.panels;
|
|
||||||
// 将比例数据存储在面板对象内部
|
|
||||||
updatedPanels[influence.position].heightRatios = result.heightRatios;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标记该位置已更新
|
|
||||||
updatedPositions.add(influence.position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 处理受影响数组:在计算该面板大小时,需要考虑哪些其他面板
|
// 如果面板区域不存在或没有面板,则返回null
|
||||||
if (influenceData.influencedBy && influenceData.influencedBy[panelPosition] &&
|
return null;
|
||||||
updatedPanels[panelPosition] && !updatedPositions.has(panelPosition)) {
|
|
||||||
|
|
||||||
// 检查updatedPanels[panelPosition]是否为数组或包含panels数组
|
|
||||||
const panelArea = updatedPanels[panelPosition] || {};
|
|
||||||
const panels = panelArea.panels || [];
|
|
||||||
|
|
||||||
if (panels.length > 0) {
|
|
||||||
const influencedByArray = influenceData.influencedBy[panelPosition].value !== undefined
|
|
||||||
? influenceData.influencedBy[panelPosition].value
|
|
||||||
: influenceData.influencedBy[panelPosition];
|
|
||||||
|
|
||||||
if (influencedByArray && Array.isArray(influencedByArray)) {
|
|
||||||
// 使用预先计算的可用空间值,避免重复计算
|
|
||||||
const availableWidth = availableWidths[panelPosition];
|
|
||||||
const availableHeight = availableHeights[panelPosition];
|
|
||||||
|
|
||||||
// 更新当前面板的尺寸
|
|
||||||
// 从面板对象内部获取比例数据
|
|
||||||
const widthRatios = panelArea.widthRatios || null;
|
|
||||||
const widthResult = this.calculatePanelsWidth(
|
|
||||||
panels,
|
|
||||||
availableWidth,
|
|
||||||
this.minSizes,
|
|
||||||
widthRatios
|
|
||||||
);
|
|
||||||
|
|
||||||
// 从面板对象内部获取比例数据
|
|
||||||
const heightRatios = panelArea.heightRatios || null;
|
|
||||||
const heightResult = this.calculatePanelsHeight(
|
|
||||||
widthResult.panels, // 使用宽度计算后的面板作为输入
|
|
||||||
availableHeight,
|
|
||||||
this.minSizes,
|
|
||||||
heightRatios
|
|
||||||
);
|
|
||||||
|
|
||||||
// 确保始终返回包含panels属性的对象结构
|
|
||||||
if (!updatedPanels[panelPosition]) {
|
|
||||||
updatedPanels[panelPosition] = {};
|
|
||||||
}
|
|
||||||
updatedPanels[panelPosition].panels = heightResult.panels;
|
|
||||||
// 将比例数据存储在面板对象内部
|
|
||||||
updatedPanels[panelPosition].widthRatios = widthResult.widthRatios;
|
|
||||||
updatedPanels[panelPosition].heightRatios = heightResult.heightRatios;
|
|
||||||
|
|
||||||
// 标记该位置已更新
|
|
||||||
updatedPositions.add(panelPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return updatedPanels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算指定位置的可用高度,考虑所有被影响面板的高度
|
* 计算面板边界
|
||||||
* @param {String} position - 面板位置
|
* @param {Object} panelAreas - 所有面板区域
|
||||||
* @param {Object} influenceData - 面板影响关系数据
|
* @param {number} containerWidth - 容器宽度
|
||||||
* @param {Object} updatedPanels - 更新后面板数据
|
* @param {number} containerHeight - 容器高度
|
||||||
* @param {Number} containerHeight - 容器高度
|
* @returns {Object} 所有面板区域的边界
|
||||||
* @param {Object} minSizes - 最小尺寸限制
|
*/
|
||||||
* @returns {Number} - 可用高度
|
calculatePanelBounds(panelAreas, containerWidth, containerHeight) {
|
||||||
|
// 重置面板边界
|
||||||
|
this.panelBounds = {
|
||||||
|
left: { x: 0, y: 0, width: 0, height: 0 },
|
||||||
|
right: { x: 0, y: 0, width: 0, height: 0 },
|
||||||
|
top: { x: 0, y: 0, width: 0, height: 0 },
|
||||||
|
bottom: { x: 0, y: 0, width: 0, height: 0 },
|
||||||
|
center: { x: 0, y: 0, width: 0, height: 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 计算顶部面板边界
|
||||||
|
if (panelAreas.top && panelAreas.top.panels && panelAreas.top.panels.length > 0) {
|
||||||
|
this.panelBounds.top = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: containerWidth,
|
||||||
|
height: panelAreas.top.height || 150
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算底部面板边界
|
||||||
|
if (panelAreas.bottom && panelAreas.bottom.panels && panelAreas.bottom.panels.length > 0) {
|
||||||
|
this.panelBounds.bottom = {
|
||||||
|
x: 0,
|
||||||
|
y: containerHeight - (panelAreas.bottom.height || 200),
|
||||||
|
width: containerWidth,
|
||||||
|
height: panelAreas.bottom.height || 200
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算左侧面板边界
|
||||||
|
if (panelAreas.left && panelAreas.left.panels && panelAreas.left.panels.length > 0) {
|
||||||
|
this.panelBounds.left = {
|
||||||
|
x: 0,
|
||||||
|
y: this.panelBounds.top.height,
|
||||||
|
width: panelAreas.left.width || 300,
|
||||||
|
height: containerHeight - this.panelBounds.top.height - this.panelBounds.bottom.height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算右侧面板边界
|
||||||
|
if (panelAreas.right && panelAreas.right.panels && panelAreas.right.panels.length > 0) {
|
||||||
|
this.panelBounds.right = {
|
||||||
|
x: containerWidth - (panelAreas.right.width || 250),
|
||||||
|
y: this.panelBounds.top.height,
|
||||||
|
width: panelAreas.right.width || 250,
|
||||||
|
height: containerHeight - this.panelBounds.top.height - this.panelBounds.bottom.height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算中心面板边界
|
||||||
|
this.panelBounds.center = {
|
||||||
|
x: this.panelBounds.left.width,
|
||||||
|
y: this.panelBounds.top.height,
|
||||||
|
width: containerWidth - this.panelBounds.left.width - this.panelBounds.right.width,
|
||||||
|
height: containerHeight - this.panelBounds.top.height - this.panelBounds.bottom.height
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确保面板边界不会出现负值
|
||||||
|
Object.keys(this.panelBounds).forEach(position => {
|
||||||
|
const bounds = this.panelBounds[position];
|
||||||
|
bounds.width = Math.max(0, bounds.width);
|
||||||
|
bounds.height = Math.max(0, bounds.height);
|
||||||
|
bounds.x = Math.max(0, bounds.x);
|
||||||
|
bounds.y = Math.max(0, bounds.y);
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.panelBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理面板大小变化对其他面板的影响
|
||||||
|
* @param {string} position - 面板位置
|
||||||
|
* @param {Object} panelData - 面板数据
|
||||||
|
* @param {number} containerWidth - 容器宽度
|
||||||
|
* @param {number} containerHeight - 容器高度
|
||||||
|
* @returns {Object} 更新后的面板边界
|
||||||
|
*/
|
||||||
|
handlePanelSizeInfluence(position, panelData, containerWidth, containerHeight) {
|
||||||
|
// 确保panelData包含所有必要的面板区域数据
|
||||||
|
const panelAreas = {
|
||||||
|
left: panelData.left || { panels: [], width: 0, height: 0 },
|
||||||
|
right: panelData.right || { panels: [], width: 0, height: 0 },
|
||||||
|
top: panelData.top || { panels: [], width: 0, height: 0 },
|
||||||
|
bottom: panelData.bottom || { panels: [], width: 0, height: 0 },
|
||||||
|
center: panelData.center || { panels: [], width: 0, height: 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重新计算所有面板边界
|
||||||
|
this.calculatePanelBounds(panelAreas, containerWidth, containerHeight);
|
||||||
|
|
||||||
|
// 返回更新后的面板边界
|
||||||
|
return this.panelBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算指定位置的可用高度
|
||||||
*/
|
*/
|
||||||
calculateAvailableHeight(position, influenceData, updatedPanels, containerHeight, minSizes) {
|
calculateAvailableHeight(position, influenceData, updatedPanels, containerHeight, minSizes) {
|
||||||
// 从容器高度开始
|
const panelBounds = this.calculatePanelBounds(0, containerHeight);
|
||||||
let availableHeight = containerHeight;
|
return panelBounds[position].height || minSizes.panelHeight;
|
||||||
let panelHeight = updatedPanels[position].height || 0;
|
|
||||||
// 如果有受影响关系数据,考虑被其他面板占用的空间
|
|
||||||
if (influenceData.influencedBy && influenceData.influencedBy[position]) {
|
|
||||||
const influencedByArray = influenceData.influencedBy[position].value !== undefined
|
|
||||||
? influenceData.influencedBy[position].value
|
|
||||||
: influenceData.influencedBy[position];
|
|
||||||
|
|
||||||
if (influencedByArray && Array.isArray(influencedByArray)) {
|
|
||||||
influencedByArray.forEach(influencedBy => {
|
|
||||||
if (influencedBy.influence && influencedBy.property === 'height') {
|
|
||||||
// 检查是否是面板区对象,如果是则提取panels数组
|
|
||||||
const panelArea = updatedPanels[influencedBy.position] || {};
|
|
||||||
const occupiedHeight = panelArea.panels && panelArea.panels.length > 0 ? panelArea.height : 0;
|
|
||||||
availableHeight -= occupiedHeight;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确保可用空间不小于最小值
|
|
||||||
// 检查是否是面板区对象,如果是则提取panels数组
|
|
||||||
const panelArea = updatedPanels[position] || {};
|
|
||||||
const panels = panelArea.panels || [];
|
|
||||||
const cnt = position == 'center' ? 1 : panels.length;
|
|
||||||
panelHeight = Math.max(minSizes.panelHeight * cnt, panelHeight);
|
|
||||||
const height = availableHeight > minSizes.panelHeight ? availableHeight : panelHeight;
|
|
||||||
return cnt > 0 ? height : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算指定位置的可用宽度,考虑所有被影响面板的宽度
|
* 计算指定位置的可用宽度
|
||||||
* @param {String} position - 面板位置
|
|
||||||
* @param {Object} influenceData - 面板影响关系数据
|
|
||||||
* @param {Object} updatedPanels - 更新后面板数据
|
|
||||||
* @param {Number} containerWidth - 容器宽度
|
|
||||||
* @param {Object} minSizes - 最小尺寸限制
|
|
||||||
* @returns {Number} - 可用宽度
|
|
||||||
*/
|
*/
|
||||||
calculateAvailableWidth(position, influenceData, updatedPanels, containerWidth, minSizes) {
|
calculateAvailableWidth(position, influenceData, updatedPanels, containerWidth, minSizes) {
|
||||||
// 从容器宽度开始
|
const panelBounds = this.calculatePanelBounds(containerWidth, 0);
|
||||||
let availableWidth = containerWidth;
|
return panelBounds[position].width || minSizes.panelWidth;
|
||||||
let panelWidth = updatedPanels[position].width || 0;
|
|
||||||
// 如果有受影响关系数据,考虑被其他面板占用的空间
|
|
||||||
if (influenceData.influencedBy && influenceData.influencedBy[position]) {
|
|
||||||
const influencedByArray = influenceData.influencedBy[position].value !== undefined
|
|
||||||
? influenceData.influencedBy[position].value
|
|
||||||
: influenceData.influencedBy[position];
|
|
||||||
|
|
||||||
if (influencedByArray && Array.isArray(influencedByArray)) {
|
|
||||||
influencedByArray.forEach(influencedBy => {
|
|
||||||
if (influencedBy.influence && influencedBy.property === 'width') {
|
|
||||||
// 检查是否是面板区对象,如果是则提取panels数组
|
|
||||||
const panelArea = updatedPanels[influencedBy.position] || {};
|
|
||||||
const occupiedWidth = panelArea.panels && panelArea.panels.length > 0 ? panelArea.width : 0;
|
|
||||||
availableWidth -= occupiedWidth;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确保可用空间不小于最小值
|
|
||||||
// 检查是否是面板区对象,如果是则提取panels数组
|
|
||||||
const panelArea = updatedPanels[position] || {};
|
|
||||||
const panels = panelArea.panels || [];
|
|
||||||
const cnt = position == 'center' ? 1 : panels.length;
|
|
||||||
panelWidth = Math.max(minSizes.panelWidth * cnt, panelWidth);
|
|
||||||
const width = availableWidth > minSizes.panelWidth ? availableWidth : panelWidth;
|
|
||||||
return panels.length > 0 ? width : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算并更新面板的宽度,确保它们均匀分布并撑满整个区域
|
* 计算并更新面板的宽度
|
||||||
* @param {Array} panels - 面板数组
|
*/
|
||||||
* @param {Number} availableWidth - 可用宽度
|
|
||||||
* @param {Object} minSizes - 最小尺寸限制
|
|
||||||
* @param {Array} widthRatios - 宽度比例数组(可选)
|
|
||||||
* @returns {Object} - 包含更新后面板和宽度比例的对象
|
|
||||||
*/
|
|
||||||
calculatePanelsWidth(panels, availableWidth, minSizes, widthRatios = null) {
|
calculatePanelsWidth(panels, availableWidth, minSizes, widthRatios = null) {
|
||||||
if (panels.length === 0) return { panels, widthRatios: null };
|
if (panels.length === 0) return { panels, widthRatios: null };
|
||||||
|
|
||||||
@@ -535,17 +441,15 @@ export class LayoutCoordinator {
|
|||||||
} else {
|
} else {
|
||||||
// 如果已有保存的宽度比例,则根据比例重新计算宽度
|
// 如果已有保存的宽度比例,则根据比例重新计算宽度
|
||||||
if (widthRatios && widthRatios.length === panelCount) {
|
if (widthRatios && widthRatios.length === panelCount) {
|
||||||
// 使用保存的比例计算宽度
|
|
||||||
calculatedWidth = Math.max(minSizes.panelWidth,
|
calculatedWidth = Math.max(minSizes.panelWidth,
|
||||||
Math.floor(availableWidth * widthRatios[index])
|
Math.floor(availableWidth * widthRatios[index])
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// 多个面板时均匀分配宽度
|
// 多个面板时均匀分配宽度
|
||||||
const baseWidth = Math.floor(availableWidth / panelCount);
|
const baseWidth = Math.floor(availableWidth / panelCount);
|
||||||
const remainder = availableWidth % panelCount; // 用于处理整数除法的余数
|
const remainder = availableWidth % panelCount;
|
||||||
|
|
||||||
calculatedWidth = Math.max(minSizes.panelWidth,
|
calculatedWidth = Math.max(minSizes.panelWidth,
|
||||||
// 将余数分配给前面的面板,使总宽度刚好等于availableWidth
|
|
||||||
index < remainder ? baseWidth + 1 : baseWidth
|
index < remainder ? baseWidth + 1 : baseWidth
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -567,12 +471,7 @@ export class LayoutCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算并更新面板的高度,确保它们均匀分布并撑满整个区域
|
* 计算并更新面板的高度
|
||||||
* @param {Array} panels - 面板数组
|
|
||||||
* @param {Number} availableHeight - 可用高度
|
|
||||||
* @param {Object} minSizes - 最小尺寸限制
|
|
||||||
* @param {Array} heightRatios - 高度比例数组(可选)
|
|
||||||
* @returns {Object} - 包含更新后面板和高度比例的对象
|
|
||||||
*/
|
*/
|
||||||
calculatePanelsHeight(panels, availableHeight, minSizes, heightRatios = null) {
|
calculatePanelsHeight(panels, availableHeight, minSizes, heightRatios = null) {
|
||||||
if (panels.length === 0) return { panels, heightRatios: null };
|
if (panels.length === 0) return { panels, heightRatios: null };
|
||||||
@@ -590,17 +489,15 @@ export class LayoutCoordinator {
|
|||||||
} else {
|
} else {
|
||||||
// 如果已有保存的高度比例,则根据比例重新计算高度
|
// 如果已有保存的高度比例,则根据比例重新计算高度
|
||||||
if (heightRatios && heightRatios.length === panelCount) {
|
if (heightRatios && heightRatios.length === panelCount) {
|
||||||
// 使用保存的比例计算高度
|
|
||||||
calculatedHeight = Math.max(minSizes.panelHeight,
|
calculatedHeight = Math.max(minSizes.panelHeight,
|
||||||
Math.floor(availableHeight * heightRatios[index])
|
Math.floor(availableHeight * heightRatios[index])
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// 多个面板时均匀分配高度
|
// 多个面板时均匀分配高度
|
||||||
const baseHeight = Math.floor(availableHeight / panelCount);
|
const baseHeight = Math.floor(availableHeight / panelCount);
|
||||||
const remainder = availableHeight % panelCount; // 用于处理整数除法的余数
|
const remainder = availableHeight % panelCount;
|
||||||
|
|
||||||
calculatedHeight = Math.max(minSizes.panelHeight,
|
calculatedHeight = Math.max(minSizes.panelHeight,
|
||||||
// 将余数分配给前面的面板,使总高度刚好等于availableHeight
|
|
||||||
index < remainder ? baseHeight + 1 : baseHeight
|
index < remainder ? baseHeight + 1 : baseHeight
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -622,27 +519,17 @@ export class LayoutCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置面板尺寸比例,确保均匀分布
|
* 重置面板尺寸比例
|
||||||
* @param {Number} panelCount - 面板数量
|
|
||||||
* @returns {Array} - 重置后的比例数组
|
|
||||||
*/
|
*/
|
||||||
resetPanelsSizeRatios(panelCount) {
|
resetPanelsSizeRatios(panelCount) {
|
||||||
if (panelCount > 0) {
|
if (panelCount > 0) {
|
||||||
// 为每个面板分配相同的比例
|
|
||||||
return Array(panelCount).fill(1 / panelCount);
|
return Array(panelCount).fill(1 / panelCount);
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新面板尺寸,确保它们均匀分布并撑满整个区域
|
* 更新面板尺寸
|
||||||
* @param {String} position - 面板位置 ('top', 'bottom', 'left', 'right')
|
|
||||||
* @param {Array} panels - 面板数组
|
|
||||||
* @param {Array} ratios - 尺寸比例数组
|
|
||||||
* @param {HTMLElement} container - 容器元素
|
|
||||||
* @param {Object} minSizes - 最小尺寸限制
|
|
||||||
* @param {Object} panelHeights - 包含顶部和底部面板高度的对象
|
|
||||||
* @returns {Object} - 包含更新后面板和比例的对象
|
|
||||||
*/
|
*/
|
||||||
updatePanelsSize(position, panels, ratios, container, minSizes, panelHeights = {}) {
|
updatePanelsSize(position, panels, ratios, container, minSizes, panelHeights = {}) {
|
||||||
if (!container || panels.length === 0) {
|
if (!container || panels.length === 0) {
|
||||||
@@ -650,13 +537,14 @@ export class LayoutCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const containerRect = container.getBoundingClientRect();
|
const containerRect = container.getBoundingClientRect();
|
||||||
|
// 使用绝对定位计算的面板边界
|
||||||
|
const panelBounds = this.calculatePanelBounds(containerRect.width, containerRect.height);
|
||||||
|
|
||||||
switch (position) {
|
switch (position) {
|
||||||
case 'top':
|
case 'top':
|
||||||
case 'bottom': {
|
case 'bottom': {
|
||||||
const availableWidth = containerRect.width;
|
const availableWidth = panelBounds[position].width;
|
||||||
|
|
||||||
// 使用布局协调器计算面板宽度
|
|
||||||
const result = this.calculatePanelsWidth(
|
const result = this.calculatePanelsWidth(
|
||||||
panels,
|
panels,
|
||||||
availableWidth,
|
availableWidth,
|
||||||
@@ -669,19 +557,11 @@ export class LayoutCoordinator {
|
|||||||
|
|
||||||
case 'left':
|
case 'left':
|
||||||
case 'right': {
|
case 'right': {
|
||||||
// 为垂直排列的面板计算高度
|
const availableHeight = panelBounds[position].height;
|
||||||
const totalHeight = containerRect.height -
|
|
||||||
(panelHeights.top || 0) -
|
|
||||||
(panelHeights.bottom || 0);
|
|
||||||
|
|
||||||
if (totalHeight <= 0) {
|
|
||||||
return { panels, ratios };
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用布局协调器计算面板高度
|
|
||||||
const result = this.calculatePanelsHeight(
|
const result = this.calculatePanelsHeight(
|
||||||
panels,
|
panels,
|
||||||
totalHeight,
|
availableHeight,
|
||||||
minSizes,
|
minSizes,
|
||||||
ratios
|
ratios
|
||||||
);
|
);
|
||||||
@@ -693,4 +573,35 @@ export class LayoutCoordinator {
|
|||||||
return { panels, ratios };
|
return { panels, ratios };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存当前布局配置
|
||||||
|
* @returns {String} - 布局配置的JSON字符串
|
||||||
|
*/
|
||||||
|
saveLayout() {
|
||||||
|
return JSON.stringify(this.panelBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载布局配置
|
||||||
|
* @param {String} layoutConfig - 布局配置的JSON字符串
|
||||||
|
*/
|
||||||
|
loadLayout(layoutConfig) {
|
||||||
|
try {
|
||||||
|
const config = JSON.parse(layoutConfig);
|
||||||
|
// 验证配置有效性并应用
|
||||||
|
if (config && typeof config === 'object') {
|
||||||
|
Object.keys(config).forEach(position => {
|
||||||
|
if (this.panelBounds[position] && typeof config[position] === 'object') {
|
||||||
|
this.panelBounds[position] = {
|
||||||
|
...this.panelBounds[position],
|
||||||
|
...config[position]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to load layout config:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -176,13 +176,18 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
function addPanel(panel, minSizes = { panelWidth: 150, panelHeight: 100 }) {
|
function addPanel(panel, minSizes = { panelWidth: 150, panelHeight: 100 }) {
|
||||||
const panelData = {
|
const panelData = {
|
||||||
...panel,
|
...panel,
|
||||||
|
id: panel.id || generateUniqueId(),
|
||||||
collapsed: panel.collapsed || false,
|
collapsed: panel.collapsed || false,
|
||||||
lastPosition: panel.position,
|
lastPosition: panel.position,
|
||||||
lastSize: panel.lastSize || {
|
lastSize: panel.lastSize || {
|
||||||
width: panel.width || 300,
|
width: panel.width || 300,
|
||||||
height: panel.height || 200
|
height: panel.height || 200
|
||||||
},
|
},
|
||||||
width: panel.width || 300
|
width: panel.width || 300,
|
||||||
|
height: panel.height || 200,
|
||||||
|
// 初始化绝对定位坐标
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取全局容器元素(只查询一次DOM)
|
// 获取全局容器元素(只查询一次DOM)
|
||||||
@@ -193,7 +198,7 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
const isLeftFirst = leftPanels.value.length === 0
|
const isLeftFirst = leftPanels.value.length === 0
|
||||||
leftPanelArea.value.panels.push(panelData)
|
leftPanelArea.value.panels.push(panelData)
|
||||||
resetPanelsSizeRatios('left')
|
resetPanelsSizeRatios('left')
|
||||||
// 使用全局容器元素更新面板尺寸
|
// 使用全局容器元素更新面板尺寸和绝对位置
|
||||||
if (container) {
|
if (container) {
|
||||||
updatePanelsSize('left', leftPanelArea.value, container, minSizes);
|
updatePanelsSize('left', leftPanelArea.value, container, minSizes);
|
||||||
}
|
}
|
||||||
@@ -206,7 +211,7 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
const isRightFirst = rightPanels.value.length === 0
|
const isRightFirst = rightPanels.value.length === 0
|
||||||
rightPanelArea.value.panels.push(panelData)
|
rightPanelArea.value.panels.push(panelData)
|
||||||
resetPanelsSizeRatios('right')
|
resetPanelsSizeRatios('right')
|
||||||
// 使用全局容器元素更新面板尺寸
|
// 使用全局容器元素更新面板尺寸和绝对位置
|
||||||
if (container) {
|
if (container) {
|
||||||
updatePanelsSize('right', rightPanelArea.value, container, minSizes);
|
updatePanelsSize('right', rightPanelArea.value, container, minSizes);
|
||||||
}
|
}
|
||||||
@@ -219,7 +224,7 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
const isTopFirst = topPanels.value.length === 0
|
const isTopFirst = topPanels.value.length === 0
|
||||||
topPanelArea.value.panels.push(panelData)
|
topPanelArea.value.panels.push(panelData)
|
||||||
resetPanelsSizeRatios('top')
|
resetPanelsSizeRatios('top')
|
||||||
// 使用全局容器元素更新面板尺寸
|
// 使用全局容器元素更新面板尺寸和绝对位置
|
||||||
if (container) {
|
if (container) {
|
||||||
updatePanelsSize('top', topPanelArea.value, container, minSizes);
|
updatePanelsSize('top', topPanelArea.value, container, minSizes);
|
||||||
}
|
}
|
||||||
@@ -232,7 +237,7 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
const isBottomFirst = bottomPanels.value.length === 0
|
const isBottomFirst = bottomPanels.value.length === 0
|
||||||
bottomPanelArea.value.panels.push(panelData)
|
bottomPanelArea.value.panels.push(panelData)
|
||||||
resetPanelsSizeRatios('bottom')
|
resetPanelsSizeRatios('bottom')
|
||||||
// 使用全局容器元素更新面板尺寸
|
// 使用全局容器元素更新面板尺寸和绝对位置
|
||||||
if (container) {
|
if (container) {
|
||||||
updatePanelsSize('bottom', bottomPanelArea.value, container, minSizes);
|
updatePanelsSize('bottom', bottomPanelArea.value, container, minSizes);
|
||||||
}
|
}
|
||||||
@@ -245,7 +250,7 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
default:
|
default:
|
||||||
centerPanelArea.value.panels.push(panelData)
|
centerPanelArea.value.panels.push(panelData)
|
||||||
resetPanelsSizeRatios('center')
|
resetPanelsSizeRatios('center')
|
||||||
// 使用全局容器元素更新中心面板尺寸
|
// 使用全局容器元素更新中心面板尺寸和绝对位置
|
||||||
if (container) {
|
if (container) {
|
||||||
updatePanelsSize('center', centerPanelArea.value, container, minSizes);
|
updatePanelsSize('center', centerPanelArea.value, container, minSizes);
|
||||||
}
|
}
|
||||||
@@ -259,6 +264,12 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
function resetPanelsSizeRatios(position) {
|
function resetPanelsSizeRatios(position) {
|
||||||
let panelArea
|
let panelArea
|
||||||
|
|
||||||
|
// 支持两种调用方式:传入position字符串或直接传入面板数量
|
||||||
|
if (typeof position === 'number') {
|
||||||
|
// 当直接传入面板数量时,返回均匀分配的比例数组
|
||||||
|
return Array(position).fill(1 / position)
|
||||||
|
}
|
||||||
|
|
||||||
switch (position) {
|
switch (position) {
|
||||||
case 'top':
|
case 'top':
|
||||||
panelArea = topPanelArea.value
|
panelArea = topPanelArea.value
|
||||||
@@ -616,9 +627,11 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
|
|
||||||
// 重置所有面板状态
|
// 重置所有面板状态
|
||||||
function resetLayout() {
|
function resetLayout() {
|
||||||
// 重置面板区对象,确保每个面板区域都包含width和height属性
|
// 重置面板区对象,确保每个面板区域都包含width、height和位置信息
|
||||||
leftPanelArea.value = {
|
leftPanelArea.value = {
|
||||||
panels: [],
|
panels: [],
|
||||||
|
x: 0, // 绝对定位的x坐标
|
||||||
|
y: 0, // 绝对定位的y坐标
|
||||||
width: 300,
|
width: 300,
|
||||||
height: 0, // 初始高度为0,将在updatePanelsSize中被正确设置
|
height: 0, // 初始高度为0,将在updatePanelsSize中被正确设置
|
||||||
heightRatios: []
|
heightRatios: []
|
||||||
@@ -626,6 +639,8 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
|
|
||||||
rightPanelArea.value = {
|
rightPanelArea.value = {
|
||||||
panels: [],
|
panels: [],
|
||||||
|
x: 0, // 初始x坐标,将在updatePanelsSize中被正确设置
|
||||||
|
y: 0, // 绝对定位的y坐标
|
||||||
width: 250,
|
width: 250,
|
||||||
height: 0, // 初始高度为0,将在updatePanelsSize中被正确设置
|
height: 0, // 初始高度为0,将在updatePanelsSize中被正确设置
|
||||||
heightRatios: []
|
heightRatios: []
|
||||||
@@ -633,6 +648,8 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
|
|
||||||
topPanelArea.value = {
|
topPanelArea.value = {
|
||||||
panels: [],
|
panels: [],
|
||||||
|
x: 0, // 绝对定位的x坐标
|
||||||
|
y: 0, // 绝对定位的y坐标
|
||||||
height: 150,
|
height: 150,
|
||||||
width: 0, // 初始宽度为0,将在updatePanelsSize中被正确设置
|
width: 0, // 初始宽度为0,将在updatePanelsSize中被正确设置
|
||||||
widthRatios: []
|
widthRatios: []
|
||||||
@@ -640,13 +657,24 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
|
|
||||||
bottomPanelArea.value = {
|
bottomPanelArea.value = {
|
||||||
panels: [],
|
panels: [],
|
||||||
|
x: 0, // 绝对定位的x坐标
|
||||||
|
y: 0, // 初始y坐标,将在updatePanelsSize中被正确设置
|
||||||
height: 200,
|
height: 200,
|
||||||
width: 0, // 初始宽度为0,将在updatePanelsSize中被正确设置
|
width: 0, // 初始宽度为0,将在updatePanelsSize中被正确设置
|
||||||
widthRatios: []
|
widthRatios: []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
centerPanelArea.value = {
|
||||||
|
panels: [],
|
||||||
|
x: 0, // 初始x坐标,将在updatePanelsSize中被正确设置
|
||||||
|
y: 0, // 初始y坐标,将在updatePanelsSize中被正确设置
|
||||||
|
width: 0, // 初始宽度为0,将在updatePanelsSize中被正确设置
|
||||||
|
height: 0, // 初始高度为0,将在updatePanelsSize中被正确设置
|
||||||
|
widthRatios: [],
|
||||||
|
heightRatios: []
|
||||||
|
}
|
||||||
|
|
||||||
// 清空其他面板集合
|
// 清空其他面板集合
|
||||||
centerPanelArea.value.panels = []
|
|
||||||
floatingWindows.value = []
|
floatingWindows.value = []
|
||||||
minimizedWindows.value = []
|
minimizedWindows.value = []
|
||||||
}
|
}
|
||||||
@@ -674,26 +702,16 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
|
|
||||||
// 初始化面板大小影响关系和受影响关系
|
// 初始化面板大小影响关系和受影响关系
|
||||||
function initializePanelSizeInfluence() {
|
function initializePanelSizeInfluence() {
|
||||||
// 初始化影响关系数据
|
// 使用LayoutCoordinator初始化面板边界系统
|
||||||
['left', 'right', 'top', 'bottom','center'].forEach(position => {
|
// 在新的绝对定位布局系统中,影响关系已内置到calculatePanelBounds方法中
|
||||||
panelSizeInfluence.influence[position].value = []
|
// 这里可以保留接口兼容性,但实际工作由LayoutCoordinator处理
|
||||||
panelSizeInfluence.influencedBy[position].value = []
|
const influenceData = layoutCoordinator.initializePanelSizeInfluence();
|
||||||
})
|
|
||||||
|
|
||||||
// 使用LayoutCoordinator初始化影响关系
|
// 初始化影响关系数据(为了保持兼容性)
|
||||||
const influenceData = layoutCoordinator.initializePanelSizeInfluence()
|
['left', 'right', 'top', 'bottom', 'center'].forEach(position => {
|
||||||
|
panelSizeInfluence.influence[position].value = influenceData?.influence?.[position] || [];
|
||||||
// 应用影响关系数据
|
panelSizeInfluence.influencedBy[position].value = influenceData?.influencedBy?.[position] || [];
|
||||||
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]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理面板大小变化对其他面板的影响
|
// 处理面板大小变化对其他面板的影响
|
||||||
@@ -714,74 +732,84 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
|
|
||||||
if (!externalContainer) return;
|
if (!externalContainer) return;
|
||||||
|
|
||||||
// 调用布局协调器处理面板大小影响
|
// 获取容器尺寸
|
||||||
const updatedPanels = layoutCoordinator.handlePanelSizeInfluence(
|
const containerWidth = externalContainer.clientWidth;
|
||||||
|
const containerHeight = externalContainer.clientHeight;
|
||||||
|
|
||||||
|
// 调用更新后的布局协调器处理面板大小影响
|
||||||
|
// 现在使用面板边界系统处理影响关系
|
||||||
|
const updatedBounds = layoutCoordinator.handlePanelSizeInfluence(
|
||||||
position,
|
position,
|
||||||
{
|
|
||||||
influence: panelSizeInfluence.influence,
|
|
||||||
influencedBy: panelSizeInfluence.influencedBy
|
|
||||||
},
|
|
||||||
panelData,
|
panelData,
|
||||||
externalContainer
|
containerWidth,
|
||||||
|
containerHeight
|
||||||
);
|
);
|
||||||
|
|
||||||
// 更新面板数据(包括面板区域本身的尺寸和内部的panels数组)
|
// 更新所有面板区域的边界信息
|
||||||
// 为每个位置定义对应的面板区域变量
|
if (updatedBounds) {
|
||||||
const panelAreaMap = {
|
// 为每个位置定义对应的面板区域变量
|
||||||
left: leftPanelArea.value,
|
const panelAreaMap = {
|
||||||
right: rightPanelArea.value,
|
left: leftPanelArea.value,
|
||||||
top: topPanelArea.value,
|
right: rightPanelArea.value,
|
||||||
bottom: bottomPanelArea.value,
|
top: topPanelArea.value,
|
||||||
center: centerPanelArea.value
|
bottom: bottomPanelArea.value,
|
||||||
};
|
center: centerPanelArea.value
|
||||||
|
};
|
||||||
|
|
||||||
const positions = ['left', 'right', 'top', 'bottom', 'center'];
|
const positions = ['left', 'right', 'top', 'bottom', 'center'];
|
||||||
positions.forEach(pos => {
|
positions.forEach(pos => {
|
||||||
if (updatedPanels && updatedPanels[pos]) {
|
if (updatedBounds[pos]) {
|
||||||
const panelArea = panelAreaMap[pos];
|
const panelArea = panelAreaMap[pos];
|
||||||
|
|
||||||
// 首先更新面板区域本身的宽高属性(如果有)
|
// 更新面板区域的位置和尺寸信息
|
||||||
if (updatedPanels[pos].width !== undefined) {
|
if (updatedBounds[pos].x !== undefined) {
|
||||||
panelArea.width = updatedPanels[pos].width;
|
panelArea.x = updatedBounds[pos].x;
|
||||||
}
|
}
|
||||||
if (updatedPanels[pos].height !== undefined) {
|
if (updatedBounds[pos].y !== undefined) {
|
||||||
panelArea.height = updatedPanels[pos].height;
|
panelArea.y = updatedBounds[pos].y;
|
||||||
|
}
|
||||||
|
if (updatedBounds[pos].width !== undefined) {
|
||||||
|
panelArea.width = updatedBounds[pos].width;
|
||||||
|
}
|
||||||
|
if (updatedBounds[pos].height !== undefined) {
|
||||||
|
panelArea.height = updatedBounds[pos].height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 更新panels数组
|
// 触发面板区域的响应式更新
|
||||||
if (updatedPanels[pos].panels) {
|
leftPanelArea.value = { ...leftPanelArea.value };
|
||||||
panelArea.panels = updatedPanels[pos].panels;
|
rightPanelArea.value = { ...rightPanelArea.value };
|
||||||
}
|
topPanelArea.value = { ...topPanelArea.value };
|
||||||
|
bottomPanelArea.value = { ...bottomPanelArea.value };
|
||||||
|
centerPanelArea.value = { ...centerPanelArea.value };
|
||||||
|
|
||||||
// 更新比例数据
|
// 显式调用updatePanelsSize来更新所有面板区域的子面板尺寸和位置,确保子面板大小随面板区域变化
|
||||||
if (updatedPanels[pos].widthRatios) {
|
if (leftPanelArea.value && leftPanelArea.value.panels && leftPanelArea.value.panels.length > 0) {
|
||||||
panelArea.widthRatios = updatedPanels[pos].widthRatios;
|
updatePanelsSize('left', leftPanelArea.value, externalContainer);
|
||||||
}
|
}
|
||||||
if (updatedPanels[pos].heightRatios) {
|
if (rightPanelArea.value && rightPanelArea.value.panels && rightPanelArea.value.panels.length > 0) {
|
||||||
panelArea.heightRatios = updatedPanels[pos].heightRatios;
|
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);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// 显式调用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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新面板尺寸
|
/**
|
||||||
|
* 更新面板尺寸
|
||||||
|
* @param {string} position - 面板位置
|
||||||
|
* @param {Object} panelArea - 面板区域对象
|
||||||
|
* @param {HTMLElement} container - 容器元素
|
||||||
|
* @param {Object} minSizes - 最小尺寸配置
|
||||||
|
*/
|
||||||
function updatePanelsSize(position, panelArea, container, minSizes = { panelWidth: 150, panelHeight: 100 }) {
|
function updatePanelsSize(position, panelArea, container, minSizes = { panelWidth: 150, panelHeight: 100 }) {
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
@@ -801,97 +829,75 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
center: centerPanelArea.value
|
center: centerPanelArea.value
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理不同位置的面板尺寸更新
|
// 使用LayoutCoordinator的updatePanelSize方法更新面板尺寸
|
||||||
if (position === 'top' || position === 'bottom') {
|
const updatedBounds = layoutCoordinator.updatePanelSize(
|
||||||
// 顶部和底部面板 - 水平排列
|
position,
|
||||||
// 更新面板区域的完整宽高信息
|
panelArea,
|
||||||
panelArea.width = layoutCoordinator.calculateAvailableWidth(
|
containerWidth,
|
||||||
position,
|
containerHeight,
|
||||||
panelSizeInfluence,
|
panelAreas,
|
||||||
panelAreas,
|
minSizes
|
||||||
containerWidth,
|
);
|
||||||
minSizes
|
|
||||||
);
|
|
||||||
// 使用当前面板区域的实际高度(已通过分割条调整后的高度)
|
|
||||||
panelArea.height = position === 'top' ? topPanelArea.value.height : bottomPanelArea.value.height;
|
|
||||||
|
|
||||||
// 确保有宽度比例数组,并且长度与面板数量匹配
|
// 更新面板区域的位置和尺寸信息
|
||||||
if (!panelArea.widthRatios || panelArea.widthRatios.length !== panelArea.panels.length) {
|
if (updatedBounds) {
|
||||||
panelArea.widthRatios = resetPanelsSizeRatios(panelArea.panels.length);
|
// 应用边界信息到面板区域
|
||||||
|
panelArea.x = updatedBounds.x;
|
||||||
|
panelArea.y = updatedBounds.y;
|
||||||
|
panelArea.width = updatedBounds.width;
|
||||||
|
panelArea.height = updatedBounds.height;
|
||||||
|
|
||||||
|
// 根据面板位置应用不同的面板排列逻辑
|
||||||
|
if (position === 'top' || position === 'bottom') {
|
||||||
|
// 顶部和底部面板 - 水平排列
|
||||||
|
// 确保有宽度比例数组,并且长度与面板数量匹配
|
||||||
|
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 = updatedBounds.height;
|
||||||
|
// 设置面板的绝对位置
|
||||||
|
panel.x = updatedBounds.x + panelArea.panels.slice(0, index).reduce((sum, p) => {
|
||||||
|
const pIndex = panelArea.panels.indexOf(p);
|
||||||
|
return sum + (p.width || (panelArea.widthRatios[pIndex] * panelArea.width));
|
||||||
|
}, 0);
|
||||||
|
panel.y = updatedBounds.y;
|
||||||
|
});
|
||||||
|
} else if (position === 'left' || position === 'right') {
|
||||||
|
// 左侧和右侧面板 - 垂直排列
|
||||||
|
// 确保有高度比例数组,并且长度与面板数量匹配
|
||||||
|
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 = updatedBounds.width;
|
||||||
|
// 设置面板的绝对位置
|
||||||
|
panel.x = updatedBounds.x;
|
||||||
|
panel.y = updatedBounds.y + panelArea.panels.slice(0, index).reduce((sum, p) => {
|
||||||
|
const pIndex = panelArea.panels.indexOf(p);
|
||||||
|
return sum + (p.height || (panelArea.heightRatios[pIndex] * panelArea.height));
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
} else if (position === 'center') {
|
||||||
|
// 中心面板的尺寸和位置设置
|
||||||
|
// 应用面板宽高和绝对位置(中心面板通常是标签页形式,所有面板共享相同的宽高)
|
||||||
|
panelArea.panels.forEach((panel) => {
|
||||||
|
panel.width = updatedBounds.width;
|
||||||
|
panel.height = updatedBounds.height;
|
||||||
|
panel.x = updatedBounds.x;
|
||||||
|
panel.y = updatedBounds.y;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应用面板宽度比例
|
|
||||||
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;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应用更新后的面板数据,触发响应式更新
|
// 应用更新后的面板数据,触发响应式更新
|
||||||
@@ -942,38 +948,60 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
|||||||
|
|
||||||
// 包装LayoutCoordinator的adjustRegionSize方法
|
// 包装LayoutCoordinator的adjustRegionSize方法
|
||||||
function adjustRegionSize(target, delta, container = null) {
|
function adjustRegionSize(target, delta, container = null) {
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
// 准备面板区域数据
|
||||||
const panelAreas = {
|
const panelAreas = {
|
||||||
top: topPanelArea.value,
|
top: topPanelArea.value,
|
||||||
bottom: bottomPanelArea.value,
|
bottom: bottomPanelArea.value,
|
||||||
left: leftPanelArea.value,
|
left: leftPanelArea.value,
|
||||||
right: rightPanelArea.value
|
right: rightPanelArea.value,
|
||||||
}
|
center: centerPanelArea.value
|
||||||
|
};
|
||||||
|
|
||||||
let containerHeight = null
|
// 获取容器尺寸
|
||||||
if (container) {
|
const containerWidth = container.clientWidth;
|
||||||
containerHeight = container.clientHeight
|
const containerHeight = container.clientHeight;
|
||||||
}
|
|
||||||
|
|
||||||
let newSize
|
// 调用更新后的adjustRegionSize方法,获取更新后的面板边界
|
||||||
switch (target) {
|
const updatedBounds = layoutCoordinator.adjustRegionSize(
|
||||||
case 'left':
|
target,
|
||||||
newSize = layoutCoordinator.adjustRegionSize('left', panelAreas.left.width, delta)
|
delta,
|
||||||
panelAreas.left.width = newSize
|
panelAreas,
|
||||||
|
containerWidth,
|
||||||
|
containerHeight
|
||||||
|
);
|
||||||
|
|
||||||
break
|
// 更新面板区域的位置和尺寸信息
|
||||||
case 'right':
|
if (updatedBounds) {
|
||||||
newSize = layoutCoordinator.adjustRegionSize('right', panelAreas.right.width, -delta)
|
// 更新受影响区域的尺寸和位置
|
||||||
panelAreas.right.width = newSize
|
Object.keys(updatedBounds).forEach(position => {
|
||||||
break
|
const bounds = updatedBounds[position];
|
||||||
case 'top':
|
const panelArea = panelAreas[position];
|
||||||
newSize = layoutCoordinator.adjustRegionSize('top', panelAreas.top.height, delta, panelAreas, containerHeight)
|
|
||||||
panelAreas.top.height = newSize
|
|
||||||
|
|
||||||
break
|
if (bounds.x !== undefined) {
|
||||||
case 'bottom':
|
panelArea.x = bounds.x;
|
||||||
newSize = layoutCoordinator.adjustRegionSize('bottom', panelAreas.bottom.height, -delta, panelAreas, containerHeight)
|
}
|
||||||
panelAreas.bottom.height = newSize
|
if (bounds.y !== undefined) {
|
||||||
break
|
panelArea.y = bounds.y;
|
||||||
|
}
|
||||||
|
if (bounds.width !== undefined) {
|
||||||
|
panelArea.width = bounds.width;
|
||||||
|
}
|
||||||
|
if (bounds.height !== undefined) {
|
||||||
|
panelArea.height = bounds.height;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 触发面板区域的响应式更新
|
||||||
|
leftPanelArea.value = { ...leftPanelArea.value };
|
||||||
|
rightPanelArea.value = { ...rightPanelArea.value };
|
||||||
|
topPanelArea.value = { ...topPanelArea.value };
|
||||||
|
bottomPanelArea.value = { ...bottomPanelArea.value };
|
||||||
|
centerPanelArea.value = { ...centerPanelArea.value };
|
||||||
|
|
||||||
|
// 应用尺寸变化后,处理面板大小对其他面板的影响
|
||||||
|
handlePanelSizeInfluence(target, container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user