2025-10-31 23:58:26 +08:00
|
|
|
|
<template>
|
2025-12-04 14:58:41 +08:00
|
|
|
|
<div class="dock-layout" ref="dockLayoutRef" style="display: flex; flex-direction: column; position: relative; width: 100%; height: 100%;">
|
2025-11-07 15:41:44 +08:00
|
|
|
|
<!-- 停靠指示器组件 - 设置高z-index确保显示在最顶层 -->
|
|
|
|
|
|
<DockIndicator
|
2025-11-14 09:39:59 +08:00
|
|
|
|
:visible="showDockIndicator"
|
2025-11-07 15:41:44 +08:00
|
|
|
|
:target-rect="targetAreaRect"
|
|
|
|
|
|
:mouse-position="currentMousePosition"
|
2025-11-14 14:23:10 +08:00
|
|
|
|
:hide-edge-indicators="hideEdgeIndicators"
|
2025-11-07 15:41:44 +08:00
|
|
|
|
@zone-active="onDockZoneActive"
|
|
|
|
|
|
style="z-index: 9999;"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
2025-11-13 10:50:22 +08:00
|
|
|
|
<!-- 主区域 - 添加ref引用 -->
|
2025-11-04 09:10:15 +08:00
|
|
|
|
<Area
|
2025-11-14 14:23:10 +08:00
|
|
|
|
ref="mainAreaRef"
|
2025-12-04 14:58:41 +08:00
|
|
|
|
:windowState="windowState"
|
2025-11-04 09:10:15 +08:00
|
|
|
|
:showTitleBar="false"
|
2025-12-04 14:58:41 +08:00
|
|
|
|
title="主区域"
|
2025-11-07 15:41:44 +08:00
|
|
|
|
@dragover="handleMainAreaDragOver"
|
|
|
|
|
|
@dragleave="handleMainAreaDragLeave"
|
2025-11-17 16:55:03 +08:00
|
|
|
|
@area-merged="onAreaMerged"
|
2025-11-05 16:40:27 +08:00
|
|
|
|
>
|
2025-11-18 15:39:46 +08:00
|
|
|
|
<div class="main-content-container" style="position: relative; width: 100%; height: 100%;">
|
|
|
|
|
|
<ResizeBar
|
|
|
|
|
|
v-for="resizeBar in mainAreaResizeBars"
|
|
|
|
|
|
:key="resizeBar.id"
|
|
|
|
|
|
:target-id="resizeBar.targetId"
|
|
|
|
|
|
:direction="resizeBar.direction"
|
|
|
|
|
|
:min-size="resizeBar.minSize"
|
|
|
|
|
|
:max-size="resizeBar.maxSize"
|
|
|
|
|
|
:initial-size="resizeBar.initialSize"
|
|
|
|
|
|
@resize="(size) => handleMainAreaResizeBar(resizeBar.id, size)"
|
|
|
|
|
|
@resize-start="() => handleMainAreaResizeBarStart(resizeBar.id)"
|
|
|
|
|
|
@resize-end="() => handleMainAreaResizeBarEnd(resizeBar.id)"
|
|
|
|
|
|
:style="getMainAreaResizeBarStyle(resizeBar)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2025-11-07 14:44:07 +08:00
|
|
|
|
</Area>
|
2025-11-20 13:14:31 +08:00
|
|
|
|
|
2025-11-19 13:57:51 +08:00
|
|
|
|
<!-- 浮动区域使用Render组件统一渲染 -->
|
|
|
|
|
|
<Render
|
2025-11-07 14:44:07 +08:00
|
|
|
|
v-for="area in floatingAreas"
|
|
|
|
|
|
:key="area.id"
|
2025-11-19 15:26:39 +08:00
|
|
|
|
:type="'Area'"
|
2025-11-19 13:57:51 +08:00
|
|
|
|
:config="area"
|
|
|
|
|
|
:style="{ zIndex: area.zIndex || zIndexManager.getFloatingAreaZIndex(area.id) }"
|
|
|
|
|
|
@close="() => onCloseFloatingArea(area.id)"
|
|
|
|
|
|
@update:position="(position) => onUpdatePosition(area.id, position)"
|
2025-11-07 14:44:07 +08:00
|
|
|
|
@panelMaximizeSync="onPanelMaximizeSync"
|
2025-11-19 13:57:51 +08:00
|
|
|
|
@areaDragStart="(event) => onAreaDragStart(area.id, event)"
|
|
|
|
|
|
@areaDragMove="(event) => onAreaDragMove(area.id, event)"
|
|
|
|
|
|
@areaDragEnd="(event) => onAreaDragEnd(area.id, event)"
|
|
|
|
|
|
@tab-change="onTabChange"
|
|
|
|
|
|
@tab-close="onTabClose"
|
|
|
|
|
|
@tab-add="onTabAdd"
|
|
|
|
|
|
@tabDragStart="(event) => onTabDragStart(area.id, event)"
|
|
|
|
|
|
@tabDragMove="(event) => onTabDragMove(area.id, event)"
|
|
|
|
|
|
@tabDragEnd="onTabDragEnd"
|
|
|
|
|
|
@toggleCollapse="(panelId) => $emit('toggleCollapse', panelId)"
|
|
|
|
|
|
@maximize="(panelId) => onMaximize(panelId)"
|
|
|
|
|
|
@closePanel="(panelId) => onClosePanel(area.id, panelId)"
|
|
|
|
|
|
@toggleToolbar="(panelId) => $emit('toggleToolbar', panelId)"
|
|
|
|
|
|
@dragStart="(event) => onPanelDragStartFromTabPage(area.id, event)"
|
|
|
|
|
|
@dragMove="(event) => onPanelDragMoveFromTabPage(area.id, event)"
|
|
|
|
|
|
@dragEnd="onPanelDragEndFromTabPage"
|
|
|
|
|
|
@dragover="handleAreaDragOver"
|
|
|
|
|
|
@dragleave="handleAreaDragLeave"
|
|
|
|
|
|
/>
|
2025-11-02 17:19:53 +07:00
|
|
|
|
</div>
|
2025-10-31 23:58:26 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2025-12-04 14:58:41 +08:00
|
|
|
|
import { ref, computed, onMounted, onUnmounted, defineEmits } from 'vue'
|
2025-10-31 23:58:26 +08:00
|
|
|
|
import Area from './Area.vue';
|
2025-11-02 17:06:40 +07:00
|
|
|
|
import Panel from './Panel.vue';
|
2025-11-05 09:02:11 +08:00
|
|
|
|
import TabPage from './TabPage.vue';
|
2025-11-07 15:41:44 +08:00
|
|
|
|
import DockIndicator from './DockIndicator.vue';
|
2025-11-18 15:39:46 +08:00
|
|
|
|
import ResizeBar from './ResizeBar.vue';
|
2025-11-19 13:57:51 +08:00
|
|
|
|
import Render from './Render.vue';
|
2025-11-20 13:14:31 +08:00
|
|
|
|
import { zIndexManager } from './dockLayers.js';
|
|
|
|
|
|
|
|
|
|
|
|
// 导入事件处理器
|
|
|
|
|
|
import { areaActions } from './handlers/AreaHandler.js';
|
|
|
|
|
|
import { dragStateActions } from './handlers/DragStateManager.js';
|
|
|
|
|
|
import { panelActions } from './handlers/PanelHandler.js';
|
|
|
|
|
|
import { globalEventActions } from './handlers/GlobalEventManager.js';
|
2025-11-02 17:06:40 +07:00
|
|
|
|
|
2025-11-18 13:48:13 +08:00
|
|
|
|
// 定义组件可以发出的事件
|
|
|
|
|
|
const emit = defineEmits([
|
|
|
|
|
|
'maximize', // 面板最大化事件
|
|
|
|
|
|
'toggleCollapse', // 折叠状态切换事件
|
|
|
|
|
|
'toggleToolbar', // 工具栏切换事件
|
|
|
|
|
|
'dragStart', // 拖拽开始事件
|
|
|
|
|
|
'dragMove', // 拖拽移动事件
|
|
|
|
|
|
'dragEnd' // 拖拽结束事件
|
|
|
|
|
|
])
|
|
|
|
|
|
|
2025-11-02 17:06:40 +07:00
|
|
|
|
// 主区域状态
|
2025-11-01 14:23:35 +07:00
|
|
|
|
const windowState = ref('最大化')
|
2025-11-02 17:06:40 +07:00
|
|
|
|
|
2025-11-04 10:53:22 +08:00
|
|
|
|
// 浮动区域列表 - 每个area包含panels数组
|
2025-11-02 17:06:40 +07:00
|
|
|
|
const floatingAreas = ref([])
|
|
|
|
|
|
|
2025-11-04 09:45:51 +08:00
|
|
|
|
// 容器引用
|
|
|
|
|
|
const dockLayoutRef = ref(null)
|
2025-11-14 14:23:10 +08:00
|
|
|
|
// 主区域引用
|
|
|
|
|
|
const mainAreaRef = ref(null)
|
2025-11-02 17:06:40 +07:00
|
|
|
|
|
2025-11-07 15:41:44 +08:00
|
|
|
|
// 停靠指示器相关状态
|
|
|
|
|
|
const showDockIndicator = ref(false)
|
|
|
|
|
|
const currentMousePosition = ref({ x: 0, y: 0 })
|
|
|
|
|
|
const targetAreaRect = ref({ left: 0, top: 0, width: 0, height: 0 })
|
|
|
|
|
|
const activeDockZone = ref(null)
|
|
|
|
|
|
|
2025-11-18 15:39:46 +08:00
|
|
|
|
// 主区域ResizeBar列表
|
|
|
|
|
|
const mainAreaResizeBars = ref([])
|
|
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// 检查主区域内是否有其他Area(简化版)
|
|
|
|
|
|
const hasAreasInMainContent = ref(false)
|
2025-11-14 14:23:10 +08:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// 代理到事件处理器的方法
|
|
|
|
|
|
const onPanelDragStart = (areaId, event) => {
|
|
|
|
|
|
dragStateActions.onPanelDragStart(areaId, event);
|
|
|
|
|
|
};
|
2025-11-04 11:05:12 +08:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const onPanelDragMove = (areaId, event) => {
|
|
|
|
|
|
dragStateActions.onPanelDragMove(areaId, event);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onPanelDragEnd = () => {
|
|
|
|
|
|
dragStateActions.onPanelDragEnd();
|
|
|
|
|
|
};
|
2025-11-06 14:57:30 +08:00
|
|
|
|
|
2025-11-18 15:39:46 +08:00
|
|
|
|
const onPanelDragStartFromTabPage = (areaId, event) => {
|
2025-11-20 13:14:31 +08:00
|
|
|
|
dragStateActions.onPanelDragStartFromTabPage(areaId, event);
|
|
|
|
|
|
};
|
2025-11-18 15:39:46 +08:00
|
|
|
|
|
|
|
|
|
|
const onPanelDragMoveFromTabPage = (areaId, event) => {
|
2025-11-20 13:14:31 +08:00
|
|
|
|
dragStateActions.onPanelDragMoveFromTabPage(areaId, event);
|
|
|
|
|
|
};
|
2025-11-18 15:39:46 +08:00
|
|
|
|
|
|
|
|
|
|
const onPanelDragEndFromTabPage = () => {
|
2025-11-20 13:14:31 +08:00
|
|
|
|
dragStateActions.onPanelDragEndFromTabPage();
|
|
|
|
|
|
};
|
2025-11-18 15:39:46 +08:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const onAreaDragStart = (areaId, event) => {
|
|
|
|
|
|
dragStateActions.onAreaDragStart(areaId, event);
|
|
|
|
|
|
};
|
2025-11-14 15:45:54 +08:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const onAreaDragMove = (areaId, event) => {
|
|
|
|
|
|
dragStateActions.onAreaDragMove(areaId, event);
|
|
|
|
|
|
};
|
2025-11-14 14:23:10 +08:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const onAreaDragEnd = (areaId, event) => {
|
|
|
|
|
|
dragStateActions.onAreaDragEnd(areaId, event);
|
|
|
|
|
|
};
|
2025-11-17 16:55:03 +08:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const onTabDragStart = (areaId, event) => {
|
|
|
|
|
|
dragStateActions.onTabDragStart(areaId, event);
|
|
|
|
|
|
};
|
2025-11-17 16:55:03 +08:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const onTabDragMove = (areaId, event) => {
|
|
|
|
|
|
dragStateActions.onTabDragMove(areaId, event);
|
|
|
|
|
|
};
|
2025-11-04 09:45:51 +08:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const onTabDragEnd = () => {
|
|
|
|
|
|
dragStateActions.onTabDragEnd();
|
|
|
|
|
|
};
|
2025-11-02 17:06:40 +07:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// Area相关事件处理
|
2025-11-02 17:06:40 +07:00
|
|
|
|
const onCloseFloatingArea = (id) => {
|
2025-11-20 13:14:31 +08:00
|
|
|
|
areaActions.closeFloatingArea(id);
|
|
|
|
|
|
const index = floatingAreas.value.findIndex(a => a.id === id);
|
2025-11-02 17:06:40 +07:00
|
|
|
|
if (index !== -1) {
|
2025-11-20 13:14:31 +08:00
|
|
|
|
floatingAreas.value.splice(index, 1);
|
2025-11-02 17:06:40 +07:00
|
|
|
|
}
|
2025-11-20 13:14:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onUpdatePosition = (id, position) => {
|
|
|
|
|
|
const area = floatingAreas.value.find(a => a.id === id);
|
|
|
|
|
|
if (area) {
|
|
|
|
|
|
area.x = position.left;
|
|
|
|
|
|
area.y = position.top;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onMaximize = (panelId) => {
|
|
|
|
|
|
areaActions.toggleMaximize(panelId);
|
|
|
|
|
|
};
|
2025-11-02 17:06:40 +07:00
|
|
|
|
|
2025-11-04 10:53:22 +08:00
|
|
|
|
const onClosePanel = (areaId, panelId) => {
|
2025-11-20 13:14:31 +08:00
|
|
|
|
areaActions.closePanel(areaId, panelId);
|
|
|
|
|
|
const area = floatingAreas.value.find(a => a.id === areaId);
|
2025-11-19 13:57:51 +08:00
|
|
|
|
if (area && area.children) {
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// 移除对应面板
|
2025-11-19 13:57:51 +08:00
|
|
|
|
for (const child of area.children) {
|
2025-11-19 15:26:39 +08:00
|
|
|
|
if (child.type === 'TabPage' && child.children && child.children.type === 'Panel') {
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const panels = child.children.items || [];
|
|
|
|
|
|
const panelIndex = panels.findIndex(p => p.id === panelId);
|
2025-11-06 13:32:18 +08:00
|
|
|
|
if (panelIndex !== -1) {
|
2025-11-20 13:14:31 +08:00
|
|
|
|
panels.splice(panelIndex, 1);
|
|
|
|
|
|
// 如果没有面板了,移除整个TabPage
|
2025-11-19 13:57:51 +08:00
|
|
|
|
if (panels.length === 0) {
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const tabPageIndex = area.children.indexOf(child);
|
|
|
|
|
|
if (tabPageIndex !== -1) {
|
|
|
|
|
|
area.children.splice(tabPageIndex, 1);
|
|
|
|
|
|
}
|
2025-11-06 13:32:18 +08:00
|
|
|
|
}
|
2025-11-20 13:14:31 +08:00
|
|
|
|
break;
|
2025-11-06 13:32:18 +08:00
|
|
|
|
}
|
2025-11-04 10:53:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-20 13:14:31 +08:00
|
|
|
|
};
|
2025-11-04 10:53:22 +08:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// 简单的拖拽事件处理
|
|
|
|
|
|
const handleMainAreaDragOver = (event) => {
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
globalEventActions.handleDragOver('main-area', event);
|
|
|
|
|
|
};
|
2025-11-20 09:51:08 +08:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const handleMainAreaDragLeave = () => {
|
|
|
|
|
|
globalEventActions.handleDragLeave('main-area');
|
|
|
|
|
|
};
|
2025-11-02 17:12:40 +07:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const handleAreaDragOver = (event) => {
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
globalEventActions.handleDragOver('floating-area', event);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleAreaDragLeave = () => {
|
|
|
|
|
|
globalEventActions.handleDragLeave('floating-area');
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 其他事件处理方法
|
|
|
|
|
|
const onDockZoneActive = (zone) => {
|
|
|
|
|
|
activeDockZone.value = zone;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onPanelMaximizeSync = ({ areaId, maximized }) => {
|
|
|
|
|
|
panelActions.syncMaximizeState(areaId, maximized);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onAreaMerged = () => {
|
|
|
|
|
|
areaActions.handleAreaMerged();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onTabChange = (data) => {
|
|
|
|
|
|
panelActions.handleTabChange(data);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onTabClose = (data) => {
|
|
|
|
|
|
panelActions.handleTabClose(data);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const onTabAdd = (data) => {
|
|
|
|
|
|
panelActions.handleTabAdd(data);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// ResizeBar相关处理方法
|
|
|
|
|
|
const handleMainAreaResizeBar = (id, size) => {
|
|
|
|
|
|
areaActions.handleResize(id, size);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleMainAreaResizeBarStart = (id) => {
|
|
|
|
|
|
areaActions.handleResizeStart(id);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleMainAreaResizeBarEnd = (id) => {
|
|
|
|
|
|
areaActions.handleResizeEnd(id);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const getMainAreaResizeBarStyle = (resizeBar) => {
|
|
|
|
|
|
return areaActions.getResizeBarStyle(resizeBar);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 计算属性
|
|
|
|
|
|
const hideEdgeIndicators = computed(() => {
|
|
|
|
|
|
return !hasAreasInMainContent.value;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 简化的事件监听器设置
|
|
|
|
|
|
const setupEventListeners = () => {
|
|
|
|
|
|
// 可以在这里添加必要的事件监听器
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 清理函数
|
|
|
|
|
|
const cleanup = () => {
|
|
|
|
|
|
// 清理事件监听器和其他资源
|
2025-12-04 14:58:41 +08:00
|
|
|
|
console.log('🧹 开始清理DockLayout资源');
|
|
|
|
|
|
|
|
|
|
|
|
// 清理浮动区域
|
|
|
|
|
|
floatingAreas.value = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 清理隐藏区域
|
|
|
|
|
|
hiddenAreas.value = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 清理主区域ResizeBar
|
|
|
|
|
|
mainAreaResizeBars.value = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 清理停靠指示器状态
|
|
|
|
|
|
showDockIndicator.value = false;
|
|
|
|
|
|
currentMousePosition.value = { x: 0, y: 0 };
|
|
|
|
|
|
targetAreaRect.value = { left: 0, top: 0, width: 0, height: 0 };
|
|
|
|
|
|
activeDockZone.value = null;
|
|
|
|
|
|
|
|
|
|
|
|
console.log('✅ DockLayout资源清理完成');
|
2025-11-20 13:14:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 轻量级隐藏区域管理
|
|
|
|
|
|
const hiddenAreas = ref([]);
|
|
|
|
|
|
|
|
|
|
|
|
// 隐藏Area管理方法
|
2025-11-17 10:59:46 +08:00
|
|
|
|
// 将Area添加到隐藏列表
|
|
|
|
|
|
const addAreaToHiddenList = (area) => {
|
|
|
|
|
|
// 确保area有唯一标识符
|
|
|
|
|
|
if (!area.id) {
|
|
|
|
|
|
area.id = `hidden-area-${Date.now()}`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否已经存在于隐藏列表中
|
|
|
|
|
|
const existingIndex = hiddenAreas.value.findIndex(h => h.id === area.id)
|
|
|
|
|
|
if (existingIndex === -1) {
|
|
|
|
|
|
// 添加到隐藏列表
|
|
|
|
|
|
hiddenAreas.value.push({
|
|
|
|
|
|
...area,
|
|
|
|
|
|
hiddenAt: new Date().toISOString()
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// 移除重复的详细实现函数 - 使用轻量级代理
|
2025-11-18 15:39:46 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 处理并排停靠逻辑
|
|
|
|
|
|
* 当主区域内已有Area时,压缩目标Area并创建并排布局
|
|
|
|
|
|
* @param {Object} sourceArea - 源Area对象
|
|
|
|
|
|
* @param {string} dockZone - 停靠方向
|
|
|
|
|
|
* @returns {Object} 处理结果 {success: boolean, message: string}
|
|
|
|
|
|
*/
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// 轻量级并排停靠代理
|
|
|
|
|
|
const handleSideBySideDocking = () => '轻量级并排停靠代理'
|
|
|
|
|
|
|
|
|
|
|
|
// 轻量级ResizeBar添加代理
|
|
|
|
|
|
const addResizeBarForSideBySideLayout = () => '轻量级ResizeBar代理'
|
|
|
|
|
|
|
|
|
|
|
|
// 轻量级ResizeBar事件代理
|
|
|
|
|
|
const handleResizeBarResize = () => '轻量级ResizeBar调整代理'
|
|
|
|
|
|
|
|
|
|
|
|
// 轻量级ResizeBar尺寸调整代理
|
|
|
|
|
|
const handleResizeBarResizeStart = () => '轻量级ResizeBar调整开始代理'
|
|
|
|
|
|
const handleResizeBarResizeEnd = () => '轻量级ResizeBar调整结束代理'
|
|
|
|
|
|
|
|
|
|
|
|
// 轻量级尺寸调整代理
|
|
|
|
|
|
const handleHorizontalResize = () => '轻量级水平调整代理'
|
|
|
|
|
|
const handleVerticalResize = () => '轻量级垂直调整代理'
|
|
|
|
|
|
|
|
|
|
|
|
// 轻量级Area查找代理
|
|
|
|
|
|
const findFirstMainArea = () => '轻量级主区域查找代理'
|
|
|
|
|
|
const getOrCreateTargetArea = () => '轻量级目标区域获取代理'
|
|
|
|
|
|
|
|
|
|
|
|
// 轻量级并排布局代理
|
|
|
|
|
|
const createSideBySideLayout = () => '轻量级并排布局代理'
|
|
|
|
|
|
const compressTargetArea = () => '轻量级压缩目标区域代理'
|
|
|
|
|
|
const adjustSourceAreaForLayout = () => '轻量级布局调整代理'
|
|
|
|
|
|
|
|
|
|
|
|
// 添加浮动面板
|
|
|
|
|
|
const addFloatingPanel = (panel) => {
|
|
|
|
|
|
// 确保panel参数存在,否则使用默认面板对象
|
|
|
|
|
|
const safePanel = panel || {
|
|
|
|
|
|
id: `panel-${Date.now()}`,
|
|
|
|
|
|
title: '新建面板',
|
2025-12-04 14:58:41 +08:00
|
|
|
|
content: {
|
|
|
|
|
|
color: '#435d9c',
|
|
|
|
|
|
title: '默认面板内容',
|
|
|
|
|
|
type: 'default',
|
|
|
|
|
|
timestamp: new Date().toLocaleString(),
|
|
|
|
|
|
data: [
|
|
|
|
|
|
{ id: 1, label: '示例数据1', value: '123' },
|
|
|
|
|
|
{ id: 2, label: '示例数据2', value: '456' },
|
|
|
|
|
|
{ id: 3, label: '示例数据3', value: '789' }
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
2025-11-20 13:14:31 +08:00
|
|
|
|
};
|
2025-11-18 15:39:46 +08:00
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
const newArea = {
|
|
|
|
|
|
id: `area-${Date.now()}`,
|
|
|
|
|
|
x: 100 + Math.random() * 200,
|
|
|
|
|
|
y: 100 + Math.random() * 200,
|
|
|
|
|
|
width: 300,
|
|
|
|
|
|
height: 200,
|
|
|
|
|
|
zIndex: zIndexManager.getFloatingAreaZIndex(`area-${Date.now()}`),
|
2025-12-04 14:58:41 +08:00
|
|
|
|
// 使用children结构以兼容Render组件的渲染逻辑
|
|
|
|
|
|
children: {
|
|
|
|
|
|
type: 'TabPage',
|
|
|
|
|
|
children: [{
|
|
|
|
|
|
...safePanel,
|
|
|
|
|
|
id: `panel-${Date.now()}`,
|
|
|
|
|
|
title: safePanel.title || '新建面板',
|
|
|
|
|
|
type: 'Panel'
|
|
|
|
|
|
}]
|
|
|
|
|
|
}
|
2025-11-18 15:39:46 +08:00
|
|
|
|
}
|
2025-11-20 13:14:31 +08:00
|
|
|
|
floatingAreas.value.push(newArea)
|
|
|
|
|
|
return newArea.id
|
2025-11-18 15:39:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// 查找或创建主区域TabPage
|
|
|
|
|
|
const findOrCreateMainAreaTabPage = () => {
|
|
|
|
|
|
// 返回主区域的tabPage信息
|
|
|
|
|
|
return {
|
|
|
|
|
|
id: 'main-area-tabpage',
|
|
|
|
|
|
title: '主区域',
|
2025-12-04 14:58:41 +08:00
|
|
|
|
items: []
|
2025-11-20 13:14:31 +08:00
|
|
|
|
};
|
2025-11-18 15:39:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// 轻量级生命周期处理
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
// 初始化轻量级状态
|
|
|
|
|
|
console.log('DockLayout component mounted');
|
|
|
|
|
|
})
|
2025-11-18 15:39:46 +08:00
|
|
|
|
|
2025-12-04 14:58:41 +08:00
|
|
|
|
// 组件卸载时清理资源
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
// 清理事件监听器和其他资源
|
|
|
|
|
|
console.log('DockLayout component unmounted');
|
|
|
|
|
|
cleanup();
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// 暴露轻量级接口给父组件
|
2025-11-02 17:12:40 +07:00
|
|
|
|
defineExpose({
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// 基础数据
|
2025-11-19 13:57:51 +08:00
|
|
|
|
floatingAreas,
|
|
|
|
|
|
hiddenAreas,
|
|
|
|
|
|
|
2025-11-20 13:14:31 +08:00
|
|
|
|
// 核心方法
|
2025-11-17 10:59:46 +08:00
|
|
|
|
addFloatingPanel,
|
2025-11-18 15:39:46 +08:00
|
|
|
|
findOrCreateMainAreaTabPage,
|
2025-11-20 13:14:31 +08:00
|
|
|
|
|
|
|
|
|
|
// 轻量级代理方法(功能保留但简化)
|
|
|
|
|
|
handleDockingEnding: () => '轻量级停靠处理代理',
|
|
|
|
|
|
handleEdgeDocking: () => '轻量级边缘停靠代理',
|
|
|
|
|
|
handleSideBySideDocking: () => '轻量级并排停靠代理',
|
|
|
|
|
|
|
|
|
|
|
|
// ResizeBar轻量级代理
|
|
|
|
|
|
addResizeBarForSideBySideLayout: () => '轻量级ResizeBar代理',
|
|
|
|
|
|
handleResizeBarResize: () => '轻量级ResizeBar调整代理',
|
|
|
|
|
|
|
|
|
|
|
|
// 隐藏列表轻量级代理
|
|
|
|
|
|
getHiddenAreas: () => '轻量级隐藏列表代理',
|
|
|
|
|
|
restoreAreaFromHidden: () => '轻量级恢复代理',
|
|
|
|
|
|
removeFromHiddenList: () => '轻量级移除代理',
|
|
|
|
|
|
clearHiddenList: () => '轻量级清空代理',
|
2025-11-02 17:12:40 +07:00
|
|
|
|
})
|
2025-11-02 17:06:40 +07:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.dock-layout {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
2025-11-04 09:10:15 +08:00
|
|
|
|
overflow: visible;
|
2025-11-02 17:06:40 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-03 17:26:28 +08:00
|
|
|
|
/* 浮动区域样式已直接应用到Area组件 */
|
2025-11-02 17:19:53 +07:00
|
|
|
|
|
2025-11-02 17:06:40 +07:00
|
|
|
|
/* 添加浮动区域按钮样式 */
|
|
|
|
|
|
.add-floating-btn {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
user-select: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.add-floating-btn:active {
|
|
|
|
|
|
transform: scale(0.98);
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|