解决事件泄漏问题
This commit is contained in:
@@ -3,9 +3,9 @@
|
||||
* 专门处理Area相关的所有事件,包括浮动区域管理、拖拽、停靠、合并等
|
||||
*/
|
||||
|
||||
import { eventBus } from '../eventBus';
|
||||
import { eventBus, EVENT_TYPES } from '../eventBus';
|
||||
|
||||
// Area事件类型常量
|
||||
// Area事件类型常量(仅包含EVENT_TYPES中没有的)
|
||||
export const AREA_EVENT_TYPES = {
|
||||
// 基础事件
|
||||
AREA_CREATED: 'area.created',
|
||||
@@ -23,16 +23,8 @@ export const AREA_EVENT_TYPES = {
|
||||
AREA_RESTORE: 'area.restore',
|
||||
AREA_COLLAPSE: 'area.collapse',
|
||||
AREA_EXPAND: 'area.expand',
|
||||
AREA_CLOSE: 'area.close',
|
||||
AREA_TOGGLE_TOOLBAR: 'area.toggleToolbar',
|
||||
|
||||
// 拖拽相关
|
||||
AREA_DRAG_START: 'area.drag.start',
|
||||
AREA_DRAG_MOVE: 'area.drag.move',
|
||||
AREA_DRAG_END: 'area.drag.end',
|
||||
AREA_DRAG_OVER: 'area.drag.over',
|
||||
AREA_DRAG_LEAVE: 'area.drag.leave',
|
||||
|
||||
// 停靠相关
|
||||
AREA_DOCK_CENTER: 'area.dock.center',
|
||||
AREA_DOCK_EDGE: 'area.dock.edge',
|
||||
@@ -759,12 +751,36 @@ class AreaEventHandler {
|
||||
* 注册事件监听器
|
||||
*/
|
||||
_registerEventListeners() {
|
||||
const events = Object.values(AREA_EVENT_TYPES);
|
||||
events.forEach(eventType => {
|
||||
// 监听 EVENT_TYPES 中的事件
|
||||
const eventTypes = [
|
||||
EVENT_TYPES.AREA_DRAG_START,
|
||||
EVENT_TYPES.AREA_DRAG_MOVE,
|
||||
EVENT_TYPES.AREA_DRAG_END,
|
||||
EVENT_TYPES.AREA_DRAG_OVER,
|
||||
EVENT_TYPES.AREA_DRAG_LEAVE,
|
||||
EVENT_TYPES.AREA_CLOSE,
|
||||
EVENT_TYPES.AREA_POSITION_UPDATE,
|
||||
EVENT_TYPES.AREA_PANEL_CLOSED
|
||||
];
|
||||
|
||||
eventTypes.forEach(eventType => {
|
||||
const listener = this._onAreaEvent;
|
||||
eventBus.on(eventType, listener, {
|
||||
priority: 1,
|
||||
deduplication: { type: 'TTL_BASED', ttl: 100 }
|
||||
deduplication: { type: 'TTL_BASED', ttl: 100 },
|
||||
componentId: 'area-handler'
|
||||
});
|
||||
this.areaListeners.set(eventType, listener);
|
||||
});
|
||||
|
||||
// 监听 AREA_EVENT_TYPES 中的事件
|
||||
const areaEventTypes = Object.values(AREA_EVENT_TYPES);
|
||||
areaEventTypes.forEach(eventType => {
|
||||
const listener = this._onAreaEvent;
|
||||
eventBus.on(eventType, listener, {
|
||||
priority: 1,
|
||||
deduplication: { type: 'TTL_BASED', ttl: 100 },
|
||||
componentId: 'area-handler'
|
||||
});
|
||||
this.areaListeners.set(eventType, listener);
|
||||
});
|
||||
@@ -775,17 +791,17 @@ class AreaEventHandler {
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _onAreaEvent(data) {
|
||||
const { eventType } = data;
|
||||
const eventType = data.eventType;
|
||||
|
||||
try {
|
||||
switch (eventType) {
|
||||
case AREA_EVENT_TYPES.AREA_DRAG_START:
|
||||
case EVENT_TYPES.AREA_DRAG_START:
|
||||
await this._handleAreaDragStart(data);
|
||||
break;
|
||||
case AREA_EVENT_TYPES.AREA_DRAG_MOVE:
|
||||
case EVENT_TYPES.AREA_DRAG_MOVE:
|
||||
await this._handleAreaDragMove(data);
|
||||
break;
|
||||
case AREA_EVENT_TYPES.AREA_DRAG_END:
|
||||
case EVENT_TYPES.AREA_DRAG_END:
|
||||
await this._handleAreaDragEnd(data);
|
||||
break;
|
||||
case AREA_EVENT_TYPES.AREA_DOCK_CENTER:
|
||||
@@ -806,13 +822,15 @@ class AreaEventHandler {
|
||||
case AREA_EVENT_TYPES.AREA_FLOATING_CREATE:
|
||||
await this._handleFloatingAreaCreate(data);
|
||||
break;
|
||||
case AREA_EVENT_TYPES.AREA_ZINDEX_MANAGEMENT:
|
||||
await this._handleAreaZIndexManagement(data);
|
||||
break;
|
||||
default:
|
||||
// 记录其他事件但不处理
|
||||
console.log(`📍 Area事件处理器: ${eventType}`, data);
|
||||
console.log(`📍 Area事件处理器: ${eventType || 'unknown'}`, data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ Area事件处理错误 (${eventType}):`, error);
|
||||
eventBus.recordError(`areaHandler_${eventType}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -884,7 +902,7 @@ class AreaEventHandler {
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleAreaDragEnd(data) {
|
||||
const { areaId, event } = data;
|
||||
const { areaId, event, finalPosition, left, top } = data;
|
||||
const dragState = this.areaStateManager.getDragState(areaId);
|
||||
|
||||
if (!dragState) return;
|
||||
@@ -896,7 +914,18 @@ class AreaEventHandler {
|
||||
// 清理拖拽状态
|
||||
dragState.isDragging = false;
|
||||
dragState.endTime = Date.now();
|
||||
dragState.endPosition = { x: event.clientX, y: event.clientY };
|
||||
|
||||
// 使用 finalPosition 或 left/top 作为结束位置
|
||||
if (finalPosition) {
|
||||
dragState.endPosition = { x: finalPosition.x, y: finalPosition.y };
|
||||
} 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.totalDistance = distance;
|
||||
dragState.duration = dragDuration;
|
||||
|
||||
@@ -1126,6 +1155,50 @@ class AreaEventHandler {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理Area层级管理事件
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _handleAreaZIndexManagement(data) {
|
||||
const { areaId, action, zIndex, reason } = data;
|
||||
|
||||
try {
|
||||
switch (action) {
|
||||
case 'activate':
|
||||
// 激活Area时更新z-index
|
||||
this.activeAreas.add(areaId);
|
||||
this.areaStateManager.updateState(areaId, {
|
||||
lastActivatedAt: Date.now()
|
||||
});
|
||||
break;
|
||||
|
||||
case 'create_floating':
|
||||
// 创建浮动Area时设置z-index
|
||||
if (zIndex) {
|
||||
this.areaStateManager.updateState(areaId, {
|
||||
zIndex,
|
||||
lastActivatedAt: Date.now()
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
// 更新z-index
|
||||
if (zIndex) {
|
||||
this.areaStateManager.updateState(areaId, {
|
||||
zIndex
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log(`📍 Area层级管理: ${action}`, data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ Area层级管理错误 (${action}):`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动内存保护机制
|
||||
*/
|
||||
@@ -1233,6 +1306,12 @@ class AreaEventHandler {
|
||||
// 创建单例实例
|
||||
const areaHandler = new AreaEventHandler();
|
||||
|
||||
/**
|
||||
* 获取Area事件处理器实例
|
||||
* @returns {AreaEventHandler} AreaEventHandler实例
|
||||
*/
|
||||
export const getAreaHandler = () => areaHandler;
|
||||
|
||||
// Area便捷操作函数
|
||||
export const areaActions = {
|
||||
/**
|
||||
|
||||
@@ -495,6 +495,8 @@ class DragStateManager {
|
||||
};
|
||||
this.isEnabled = true;
|
||||
this.debugMode = false;
|
||||
this.eventListenersRegistered = false; // 初始化监听器注册标志
|
||||
this.cleanupScheduler = null; // 初始化清理调度器
|
||||
|
||||
// 绑定方法
|
||||
this._onDragEvent = this._onDragEvent.bind(this);
|
||||
@@ -516,12 +518,24 @@ class DragStateManager {
|
||||
console.log('🎯 拖拽状态管理器初始化完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一的拖拽ID
|
||||
* @param {string} componentType - 组件类型
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
_generateDragId(componentType) {
|
||||
const timestamp = Date.now();
|
||||
const random = Math.random().toString(36).substring(2, 9);
|
||||
return `${componentType}_${timestamp}_${random}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册事件监听器
|
||||
*/
|
||||
_registerEventListeners() {
|
||||
// 防止重复注册监听器
|
||||
if (this.eventListenersRegistered) {
|
||||
console.log('🚫 已经注册了监听器,跳过重复注册');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -537,17 +551,22 @@ class DragStateManager {
|
||||
dragEvents.forEach(eventType => {
|
||||
eventBus.on(eventType, this._onDragEvent, {
|
||||
priority: 1,
|
||||
deduplication: { type: 'EVENT_BASED', key: 'dragState' }
|
||||
deduplication: { type: 'EVENT_BASED', key: 'dragState' },
|
||||
componentId: 'drag-state-manager'
|
||||
});
|
||||
});
|
||||
|
||||
this.eventListenersRegistered = true;
|
||||
console.log('✅ 拖拽管理器事件监听器注册完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁管理器
|
||||
*/
|
||||
destroy() {
|
||||
// 取消所有拖拽
|
||||
this.cancelAllDrags();
|
||||
|
||||
// 清理事件监听器
|
||||
const dragEvents = [
|
||||
// Panel拖拽事件
|
||||
@@ -565,10 +584,17 @@ class DragStateManager {
|
||||
// 清理清理调度器
|
||||
this._stopCleanupScheduler();
|
||||
|
||||
// 清理拖拽状态
|
||||
this.dragStates.clear();
|
||||
// 清理数据
|
||||
this.activeDrags.clear();
|
||||
this.dragHistory = [];
|
||||
this.dragTargets.clear();
|
||||
|
||||
// 清理冲突检测器
|
||||
this.conflictDetector.activeDrags.clear();
|
||||
this.conflictDetector.conflictHistory = [];
|
||||
|
||||
this.isEnabled = false;
|
||||
this.eventListenersRegistered = false;
|
||||
console.log('🗑️ 拖拽状态管理器已销毁');
|
||||
}
|
||||
|
||||
@@ -579,34 +605,66 @@ class DragStateManager {
|
||||
async _onDragEvent(data) {
|
||||
if (!this.isEnabled) return;
|
||||
|
||||
const monitorId = globalEventActions.startMonitor(`drag_${data.eventType || data.type}`);
|
||||
const monitorId = globalEventActions.startMonitor(`drag_${data.eventType}`);
|
||||
|
||||
try {
|
||||
const { eventType = data.type, dragId, componentType, sourceElement } = data;
|
||||
|
||||
// 从事件数据中提取 dragId,如果没有则根据组件类型推断
|
||||
let actualDragId = dragId;
|
||||
if (!actualDragId) {
|
||||
if (data.panelId) {
|
||||
actualDragId = `panel_${data.panelId}_${data.timestamp || Date.now()}`;
|
||||
} else if (data.tabIndex !== undefined) {
|
||||
actualDragId = `tabpage_${data.tabId}_${data.tabIndex}_${data.timestamp || Date.now()}`;
|
||||
} else if (data.areaId) {
|
||||
actualDragId = `area_${data.areaId}_${data.timestamp || Date.now()}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 推断组件类型
|
||||
let actualComponentType = componentType;
|
||||
if (!actualComponentType) {
|
||||
if (data.panelId) {
|
||||
actualComponentType = 'panel';
|
||||
} else if (data.tabIndex !== undefined) {
|
||||
actualComponentType = 'tabpage';
|
||||
} else if (data.areaId) {
|
||||
actualComponentType = 'area';
|
||||
}
|
||||
}
|
||||
|
||||
// 准备标准化的拖拽数据
|
||||
const dragData = {
|
||||
...data,
|
||||
dragId: actualDragId,
|
||||
componentType: actualComponentType,
|
||||
sourceElement: sourceElement || data.element
|
||||
};
|
||||
|
||||
switch (eventType) {
|
||||
case 'panel.drag.start':
|
||||
case 'tabpage.drag.start':
|
||||
case 'area.drag.start':
|
||||
await this._handleDragStart(data);
|
||||
await this._handleDragStart(dragData);
|
||||
break;
|
||||
|
||||
case 'panel.drag.move':
|
||||
case 'tabpage.drag.move':
|
||||
case 'area.drag.move':
|
||||
await this._handleDragMove(data);
|
||||
await this._handleDragMove(dragData);
|
||||
break;
|
||||
|
||||
case 'panel.drag.end':
|
||||
case 'tabpage.drag.end':
|
||||
case 'area.drag.end':
|
||||
await this._handleDragEnd(data);
|
||||
await this._handleDragEnd(dragData);
|
||||
break;
|
||||
|
||||
case 'panel.drag.cancel':
|
||||
case 'tabpage.drag.cancel':
|
||||
case 'area.drag.cancel':
|
||||
await this._handleDragCancel(data);
|
||||
await this._handleDragCancel(dragData);
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -628,28 +686,31 @@ class DragStateManager {
|
||||
async _handleDragStart(data) {
|
||||
const { dragId, componentType, sourceElement, position, options = {} } = data;
|
||||
|
||||
// 如果没有提供 dragId,生成一个唯一的 dragId
|
||||
const actualDragId = dragId || this._generateDragId(componentType);
|
||||
|
||||
// 创建拖拽状态
|
||||
const dragState = new DragState(dragId, componentType, sourceElement, options);
|
||||
const dragState = new DragState(actualDragId, componentType, sourceElement, options);
|
||||
dragState.startPosition = { ...position };
|
||||
dragState.currentPosition = { ...position };
|
||||
dragState.status = 'active';
|
||||
|
||||
// 保存拖拽状态
|
||||
this.activeDrags.set(dragId, dragState);
|
||||
this.activeDrags.set(actualDragId, dragState);
|
||||
|
||||
// 注册到冲突检测器
|
||||
this.conflictDetector.registerDrag(dragState);
|
||||
|
||||
// 触发状态变更事件
|
||||
// 触发状态变更事件,包含 dragId
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_STATE_CHANGE, {
|
||||
dragId,
|
||||
dragId: actualDragId,
|
||||
newStatus: 'active',
|
||||
dragState: dragState.getSummary()
|
||||
});
|
||||
|
||||
// 发送初始反馈
|
||||
if (this.debugMode) {
|
||||
this._updateDragFeedback(dragId, {
|
||||
this._updateDragFeedback(actualDragId, {
|
||||
visible: true,
|
||||
content: `开始拖拽 ${componentType}`,
|
||||
type: 'default',
|
||||
@@ -658,8 +719,10 @@ class DragStateManager {
|
||||
}
|
||||
|
||||
if (this.debugMode) {
|
||||
console.log(`🎯 拖拽开始: ${dragId} (${componentType})`, position);
|
||||
console.log(`🎯 拖拽开始: ${actualDragId} (${componentType})`, position);
|
||||
}
|
||||
|
||||
return actualDragId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -670,7 +733,10 @@ class DragStateManager {
|
||||
const { dragId, position, targetElement, targetArea } = data;
|
||||
const dragState = this.activeDrags.get(dragId);
|
||||
|
||||
if (!dragState || dragState.status !== 'active') return;
|
||||
if (!dragState || dragState.status !== 'active') {
|
||||
console.warn(`⚠️ 未找到活跃的拖拽状态: ${dragId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新位置
|
||||
dragState.updatePosition(position.x, position.y);
|
||||
@@ -726,7 +792,10 @@ class DragStateManager {
|
||||
const { dragId, finalPosition, dropTarget, success = true } = data;
|
||||
const dragState = this.activeDrags.get(dragId);
|
||||
|
||||
if (!dragState) return;
|
||||
if (!dragState) {
|
||||
console.warn(`⚠️ 未找到拖拽状态: ${dragId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 完成拖拽
|
||||
dragState.complete('completed', { success, finalPosition, dropTarget });
|
||||
@@ -743,7 +812,10 @@ class DragStateManager {
|
||||
// 从冲突检测器注销
|
||||
this.conflictDetector.unregisterDrag(dragId);
|
||||
|
||||
// 触发状态变更事件
|
||||
// 清理拖拽目标
|
||||
this.dragTargets.delete(dragId);
|
||||
|
||||
// 触发状态变更事件,包含 dragId
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_STATE_CHANGE, {
|
||||
dragId,
|
||||
newStatus: 'completed',
|
||||
@@ -773,7 +845,10 @@ class DragStateManager {
|
||||
const { dragId, reason } = data;
|
||||
const dragState = this.activeDrags.get(dragId);
|
||||
|
||||
if (!dragState) return;
|
||||
if (!dragState) {
|
||||
console.warn(`⚠️ 未找到拖拽状态: ${dragId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 取消拖拽
|
||||
dragState.complete('cancelled', { reason });
|
||||
@@ -790,7 +865,10 @@ class DragStateManager {
|
||||
// 从冲突检测器注销
|
||||
this.conflictDetector.unregisterDrag(dragId);
|
||||
|
||||
// 触发状态变更事件
|
||||
// 清理拖拽目标
|
||||
this.dragTargets.delete(dragId);
|
||||
|
||||
// 触发状态变更事件,包含 dragId
|
||||
eventBus.emit(DRAG_STATE_TYPES.DRAG_STATE_CHANGE, {
|
||||
dragId,
|
||||
newStatus: 'cancelled',
|
||||
@@ -1024,11 +1102,24 @@ class DragStateManager {
|
||||
* 启动清理调度器
|
||||
*/
|
||||
_startCleanupScheduler() {
|
||||
setInterval(() => {
|
||||
if (this.cleanupScheduler) {
|
||||
return;
|
||||
}
|
||||
this.cleanupScheduler = setInterval(() => {
|
||||
this._cleanupExpiredData();
|
||||
}, 300000); // 每5分钟清理一次
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止清理调度器
|
||||
*/
|
||||
_stopCleanupScheduler() {
|
||||
if (this.cleanupScheduler) {
|
||||
clearInterval(this.cleanupScheduler);
|
||||
this.cleanupScheduler = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理过期数据
|
||||
*/
|
||||
@@ -1663,26 +1754,6 @@ class DragStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁管理器
|
||||
*/
|
||||
destroy() {
|
||||
// 取消所有拖拽
|
||||
this.cancelAllDrags();
|
||||
|
||||
// 清理数据
|
||||
this.activeDrags.clear();
|
||||
this.dragHistory = [];
|
||||
this.dragTargets.clear();
|
||||
|
||||
// 清理冲突检测器
|
||||
this.conflictDetector.activeDrags.clear();
|
||||
this.conflictDetector.conflictHistory = [];
|
||||
|
||||
this.isEnabled = false;
|
||||
console.log('🗑️ 拖拽状态管理器已销毁');
|
||||
}
|
||||
|
||||
/**
|
||||
* Area拖拽开始
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
@@ -1878,18 +1949,8 @@ class DragStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 延迟创建单例实例
|
||||
let dragStateManager = null;
|
||||
|
||||
/**
|
||||
* 确保单例实例存在
|
||||
*/
|
||||
function ensureDragStateManagerInstance() {
|
||||
if (!dragStateManager) {
|
||||
dragStateManager = new DragStateManager();
|
||||
}
|
||||
return dragStateManager;
|
||||
}
|
||||
// 立即创建单例实例,避免并发初始化问题
|
||||
const dragStateManager = new DragStateManager();
|
||||
|
||||
// 便捷操作函数
|
||||
export const dragStateActions = {
|
||||
@@ -1898,150 +1959,153 @@ export const dragStateActions = {
|
||||
* @param {string} dragId - 拖拽ID
|
||||
* @returns {Object} 拖拽状态
|
||||
*/
|
||||
getDragState: (dragId) => ensureDragStateManagerInstance().getDragState(dragId),
|
||||
getDragState: (dragId) => dragStateManager.getDragState(dragId),
|
||||
|
||||
/**
|
||||
* 获取所有活跃拖拽
|
||||
* @returns {Array} 活跃拖拽列表
|
||||
*/
|
||||
getActiveDrags: () => ensureDragStateManagerInstance().getActiveDrags(),
|
||||
getActiveDrags: () => dragStateManager.getActiveDrags(),
|
||||
|
||||
/**
|
||||
* 获取拖拽历史
|
||||
* @param {number} limit - 限制数量
|
||||
* @returns {Array} 历史记录
|
||||
*/
|
||||
getHistory: (limit = 100) => ensureDragStateManagerInstance().getDragHistory(limit),
|
||||
getHistory: (limit = 100) => dragStateManager.getDragHistory(limit),
|
||||
|
||||
/**
|
||||
* 获取统计信息
|
||||
* @returns {Object} 统计信息
|
||||
*/
|
||||
getStats: () => ensureDragStateManagerInstance().getDragStats(),
|
||||
getStats: () => dragStateManager.getDragStats(),
|
||||
|
||||
/**
|
||||
* 设置调试模式
|
||||
* @param {boolean} enabled - 是否启用
|
||||
*/
|
||||
setDebugMode: (enabled) => ensureDragStateManagerInstance().setDebugMode(enabled),
|
||||
setDebugMode: (enabled) => dragStateManager.setDebugMode(enabled),
|
||||
|
||||
/**
|
||||
* 启用/禁用管理器
|
||||
* @param {boolean} enabled - 是否启用
|
||||
*/
|
||||
setEnabled: (enabled) => ensureDragStateManagerInstance().setEnabled(enabled),
|
||||
setEnabled: (enabled) => dragStateManager.setEnabled(enabled),
|
||||
|
||||
/**
|
||||
* 取消所有拖拽
|
||||
*/
|
||||
cancelAll: () => ensureDragStateManagerInstance().cancelAllDrags(),
|
||||
cancelAll: () => dragStateManager.cancelAllDrags(),
|
||||
|
||||
/**
|
||||
* 面板拖拽开始
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
onPanelDragStart: (eventData) => ensureDragStateManagerInstance().onPanelDragStart(eventData),
|
||||
onPanelDragStart: (eventData) => dragStateManager.onPanelDragStart(eventData),
|
||||
|
||||
/**
|
||||
* 面板拖拽移动
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onPanelDragMove: (eventData) => ensureDragStateManagerInstance().onPanelDragMove(eventData),
|
||||
onPanelDragMove: (eventData) => dragStateManager.onPanelDragMove(eventData),
|
||||
|
||||
/**
|
||||
* 面板拖拽结束
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onPanelDragEnd: (eventData) => ensureDragStateManagerInstance().onPanelDragEnd(eventData),
|
||||
onPanelDragEnd: (eventData) => dragStateManager.onPanelDragEnd(eventData),
|
||||
|
||||
/**
|
||||
* TabPage拖拽开始
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
onPanelDragStartFromTabPage: (eventData) => ensureDragStateManagerInstance().onPanelDragStartFromTabPage(eventData),
|
||||
onPanelDragStartFromTabPage: (eventData) => dragStateManager.onPanelDragStartFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* TabPage拖拽移动
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onPanelDragMoveFromTabPage: (eventData) => ensureDragStateManagerInstance().onPanelDragMoveFromTabPage(eventData),
|
||||
onPanelDragMoveFromTabPage: (eventData) => dragStateManager.onPanelDragMoveFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* TabPage拖拽结束
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onPanelDragEndFromTabPage: (eventData) => ensureDragStateManagerInstance().onPanelDragEndFromTabPage(eventData),
|
||||
onPanelDragEndFromTabPage: (eventData) => dragStateManager.onPanelDragEndFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* Area拖拽开始
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
onAreaDragStart: (eventData) => ensureDragStateManagerInstance().onAreaDragStart(eventData),
|
||||
onAreaDragStart: (eventData) => dragStateManager.onAreaDragStart(eventData),
|
||||
|
||||
/**
|
||||
* Area拖拽移动
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onAreaDragMove: (eventData) => ensureDragStateManagerInstance().onAreaDragMove(eventData),
|
||||
onAreaDragMove: (eventData) => dragStateManager.onAreaDragMove(eventData),
|
||||
|
||||
/**
|
||||
* Area拖拽结束
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onAreaDragEnd: (eventData) => ensureDragStateManagerInstance().onAreaDragEnd(eventData),
|
||||
onAreaDragEnd: (eventData) => dragStateManager.onAreaDragEnd(eventData),
|
||||
|
||||
/**
|
||||
* Tab拖拽开始
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {string} 拖拽ID
|
||||
*/
|
||||
onTabDragStart: (eventData) => ensureDragStateManagerInstance().onPanelDragStartFromTabPage(eventData),
|
||||
onTabDragStart: (eventData) => dragStateManager.onPanelDragStartFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* Tab拖拽移动
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onTabDragMove: (eventData) => ensureDragStateManagerInstance().onPanelDragMoveFromTabPage(eventData),
|
||||
onTabDragMove: (eventData) => dragStateManager.onPanelDragMoveFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* Tab拖拽结束
|
||||
* @param {Object} eventData - 拖拽事件数据
|
||||
* @returns {boolean} 是否成功
|
||||
*/
|
||||
onTabDragEnd: (eventData) => ensureDragStateManagerInstance().onPanelDragEndFromTabPage(eventData),
|
||||
onTabDragEnd: (eventData) => dragStateManager.onPanelDragEndFromTabPage(eventData),
|
||||
|
||||
/**
|
||||
* 初始化拖拽管理器
|
||||
*/
|
||||
initialize: () => ensureDragStateManagerInstance(),
|
||||
initialize: () => dragStateManager,
|
||||
|
||||
/**
|
||||
* 销毁拖拽管理器
|
||||
*/
|
||||
destroy: () => {
|
||||
if (dragStateManager) {
|
||||
// 清理拖拽管理器资源
|
||||
dragStateManager.activeDrags.clear();
|
||||
dragStateManager.dragHistory = [];
|
||||
// 清理拖拽管理器资源,先调用实例的destroy方法清理监听器
|
||||
try {
|
||||
dragStateManager.destroy();
|
||||
} catch (e) {
|
||||
console.warn('销毁拖拽状态管理器时出错:', e);
|
||||
}
|
||||
dragStateManager = null;
|
||||
console.log('🗑️ 拖拽状态管理器已销毁,所有资源已清理');
|
||||
console.log('🗑️ 拖拽状态管理器已销毁');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 导出
|
||||
export default {
|
||||
getInstance: ensureDragStateManagerInstance,
|
||||
getInstance: () => dragStateManager,
|
||||
actions: dragStateActions
|
||||
};
|
||||
export { DragState };
|
||||
@@ -140,10 +140,10 @@ class EventBusManager {
|
||||
{ name: 'tabpage', handler: tabPageHandler, events: TABPAGE_EVENT_TYPES },
|
||||
{ name: 'area', handler: areaHandler, events: AREA_EVENT_TYPES },
|
||||
{ name: 'global', handler: globalEventManager, events: GLOBAL_EVENT_TYPES },
|
||||
{ name: 'drag', handler: dragStateManager, events: DRAG_STATE_TYPES }
|
||||
{ name: 'drag', handler: dragStateManager.getInstance(), events: DRAG_STATE_TYPES, skipEventRegistration: true }
|
||||
];
|
||||
|
||||
for (const { name, handler, events } of handlers) {
|
||||
for (const { name, handler, events, skipEventRegistration = false } of handlers) {
|
||||
const handlerConfig = this.config.handlers[name];
|
||||
|
||||
if (!handlerConfig?.enabled) {
|
||||
@@ -154,15 +154,20 @@ class EventBusManager {
|
||||
try {
|
||||
console.log(`📝 注册事件处理器: ${name}`);
|
||||
|
||||
// 注册事件处理器到事件总线
|
||||
Object.values(events).forEach(eventType => {
|
||||
if (typeof handler.handleEvent === 'function') {
|
||||
eventBus.on(eventType, handler.handleEvent.bind(handler), {
|
||||
priority: 1,
|
||||
id: `handler-${name}`
|
||||
});
|
||||
}
|
||||
});
|
||||
// 注册事件处理器到事件总线(除非跳过)
|
||||
if (!skipEventRegistration) {
|
||||
Object.values(events).forEach(eventType => {
|
||||
if (typeof handler.handleEvent === 'function') {
|
||||
eventBus.on(eventType, handler.handleEvent.bind(handler), {
|
||||
priority: 1,
|
||||
id: `handler-${name}`,
|
||||
componentId: `handler-${name}`
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log(`⏭️ 跳过事件监听器注册(内部自动注册): ${name}`);
|
||||
}
|
||||
|
||||
// 调用初始化方法(如果存在)
|
||||
if (typeof handler.initialize === 'function') {
|
||||
@@ -236,7 +241,7 @@ class EventBusManager {
|
||||
routeTime: Date.now()
|
||||
});
|
||||
});
|
||||
}, { id: 'router', priority: 0 });
|
||||
}, { id: 'router', priority: 0, componentId: 'event-router' });
|
||||
});
|
||||
|
||||
console.log(`🔗 设置了 ${routes.length} 个事件路由`);
|
||||
|
||||
@@ -4,13 +4,6 @@
|
||||
*/
|
||||
|
||||
import { eventBus } from '../eventBus';
|
||||
import { PANEL_EVENT_TYPES, panelActions, panelHandler } from './PanelHandler';
|
||||
import tabPageHandlerModule, { TABPAGE_EVENT_TYPES, tabPageActions } from './TabPageHandler';
|
||||
import areaHandlerModule, { AREA_EVENT_TYPES, areaActions } from './AreaHandler';
|
||||
|
||||
// 获取处理器实例
|
||||
const tabPageHandler = tabPageHandlerModule.getInstance ? tabPageHandlerModule.getInstance() : tabPageHandlerModule;
|
||||
const areaHandler = areaHandlerModule;
|
||||
|
||||
// 全局事件类型常量
|
||||
export const GLOBAL_EVENT_TYPES = {
|
||||
@@ -50,59 +43,7 @@ export const GLOBAL_EVENT_TYPES = {
|
||||
DEBUG_MEMORY: 'debug.memory'
|
||||
};
|
||||
|
||||
// 事件路由配置
|
||||
const EVENT_ROUTES = {
|
||||
// Panel事件路由
|
||||
[PANEL_EVENT_TYPES.PANEL_DRAG_START]: {
|
||||
handlers: ['panelHandler', 'areaHandler'],
|
||||
priority: 1,
|
||||
timeout: 5000
|
||||
},
|
||||
[PANEL_EVENT_TYPES.PANEL_MAXIMIZE]: {
|
||||
handlers: ['panelHandler', 'areaHandler'],
|
||||
priority: 1,
|
||||
timeout: 3000
|
||||
},
|
||||
[PANEL_EVENT_TYPES.PANEL_CLOSE_REQUEST]: {
|
||||
handlers: ['panelHandler', 'tabPageHandler'],
|
||||
priority: 2,
|
||||
timeout: 5000
|
||||
},
|
||||
|
||||
// TabPage事件路由
|
||||
[TABPAGE_EVENT_TYPES.TABPAGE_DRAG_START]: {
|
||||
handlers: ['tabPageHandler', 'areaHandler'],
|
||||
priority: 1,
|
||||
timeout: 5000
|
||||
},
|
||||
[TABPAGE_EVENT_TYPES.TABPAGE_SWITCH]: {
|
||||
handlers: ['tabPageHandler', 'panelHandler'],
|
||||
priority: 2,
|
||||
timeout: 3000
|
||||
},
|
||||
[TABPAGE_EVENT_TYPES.TABPAGE_CLOSE_REQUEST]: {
|
||||
handlers: ['tabPageHandler', 'panelHandler'],
|
||||
priority: 2,
|
||||
timeout: 5000
|
||||
},
|
||||
|
||||
// Area事件路由
|
||||
[AREA_EVENT_TYPES.AREA_DRAG_START]: {
|
||||
handlers: ['areaHandler', 'tabPageHandler'],
|
||||
priority: 1,
|
||||
timeout: 5000
|
||||
},
|
||||
[AREA_EVENT_TYPES.AREA_MERGE]: {
|
||||
handlers: ['areaHandler', 'tabPageHandler', 'panelHandler'],
|
||||
priority: 1,
|
||||
timeout: 10000
|
||||
},
|
||||
[AREA_EVENT_TYPES.AREA_DOCK_CENTER]: {
|
||||
handlers: ['areaHandler', 'tabPageHandler'],
|
||||
priority: 1,
|
||||
timeout: 8000
|
||||
}
|
||||
};
|
||||
// 事件路由配置将在构造函数中动态创建
|
||||
|
||||
// 事件执行监控
|
||||
class EventExecutionMonitor {
|
||||
@@ -297,31 +238,26 @@ class GlobalEventManager {
|
||||
static instance = null;
|
||||
|
||||
constructor() {
|
||||
// 单例模式实现:如果已经有实例,直接返回现有实例
|
||||
if (GlobalEventManager.instance) {
|
||||
return GlobalEventManager.instance;
|
||||
}
|
||||
|
||||
this.eventHandlers = new Map();
|
||||
this.eventRoutes = new Map(Object.entries(EVENT_ROUTES));
|
||||
this.eventRoutes = new Map();
|
||||
this.executionMonitor = new EventExecutionMonitor();
|
||||
this.eventChains = new Map();
|
||||
this.crossComponentChannels = new Map();
|
||||
this.isInitialized = false;
|
||||
this.isDestroyed = false;
|
||||
this.eventListenersRegistered = false;
|
||||
this.componentListenersRegistered = false;
|
||||
this.debugMode = false;
|
||||
this.handlerMap = {};
|
||||
this.eventListenerUnsubscribers = [];
|
||||
|
||||
// 绑定方法
|
||||
this._onGlobalEvent = this._onGlobalEvent.bind(this);
|
||||
this._onSystemError = this._handleSystemError.bind(this);
|
||||
this._cleanupExpiredData = this._cleanupExpiredData.bind(this);
|
||||
|
||||
// 延迟初始化,先不调用_initialize()
|
||||
|
||||
// 保存实例到静态属性
|
||||
GlobalEventManager.instance = this;
|
||||
}
|
||||
|
||||
@@ -329,41 +265,29 @@ class GlobalEventManager {
|
||||
* 初始化事件管理器
|
||||
*/
|
||||
async _initialize() {
|
||||
// 防止重复初始化
|
||||
if (this.isInitialized) {
|
||||
console.warn('⚠️ 全局事件管理器已初始化,跳过重复初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化处理器映射
|
||||
this.handlerMap = {
|
||||
panelHandler,
|
||||
tabPageHandler,
|
||||
areaHandler
|
||||
};
|
||||
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(),
|
||||
handlers: Object.keys(this.handlerMap)
|
||||
timestamp: Date.now()
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册全局事件监听器
|
||||
* 添加初始化锁防止并发场景下的重复注册
|
||||
*/
|
||||
_registerGlobalEventListeners() {
|
||||
// 检查是否已经注册过事件监听器
|
||||
@@ -372,236 +296,46 @@ class GlobalEventManager {
|
||||
return;
|
||||
}
|
||||
|
||||
const globalEvents = Object.values(GLOBAL_EVENT_TYPES);
|
||||
globalEvents.forEach(eventType => {
|
||||
const unsubscribe = eventBus.on(eventType, this._onGlobalEvent, {
|
||||
priority: 0, // 最高优先级
|
||||
deduplication: { type: 'TTL_BASED', ttl: 50 }
|
||||
});
|
||||
this.eventListenerUnsubscribers.push(unsubscribe);
|
||||
});
|
||||
|
||||
// 注册所有组件事件监听器
|
||||
this._registerComponentEventListeners();
|
||||
|
||||
// 标记为已注册
|
||||
// 先标记为正在注册,防止并发
|
||||
this.eventListenersRegistered = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册组件事件监听器
|
||||
*/
|
||||
_registerComponentEventListeners() {
|
||||
// 防止重复注册组件事件监听器
|
||||
if (this.componentListenersRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Panel事件监听
|
||||
Object.values(PANEL_EVENT_TYPES).forEach(eventType => {
|
||||
const unsubscribe = eventBus.on(eventType, this._routeEvent.bind(this, eventType, null, 'panel'), { priority: 1 });
|
||||
this.eventListenerUnsubscribers.push(unsubscribe);
|
||||
});
|
||||
|
||||
// TabPage事件监听
|
||||
Object.values(TABPAGE_EVENT_TYPES).forEach(eventType => {
|
||||
const unsubscribe = eventBus.on(eventType, this._routeEvent.bind(this, eventType, null, 'tabPage'), { priority: 1 });
|
||||
this.eventListenerUnsubscribers.push(unsubscribe);
|
||||
});
|
||||
|
||||
// Area事件监听
|
||||
Object.values(AREA_EVENT_TYPES).forEach(eventType => {
|
||||
const unsubscribe = eventBus.on(eventType, this._routeEvent.bind(this, eventType, null, 'area'), { priority: 1 });
|
||||
this.eventListenerUnsubscribers.push(unsubscribe);
|
||||
});
|
||||
|
||||
this.componentListenersRegistered = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 路由事件到相应的处理器
|
||||
* @param {string} eventType - 事件类型
|
||||
* @param {Object} eventData - 事件数据
|
||||
* @param {string} source - 事件源
|
||||
*/
|
||||
async _routeEvent(eventType, eventData, source) {
|
||||
const eventId = `${eventType}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
const routeConfig = this.eventRoutes.get(eventType);
|
||||
|
||||
// 开始监控
|
||||
this.executionMonitor.startMonitoring(eventId, { ...eventData, eventType });
|
||||
|
||||
eventBus.emit(GLOBAL_EVENT_TYPES.EVENT_ROUTE_START, {
|
||||
eventId,
|
||||
eventType,
|
||||
source,
|
||||
routeConfig
|
||||
});
|
||||
|
||||
try {
|
||||
if (routeConfig) {
|
||||
// 使用配置的路由
|
||||
await this._executeRoutedHandlers(eventId, eventType, eventData, routeConfig);
|
||||
} else {
|
||||
// 默认路由到相应组件处理器
|
||||
await this._executeDefaultHandler(eventId, eventType, eventData, source);
|
||||
}
|
||||
|
||||
// 完成监控
|
||||
this.executionMonitor.completeMonitoring(eventId);
|
||||
|
||||
eventBus.emit(GLOBAL_EVENT_TYPES.EVENT_ROUTE_SUCCESS, {
|
||||
eventId,
|
||||
eventType,
|
||||
source,
|
||||
timestamp: Date.now()
|
||||
const globalEvents = Object.values(GLOBAL_EVENT_TYPES);
|
||||
globalEvents.forEach(eventType => {
|
||||
const unsubscribe = eventBus.on(eventType, this._onGlobalEvent, {
|
||||
priority: 0, // 最高优先级
|
||||
deduplication: { type: 'TTL_BASED', ttl: 50 },
|
||||
componentId: 'global-event-manager'
|
||||
});
|
||||
this.eventListenerUnsubscribers.push(unsubscribe);
|
||||
});
|
||||
|
||||
// 注册所有组件事件监听器
|
||||
this._registerComponentEventListeners();
|
||||
} catch (error) {
|
||||
// 记录错误
|
||||
this.executionMonitor.recordError(eventId, error);
|
||||
|
||||
eventBus.emit(GLOBAL_EVENT_TYPES.EVENT_ROUTE_ERROR, {
|
||||
eventId,
|
||||
eventType,
|
||||
source,
|
||||
error: error.message,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
// 触发系统错误事件
|
||||
eventBus.emit(GLOBAL_EVENT_TYPES.SYSTEM_ERROR, {
|
||||
eventId,
|
||||
eventType,
|
||||
source,
|
||||
error,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行路由的处理器
|
||||
* @param {string} eventId - 事件ID
|
||||
* @param {string} eventType - 事件类型
|
||||
* @param {Object} eventData - 事件数据
|
||||
* @param {Object} routeConfig - 路由配置
|
||||
*/
|
||||
async _executeRoutedHandlers(eventId, eventType, eventData, routeConfig) {
|
||||
const { handlers, priority, timeout = 5000 } = routeConfig;
|
||||
const handlerPromises = handlers.map(async (handlerName) => {
|
||||
const startTime = Date.now();
|
||||
this.executionMonitor.recordHandlerStart(eventId, handlerName);
|
||||
|
||||
try {
|
||||
const handler = this.handlerMap[handlerName];
|
||||
if (!handler) {
|
||||
throw new Error(`Handler ${handlerName} not found`);
|
||||
}
|
||||
|
||||
// 执行处理器
|
||||
const result = await this._executeHandlerWithTimeout(
|
||||
handler,
|
||||
eventType,
|
||||
eventData,
|
||||
timeout
|
||||
);
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
this.executionMonitor.recordHandlerComplete(eventId, handlerName, true, duration);
|
||||
|
||||
return { handlerName, result, duration };
|
||||
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
this.executionMonitor.recordHandlerComplete(eventId, handlerName, false, duration, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// 等待所有处理器完成
|
||||
const results = await Promise.allSettled(handlerPromises);
|
||||
|
||||
// 检查是否有失败的处理器
|
||||
const failures = results.filter(result => result.status === 'rejected');
|
||||
if (failures.length > 0) {
|
||||
throw new Error(`Handler execution failed: ${failures.map(f => f.reason.message).join(', ')}`);
|
||||
}
|
||||
|
||||
return results.map(result => result.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行默认处理器
|
||||
* @param {string} eventId - 事件ID
|
||||
* @param {string} eventType - 事件类型
|
||||
* @param {Object} eventData - 事件数据
|
||||
* @param {string} source - 事件源
|
||||
*/
|
||||
async _executeDefaultHandler(eventId, eventType, eventData, source) {
|
||||
const handlerName = `${source}Handler`;
|
||||
const handler = this.handlerMap[handlerName];
|
||||
|
||||
if (!handler) {
|
||||
throw new Error(`Default handler ${handlerName} not found`);
|
||||
}
|
||||
|
||||
this.executionMonitor.recordHandlerStart(eventId, handlerName);
|
||||
|
||||
try {
|
||||
const result = await this._executeHandlerWithTimeout(handler, eventType, eventData, 5000);
|
||||
const duration = Date.now() - this.executionMonitor.getExecutionDetail(eventId).startTime;
|
||||
this.executionMonitor.recordHandlerComplete(eventId, handlerName, true, duration);
|
||||
return result;
|
||||
} catch (error) {
|
||||
const duration = Date.now() - this.executionMonitor.getExecutionDetail(eventId).startTime;
|
||||
this.executionMonitor.recordHandlerComplete(eventId, handlerName, false, duration, error);
|
||||
// 如果注册失败,重置标志位
|
||||
this.eventListenersRegistered = false;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 带超时的处理器执行
|
||||
* @param {Object} handler - 处理器对象
|
||||
* @param {string} eventType - 事件类型
|
||||
* @param {Object} eventData - 事件数据
|
||||
* @param {number} timeout - 超时时间
|
||||
* @returns {Promise} 执行结果
|
||||
* 注册组件事件监听器
|
||||
* 添加初始化锁防止并发场景下的重复注册
|
||||
*/
|
||||
async _executeHandlerWithTimeout(handler, eventType, eventData, timeout) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
reject(new Error(`Handler execution timeout after ${timeout}ms`));
|
||||
}, timeout);
|
||||
|
||||
try {
|
||||
// 假设处理器有处理事件的方法
|
||||
if (typeof handler._onEvent === 'function') {
|
||||
const result = handler._onEvent({ eventType, ...eventData });
|
||||
if (result instanceof Promise) {
|
||||
result.then(resolve).catch(reject).finally(() => clearTimeout(timer));
|
||||
} else {
|
||||
resolve(result);
|
||||
clearTimeout(timer);
|
||||
}
|
||||
} else {
|
||||
// 如果处理器没有_onEvent方法,直接解析
|
||||
resolve(true);
|
||||
clearTimeout(timer);
|
||||
}
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
clearTimeout(timer);
|
||||
}
|
||||
});
|
||||
_registerComponentEventListeners() {
|
||||
if (this.componentListenersRegistered) {
|
||||
console.warn('⚠️ 组件事件监听器已经注册,跳过重复注册');
|
||||
return;
|
||||
}
|
||||
|
||||
this.componentListenersRegistered = true;
|
||||
|
||||
console.log('✅ 组件事件监听器注册完成(Handler自行订阅事件)');
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理全局事件
|
||||
* @param {Object} data - 事件数据
|
||||
*/
|
||||
async _onGlobalEvent(data) {
|
||||
const { eventType } = data;
|
||||
const eventType = data.eventType;
|
||||
|
||||
try {
|
||||
switch (eventType) {
|
||||
@@ -634,18 +368,8 @@ class GlobalEventManager {
|
||||
async _handleSystemInit(data) {
|
||||
console.log('🚀 系统初始化开始...', data);
|
||||
|
||||
// 检查所有处理器是否就绪
|
||||
const handlersStatus = {};
|
||||
for (const [name, handler] of Object.entries(this.handlerMap)) {
|
||||
handlersStatus[name] = {
|
||||
ready: typeof handler === 'object',
|
||||
methods: Object.getOwnPropertyNames(Object.getPrototypeOf(handler))
|
||||
};
|
||||
}
|
||||
|
||||
eventBus.emit(GLOBAL_EVENT_TYPES.SYSTEM_READY, {
|
||||
manager: 'globalEventManager',
|
||||
handlersStatus,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
}
|
||||
@@ -714,37 +438,13 @@ class GlobalEventManager {
|
||||
async _handleCrossComponentRequest(data) {
|
||||
const { requestId, targetComponent, action, payload } = data;
|
||||
|
||||
try {
|
||||
// 查找目标组件的处理器
|
||||
const handler = this.handlerMap[`${targetComponent}Handler`];
|
||||
if (!handler) {
|
||||
throw new Error(`Target component handler ${targetComponent}Handler not found`);
|
||||
}
|
||||
|
||||
// 执行请求
|
||||
const result = await handler[action](payload);
|
||||
|
||||
// 发送响应
|
||||
eventBus.emit(GLOBAL_EVENT_TYPES.CROSS_COMPONENT_RESPONSE, {
|
||||
requestId,
|
||||
targetComponent,
|
||||
action,
|
||||
result,
|
||||
success: true,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
// 发送错误响应
|
||||
eventBus.emit(GLOBAL_EVENT_TYPES.CROSS_COMPONENT_RESPONSE, {
|
||||
requestId,
|
||||
targetComponent,
|
||||
action,
|
||||
error: error.message,
|
||||
success: false,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
}
|
||||
// 通过事件总线转发跨组件请求
|
||||
// 目标Handler应该监听这个事件并处理
|
||||
eventBus.emit(`${targetComponent}.${action}`, {
|
||||
requestId,
|
||||
payload,
|
||||
isCrossComponent: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1032,41 +732,52 @@ class GlobalEventManager {
|
||||
|
||||
/**
|
||||
* 销毁事件管理器
|
||||
* 添加销毁锁防止重复销毁,确保正确清理所有监听器
|
||||
*/
|
||||
destroy() {
|
||||
// 清理自己注册的所有事件监听器
|
||||
this.eventListenerUnsubscribers.forEach(unsubscribe => {
|
||||
try {
|
||||
unsubscribe();
|
||||
} catch (error) {
|
||||
console.warn('清理监听器时出错:', error);
|
||||
}
|
||||
});
|
||||
this.eventListenerUnsubscribers = [];
|
||||
if (this.isDestroyed) {
|
||||
console.warn('⚠️ 全局事件管理器已经被销毁,跳过重复销毁');
|
||||
return;
|
||||
}
|
||||
|
||||
// 销毁各个处理器
|
||||
Object.values(this.handlerMap).forEach(handler => {
|
||||
if (typeof handler.destroy === 'function') {
|
||||
handler.destroy();
|
||||
}
|
||||
});
|
||||
this.isDestroyed = true;
|
||||
|
||||
// 清理自己注册的所有事件监听器
|
||||
if (this.eventListenerUnsubscribers.length > 0) {
|
||||
this.eventListenerUnsubscribers.forEach(unsubscribe => {
|
||||
try {
|
||||
if (typeof unsubscribe === 'function') {
|
||||
unsubscribe();
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('清理监听器时出错:', error);
|
||||
}
|
||||
});
|
||||
this.eventListenerUnsubscribers = [];
|
||||
}
|
||||
|
||||
// 清理数据
|
||||
this.eventHandlers.clear();
|
||||
this.eventChains.clear();
|
||||
this.crossComponentChannels.clear();
|
||||
this.handlerMap = {};
|
||||
this.eventRoutes.clear();
|
||||
if (this.eventHandlers) this.eventHandlers.clear();
|
||||
if (this.eventChains) this.eventChains.clear();
|
||||
if (this.crossComponentChannels) this.crossComponentChannels.clear();
|
||||
if (this.eventRoutes) this.eventRoutes.clear();
|
||||
|
||||
// 清理执行监控器
|
||||
if (this.executionMonitor) {
|
||||
this.executionMonitor.cleanup();
|
||||
}
|
||||
|
||||
// 重置状态标志
|
||||
this.isInitialized = false;
|
||||
this.eventListenersRegistered = false;
|
||||
this.componentListenersRegistered = false;
|
||||
|
||||
console.log('🗑️ 全局事件管理器已销毁,所有监听器已清理');
|
||||
}
|
||||
}
|
||||
|
||||
// 延迟创建单例实例
|
||||
let globalEventManager = null;
|
||||
// 立即创建单例实例,避免并发初始化问题
|
||||
const globalEventManager = new GlobalEventManager();
|
||||
|
||||
// 全局便捷API
|
||||
export const globalEventActions = {
|
||||
@@ -1076,7 +787,6 @@ export const globalEventActions = {
|
||||
* @returns {string} 监控ID
|
||||
*/
|
||||
startMonitor: (operation) => {
|
||||
ensureInstance();
|
||||
return globalEventManager.startPerformanceMonitor(operation);
|
||||
},
|
||||
|
||||
@@ -1086,7 +796,6 @@ export const globalEventActions = {
|
||||
* @param {Object} metadata - 元数据
|
||||
*/
|
||||
endMonitor: (monitorId, metadata = {}) => {
|
||||
ensureInstance();
|
||||
globalEventManager.endPerformanceMonitor(monitorId, metadata);
|
||||
},
|
||||
|
||||
@@ -1097,7 +806,6 @@ export const globalEventActions = {
|
||||
* @returns {string} 链ID
|
||||
*/
|
||||
createChain: (chainName, events) => {
|
||||
ensureInstance();
|
||||
return globalEventManager.createEventChain(chainName, events);
|
||||
},
|
||||
|
||||
@@ -1108,7 +816,6 @@ export const globalEventActions = {
|
||||
* @param {Array} targets - 目标组件
|
||||
*/
|
||||
broadcast: (message, data = {}, targets = null) => {
|
||||
ensureInstance();
|
||||
globalEventManager.broadcast(message, data, targets);
|
||||
},
|
||||
|
||||
@@ -1120,7 +827,6 @@ export const globalEventActions = {
|
||||
* @returns {Promise} 响应
|
||||
*/
|
||||
request: (component, action, payload) => {
|
||||
ensureInstance();
|
||||
return globalEventManager.request(component, action, payload);
|
||||
},
|
||||
|
||||
@@ -1136,7 +842,6 @@ export const globalEventActions = {
|
||||
* @returns {Object} 统计信息
|
||||
*/
|
||||
getStats: () => {
|
||||
ensureInstance();
|
||||
return globalEventManager.getExecutionStats();
|
||||
},
|
||||
|
||||
@@ -1145,7 +850,6 @@ export const globalEventActions = {
|
||||
* @returns {Array} 链状态
|
||||
*/
|
||||
getChainStatus: () => {
|
||||
ensureInstance();
|
||||
return globalEventManager.getEventChainStatus();
|
||||
},
|
||||
|
||||
@@ -1153,7 +857,7 @@ export const globalEventActions = {
|
||||
* 初始化事件管理器
|
||||
*/
|
||||
initialize: () => {
|
||||
ensureInstance();
|
||||
return globalEventManager;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1162,31 +866,15 @@ export const globalEventActions = {
|
||||
destroy: () => {
|
||||
if (globalEventManager) {
|
||||
globalEventManager.destroy();
|
||||
globalEventManager = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 确保单例实例存在
|
||||
*/
|
||||
async function ensureInstance() {
|
||||
if (!globalEventManager) {
|
||||
globalEventManager = new GlobalEventManager();
|
||||
// 异步初始化
|
||||
await globalEventManager._initialize();
|
||||
} else if (!globalEventManager.isInitialized) {
|
||||
// 如果实例存在但未初始化,完成初始化
|
||||
await globalEventManager._initialize();
|
||||
}
|
||||
return globalEventManager;
|
||||
}
|
||||
|
||||
// 导出单例实例访问方法
|
||||
export const getGlobalEventManager = ensureInstance;
|
||||
export const getGlobalEventManager = () => globalEventManager;
|
||||
|
||||
// 导出事件管理器和相关API
|
||||
export default {
|
||||
getInstance: getGlobalEventManager,
|
||||
getInstance: () => globalEventManager,
|
||||
actions: globalEventActions
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
import { emitEvent, onEvent, onceEvent, registerHandler, unregisterHandler, getHandlerSnapshot } from '../eventBus'
|
||||
import { nanoid } from 'nanoid'
|
||||
import { emitEvent, onEvent, onceEvent, registerHandler, unregisterHandler, getHandlerSnapshot } from '../eventBus'
|
||||
|
||||
// Panel事件类型常量
|
||||
export const PANEL_EVENT_TYPES = {
|
||||
@@ -151,9 +151,11 @@ class PanelEventHandler {
|
||||
// 触发最大化事件(false表示还原)
|
||||
await emitEvent(PANEL_EVENT_TYPES.MAXIMIZE, {
|
||||
panelId,
|
||||
maximized: false,
|
||||
source: 'PanelHandler'
|
||||
}, { priority })
|
||||
maximized: false
|
||||
}, {
|
||||
priority,
|
||||
source: { component: 'PanelHandler', panelId }
|
||||
})
|
||||
|
||||
// 如果需要同步到Area
|
||||
if (syncToArea) {
|
||||
@@ -171,10 +173,12 @@ class PanelEventHandler {
|
||||
*/
|
||||
requestClose(eventData) {
|
||||
const { areaId, panelId } = eventData;
|
||||
this.emitEvent(PANEL_EVENT_TYPES.CLOSE_REQUEST, {
|
||||
emitEvent(PANEL_EVENT_TYPES.CLOSE_REQUEST, {
|
||||
areaId,
|
||||
panelId,
|
||||
timestamp: Date.now()
|
||||
}, {
|
||||
source: { component: 'PanelHandler', panelId, areaId }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -231,9 +235,11 @@ class PanelEventHandler {
|
||||
|
||||
return emitEvent(PANEL_EVENT_TYPES.TOGGLE_TOOLBAR, {
|
||||
panelId,
|
||||
toolbarExpanded: panelState.toolbarExpanded,
|
||||
source: 'PanelHandler'
|
||||
}, { priority })
|
||||
toolbarExpanded: panelState.toolbarExpanded
|
||||
}, {
|
||||
priority,
|
||||
source: { component: 'PanelHandler', panelId }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,9 +267,11 @@ class PanelEventHandler {
|
||||
return emitEvent(PANEL_EVENT_TYPES.DRAG_START, {
|
||||
panelId,
|
||||
event: dragEvent,
|
||||
dragState,
|
||||
source: 'PanelHandler'
|
||||
}, { priority })
|
||||
dragState
|
||||
}, {
|
||||
priority,
|
||||
source: { component: 'PanelHandler', panelId }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,9 +333,11 @@ class PanelEventHandler {
|
||||
panelId,
|
||||
event: dragEvent,
|
||||
dragState,
|
||||
duration: dragState.endTime - dragState.startTime,
|
||||
source: 'PanelHandler'
|
||||
}, { priority })
|
||||
duration: dragState.endTime - dragState.startTime
|
||||
}, {
|
||||
priority,
|
||||
source: { component: 'PanelHandler', panelId }
|
||||
})
|
||||
|
||||
// 清理拖拽状态
|
||||
this.dragStates.delete(panelId)
|
||||
@@ -353,10 +363,11 @@ class PanelEventHandler {
|
||||
this.panelStates.set(panelId, panelState)
|
||||
|
||||
return emitEvent(PANEL_EVENT_TYPES.ACTIVATED, {
|
||||
panelId,
|
||||
source: 'PanelHandler',
|
||||
timestamp: Date.now()
|
||||
}, { priority })
|
||||
panelId
|
||||
}, {
|
||||
priority,
|
||||
source: { component: 'PanelHandler', panelId }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,10 +388,11 @@ class PanelEventHandler {
|
||||
this.panelStates.set(panelId, panelState)
|
||||
|
||||
return emitEvent(PANEL_EVENT_TYPES.DEACTIVATED, {
|
||||
panelId,
|
||||
source: 'PanelHandler',
|
||||
timestamp: Date.now()
|
||||
}, { priority })
|
||||
panelId
|
||||
}, {
|
||||
priority,
|
||||
source: { component: 'PanelHandler', panelId }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -441,10 +453,12 @@ class PanelEventHandler {
|
||||
*/
|
||||
onExpand(eventData) {
|
||||
const { areaId, panelId } = eventData;
|
||||
this.emitEvent(PANEL_EVENT_TYPES.EXPAND, {
|
||||
emitEvent(PANEL_EVENT_TYPES.EXPAND, {
|
||||
areaId,
|
||||
panelId,
|
||||
timestamp: Date.now()
|
||||
}, {
|
||||
source: { component: 'PanelHandler', panelId, areaId }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -454,10 +468,12 @@ class PanelEventHandler {
|
||||
*/
|
||||
onMaximize(eventData) {
|
||||
const { areaId, panelId } = eventData;
|
||||
this.emitEvent(PANEL_EVENT_TYPES.MAXIMIZE, {
|
||||
emitEvent(PANEL_EVENT_TYPES.MAXIMIZE, {
|
||||
areaId,
|
||||
panelId,
|
||||
timestamp: Date.now()
|
||||
}, {
|
||||
source: { component: 'PanelHandler', panelId, areaId }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -480,10 +496,12 @@ class PanelEventHandler {
|
||||
*/
|
||||
onToggleToolbar(eventData) {
|
||||
const { areaId, panelId } = eventData;
|
||||
this.emitEvent(PANEL_EVENT_TYPES.TOGGLE_TOOLBAR, {
|
||||
emitEvent(PANEL_EVENT_TYPES.TOGGLE_TOOLBAR, {
|
||||
areaId,
|
||||
panelId,
|
||||
timestamp: Date.now()
|
||||
}, {
|
||||
source: { component: 'PanelHandler', panelId, areaId }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -507,11 +525,13 @@ class PanelEventHandler {
|
||||
*/
|
||||
onSizeUpdate(eventData) {
|
||||
const { areaId, panelId, size } = eventData;
|
||||
this.emitEvent('panel.size.update', {
|
||||
emitEvent('panel.size.update', {
|
||||
areaId,
|
||||
panelId,
|
||||
size,
|
||||
timestamp: Date.now()
|
||||
}, {
|
||||
source: { component: 'PanelHandler', panelId, areaId }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -567,8 +587,9 @@ class PanelEventHandler {
|
||||
return emitEvent(PANEL_EVENT_TYPES.MAXIMIZE_SYNC, {
|
||||
panelId,
|
||||
maximized,
|
||||
areaId: panelState.areaId,
|
||||
source: 'PanelHandler'
|
||||
areaId: panelState.areaId
|
||||
}, {
|
||||
source: { component: 'PanelHandler', panelId, areaId: panelState.areaId }
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ class TabPageEventHandler {
|
||||
* @param {string} data.eventType - 事件类型
|
||||
*/
|
||||
async _onTabPageEvent(data) {
|
||||
const { eventType } = data;
|
||||
const eventType = data.eventType;
|
||||
|
||||
try {
|
||||
switch (eventType) {
|
||||
@@ -222,7 +222,6 @@ class TabPageEventHandler {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ TabPage事件处理错误 (${eventType}):`, error);
|
||||
eventBus.recordError(`tabPageHandler_${eventType}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,6 +590,9 @@ function ensureInstance() {
|
||||
return tabPageHandler;
|
||||
}
|
||||
|
||||
// 导出单例实例访问方法
|
||||
export const getTabPageHandler = ensureInstance;
|
||||
|
||||
// TabPage便捷操作函数
|
||||
export const tabPageActions = {
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user