拖拽Area停靠中心区域
This commit is contained in:
@@ -99,14 +99,52 @@
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="vs-content">
|
||||
<!-- 这里是内容区域,使用slot接收子组件,并监听Panel的maximize事件 -->
|
||||
<slot @maximize="onPanelMaximize"></slot>
|
||||
<!-- 这里是内容区域,优先显示slot内容,如果没有slot内容则显示接收到的外部内容 -->
|
||||
<template v-if="$slots.default">
|
||||
<slot @maximize="onPanelMaximize"></slot>
|
||||
</template>
|
||||
<!-- 直接显示接收到的外部TabPage内容,不需要额外包装 -->
|
||||
<template v-else-if="receivedContent.length > 0">
|
||||
<TabPage
|
||||
v-for="(item, index) in receivedContent"
|
||||
:key="`received-tab-${index}`"
|
||||
:id="item.tabPage.id"
|
||||
:title="item.tabPage.title"
|
||||
:panels="item.tabPage.panels"
|
||||
:tabPosition="'bottom'"
|
||||
@tabDragStart="() => {}"
|
||||
@tabDragMove="() => {}"
|
||||
@tabDragEnd="() => {}"
|
||||
>
|
||||
<!-- 在TabPage内渲染其包含的Panels -->
|
||||
<Panel
|
||||
v-for="panel in item.tabPage.panels"
|
||||
:key="`received-panel-${index}-${panel.id}`"
|
||||
:id="panel.id"
|
||||
:title="panel.title"
|
||||
:collapsed="panel.collapsed"
|
||||
:toolbarExpanded="panel.toolbarExpanded"
|
||||
:maximized="panel.maximized"
|
||||
@toggleCollapse="() => {}"
|
||||
@maximize="onPanelMaximize"
|
||||
@close="() => {}"
|
||||
@toggleToolbar="() => {}"
|
||||
@dragStart="() => {}"
|
||||
@dragMove="() => {}"
|
||||
@dragEnd="() => {}"
|
||||
@dragover="handleDragOver"
|
||||
@dragleave="handleDragLeave"
|
||||
/>
|
||||
</TabPage>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, computed, defineEmits, ref, onMounted, watch } from 'vue'
|
||||
import { defineProps, computed, defineEmits, ref, onMounted, watch, defineExpose } from 'vue'
|
||||
import TabPage from './TabPage.vue'
|
||||
import Panel from './Panel.vue'
|
||||
|
||||
const props = defineProps({
|
||||
id: { type: String, required: true },
|
||||
@@ -137,6 +175,9 @@ const originalPosition = ref({
|
||||
// 保存最大化前的位置和大小,用于还原
|
||||
const maximizedFromPosition = ref(null)
|
||||
|
||||
// 存储接收到的外部Area内容
|
||||
const receivedContent = ref([])
|
||||
|
||||
// 拖拽相关状态
|
||||
const isDragging = ref(false)
|
||||
const dragStartPos = ref({ x: 0, y: 0 })
|
||||
@@ -527,6 +568,61 @@ onMounted(() => {
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 添加Area内容的方法,用于主区域的Area接收外部Area内容
|
||||
const appendAreaContent = (sourceArea) => {
|
||||
console.log(`[Area] ${props.id} 接收到内容移动请求:`, sourceArea)
|
||||
|
||||
if (!sourceArea) {
|
||||
console.warn('[Area] 源Area为空,无法接收内容')
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
// 清空之前的内容,确保只接收一个新的TabPage
|
||||
receivedContent.value = []
|
||||
|
||||
// 处理源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
|
||||
})
|
||||
console.log(`[Area] 成功接收tabPage: ${tabPage.title},并设置Panel为最大化状态`)
|
||||
}
|
||||
} else {
|
||||
console.warn('[Area] 源Area中没有tabPages数据')
|
||||
}
|
||||
|
||||
console.log(`[Area] ${props.id} 当前接收内容数量: ${receivedContent.value.length}`)
|
||||
return true
|
||||
|
||||
} catch (error) {
|
||||
console.error('[Area] 接收外部内容时出错:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露方法给父组件调用
|
||||
defineExpose({
|
||||
appendAreaContent,
|
||||
id: props.id,
|
||||
title: props.title,
|
||||
isMaximized: isMaximized.value
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -784,4 +880,55 @@ onMounted(() => {
|
||||
align-items: stretch;
|
||||
justify-content: stretch;
|
||||
}
|
||||
|
||||
/* 接收到的外部内容样式 */
|
||||
.received-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background: #f8f9ff;
|
||||
border: 1px solid #e0e6f0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.received-item {
|
||||
background: white;
|
||||
border: 1px solid #d0d7e2;
|
||||
border-radius: 6px;
|
||||
margin: 8px;
|
||||
padding: 12px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
transition: box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.received-item:hover {
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.received-title {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #2c3e7a;
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 6px;
|
||||
border-bottom: 1px solid #e8edf7;
|
||||
}
|
||||
|
||||
.received-body {
|
||||
min-height: 60px;
|
||||
}
|
||||
|
||||
/* TabPage和Panel容器样式 */
|
||||
.tab-page-container,
|
||||
.area-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px dashed #c7d2ea;
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
background: #fafbff;
|
||||
color: #6b7aa9;
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user