面板拖拽问题
This commit is contained in:
@@ -113,7 +113,7 @@
|
||||
|
||||
<script setup>
|
||||
import { defineProps, computed, ref, onMounted, onUnmounted, watch, defineExpose } from 'vue'
|
||||
import { emitEvent, EVENT_TYPES, globalEventListenerManager } from './eventBus'
|
||||
import { emitEvent, EVENT_TYPES } from './eventBus'
|
||||
import TabPage from './TabPage.vue'
|
||||
import Panel from './Panel.vue'
|
||||
import Render from './Render.vue'
|
||||
@@ -358,11 +358,7 @@ const onDragStart = (e) => {
|
||||
emitEvent(EVENT_TYPES.AREA_DRAG_START, {
|
||||
dragId: currentDragId.value,
|
||||
areaId: props.id,
|
||||
event: e,
|
||||
element: areaRef.value,
|
||||
position: { x: e.clientX, y: e.clientY },
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY,
|
||||
startLeft: originalPosition.value.left || 0,
|
||||
startTop: originalPosition.value.top || 0,
|
||||
timestamp: Date.now()
|
||||
@@ -370,10 +366,6 @@ const onDragStart = (e) => {
|
||||
source: { component: 'Area', areaId: props.id, dragId: currentDragId.value }
|
||||
})
|
||||
|
||||
// 使用全局事件管理器添加事件监听
|
||||
globalEventListenerManager.addGlobalListener('mousemove', onDragMove)
|
||||
globalEventListenerManager.addGlobalListener('mouseup', onDragEnd)
|
||||
|
||||
// 防止文本选择
|
||||
e.preventDefault()
|
||||
}
|
||||
@@ -409,11 +401,7 @@ const onDragMove = (e) => {
|
||||
emitEvent(EVENT_TYPES.AREA_DRAG_MOVE, {
|
||||
dragId: currentDragId.value,
|
||||
areaId: props.id,
|
||||
event: e,
|
||||
element: areaRef.value,
|
||||
position: { x: e.clientX, y: e.clientY },
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY,
|
||||
left: newLeft,
|
||||
top: newTop,
|
||||
timestamp: Date.now()
|
||||
@@ -453,9 +441,6 @@ const onDragEnd = () => {
|
||||
|
||||
isDragging.value = false
|
||||
currentDragId.value = null
|
||||
// 使用全局事件管理器移除事件监听
|
||||
globalEventListenerManager.removeGlobalListener('mousemove', onDragMove)
|
||||
globalEventListenerManager.removeGlobalListener('mouseup', onDragEnd)
|
||||
}
|
||||
|
||||
// 调整大小开始
|
||||
@@ -477,50 +462,45 @@ const onResizeStart = (direction, e) => {
|
||||
top: originalPosition.value.top
|
||||
}
|
||||
|
||||
// 使用全局事件管理器添加事件监听
|
||||
globalEventListenerManager.addGlobalListener('mousemove', onResizeMove)
|
||||
globalEventListenerManager.addGlobalListener('mouseup', onResizeEnd)
|
||||
globalEventListenerManager.addGlobalListener('mouseleave', onResizeEnd)
|
||||
|
||||
// 防止文本选择
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
// 调整大小移动
|
||||
const onResizeMove = (e) => {
|
||||
if (!isResizing.value) return
|
||||
const onResizeMove = (e) => {
|
||||
if (!isResizing.value) return
|
||||
|
||||
const deltaX = e.clientX - resizeStartPos.value.x
|
||||
const deltaY = e.clientY - resizeStartPos.value.y
|
||||
const deltaX = e.clientX - resizeStartPos.value.x
|
||||
const deltaY = e.clientY - resizeStartPos.value.y
|
||||
|
||||
let newWidth = resizeStartSize.value.width
|
||||
let newHeight = resizeStartSize.value.height
|
||||
let newLeft = resizeStartAreaPos.value.left
|
||||
let newTop = resizeStartAreaPos.value.top
|
||||
let newWidth = resizeStartSize.value.width
|
||||
let newHeight = resizeStartSize.value.height
|
||||
let newLeft = resizeStartAreaPos.value.left
|
||||
let newTop = resizeStartAreaPos.value.top
|
||||
|
||||
// 根据方向调整大小
|
||||
switch (resizeDirection.value) {
|
||||
case 'nw':
|
||||
newWidth = Math.max(200, resizeStartSize.value.width - deltaX)
|
||||
newHeight = Math.max(150, resizeStartSize.value.height - deltaY)
|
||||
newLeft = resizeStartAreaPos.value.left + deltaX
|
||||
newTop = resizeStartAreaPos.value.top + deltaY
|
||||
break
|
||||
case 'ne':
|
||||
newWidth = Math.max(200, resizeStartSize.value.width + deltaX)
|
||||
newHeight = Math.max(150, resizeStartSize.value.height - deltaY)
|
||||
newTop = resizeStartAreaPos.value.top + deltaY
|
||||
break
|
||||
case 'sw':
|
||||
newWidth = Math.max(200, resizeStartSize.value.width - deltaX)
|
||||
newHeight = Math.max(150, resizeStartSize.value.height + deltaY)
|
||||
newLeft = resizeStartAreaPos.value.left + deltaX
|
||||
break
|
||||
case 'se':
|
||||
newWidth = Math.max(200, resizeStartSize.value.width + deltaX)
|
||||
newHeight = Math.max(150, resizeStartSize.value.height + deltaY)
|
||||
break
|
||||
// 根据方向调整大小
|
||||
switch (resizeDirection.value) {
|
||||
case 'nw':
|
||||
newWidth = Math.max(200, resizeStartSize.value.width - deltaX)
|
||||
newHeight = Math.max(150, resizeStartSize.value.height - deltaY)
|
||||
newLeft = resizeStartAreaPos.value.left + deltaX
|
||||
newTop = resizeStartAreaPos.value.top + deltaY
|
||||
break
|
||||
case 'ne':
|
||||
newWidth = Math.max(200, resizeStartSize.value.width + deltaX)
|
||||
newHeight = Math.max(150, resizeStartSize.value.height - deltaY)
|
||||
newTop = resizeStartAreaPos.value.top + deltaY
|
||||
break
|
||||
case 'sw':
|
||||
newWidth = Math.max(200, resizeStartSize.value.width - deltaX)
|
||||
newHeight = Math.max(150, resizeStartSize.value.height + deltaY)
|
||||
newLeft = resizeStartAreaPos.value.left + deltaX
|
||||
break
|
||||
case 'se':
|
||||
newWidth = Math.max(200, resizeStartSize.value.width + deltaX)
|
||||
newHeight = Math.max(150, resizeStartSize.value.height + deltaY)
|
||||
break
|
||||
case 'n':
|
||||
// 拖动上边框时,Area向上边扩展
|
||||
newHeight = Math.max(150, resizeStartSize.value.height - deltaY)
|
||||
@@ -588,10 +568,6 @@ const onResizeStart = (direction, e) => {
|
||||
const onResizeEnd = () => {
|
||||
isResizing.value = false
|
||||
resizeDirection.value = null
|
||||
// 使用全局事件管理器移除事件监听
|
||||
globalEventListenerManager.removeGlobalListener('mousemove', onResizeMove)
|
||||
globalEventListenerManager.removeGlobalListener('mouseup', onResizeEnd)
|
||||
globalEventListenerManager.removeGlobalListener('mouseleave', onResizeEnd)
|
||||
}
|
||||
|
||||
const onToggleMaximize = () => {
|
||||
@@ -672,16 +648,13 @@ onMounted(() => {
|
||||
}
|
||||
})
|
||||
|
||||
// 组件卸载时清理全局事件监听器
|
||||
// 组件卸载时清理状态
|
||||
onUnmounted(() => {
|
||||
// 清理拖拽相关的全局事件监听器
|
||||
globalEventListenerManager.removeGlobalListener('mousemove', onDragMove)
|
||||
globalEventListenerManager.removeGlobalListener('mouseup', onDragEnd)
|
||||
|
||||
// 清理调整大小相关的全局事件监听器
|
||||
globalEventListenerManager.removeGlobalListener('mousemove', onResizeMove)
|
||||
globalEventListenerManager.removeGlobalListener('mouseup', onResizeEnd)
|
||||
globalEventListenerManager.removeGlobalListener('mouseleave', onResizeEnd)
|
||||
// 清理拖拽和调整大小状态
|
||||
isDragging.value = false
|
||||
currentDragId.value = null
|
||||
isResizing.value = false
|
||||
resizeDirection.value = null
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -106,43 +106,68 @@ const mainAreaResizeBars = ref([])
|
||||
// 检查主区域内是否有其他Area(简化版)
|
||||
const hasAreasInMainContent = ref(false)
|
||||
|
||||
/**
|
||||
* 检查是否应该操作区域而非面板
|
||||
* 当只有一个面板时,操作区域而不是面板
|
||||
* @param {string} areaId - Area ID
|
||||
* @returns {boolean} 是否应该操作区域
|
||||
*/
|
||||
const shouldOperateAreaInsteadOfPanel = (areaId) => {
|
||||
const area = floatingAreas.value.find(a => a.id === areaId);
|
||||
if (!area) return false;
|
||||
if (!area) {
|
||||
console.log(`[DockLayout] 未找到Area: ${areaId}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const childrenArray = Array.isArray(area.children) ? area.children : [area.children];
|
||||
if (childrenArray.length !== 1) return false;
|
||||
try {
|
||||
// 简化逻辑:直接检查区域的面板数量
|
||||
// 遍历所有子元素,统计Panel数量
|
||||
let panelCount = 0;
|
||||
|
||||
const tabPage = childrenArray[0];
|
||||
if (tabPage.type !== 'TabPage') return false;
|
||||
const childrenArray = Array.isArray(area.children) ? area.children : [area.children];
|
||||
|
||||
const tabPageChildren = tabPage.children;
|
||||
const tabPageChildrenArray = Array.isArray(tabPageChildren) ? tabPageChildren : [tabPageChildren];
|
||||
if (tabPageChildrenArray.length !== 1) return false;
|
||||
for (const child of childrenArray) {
|
||||
if (child.type === 'TabPage' && child.children) {
|
||||
const tabChildrenArray = Array.isArray(child.children) ? child.children : [child.children];
|
||||
for (const tabChild of tabChildrenArray) {
|
||||
if (tabChild.type === 'Panel') {
|
||||
panelCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查TabPage的children是否是Panel组件
|
||||
const childItem = tabPageChildrenArray[0];
|
||||
if (childItem.type !== 'Panel') return false;
|
||||
// 如果区域中只有一个面板,返回true
|
||||
const result = panelCount === 1;
|
||||
if (result) {
|
||||
console.log(`[DockLayout] Area ${areaId} 是单Panel模式,应该操作Area而不是Panel`);
|
||||
}
|
||||
|
||||
return true;
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`[DockLayout] 检查单Panel模式时出错:`, error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const onCloseFloatingArea = (event) => {
|
||||
const id = event.areaId;
|
||||
areaActions.closeFloatingArea(id);
|
||||
areaActions.closeFloating(id);
|
||||
const index = floatingAreas.value.findIndex(a => a.id === id);
|
||||
if (index !== -1) {
|
||||
floatingAreas.value.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
// 保持旧的onUpdatePosition函数以兼容现有事件
|
||||
const onUpdatePosition = (event) => {
|
||||
const id = event.areaId;
|
||||
const position = event;
|
||||
// 处理不同事件类型的数据结构
|
||||
const position = event.position || event;
|
||||
const area = floatingAreas.value.find(a => a.id === id);
|
||||
if (area) {
|
||||
area.x = position.left;
|
||||
area.y = position.top;
|
||||
area.left = position.left;
|
||||
area.top = position.top;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -227,64 +252,79 @@ const handleAreaDragLeave = (event) => {
|
||||
|
||||
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;
|
||||
const panelId = event.panelId;
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
// 触发面板拖拽开始上升事件
|
||||
eventBus.emit(EVENT_TYPES.PANEL_DRAG_START, {
|
||||
dragId: event.dragId,
|
||||
panelId: panelId,
|
||||
areaId: areaId,
|
||||
position: event.position,
|
||||
timestamp: event.timestamp,
|
||||
layout: {
|
||||
areas: floatingAreas.value
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`🚀 面板拖拽开始: panelId=${panelId}, areaId=${areaId}, dragId=${event.dragId}`);
|
||||
};
|
||||
|
||||
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 panelId = event.panelId;
|
||||
|
||||
// 触发面板拖拽移动上升事件
|
||||
eventBus.emit(EVENT_TYPES.PANEL_DRAG_MOVE, {
|
||||
dragId: event.dragId,
|
||||
panelId: panelId,
|
||||
areaId: areaId,
|
||||
position: event.position,
|
||||
timestamp: event.timestamp,
|
||||
layout: {
|
||||
areas: floatingAreas.value
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`📱 面板拖拽移动: panelId=${panelId}, areaId=${areaId}, position=${JSON.stringify(event.position)}`);
|
||||
};
|
||||
|
||||
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;
|
||||
const panelId = event.panelId;
|
||||
|
||||
eventBus.emit(EVENT_TYPES.AREA_DRAG_END, {
|
||||
dragId: event.dragId,
|
||||
areaId: areaId,
|
||||
finalPosition: {
|
||||
x: left,
|
||||
y: top
|
||||
},
|
||||
left: left,
|
||||
top: top
|
||||
});
|
||||
// 触发面板拖拽结束上升事件
|
||||
eventBus.emit(EVENT_TYPES.PANEL_DRAG_END, {
|
||||
dragId: event.dragId,
|
||||
panelId: panelId,
|
||||
areaId: areaId,
|
||||
position: event.position,
|
||||
timestamp: event.timestamp,
|
||||
layout: {
|
||||
areas: floatingAreas.value
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`✅ 面板拖拽结束: panelId=${panelId}, areaId=${areaId}, finalPosition=${JSON.stringify(event.position)}`);
|
||||
};
|
||||
|
||||
// 监听区域位置更新下降事件
|
||||
const onAreaPositionUpdate = (event) => {
|
||||
const id = event.areaId;
|
||||
const position = event.position;
|
||||
const area = floatingAreas.value.find(a => a.id === id);
|
||||
if (area) {
|
||||
area.left = position.left;
|
||||
area.top = position.top;
|
||||
}
|
||||
};
|
||||
|
||||
// 监听区域拖拽状态更新下降事件
|
||||
const onAreaDragStateUpdate = (event) => {
|
||||
const id = event.areaId;
|
||||
const status = event.status;
|
||||
const area = floatingAreas.value.find(a => a.id === id);
|
||||
if (area) {
|
||||
area.isDragging = status === 'active' || status === 'moving';
|
||||
}
|
||||
};
|
||||
|
||||
@@ -387,10 +427,15 @@ const setupEventListeners = () => {
|
||||
|
||||
// Area相关事件
|
||||
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.AREA_POSITION_UPDATE, onUpdatePosition, { componentId: 'dock-layout' }));
|
||||
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.AREA_FLOATING_UPDATE_POSITION, onUpdatePosition, { componentId: 'dock-layout' }));
|
||||
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.AREA_DRAG_OVER, handleAreaDragOver, { componentId: 'dock-layout' }));
|
||||
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.AREA_DRAG_LEAVE, handleAreaDragLeave, { componentId: 'dock-layout' }));
|
||||
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.AREA_MERGE_REQUEST, handleAreaMergeRequest, { componentId: 'dock-layout' }));
|
||||
|
||||
// 添加新的下降事件监听器
|
||||
unsubscribeFunctions.push(eventBus.on('area.position.update', onAreaPositionUpdate, { componentId: 'dock-layout' }));
|
||||
unsubscribeFunctions.push(eventBus.on('area.drag.state.update', onAreaDragStateUpdate, { componentId: 'dock-layout' }));
|
||||
|
||||
// Tab相关事件
|
||||
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.TAB_CHANGE, onTabChange, { componentId: 'dock-layout' }));
|
||||
unsubscribeFunctions.push(eventBus.on(EVENT_TYPES.TAB_CLOSE, onTabClose, { componentId: 'dock-layout' }));
|
||||
@@ -533,8 +578,9 @@ const addFloatingPanel = (panel) => {
|
||||
|
||||
const newArea = {
|
||||
id: `area-${Date.now()}`,
|
||||
x: 100 + Math.random() * 200,
|
||||
y: 100 + Math.random() * 200,
|
||||
type: 'floating', // 添加浮动类型标识
|
||||
left: 100 + Math.random() * 200,
|
||||
top: 100 + Math.random() * 200,
|
||||
width: 300,
|
||||
height: 200,
|
||||
zIndex: zIndexManager.getFloatingAreaZIndex(`area-${Date.now()}`),
|
||||
@@ -549,7 +595,13 @@ const addFloatingPanel = (panel) => {
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
// 添加到DockLayout的floatingAreas数组中用于渲染
|
||||
floatingAreas.value.push(newArea)
|
||||
|
||||
// 同时注册到AreaHandler的状态管理中,确保事件处理能正常进行
|
||||
areaActions.createFloating(newArea)
|
||||
|
||||
return newArea.id
|
||||
}
|
||||
|
||||
|
||||
@@ -119,6 +119,10 @@ import {
|
||||
emitEvent,
|
||||
onEvent
|
||||
} from './eventBus';
|
||||
import { areaActions, getAreaHandler } from './handlers/AreaHandler';
|
||||
|
||||
// 获取AreaHandler实例
|
||||
const areaHandler = getAreaHandler();
|
||||
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
@@ -241,141 +245,7 @@ const onToggleToolbar = () => {
|
||||
// 拖拽相关状态
|
||||
let isDragging = false
|
||||
let currentDragId = null
|
||||
|
||||
// 全局内存泄漏保护机制
|
||||
if (!window.__panelMemoryProtection) {
|
||||
window.__panelMemoryProtection = {
|
||||
// 存储所有面板组件实例追踪信息
|
||||
panelInstances: new Map(),
|
||||
|
||||
// 定时检测内存泄漏(开发环境)
|
||||
startLeakDetection() {
|
||||
if (import.meta.env.DEV) {
|
||||
setInterval(() => {
|
||||
this.detectMemoryLeaks()
|
||||
}, 30000) // 每30秒检测一次
|
||||
}
|
||||
},
|
||||
|
||||
// 检测内存泄漏
|
||||
detectMemoryLeaks() {
|
||||
const activePanels = window.__panelDragHandlers ? window.__panelDragHandlers.size : 0
|
||||
const registeredPanels = this.panelInstances.size
|
||||
|
||||
if (activePanels !== registeredPanels) {
|
||||
console.warn(`[内存泄漏检测] 发现面板内存不一致 - 活动拖拽: ${activePanels}, 注册实例: ${registeredPanels}`)
|
||||
|
||||
// 清理 orphaned handlers
|
||||
if (window.__panelDragHandlers && activePanels > 0) {
|
||||
window.__panelDragHandlers.forEach((handlers, panelId) => {
|
||||
if (!this.panelInstances.has(panelId)) {
|
||||
console.warn(`[内存泄漏检测] 清理orphaned handler: ${panelId}`)
|
||||
document.removeEventListener('mousemove', handlers.dragMoveHandler, false)
|
||||
document.removeEventListener('mouseup', handlers.dragEndHandler, false)
|
||||
document.removeEventListener('mouseleave', handlers.dragEndHandler, false)
|
||||
window.__panelDragHandlers.delete(panelId)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 注册面板实例
|
||||
registerPanel(panelId) {
|
||||
this.panelInstances.set(panelId, {
|
||||
createdAt: Date.now(),
|
||||
lastActivity: Date.now()
|
||||
})
|
||||
},
|
||||
|
||||
// 注销面板实例
|
||||
unregisterPanel(panelId) {
|
||||
this.panelInstances.delete(panelId)
|
||||
},
|
||||
|
||||
// 更新活动状态
|
||||
updateActivity(panelId) {
|
||||
const panel = this.panelInstances.get(panelId)
|
||||
if (panel) {
|
||||
panel.lastActivity = Date.now()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 启动内存泄漏检测
|
||||
window.__panelMemoryProtection.startLeakDetection()
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加Document拖拽事件监听器
|
||||
*/
|
||||
const addDocumentDragListeners = () => {
|
||||
// 移除可能存在的旧监听器
|
||||
cleanupDragEventListeners()
|
||||
|
||||
// 使用组件实例标识符确保清理正确性
|
||||
const componentId = `panel_${props.id}`
|
||||
const dragMoveHandler = (e) => onDragMove(e)
|
||||
const dragEndHandler = (e) => onDragEnd(e)
|
||||
|
||||
// 将处理函数绑定到组件作用域,避免匿名函数导致的清理问题
|
||||
if (!window.__panelDragHandlers) {
|
||||
window.__panelDragHandlers = new Map()
|
||||
}
|
||||
|
||||
window.__panelDragHandlers.set(componentId, {
|
||||
dragMoveHandler,
|
||||
dragEndHandler
|
||||
})
|
||||
|
||||
document.addEventListener('mousemove', dragMoveHandler, false)
|
||||
document.addEventListener('mouseup', dragEndHandler, false)
|
||||
document.addEventListener('mouseleave', dragEndHandler, false)
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
console.log(`[Panel:${props.id}] Document拖拽事件监听器已添加: ${componentId}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理Document拖拽事件监听器
|
||||
*/
|
||||
const cleanupDragEventListeners = () => {
|
||||
try {
|
||||
const componentId = `panel_${props.id}`
|
||||
|
||||
// 从全局拖拽处理函数映射中获取处理函数
|
||||
const handlers = window.__panelDragHandlers?.get(componentId)
|
||||
|
||||
if (handlers) {
|
||||
// 使用正确的处理函数引用进行清理
|
||||
document.removeEventListener('mousemove', handlers.dragMoveHandler, false)
|
||||
document.removeEventListener('mouseup', handlers.dragEndHandler, false)
|
||||
document.removeEventListener('mouseleave', handlers.dragEndHandler, false)
|
||||
|
||||
// 从映射中移除
|
||||
window.__panelDragHandlers.delete(componentId)
|
||||
|
||||
// 清理映射,如果为空则删除整个映射
|
||||
if (window.__panelDragHandlers.size === 0) {
|
||||
delete window.__panelDragHandlers
|
||||
}
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
console.log(`[Panel:${props.id}] Document拖拽事件监听器已清理: ${componentId}`)
|
||||
}
|
||||
}
|
||||
|
||||
// 立即重置拖拽状态,确保清理完整性
|
||||
isDragging = false
|
||||
|
||||
} catch (error) {
|
||||
console.warn(`[Panel:${props.id}] 清理拖拽事件监听器时出错:`, error)
|
||||
|
||||
// 发生错误时仍然重置状态
|
||||
isDragging = false
|
||||
}
|
||||
}
|
||||
let currentAreaId = null
|
||||
|
||||
// 拖拽开始
|
||||
const onDragStart = (e) => {
|
||||
@@ -384,7 +254,7 @@ const onDragStart = (e) => {
|
||||
// 1. 立即重置之前的拖拽状态
|
||||
isDragging = false
|
||||
currentDragId = null
|
||||
cleanupDragEventListeners()
|
||||
currentAreaId = null
|
||||
|
||||
isDragging = true
|
||||
|
||||
@@ -393,73 +263,90 @@ const onDragStart = (e) => {
|
||||
|
||||
console.log(`[Panel:${props.id}] 开始拖拽, dragId: ${currentDragId}`)
|
||||
|
||||
const areaId = getCurrentAreaId();
|
||||
// 保存当前Area的ID,避免在拖拽移动过程中重复调用getCurrentAreaId()
|
||||
currentAreaId = getCurrentAreaId();
|
||||
|
||||
// 获取所有浮动区域信息,用于单面板检测
|
||||
const floatingAreas = areaHandler.areaStateManager.getFloatingAreas();
|
||||
|
||||
emitEvent(EVENT_TYPES.PANEL_DRAG_START, {
|
||||
dragId: currentDragId,
|
||||
panelId: props.id,
|
||||
areaId: areaId,
|
||||
areaId: currentAreaId,
|
||||
position: { x: e.clientX, y: e.clientY },
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
layout: {
|
||||
areas: floatingAreas
|
||||
}
|
||||
}, {
|
||||
source: { component: 'Panel', panelId: props.id, dragId: currentDragId }
|
||||
})
|
||||
|
||||
// 添加全局的拖拽移动和结束事件监听
|
||||
const onDragMove = (e) => {
|
||||
if (isDragging) {
|
||||
// 获取所有浮动区域信息,用于单面板检测
|
||||
const floatingAreas = areaHandler.areaStateManager.getFloatingAreas();
|
||||
|
||||
emitEvent(EVENT_TYPES.PANEL_DRAG_MOVE, {
|
||||
dragId: currentDragId,
|
||||
panelId: props.id,
|
||||
areaId: currentAreaId,
|
||||
position: { x: e.clientX, y: e.clientY },
|
||||
timestamp: Date.now(),
|
||||
layout: {
|
||||
areas: floatingAreas
|
||||
}
|
||||
}, {
|
||||
source: { component: 'Panel', panelId: props.id, dragId: currentDragId }
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const onDragEnd = () => {
|
||||
if (isDragging) {
|
||||
isDragging = false
|
||||
// 获取所有浮动区域信息,用于单面板检测
|
||||
const floatingAreas = areaHandler.areaStateManager.getFloatingAreas();
|
||||
|
||||
emitEvent(EVENT_TYPES.PANEL_DRAG_END, {
|
||||
dragId: currentDragId,
|
||||
panelId: props.id,
|
||||
areaId: currentAreaId,
|
||||
timestamp: Date.now(),
|
||||
layout: {
|
||||
areas: floatingAreas
|
||||
}
|
||||
}, {
|
||||
source: { component: 'Panel', panelId: props.id, dragId: currentDragId }
|
||||
})
|
||||
|
||||
// 清理全局事件监听器
|
||||
document.removeEventListener('mousemove', onDragMove)
|
||||
document.removeEventListener('mouseup', onDragEnd)
|
||||
document.removeEventListener('mouseleave', onDragEnd)
|
||||
}
|
||||
};
|
||||
|
||||
// 添加全局事件监听器
|
||||
document.addEventListener('mousemove', onDragMove)
|
||||
document.addEventListener('mouseup', onDragEnd)
|
||||
document.addEventListener('mouseleave', onDragEnd)
|
||||
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
addDocumentDragListeners()
|
||||
}
|
||||
};
|
||||
|
||||
// 拖拽移动
|
||||
const onDragMove = (e) => {
|
||||
if (isDragging && currentDragId) {
|
||||
// 防止文本选择和默认行为
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const areaId = getCurrentAreaId();
|
||||
|
||||
emitEvent(EVENT_TYPES.PANEL_DRAG_MOVE, {
|
||||
dragId: currentDragId,
|
||||
panelId: props.id,
|
||||
areaId: areaId,
|
||||
position: { x: e.clientX, y: e.clientY },
|
||||
timestamp: Date.now()
|
||||
}, {
|
||||
source: { component: 'Panel', panelId: props.id, dragId: currentDragId }
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const onDragEnd = () => {
|
||||
if (isDragging && currentDragId) {
|
||||
isDragging = false;
|
||||
|
||||
console.log(`[Panel:${props.id}] 结束拖拽, dragId: ${currentDragId}`)
|
||||
|
||||
const areaId = getCurrentAreaId();
|
||||
|
||||
emitEvent(EVENT_TYPES.PANEL_DRAG_END, {
|
||||
dragId: currentDragId,
|
||||
panelId: props.id,
|
||||
areaId: areaId,
|
||||
timestamp: Date.now()
|
||||
}, {
|
||||
source: { component: 'Panel', panelId: props.id, dragId: currentDragId }
|
||||
})
|
||||
|
||||
currentDragId = null;
|
||||
cleanupDragEventListeners();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 监听面板关闭事件,更新组件状态(可选)
|
||||
* 注册面板相关事件监听器,确保唯一性
|
||||
*/
|
||||
const setupEventListeners = () => {
|
||||
try {
|
||||
if (import.meta.env.DEV) {
|
||||
console.log(`[Panel:${props.id}] 开始注册事件监听器...`)
|
||||
}
|
||||
|
||||
// 监听面板最大化同步事件
|
||||
const unsubscribeMaximizeSync = onEvent(EVENT_TYPES.PANEL_MAXIMIZE_SYNC, (data) => {
|
||||
if (data.panelId === props.id) {
|
||||
@@ -467,7 +354,17 @@ const setupEventListeners = () => {
|
||||
}
|
||||
}, { componentId: `panel-${props.id}` })
|
||||
|
||||
// 生成唯一的订阅ID
|
||||
const subscriptionId = `maximizeSync_${props.id}_${Date.now()}`
|
||||
|
||||
// 检查是否已经注册过相同的监听器
|
||||
if (subscriptionRegistry.has(subscriptionId)) {
|
||||
// 监听器已存在,打日志并返回
|
||||
console.warn(`[Panel:${props.id}] 监听器已存在,跳过重复注册: ${subscriptionId}`)
|
||||
return
|
||||
}
|
||||
|
||||
// 将订阅函数添加到集合和注册表中
|
||||
subscriptions.add(unsubscribeMaximizeSync)
|
||||
subscriptionRegistry.set(subscriptionId, {
|
||||
unsubscribe: unsubscribeMaximizeSync,
|
||||
@@ -483,21 +380,20 @@ const setupEventListeners = () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* 增强版清理事件监听器,返回清理结果统计
|
||||
* 清理事件监听器
|
||||
*/
|
||||
const cleanupEventListeners = () => {
|
||||
const cleanupResult = {
|
||||
eventSubscriptions: 0,
|
||||
documentListeners: 0,
|
||||
errors: []
|
||||
}
|
||||
|
||||
try {
|
||||
if (import.meta.env.DEV) {
|
||||
console.log(`[Panel:${props.id}] 开始清理所有事件监听器...`)
|
||||
console.log(`[Panel:${props.id}] 开始清理事件订阅...`)
|
||||
}
|
||||
|
||||
// 1. 清理事件订阅
|
||||
// 清理事件订阅
|
||||
let unsubscribeCount = 0
|
||||
const subscriptionsToCleanup = Array.from(subscriptions)
|
||||
|
||||
@@ -529,17 +425,7 @@ const cleanupEventListeners = () => {
|
||||
cleanupResult.errors.push(`事件订阅清理错误: ${error.message}`)
|
||||
}
|
||||
|
||||
try {
|
||||
// 2. 清理Document事件监听器
|
||||
cleanupDragEventListeners()
|
||||
cleanupResult.documentListeners = 3 // mousemove, mouseup, mouseleave
|
||||
|
||||
} catch (error) {
|
||||
console.error(`[Panel:${props.id}] 清理Document事件监听器时发生错误:`, error)
|
||||
cleanupResult.errors.push(`Document事件清理错误: ${error.message}`)
|
||||
}
|
||||
|
||||
// 3. 重置状态
|
||||
// 重置状态
|
||||
try {
|
||||
isDragging = false
|
||||
if (import.meta.env.DEV) {
|
||||
@@ -549,7 +435,7 @@ const cleanupEventListeners = () => {
|
||||
cleanupResult.errors.push(`状态重置错误: ${error.message}`)
|
||||
}
|
||||
|
||||
// 4. 输出清理结果摘要
|
||||
// 输出清理结果摘要
|
||||
if (import.meta.env.DEV) {
|
||||
const totalErrors = cleanupResult.errors.length
|
||||
if (totalErrors > 0) {
|
||||
@@ -566,11 +452,6 @@ const cleanupEventListeners = () => {
|
||||
onMounted(() => {
|
||||
console.log(`[Panel:${props.id}] 组件已挂载`)
|
||||
|
||||
// 注册到全局内存保护机制
|
||||
if (window.__panelMemoryProtection) {
|
||||
window.__panelMemoryProtection.registerPanel(`panel_${props.id}`)
|
||||
}
|
||||
|
||||
// 启用调试模式(开发环境)
|
||||
if (import.meta.env.DEV) {
|
||||
eventBus.setDebugMode(true)
|
||||
@@ -579,11 +460,6 @@ onMounted(() => {
|
||||
// 设置事件监听器
|
||||
setupEventListeners()
|
||||
|
||||
// 更新活动状态
|
||||
if (window.__panelMemoryProtection) {
|
||||
window.__panelMemoryProtection.updateActivity(`panel_${props.id}`)
|
||||
}
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
console.log(`[Panel:${props.id}] 所有监听器设置完成`)
|
||||
}
|
||||
@@ -592,14 +468,9 @@ onMounted(() => {
|
||||
onUnmounted(() => {
|
||||
console.log(`[Panel:${props.id}] 组件即将卸载`)
|
||||
|
||||
// 立即注销全局内存保护机制
|
||||
if (window.__panelMemoryProtection) {
|
||||
window.__panelMemoryProtection.unregisterPanel(`panel_${props.id}`)
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. 立即设置标志位,防止新的异步操作
|
||||
isDragging.value = false
|
||||
isDragging = false
|
||||
|
||||
// 2. 同步清理所有可以直接清理的资源
|
||||
const cleanupResult = cleanupEventListeners()
|
||||
@@ -614,7 +485,7 @@ onUnmounted(() => {
|
||||
|
||||
// 即使出现异常,也要尝试强制清理
|
||||
try {
|
||||
isDragging.value = false
|
||||
isDragging = false
|
||||
} catch (forceError) {
|
||||
console.error(`[Panel:${props.id}] 强制清理也失败:`, forceError)
|
||||
}
|
||||
|
||||
@@ -740,127 +740,7 @@ export function getEventBus() {
|
||||
|
||||
export const eventBus = eventBusInstance
|
||||
|
||||
class GlobalEventListenerManager {
|
||||
constructor() {
|
||||
this.listeners = new Map()
|
||||
}
|
||||
|
||||
addGlobalListener(eventType, handler) {
|
||||
if (!this.listeners.has(eventType)) {
|
||||
this.listeners.set(eventType, new Map())
|
||||
}
|
||||
|
||||
const eventHandlers = this.listeners.get(eventType)
|
||||
const handlerId = handler.toString()
|
||||
const isDuplicate = eventHandlers.has(handlerId)
|
||||
|
||||
if (!isDuplicate) {
|
||||
document.addEventListener(eventType, handler)
|
||||
eventHandlers.set(handlerId, {
|
||||
handler,
|
||||
count: 0
|
||||
})
|
||||
|
||||
const handlerInfo = eventHandlers.get(handlerId)
|
||||
handlerInfo.count++
|
||||
|
||||
const currentCount = handlerInfo.count
|
||||
const totalListeners = Array.from(this.listeners.values()).reduce((sum, map) => sum + map.size, 0)
|
||||
|
||||
console.log(`📌 [Listener] ADD: ${eventType} - ${handlerId.slice(0, 30)}... (count: ${currentCount}) | Total listeners: ${totalListeners}`)
|
||||
} else {
|
||||
const handlerInfo = eventHandlers.get(handlerId)
|
||||
handlerInfo.count++
|
||||
|
||||
const currentCount = handlerInfo.count
|
||||
const totalListeners = Array.from(this.listeners.values()).reduce((sum, map) => sum + map.size, 0)
|
||||
|
||||
console.log(`🔁 [Listener] DUPLICATE: ${eventType} - ${handlerId.slice(0, 30)}... (already registered, count: ${currentCount})`)
|
||||
}
|
||||
|
||||
return handlerId
|
||||
}
|
||||
|
||||
removeGlobalListener(eventType, handler) {
|
||||
if (!this.listeners.has(eventType)) {
|
||||
console.log(`❌ [Listener] REMOVE_FAILED: ${eventType} - ${handler.toString().slice(0, 30)}... (event type not found)`)
|
||||
return false
|
||||
}
|
||||
|
||||
const eventHandlers = this.listeners.get(eventType)
|
||||
const handlerId = handler.toString()
|
||||
|
||||
if (!eventHandlers.has(handlerId)) {
|
||||
console.log(`❌ [Listener] REMOVE_FAILED: ${eventType} - ${handlerId.slice(0, 30)}... (handler not found)`)
|
||||
return false
|
||||
}
|
||||
|
||||
const handlerInfo = eventHandlers.get(handlerId)
|
||||
const oldCount = handlerInfo.count
|
||||
|
||||
if (handlerInfo.count > 0) {
|
||||
handlerInfo.count--
|
||||
const newCount = handlerInfo.count
|
||||
|
||||
if (newCount === 0) {
|
||||
document.removeEventListener(eventType, handler)
|
||||
eventHandlers.delete(handlerId)
|
||||
|
||||
if (eventHandlers.size === 0) {
|
||||
this.listeners.delete(eventType)
|
||||
}
|
||||
}
|
||||
|
||||
const totalListeners = Array.from(this.listeners.values()).reduce((sum, map) => sum + map.size, 0)
|
||||
|
||||
console.log(`🗑️ [Listener] REMOVE: ${eventType} - ${handlerId.slice(0, 30)}... (count: ${oldCount} → ${newCount}) | Total listeners: ${totalListeners}`)
|
||||
return true
|
||||
}
|
||||
|
||||
console.log(`❌ [Listener] REMOVE_FAILED: ${eventType} - ${handlerId.slice(0, 30)}... (count already 0)`)
|
||||
return false
|
||||
}
|
||||
|
||||
getStats() {
|
||||
const stats = {}
|
||||
for (const [eventType, eventHandlers] of this.listeners.entries()) {
|
||||
let totalCount = 0
|
||||
for (const handlerInfo of eventHandlers.values()) {
|
||||
totalCount += handlerInfo.count
|
||||
}
|
||||
|
||||
stats[eventType] = {
|
||||
count: totalCount,
|
||||
handlerCount: eventHandlers.size
|
||||
}
|
||||
}
|
||||
return stats
|
||||
}
|
||||
|
||||
clearAll() {
|
||||
let removedCount = 0
|
||||
let eventTypesCount = this.listeners.size
|
||||
|
||||
for (const [eventType, eventHandlers] of this.listeners.entries()) {
|
||||
removedCount += eventHandlers.size
|
||||
for (const [handlerId, handlerInfo] of eventHandlers.entries()) {
|
||||
document.removeEventListener(eventType, handlerInfo.handler)
|
||||
}
|
||||
}
|
||||
|
||||
this.listeners.clear()
|
||||
|
||||
console.log(`🧹 [Listener] CLEAR_ALL: Removed ${removedCount} listeners across ${eventTypesCount} event types`)
|
||||
}
|
||||
}
|
||||
|
||||
const globalEventListenerManagerInstance = new GlobalEventListenerManager()
|
||||
|
||||
export function getGlobalEventListenerManager() {
|
||||
return globalEventListenerManagerInstance
|
||||
}
|
||||
|
||||
export const globalEventListenerManager = globalEventListenerManagerInstance
|
||||
|
||||
class EventHandlerRegistry {
|
||||
constructor() {
|
||||
@@ -996,38 +876,38 @@ export const getHandlerSnapshot = () => {
|
||||
|
||||
export const triggerDragEvent = {
|
||||
area: {
|
||||
start: (areaId, event) => {
|
||||
return eventBus.emit(EVENT_TYPES.AREA_DRAG_START, { areaId, event })
|
||||
start: (areaId, position) => {
|
||||
return eventBus.emit(EVENT_TYPES.AREA_DRAG_START, { areaId, position })
|
||||
},
|
||||
move: (areaId, event) => {
|
||||
eventBus.emit(EVENT_TYPES.AREA_DRAG_MOVE, { areaId, event })
|
||||
move: (areaId, position) => {
|
||||
eventBus.emit(EVENT_TYPES.AREA_DRAG_MOVE, { areaId, position })
|
||||
},
|
||||
end: (areaId, event) => {
|
||||
eventBus.emit(EVENT_TYPES.AREA_DRAG_END, { areaId, event })
|
||||
end: (areaId, position) => {
|
||||
eventBus.emit(EVENT_TYPES.AREA_DRAG_END, { areaId, position })
|
||||
}
|
||||
},
|
||||
|
||||
tab: {
|
||||
start: (tabId, event) => {
|
||||
return eventBus.emit(EVENT_TYPES.TAB_DRAG_START, { tabId, event })
|
||||
start: (tabId, position) => {
|
||||
return eventBus.emit(EVENT_TYPES.TAB_DRAG_START, { tabId, position })
|
||||
},
|
||||
move: (tabId, event) => {
|
||||
eventBus.emit(EVENT_TYPES.TAB_DRAG_MOVE, { tabId, event })
|
||||
move: (tabId, position) => {
|
||||
eventBus.emit(EVENT_TYPES.TAB_DRAG_MOVE, { tabId, position })
|
||||
},
|
||||
end: (tabId, event) => {
|
||||
eventBus.emit(EVENT_TYPES.TAB_DRAG_END, { tabId, event })
|
||||
end: (tabId, position) => {
|
||||
eventBus.emit(EVENT_TYPES.TAB_DRAG_END, { tabId, position })
|
||||
}
|
||||
},
|
||||
|
||||
panel: {
|
||||
start: (panelId, event) => {
|
||||
return eventBus.emit(EVENT_TYPES.PANEL_DRAG_START, { panelId, event })
|
||||
start: (panelId, position) => {
|
||||
return eventBus.emit(EVENT_TYPES.PANEL_DRAG_START, { panelId, position })
|
||||
},
|
||||
move: (panelId, event) => {
|
||||
eventBus.emit(EVENT_TYPES.PANEL_DRAG_MOVE, { panelId, event })
|
||||
move: (panelId, position) => {
|
||||
eventBus.emit(EVENT_TYPES.PANEL_DRAG_MOVE, { panelId, position })
|
||||
},
|
||||
end: (panelId, event) => {
|
||||
eventBus.emit(EVENT_TYPES.PANEL_DRAG_END, { panelId, event })
|
||||
end: (panelId, position) => {
|
||||
eventBus.emit(EVENT_TYPES.PANEL_DRAG_END, { panelId, position })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,13 +56,18 @@ class AreaStateManager {
|
||||
* @returns {string} Area ID
|
||||
*/
|
||||
createFloatingArea(areaConfig) {
|
||||
const areaId = `floating-area-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
// 使用传入的ID,如果没有则生成新的ID
|
||||
const areaId = areaConfig.id || `floating-area-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
|
||||
// 优先使用left/top,兼容x/y
|
||||
const left = areaConfig.left !== undefined ? areaConfig.left : areaConfig.x || 50;
|
||||
const top = areaConfig.top !== undefined ? areaConfig.top : areaConfig.y || 50;
|
||||
|
||||
const floatingArea = {
|
||||
id: areaId,
|
||||
type: 'floating',
|
||||
x: areaConfig.x || 50,
|
||||
y: areaConfig.y || 50,
|
||||
left: left,
|
||||
top: top,
|
||||
width: areaConfig.width || 400,
|
||||
height: areaConfig.height || 300,
|
||||
zIndex: areaConfig.zIndex || 1001,
|
||||
@@ -120,8 +125,8 @@ class AreaStateManager {
|
||||
|
||||
const updatedArea = {
|
||||
...area,
|
||||
x: position.left || area.x,
|
||||
y: position.top || area.y,
|
||||
left: position.left || area.left,
|
||||
top: position.top || area.top,
|
||||
lastPositionUpdate: Date.now()
|
||||
};
|
||||
|
||||
@@ -132,8 +137,8 @@ class AreaStateManager {
|
||||
eventBus.emit(EVENT_TYPES.AREA_FLOATING_UPDATE_POSITION, {
|
||||
areaId,
|
||||
position: {
|
||||
left: updatedArea.x,
|
||||
top: updatedArea.y
|
||||
left: updatedArea.left,
|
||||
top: updatedArea.top
|
||||
},
|
||||
timestamp: Date.now()
|
||||
});
|
||||
@@ -338,8 +343,8 @@ class AreaEventHandler {
|
||||
addFloatingPanel(options = {}) {
|
||||
try {
|
||||
const areaConfig = {
|
||||
x: options.x || 50,
|
||||
y: options.y || 50,
|
||||
left: options.left || options.x || 50,
|
||||
top: options.top || options.y || 50,
|
||||
width: options.width || 280,
|
||||
height: options.height || 200,
|
||||
title: options.title || `浮动区域 ${Date.now()}`,
|
||||
@@ -543,7 +548,7 @@ class AreaEventHandler {
|
||||
// 触发工具栏切换事件
|
||||
eventBus.emit(EVENT_TYPES.AREA_TOGGLE_TOOLBAR, {
|
||||
areaId,
|
||||
expanded: toolbarExpanded,
|
||||
expanded: newToolbarState,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
@@ -819,13 +824,14 @@ class AreaEventHandler {
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleAreaDragStart(data) {
|
||||
const { areaId, event, source = 'direct' } = data;
|
||||
const { areaId, position, source = 'direct' } = data;
|
||||
|
||||
// 记录拖拽状态
|
||||
// 记录拖拽状态,包括上一次鼠标位置
|
||||
this.areaStateManager.setDragState(areaId, {
|
||||
isDragging: true,
|
||||
source,
|
||||
startPosition: { x: event.clientX, y: event.clientY },
|
||||
startPosition: position,
|
||||
lastPosition: position, // 记录上一次鼠标位置
|
||||
startTime: Date.now(),
|
||||
dragType: 'area'
|
||||
});
|
||||
@@ -846,25 +852,25 @@ class AreaEventHandler {
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleAreaDragMove(data) {
|
||||
const { areaId, event } = data;
|
||||
const { areaId, position } = data;
|
||||
const dragState = this.areaStateManager.getDragState(areaId);
|
||||
|
||||
if (!dragState || !dragState.isDragging) return;
|
||||
|
||||
// 计算移动距离
|
||||
const deltaX = event.clientX - dragState.startPosition.x;
|
||||
const deltaY = event.clientY - dragState.startPosition.y;
|
||||
// 计算移动距离:使用上一次鼠标位置,而不是初始位置,避免累积偏移
|
||||
const deltaX = position.x - dragState.lastPosition.x;
|
||||
const deltaY = position.y - dragState.lastPosition.y;
|
||||
|
||||
// 更新拖拽状态
|
||||
dragState.lastPosition = { x: event.clientX, y: event.clientY };
|
||||
// 更新拖拽状态:记录当前鼠标位置为下一次的lastPosition
|
||||
dragState.lastPosition = position;
|
||||
dragState.delta = { x: deltaX, y: deltaY };
|
||||
|
||||
// 更新Area位置(如果是浮动Area)
|
||||
const areaState = this.areaStateManager.getState(areaId);
|
||||
if (areaState.type === 'floating') {
|
||||
this.areaStateManager.updateFloatingAreaPosition(areaId, {
|
||||
left: (areaState.x || 0) + deltaX,
|
||||
top: (areaState.y || 0) + deltaY
|
||||
left: (areaState.left || 0) + deltaX,
|
||||
top: (areaState.top || 0) + deltaY
|
||||
});
|
||||
}
|
||||
|
||||
@@ -872,7 +878,7 @@ class AreaEventHandler {
|
||||
eventBus.emit(EVENT_TYPES.AREA_DRAG_MOVE, {
|
||||
areaId,
|
||||
delta: { x: deltaX, y: deltaY },
|
||||
position: { x: event.clientX, y: event.clientY },
|
||||
position: position,
|
||||
isDragging: dragState.isDragging
|
||||
});
|
||||
}
|
||||
@@ -882,7 +888,7 @@ class AreaEventHandler {
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleAreaDragEnd(data) {
|
||||
const { areaId, event, finalPosition, left, top } = data;
|
||||
const { areaId, finalPosition, left, top } = data;
|
||||
const dragState = this.areaStateManager.getDragState(areaId);
|
||||
|
||||
if (!dragState) return;
|
||||
@@ -897,13 +903,11 @@ class AreaEventHandler {
|
||||
|
||||
// 使用 finalPosition 或 left/top 作为结束位置
|
||||
if (finalPosition) {
|
||||
dragState.endPosition = { x: finalPosition.x, y: finalPosition.y };
|
||||
dragState.endPosition = finalPosition;
|
||||
} else if (left !== undefined && top !== undefined) {
|
||||
dragState.endPosition = { x: left, y: top };
|
||||
} else if (event) {
|
||||
dragState.endPosition = { x: event.clientX, y: event.clientY };
|
||||
} else {
|
||||
dragState.endPosition = dragState.startPosition;
|
||||
dragState.endPosition = dragState.lastPosition;
|
||||
}
|
||||
|
||||
dragState.totalDistance = distance;
|
||||
@@ -1326,13 +1330,13 @@ export const areaActions = {
|
||||
/**
|
||||
* 开始Area拖拽
|
||||
* @param {string} areaId - Area ID
|
||||
* @param {Event} event - 拖拽事件
|
||||
* @param {Object} position - 鼠标位置
|
||||
* @param {string} source - 拖拽源
|
||||
*/
|
||||
startDrag: (areaId, event, source = 'direct') => {
|
||||
startDrag: (areaId, position, source = 'direct') => {
|
||||
eventBus.emit(EVENT_TYPES.AREA_DRAG_START, {
|
||||
areaId,
|
||||
event,
|
||||
position,
|
||||
source,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
@@ -1341,12 +1345,12 @@ export const areaActions = {
|
||||
/**
|
||||
* Area拖拽移动
|
||||
* @param {string} areaId - Area ID
|
||||
* @param {Event} event - 拖拽事件
|
||||
* @param {Object} position - 鼠标位置
|
||||
*/
|
||||
moveDrag: (areaId, event) => {
|
||||
moveDrag: (areaId, position) => {
|
||||
eventBus.emit(EVENT_TYPES.AREA_DRAG_MOVE, {
|
||||
areaId,
|
||||
event,
|
||||
position,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
},
|
||||
@@ -1354,12 +1358,12 @@ export const areaActions = {
|
||||
/**
|
||||
* 结束Area拖拽
|
||||
* @param {string} areaId - Area ID
|
||||
* @param {Event} event - 拖拽事件
|
||||
* @param {Object} [finalPosition] - 最终鼠标位置
|
||||
*/
|
||||
endDrag: (areaId, event) => {
|
||||
endDrag: (areaId, finalPosition) => {
|
||||
eventBus.emit(EVENT_TYPES.AREA_DRAG_END, {
|
||||
areaId,
|
||||
event,
|
||||
finalPosition,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
},
|
||||
@@ -1537,27 +1541,27 @@ export const triggerAreaDrag = {
|
||||
/**
|
||||
* 开始Area拖拽
|
||||
* @param {string} areaId - Area ID
|
||||
* @param {Event} event - 拖拽事件
|
||||
* @param {Object} position - 鼠标位置
|
||||
*/
|
||||
start: (areaId, event) => {
|
||||
areaActions.startDrag(areaId, event, 'direct');
|
||||
start: (areaId, position) => {
|
||||
areaActions.startDrag(areaId, position, 'direct');
|
||||
},
|
||||
|
||||
/**
|
||||
* 处理Area拖拽移动
|
||||
* @param {string} areaId - Area ID
|
||||
* @param {Event} event - 拖拽事件
|
||||
* @param {Object} position - 鼠标位置
|
||||
*/
|
||||
move: (areaId, event) => {
|
||||
areaActions.moveDrag(areaId, event);
|
||||
move: (areaId, position) => {
|
||||
areaActions.moveDrag(areaId, position);
|
||||
},
|
||||
|
||||
/**
|
||||
* 结束Area拖拽
|
||||
* @param {string} areaId - Area ID
|
||||
* @param {Event} event - 拖拽事件
|
||||
* @param {Object} [finalPosition] - 最终鼠标位置
|
||||
*/
|
||||
end: (areaId, event) => {
|
||||
areaActions.endDrag(areaId, event);
|
||||
end: (areaId, finalPosition) => {
|
||||
areaActions.endDrag(areaId, finalPosition);
|
||||
}
|
||||
};
|
||||
@@ -65,6 +65,7 @@ class DragState {
|
||||
this.status = 'pending'; // pending, active, completed, cancelled, error
|
||||
this.currentPosition = { x: 0, y: 0 };
|
||||
this.startPosition = { x: 0, y: 0 };
|
||||
this.lastPosition = { x: 0, y: 0 }; // 添加lastPosition用于计算delta
|
||||
this.targetElement = null;
|
||||
this.targetArea = null;
|
||||
this.dragVector = { x: 0, y: 0 };
|
||||
@@ -108,13 +109,14 @@ class DragState {
|
||||
const deltaTime = timestamp - this.lastUpdateTime;
|
||||
|
||||
// 更新位置
|
||||
this.lastPosition = { ...this.currentPosition }; // 保存上一个位置
|
||||
this.currentPosition = { x, y };
|
||||
this.lastUpdateTime = timestamp;
|
||||
|
||||
// 计算拖拽向量
|
||||
// 计算拖拽向量(使用上一个位置计算delta,而不是startPosition)
|
||||
this.dragVector = {
|
||||
x: x - this.startPosition.x,
|
||||
y: y - this.startPosition.y
|
||||
x: x - this.lastPosition.x,
|
||||
y: y - this.lastPosition.y
|
||||
};
|
||||
|
||||
// 计算速度(像素/毫秒)
|
||||
@@ -671,13 +673,13 @@ class DragStateManager {
|
||||
case EVENT_TYPES.PANEL_DRAG_END:
|
||||
case EVENT_TYPES.TABPAGE_DRAG_END:
|
||||
case EVENT_TYPES.AREA_DRAG_END:
|
||||
await this._handleDragEnd(dragData);
|
||||
await this._handleDragEnd({ ...dragData, eventType });
|
||||
break;
|
||||
|
||||
case EVENT_TYPES.PANEL_DRAG_CANCEL:
|
||||
case EVENT_TYPES.TABPAGE_DRAG_CANCEL:
|
||||
case EVENT_TYPES.AREA_DRAG_CANCEL:
|
||||
await this._handleDragCancel(dragData);
|
||||
await this._handleDragCancel({ ...dragData, eventType });
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -713,13 +715,19 @@ class DragStateManager {
|
||||
|
||||
// 如果是同一个拖拽操作,更新组件类型和位置
|
||||
if (existingDragState && existingDragState.status === 'active') {
|
||||
// 只有在组件类型不同时才更新
|
||||
if (existingDragState.componentType !== componentType) {
|
||||
existingDragState.componentType = componentType;
|
||||
console.log(`🔄 更新拖拽状态组件类型: ${actualDragId} 从 ${existingDragState.componentType} 到 ${componentType}`);
|
||||
// 保存旧的组件类型用于日志
|
||||
const oldComponentType = existingDragState.componentType;
|
||||
|
||||
// 更新组件类型
|
||||
existingDragState.componentType = componentType;
|
||||
|
||||
// 如果组件类型发生变化,记录日志
|
||||
if (oldComponentType !== componentType) {
|
||||
console.log(`🔄 更新拖拽状态组件类型: ${actualDragId} 从 ${oldComponentType} 到 ${componentType}`);
|
||||
}
|
||||
|
||||
// 如果提供了新位置,更新位置信息
|
||||
// 如果提供了新位置,只更新currentPosition,不更新startPosition
|
||||
// startPosition只在拖拽开始时设置,确保delta计算正确
|
||||
if (position) {
|
||||
existingDragState.currentPosition = { ...position };
|
||||
}
|
||||
@@ -774,12 +782,46 @@ class DragStateManager {
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleDragMove(data) {
|
||||
const { dragId, position, targetElement, targetArea } = data;
|
||||
const dragState = this.activeDrags.get(dragId);
|
||||
const { dragId, position, targetElement, targetArea, componentType, eventType } = data;
|
||||
let dragState = this.activeDrags.get(dragId);
|
||||
|
||||
// 改进:如果没有找到拖拽状态,尝试从事件类型和数据中重新创建或查找
|
||||
if (!dragState || dragState.status !== 'active') {
|
||||
console.warn(`⚠️ 未找到活跃的拖拽状态: ${dragId}`);
|
||||
return;
|
||||
// 1. 检查是否有其他活跃的拖拽状态
|
||||
if (this.activeDrags.size > 0) {
|
||||
// 如果只有一个活跃拖拽,使用它
|
||||
if (this.activeDrags.size === 1) {
|
||||
dragState = Array.from(this.activeDrags.values())[0];
|
||||
console.log(`🔄 使用唯一的活跃拖拽状态: ${dragState.dragId}`);
|
||||
} else {
|
||||
// 2. 根据组件类型查找合适的拖拽状态
|
||||
const dragsOfType = Array.from(this.activeDrags.values())
|
||||
.filter(ds => ds.status === 'active' && ds.componentType === componentType);
|
||||
|
||||
if (dragsOfType.length > 0) {
|
||||
dragState = dragsOfType[0];
|
||||
console.log(`🔄 使用同类型的活跃拖拽状态: ${dragState.dragId}`);
|
||||
} else {
|
||||
// 3. 如果是区域拖拽事件,直接创建新的拖拽状态
|
||||
if (eventType && eventType.includes('area.')) {
|
||||
const newDragId = dragId || `area_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
||||
dragState = new DragState(newDragId, 'area');
|
||||
dragState.status = 'active';
|
||||
dragState.startPosition = { ...position };
|
||||
dragState.currentPosition = { ...position };
|
||||
dragState.lastPosition = { ...position };
|
||||
this.activeDrags.set(newDragId, dragState);
|
||||
console.log(`🆕 创建新的区域拖拽状态: ${newDragId}`);
|
||||
} else {
|
||||
console.warn(`⚠️ 未找到活跃的拖拽状态: ${dragId},事件类型: ${eventType}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn(`⚠️ 没有活跃的拖拽状态,忽略拖拽移动事件: ${dragId}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新位置
|
||||
@@ -833,11 +875,17 @@ class DragStateManager {
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleDragEnd(data) {
|
||||
const { dragId, finalPosition, dropTarget, success = true } = data;
|
||||
const dragState = this.activeDrags.get(dragId);
|
||||
const { dragId, finalPosition, dropTarget, success = true, eventType } = data;
|
||||
|
||||
// 检查拖拽状态是否存在
|
||||
let dragState = this.activeDrags.get(dragId);
|
||||
|
||||
// 如果拖拽状态不存在,可能是已经处理过了,直接返回
|
||||
if (!dragState) {
|
||||
console.warn(`⚠️ 未找到拖拽状态: ${dragId}`);
|
||||
// 检查事件类型,只对area.drag.end事件发出警告
|
||||
if (eventType !== 'area.drag.end') {
|
||||
console.warn(`⚠️ 未找到拖拽状态: ${dragId}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -886,11 +934,14 @@ class DragStateManager {
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleDragCancel(data) {
|
||||
const { dragId, reason } = data;
|
||||
const { dragId, reason, eventType } = data;
|
||||
const dragState = this.activeDrags.get(dragId);
|
||||
|
||||
if (!dragState) {
|
||||
console.warn(`⚠️ 未找到拖拽状态: ${dragId}`);
|
||||
// 检查事件类型,只对非area.drag.cancel事件发出警告
|
||||
if (eventType !== 'area.drag.cancel') {
|
||||
console.warn(`⚠️ 未找到拖拽状态: ${dragId}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* 统一管理所有事件处理器,提供事件路由、分发、监控和调试功能
|
||||
*/
|
||||
|
||||
import { eventBus } from '../eventBus';
|
||||
import { eventBus, EVENT_TYPES } from '../eventBus';
|
||||
|
||||
// 全局事件类型常量
|
||||
export const GLOBAL_EVENT_TYPES = {
|
||||
@@ -20,6 +20,10 @@ export const GLOBAL_EVENT_TYPES = {
|
||||
EVENT_ROUTE_ERROR: 'event.route.error',
|
||||
EVENT_ROUTE_FALLBACK: 'event.route.fallback',
|
||||
|
||||
// 事件升降模式
|
||||
EVENT_RISING: 'event.rising', // 上升事件:用户触发的原始事件
|
||||
EVENT_FALLING: 'event.falling', // 下降事件:事件中心处理后的执行事件
|
||||
|
||||
// 跨组件通信
|
||||
CROSS_COMPONENT_BROADCAST: 'cross.component.broadcast',
|
||||
CROSS_COMPONENT_REQUEST: 'cross.component.request',
|
||||
@@ -259,6 +263,33 @@ class GlobalEventManager {
|
||||
this._cleanupExpiredData = this._cleanupExpiredData.bind(this);
|
||||
|
||||
GlobalEventManager.instance = this;
|
||||
|
||||
// 同步初始化,确保事件监听器被正确注册
|
||||
this._initializeSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步初始化事件管理器
|
||||
*/
|
||||
_initializeSync() {
|
||||
if (this.isInitialized) {
|
||||
console.warn('⚠️ 全局事件管理器已初始化,跳过重复初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
this.eventRoutes = new Map();
|
||||
|
||||
this._registerGlobalEventListeners();
|
||||
this._startCleanupScheduler();
|
||||
this._startDebugMode();
|
||||
|
||||
this.isInitialized = true;
|
||||
console.log('✅ 全局事件管理器初始化完成');
|
||||
|
||||
eventBus.emit(GLOBAL_EVENT_TYPES.SYSTEM_READY, {
|
||||
manager: 'globalEventManager',
|
||||
timestamp: Date.now()
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,11 +360,327 @@ class GlobalEventManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// 注册所有上升事件监听器
|
||||
// 使用EVENT_TYPES常量确保事件类型匹配
|
||||
const risingEvents = [
|
||||
// 面板拖拽上升事件
|
||||
EVENT_TYPES.PANEL_DRAG_START,
|
||||
EVENT_TYPES.PANEL_DRAG_MOVE,
|
||||
EVENT_TYPES.PANEL_DRAG_END,
|
||||
EVENT_TYPES.PANEL_DRAG_CANCEL,
|
||||
// 区域拖拽上升事件
|
||||
EVENT_TYPES.AREA_DRAG_START,
|
||||
EVENT_TYPES.AREA_DRAG_MOVE,
|
||||
EVENT_TYPES.AREA_DRAG_END,
|
||||
EVENT_TYPES.AREA_DRAG_CANCEL,
|
||||
// TabPage拖拽上升事件
|
||||
EVENT_TYPES.TABPAGE_DRAG_START,
|
||||
EVENT_TYPES.TABPAGE_DRAG_MOVE,
|
||||
EVENT_TYPES.TABPAGE_DRAG_END,
|
||||
EVENT_TYPES.TABPAGE_DRAG_CANCEL
|
||||
];
|
||||
|
||||
// 注册上升事件监听器,统一由_handleRisingEvent处理
|
||||
risingEvents.forEach(eventType => {
|
||||
const unsubscribe = eventBus.on(eventType, this._handleRisingEvent.bind(this), {
|
||||
priority: 0, // 最高优先级
|
||||
componentId: 'global-event-manager'
|
||||
});
|
||||
this.eventListenerUnsubscribers.push(unsubscribe);
|
||||
});
|
||||
|
||||
this.componentListenersRegistered = true;
|
||||
|
||||
console.log('✅ 组件事件监听器注册完成(Handler自行订阅事件)');
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理上升事件(用户触发的原始事件)
|
||||
* @param {Object} data - 事件数据
|
||||
* @param {Object} event - 完整的事件对象
|
||||
*/
|
||||
async _handleRisingEvent(data, event) {
|
||||
// 从事件对象中获取事件类型
|
||||
const eventType = event.type;
|
||||
|
||||
try {
|
||||
// 总是输出日志,便于调试
|
||||
console.log(`📈 收到上升事件: ${eventType}`, { data });
|
||||
|
||||
// 根据事件类型分发到不同的处理方法
|
||||
switch (eventType) {
|
||||
// 面板拖拽事件
|
||||
case 'panel.drag.start':
|
||||
await this._handlePanelDragStart(data);
|
||||
break;
|
||||
case 'panel.drag.move':
|
||||
await this._handlePanelDragMove(data);
|
||||
break;
|
||||
case 'panel.drag.end':
|
||||
await this._handlePanelDragEnd(data);
|
||||
break;
|
||||
case 'panel.drag.cancel':
|
||||
await this._handlePanelDragCancel(data);
|
||||
break;
|
||||
// 区域拖拽事件
|
||||
case 'area.drag.start':
|
||||
await this._handleAreaDragStart(data);
|
||||
break;
|
||||
case 'area.drag.move':
|
||||
await this._handleAreaDragMove(data);
|
||||
break;
|
||||
case 'area.drag.end':
|
||||
await this._handleAreaDragEnd(data);
|
||||
break;
|
||||
case 'area.drag.cancel':
|
||||
await this._handleAreaDragCancel(data);
|
||||
break;
|
||||
// 默认处理
|
||||
default:
|
||||
console.log(`🌐 全局事件: ${eventType}`, data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ 上升事件处理错误 (${eventType}):`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否应该操作区域而非面板
|
||||
* 当只有一个面板时,操作区域而不是面板
|
||||
* @param {Object} data - 事件数据
|
||||
* @returns {boolean} 是否应该操作区域
|
||||
*/
|
||||
_shouldOperateAreaInsteadOfPanel(data) {
|
||||
const { panelId, areaId, layout } = data;
|
||||
|
||||
console.log(`🔍 检查单面板模式: areaId=${areaId}, panelId=${panelId}`);
|
||||
console.log(` layout信息: ${layout ? '提供' : '未提供'}`);
|
||||
|
||||
// 如果没有提供layout信息,默认返回false
|
||||
if (!layout) {
|
||||
console.log('❌ 没有提供layout信息,返回false');
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log(` 所有区域数量: ${layout.areas?.length || 0}`);
|
||||
|
||||
// 获取当前区域
|
||||
const area = layout.areas?.find(a => a.id === areaId);
|
||||
if (!area) {
|
||||
console.log(`❌ 找不到区域: ${areaId},返回false`);
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log(` 找到区域: ${areaId}, 类型: ${area.type}`);
|
||||
|
||||
// 修复:检查area.children而非area.panels,统计Panel数量
|
||||
let panelCount = 0;
|
||||
|
||||
// 遍历所有children,统计Panel数量
|
||||
const childrenArray = Array.isArray(area.children) ? area.children : [area.children];
|
||||
console.log(` 区域children数量: ${childrenArray.length}`);
|
||||
|
||||
for (const child of childrenArray) {
|
||||
console.log(` 检查child: 类型=${child.type}, 有children=${!!child.children}`);
|
||||
if (child.type === 'TabPage' && child.children) {
|
||||
const tabChildrenArray = Array.isArray(child.children) ? child.children : [child.children];
|
||||
console.log(` TabPage children数量: ${tabChildrenArray.length}`);
|
||||
|
||||
for (const tabChild of tabChildrenArray) {
|
||||
console.log(` 检查TabPage child: 类型=${tabChild.type}, id=${tabChild.id || 'unknown'}`);
|
||||
if (tabChild.type === 'Panel') {
|
||||
panelCount++;
|
||||
console.log(`✅ 找到Panel: ${tabChild.id || 'unknown'}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`📊 区域${areaId}的Panel数量: ${panelCount}`);
|
||||
|
||||
// 如果区域中只有一个面板,返回true
|
||||
const result = panelCount === 1;
|
||||
console.log(`✅ 单面板检测结果: ${result}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理面板拖拽开始事件
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handlePanelDragStart(data) {
|
||||
if (this.debugMode) {
|
||||
console.log('👋 处理面板拖拽开始:', data);
|
||||
}
|
||||
|
||||
// 检查是否应该操作区域而非面板
|
||||
const shouldOperateArea = this._shouldOperateAreaInsteadOfPanel(data);
|
||||
|
||||
if (shouldOperateArea) {
|
||||
// 转换为区域拖拽事件
|
||||
const areaDragStartData = {
|
||||
...data,
|
||||
eventType: 'area.drag.start',
|
||||
dragId: data.dragId || `area_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`
|
||||
};
|
||||
|
||||
// 发送区域拖拽开始事件
|
||||
eventBus.emit('area.drag.start', areaDragStartData);
|
||||
} else {
|
||||
// 发送面板拖拽状态更新事件(下降事件)
|
||||
eventBus.emit('panel.drag.state.update', {
|
||||
...data,
|
||||
status: 'active'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理面板拖拽移动事件
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handlePanelDragMove(data) {
|
||||
if (this.debugMode) {
|
||||
console.log('✋ 处理面板拖拽移动:', data);
|
||||
}
|
||||
|
||||
// 检查是否应该操作区域而非面板
|
||||
const shouldOperateArea = this._shouldOperateAreaInsteadOfPanel(data);
|
||||
|
||||
if (shouldOperateArea) {
|
||||
// 转换为区域拖拽移动事件
|
||||
const areaDragMoveData = {
|
||||
...data,
|
||||
eventType: 'area.drag.move'
|
||||
};
|
||||
|
||||
// 发送区域拖拽移动事件
|
||||
eventBus.emit('area.drag.move', areaDragMoveData);
|
||||
} else {
|
||||
// 发送面板拖拽状态更新事件(下降事件)
|
||||
eventBus.emit('panel.drag.state.update', {
|
||||
...data,
|
||||
status: 'moving'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理面板拖拽结束事件
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handlePanelDragEnd(data) {
|
||||
if (this.debugMode) {
|
||||
console.log('✋ 处理面板拖拽结束:', data);
|
||||
}
|
||||
|
||||
// 检查是否应该操作区域而非面板
|
||||
const shouldOperateArea = this._shouldOperateAreaInsteadOfPanel(data);
|
||||
|
||||
if (shouldOperateArea) {
|
||||
// 转换为区域拖拽结束事件
|
||||
const areaDragEndData = {
|
||||
...data,
|
||||
eventType: 'area.drag.end'
|
||||
};
|
||||
|
||||
// 发送区域拖拽结束事件
|
||||
eventBus.emit('area.drag.end', areaDragEndData);
|
||||
} else {
|
||||
// 发送面板拖拽状态更新事件(下降事件)
|
||||
eventBus.emit('panel.drag.state.update', {
|
||||
...data,
|
||||
status: 'ended'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理面板拖拽取消事件
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handlePanelDragCancel(data) {
|
||||
if (this.debugMode) {
|
||||
console.log('✋ 处理面板拖拽取消:', data);
|
||||
}
|
||||
|
||||
// 发送面板拖拽状态更新事件(下降事件)
|
||||
eventBus.emit('panel.drag.state.update', {
|
||||
...data,
|
||||
status: 'cancelled'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理区域拖拽开始事件
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleAreaDragStart(data) {
|
||||
if (this.debugMode) {
|
||||
console.log('👋 处理区域拖拽开始:', data);
|
||||
}
|
||||
|
||||
// 发送区域拖拽状态更新事件(下降事件)
|
||||
eventBus.emit('area.drag.state.update', {
|
||||
...data,
|
||||
status: 'active'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理区域拖拽移动事件
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleAreaDragMove(data) {
|
||||
if (this.debugMode) {
|
||||
console.log('✋ 处理区域拖拽移动:', data);
|
||||
}
|
||||
|
||||
// 发送区域拖拽状态更新事件(下降事件)
|
||||
eventBus.emit('area.drag.state.update', {
|
||||
...data,
|
||||
status: 'moving'
|
||||
});
|
||||
|
||||
// 发送区域位置更新事件(下降事件)
|
||||
eventBus.emit('area.position.update', {
|
||||
...data,
|
||||
position: data.position
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理区域拖拽结束事件
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleAreaDragEnd(data) {
|
||||
if (this.debugMode) {
|
||||
console.log('✋ 处理区域拖拽结束:', data);
|
||||
}
|
||||
|
||||
// 发送区域拖拽状态更新事件(下降事件)
|
||||
eventBus.emit('area.drag.state.update', {
|
||||
...data,
|
||||
status: 'ended'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理区域拖拽取消事件
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleAreaDragCancel(data) {
|
||||
if (this.debugMode) {
|
||||
console.log('✋ 处理区域拖拽取消:', data);
|
||||
}
|
||||
|
||||
// 发送区域拖拽状态更新事件(下降事件)
|
||||
eventBus.emit('area.drag.state.update', {
|
||||
...data,
|
||||
status: 'cancelled'
|
||||
});
|
||||
}
|
||||
|
||||
async _onGlobalEvent(data) {
|
||||
const eventType = data.eventType;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user