增加重算列表
This commit is contained in:
@@ -303,6 +303,7 @@ const container = ref(null);
|
||||
// 初始化Pinia store
|
||||
const store = useDockPanelStore();
|
||||
|
||||
// 基于 watch 的受影响重算已移除;改为在 store 的增删面板操作中按影响列表统一触发。
|
||||
// 定义布局应用完成后的回调函数,用于刷新面板大小
|
||||
function handleLayoutApplied() {
|
||||
// 确保容器存在后调用refreshPanelSizes并传递容器元素
|
||||
@@ -742,8 +743,8 @@ function handleKeyDown(event) {
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
// 初始化容器引用
|
||||
const container = document.querySelector('.dock-panel-container');
|
||||
layoutManager.setContainer(container);
|
||||
container.value = document.querySelector('.dock-panel-container');
|
||||
layoutManager.setContainer(container.value);
|
||||
|
||||
// 检查URL参数是否有强制重置布局的标记
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
@@ -778,6 +779,9 @@ onMounted(() => {
|
||||
// 初始化面板大小影响关系
|
||||
initializePanelSizeInfluence();
|
||||
|
||||
// 初始化边界(确保下区宽度按左右面板扣减)
|
||||
store.handlePanelSizeInfluence('bottom', container.value);
|
||||
|
||||
// 添加事件监听
|
||||
document.addEventListener('mousemove', handleMouseMove);
|
||||
document.addEventListener('mouseup', handleMouseUp);
|
||||
|
||||
@@ -339,12 +339,32 @@ export class LayoutCoordinator {
|
||||
}
|
||||
|
||||
// 计算底部面板边界 - 底部面板通常位于最下方,只受容器高度限制
|
||||
// 注意:为避免依赖未计算的左右宽度,这里的底部边界设置被延后至左右边界计算之后
|
||||
if (panelAreas.bottom && panelAreas.bottom.panels && panelAreas.bottom.panels.length > 0) {
|
||||
const bottomInfluencedBy = influenceData.influencedBy.bottom || [];
|
||||
const bottomHeight = panelAreas.bottom.height || 200;
|
||||
let bottomX = 0;
|
||||
let bottomWidth = containerWidth;
|
||||
|
||||
bottomInfluencedBy.forEach(item => {
|
||||
if (item.influence && item.property === 'width') {
|
||||
const pos = item.position;
|
||||
const area = panelAreas[pos];
|
||||
const w = (this.panelBounds[pos]?.width ?? area?.width ?? 0);
|
||||
if (w > 0) {
|
||||
bottomWidth -= w;
|
||||
if (pos === 'left') {
|
||||
bottomX += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.panelBounds.bottom = {
|
||||
x: 0,
|
||||
y: containerHeight - (panelAreas.bottom.height || 200),
|
||||
width: containerWidth,
|
||||
height: panelAreas.bottom.height || 200
|
||||
x: Math.max(0, bottomX),
|
||||
y: containerHeight - bottomHeight,
|
||||
width: Math.max(0, bottomWidth),
|
||||
height: bottomHeight
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -131,6 +131,8 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
||||
center: ref([])
|
||||
}
|
||||
}
|
||||
// 全局:待重算的区域队列(去重)
|
||||
const pendingRecompute = new Set();
|
||||
|
||||
// 根据面板ID获取面板位置
|
||||
function getPanelPositionById(panelId) {
|
||||
@@ -193,57 +195,102 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
||||
// 获取全局容器元素(只查询一次DOM)
|
||||
const container = document.querySelector('.dock-panel-container');
|
||||
|
||||
// 辅助:获取区域对象
|
||||
function getAreaByPos(pos) {
|
||||
return pos === 'left' ? leftPanelArea.value
|
||||
: pos === 'right' ? rightPanelArea.value
|
||||
: pos === 'top' ? topPanelArea.value
|
||||
: pos === 'bottom' ? bottomPanelArea.value
|
||||
: pos === 'center' ? centerPanelArea.value
|
||||
: null;
|
||||
}
|
||||
// 辅助:获取受影响的区域列表
|
||||
function impactedBy(position) {
|
||||
const map = panelSizeInfluence.value?.influencedBy || {};
|
||||
return Object.keys(map).filter(pos => {
|
||||
const arr = map[pos] || [];
|
||||
return arr.some(item => item.influence && item.position === position);
|
||||
});
|
||||
}
|
||||
// 队列入列
|
||||
function enqueueRecompute(...positions) {
|
||||
positions.filter(Boolean).forEach(p => pendingRecompute.add(p));
|
||||
}
|
||||
// 处理队列
|
||||
function processRecomputeQueue(externalContainer, sizes = minSizes) {
|
||||
if (!externalContainer) return;
|
||||
let guard = 0;
|
||||
while (pendingRecompute.size > 0 && guard < 20) {
|
||||
guard++;
|
||||
const iterator = pendingRecompute.values();
|
||||
const current = iterator.next().value;
|
||||
pendingRecompute.delete(current);
|
||||
// 先整体更新边界
|
||||
handlePanelSizeInfluence(current, externalContainer);
|
||||
// 更新当前区域的子面板尺寸
|
||||
const currentArea = getAreaByPos(current);
|
||||
if (currentArea) {
|
||||
updatePanelsSize(current, currentArea, externalContainer, sizes);
|
||||
}
|
||||
// 将受影响区域入队并更新其子面板尺寸
|
||||
const impacted = impactedBy(current);
|
||||
impacted.forEach(pos => {
|
||||
const area = getAreaByPos(pos);
|
||||
if (area) {
|
||||
updatePanelsSize(pos, area, externalContainer, sizes);
|
||||
pendingRecompute.add(pos);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
enqueueRecompute('left');
|
||||
processRecomputeQueue(container, minSizes);
|
||||
}
|
||||
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)
|
||||
enqueueRecompute('right');
|
||||
processRecomputeQueue(container, minSizes);
|
||||
}
|
||||
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)
|
||||
enqueueRecompute('top');
|
||||
processRecomputeQueue(container, minSizes);
|
||||
}
|
||||
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)
|
||||
enqueueRecompute('bottom');
|
||||
processRecomputeQueue(container, minSizes);
|
||||
}
|
||||
break
|
||||
case 'center':
|
||||
@@ -363,7 +410,9 @@ export const useDockPanelStore = defineStore('dockPanel', () => {
|
||||
}
|
||||
// 如果面板区域变为空,触发尺寸影响处理以更新其他区域
|
||||
if (panels.length === 0) {
|
||||
handlePanelSizeInfluence(position, container);
|
||||
// 入队并批量重算,直到队列为空
|
||||
enqueueRecompute(position);
|
||||
processRecomputeQueue(container, { panelWidth: 150, panelHeight: 100 });
|
||||
}
|
||||
|
||||
// 处理中心面板的特殊逻辑
|
||||
|
||||
Reference in New Issue
Block a user