修复运行异常

This commit is contained in:
zqm
2025-12-29 09:05:37 +08:00
parent 09e4076635
commit 9aad6ebc21
10 changed files with 448 additions and 281 deletions

View File

@@ -100,17 +100,23 @@
<!-- 内容区域 --> <!-- 内容区域 -->
<div class="vs-content"> <div class="vs-content">
<!-- 直接渲染插槽内容Render组件会自动处理children --> <!-- 使用Render组件渲染children配置 -->
<slot></slot> <div v-for="child in Array.isArray(children) ? children : [children]" :key="child.id" style="width: 100%; height: 100%;">
<Render
:type="child.type"
:config="child"
/>
</div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { defineProps, computed, ref, onMounted, onUnmounted, watch, defineExpose, useSlots } from 'vue' import { defineProps, computed, ref, onMounted, onUnmounted, watch, defineExpose } from 'vue'
import { emitEvent, EVENT_TYPES, globalEventListenerManager } from './eventBus' import { emitEvent, EVENT_TYPES, globalEventListenerManager } from './eventBus'
import TabPage from './TabPage.vue' import TabPage from './TabPage.vue'
import Panel from './Panel.vue' import Panel from './Panel.vue'
import Render from './Render.vue'
import { zIndexManager, Z_INDEX_LAYERS } from './dockLayers' import { zIndexManager, Z_INDEX_LAYERS } from './dockLayers'
const props = defineProps({ const props = defineProps({
@@ -127,7 +133,12 @@ const props = defineProps({
// 位置属性,可选 // 位置属性,可选
left: { type: Number, default: undefined }, left: { type: Number, default: undefined },
top: { type: Number, default: undefined }, top: { type: Number, default: undefined },
draggable: { type: Boolean, default: true } draggable: { type: Boolean, default: true },
// 子组件配置
children: {
type: [Array, Object],
default: () => []
}
}) })
// 使用全局事件总线和拖拽管理器 // 使用全局事件总线和拖拽管理器
@@ -149,30 +160,32 @@ const maximizedFromPosition = ref(null)
// 组件引用 // 组件引用
const areaRef = ref(null) const areaRef = ref(null)
// 获取插槽 // 不再需要获取插槽改为使用props.children
const slots = useSlots();
// 计算属性:是否显示标题栏 // 计算属性:是否显示标题栏
const shouldShowTitleBar = computed(() => { const shouldShowTitleBar = computed(() => {
// 基础条件props.showTitleBar为true // 基础条件props.showTitleBar为true
if (!props.showTitleBar) return false; if (!props.showTitleBar) return false;
// 获取插槽内容 // 检查children配置
if (slots.default) { if (props.children) {
const slotChildren = slots.default(); const childrenArray = Array.isArray(props.children) ? props.children : [props.children];
// 如果没有插槽内容,显示标题栏 // 如果没有children,显示标题栏
if (slotChildren.length === 0) return true; if (childrenArray.length === 0) return true;
// 如果插槽内容不是TabPage显示标题栏 // 如果children不是TabPage显示标题栏
const firstChild = slotChildren[0]; const firstChild = childrenArray[0];
if (firstChild.type.name !== 'TabPage') return true; if (firstChild.type !== 'TabPage') return true;
// 获取TabPage的插槽内容 // 检查TabPage的children
const tabPageSlots = firstChild.children?.default ? firstChild.children.default() : []; const tabPageChildren = firstChild.children;
if (!tabPageChildren) return true;
const tabPageChildrenArray = Array.isArray(tabPageChildren) ? tabPageChildren : [tabPageChildren];
// 如果TabPage包含多个Panel显示标题栏 // 如果TabPage包含多个Panel显示标题栏
if (tabPageSlots.length !== 1) return true; if (tabPageChildrenArray.length !== 1) return true;
// 如果TabPage只包含一个Panel不显示标题栏 // 如果TabPage只包含一个Panel不显示标题栏
return false; return false;
@@ -275,17 +288,24 @@ const onPanelMaximize = (panelId) => {
// // console.log('🔸 Area接收最大化事件 - Panel ID:', panelId) // // console.log('🔸 Area接收最大化事件 - Panel ID:', panelId)
// 检查内容区是否只有一个Panel // 检查内容区是否只有一个Panel
const slotChildren = slots.default ? slots.default() : []
let isSinglePanel = false let isSinglePanel = false
// 查找TabPage组件 // 检查children配置
const tabPages = slotChildren.filter(child => child.type.name === 'TabPage') if (props.children) {
const childrenArray = Array.isArray(props.children) ? props.children : [props.children]
if (tabPages.length === 1) {
// 获取TabPage的插槽内容 // 查找TabPage组件
const tabPageSlots = tabPages[0].children?.default ? tabPages[0].children.default() : [] const tabPages = childrenArray.filter(child => child.type === 'TabPage')
// 如果TabPage只有一个Panel认为是单Panel模式
isSinglePanel = tabPageSlots.length === 1 if (tabPages.length === 1) {
// 检查TabPage的children
const tabPageChildren = tabPages[0].children
if (tabPageChildren) {
const tabPageChildrenArray = Array.isArray(tabPageChildren) ? tabPageChildren : [tabPageChildren]
// 如果TabPage只有一个Panel认为是单Panel模式
isSinglePanel = tabPageChildrenArray.length === 1
}
}
} }
// // console.log('🔸 检查是否单Panel模式:', { tabPages: tabPages.length, isSinglePanel }) // // console.log('🔸 检查是否单Panel模式:', { tabPages: tabPages.length, isSinglePanel })

View File

@@ -79,7 +79,11 @@ const mainAreaConfig = ref({
id: 'MainArea', id: 'MainArea',
title: '主区域', title: '主区域',
windowState: windowState.value, windowState: windowState.value,
showTitleBar: false showTitleBar: false,
children: {
type: 'TabPage',
children: []
}
}) })
// 浮动区域列表 - 每个area包含panels数组 // 浮动区域列表 - 每个area包含panels数组
@@ -102,7 +106,27 @@ const mainAreaResizeBars = ref([])
// 检查主区域内是否有其他Area简化版 // 检查主区域内是否有其他Area简化版
const hasAreasInMainContent = ref(false) const hasAreasInMainContent = ref(false)
// Area相关事件处理 const shouldOperateAreaInsteadOfPanel = (areaId) => {
const area = floatingAreas.value.find(a => a.id === areaId);
if (!area) return false;
const childrenArray = Array.isArray(area.children) ? area.children : [area.children];
if (childrenArray.length !== 1) return false;
const tabPage = childrenArray[0];
if (tabPage.type !== 'TabPage') return false;
const tabPageChildren = tabPage.children;
const tabPageChildrenArray = Array.isArray(tabPageChildren) ? tabPageChildren : [tabPageChildren];
if (tabPageChildrenArray.length !== 1) return false;
// 检查TabPage的children是否是Panel组件
const childItem = tabPageChildrenArray[0];
if (childItem.type !== 'Panel') return false;
return true;
};
const onCloseFloatingArea = (event) => { const onCloseFloatingArea = (event) => {
const id = event.areaId; const id = event.areaId;
areaActions.closeFloatingArea(id); areaActions.closeFloatingArea(id);
@@ -124,27 +148,55 @@ const onUpdatePosition = (event) => {
const onMaximize = (event) => { const onMaximize = (event) => {
const panelId = event.panelId; const panelId = event.panelId;
areaActions.toggleMaximize(panelId); const areaId = event.areaId;
if (shouldOperateAreaInsteadOfPanel(areaId)) {
areaActions.toggleMaximize(areaId);
} else {
panelActions.maximize(panelId);
}
}; };
const onClosePanel = (event) => { const onPanelClose = (event) => {
const areaId = event.areaId; const areaId = event.areaId;
const panelId = event.panelId; const panelId = event.panelId;
areaActions.closePanel(areaId, panelId);
const area = floatingAreas.value.find(a => a.id === areaId); if (shouldOperateAreaInsteadOfPanel(areaId)) {
if (area && area.children) { onCloseFloatingArea({ areaId });
// 移除对应面板 } else {
for (const child of area.children) { areaActions.closePanel(areaId, panelId);
if (child.type === 'TabPage' && child.children && child.children.type === 'Panel') { const area = floatingAreas.value.find(a => a.id === areaId);
const panels = child.children.items || []; if (area && area.children) {
const panelIndex = panels.findIndex(p => p.id === panelId); for (const child of area.children) {
if (panelIndex !== -1) { if (child.type === 'TabPage' && child.children) {
panels.splice(panelIndex, 1); // 处理TabPage的children可能是单个Panel或Panel数组
// 如果没有面板了移除整个TabPage const isArray = Array.isArray(child.children);
if (panels.length === 0) { const childrenArray = isArray ? child.children : [child.children];
const tabPageIndex = area.children.indexOf(child);
if (tabPageIndex !== -1) { // 检查每个子项是否为Panel组件
area.children.splice(tabPageIndex, 1); for (let i = 0; i < childrenArray.length; i++) {
const item = childrenArray[i];
if (item.type === 'Panel' && item.id === panelId) {
// 从数组中移除Panel
if (isArray) {
child.children.splice(i, 1);
} else {
// 如果是单个Panel移除整个TabPage
const tabPageIndex = area.children.indexOf(child);
if (tabPageIndex !== -1) {
area.children.splice(tabPageIndex, 1);
}
break;
}
// 如果Panel数组为空移除TabPage
if (child.children.length === 0) {
const tabPageIndex = area.children.indexOf(child);
if (tabPageIndex !== -1) {
area.children.splice(tabPageIndex, 1);
}
}
break;
} }
} }
break; break;
@@ -170,7 +222,70 @@ const handleAreaDragOver = (event) => {
}; };
const handleAreaDragLeave = (event) => { const handleAreaDragLeave = (event) => {
globalEventActions.handleDragLeave('floating-area', event); globalEventActions.handleDragLeave('floating-area');
};
const onPanelDragStart = (event) => {
const areaId = event.areaId;
if (shouldOperateAreaInsteadOfPanel(areaId)) {
const area = floatingAreas.value.find(a => a.id === areaId);
const startLeft = area ? (area.x || 0) : 0;
const startTop = area ? (area.y || 0) : 0;
eventBus.emit(EVENT_TYPES.AREA_DRAG_START, {
dragId: event.dragId,
areaId: areaId,
event: {
clientX: event.position.x,
clientY: event.position.y
},
element: null,
position: event.position,
clientX: event.position.x,
clientY: event.position.y,
startLeft: startLeft,
startTop: startTop,
timestamp: event.timestamp
});
}
};
const onPanelDragMove = (event) => {
const areaId = event.areaId;
if (shouldOperateAreaInsteadOfPanel(areaId)) {
eventBus.emit(EVENT_TYPES.AREA_DRAG_MOVE, {
dragId: event.dragId,
areaId: areaId,
event: {
clientX: event.position.x,
clientY: event.position.y
},
position: event.position,
clientX: event.position.x,
clientY: event.position.y,
timestamp: event.timestamp
});
}
};
const onPanelDragEnd = (event) => {
const areaId = event.areaId;
if (shouldOperateAreaInsteadOfPanel(areaId)) {
const area = floatingAreas.value.find(a => a.id === areaId);
const left = area ? (area.x || 0) : 0;
const top = area ? (area.y || 0) : 0;
eventBus.emit(EVENT_TYPES.AREA_DRAG_END, {
dragId: event.dragId,
areaId: areaId,
finalPosition: {
x: left,
y: top
},
left: left,
top: top
});
}
}; };
// 其他事件处理方法 // 其他事件处理方法
@@ -285,9 +400,12 @@ const setupEventListeners = () => {
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_TOGGLE_COLLAPSE, () => emit('toggleCollapse'), { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_TOGGLE_COLLAPSE, () => emit('toggleCollapse'), { componentId: 'dock-layout' }));
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_MAXIMIZE, onMaximize, { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_MAXIMIZE, onMaximize, { componentId: 'dock-layout' }));
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_CLOSE_REQUEST, onCloseFloatingArea, { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_CLOSE_REQUEST, onCloseFloatingArea, { componentId: 'dock-layout' }));
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_CLOSE, onClosePanel, { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_CLOSE, onPanelClose, { componentId: 'dock-layout' }));
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_TOGGLE_TOOLBAR, () => emit('toggleToolbar'), { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_TOGGLE_TOOLBAR, () => emit('toggleToolbar'), { componentId: 'dock-layout' }));
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_MAXIMIZE_SYNC, onPanelMaximizeSync, { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_MAXIMIZE_SYNC, onPanelMaximizeSync, { componentId: 'dock-layout' }));
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_DRAG_START, onPanelDragStart, { componentId: 'dock-layout' }));
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_DRAG_MOVE, onPanelDragMove, { componentId: 'dock-layout' }));
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.PANEL_DRAG_END, onPanelDragEnd, { componentId: 'dock-layout' }));
// Resize相关事件 // Resize相关事件
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.RESIZE_START, () => emit('dragStart'), { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.RESIZE_START, () => emit('dragStart'), { componentId: 'dock-layout' }));
@@ -300,8 +418,8 @@ const setupEventListeners = () => {
}, { componentId: 'dock-layout' })); }, { componentId: 'dock-layout' }));
// 自定义事件 // 自定义事件
unsubscribeFunctions.push(eventBus.on('area-merged', onAreaMerged, { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.AREA_MERGED, onAreaMerged, { componentId: 'dock-layout' }));
unsubscribeFunctions.push(eventBus.on('dock-zone-active', (event) => onDockZoneActive(event.zoneId), { componentId: 'dock-layout' })); unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.DOCK_ZONE_ACTIVE, (event) => onDockZoneActive(event.zoneId), { componentId: 'dock-layout' }));
return unsubscribeFunctions; return unsubscribeFunctions;
}; };
@@ -314,6 +432,11 @@ const cleanup = () => {
// 清理事件监听器和其他资源 // 清理事件监听器和其他资源
console.log('🧹 开始清理DockLayout资源'); console.log('🧹 开始清理DockLayout资源');
// 清理事件监听器
console.log('🔇 开始清理事件监听器');
unsubscribeFunctions.value.forEach(unsubscribe => unsubscribe());
unsubscribeFunctions.value = [];
// 清理浮动区域 // 清理浮动区域
floatingAreas.value = []; floatingAreas.value = [];

View File

@@ -168,11 +168,9 @@ const props = defineProps({
// 事件订阅管理 - 使用Set避免key冲突并添加唯一标识符 // 事件订阅管理 - 使用Set避免key冲突并添加唯一标识符
const subscriptions = new Set(); const subscriptions = new Set();
const subscriptionRegistry = new Map(); // 用于追踪订阅详细信息 const subscriptionRegistry = new Map();
// 动态获取当前面板所在的Area ID
const getCurrentAreaId = () => { const getCurrentAreaId = () => {
// 通过DOM向上查找最近的Area容器
const panelElement = document.querySelector(`[data-panel-id="${props.id}"]`); const panelElement = document.querySelector(`[data-panel-id="${props.id}"]`);
if (panelElement) { if (panelElement) {
const areaElement = panelElement.closest('[data-area-id]'); const areaElement = panelElement.closest('[data-area-id]');
@@ -181,8 +179,6 @@ const getCurrentAreaId = () => {
} }
} }
// 备用方法:通过父组件查找
// 向上查找vs-area容器
const parentElement = document.querySelector(`[data-panel-id="${props.id}"]`)?.parentElement; const parentElement = document.querySelector(`[data-panel-id="${props.id}"]`)?.parentElement;
if (parentElement) { if (parentElement) {
const areaElement = parentElement.closest('.vs-area'); const areaElement = parentElement.closest('.vs-area');
@@ -399,7 +395,6 @@ const onDragStart = (e) => {
const areaId = getCurrentAreaId(); const areaId = getCurrentAreaId();
// 2. 使用事件总线触发面板拖拽开始事件,包含统一的 dragId 和标准化数据格式
emitEvent(EVENT_TYPES.PANEL_DRAG_START, { emitEvent(EVENT_TYPES.PANEL_DRAG_START, {
dragId: currentDragId, dragId: currentDragId,
panelId: props.id, panelId: props.id,
@@ -410,27 +405,9 @@ const onDragStart = (e) => {
source: { component: 'Panel', panelId: props.id, dragId: currentDragId } source: { component: 'Panel', panelId: props.id, dragId: currentDragId }
}) })
// 3. 同时触发Area拖拽开始事件实现通过Panel标题栏拖拽Area
emitEvent(EVENT_TYPES.AREA_DRAG_START, {
dragId: currentDragId,
areaId: areaId,
event: e,
element: null,
position: { x: e.clientX, y: e.clientY },
clientX: e.clientX,
clientY: e.clientY,
startLeft: 0,
startTop: 0,
timestamp: Date.now()
}, {
source: { component: 'Panel', panelId: props.id, dragId: currentDragId }
})
// 4. 防止文本选择和默认行为
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
// 5. 添加Document事件监听器使用一次性变量避免内存泄漏
addDocumentDragListeners() addDocumentDragListeners()
} }
}; };
@@ -444,7 +421,6 @@ const onDragMove = (e) => {
const areaId = getCurrentAreaId(); const areaId = getCurrentAreaId();
// 1. 使用事件总线触发面板拖拽移动事件,包含 dragId
emitEvent(EVENT_TYPES.PANEL_DRAG_MOVE, { emitEvent(EVENT_TYPES.PANEL_DRAG_MOVE, {
dragId: currentDragId, dragId: currentDragId,
panelId: props.id, panelId: props.id,
@@ -454,23 +430,9 @@ const onDragMove = (e) => {
}, { }, {
source: { component: 'Panel', panelId: props.id, dragId: currentDragId } source: { component: 'Panel', panelId: props.id, dragId: currentDragId }
}) })
// 2. 同时触发Area拖拽移动事件实现通过Panel标题栏拖拽Area
emitEvent(EVENT_TYPES.AREA_DRAG_MOVE, {
dragId: currentDragId,
areaId: areaId,
event: e,
position: { x: e.clientX, y: e.clientY },
clientX: e.clientX,
clientY: e.clientY,
timestamp: Date.now()
}, {
source: { component: 'Panel', panelId: props.id, dragId: currentDragId }
})
} }
}; };
// 拖拽结束
const onDragEnd = () => { const onDragEnd = () => {
if (isDragging && currentDragId) { if (isDragging && currentDragId) {
isDragging = false; isDragging = false;
@@ -479,7 +441,6 @@ const onDragEnd = () => {
const areaId = getCurrentAreaId(); const areaId = getCurrentAreaId();
// 1. 使用事件总线触发面板拖拽结束事件,包含 dragId
emitEvent(EVENT_TYPES.PANEL_DRAG_END, { emitEvent(EVENT_TYPES.PANEL_DRAG_END, {
dragId: currentDragId, dragId: currentDragId,
panelId: props.id, panelId: props.id,
@@ -489,22 +450,8 @@ const onDragEnd = () => {
source: { component: 'Panel', panelId: props.id, dragId: currentDragId } source: { component: 'Panel', panelId: props.id, dragId: currentDragId }
}) })
// 2. 同时触发Area拖拽结束事件实现通过Panel标题栏拖拽Area currentDragId = null;
emitEvent(EVENT_TYPES.AREA_DRAG_END, { cleanupDragEventListeners();
dragId: currentDragId,
areaId: areaId,
event: null,
position: null,
timestamp: Date.now()
}, {
source: { component: 'Panel', panelId: props.id, dragId: currentDragId }
})
// 3. 使用统一的清理方法,确保一致性和完整性
cleanupDragEventListeners()
// 4. 重置 dragId
currentDragId = null
} }
}; };
@@ -652,7 +599,7 @@ onUnmounted(() => {
try { try {
// 1. 立即设置标志位,防止新的异步操作 // 1. 立即设置标志位,防止新的异步操作
isDragging = false isDragging.value = false
// 2. 同步清理所有可以直接清理的资源 // 2. 同步清理所有可以直接清理的资源
const cleanupResult = cleanupEventListeners() const cleanupResult = cleanupEventListeners()
@@ -662,24 +609,12 @@ onUnmounted(() => {
console.log(`[Panel:${props.id}] 组件清理结果:`, cleanupResult) console.log(`[Panel:${props.id}] 组件清理结果:`, cleanupResult)
} }
// 4. 清理超时保护 - 简化版本,防止无限等待
const cleanupTimeout = setTimeout(() => {
console.warn(`[Panel:${props.id}] 清理超时,但继续卸载`)
}, 200) // 缩短超时时间
// 5. 清理超时定时器,确保不会泄露
setTimeout(() => {
clearTimeout(cleanupTimeout)
}, 250)
} catch (error) { } catch (error) {
console.error(`[Panel:${props.id}] 清理过程中出现异常:`, error) console.error(`[Panel:${props.id}] 清理过程中出现异常:`, error)
// 即使出现异常,也要尝试强制清理 // 即使出现异常,也要尝试强制清理
try { try {
isDragging = false isDragging.value = false
// 强制清理事件监听器
cleanupEventListeners()
} catch (forceError) { } catch (forceError) {
console.error(`[Panel:${props.id}] 强制清理也失败:`, forceError) console.error(`[Panel:${props.id}] 强制清理也失败:`, forceError)
} }

View File

@@ -74,7 +74,8 @@ const componentProps = computed(() => {
showTitleBar: config.showTitleBar !== false, showTitleBar: config.showTitleBar !== false,
left: config.left, left: config.left,
top: config.top, top: config.top,
draggable: config.draggable !== false draggable: config.draggable !== false,
children: config.children
} }
case 'TabPage': case 'TabPage':
@@ -82,7 +83,8 @@ const componentProps = computed(() => {
id: config.id, id: config.id,
title: config.title || '标签页', title: config.title || '标签页',
showTabs: config.showTabs !== false, showTabs: config.showTabs !== false,
tabPosition: config.tabPosition || 'top' tabPosition: config.tabPosition || 'top',
children: config.children
} }
case 'Panel': case 'Panel':
@@ -125,7 +127,7 @@ const componentListeners = computed(() => {
} }
allListeners['area-merged'] = (event) => { allListeners['area-merged'] = (event) => {
// if (props.debug) console.log(`[Render-Area ${props.config.id}] area-merged:`, event) // if (props.debug) console.log(`[Render-Area ${props.config.id}] area-merged:`, event)
eventBus.emit('area-merged', { ...event, areaId: props.config.id }) eventBus.emit(EVENT_TYPES.AREA_MERGED, { ...event, areaId: props.config.id })
} }
allListeners['toggleCollapse'] = (event) => { allListeners['toggleCollapse'] = (event) => {
// if (props.debug) console.log(`[Render-Area ${props.config.id}] toggleCollapse:`, event) // if (props.debug) console.log(`[Render-Area ${props.config.id}] toggleCollapse:`, event)

View File

@@ -33,13 +33,6 @@ const props = withDefaults(defineProps<Props>(), {
resizeStep: 10 resizeStep: 10
}) })
// 事件定义
interface Emits {
resize: [newSize: number]
resizeStart: []
resizeEnd: []
}
// 使用事件总线替代直接emit // 使用事件总线替代直接emit
// 响应式状态 // 响应式状态
@@ -167,6 +160,10 @@ defineExpose({
background-color: rgba(64, 158, 255, 0.1); background-color: rgba(64, 158, 255, 0.1);
} }
.resize-bar-hover {
background-color: rgba(64, 158, 255, 0.1);
}
.resize-bar-horizontal { .resize-bar-horizontal {
cursor: col-resize; cursor: col-resize;
border-left: 1px solid transparent; border-left: 1px solid transparent;
@@ -205,6 +202,10 @@ defineExpose({
background-color: rgba(64, 158, 255, 0.6); background-color: rgba(64, 158, 255, 0.6);
} }
.resize-bar-hover .resize-bar-line {
background-color: rgba(64, 158, 255, 0.6);
}
.resize-bar:active .resize-bar-line { .resize-bar:active .resize-bar-line {
background-color: var(--dock-primary-color, #409eff); background-color: var(--dock-primary-color, #409eff);
} }

View File

@@ -149,6 +149,11 @@ const props = defineProps({
type: String, type: String,
default: 'top', default: 'top',
validator: (value) => ['top', 'right', 'bottom', 'left'].includes(value) validator: (value) => ['top', 'right', 'bottom', 'left'].includes(value)
},
// 子组件配置,支持数组或单个对象
children: {
type: [Array, Object],
default: null
} }
}) })

View File

@@ -52,9 +52,56 @@ export const EVENT_TYPES = {
AREA_DRAG_START: 'area.drag.start', AREA_DRAG_START: 'area.drag.start',
AREA_DRAG_MOVE: 'area.drag.move', AREA_DRAG_MOVE: 'area.drag.move',
AREA_DRAG_END: 'area.drag.end', AREA_DRAG_END: 'area.drag.end',
AREA_DRAG_CANCEL: 'area.drag.cancel',
AREA_DRAG_OVER: 'area.drag.over', AREA_DRAG_OVER: 'area.drag.over',
AREA_DRAG_LEAVE: 'area.drag.leave', AREA_DRAG_LEAVE: 'area.drag.leave',
AREA_PANEL_CLOSED: 'area.panel.closed', AREA_PANEL_CLOSED: 'area.panel.closed',
AREA_MERGE_REQUEST: 'area.merge.request',
AREA_MERGED: 'area.merged',
// 基础事件
AREA_CREATED: 'area.created',
AREA_DESTROYED: 'area.destroyed',
AREA_UPDATED: 'area.updated',
AREA_ERROR: 'area.error',
// 浮动区域管理
AREA_FLOATING_CREATE: 'area.floating.create',
AREA_FLOATING_CLOSE: 'area.floating.close',
AREA_FLOATING_UPDATE_POSITION: 'area.floating.updatePosition',
AREA_FLOATING_ZINDEX_CHANGE: 'area.floating.zindex.change',
// Area操作
AREA_MAXIMIZE: 'area.maximize',
AREA_RESTORE: 'area.restore',
AREA_COLLAPSE: 'area.collapse',
AREA_EXPAND: 'area.expand',
AREA_TOGGLE_TOOLBAR: 'area.toggleToolbar',
// 停靠相关
AREA_DOCK_CENTER: 'area.dock.center',
AREA_DOCK_EDGE: 'area.dock.edge',
AREA_DOCK_SPLIT: 'area.dock.split',
AREA_MERGE: 'area.merge',
AREA_UNMERGE: 'area.unmerge',
// 调整大小
AREA_RESIZE_START: 'area.resize.start',
AREA_RESIZE: 'area.resize',
AREA_RESIZE_END: 'area.resize.end',
AREA_RATIO_CHANGE: 'area.ratio.change',
AREA_HIDE: 'area.hide',
AREA_SHOW: 'area.show',
AREA_MINIMIZE: 'area.minimize',
AREA_RESTORE_FROM_MINIMIZE: 'area.restoreFromMinimize',
AREA_ZINDEX_MANAGEMENT: 'area.zindex.management',
AREA_ACTIVATION: 'area.activation',
AREA_DEACTIVATION: 'area.deactivation',
AREA_CONTENT_CHANGE: 'area.content.change',
AREA_PANEL_COUNT_CHANGE: 'area.panel.count.change',
AREA_TABPAGE_MERGE: 'area.tabpage.merge',
AREA_TABPAGE_SYNC: 'area.tabpage.sync',
AREA_PANEL_SYNC: 'area.panel.sync',
PANEL_MAXIMIZE_SYNC: 'panel.maximize.sync', PANEL_MAXIMIZE_SYNC: 'panel.maximize.sync',
PANEL_MAXIMIZE: 'panel.maximize', PANEL_MAXIMIZE: 'panel.maximize',
@@ -67,6 +114,7 @@ export const EVENT_TYPES = {
PANEL_DRAG_START: 'panel.drag.start', PANEL_DRAG_START: 'panel.drag.start',
PANEL_DRAG_MOVE: 'panel.drag.move', PANEL_DRAG_MOVE: 'panel.drag.move',
PANEL_DRAG_END: 'panel.drag.end', PANEL_DRAG_END: 'panel.drag.end',
PANEL_DRAG_CANCEL: 'panel.drag.cancel',
PANEL_DRAG_START_FROM_TABPAGE: 'panel.drag.start.fromTabPage', PANEL_DRAG_START_FROM_TABPAGE: 'panel.drag.start.fromTabPage',
PANEL_DRAG_MOVE_FROM_TABPAGE: 'panel.drag.move.fromTabPage', PANEL_DRAG_MOVE_FROM_TABPAGE: 'panel.drag.move.fromTabPage',
PANEL_DRAG_END_FROM_TABPAGE: 'panel.drag.end.fromTabPage', PANEL_DRAG_END_FROM_TABPAGE: 'panel.drag.end.fromTabPage',
@@ -78,6 +126,12 @@ export const EVENT_TYPES = {
TAB_DRAG_MOVE: 'tab.drag.move', TAB_DRAG_MOVE: 'tab.drag.move',
TAB_DRAG_END: 'tab.drag.end', TAB_DRAG_END: 'tab.drag.end',
// 标签页拖拽事件
TABPAGE_DRAG_START: 'tabpage.drag.start',
TABPAGE_DRAG_MOVE: 'tabpage.drag.move',
TABPAGE_DRAG_END: 'tabpage.drag.end',
TABPAGE_DRAG_CANCEL: 'tabpage.drag.cancel',
INDICATOR_SHOW: 'indicator.show', INDICATOR_SHOW: 'indicator.show',
INDICATOR_HIDE: 'indicator.hide', INDICATOR_HIDE: 'indicator.hide',
INDICATOR_UPDATE: 'indicator.update', INDICATOR_UPDATE: 'indicator.update',
@@ -87,7 +141,10 @@ export const EVENT_TYPES = {
RESIZE_END: 'resize.end', RESIZE_END: 'resize.end',
WINDOW_STATE_CHANGE: 'window.state.change', WINDOW_STATE_CHANGE: 'window.state.change',
Z_INDEX_UPDATE: 'zIndex.update' Z_INDEX_UPDATE: 'zIndex.update',
// Dock相关事件
DOCK_ZONE_ACTIVE: 'dock.zone.active'
} }
export const PRIORITY_LEVELS = { export const PRIORITY_LEVELS = {
@@ -278,6 +335,11 @@ class EnhancedEventBus {
retries = 0 retries = 0
} = options } = options
const definedEventTypes = Object.values(EVENT_TYPES)
if (!definedEventTypes.includes(eventType)) {
console.warn(`⚠️ [EventBus] 未定义的事件类型: "${eventType}"。请在 EVENT_TYPES 中定义此事件类型。`)
}
const wrappedHandler = async (event) => { const wrappedHandler = async (event) => {
const startTime = performance.now() const startTime = performance.now()

View File

@@ -5,60 +5,6 @@
import { eventBus, EVENT_TYPES } from '../eventBus'; import { eventBus, EVENT_TYPES } from '../eventBus';
// Area事件类型常量仅包含EVENT_TYPES中没有的
export const AREA_EVENT_TYPES = {
// 基础事件
AREA_CREATED: 'area.created',
AREA_DESTROYED: 'area.destroyed',
AREA_UPDATED: 'area.updated',
// 浮动区域管理
AREA_FLOATING_CREATE: 'area.floating.create',
AREA_FLOATING_CLOSE: 'area.floating.close',
AREA_FLOATING_UPDATE_POSITION: 'area.floating.updatePosition',
AREA_FLOATING_ZINDEX_CHANGE: 'area.floating.zindex.change',
// Area操作
AREA_MAXIMIZE: 'area.maximize',
AREA_RESTORE: 'area.restore',
AREA_COLLAPSE: 'area.collapse',
AREA_EXPAND: 'area.expand',
AREA_TOGGLE_TOOLBAR: 'area.toggleToolbar',
// 停靠相关
AREA_DOCK_CENTER: 'area.dock.center',
AREA_DOCK_EDGE: 'area.dock.edge',
AREA_DOCK_SPLIT: 'area.dock.split',
AREA_MERGE: 'area.merge',
AREA_UNMERGE: 'area.unmerge',
// 调整大小
AREA_RESIZE_START: 'area.resize.start',
AREA_RESIZE: 'area.resize',
AREA_RESIZE_END: 'area.resize.end',
AREA_RATIO_CHANGE: 'area.ratio.change',
// 隐藏/显示
AREA_HIDE: 'area.hide',
AREA_SHOW: 'area.show',
AREA_MINIMIZE: 'area.minimize',
AREA_RESTORE_FROM_MINIMIZE: 'area.restoreFromMinimize',
// 层级管理
AREA_ZINDEX_MANAGEMENT: 'area.zindex.management',
AREA_ACTIVATION: 'area.activation',
AREA_DEACTIVATION: 'area.deactivation',
// 内容管理
AREA_CONTENT_CHANGE: 'area.content.change',
AREA_PANEL_COUNT_CHANGE: 'area.panel.count.change',
AREA_TABPAGE_MERGE: 'area.tabpage.merge',
// 与其他组件的交互
AREA_TABPAGE_SYNC: 'area.tabpage.sync',
AREA_PANEL_SYNC: 'area.panel.sync'
};
// Area状态管理 // Area状态管理
class AreaStateManager { class AreaStateManager {
constructor() { constructor() {
@@ -96,7 +42,7 @@ class AreaStateManager {
this.states.set(areaId, newState); this.states.set(areaId, newState);
// 触发状态更新事件 // 触发状态更新事件
eventBus.emit(AREA_EVENT_TYPES.AREA_UPDATED, { eventBus.emit(EVENT_TYPES.AREA_UPDATED, {
areaId, areaId,
oldState: currentState, oldState: currentState,
newState, newState,
@@ -132,7 +78,7 @@ class AreaStateManager {
this.states.set(areaId, floatingArea); this.states.set(areaId, floatingArea);
// 触发创建事件 // 触发创建事件
eventBus.emit(AREA_EVENT_TYPES.AREA_FLOATING_CREATE, { eventBus.emit(EVENT_TYPES.AREA_FLOATING_CREATE, {
areaId, areaId,
config: floatingArea, config: floatingArea,
timestamp: Date.now() timestamp: Date.now()
@@ -154,7 +100,7 @@ class AreaStateManager {
this.states.delete(areaId); this.states.delete(areaId);
// 触发关闭事件 // 触发关闭事件
eventBus.emit(AREA_EVENT_TYPES.AREA_FLOATING_CLOSE, { eventBus.emit(EVENT_TYPES.AREA_FLOATING_CLOSE, {
areaId, areaId,
config: area, config: area,
timestamp: Date.now() timestamp: Date.now()
@@ -183,7 +129,7 @@ class AreaStateManager {
this.states.set(areaId, updatedArea); this.states.set(areaId, updatedArea);
// 触发位置更新事件 // 触发位置更新事件
eventBus.emit(AREA_EVENT_TYPES.AREA_FLOATING_UPDATE_POSITION, { eventBus.emit(EVENT_TYPES.AREA_FLOATING_UPDATE_POSITION, {
areaId, areaId,
position: { position: {
left: updatedArea.x, left: updatedArea.x,
@@ -207,7 +153,7 @@ class AreaStateManager {
hiddenAt: Date.now() hiddenAt: Date.now()
}); });
eventBus.emit(AREA_EVENT_TYPES.AREA_HIDE, { eventBus.emit(EVENT_TYPES.AREA_HIDE, {
areaId, areaId,
reason: 'hidden_list', reason: 'hidden_list',
timestamp: Date.now() timestamp: Date.now()
@@ -226,7 +172,7 @@ class AreaStateManager {
restoredAt: Date.now() restoredAt: Date.now()
}); });
eventBus.emit(AREA_EVENT_TYPES.AREA_SHOW, { eventBus.emit(EVENT_TYPES.AREA_SHOW, {
areaId, areaId,
reason: 'restored_from_hidden', reason: 'restored_from_hidden',
timestamp: Date.now() timestamp: Date.now()
@@ -409,7 +355,7 @@ class AreaEventHandler {
const areaId = this.areaStateManager.createFloatingArea(areaConfig); const areaId = this.areaStateManager.createFloatingArea(areaConfig);
// 触发成功事件 // 触发成功事件
eventBus.emit(AREA_EVENT_TYPES.AREA_CREATED, { eventBus.emit(EVENT_TYPES.AREA_CREATED, {
areaId, areaId,
config: areaConfig, config: areaConfig,
source: 'addFloatingPanel', source: 'addFloatingPanel',
@@ -419,7 +365,7 @@ class AreaEventHandler {
return areaId; return areaId;
} catch (error) { } catch (error) {
console.error('创建浮动Area时出错:', error); console.error('创建浮动Area时出错:', error);
eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { eventBus.emit(EVENT_TYPES.AREA_ERROR, {
operation: 'addFloatingPanel', operation: 'addFloatingPanel',
error: error.message, error: error.message,
timestamp: Date.now() timestamp: Date.now()
@@ -442,7 +388,7 @@ class AreaEventHandler {
} }
// 触发关闭开始事件 // 触发关闭开始事件
eventBus.emit(AREA_EVENT_TYPES.AREA_CLOSE, { eventBus.emit(EVENT_TYPES.AREA_CLOSE, {
areaId, areaId,
config: area, config: area,
source: 'closeFloatingArea', source: 'closeFloatingArea',
@@ -459,7 +405,7 @@ class AreaEventHandler {
this.areaStateManager.clearResizeState(areaId); this.areaStateManager.clearResizeState(areaId);
// 触发关闭完成事件 // 触发关闭完成事件
eventBus.emit(AREA_EVENT_TYPES.AREA_DESTROYED, { eventBus.emit(EVENT_TYPES.AREA_DESTROYED, {
areaId, areaId,
source: 'closeFloatingArea', source: 'closeFloatingArea',
timestamp: Date.now() timestamp: Date.now()
@@ -469,7 +415,7 @@ class AreaEventHandler {
return success; return success;
} catch (error) { } catch (error) {
console.error('关闭浮动Area时出错:', error); console.error('关闭浮动Area时出错:', error);
eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { eventBus.emit(EVENT_TYPES.AREA_ERROR, {
areaId, areaId,
operation: 'closeFloatingArea', operation: 'closeFloatingArea',
error: error.message, error: error.message,
@@ -519,7 +465,7 @@ class AreaEventHandler {
} }
// 触发合并完成事件 // 触发合并完成事件
eventBus.emit(AREA_EVENT_TYPES.AREA_MERGE, { eventBus.emit(EVENT_TYPES.AREA_MERGE, {
sourceAreaId: sourceArea.id, sourceAreaId: sourceArea.id,
targetAreaHasContent, targetAreaHasContent,
timestamp: Date.now() timestamp: Date.now()
@@ -527,7 +473,7 @@ class AreaEventHandler {
} catch (error) { } catch (error) {
console.error('处理Area合并事件时出错:', error); console.error('处理Area合并事件时出错:', error);
eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { eventBus.emit(EVENT_TYPES.AREA_ERROR, {
operation: 'onAreaMerged', operation: 'onAreaMerged',
eventData, eventData,
error: error.message, error: error.message,
@@ -556,7 +502,7 @@ class AreaEventHandler {
}); });
// 触发折叠/展开事件 // 触发折叠/展开事件
eventBus.emit(newCollapsedState ? AREA_EVENT_TYPES.AREA_COLLAPSE : AREA_EVENT_TYPES.AREA_EXPAND, { eventBus.emit(newCollapsedState ? EVENT_TYPES.AREA_COLLAPSE : EVENT_TYPES.AREA_EXPAND, {
areaId, areaId,
collapsed: newCollapsedState, collapsed: newCollapsedState,
timestamp: Date.now() timestamp: Date.now()
@@ -565,7 +511,7 @@ class AreaEventHandler {
return true; return true;
} catch (error) { } catch (error) {
console.error('切换Area折叠状态时出错:', error); console.error('切换Area折叠状态时出错:', error);
eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { eventBus.emit(EVENT_TYPES.AREA_ERROR, {
areaId, areaId,
operation: 'toggleCollapse', operation: 'toggleCollapse',
error: error.message, error: error.message,
@@ -595,16 +541,16 @@ class AreaEventHandler {
}); });
// 触发工具栏切换事件 // 触发工具栏切换事件
eventBus.emit(AREA_EVENT_TYPES.AREA_TOGGLE_TOOLBAR, { eventBus.emit(EVENT_TYPES.AREA_TOGGLE_TOOLBAR, {
areaId, areaId,
expanded: newToolbarState, expanded: toolbarExpanded,
timestamp: Date.now() timestamp: Date.now()
}); });
return true; return true;
} catch (error) { } catch (error) {
console.error('切换Area工具栏状态时出错:', error); console.error('切换Area工具栏状态时出错:', error);
eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { eventBus.emit(EVENT_TYPES.AREA_ERROR, {
areaId, areaId,
operation: 'toggleToolbar', operation: 'toggleToolbar',
error: error.message, error: error.message,
@@ -637,7 +583,7 @@ class AreaEventHandler {
}); });
// 触发最大化/还原事件 // 触发最大化/还原事件
eventBus.emit(isCurrentlyMaximized ? AREA_EVENT_TYPES.AREA_RESTORE : AREA_EVENT_TYPES.AREA_MAXIMIZE, { eventBus.emit(isCurrentlyMaximized ? EVENT_TYPES.AREA_RESTORE : EVENT_TYPES.AREA_MAXIMIZE, {
areaId, areaId,
windowState: newWindowState, windowState: newWindowState,
timestamp: Date.now() timestamp: Date.now()
@@ -651,7 +597,7 @@ class AreaEventHandler {
return true; return true;
} catch (error) { } catch (error) {
console.error('切换Area最大化状态时出错:', error); console.error('切换Area最大化状态时出错:', error);
eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { eventBus.emit(EVENT_TYPES.AREA_ERROR, {
areaId, areaId,
operation: 'toggleMaximize', operation: 'toggleMaximize',
error: error.message, error: error.message,
@@ -677,14 +623,14 @@ class AreaEventHandler {
}); });
// 触发激活事件 // 触发激活事件
eventBus.emit(AREA_EVENT_TYPES.AREA_ACTIVATION, { eventBus.emit(EVENT_TYPES.AREA_ACTIVATION, {
areaId, areaId,
timestamp: Date.now() timestamp: Date.now()
}); });
} catch (error) { } catch (error) {
console.error('激活Area时出错:', error); console.error('激活Area时出错:', error);
eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { eventBus.emit(EVENT_TYPES.AREA_ERROR, {
areaId, areaId,
operation: 'activateArea', operation: 'activateArea',
error: error.message, error: error.message,
@@ -736,7 +682,7 @@ class AreaEventHandler {
_storeHiddenAreaTabPages(areaId, tabPages) { _storeHiddenAreaTabPages(areaId, tabPages) {
try { try {
// 将TabPage信息存储到历史记录中 // 将TabPage信息存储到历史记录中
eventBus.emit(AREA_EVENT_TYPES.AREA_HIDE, { eventBus.emit(EVENT_TYPES.AREA_HIDE, {
areaId, areaId,
reason: 'merge_with_content', reason: 'merge_with_content',
tabPages: [...tabPages], tabPages: [...tabPages],
@@ -773,8 +719,42 @@ class AreaEventHandler {
this.areaListeners.set(eventType, listener); this.areaListeners.set(eventType, listener);
}); });
// 监听 AREA_EVENT_TYPES 中的事件 // 监听 Area相关事件
const areaEventTypes = Object.values(AREA_EVENT_TYPES); const areaEventTypes = [
EVENT_TYPES.AREA_CREATED,
EVENT_TYPES.AREA_DESTROYED,
EVENT_TYPES.AREA_UPDATED,
EVENT_TYPES.AREA_FLOATING_CREATE,
EVENT_TYPES.AREA_FLOATING_CLOSE,
EVENT_TYPES.AREA_FLOATING_UPDATE_POSITION,
EVENT_TYPES.AREA_FLOATING_ZINDEX_CHANGE,
EVENT_TYPES.AREA_MAXIMIZE,
EVENT_TYPES.AREA_RESTORE,
EVENT_TYPES.AREA_COLLAPSE,
EVENT_TYPES.AREA_EXPAND,
EVENT_TYPES.AREA_TOGGLE_TOOLBAR,
EVENT_TYPES.AREA_DOCK_CENTER,
EVENT_TYPES.AREA_DOCK_EDGE,
EVENT_TYPES.AREA_DOCK_SPLIT,
EVENT_TYPES.AREA_MERGE,
EVENT_TYPES.AREA_UNMERGE,
EVENT_TYPES.AREA_RESIZE_START,
EVENT_TYPES.AREA_RESIZE,
EVENT_TYPES.AREA_RESIZE_END,
EVENT_TYPES.AREA_RATIO_CHANGE,
EVENT_TYPES.AREA_HIDE,
EVENT_TYPES.AREA_SHOW,
EVENT_TYPES.AREA_MINIMIZE,
EVENT_TYPES.AREA_RESTORE_FROM_MINIMIZE,
EVENT_TYPES.AREA_ZINDEX_MANAGEMENT,
EVENT_TYPES.AREA_ACTIVATION,
EVENT_TYPES.AREA_DEACTIVATION,
EVENT_TYPES.AREA_CONTENT_CHANGE,
EVENT_TYPES.AREA_PANEL_COUNT_CHANGE,
EVENT_TYPES.AREA_TABPAGE_MERGE,
EVENT_TYPES.AREA_TABPAGE_SYNC,
EVENT_TYPES.AREA_PANEL_SYNC
];
areaEventTypes.forEach(eventType => { areaEventTypes.forEach(eventType => {
const listener = this._onAreaEvent; const listener = this._onAreaEvent;
eventBus.on(eventType, listener, { eventBus.on(eventType, listener, {
@@ -804,25 +784,25 @@ class AreaEventHandler {
case EVENT_TYPES.AREA_DRAG_END: case EVENT_TYPES.AREA_DRAG_END:
await this._handleAreaDragEnd(data); await this._handleAreaDragEnd(data);
break; break;
case AREA_EVENT_TYPES.AREA_DOCK_CENTER: case EVENT_TYPES.AREA_DOCK_CENTER:
await this._handleAreaDockCenter(data); await this._handleAreaDockCenter(data);
break; break;
case AREA_EVENT_TYPES.AREA_MERGE: case EVENT_TYPES.AREA_MERGE:
await this._handleAreaMerge(data); await this._handleAreaMerge(data);
break; break;
case AREA_EVENT_TYPES.AREA_RESIZE_START: case EVENT_TYPES.AREA_RESIZE_START:
await this._handleAreaResizeStart(data); await this._handleAreaResizeStart(data);
break; break;
case AREA_EVENT_TYPES.AREA_RESIZE: case EVENT_TYPES.AREA_RESIZE:
await this._handleAreaResize(data); await this._handleAreaResize(data);
break; break;
case AREA_EVENT_TYPES.AREA_RESIZE_END: case EVENT_TYPES.AREA_RESIZE_END:
await this._handleAreaResizeEnd(data); await this._handleAreaResizeEnd(data);
break; break;
case AREA_EVENT_TYPES.AREA_FLOATING_CREATE: case EVENT_TYPES.AREA_FLOATING_CREATE:
await this._handleFloatingAreaCreate(data); await this._handleFloatingAreaCreate(data);
break; break;
case AREA_EVENT_TYPES.AREA_ZINDEX_MANAGEMENT: case EVENT_TYPES.AREA_ZINDEX_MANAGEMENT:
await this._handleAreaZIndexManagement(data); await this._handleAreaZIndexManagement(data);
break; break;
default: default:
@@ -854,7 +834,7 @@ class AreaEventHandler {
this.activeAreas.add(areaId); this.activeAreas.add(areaId);
// 触发层级管理 // 触发层级管理
eventBus.emit(AREA_EVENT_TYPES.AREA_ZINDEX_MANAGEMENT, { eventBus.emit(EVENT_TYPES.AREA_ZINDEX_MANAGEMENT, {
areaId, areaId,
action: 'activate', action: 'activate',
reason: 'drag_start' reason: 'drag_start'
@@ -889,7 +869,7 @@ class AreaEventHandler {
} }
// 触发拖拽移动事件 // 触发拖拽移动事件
eventBus.emit(AREA_EVENT_TYPES.AREA_DRAG_MOVE, { eventBus.emit(EVENT_TYPES.AREA_DRAG_MOVE, {
areaId, areaId,
delta: { x: deltaX, y: deltaY }, delta: { x: deltaX, y: deltaY },
position: { x: event.clientX, y: event.clientY }, position: { x: event.clientX, y: event.clientY },
@@ -930,7 +910,7 @@ class AreaEventHandler {
dragState.duration = dragDuration; dragState.duration = dragDuration;
// 触发拖拽结束事件 // 触发拖拽结束事件
eventBus.emit(AREA_EVENT_TYPES.AREA_DRAG_END, { eventBus.emit(EVENT_TYPES.AREA_DRAG_END, {
areaId, areaId,
dragInfo: { dragInfo: {
duration: dragDuration, duration: dragDuration,
@@ -959,7 +939,7 @@ class AreaEventHandler {
// 验证停靠条件 // 验证停靠条件
if (!areaState || !areaState.tabPages || areaState.tabPages.length === 0) { if (!areaState || !areaState.tabPages || areaState.tabPages.length === 0) {
eventBus.emit(AREA_EVENT_TYPES.AREA_DOCK_CENTER, { eventBus.emit(EVENT_TYPES.AREA_DOCK_CENTER, {
areaId, areaId,
success: false, success: false,
reason: 'invalid_area_state', reason: 'invalid_area_state',
@@ -979,7 +959,7 @@ class AreaEventHandler {
}; };
// 触发停靠成功事件 // 触发停靠成功事件
eventBus.emit(AREA_EVENT_TYPES.AREA_DOCK_CENTER, dockingResult); eventBus.emit(EVENT_TYPES.AREA_DOCK_CENTER, dockingResult);
// 如果停靠成功,从浮动区域移除 // 如果停靠成功,从浮动区域移除
if (dockingResult.success && areaState.type === 'floating') { if (dockingResult.success && areaState.type === 'floating') {
@@ -1015,7 +995,7 @@ class AreaEventHandler {
}; };
// 触发合并事件 // 触发合并事件
eventBus.emit(AREA_EVENT_TYPES.AREA_MERGE, mergeResult); eventBus.emit(EVENT_TYPES.AREA_MERGE, mergeResult);
// 隐藏源Area保存到隐藏列表 // 隐藏源Area保存到隐藏列表
this.areaStateManager.addToHiddenList(sourceAreaId); this.areaStateManager.addToHiddenList(sourceAreaId);
@@ -1038,7 +1018,7 @@ class AreaEventHandler {
}); });
// 触发调整大小开始事件 // 触发调整大小开始事件
eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE_START, { eventBus.emit(EVENT_TYPES.AREA_RESIZE_START, {
areaId, areaId,
resizeType, resizeType,
direction, direction,
@@ -1072,7 +1052,7 @@ class AreaEventHandler {
} }
// 触发调整大小事件 // 触发调整大小事件
eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE, { eventBus.emit(EVENT_TYPES.AREA_RESIZE, {
areaId, areaId,
size, size,
delta, delta,
@@ -1110,7 +1090,7 @@ class AreaEventHandler {
} }
// 触发调整大小结束事件 // 触发调整大小结束事件
eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE_END, { eventBus.emit(EVENT_TYPES.AREA_RESIZE_END, {
areaId, areaId,
resizeInfo: { resizeInfo: {
duration: resizeDuration, duration: resizeDuration,
@@ -1147,7 +1127,7 @@ class AreaEventHandler {
}); });
// 触发层级管理事件 // 触发层级管理事件
eventBus.emit(AREA_EVENT_TYPES.AREA_ZINDEX_MANAGEMENT, { eventBus.emit(EVENT_TYPES.AREA_ZINDEX_MANAGEMENT, {
areaId, areaId,
action: 'create_floating', action: 'create_floating',
zIndex, zIndex,
@@ -1350,7 +1330,7 @@ export const areaActions = {
* @param {string} source - 拖拽源 * @param {string} source - 拖拽源
*/ */
startDrag: (areaId, event, source = 'direct') => { startDrag: (areaId, event, source = 'direct') => {
eventBus.emit(AREA_EVENT_TYPES.AREA_DRAG_START, { eventBus.emit(EVENT_TYPES.AREA_DRAG_START, {
areaId, areaId,
event, event,
source, source,
@@ -1364,7 +1344,7 @@ export const areaActions = {
* @param {Event} event - 拖拽事件 * @param {Event} event - 拖拽事件
*/ */
moveDrag: (areaId, event) => { moveDrag: (areaId, event) => {
eventBus.emit(AREA_EVENT_TYPES.AREA_DRAG_MOVE, { eventBus.emit(EVENT_TYPES.AREA_DRAG_MOVE, {
areaId, areaId,
event, event,
timestamp: Date.now() timestamp: Date.now()
@@ -1377,7 +1357,7 @@ export const areaActions = {
* @param {Event} event - 拖拽事件 * @param {Event} event - 拖拽事件
*/ */
endDrag: (areaId, event) => { endDrag: (areaId, event) => {
eventBus.emit(AREA_EVENT_TYPES.AREA_DRAG_END, { eventBus.emit(EVENT_TYPES.AREA_DRAG_END, {
areaId, areaId,
event, event,
timestamp: Date.now() timestamp: Date.now()
@@ -1391,7 +1371,7 @@ export const areaActions = {
* @param {string} mergeStrategy - 合并策略 * @param {string} mergeStrategy - 合并策略
*/ */
dockToCenter: (areaId, targetAreaId = 'main', mergeStrategy = 'auto') => { dockToCenter: (areaId, targetAreaId = 'main', mergeStrategy = 'auto') => {
eventBus.emit(AREA_EVENT_TYPES.AREA_DOCK_CENTER, { eventBus.emit(EVENT_TYPES.AREA_DOCK_CENTER, {
areaId, areaId,
targetAreaId, targetAreaId,
mergeStrategy, mergeStrategy,
@@ -1407,7 +1387,7 @@ export const areaActions = {
* @param {Object} mergeOptions - 合并选项 * @param {Object} mergeOptions - 合并选项
*/ */
merge: (sourceAreaId, targetAreaId, mergeType = 'tabPage', mergeOptions = {}) => { merge: (sourceAreaId, targetAreaId, mergeType = 'tabPage', mergeOptions = {}) => {
eventBus.emit(AREA_EVENT_TYPES.AREA_MERGE, { eventBus.emit(EVENT_TYPES.AREA_MERGE, {
sourceAreaId, sourceAreaId,
targetAreaId, targetAreaId,
mergeType, mergeType,
@@ -1424,7 +1404,7 @@ export const areaActions = {
* @param {string} direction - 调整方向 * @param {string} direction - 调整方向
*/ */
startResize: (areaId, originalSize, resizeType = 'split', direction = 'both') => { startResize: (areaId, originalSize, resizeType = 'split', direction = 'both') => {
eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE_START, { eventBus.emit(EVENT_TYPES.AREA_RESIZE_START, {
areaId, areaId,
originalSize, originalSize,
resizeType, resizeType,
@@ -1440,7 +1420,7 @@ export const areaActions = {
* @param {Object} delta - 大小变化 * @param {Object} delta - 大小变化
*/ */
resize: (areaId, size, delta) => { resize: (areaId, size, delta) => {
eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE, { eventBus.emit(EVENT_TYPES.AREA_RESIZE, {
areaId, areaId,
size, size,
delta, delta,
@@ -1454,7 +1434,7 @@ export const areaActions = {
* @param {Object} finalSize - 最终大小 * @param {Object} finalSize - 最终大小
*/ */
endResize: (areaId, finalSize) => { endResize: (areaId, finalSize) => {
eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE_END, { eventBus.emit(EVENT_TYPES.AREA_RESIZE_END, {
areaId, areaId,
finalSize, finalSize,
timestamp: Date.now() timestamp: Date.now()
@@ -1467,7 +1447,7 @@ export const areaActions = {
* @param {Object} options - 选项 * @param {Object} options - 选项
*/ */
maximize: (areaId, options = {}) => { maximize: (areaId, options = {}) => {
eventBus.emit(AREA_EVENT_TYPES.AREA_MAXIMIZE, { eventBus.emit(EVENT_TYPES.AREA_MAXIMIZE, {
areaId, areaId,
...options, ...options,
timestamp: Date.now() timestamp: Date.now()
@@ -1480,7 +1460,7 @@ export const areaActions = {
* @param {Object} options - 选项 * @param {Object} options - 选项
*/ */
restore: (areaId, options = {}) => { restore: (areaId, options = {}) => {
eventBus.emit(AREA_EVENT_TYPES.AREA_RESTORE, { eventBus.emit(EVENT_TYPES.AREA_RESTORE, {
areaId, areaId,
...options, ...options,
timestamp: Date.now() timestamp: Date.now()
@@ -1493,7 +1473,7 @@ export const areaActions = {
* @param {Object} options - 选项 * @param {Object} options - 选项
*/ */
collapse: (areaId, options = {}) => { collapse: (areaId, options = {}) => {
eventBus.emit(AREA_EVENT_TYPES.AREA_COLLAPSE, { eventBus.emit(EVENT_TYPES.AREA_COLLAPSE, {
areaId, areaId,
...options, ...options,
timestamp: Date.now() timestamp: Date.now()
@@ -1506,7 +1486,7 @@ export const areaActions = {
* @param {Object} options - 选项 * @param {Object} options - 选项
*/ */
expand: (areaId, options = {}) => { expand: (areaId, options = {}) => {
eventBus.emit(AREA_EVENT_TYPES.AREA_EXPAND, { eventBus.emit(EVENT_TYPES.AREA_EXPAND, {
areaId, areaId,
...options, ...options,
timestamp: Date.now() timestamp: Date.now()
@@ -1519,7 +1499,7 @@ export const areaActions = {
* @param {Object} options - 选项 * @param {Object} options - 选项
*/ */
close: (areaId, options = {}) => { close: (areaId, options = {}) => {
eventBus.emit(AREA_EVENT_TYPES.AREA_CLOSE, { eventBus.emit(EVENT_TYPES.AREA_CLOSE, {
areaId, areaId,
...options, ...options,
timestamp: Date.now() timestamp: Date.now()
@@ -1532,7 +1512,7 @@ export const areaActions = {
* @param {Object} options - 选项 * @param {Object} options - 选项
*/ */
toggleToolbar: (areaId, options = {}) => { toggleToolbar: (areaId, options = {}) => {
eventBus.emit(AREA_EVENT_TYPES.AREA_TOGGLE_TOOLBAR, { eventBus.emit(EVENT_TYPES.AREA_TOGGLE_TOOLBAR, {
areaId, areaId,
...options, ...options,
timestamp: Date.now() timestamp: Date.now()

View File

@@ -3,7 +3,7 @@
* 统一管理所有组件的拖拽状态,提供拖拽历史、性能监控、冲突检测等功能 * 统一管理所有组件的拖拽状态,提供拖拽历史、性能监控、冲突检测等功能
*/ */
import { eventBus } from '../eventBus'; import { eventBus, EVENT_TYPES } from '../eventBus';
import { GLOBAL_EVENT_TYPES, globalEventActions } from './GlobalEventManager'; import { GLOBAL_EVENT_TYPES, globalEventActions } from './GlobalEventManager';
// 拖拽状态类型 // 拖拽状态类型
@@ -541,11 +541,11 @@ class DragStateManager {
const dragEvents = [ const dragEvents = [
// Panel拖拽事件 // Panel拖拽事件
'panel.drag.start', 'panel.drag.move', 'panel.drag.end', 'panel.drag.cancel', EVENT_TYPES.PANEL_DRAG_START, EVENT_TYPES.PANEL_DRAG_MOVE, EVENT_TYPES.PANEL_DRAG_END, EVENT_TYPES.PANEL_DRAG_CANCEL,
// TabPage拖拽事件 // TabPage拖拽事件
'tabpage.drag.start', 'tabpage.drag.move', 'tabpage.drag.end', 'tabpage.drag.cancel', EVENT_TYPES.TABPAGE_DRAG_START, EVENT_TYPES.TABPAGE_DRAG_MOVE, EVENT_TYPES.TABPAGE_DRAG_END, EVENT_TYPES.TABPAGE_DRAG_CANCEL,
// Area拖拽事件 // Area拖拽事件
'area.drag.start', 'area.drag.move', 'area.drag.end', 'area.drag.cancel' EVENT_TYPES.AREA_DRAG_START, EVENT_TYPES.AREA_DRAG_MOVE, EVENT_TYPES.AREA_DRAG_END, EVENT_TYPES.AREA_DRAG_CANCEL
]; ];
dragEvents.forEach(eventType => { dragEvents.forEach(eventType => {
@@ -570,11 +570,11 @@ class DragStateManager {
// 清理事件监听器 // 清理事件监听器
const dragEvents = [ const dragEvents = [
// Panel拖拽事件 // Panel拖拽事件
'panel.drag.start', 'panel.drag.move', 'panel.drag.end', 'panel.drag.cancel', EVENT_TYPES.PANEL_DRAG_START, EVENT_TYPES.PANEL_DRAG_MOVE, EVENT_TYPES.PANEL_DRAG_END, EVENT_TYPES.PANEL_DRAG_CANCEL,
// TabPage拖拽事件 // TabPage拖拽事件
'tabpage.drag.start', 'tabpage.drag.move', 'tabpage.drag.end', 'tabpage.drag.cancel', EVENT_TYPES.TABPAGE_DRAG_START, EVENT_TYPES.TABPAGE_DRAG_MOVE, EVENT_TYPES.TABPAGE_DRAG_END, EVENT_TYPES.TABPAGE_DRAG_CANCEL,
// Area拖拽事件 // Area拖拽事件
'area.drag.start', 'area.drag.move', 'area.drag.end', 'area.drag.cancel' EVENT_TYPES.AREA_DRAG_START, EVENT_TYPES.AREA_DRAG_MOVE, EVENT_TYPES.AREA_DRAG_END, EVENT_TYPES.AREA_DRAG_CANCEL
]; ];
dragEvents.forEach(eventType => { dragEvents.forEach(eventType => {
@@ -608,22 +608,39 @@ class DragStateManager {
const monitorId = globalEventActions.startMonitor(`drag_${data.eventType}`); const monitorId = globalEventActions.startMonitor(`drag_${data.eventType}`);
try { try {
const { eventType = data.type, dragId, componentType, sourceElement } = data; const { eventType = data.type, dragId, componentType: providedComponentType, sourceElement } = data;
console.log('🔍 _onDragEvent 接收到的数据:', { eventType, dragId, componentType, data }); console.log('🔍 _onDragEvent 接收到的数据:', { eventType, dragId, componentType: providedComponentType, data });
// 推断组件类型 // 改进从事件类型直接推断组件类型优先级高于提供的componentType
let actualComponentType = componentType; let actualComponentType = providedComponentType;
// 1. 优先从eventType推断组件类型最可靠
if (!actualComponentType) { if (!actualComponentType) {
if (data.panelId) { if (eventType.includes('panel.')) {
actualComponentType = 'panel'; actualComponentType = 'panel';
} else if (data.tabIndex !== undefined) { } else if (eventType.includes('tabpage.')) {
actualComponentType = 'tabpage'; actualComponentType = 'tabpage';
} else if (data.areaId) { } else if (eventType.includes('area.')) {
actualComponentType = 'area'; actualComponentType = 'area';
} else {
// 2. 如果事件类型中没有组件类型信息,再根据事件数据推断
if (data.panelId) {
actualComponentType = 'panel';
} else if (data.tabIndex !== undefined || data.tabPageId) {
actualComponentType = 'tabpage';
} else if (data.areaId) {
actualComponentType = 'area';
}
} }
} }
// 3. 确保组件类型有效
if (!actualComponentType) {
console.warn('⚠️ 无法推断组件类型,使用默认值 "panel"', data);
actualComponentType = 'panel';
}
// 从事件数据中提取 dragId如果没有则使用统一的生成方法 // 从事件数据中提取 dragId如果没有则使用统一的生成方法
let actualDragId = dragId || this._generateDragId(actualComponentType); let actualDragId = dragId || this._generateDragId(actualComponentType);
@@ -637,28 +654,29 @@ class DragStateManager {
sourceElement: sourceElement || data.element sourceElement: sourceElement || data.element
}; };
// 改进使用EVENT_TYPES常量替代字符串事件类型
switch (eventType) { switch (eventType) {
case 'panel.drag.start': case EVENT_TYPES.PANEL_DRAG_START:
case 'tabpage.drag.start': case EVENT_TYPES.TABPAGE_DRAG_START:
case 'area.drag.start': case EVENT_TYPES.AREA_DRAG_START:
await this._handleDragStart(dragData); await this._handleDragStart(dragData);
break; break;
case 'panel.drag.move': case EVENT_TYPES.PANEL_DRAG_MOVE:
case 'tabpage.drag.move': case EVENT_TYPES.TABPAGE_DRAG_MOVE:
case 'area.drag.move': case EVENT_TYPES.AREA_DRAG_MOVE:
await this._handleDragMove(dragData); await this._handleDragMove(dragData);
break; break;
case 'panel.drag.end': case EVENT_TYPES.PANEL_DRAG_END:
case 'tabpage.drag.end': case EVENT_TYPES.TABPAGE_DRAG_END:
case 'area.drag.end': case EVENT_TYPES.AREA_DRAG_END:
await this._handleDragEnd(dragData); await this._handleDragEnd(dragData);
break; break;
case 'panel.drag.cancel': case EVENT_TYPES.PANEL_DRAG_CANCEL:
case 'tabpage.drag.cancel': case EVENT_TYPES.TABPAGE_DRAG_CANCEL:
case 'area.drag.cancel': case EVENT_TYPES.AREA_DRAG_CANCEL:
await this._handleDragCancel(dragData); await this._handleDragCancel(dragData);
break; break;
} }
@@ -690,8 +708,29 @@ class DragStateManager {
// 检查是否已存在相同 dragId 的拖拽状态 // 检查是否已存在相同 dragId 的拖拽状态
if (this.activeDrags.has(actualDragId)) { if (this.activeDrags.has(actualDragId)) {
console.log(`⚠️ 拖拽状态已存在: ${actualDragId},跳过创建`); // 拖拽状态已存在,更新现有状态而不是创建新状态
return actualDragId; const existingDragState = this.activeDrags.get(actualDragId);
// 如果是同一个拖拽操作,更新组件类型和位置
if (existingDragState && existingDragState.status === 'active') {
// 只有在组件类型不同时才更新
if (existingDragState.componentType !== componentType) {
existingDragState.componentType = componentType;
console.log(`🔄 更新拖拽状态组件类型: ${actualDragId}${existingDragState.componentType}${componentType}`);
}
// 如果提供了新位置,更新位置信息
if (position) {
existingDragState.currentPosition = { ...position };
}
// 如果提供了新的源元素,更新源元素
if (sourceElement) {
existingDragState.sourceElement = sourceElement;
}
return actualDragId;
}
} }
// 创建拖拽状态 // 创建拖拽状态

View File

@@ -3,7 +3,7 @@
* 对所有事件处理器进行集成测试、性能监控和优化建议 * 对所有事件处理器进行集成测试、性能监控和优化建议
*/ */
import { eventBus } from '../eventBus'; import { eventBus, EVENT_TYPES } from '../eventBus';
import { panelHandler, PANEL_EVENT_TYPES } from './PanelHandler'; import { panelHandler, PANEL_EVENT_TYPES } from './PanelHandler';
import tabPageHandler, { TABPAGE_EVENT_TYPES } from './TabPageHandler'; import tabPageHandler, { TABPAGE_EVENT_TYPES } from './TabPageHandler';
import areaHandler, { AREA_EVENT_TYPES } from './AreaHandler'; import areaHandler, { AREA_EVENT_TYPES } from './AreaHandler';
@@ -1048,7 +1048,7 @@ class IntegrationTester {
const startTime = performance.now(); const startTime = performance.now();
// 模拟拖拽开始 // 模拟拖拽开始
eventBus.emit('panel.drag.start', { eventBus.emit(EVENT_TYPES.PANEL_DRAG_START, {
dragId: 'test-panel-drag', dragId: 'test-panel-drag',
panelId: 'test-panel-drag-id', panelId: 'test-panel-drag-id',
startPosition: { x: 100, y: 100 } startPosition: { x: 100, y: 100 }
@@ -1056,7 +1056,7 @@ class IntegrationTester {
// 模拟拖拽移动 // 模拟拖拽移动
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
eventBus.emit('panel.drag.move', { eventBus.emit(EVENT_TYPES.PANEL_DRAG_MOVE, {
dragId: 'test-panel-drag', dragId: 'test-panel-drag',
currentPosition: { x: 100 + i * 10, y: 100 + i * 5 } currentPosition: { x: 100 + i * 10, y: 100 + i * 5 }
}); });
@@ -1064,7 +1064,7 @@ class IntegrationTester {
} }
// 模拟拖拽结束 // 模拟拖拽结束
eventBus.emit('panel.drag.end', { eventBus.emit(EVENT_TYPES.PANEL_DRAG_END, {
dragId: 'test-panel-drag', dragId: 'test-panel-drag',
finalPosition: { x: 200, y: 150 }, finalPosition: { x: 200, y: 150 },
success: true success: true
@@ -1083,18 +1083,18 @@ class IntegrationTester {
async _testTabPageDrag(result) { async _testTabPageDrag(result) {
const startTime = performance.now(); const startTime = performance.now();
eventBus.emit('tabpage.drag.start', { eventBus.emit(EVENT_TYPES.TABPAGE_DRAG_START, {
dragId: 'test-tabpage-drag', dragId: 'test-tabpage-drag',
tabPageId: 'test-tabpage-drag-id', tabPageId: 'test-tabpage-drag-id',
startPosition: { x: 50, y: 50 } startPosition: { x: 50, y: 50 }
}); });
eventBus.emit('tabpage.drag.move', { eventBus.emit(EVENT_TYPES.TABPAGE_DRAG_MOVE, {
dragId: 'test-tabpage-drag', dragId: 'test-tabpage-drag',
currentPosition: { x: 150, y: 100 } currentPosition: { x: 150, y: 100 }
}); });
eventBus.emit('tabpage.drag.end', { eventBus.emit(EVENT_TYPES.TABPAGE_DRAG_END, {
dragId: 'test-tabpage-drag', dragId: 'test-tabpage-drag',
finalPosition: { x: 150, y: 100 }, finalPosition: { x: 150, y: 100 },
success: true success: true
@@ -1113,18 +1113,18 @@ class IntegrationTester {
async _testAreaDrag(result) { async _testAreaDrag(result) {
const startTime = performance.now(); const startTime = performance.now();
eventBus.emit('area.drag.start', { eventBus.emit(EVENT_TYPES.AREA_DRAG_START, {
dragId: 'test-area-drag', dragId: 'test-area-drag',
areaId: 'test-area-drag-id', areaId: 'test-area-drag-id',
startPosition: { x: 200, y: 200 } startPosition: { x: 200, y: 200 }
}); });
eventBus.emit('area.drag.move', { eventBus.emit(EVENT_TYPES.AREA_DRAG_MOVE, {
dragId: 'test-area-drag', dragId: 'test-area-drag',
currentPosition: { x: 300, y: 250 } currentPosition: { x: 300, y: 250 }
}); });
eventBus.emit('area.drag.end', { eventBus.emit(EVENT_TYPES.AREA_DRAG_END, {
dragId: 'test-area-drag', dragId: 'test-area-drag',
finalPosition: { x: 300, y: 250 }, finalPosition: { x: 300, y: 250 },
success: true success: true
@@ -1146,7 +1146,7 @@ class IntegrationTester {
// 同时启动多个拖拽 // 同时启动多个拖拽
dragIds.forEach((dragId, index) => { dragIds.forEach((dragId, index) => {
eventBus.emit('panel.drag.start', { eventBus.emit(EVENT_TYPES.PANEL_DRAG_START, {
dragId, dragId,
panelId: `panel-${index}`, panelId: `panel-${index}`,
startPosition: { x: 50 + index * 100, y: 50 } startPosition: { x: 50 + index * 100, y: 50 }
@@ -1156,7 +1156,7 @@ class IntegrationTester {
// 模拟同时移动 // 模拟同时移动
for (let i = 0; i < 5; i++) { for (let i = 0; i < 5; i++) {
dragIds.forEach((dragId, index) => { dragIds.forEach((dragId, index) => {
eventBus.emit('panel.drag.move', { eventBus.emit(EVENT_TYPES.PANEL_DRAG_MOVE, {
dragId, dragId,
currentPosition: { x: 50 + index * 100 + i * 20, y: 50 + i * 10 } currentPosition: { x: 50 + index * 100 + i * 20, y: 50 + i * 10 }
}); });
@@ -1166,7 +1166,7 @@ class IntegrationTester {
// 结束所有拖拽 // 结束所有拖拽
dragIds.forEach((dragId, index) => { dragIds.forEach((dragId, index) => {
eventBus.emit('panel.drag.end', { eventBus.emit(EVENT_TYPES.PANEL_DRAG_END, {
dragId, dragId,
finalPosition: { x: 50 + index * 100 + 100, y: 50 + 50 }, finalPosition: { x: 50 + index * 100 + 100, y: 50 + 50 },
success: true success: true