使用全局事件总线
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
ref="areaRef"
|
||||
class="vs-area select-none"
|
||||
:class="{ 'is-maximized': isMaximized, 'is-normal': !isMaximized }"
|
||||
:style="areaStyle"
|
||||
@@ -133,7 +134,7 @@
|
||||
|
||||
<script setup>
|
||||
import { defineProps, computed, ref, onMounted, onUnmounted, watch, defineExpose } from 'vue'
|
||||
import { emitEvent, EVENT_TYPES } from './eventBus.js'
|
||||
import { emitEvent, EVENT_TYPES, globalEventListenerManager } from './eventBus.js'
|
||||
import TabPage from './TabPage.vue'
|
||||
import Panel from './Panel.vue'
|
||||
import { zIndexManager, Z_INDEX_LAYERS } from './dockLayers.js'
|
||||
@@ -155,6 +156,8 @@ const props = defineProps({
|
||||
draggable: { type: Boolean, default: true }
|
||||
})
|
||||
|
||||
// 使用全局事件总线和拖拽管理器
|
||||
|
||||
// 本地状态
|
||||
const localState = ref(props.windowState)
|
||||
// 保存原始位置和大小信息
|
||||
@@ -170,6 +173,9 @@ const maximizedFromPosition = ref(null)
|
||||
// 存储接收到的外部Area内容
|
||||
const receivedContent = ref([])
|
||||
|
||||
// 组件引用
|
||||
const areaRef = ref(null)
|
||||
|
||||
// 拖拽相关状态
|
||||
const isDragging = ref(false)
|
||||
const dragStartPos = ref({ x: 0, y: 0 })
|
||||
@@ -301,18 +307,21 @@ const onDragStart = (e) => {
|
||||
y: originalPosition.value.top || 0
|
||||
}
|
||||
|
||||
// 通知父组件拖拽开始
|
||||
// 使用事件总线通知拖拽开始
|
||||
emitEvent(EVENT_TYPES.AREA_DRAG_START, {
|
||||
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
|
||||
})
|
||||
|
||||
// 添加全局事件监听
|
||||
document.addEventListener('mousemove', onDragMove)
|
||||
document.addEventListener('mouseup', onDragEnd)
|
||||
// 使用全局事件管理器添加事件监听
|
||||
globalEventListenerManager.addGlobalListener('mousemove', onDragMove)
|
||||
globalEventListenerManager.addGlobalListener('mouseup', onDragEnd)
|
||||
|
||||
// 防止文本选择
|
||||
e.preventDefault()
|
||||
@@ -345,32 +354,39 @@ const onDragMove = (e) => {
|
||||
originalPosition.value.left = newLeft
|
||||
originalPosition.value.top = newTop
|
||||
|
||||
// 通知父组件拖拽移动
|
||||
// 使用事件总线通知拖拽移动
|
||||
emitEvent(EVENT_TYPES.AREA_DRAG_MOVE, {
|
||||
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
|
||||
})
|
||||
|
||||
// 通知父组件位置变化
|
||||
// 使用事件总线通知位置变化
|
||||
emitEvent(EVENT_TYPES.AREA_POSITION_UPDATE, { areaId: props.id, left: newLeft, top: newTop })
|
||||
}
|
||||
|
||||
// 拖拽结束
|
||||
const onDragEnd = () => {
|
||||
// 通知父组件拖拽结束
|
||||
// 使用事件总线通知拖拽结束
|
||||
emitEvent(EVENT_TYPES.AREA_DRAG_END, {
|
||||
areaId: props.id,
|
||||
finalPosition: {
|
||||
x: originalPosition.value.left,
|
||||
y: originalPosition.value.top
|
||||
},
|
||||
left: originalPosition.value.left,
|
||||
top: originalPosition.value.top
|
||||
})
|
||||
|
||||
isDragging.value = false
|
||||
// 移除全局事件监听
|
||||
document.removeEventListener('mousemove', onDragMove)
|
||||
document.removeEventListener('mouseup', onDragEnd)
|
||||
// 使用全局事件管理器移除事件监听
|
||||
globalEventListenerManager.removeGlobalListener('mousemove', onDragMove)
|
||||
globalEventListenerManager.removeGlobalListener('mouseup', onDragEnd)
|
||||
}
|
||||
|
||||
// 调整大小开始
|
||||
@@ -392,10 +408,10 @@ const onResizeStart = (direction, e) => {
|
||||
top: originalPosition.value.top
|
||||
}
|
||||
|
||||
// 添加全局事件监听
|
||||
document.addEventListener('mousemove', onResizeMove)
|
||||
document.addEventListener('mouseup', onResizeEnd)
|
||||
document.addEventListener('mouseleave', onResizeEnd)
|
||||
// 使用全局事件管理器添加事件监听
|
||||
globalEventListenerManager.addGlobalListener('mousemove', onResizeMove)
|
||||
globalEventListenerManager.addGlobalListener('mouseup', onResizeEnd)
|
||||
globalEventListenerManager.addGlobalListener('mouseleave', onResizeEnd)
|
||||
|
||||
// 防止文本选择
|
||||
e.preventDefault()
|
||||
@@ -486,7 +502,7 @@ const onResizeStart = (direction, e) => {
|
||||
originalPosition.value.left = newLeft
|
||||
originalPosition.value.top = newTop
|
||||
|
||||
// 通知父组件位置变化
|
||||
// 使用事件总线通知位置变化
|
||||
emitEvent(EVENT_TYPES.AREA_POSITION_UPDATE, {
|
||||
areaId: props.id,
|
||||
left: newLeft,
|
||||
@@ -501,10 +517,10 @@ const onResizeStart = (direction, e) => {
|
||||
const onResizeEnd = () => {
|
||||
isResizing.value = false
|
||||
resizeDirection.value = null
|
||||
// 移除全局事件监听
|
||||
document.removeEventListener('mousemove', onResizeMove)
|
||||
document.removeEventListener('mouseup', onResizeEnd)
|
||||
document.removeEventListener('mouseleave', onResizeEnd)
|
||||
// 使用全局事件管理器移除事件监听
|
||||
globalEventListenerManager.removeGlobalListener('mousemove', onResizeMove)
|
||||
globalEventListenerManager.removeGlobalListener('mouseup', onResizeEnd)
|
||||
globalEventListenerManager.removeGlobalListener('mouseleave', onResizeEnd)
|
||||
}
|
||||
|
||||
const onToggleMaximize = () => {
|
||||
@@ -580,13 +596,13 @@ onMounted(() => {
|
||||
// 组件卸载时清理全局事件监听器
|
||||
onUnmounted(() => {
|
||||
// 清理拖拽相关的全局事件监听器
|
||||
document.removeEventListener('mousemove', onDragMove)
|
||||
document.removeEventListener('mouseup', onDragEnd)
|
||||
globalEventListenerManager.removeGlobalListener('mousemove', onDragMove)
|
||||
globalEventListenerManager.removeGlobalListener('mouseup', onDragEnd)
|
||||
|
||||
// 清理调整大小相关的全局事件监听器
|
||||
document.removeEventListener('mousemove', onResizeMove)
|
||||
document.removeEventListener('mouseup', onResizeEnd)
|
||||
document.removeEventListener('mouseleave', onResizeEnd)
|
||||
globalEventListenerManager.removeGlobalListener('mousemove', onResizeMove)
|
||||
globalEventListenerManager.removeGlobalListener('mouseup', onResizeEnd)
|
||||
globalEventListenerManager.removeGlobalListener('mouseleave', onResizeEnd)
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -118,11 +118,11 @@ const onPanelDragEnd = () => {
|
||||
};
|
||||
|
||||
const onPanelDragStartFromTabPage = (event) => {
|
||||
dragStateActions.onPanelDragStartFromTabPage(event.areaId, event);
|
||||
dragStateActions.onPanelDragStartFromTabPage(event);
|
||||
};
|
||||
|
||||
const onPanelDragMoveFromTabPage = (event) => {
|
||||
dragStateActions.onPanelDragMoveFromTabPage(event.areaId, event);
|
||||
dragStateActions.onPanelDragMoveFromTabPage(event);
|
||||
};
|
||||
|
||||
const onPanelDragEndFromTabPage = () => {
|
||||
@@ -130,23 +130,23 @@ const onPanelDragEndFromTabPage = () => {
|
||||
};
|
||||
|
||||
const onAreaDragStart = (event) => {
|
||||
dragStateActions.onAreaDragStart(event.areaId, event);
|
||||
dragStateActions.onAreaDragStart(event);
|
||||
};
|
||||
|
||||
const onAreaDragMove = (event) => {
|
||||
dragStateActions.onAreaDragMove(event.areaId, event);
|
||||
dragStateActions.onAreaDragMove(event);
|
||||
};
|
||||
|
||||
const onAreaDragEnd = (event) => {
|
||||
dragStateActions.onAreaDragEnd(event.areaId, event);
|
||||
dragStateActions.onAreaDragEnd(event);
|
||||
};
|
||||
|
||||
const onTabDragStart = (event) => {
|
||||
dragStateActions.onTabDragStart(event.areaId, event);
|
||||
dragStateActions.onTabDragStart(event);
|
||||
};
|
||||
|
||||
const onTabDragMove = (event) => {
|
||||
dragStateActions.onTabDragMove(event.areaId, event);
|
||||
dragStateActions.onTabDragMove(event);
|
||||
};
|
||||
|
||||
const onTabDragEnd = () => {
|
||||
|
||||
@@ -213,17 +213,10 @@ class PriorityEventQueue {
|
||||
}
|
||||
return priorityMap[priority] || 'UNKNOWN'
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有队列
|
||||
*/
|
||||
clear() {
|
||||
for (const queue of Object.values(this.queues)) {
|
||||
queue.length = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 增强的事件总线类
|
||||
class EnhancedEventBus {
|
||||
constructor() {
|
||||
@@ -1078,4 +1071,110 @@ export const unregisterHandler = (handlerName) => {
|
||||
|
||||
export const getHandlerSnapshot = () => {
|
||||
return handlerRegistry.getSnapshot()
|
||||
}
|
||||
}
|
||||
|
||||
// 全局事件监听管理器
|
||||
class GlobalEventListenerManager {
|
||||
constructor() {
|
||||
this.listeners = new Map()
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加全局事件监听
|
||||
* @param {string} eventType 事件类型
|
||||
* @param {Function} handler 事件处理函数
|
||||
*/
|
||||
addGlobalListener(eventType, handler) {
|
||||
if (!this.listeners.has(eventType)) {
|
||||
this.listeners.set(eventType, new Map())
|
||||
}
|
||||
|
||||
const eventHandlers = this.listeners.get(eventType)
|
||||
const handlerId = handler.toString()
|
||||
|
||||
// 如果是第一次添加这个处理函数,实际添加到文档
|
||||
if (!eventHandlers.has(handlerId)) {
|
||||
document.addEventListener(eventType, handler)
|
||||
eventHandlers.set(handlerId, {
|
||||
handler,
|
||||
count: 0
|
||||
})
|
||||
}
|
||||
|
||||
// 增加这个处理函数的引用计数
|
||||
eventHandlers.get(handlerId).count++
|
||||
return handlerId
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除全局事件监听
|
||||
* @param {string} eventType 事件类型
|
||||
* @param {Function} handler 事件处理函数
|
||||
*/
|
||||
removeGlobalListener(eventType, handler) {
|
||||
if (!this.listeners.has(eventType)) {
|
||||
return false
|
||||
}
|
||||
|
||||
const eventHandlers = this.listeners.get(eventType)
|
||||
const handlerId = handler.toString()
|
||||
|
||||
if (!eventHandlers.has(handlerId)) {
|
||||
return false
|
||||
}
|
||||
|
||||
const handlerInfo = eventHandlers.get(handlerId)
|
||||
|
||||
// 减少这个处理函数的引用计数
|
||||
if (handlerInfo.count > 0) {
|
||||
handlerInfo.count--
|
||||
|
||||
// 如果计数器减到0,实际从文档移除
|
||||
if (handlerInfo.count === 0) {
|
||||
document.removeEventListener(eventType, handler)
|
||||
eventHandlers.delete(handlerId)
|
||||
|
||||
// 如果这个事件类型没有处理函数了,清理该事件类型的映射
|
||||
if (eventHandlers.size === 0) {
|
||||
this.listeners.delete(eventType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全局事件监听统计
|
||||
*/
|
||||
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() {
|
||||
for (const [eventType, eventHandlers] of this.listeners.entries()) {
|
||||
for (const [handlerId, handlerInfo] of eventHandlers.entries()) {
|
||||
document.removeEventListener(eventType, handlerInfo.handler)
|
||||
}
|
||||
}
|
||||
this.listeners.clear()
|
||||
}
|
||||
}
|
||||
|
||||
// 导出全局事件管理器实例
|
||||
export const globalEventListenerManager = new GlobalEventListenerManager()
|
||||
@@ -1572,6 +1572,29 @@ class DragStateManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID或Area ID查找拖拽状态
|
||||
* @private
|
||||
* @param {string} dragId - 拖拽ID
|
||||
* @param {string} areaId - Area ID
|
||||
* @returns {Object|null} 拖拽状态
|
||||
*/
|
||||
_findDragByIdOrAreaId(dragId, areaId) {
|
||||
// 首先尝试通过dragId查找
|
||||
if (dragId && this.activeDrags.has(dragId)) {
|
||||
return { dragId, dragState: this.activeDrags.get(dragId) };
|
||||
}
|
||||
|
||||
// 如果找不到,尝试通过areaId查找
|
||||
for (const [id, dragState] of this.activeDrags.entries()) {
|
||||
if (dragState.options.areaId === areaId) {
|
||||
return { dragId: id, dragState };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测拖拽目标
|
||||
* @private
|
||||
@@ -1624,6 +1647,200 @@ class DragStateManager {
|
||||
this.isEnabled = false;
|
||||
console.log('🗑️ 拖拽状态管理器已销毁');
|
||||
}
|
||||
|
||||
/**
|
||||
* Area拖拽开始
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
onAreaDragStart(eventData) {
|
||||
try {
|
||||
const {
|
||||
event,
|
||||
areaId,
|
||||
element,
|
||||
type = 'area',
|
||||
position = { x: 0, y: 0 },
|
||||
...options
|
||||
} = eventData;
|
||||
|
||||
// 检查是否有其他活跃拖拽
|
||||
if (this.activeDrags.size > 0) {
|
||||
console.warn('检测到其他活跃拖拽,暂停之前的拖拽');
|
||||
this.cancelAllDrags();
|
||||
}
|
||||
|
||||
// 创建拖拽ID
|
||||
const dragId = `area-${areaId}-${Date.now()}`;
|
||||
|
||||
// 创建拖拽状态
|
||||
const dragState = new DragState(dragId, DRAG_AREA_TYPES.AREA, element, {
|
||||
areaId,
|
||||
sourceType: type,
|
||||
...options
|
||||
});
|
||||
|
||||
// 设置起始位置
|
||||
const clientX = event?.clientX || eventData.clientX;
|
||||
const clientY = event?.clientY || eventData.clientY;
|
||||
const startX = position.x || clientX;
|
||||
const startY = position.y || clientY;
|
||||
dragState.startPosition = { x: startX, y: startY };
|
||||
dragState.updatePosition(startX, startY);
|
||||
|
||||
// 设置状态为活跃
|
||||
dragState.status = 'active';
|
||||
this.activeDrags.set(dragId, dragState);
|
||||
|
||||
// 触发拖拽开始事件
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_START, {
|
||||
dragId,
|
||||
dragState: dragState.getSummary(),
|
||||
source: 'onAreaDragStart',
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
console.log(`🎯 区域拖拽开始: ${areaId}, dragId: ${dragId}`);
|
||||
|
||||
return dragId;
|
||||
} catch (error) {
|
||||
console.error('区域拖拽开始时出错:', error);
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_PERFORMANCE_MONITOR, {
|
||||
operation: 'onAreaDragStart',
|
||||
error: error.message,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Area拖拽移动
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
*/
|
||||
onAreaDragMove(eventData) {
|
||||
try {
|
||||
const {
|
||||
event,
|
||||
dragId,
|
||||
areaId,
|
||||
element,
|
||||
type = 'area',
|
||||
position = { x: 0, y: 0 },
|
||||
...options
|
||||
} = eventData;
|
||||
|
||||
// 查找拖拽状态
|
||||
const activeDrag = this._findDragByIdOrAreaId(dragId, areaId);
|
||||
if (!activeDrag) {
|
||||
console.warn('找不到区域拖拽状态:', areaId);
|
||||
return false;
|
||||
}
|
||||
|
||||
const dragState = activeDrag.dragState;
|
||||
if (dragState.status !== 'active') {
|
||||
console.warn('拖拽状态不活跃:', dragId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新位置
|
||||
const clientX = event?.clientX || eventData.clientX;
|
||||
const clientY = event?.clientY || eventData.clientY;
|
||||
const currentX = position.x || clientX;
|
||||
const currentY = position.y || clientY;
|
||||
dragState.updatePosition(currentX, currentY);
|
||||
|
||||
// 检测目标区域
|
||||
const targetElement = this._detectDragTarget(currentX, currentY);
|
||||
if (targetElement) {
|
||||
dragState.setTarget(targetElement.element, targetElement.area);
|
||||
}
|
||||
|
||||
// 触发拖拽移动事件
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_MOVE, {
|
||||
dragId,
|
||||
dragState: dragState.getSummary(),
|
||||
position: { x: currentX, y: currentY },
|
||||
target: targetElement,
|
||||
source: 'onAreaDragMove',
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('区域拖拽移动时出错:', error);
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_PERFORMANCE_MONITOR, {
|
||||
operation: 'onAreaDragMove',
|
||||
error: error.message,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Area拖拽结束
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
*/
|
||||
onAreaDragEnd(eventData) {
|
||||
try {
|
||||
const {
|
||||
event,
|
||||
dragId,
|
||||
areaId,
|
||||
type = 'area',
|
||||
finalPosition = { x: 0, y: 0 },
|
||||
dropTarget,
|
||||
...options
|
||||
} = eventData;
|
||||
|
||||
// 查找拖拽状态
|
||||
const activeDrag = this._findDragByIdOrAreaId(dragId, areaId);
|
||||
if (!activeDrag) {
|
||||
console.warn('找不到区域拖拽状态:', areaId);
|
||||
return false;
|
||||
}
|
||||
|
||||
const dragState = activeDrag.dragState;
|
||||
|
||||
// 更新最终位置
|
||||
const clientX = event?.clientX || eventData.clientX;
|
||||
const clientY = event?.clientY || eventData.clientY;
|
||||
const finalX = finalPosition.x || clientX;
|
||||
const finalY = finalPosition.y || clientY;
|
||||
dragState.updatePosition(finalX, finalY);
|
||||
|
||||
// 设置最终状态
|
||||
dragState.status = 'completed';
|
||||
dragState.setTarget(dropTarget?.element || null, dropTarget?.area || null);
|
||||
|
||||
// 触发拖拽结束事件
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_END, {
|
||||
dragId,
|
||||
dragState: dragState.getSummary(),
|
||||
finalPosition: { x: finalX, y: finalY },
|
||||
dropTarget,
|
||||
source: 'onAreaDragEnd',
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
// 移动到历史记录
|
||||
this.dragHistory.push(dragState.getSummary());
|
||||
this.activeDrags.delete(activeDrag.dragId);
|
||||
|
||||
console.log(`✅ 区域拖拽结束: ${areaId}, dragId: ${dragId}`);
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('区域拖拽结束时出错:', error);
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_PERFORMANCE_MONITOR, {
|
||||
operation: 'onAreaDragEnd',
|
||||
error: error.message,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 延迟创建单例实例
|
||||
@@ -1731,21 +1948,21 @@ export const dragStateActions = {
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
onAreaDragStart: (eventData) => ensureDragStateManagerInstance().onPanelDragStart(eventData),
|
||||
onAreaDragStart: (eventData) => ensureDragStateManagerInstance().onAreaDragStart(eventData),
|
||||
|
||||
/**
|
||||
* Area拖拽移动
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onAreaDragMove: (eventData) => ensureDragStateManagerInstance().onPanelDragMove(eventData),
|
||||
onAreaDragMove: (eventData) => ensureDragStateManagerInstance().onAreaDragMove(eventData),
|
||||
|
||||
/**
|
||||
* Area拖拽结束
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onAreaDragEnd: (eventData) => ensureDragStateManagerInstance().onPanelDragEnd(eventData),
|
||||
onAreaDragEnd: (eventData) => ensureDragStateManagerInstance().onAreaDragEnd(eventData),
|
||||
|
||||
/**
|
||||
* Tab拖拽开始
|
||||
|
||||
Reference in New Issue
Block a user