修改内容区显示逻辑,改为配置驱动
This commit is contained in:
@@ -50,7 +50,7 @@
|
||||
@mousedown="onResizeStart('w', $event)"
|
||||
></div>
|
||||
<!-- 顶部标题栏 -->
|
||||
<div v-if="showTitleBar" class="vs-title-bar" :class="{ 'cursor-move': !isMaximized }" @mousedown="onDragStart">
|
||||
<div v-if="shouldShowTitleBar" class="vs-title-bar" :class="{ 'cursor-move': !isMaximized }" @mousedown="onDragStart">
|
||||
<div class="vs-title-left">
|
||||
<div class="vs-app-icon" aria-label="AppIcon">
|
||||
<svg class="vs-icon" viewBox="0 0 22.4 22.4" aria-hidden="true">
|
||||
@@ -99,41 +99,15 @@
|
||||
</div>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="vs-content">
|
||||
<!-- 优先显示receivedContent(停靠的外部内容) -->
|
||||
<template v-if="receivedContent && receivedContent.length > 0">
|
||||
<!-- 调试信息 -->
|
||||
<div v-if="false" style="position: absolute; top: 0; left: 0; background: red; color: white; padding: 5px; z-index: 9999;">
|
||||
DEBUG: receivedContent长度 = {{ receivedContent.length }}
|
||||
<div v-for="(item, index) in receivedContent" :key="`debug-${index}`">
|
||||
TabPage {{ index }}: {{ item.tabPage.id }} - {{ item.tabPage.title }} ({{ item.tabPage.panels.length }} panels)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TabPage
|
||||
v-for="(item, index) in receivedContent"
|
||||
:key="item.tabPage.id"
|
||||
:id="item.tabPage.id"
|
||||
:title="item.tabPage.title"
|
||||
:panels="item.tabPage.panels"
|
||||
:tabPosition="'bottom'"
|
||||
@tabDragStart="() => {}"
|
||||
@tabDragMove="() => {}"
|
||||
@tabDragEnd="() => {}"
|
||||
@maximize="onPanelMaximize"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 如果没有receivedContent但有slot内容,显示slot内容 -->
|
||||
<template v-else-if="$slots.default">
|
||||
<slot></slot>
|
||||
</template>
|
||||
<div class="vs-content">
|
||||
<!-- 直接渲染插槽内容,Render组件会自动处理children -->
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, computed, ref, onMounted, onUnmounted, watch, defineExpose } from 'vue'
|
||||
import { defineProps, computed, ref, onMounted, onUnmounted, watch, defineExpose, useSlots } from 'vue'
|
||||
import { emitEvent, EVENT_TYPES, globalEventListenerManager } from './eventBus'
|
||||
import TabPage from './TabPage.vue'
|
||||
import Panel from './Panel.vue'
|
||||
@@ -170,12 +144,44 @@ const originalPosition = ref({
|
||||
// 保存最大化前的位置和大小,用于还原
|
||||
const maximizedFromPosition = ref(null)
|
||||
|
||||
// 存储接收到的外部Area内容
|
||||
const receivedContent = ref([])
|
||||
// 不再需要存储接收到的外部Area内容,改为通过children配置管理
|
||||
|
||||
// 组件引用
|
||||
const areaRef = ref(null)
|
||||
|
||||
// 获取插槽
|
||||
const slots = useSlots();
|
||||
|
||||
// 计算属性:是否显示标题栏
|
||||
const shouldShowTitleBar = computed(() => {
|
||||
// 基础条件:props.showTitleBar为true
|
||||
if (!props.showTitleBar) return false;
|
||||
|
||||
// 获取插槽内容
|
||||
if (slots.default) {
|
||||
const slotChildren = slots.default();
|
||||
|
||||
// 如果没有插槽内容,显示标题栏
|
||||
if (slotChildren.length === 0) return true;
|
||||
|
||||
// 如果插槽内容不是TabPage,显示标题栏
|
||||
const firstChild = slotChildren[0];
|
||||
if (firstChild.type.name !== 'TabPage') return true;
|
||||
|
||||
// 获取TabPage的插槽内容
|
||||
const tabPageSlots = firstChild.children?.default ? firstChild.children.default() : [];
|
||||
|
||||
// 如果TabPage包含多个Panel,显示标题栏
|
||||
if (tabPageSlots.length !== 1) return true;
|
||||
|
||||
// 如果TabPage只包含一个Panel,不显示标题栏
|
||||
return false;
|
||||
}
|
||||
|
||||
// 默认显示标题栏
|
||||
return true;
|
||||
});
|
||||
|
||||
// 拖拽相关状态
|
||||
const isDragging = ref(false)
|
||||
const dragStartPos = ref({ x: 0, y: 0 })
|
||||
@@ -269,9 +275,20 @@ const onPanelMaximize = (panelId) => {
|
||||
// // console.log('🔸 Area接收最大化事件 - Panel ID:', panelId)
|
||||
|
||||
// 检查内容区是否只有一个Panel
|
||||
const panelChildren = $slots.default ? $slots.default() : []
|
||||
const isSinglePanel = panelChildren.length === 1
|
||||
// // console.log('🔸 检查是否单Panel模式:', { panelChildren: panelChildren.length, isSinglePanel })
|
||||
const slotChildren = slots.default ? slots.default() : []
|
||||
let isSinglePanel = false
|
||||
|
||||
// 查找TabPage组件
|
||||
const tabPages = slotChildren.filter(child => child.type.name === 'TabPage')
|
||||
|
||||
if (tabPages.length === 1) {
|
||||
// 获取TabPage的插槽内容
|
||||
const tabPageSlots = tabPages[0].children?.default ? tabPages[0].children.default() : []
|
||||
// 如果TabPage只有一个Panel,认为是单Panel模式
|
||||
isSinglePanel = tabPageSlots.length === 1
|
||||
}
|
||||
|
||||
// // console.log('🔸 检查是否单Panel模式:', { tabPages: tabPages.length, isSinglePanel })
|
||||
|
||||
if (isSinglePanel) {
|
||||
// // console.log('🔸 单Panel模式,切换Area最大化状态')
|
||||
@@ -659,132 +676,26 @@ const mergeAreaContent = (sourceArea) => {
|
||||
}
|
||||
|
||||
try {
|
||||
const isEmpty = receivedContent.value.length === 0
|
||||
// 发送合并请求事件,让父组件处理配置修改
|
||||
emitEvent(EVENT_TYPES.AREA_MERGE_REQUEST, {
|
||||
sourceArea: sourceArea,
|
||||
targetAreaId: props.id
|
||||
}, {
|
||||
source: { component: 'Area', areaId: props.id }
|
||||
})
|
||||
|
||||
if (isEmpty) {
|
||||
// 4.2.1 如果目标Area内容区为空,将源Area内容区的子组件添加到目标Area内容区
|
||||
// console.log('[Area] 目标Area为空,添加源Area的子组件')
|
||||
|
||||
// 处理源Area的所有tabPages(支持两种模式:tabPages和children)
|
||||
let tabPagesData = []
|
||||
|
||||
if (sourceArea.children) {
|
||||
// 统一处理children结构
|
||||
const childrenArray = Array.isArray(sourceArea.children) ? sourceArea.children : [sourceArea.children]
|
||||
for (const child of childrenArray) {
|
||||
if (child.type === 'TabPage' && child.children) {
|
||||
tabPagesData.push({
|
||||
id: child.id,
|
||||
title: child.title,
|
||||
panels: Array.isArray(child.children) ? child.children : (child.children.type === 'Panel' ? [child.children] : [])
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tabPagesData.length > 0) {
|
||||
tabPagesData.forEach((tabPage, tabIndex) => {
|
||||
// 保持原有的tabPage ID,确保Vue组件状态连续性
|
||||
const tabPageId = `merged-tabpage-${tabPage.id}`
|
||||
const newPanels = (tabPage.panels || []).map((panel, panelIndex) => {
|
||||
// 保持原有Panel ID不变,确保Vue响应式和状态稳定性
|
||||
// console.log(`[Area] 添加Panel: ${panel.id}`)
|
||||
return {
|
||||
...panel,
|
||||
maximized: true
|
||||
}
|
||||
})
|
||||
|
||||
receivedContent.value.push({
|
||||
id: `received-${tabPageId}`,
|
||||
title: tabPage.title || `标签页${tabIndex + 1}`,
|
||||
tabPage: {
|
||||
...tabPage,
|
||||
id: tabPageId,
|
||||
panels: newPanels
|
||||
},
|
||||
panels: newPanels
|
||||
})
|
||||
|
||||
// console.log(`[Area] 成功添加TabPage: ${tabPage.title} (${newPanels.length} 个Panel)`)
|
||||
})
|
||||
}
|
||||
|
||||
// 触发事件通知父组件将源Area保存到隐藏列表
|
||||
emitEvent(EVENT_TYPES.AREA_MERGED, {
|
||||
sourceArea: sourceArea,
|
||||
targetAreaId: props.id,
|
||||
targetAreaHasContent: false, // 目标Area为空
|
||||
operation: 'add-children',
|
||||
addedTabPages: receivedContent.value
|
||||
}, {
|
||||
source: { component: 'Area', areaId: props.id }
|
||||
})
|
||||
|
||||
return true
|
||||
|
||||
} else {
|
||||
// 4.2.3 如果目标Area已有TabPage,合并TabPage标签页
|
||||
// console.log('[Area] 目标Area已有TabPage,合并TabPage标签页')
|
||||
|
||||
// 获取第一个现有的TabPage作为合并目标
|
||||
const existingTabPage = receivedContent.value[0]
|
||||
if (!existingTabPage) {
|
||||
// console.error('[Area] 现有TabPage不存在')
|
||||
return false
|
||||
}
|
||||
|
||||
// 处理源Area的所有children(统一使用children结构)
|
||||
let tabPagesData = []
|
||||
|
||||
if (sourceArea.children) {
|
||||
// 统一处理children结构
|
||||
const childrenArray = Array.isArray(sourceArea.children) ? sourceArea.children : [sourceArea.children]
|
||||
for (const child of childrenArray) {
|
||||
if (child.type === 'TabPage' && child.children) {
|
||||
tabPagesData.push({
|
||||
id: child.id,
|
||||
title: child.title,
|
||||
panels: Array.isArray(child.children) ? child.children : (child.children.type === 'Panel' ? [child.children] : [])
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tabPagesData.length > 0) {
|
||||
tabPagesData.forEach((sourceTabPage, tabIndex) => {
|
||||
if (sourceTabPage && sourceTabPage.panels) {
|
||||
// 保持原有Panel ID不变,避免Vue组件重新创建和状态丢失
|
||||
const newPanels = sourceTabPage.panels.map((panel, panelIndex) => {
|
||||
// // console.log(`[Area] 合并Panel到现有TabPage: ${panel.id}`)
|
||||
return {
|
||||
...panel,
|
||||
maximized: true
|
||||
}
|
||||
})
|
||||
|
||||
// 将新的Panel添加到现有TabPage,保持ID连续性
|
||||
existingTabPage.tabPage.panels.push(...newPanels)
|
||||
// existingTabPage.panels 是旧引用,保持结构一致性但避免重复添加
|
||||
// // console.log(`[Area] 成功合并 ${newPanels.length} 个Panel到现有TabPage`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 触发事件通知父组件将源Area及其TabPage组件保存到隐藏列表
|
||||
emitEvent(EVENT_TYPES.AREA_MERGED, {
|
||||
sourceArea: sourceArea,
|
||||
targetAreaId: props.id,
|
||||
targetAreaHasContent: true, // 目标Area已有内容
|
||||
operation: 'merge-tabpages',
|
||||
sourceTabPages: tabPagesData
|
||||
}, {
|
||||
source: { component: 'Area', areaId: props.id }
|
||||
})
|
||||
// 更新完成
|
||||
// // console.log(`[Area] 合并完成,现有TabPage共有 ${existingTabPage.tabPage.panels.length} 个Panel`)
|
||||
return true
|
||||
}
|
||||
// 触发事件通知父组件将源Area保存到隐藏列表
|
||||
emitEvent(EVENT_TYPES.AREA_MERGED, {
|
||||
sourceArea: sourceArea,
|
||||
targetAreaId: props.id,
|
||||
targetAreaHasContent: false, // 简化处理,由父组件判断
|
||||
operation: 'merge-children',
|
||||
sourceTabPages: sourceArea.children ? [sourceArea.children] : []
|
||||
}, {
|
||||
source: { component: 'Area', areaId: props.id }
|
||||
})
|
||||
|
||||
return true
|
||||
|
||||
} catch (error) {
|
||||
// console.error('[Area] 合并Area内容时出错:', error)
|
||||
|
||||
Reference in New Issue
Block a user