点击修改z-index

This commit is contained in:
zqm
2026-01-05 13:29:28 +08:00
parent 10e40b0eee
commit 652b53ff3e
4 changed files with 62 additions and 92 deletions

View File

@@ -7,6 +7,7 @@
:data-area-id="id" :data-area-id="id"
@dragover="handleDragOver" @dragover="handleDragOver"
@dragleave="handleDragLeave" @dragleave="handleDragLeave"
@click.capture="onAreaClick"
> >
<!-- 调整大小的边框 --> <!-- 调整大小的边框 -->
<div <div
@@ -280,7 +281,7 @@ const areaStyle = computed(() => {
height: `${originalPosition.value.height}px`, height: `${originalPosition.value.height}px`,
left: `${originalPosition.value.left}px`, left: `${originalPosition.value.left}px`,
top: `${originalPosition.value.top}px`, top: `${originalPosition.value.top}px`,
zIndex: Z_INDEX_LAYERS.CONTENT // 使用统一的z-index层级 zIndex: zIndexManager.getFloatingAreaZIndex(props.id) // 使用动态的z-index
} }
return style return style
@@ -436,11 +437,9 @@ const onDragEnd = (eventData) => {
// 处理事件总线的area.resize.move事件 // 处理事件总线的area.resize.move事件
const onAreaResizeMove = (eventData) => { const onAreaResizeMove = (eventData) => {
console.log(`[Area:${props.id}] 收到AREA_RESIZE_MOVE事件:`, eventData) // 添加调试日志
const { areaId, size, position, direction, timestamp } = eventData const { areaId, size, position, direction, timestamp } = eventData
if (areaId !== props.id) { if (areaId !== props.id) {
console.log(`[Area:${props.id}] areaId不匹配期望: ${props.id}, 实际: ${areaId}`) // 添加调试日志
return return
} }
@@ -450,8 +449,6 @@ const onAreaResizeMove = (eventData) => {
return return
} }
console.log(`[Area:${props.id}] 更新前originalPosition:`, originalPosition.value) // 添加调试日志
// 应用最小尺寸限制与CSS保持一致 // 应用最小尺寸限制与CSS保持一致
const minWidth = 200 const minWidth = 200
const minHeight = 30 const minHeight = 30
@@ -474,46 +471,12 @@ const onAreaResizeMove = (eventData) => {
let newLeft = inputLeft let newLeft = inputLeft
let newTop = inputTop let newTop = inputTop
// 计算边界位置,用于调试 // 计算边界位置
const oldBottom = originalPosition.value.top + originalPosition.value.height const oldBottom = originalPosition.value.top + originalPosition.value.height
const newBottom = newTop + newHeight const newBottom = newTop + newHeight
const oldRight = originalPosition.value.left + originalPosition.value.width const oldRight = originalPosition.value.left + originalPosition.value.width
const newRight = newLeft + newWidth const newRight = newLeft + newWidth
// 对对角线方向进行特殊处理和日志记录
switch (direction) {
case 'top-right':
console.log(`[Area:${props.id}] top-right方向处理: 原下边框: ${oldBottom}, 新下边框: ${newBottom}, 差值: ${newBottom - oldBottom}`)
// 验证top-right方向下边框位置是否保持不变
if (Math.abs(newBottom - oldBottom) > 1) {
console.warn(`[Area:${props.id}] top-right方向下边框位置变化较大可能存在计算误差`)
}
break
case 'top-left':
console.log(`[Area:${props.id}] top-left方向处理: 原下边框: ${oldBottom}, 新下边框: ${newBottom}, 差值: ${newBottom - oldBottom}`)
console.log(`[Area:${props.id}] top-left方向处理: 原右边框: ${oldRight}, 新右边框: ${newRight}, 差值: ${newRight - oldRight}`)
break
case 'bottom-left':
console.log(`[Area:${props.id}] bottom-left方向处理: 原上边框: ${originalPosition.value.top}, 新上边框: ${newTop}, 差值: ${newTop - originalPosition.value.top}`)
console.log(`[Area:${props.id}] bottom-left方向处理: 原右边框: ${oldRight}, 新右边框: ${newRight}, 差值: ${newRight - oldRight}`)
break
case 'top':
console.log(`[Area:${props.id}] top方向处理: 原下边框: ${oldBottom}, 新下边框: ${newBottom}, 差值: ${newBottom - oldBottom}`)
break
case 'left':
console.log(`[Area:${props.id}] left方向处理: 原右边框: ${oldRight}, 新右边框: ${newRight}, 差值: ${newRight - oldRight}`)
break
}
// 使用已有的边界位置计算结果,无需重新声明
// 确保新的位置和尺寸在合理范围内
// 注意不直接限制newTop和newLeft而是通过调整尺寸来保持在可视区域内
// 这样可以避免拖拽时的突然跳动
// 获取父容器尺寸,用于边界检查 // 获取父容器尺寸,用于边界检查
let parentWidth = window.innerWidth let parentWidth = window.innerWidth
let parentHeight = window.innerHeight let parentHeight = window.innerHeight
@@ -547,8 +510,6 @@ const onAreaResizeMove = (eventData) => {
top: newTop top: newTop
} }
console.log(`[Area:${props.id}] 更新后originalPosition:`, originalPosition.value) // 添加调试日志
// 发送区域位置和尺寸更新事件 // 发送区域位置和尺寸更新事件
emitEvent(EVENT_TYPES.AREA_POSITION_UPDATE, { emitEvent(EVENT_TYPES.AREA_POSITION_UPDATE, {
areaId: props.id, areaId: props.id,
@@ -737,6 +698,20 @@ const onClose = () => emitEvent(EVENT_TYPES.PANEL_CLOSE_REQUEST, {
source: { component: 'Area', areaId: props.id } source: { component: 'Area', areaId: props.id }
}) })
// 区域点击事件 - 将当前区域置于最顶层
const onAreaClick = () => {
console.log(`[Area:${props.id}] onAreaClick called`);
zIndexManager.activateFloatingArea(props.id)
const newZIndex = zIndexManager.getFloatingAreaZIndex(props.id);
console.log(`[Area:${props.id}] New z-index: ${newZIndex}`);
emitEvent(EVENT_TYPES.Z_INDEX_UPDATE, {
areaId: props.id,
zIndex: newZIndex
}, {
source: { component: 'Area', areaId: props.id }
})
}
// 组件挂载后获取父容器引用并初始化位置 // 组件挂载后获取父容器引用并初始化位置
onMounted(() => { onMounted(() => {
parentContainer.value = document.querySelector('.dock-layout') || window parentContainer.value = document.querySelector('.dock-layout') || window

View File

@@ -40,7 +40,7 @@
:key="area.id" :key="area.id"
:type="'Area'" :type="'Area'"
:config="area" :config="area"
:style="{ zIndex: area.zIndex || zIndexManager.getFloatingAreaZIndex(area.id) }" :style="{ zIndex: zIndexManager.getFloatingAreaZIndex(area.id) }"
/> />
</div> </div>
</template> </template>
@@ -126,49 +126,27 @@ const dragOperationCache = new Map();
* @returns {boolean} 是否应该操作区域 * @returns {boolean} 是否应该操作区域
*/ */
const shouldOperateAreaInsteadOfPanel = (areaId) => { const shouldOperateAreaInsteadOfPanel = (areaId) => {
console.log(`[DockLayout] 检查单Panel模式areaId: ${areaId}`);
console.log(`[DockLayout] 当前floatingAreas:`, floatingAreas.value);
const area = floatingAreas.value.find(a => a.id === areaId);
if (!area) {
console.log(`[DockLayout] 未找到Area: ${areaId}`);
return false;
}
try { try {
// 简化逻辑:直接检查区域的面板数量 // 简化逻辑:直接检查区域的面板数量
// 遍历所有子元素统计Panel数量 // 遍历所有子元素统计Panel数量
let panelCount = 0; let panelCount = 0;
console.log(`[DockLayout] Area ${areaId} 的children:`, area.children);
const childrenArray = Array.isArray(area.children) ? area.children : [area.children]; const childrenArray = Array.isArray(area.children) ? area.children : [area.children];
for (const child of childrenArray) { for (const child of childrenArray) {
console.log(`[DockLayout] 检查子元素:`, child);
if (child.type === 'TabPage' && child.children) { if (child.type === 'TabPage' && child.children) {
console.log(`[DockLayout] 找到TabPagechildren:`, child.children);
const tabChildrenArray = Array.isArray(child.children) ? child.children : [child.children]; const tabChildrenArray = Array.isArray(child.children) ? child.children : [child.children];
for (const tabChild of tabChildrenArray) { for (const tabChild of tabChildrenArray) {
console.log(`[DockLayout] 检查TabPage子元素:`, tabChild);
if (tabChild.type === 'Panel') { if (tabChild.type === 'Panel') {
panelCount++; panelCount++;
console.log(`[DockLayout] 找到Panel当前计数: ${panelCount}`);
} }
} }
} }
} }
// 如果区域中只有一个面板返回true // 如果区域中只有一个面板返回true
const result = panelCount === 1; return panelCount === 1;
console.log(`[DockLayout] Area ${areaId} 单Panel检查结果:`, result, `(面板数量: ${panelCount})`);
if (result) {
console.log(`[DockLayout] Area ${areaId} 是单Panel模式应该操作Area而不是Panel`);
}
return result;
} catch (error) { } catch (error) {
console.error(`[DockLayout] 检查单Panel模式时出错:`, error);
return false; return false;
} }
}; };
@@ -182,8 +160,6 @@ const shouldOperateAreaInsteadOfPanel = (areaId) => {
const shouldOperateAreaInsteadOfPanelFromData = (data) => { const shouldOperateAreaInsteadOfPanelFromData = (data) => {
const { panelId, areaId } = data; const { panelId, areaId } = data;
console.log(`🔍 检查单面板模式: areaId=${areaId}, panelId=${panelId}`);
// 从AreaHandler获取区域状态 // 从AreaHandler获取区域状态
const areaState = areaHandler.getAreaState(areaId); const areaState = areaHandler.getAreaState(areaId);
@@ -195,9 +171,7 @@ const shouldOperateAreaInsteadOfPanelFromData = (data) => {
} }
// 如果区域中只有一个面板返回true // 如果区域中只有一个面板返回true
const result = panelCount === 1; return panelCount === 1;
console.log(`✅ 单面板检测结果: ${result} (面板数量: ${panelCount})`);
return result;
}; };
const onCloseFloatingArea = (event) => { const onCloseFloatingArea = (event) => {
@@ -586,6 +560,8 @@ const setupEventListeners = () => {
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_CHECK_SINGLE_PANEL, onCheckSinglePanel, { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_CHECK_SINGLE_PANEL, onCheckSinglePanel, { componentId: 'dock-layout' }));
// Area位置更新事件 // Area位置更新事件
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.AREA_POSITION_UPDATE, onAreaPositionUpdate, { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.AREA_POSITION_UPDATE, onAreaPositionUpdate, { componentId: 'dock-layout' }));
// Area z-index更新事件
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.Z_INDEX_UPDATE, onZIndexUpdate, { componentId: 'dock-layout' }));
// Resize相关事件 // Resize相关事件
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.RESIZE_START, () => emit('dragStart'), { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.RESIZE_START, () => emit('dragStart'), { componentId: 'dock-layout' }));
@@ -1191,6 +1167,16 @@ const onAreaPositionUpdate = (event) => {
} }
}; };
// 处理Area z-index更新事件
const onZIndexUpdate = (event) => {
const { areaId, zIndex } = event;
const area = floatingAreas.value.find(a => a.id === areaId);
if (area) {
area.zIndex = zIndex;
}
};
const onAreaResizeEnd = (event) => { const onAreaResizeEnd = (event) => {
const { areaId, direction, finalPosition } = event; const { areaId, direction, finalPosition } = event;

View File

@@ -703,15 +703,11 @@ const onResizeStart = (e, direction) => {
*/ */
const setupEventListeners = () => { const setupEventListeners = () => {
try { try {
if (import.meta.env.DEV) {
console.log(`[Panel:${props.id}] 开始注册事件监听器...`)
}
// 监听面板最大化同步事件 // 监听面板最大化同步事件
const unsubscribeMaximizeSync = onEvent(EVENT_TYPES.PANEL_MAXIMIZE_SYNC, (data) => { const unsubscribeMaximizeSync = onEvent(EVENT_TYPES.PANEL_MAXIMIZE_SYNC, (data) => {
// 同时检查panelId和areaId确保正确匹配 // 同时检查panelId和areaId确保正确匹配
if (data.panelId === props.id || data.areaId === getCurrentAreaId()) { if (data.panelId === props.id || data.areaId === getCurrentAreaId()) {
console.log(`[Panel:${props.id}] 收到最大化同步事件:`, data);
isMaximized.value = data.maximized; isMaximized.value = data.maximized;
} }
}, { componentId: `panel-${props.id}` }) }, { componentId: `panel-${props.id}` })
@@ -720,7 +716,6 @@ const setupEventListeners = () => {
const unsubscribeSinglePanelResult = onEvent(EVENT_TYPES.PANEL_SINGLE_PANEL_RESULT, (data) => { const unsubscribeSinglePanelResult = onEvent(EVENT_TYPES.PANEL_SINGLE_PANEL_RESULT, (data) => {
// 检查panelId或areaId匹配 // 检查panelId或areaId匹配
if (data.panelId === props.id || data.areaId === getCurrentAreaId()) { if (data.panelId === props.id || data.areaId === getCurrentAreaId()) {
console.log(`[Panel:${props.id}] 收到单面板检测结果:`, data.isSinglePanel);
isSinglePanel.value = data.isSinglePanel; isSinglePanel.value = data.isSinglePanel;
} }
}, { componentId: `panel-${props.id}` }) }, { componentId: `panel-${props.id}` })
@@ -811,7 +806,7 @@ const cleanupEventListeners = () => {
// 重置状态 // 重置状态
try { try {
isDragging = false isDragging.value = false
if (import.meta.env.DEV) { if (import.meta.env.DEV) {
console.log(`[Panel:${props.id}] 拖拽状态已重置`) console.log(`[Panel:${props.id}] 拖拽状态已重置`)
} }
@@ -867,7 +862,7 @@ onUnmounted(() => {
try { try {
// 1. 立即设置标志位,防止新的异步操作 // 1. 立即设置标志位,防止新的异步操作
isDragging = false isDragging.value = false
// 2. 同步清理所有可以直接清理的资源 // 2. 同步清理所有可以直接清理的资源
const cleanupResult = cleanupEventListeners() const cleanupResult = cleanupEventListeners()
@@ -882,7 +877,7 @@ onUnmounted(() => {
// 即使出现异常,也要尝试强制清理 // 即使出现异常,也要尝试强制清理
try { try {
isDragging = false isDragging.value = false
} catch (forceError) { } catch (forceError) {
console.error(`[Panel:${props.id}] 强制清理也失败:`, forceError) console.error(`[Panel:${props.id}] 强制清理也失败:`, forceError)
} }

View File

@@ -49,19 +49,25 @@ class ZIndexManager {
* @returns {number} z-index值 * @returns {number} z-index值
*/ */
getFloatingAreaZIndex(areaId, isActive = false) { getFloatingAreaZIndex(areaId, isActive = false) {
console.log(`[zIndexManager] getFloatingAreaZIndex called for areaId: ${areaId}, isActive: ${isActive}`);
if (isActive) { if (isActive) {
return this.floatingAreas.get(areaId) || Z_INDEX_LAYERS.FLOATING_AREA_ACTIVE const zIndex = this.floatingAreas.get(areaId) || Z_INDEX_LAYERS.FLOATING_AREA_ACTIVE;
console.log(`[zIndexManager] getFloatingAreaZIndex returning for ${areaId}: ${zIndex}`);
return zIndex;
} }
// 为新区域分配z-index // 为新区域分配z-index
if (!this.floatingAreas.has(areaId)) { if (!this.floatingAreas.has(areaId)) {
const maxZIndex = Math.max(...Array.from(this.floatingAreas.values()), Z_INDEX_LAYERS.FLOATING_AREA) const maxZIndex = Math.max(...Array.from(this.floatingAreas.values()), Z_INDEX_LAYERS.FLOATING_AREA);
const newZIndex = maxZIndex + 1 const newZIndex = maxZIndex + 1;
this.floatingAreas.set(areaId, newZIndex) this.floatingAreas.set(areaId, newZIndex);
return newZIndex console.log(`[zIndexManager] Assigned new z-index for ${areaId}: ${newZIndex}`);
return newZIndex;
} }
return this.floatingAreas.get(areaId) const existingZIndex = this.floatingAreas.get(areaId);
console.log(`[zIndexManager] Returning existing z-index for ${areaId}: ${existingZIndex}`);
return existingZIndex;
} }
/** /**
@@ -69,24 +75,32 @@ class ZIndexManager {
* @param {string} areaId - 区域ID * @param {string} areaId - 区域ID
*/ */
activateFloatingArea(areaId) { activateFloatingArea(areaId) {
console.log(`[zIndexManager] activateFloatingArea called for areaId: ${areaId}`);
// 获取当前最大z-index // 获取当前最大z-index
const maxZIndex = Math.max(...Array.from(this.floatingAreas.values()), Z_INDEX_LAYERS.FLOATING_AREA) const maxZIndex = Math.max(...Array.from(this.floatingAreas.values()), Z_INDEX_LAYERS.FLOATING_AREA);
this.floatingAreas.set(areaId, maxZIndex + 1) const newZIndex = maxZIndex + 1;
this.floatingAreas.set(areaId, newZIndex);
console.log(`[zIndexManager] Set z-index for ${areaId} to ${newZIndex}`);
// 触发重排以确保层级生效 // 触发重排以确保层级生效
this.reorderFloatingAreas() this.reorderFloatingAreas();
console.log(`[zIndexManager] Floating areas after activation:`, this.getStatus());
} }
/** /**
* 重新排序浮动区域层级 * 重新排序浮动区域层级
*/ */
reorderFloatingAreas() { reorderFloatingAreas() {
const areas = Array.from(this.floatingAreas.entries()) console.log(`[zIndexManager] reorderFloatingAreas called`);
areas.sort((a, b) => a[1] - b[1]) // 按z-index排序 const areas = Array.from(this.floatingAreas.entries());
areas.sort((a, b) => a[1] - b[1]); // 按z-index排序
areas.forEach(([areaId], index) => { areas.forEach(([areaId], index) => {
this.floatingAreas.set(areaId, Z_INDEX_LAYERS.FLOATING_AREA + index + 1) const newZIndex = Z_INDEX_LAYERS.FLOATING_AREA + index + 1;
}) this.floatingAreas.set(areaId, newZIndex);
console.log(`[zIndexManager] Reordered ${areaId} to z-index: ${newZIndex}`);
});
console.log(`[zIndexManager] reorderFloatingAreas completed, current state:`, this.getStatus());
} }
/** /**