修复主区域边缘指示器显示逻辑

- 修改DockLayout.vue中的hideEdgeIndicators判断逻辑,从简单检查floatingAreas数组改为实际检测主区域内容区内是否包含其他Area
- 添加checkMainContentForAreas函数,通过DOM查询检测主区域内的.vs-area、.tab-page和.panel元素
- 添加onMounted钩子和floatingAreas监听器,确保在适当时机进行检测
- 保持DockIndicator.vue中v-if条件渲染边缘指示器的逻辑
- 修复第3条需求:当主区域内没有其他Area时正确隐藏外部边缘指示器
This commit is contained in:
zqm
2025-11-14 14:23:10 +08:00
parent 806674d5aa
commit c298d7ba2d
3 changed files with 84 additions and 27 deletions

View File

@@ -69,6 +69,7 @@
<!-- 上指示根据activeDockZone状态显示和高亮 -->
<svg
v-if="!props.hideEdgeIndicators"
width="41"
height="41"
viewBox="0 0 40 40"
@@ -93,6 +94,7 @@
<!-- 右指示根据activeDockZone状态显示和高亮 -->
<svg
v-if="!props.hideEdgeIndicators"
width="41"
height="41"
viewBox="0 0 40 40"
@@ -117,6 +119,7 @@
<!-- 下指示根据activeDockZone状态显示和高亮 -->
<svg
v-if="!props.hideEdgeIndicators"
width="41"
height="41"
viewBox="0 0 40 40"
@@ -141,6 +144,7 @@
<!-- 左指示根据activeDockZone状态显示和高亮 -->
<svg
v-if="!props.hideEdgeIndicators"
width="41"
height="41"
viewBox="0 0 40 40"
@@ -434,34 +438,14 @@
<script setup>
import { computed, watch, ref, onUnmounted } from 'vue'
// Props定义
const props = defineProps({
// 是否可见
visible: {
type: Boolean,
default: false
},
// 目标区域的位置和大小信息
targetRect: {
type: Object,
default: () => ({
left: 0,
top: 0,
width: 0,
height: 0
})
},
// 鼠标位置
mousePosition: {
type: Object,
default: () => ({
x: 0,
y: 0
})
}
visible: Boolean,
targetRect: Object,
mousePosition: Object,
hideEdgeIndicators: Boolean
})
// 鼠标悬停在哪个指示器上
// 创建响应式的hoveredZone状态
const hoveredZone = ref(null)
// 鼠标是否悬停在中心指示器上(用于控制中心指示区的显示)
const isCenterIndicatorHovered = ref(false)

View File

@@ -6,12 +6,14 @@
:visible="showDockIndicator"
:target-rect="targetAreaRect"
:mouse-position="currentMousePosition"
:hide-edge-indicators="hideEdgeIndicators"
@zone-active="onDockZoneActive"
style="z-index: 9999;"
/>
<!-- 主区域 - 添加ref引用 -->
<Area
ref="mainAreaRef"
:WindowState="windowState"
:showTitleBar="false"
title="主区域"
@@ -19,6 +21,7 @@
@dragover="handleMainAreaDragOver"
@dragleave="handleMainAreaDragLeave"
>
<!-- 这里可以放置主区域的内容 -->
</Area>
<!-- 浮动区域直接渲染不使用额外的div包装 -->
<Area
@@ -85,7 +88,7 @@
</template>
<script setup>
import { ref, defineExpose, nextTick, watch } from 'vue'
import { ref, defineExpose, nextTick, watch, computed, onMounted } from 'vue'
import Area from './Area.vue';
import Panel from './Panel.vue';
import TabPage from './TabPage.vue';
@@ -99,6 +102,8 @@ const floatingAreas = ref([])
// 容器引用
const dockLayoutRef = ref(null)
// 主区域引用
const mainAreaRef = ref(null)
// 区域ID计数器
let areaIdCounter = 1
@@ -108,6 +113,15 @@ const currentMousePosition = ref({ x: 0, y: 0 })
const targetAreaRect = ref({ left: 0, top: 0, width: 0, height: 0 })
const activeDockZone = ref(null)
// 检查主区域内是否有其他AreaTabPage和Panel等子组件
const hasAreasInMainContent = ref(false)
// 计算是否隐藏外部边缘指示器
const hideEdgeIndicators = computed(() => {
// 当主区域内没有其他Area时隐藏外部边缘指示器
return !hasAreasInMainContent.value
})
// Panel拖拽相关状态
const panelDragState = ref({
isDragging: false,
@@ -124,6 +138,46 @@ const tabDragState = ref({
startAreaPos: { x: 0, y: 0 }
})
// 检测主区域内是否有其他Area
const checkMainContentForAreas = () => {
if (!mainAreaRef.value) {
hasAreasInMainContent.value = false
return
}
try {
// 获取主区域的DOM元素
const mainAreaElement = mainAreaRef.value.$el
if (!mainAreaElement) {
hasAreasInMainContent.value = false
return
}
// 检查主区域内容区内是否包含vs-area元素子Area
const childAreas = mainAreaElement.querySelectorAll('.vs-area')
const hasChildAreas = childAreas.length > 1 // 排除主区域本身
// 检查主区域内容区内是否包含TabPage
const tabPages = mainAreaElement.querySelectorAll('.tab-page, [class*="tab"]')
// 检查主区域内容区内是否包含Panel
const panels = mainAreaElement.querySelectorAll('.panel, [class*="panel"]')
// 如果有任何子Area、TabPage或Panel则认为主区域内有其他Area
hasAreasInMainContent.value = hasChildAreas || tabPages.length > 0 || panels.length > 0
console.log('主区域内容检查结果:', {
childAreas: hasChildAreas,
tabPages: tabPages.length,
panels: panels.length,
hasAreasInMainContent: hasAreasInMainContent.value
})
} catch (error) {
console.error('检查主区域内容时出错:', error)
hasAreasInMainContent.value = false
}
}
// 添加新的浮动面板
const addFloatingPanel = () => {
// 获取父容器尺寸以计算居中位置
@@ -477,6 +531,24 @@ watch(floatingAreas, (newAreas) => {
});
}, { deep: true });
// 组件挂载后检查主区域内容
onMounted(() => {
// 延迟执行确保DOM完全渲染
setTimeout(() => {
checkMainContentForAreas()
}, 100)
})
// 监听主区域内容变化
watch(floatingAreas, () => {
// 当浮动区域变化时,重新检查主区域内容
setTimeout(() => {
checkMainContentForAreas()
}, 100)
}, { deep: true })
// 当主区域内没有其他Area时隐藏外部边缘指示器只显示中心指示器
// 处理主区域的dragover事件
const handleMainAreaDragOver = (event) => {
event.preventDefault()

View File

@@ -33,3 +33,4 @@
### 停靠规则
1. 当一个Panel被拖动时显示停靠指示器。
2. 当拖动Panel到指示器时显示停靠区。
3. 当主区域内没有其他Area时隐藏外部边缘指示器只显示中心指示器。