中心区依靠多个TabPanel
This commit is contained in:
@@ -125,6 +125,7 @@
|
||||
:collapsed="panel.collapsed"
|
||||
:toolbarExpanded="panel.toolbarExpanded"
|
||||
:maximized="panel.maximized"
|
||||
:content="panel.content"
|
||||
@toggleCollapse="() => {}"
|
||||
@maximize="onPanelMaximize"
|
||||
@close="() => {}"
|
||||
@@ -262,7 +263,7 @@ const areaStyle = computed(() => {
|
||||
return style
|
||||
})
|
||||
|
||||
const emit = defineEmits(['close', 'update:WindowState', 'update:position', 'dragover', 'dragleave', 'areaDragStart', 'areaDragMove', 'areaDragEnd'])
|
||||
const emit = defineEmits(['close', 'update:WindowState', 'update:position', 'dragover', 'dragleave', 'areaDragStart', 'areaDragMove', 'areaDragEnd', 'area-merged'])
|
||||
|
||||
// 处理Panel的最大化事件
|
||||
const onPanelMaximize = (panelId) => {
|
||||
@@ -569,56 +570,121 @@ onMounted(() => {
|
||||
}
|
||||
})
|
||||
|
||||
// 添加Area内容的方法,用于主区域的Area接收外部Area内容
|
||||
const appendAreaContent = (sourceArea) => {
|
||||
console.log(`[Area] ${props.id} 接收到内容移动请求:`, sourceArea)
|
||||
|
||||
|
||||
// 合并Area内容的方法,只保留合并逻辑
|
||||
const mergeAreaContent = (sourceArea) => {
|
||||
console.log(`[Area] ${props.id} 接收到Area合并请求:`, sourceArea)
|
||||
|
||||
if (!sourceArea) {
|
||||
console.warn('[Area] 源Area为空,无法接收内容')
|
||||
console.warn('[Area] 源Area为空,无法合并内容')
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
// 清空之前的内容,确保只接收一个新的TabPage
|
||||
receivedContent.value = []
|
||||
const isEmpty = receivedContent.value.length === 0
|
||||
|
||||
// 处理源Area的tabPages,只接收第一个TabPage(用户要求只能接收一个TabPage)
|
||||
if (sourceArea.tabPages && sourceArea.tabPages.length > 0) {
|
||||
const tabPage = sourceArea.tabPages[0] // 只接收第一个TabPage
|
||||
if (tabPage) {
|
||||
// 确保所有Panel都处于最大化状态,显示还原按钮
|
||||
const maximizedPanels = (tabPage.panels || []).map(panel => ({
|
||||
...panel,
|
||||
maximized: true // 设置为最大化状态
|
||||
}))
|
||||
|
||||
receivedContent.value.push({
|
||||
id: `received-${tabPage.id || Date.now() + Math.random()}`,
|
||||
title: tabPage.title || '标签页',
|
||||
tabPage: {
|
||||
...tabPage,
|
||||
panels: maximizedPanels // 使用最大化状态的Panel
|
||||
},
|
||||
panels: maximizedPanels
|
||||
if (isEmpty) {
|
||||
// 4.2.1 如果目标Area内容区为空,将源Area内容区的子组件添加到目标Area内容区
|
||||
console.log('[Area] 目标Area为空,添加源Area的子组件')
|
||||
|
||||
// 处理源Area的所有tabPages
|
||||
if (sourceArea.tabPages && sourceArea.tabPages.length > 0) {
|
||||
sourceArea.tabPages.forEach((tabPage, tabIndex) => {
|
||||
const newTabPageId = `merged-tabpage-${Date.now()}-${tabIndex}`
|
||||
const newPanels = (tabPage.panels || []).map((panel, panelIndex) => {
|
||||
const newPanelId = `merged-panel-${Date.now()}-${tabIndex}-${panelIndex}`
|
||||
console.log(`[Area] 添加Panel: ${panel.id} -> ${newPanelId}`)
|
||||
return {
|
||||
...panel,
|
||||
id: newPanelId,
|
||||
maximized: true
|
||||
}
|
||||
})
|
||||
|
||||
receivedContent.value.push({
|
||||
id: `received-${newTabPageId}`,
|
||||
title: tabPage.title || `标签页${tabIndex + 1}`,
|
||||
tabPage: {
|
||||
...tabPage,
|
||||
id: newTabPageId,
|
||||
panels: newPanels
|
||||
},
|
||||
panels: newPanels
|
||||
})
|
||||
|
||||
console.log(`[Area] 成功添加TabPage: ${tabPage.title} (${newPanels.length} 个Panel)`)
|
||||
})
|
||||
console.log(`[Area] 成功接收tabPage: ${tabPage.title},并设置Panel为最大化状态`)
|
||||
}
|
||||
|
||||
// 触发事件通知父组件将源Area保存到隐藏列表
|
||||
emit('area-merged', {
|
||||
sourceArea: sourceArea,
|
||||
targetAreaId: props.id,
|
||||
targetAreaHasContent: false, // 目标Area为空
|
||||
operation: 'add-children',
|
||||
addedTabPages: receivedContent.value
|
||||
})
|
||||
|
||||
return true
|
||||
|
||||
} else {
|
||||
console.warn('[Area] 源Area中没有tabPages数据')
|
||||
// 4.2.2 如果目标Area内容区已包含TabPage,将源Area的每个TabPage添加到目标Area的TabPage中
|
||||
console.log('[Area] 目标Area已有TabPage,合并TabPage标签页')
|
||||
|
||||
// 获取第一个现有的TabPage作为合并目标
|
||||
const existingTabPage = receivedContent.value[0]
|
||||
if (!existingTabPage) {
|
||||
console.error('[Area] 现有TabPage不存在')
|
||||
return false
|
||||
}
|
||||
|
||||
// 处理源Area的所有tabPages
|
||||
if (sourceArea.tabPages && sourceArea.tabPages.length > 0) {
|
||||
sourceArea.tabPages.forEach((sourceTabPage, tabIndex) => {
|
||||
if (sourceTabPage && sourceTabPage.panels) {
|
||||
// 为每个Panel创建新的唯一ID避免冲突
|
||||
const newPanels = sourceTabPage.panels.map((panel, panelIndex) => {
|
||||
const newPanelId = `merged-panel-${Date.now()}-${tabIndex}-${panelIndex}`
|
||||
console.log(`[Area] 合并Panel到现有TabPage: ${panel.id} -> ${newPanelId}`)
|
||||
return {
|
||||
...panel,
|
||||
id: newPanelId,
|
||||
maximized: true
|
||||
}
|
||||
})
|
||||
|
||||
// 将新的Panel添加到现有TabPage
|
||||
existingTabPage.tabPage.panels.push(...newPanels)
|
||||
existingTabPage.panels.push(...newPanels)
|
||||
|
||||
console.log(`[Area] 成功合并 ${newPanels.length} 个Panel到现有TabPage`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 触发事件通知父组件将源Area及其TabPage组件保存到隐藏列表
|
||||
emit('area-merged', {
|
||||
sourceArea: sourceArea,
|
||||
targetAreaId: props.id,
|
||||
targetAreaHasContent: true, // 目标Area已有内容
|
||||
operation: 'merge-tabpages',
|
||||
sourceTabPages: sourceArea.tabPages || []
|
||||
})
|
||||
|
||||
console.log(`[Area] 合并完成,现有TabPage共有 ${existingTabPage.tabPage.panels.length} 个Panel`)
|
||||
return true
|
||||
}
|
||||
|
||||
console.log(`[Area] ${props.id} 当前接收内容数量: ${receivedContent.value.length}`)
|
||||
return true
|
||||
|
||||
} catch (error) {
|
||||
console.error('[Area] 接收外部内容时出错:', error)
|
||||
console.error('[Area] 合并Area内容时出错:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露方法给父组件调用
|
||||
defineExpose({
|
||||
appendAreaContent,
|
||||
mergeAreaContent, // 合并Area内容的方法
|
||||
id: props.id,
|
||||
title: props.title,
|
||||
isMaximized: isMaximized.value
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
:style="{ position: 'relative', width: '100%', height: '100%', zIndex: 1 }"
|
||||
@dragover="handleMainAreaDragOver"
|
||||
@dragleave="handleMainAreaDragLeave"
|
||||
@area-merged="onAreaMerged"
|
||||
>
|
||||
<!-- 这里可以放置主区域的内容 -->
|
||||
</Area>
|
||||
@@ -76,6 +77,7 @@
|
||||
:collapsed="panel.collapsed"
|
||||
:toolbarExpanded="panel.toolbarExpanded"
|
||||
:maximized="panel.maximized"
|
||||
:content="panel.content"
|
||||
@toggleCollapse="onToggleCollapse"
|
||||
@maximize="onMaximize"
|
||||
@close="onClosePanel(area.id, panel.id)"
|
||||
@@ -180,6 +182,44 @@ const checkMainContentForAreas = () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机测试内容用于合并测试
|
||||
* @param {number} panelIndex - 面板索引
|
||||
* @returns {Object} 包含随机内容的对象
|
||||
*/
|
||||
const generateRandomContent = (panelIndex) => {
|
||||
const contentTypes = ['图表', '数据', '配置', '文档', '代码', '日志']
|
||||
const randomType = contentTypes[Math.floor(Math.random() * contentTypes.length)]
|
||||
const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD']
|
||||
const randomColor = colors[Math.floor(Math.random() * colors.length)]
|
||||
|
||||
return {
|
||||
type: randomType,
|
||||
color: randomColor,
|
||||
index: panelIndex,
|
||||
title: `${randomType}面板 ${panelIndex + 1}`,
|
||||
data: generateSampleData(panelIndex),
|
||||
timestamp: new Date().toLocaleString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成样本数据
|
||||
* @param {number} dataIndex - 数据索引
|
||||
* @returns {Array} 样本数据数组
|
||||
*/
|
||||
const generateSampleData = (dataIndex) => {
|
||||
const data = []
|
||||
for (let i = 0; i < 5; i++) {
|
||||
data.push({
|
||||
label: `项目 ${String.fromCharCode(65 + i)}`,
|
||||
value: Math.floor(Math.random() * 100) + 10,
|
||||
id: `data-${dataIndex}-${i}`
|
||||
})
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// 添加新的浮动面板
|
||||
const addFloatingPanel = () => {
|
||||
// 获取父容器尺寸以计算居中位置
|
||||
@@ -217,13 +257,15 @@ const addFloatingPanel = () => {
|
||||
panels: [
|
||||
{
|
||||
id: `panel-${areaIdCounter - 1}-1-1`,
|
||||
title: `面板 1`,
|
||||
title: `面板 ${areaIdCounter - 1}`,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 100,
|
||||
height: 100,
|
||||
collapsed: false,
|
||||
toolbarExpanded: false
|
||||
toolbarExpanded: false,
|
||||
// 添加随机测试内容以便合并测试
|
||||
content: generateRandomContent(areaIdCounter - 1)
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -354,6 +396,41 @@ const addAreaToHiddenList = (area) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 处理Area合并事件
|
||||
const onAreaMerged = (eventData) => {
|
||||
console.log('处理Area合并事件:', eventData)
|
||||
|
||||
const { sourceArea, targetAreaHasContent } = eventData
|
||||
|
||||
// 获取源Area对象
|
||||
const sourceAreaObj = floatingAreas.value.find(a => a.id === sourceArea.id)
|
||||
if (!sourceAreaObj) {
|
||||
console.warn('找不到源Area:', sourceArea.id)
|
||||
return
|
||||
}
|
||||
|
||||
// 根据目标Area内容状态执行不同的隐藏逻辑
|
||||
if (targetAreaHasContent) {
|
||||
// 目标Area已有内容:保存源Area及其TabPage组件到隐藏列表
|
||||
console.log('目标Area已有内容,保存源Area和TabPage组件到隐藏列表')
|
||||
addAreaToHiddenList({
|
||||
...sourceAreaObj,
|
||||
tabPages: [...sourceAreaObj.tabPages] // 深拷贝TabPages
|
||||
})
|
||||
} else {
|
||||
// 目标Area为空:仅保存源Area到隐藏列表
|
||||
console.log('目标Area为空,保存源Area到隐藏列表')
|
||||
addAreaToHiddenList(sourceAreaObj)
|
||||
}
|
||||
|
||||
// 从浮动区域中移除已合并的源Area
|
||||
const sourceIndex = floatingAreas.value.findIndex(a => a.id === sourceArea.id)
|
||||
if (sourceIndex !== -1) {
|
||||
floatingAreas.value.splice(sourceIndex, 1)
|
||||
console.log('源Area已从浮动区域移除:', sourceArea.id)
|
||||
}
|
||||
}
|
||||
|
||||
// Panel拖拽开始
|
||||
const onPanelDragStart = (areaId, event) => {
|
||||
const area = floatingAreas.value.find(a => a.id === areaId)
|
||||
@@ -909,7 +986,7 @@ const onPanelMaximizeSync = ({ areaId, maximized }) => {
|
||||
* 检查Area是否可以停靠到中心区域
|
||||
* @param {Object} sourceArea - 源Area对象
|
||||
* @param {Object} targetArea - 目标Area对象(主区域)
|
||||
* @returns {Object} 验证结果 {canDock: boolean, reason: string}
|
||||
* @returns {Object} 验证结果 {canDock: boolean, reason: string, strategy: string}
|
||||
*/
|
||||
const canDockToCenter = (sourceArea, targetArea) => {
|
||||
// 验证1:检查源Area是否包含TabPage
|
||||
@@ -949,69 +1026,248 @@ const canDockToCenter = (sourceArea, targetArea) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 所有验证通过
|
||||
// 5.2. 新增验证:根据目标Area状态确定停靠策略
|
||||
// 检查主区域内容状态
|
||||
checkMainContentForAreas()
|
||||
|
||||
// 如果主区域已有内容,判断停靠策略
|
||||
if (hasAreasInMainContent.value) {
|
||||
// 检查主区域是否已有TabPage
|
||||
const mainAreaElement = mainAreaRef.value?.$el
|
||||
if (mainAreaElement) {
|
||||
const existingTabPages = mainAreaElement.querySelectorAll('.tab-page, [class*="tab"]')
|
||||
const hasExistingTabPage = existingTabPages.length > 0
|
||||
|
||||
if (hasExistingTabPage && sourceArea.tabPages.length === 1) {
|
||||
// 场景5.2:源Area只有一个TabPage,目标Area也有TabPage
|
||||
// 策略:合并TabPage标签页
|
||||
return {
|
||||
canDock: true,
|
||||
reason: '可以停靠 - 采用TabPage标签页合并策略',
|
||||
strategy: 'merge-tabpages'
|
||||
}
|
||||
} else {
|
||||
// 其他场景:采用简单Area内容移动策略
|
||||
return {
|
||||
canDock: true,
|
||||
reason: '可以停靠 - 采用简单移动策略',
|
||||
strategy: 'simple-move'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 主区域为空的情况:采用简单移动策略
|
||||
return {
|
||||
canDock: true,
|
||||
reason: '验证通过,可以停靠到中心区域'
|
||||
reason: '验证通过,可以停靠到中心区域',
|
||||
strategy: 'simple-move'
|
||||
}
|
||||
}
|
||||
|
||||
// 第3步:中心停靠逻辑
|
||||
// 3.3 创建handleCenterDocking核心处理函数
|
||||
/**
|
||||
* 处理中心停靠的核心函数
|
||||
* @param {string} areaId - 源Area的ID
|
||||
* 处理中心停靠逻辑
|
||||
* @param {string} sourceAreaId - 源Area的ID
|
||||
* @returns {Object} 处理结果 {success: boolean, message: string}
|
||||
*/
|
||||
const handleCenterDocking = (areaId) => {
|
||||
const handleCenterDocking = (sourceAreaId) => {
|
||||
console.log('开始处理中心停靠:', sourceAreaId)
|
||||
|
||||
// 1. 查找源Area
|
||||
const sourceArea = floatingAreas.value.find(a => a.id === sourceAreaId)
|
||||
if (!sourceArea) {
|
||||
return {
|
||||
success: false,
|
||||
message: `未找到ID为 ${sourceAreaId} 的源Area`
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 验证停靠条件
|
||||
const validationResult = canDockToCenter(sourceArea, mainAreaRef.value)
|
||||
if (!validationResult.canDock) {
|
||||
return {
|
||||
success: false,
|
||||
message: `停靠验证失败: ${validationResult.reason}`
|
||||
}
|
||||
}
|
||||
|
||||
console.log('停靠验证通过:', validationResult.reason)
|
||||
|
||||
try {
|
||||
// 3.4 查找源Area
|
||||
const sourceArea = floatingAreas.value.find(a => a.id === areaId)
|
||||
if (!sourceArea) {
|
||||
return {
|
||||
success: false,
|
||||
message: '找不到指定的Area'
|
||||
}
|
||||
}
|
||||
|
||||
// 2.1-2.5 验证是否可以停靠到中心
|
||||
const validation = canDockToCenter(sourceArea, mainAreaRef.value)
|
||||
if (!validation.canDock) {
|
||||
return {
|
||||
success: false,
|
||||
message: `验证失败:${validation.reason}`
|
||||
}
|
||||
}
|
||||
|
||||
// 3.4 实现Area子组件移动到主区域的逻辑
|
||||
// 将Area的内容移动到主区域(通过主区域Ref处理)
|
||||
if (mainAreaRef.value && mainAreaRef.value.appendAreaContent) {
|
||||
mainAreaRef.value.appendAreaContent(sourceArea)
|
||||
// 3. 根据策略执行停靠逻辑
|
||||
if (validationResult.strategy === 'merge-tabpages') {
|
||||
// 5.2. 策略:合并TabPage标签页
|
||||
return handleMergeTabpagesDocking(sourceArea)
|
||||
} else {
|
||||
console.warn('主区域Ref不可用,无法移动内容')
|
||||
// 默认策略:简单Area内容移动
|
||||
return handleSimpleAreaDocking(sourceArea)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('停靠处理过程中发生错误:', error)
|
||||
return {
|
||||
success: false,
|
||||
message: `停靠过程中发生错误: ${error.message}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5.2. 新增:处理TabPage标签页合并策略
|
||||
/**
|
||||
* 处理TabPage标签页合并策略
|
||||
* 当源Area只有一个TabPage且目标Area已有TabPage时使用此策略
|
||||
* @param {Object} sourceArea - 源Area对象
|
||||
* @returns {Object} 处理结果 {success: boolean, message: string}
|
||||
*/
|
||||
// 合并TabPage标签页的核心处理函数
|
||||
const handleMergeTabpagesDocking = (sourceArea) => {
|
||||
console.log(`[DockLayout] 开始合并TabPage标签页,源Area:`, sourceArea)
|
||||
|
||||
try {
|
||||
// 验证源Area是否有效
|
||||
if (!sourceArea || !sourceArea.tabPages || sourceArea.tabPages.length === 0) {
|
||||
console.warn('[DockLayout] 源Area无效或没有TabPage,无法执行合并操作')
|
||||
return null
|
||||
}
|
||||
|
||||
// 查找主区域的Area组件
|
||||
const mainArea = mainAreaRef.value
|
||||
if (!mainArea) {
|
||||
console.error('[DockLayout] 找不到主区域引用')
|
||||
return null
|
||||
}
|
||||
|
||||
console.log('[DockLayout] 使用新的mergeAreaContent方法合并TabPage')
|
||||
const success = mainArea.mergeAreaContent(sourceArea)
|
||||
|
||||
if (success) {
|
||||
const newTabPageId = `merged-${Date.now()}`
|
||||
const panelsCount = sourceArea.tabPages[0]?.panels?.length || 0
|
||||
console.log(`[DockLayout] 成功合并 ${panelsCount} 个Panel到主区域TabPage: ${newTabPageId}`)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
newTabPageId: newTabPageId,
|
||||
panelsAdded: panelsCount
|
||||
}
|
||||
}
|
||||
|
||||
console.error('[DockLayout] mergeAreaContent方法执行失败')
|
||||
return null
|
||||
|
||||
} catch (error) {
|
||||
console.error('[DockLayout] 合并TabPage时发生错误:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在主区域查找或创建TabPage
|
||||
* @returns {Object} 查找结果 {success: boolean, message: string, tabPage?: Object}
|
||||
*/
|
||||
const findOrCreateMainAreaTabPage = () => {
|
||||
try {
|
||||
// 检查主区域是否已经接收了内容
|
||||
if (mainAreaRef.value && mainAreaRef.value.receivedContent) {
|
||||
const existingContent = mainAreaRef.value.receivedContent
|
||||
console.log('检查主区域已接收内容,数量:', existingContent.length)
|
||||
|
||||
if (existingContent.length > 0) {
|
||||
// 找到现有的TabPage内容
|
||||
const existingTabPage = existingContent[0] // 只使用第一个TabPage
|
||||
console.log('找到现有的TabPage:', existingTabPage.title)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: '找到现有的TabPage',
|
||||
tabPage: existingTabPage.tabPage,
|
||||
rawTabPage: existingTabPage // 返回原始TabPage对象以供修改
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3.5 实现Area添加到隐藏列表的逻辑
|
||||
addAreaToHiddenList(sourceArea)
|
||||
|
||||
// 3.6 实现Area从浮动区域移除的逻辑
|
||||
const index = floatingAreas.value.findIndex(a => a.id === areaId)
|
||||
if (index !== -1) {
|
||||
floatingAreas.value.splice(index, 1)
|
||||
}
|
||||
|
||||
// 3.7 更新主区域和浮动区域的响应式状态
|
||||
checkMainContentForAreas()
|
||||
// 如果主区域没有内容,现在不再主动创建空TabPage
|
||||
// 因为在合并逻辑中,Area会自动根据需要创建TabPage
|
||||
console.log('主区域没有现有TabPage,将通过合并操作自动创建')
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: '成功停靠到中心区域'
|
||||
message: '主区域为空,等待合并操作创建TabPage',
|
||||
tabPage: null,
|
||||
rawTabPage: null
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('中心停靠处理错误:', error)
|
||||
console.error('查找TabPage时发生错误:', error)
|
||||
return {
|
||||
success: false,
|
||||
message: `停靠处理出错:${error.message}`
|
||||
message: `查找TabPage失败: ${error.message}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3.4 实现简单Area停靠策略(重构为使用合并逻辑)
|
||||
/**
|
||||
* 处理简单Area停靠策略(Area内容合并)
|
||||
* 当主区域为空或不符合TabPage合并条件时使用此策略
|
||||
* @param {Object} sourceArea - 源Area对象
|
||||
* @returns {Object} 处理结果 {success: boolean, message: string}
|
||||
*/
|
||||
const handleSimpleAreaDocking = (sourceArea) => {
|
||||
console.log('执行简单Area停靠策略(使用合并逻辑)')
|
||||
|
||||
try {
|
||||
// 1. 验证源Area结构
|
||||
if (!sourceArea.tabPages || sourceArea.tabPages.length === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: '源Area不包含TabPage,无法进行停靠合并'
|
||||
}
|
||||
}
|
||||
|
||||
console.log('源Area结构验证通过,包含', sourceArea.tabPages.length, '个TabPage')
|
||||
|
||||
// 2. 使用mergeAreaContent方法将源Area合并到主区域
|
||||
if (mainAreaRef.value && typeof mainAreaRef.value.mergeAreaContent === 'function') {
|
||||
console.log('通过mergeAreaContent方法合并源Area到主区域')
|
||||
const result = mainAreaRef.value.mergeAreaContent(sourceArea)
|
||||
|
||||
if (result) {
|
||||
console.log('源Area成功合并到主区域,area-merged事件将处理隐藏列表操作')
|
||||
|
||||
// 3. 更新主区域状态(合并完成后由事件处理函数处理隐藏列表)
|
||||
nextTick(() => {
|
||||
checkMainContentForAreas()
|
||||
// 确保主区域最大化显示还原按钮
|
||||
if (mainAreaRef.value) {
|
||||
mainAreaRef.value.WindowState = '最大化'
|
||||
console.log('主区域状态已设置为最大化')
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `成功合并 ${sourceArea.tabPages.length} 个TabPage到主区域`
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
message: 'mergeAreaContent方法执行失败'
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error('主区域不支持mergeAreaContent方法')
|
||||
return {
|
||||
success: false,
|
||||
message: '主区域不支持合并操作'
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('简单Area停靠策略执行时发生错误:', error)
|
||||
return {
|
||||
success: false,
|
||||
message: `简单Area停靠失败: ${error.message}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,41 @@
|
||||
</div>
|
||||
|
||||
<!-- 内容区:可折叠 -->
|
||||
<div class="content-area bg-[#f5f7fb] flex-1" v-show="!collapsed"></div>
|
||||
<div class="content-area bg-[#f5f7fb] flex-1 p-4" v-show="!collapsed">
|
||||
<div v-if="content" class="panel-content">
|
||||
<div class="mb-4">
|
||||
<h3 class="text-lg font-bold mb-2" :style="{ color: content.color }">
|
||||
{{ content.title }}
|
||||
</h3>
|
||||
<p class="text-sm text-gray-600 mb-3">
|
||||
类型:{{ content.type }} | 创建时间:{{ content.timestamp }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 gap-3">
|
||||
<div
|
||||
v-for="(item, index) in content.data"
|
||||
:key="item.id"
|
||||
class="data-item p-3 border rounded-lg shadow-sm"
|
||||
:style="{
|
||||
borderLeftColor: content.color,
|
||||
borderLeftWidth: '4px'
|
||||
}"
|
||||
>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="font-medium">{{ item.label }}</span>
|
||||
<span class="text-sm font-bold" :style="{ color: content.color }">
|
||||
{{ item.value }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-gray-500 text-center">
|
||||
<p>暂无内容</p>
|
||||
<div class="mt-2 text-xs">面板ID: {{ id }} - 标题: {{ title }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -116,6 +150,10 @@ const props = defineProps({
|
||||
maximized: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
content: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -35,10 +35,9 @@
|
||||
1. 当一个Panel被拖动时,显示停靠指示器。
|
||||
2. 当拖动Panel到指示器时,显示停靠区。
|
||||
3. 当主区域内没有其他Area时,隐藏外部边缘指示器、中心区域容器,只显示中心指示器。
|
||||
4. 当将源Panel拖动到中心指示器时
|
||||
4.1. 如果源Area只有一个直接子组件(TabPage),且目标Area内容区为空,则将源Area的子组件停靠到中心区域。这个源Area保存到DockLayout的的隐藏列表中。
|
||||
5. 当将源Area拖动到中心指示器时
|
||||
5.1. 如果源Area只有一个直接子组件(TabPage),且目标Area内容区为空,则将源Area的子组件停靠到中心区域。这个源Area保存到DockLayout的的隐藏列表中。
|
||||
5.2. 如果源Area只有一个直接子组件(TabPage),且目标Area内容区已经包含一个TabPage,则将源Area的TabPage组件的每个标签页移动并添加到目标Area的Tabpage中。这个源Area保存到DockLayout的的隐藏列表中。
|
||||
4. 当将源Area拖动到中心指示器时
|
||||
4.1. Area的merge行为只接受一个Area参数.
|
||||
4.1. 如果目标Area内容区为空,则将源Area内容区的子组件添加到目标Area内容区。这个源Area保存到DockLayout的的隐藏列表中。
|
||||
4.2. 如果目标Area内容区已经包含一个TabPage,则将源Area的TabPage组件的每个标签页添加到目标Area的Tabpage中。这个源Area和源Area的TabPage组件保存到DockLayout的的隐藏列表中。
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user