/** * Area事件处理器 * 专门处理Area相关的所有事件,包括浮动区域管理、拖拽、停靠、合并等 */ import { eventBus } from '../eventBus'; // Area事件类型常量 export const AREA_EVENT_TYPES = { // 基础事件 AREA_CREATED: 'area.created', AREA_DESTROYED: 'area.destroyed', AREA_UPDATED: 'area.updated', // 浮动区域管理 AREA_FLOATING_CREATE: 'area.floating.create', AREA_FLOATING_CLOSE: 'area.floating.close', AREA_FLOATING_UPDATE_POSITION: 'area.floating.updatePosition', AREA_FLOATING_ZINDEX_CHANGE: 'area.floating.zindex.change', // Area操作 AREA_MAXIMIZE: 'area.maximize', AREA_RESTORE: 'area.restore', AREA_COLLAPSE: 'area.collapse', AREA_EXPAND: 'area.expand', AREA_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', AREA_DOCK_SPLIT: 'area.dock.split', AREA_MERGE: 'area.merge', AREA_UNMERGE: 'area.unmerge', // 调整大小 AREA_RESIZE_START: 'area.resize.start', AREA_RESIZE: 'area.resize', AREA_RESIZE_END: 'area.resize.end', AREA_RATIO_CHANGE: 'area.ratio.change', // 隐藏/显示 AREA_HIDE: 'area.hide', AREA_SHOW: 'area.show', AREA_MINIMIZE: 'area.minimize', AREA_RESTORE_FROM_MINIMIZE: 'area.restoreFromMinimize', // 层级管理 AREA_ZINDEX_MANAGEMENT: 'area.zindex.management', AREA_ACTIVATION: 'area.activation', AREA_DEACTIVATION: 'area.deactivation', // 内容管理 AREA_CONTENT_CHANGE: 'area.content.change', AREA_PANEL_COUNT_CHANGE: 'area.panel.count.change', AREA_TABPAGE_MERGE: 'area.tabpage.merge', // 与其他组件的交互 AREA_TABPAGE_SYNC: 'area.tabpage.sync', AREA_PANEL_SYNC: 'area.panel.sync' }; // Area状态管理 class AreaStateManager { constructor() { this.states = new Map(); this.floatingAreas = new Map(); this.hiddenAreas = new Set(); this.dragState = new Map(); this.resizeState = new Map(); this.history = []; this.maxHistorySize = 100; } /** * 更新Area状态 * @param {string} areaId - Area ID * @param {Object} updates - 状态更新 */ updateState(areaId, updates) { const currentState = this.states.get(areaId) || {}; const newState = { ...currentState, ...updates, lastUpdated: Date.now() }; // 记录历史 this.history.push({ areaId, oldState: currentState, newState, timestamp: Date.now() }); // 限制历史记录大小 if (this.history.length > this.maxHistorySize) { this.history.shift(); } this.states.set(areaId, newState); // 触发状态更新事件 eventBus.emit(AREA_EVENT_TYPES.AREA_UPDATED, { areaId, oldState: currentState, newState, updates }); } /** * 创建浮动Area * @param {Object} areaConfig - Area配置 * @returns {string} Area ID */ createFloatingArea(areaConfig) { const areaId = `floating-area-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const floatingArea = { id: areaId, type: 'floating', x: areaConfig.x || 50, y: areaConfig.y || 50, width: areaConfig.width || 400, height: areaConfig.height || 300, zIndex: areaConfig.zIndex || 1001, collapsed: areaConfig.collapsed || false, windowState: areaConfig.windowState || 'normal', // normal, maximized, minimized toolbarExpanded: areaConfig.toolbarExpanded !== false, tabPages: areaConfig.tabPages || [], createdAt: Date.now(), ...areaConfig }; this.floatingAreas.set(areaId, floatingArea); this.states.set(areaId, floatingArea); // 触发创建事件 eventBus.emit(AREA_EVENT_TYPES.AREA_FLOATING_CREATE, { areaId, config: floatingArea, timestamp: Date.now() }); return areaId; } /** * 关闭浮动Area * @param {string} areaId - Area ID */ closeFloatingArea(areaId) { const area = this.floatingAreas.get(areaId); if (!area) return false; // 清理状态 this.floatingAreas.delete(areaId); this.states.delete(areaId); // 触发关闭事件 eventBus.emit(AREA_EVENT_TYPES.AREA_FLOATING_CLOSE, { areaId, config: area, timestamp: Date.now() }); return true; } /** * 更新浮动Area位置 * @param {string} areaId - Area ID * @param {Object} position - 位置信息 */ updateFloatingAreaPosition(areaId, position) { const area = this.floatingAreas.get(areaId); if (!area) return false; const updatedArea = { ...area, x: position.left || area.x, y: position.top || area.y, lastPositionUpdate: Date.now() }; this.floatingAreas.set(areaId, updatedArea); this.states.set(areaId, updatedArea); // 触发位置更新事件 eventBus.emit(AREA_EVENT_TYPES.AREA_FLOATING_UPDATE_POSITION, { areaId, position: { left: updatedArea.x, top: updatedArea.y }, timestamp: Date.now() }); return true; } /** * 添加到隐藏列表 * @param {string} areaId - Area ID */ addToHiddenList(areaId) { this.hiddenAreas.add(areaId); this.states.set(areaId, { ...this.states.get(areaId), hidden: true, hiddenAt: Date.now() }); eventBus.emit(AREA_EVENT_TYPES.AREA_HIDE, { areaId, reason: 'hidden_list', timestamp: Date.now() }); } /** * 从隐藏列表移除 * @param {string} areaId - Area ID */ removeFromHiddenList(areaId) { this.hiddenAreas.delete(areaId); this.states.set(areaId, { ...this.states.get(areaId), hidden: false, restoredAt: Date.now() }); eventBus.emit(AREA_EVENT_TYPES.AREA_SHOW, { areaId, reason: 'restored_from_hidden', timestamp: Date.now() }); } /** * 获取Area状态 * @param {string} areaId - Area ID * @returns {Object} Area状态 */ getState(areaId) { return this.states.get(areaId) || {}; } /** * 获取浮动Area列表 * @returns {Array} 浮动Area列表 */ getFloatingAreas() { return Array.from(this.floatingAreas.values()); } /** * 获取隐藏Area列表 * @returns {Array} 隐藏Area列表 */ getHiddenAreas() { return Array.from(this.hiddenAreas); } /** * 记录拖拽状态 * @param {string} areaId - Area ID * @param {Object} dragInfo - 拖拽信息 */ setDragState(areaId, dragInfo) { this.dragState.set(areaId, { ...dragInfo, timestamp: Date.now() }); } /** * 获取拖拽状态 * @param {string} areaId - Area ID * @returns {Object} 拖拽状态 */ getDragState(areaId) { return this.dragState.get(areaId); } /** * 清理拖拽状态 * @param {string} areaId - Area ID */ clearDragState(areaId) { this.dragState.delete(areaId); } /** * 记录调整大小状态 * @param {string} areaId - Area ID * @param {Object} resizeInfo - 调整信息 */ setResizeState(areaId, resizeInfo) { this.resizeState.set(areaId, { ...resizeInfo, timestamp: Date.now() }); } /** * 获取调整大小状态 * @param {string} areaId - Area ID * @returns {Object} 调整大小状态 */ getResizeState(areaId) { return this.resizeState.get(areaId); } /** * 清理调整大小状态 * @param {string} areaId - Area ID */ clearResizeState(areaId) { this.resizeState.delete(areaId); } /** * 获取历史记录 * @param {number} limit - 限制数量 * @returns {Array} 历史记录 */ getHistory(limit = 20) { return this.history.slice(-limit); } /** * 清理过期历史记录 * @param {number} maxAge - 最大年龄(毫秒) */ cleanupHistory(maxAge = 7200000) { // 2小时 const now = Date.now(); this.history = this.history.filter(record => (now - record.timestamp) < maxAge); } /** * 获取统计信息 * @returns {Object} 统计信息 */ getStats() { return { totalAreas: this.states.size, floatingAreas: this.floatingAreas.size, hiddenAreas: this.hiddenAreas.size, draggingAreas: this.dragState.size, resizingAreas: this.resizeState.size, historySize: this.history.length }; } } /** * Area事件处理器类 */ class AreaEventHandler { constructor() { this.areaStateManager = new AreaStateManager(); this.areaListeners = new Map(); this.activeAreas = new Set(); this.memoryProtection = { maxAreas: 50, cleanupInterval: 30000, lastCleanup: 0 }; // 绑定方法 this._onAreaEvent = this._onAreaEvent.bind(this); this._onMemoryCheck = this._onMemoryCheck.bind(this); this._initialize(); } /** * 初始化事件处理器 */ _initialize() { // 注册事件监听器 this._registerEventListeners(); // 启动内存保护 this._startMemoryProtection(); console.log('✅ Area事件处理器初始化完成'); } /** * 添加新的浮动Area(从DockLayout.vue迁移) * @param {Object} options - 配置选项 * @returns {string} Area ID */ addFloatingPanel(options = {}) { try { const areaConfig = { x: options.x || 50, y: options.y || 50, width: options.width || 280, height: options.height || 200, title: options.title || `浮动区域 ${Date.now()}`, showTitleBar: options.showTitleBar !== false, resizable: options.resizable !== false, draggable: options.draggable !== false, tabPages: options.tabPages || [], content: options.content || this._generateRandomContent(), ...options }; // 创建浮动Area const areaId = this.areaStateManager.createFloatingArea(areaConfig); // 触发成功事件 eventBus.emit(AREA_EVENT_TYPES.AREA_CREATED, { areaId, config: areaConfig, source: 'addFloatingPanel', timestamp: Date.now() }); return areaId; } catch (error) { console.error('创建浮动Area时出错:', error); eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { operation: 'addFloatingPanel', error: error.message, timestamp: Date.now() }); return null; } } /** * 关闭浮动Area(从DockLayout.vue迁移) * @param {string} areaId - Area ID */ closeFloatingArea(areaId) { try { // 检查Area是否存在 const area = this.areaStateManager.getState(areaId); if (!area) { console.warn('找不到要关闭的Area:', areaId); return false; } // 触发关闭开始事件 eventBus.emit(AREA_EVENT_TYPES.AREA_CLOSE, { areaId, config: area, source: 'closeFloatingArea', timestamp: Date.now() }); // 执行关闭逻辑 const success = this.areaStateManager.closeFloatingArea(areaId); if (success) { // 清理相关状态 this.activeAreas.delete(areaId); this.areaStateManager.clearDragState(areaId); this.areaStateManager.clearResizeState(areaId); // 触发关闭完成事件 eventBus.emit(AREA_EVENT_TYPES.AREA_DESTROYED, { areaId, source: 'closeFloatingArea', timestamp: Date.now() }); } return success; } catch (error) { console.error('关闭浮动Area时出错:', error); eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { areaId, operation: 'closeFloatingArea', error: error.message, timestamp: Date.now() }); return false; } } /** * 处理Area合并事件(从DockLayout.vue迁移) * @param {Object} eventData - 合并事件数据 */ onAreaMerged(eventData) { try { const { sourceArea, targetAreaHasContent } = eventData; // 获取源Area对象 const sourceAreaState = this.areaStateManager.getState(sourceArea.id); if (!sourceAreaState) { console.warn('找不到源Area:', sourceArea.id); return; } // 根据目标Area内容状态执行不同的隐藏逻辑 if (targetAreaHasContent) { // 目标Area已有内容:保存源Area及其TabPage组件到隐藏列表 console.log('目标Area已有内容,保存源Area和TabPage组件到隐藏列表'); // 添加到隐藏列表 this.areaStateManager.addToHiddenList(sourceArea.id); // 存储TabPage相关信息 if (sourceAreaState.tabPages) { this._storeHiddenAreaTabPages(sourceArea.id, sourceAreaState.tabPages); } } else { // 目标Area为空:仅保存源Area到隐藏列表 console.log('目标Area为空,保存源Area到隐藏列表'); this.areaStateManager.addToHiddenList(sourceArea.id); } // 从浮动区域中移除已合并的源Area const success = this.areaStateManager.closeFloatingArea(sourceArea.id); if (success) { console.log('源Area已从浮动区域移除:', sourceArea.id); } // 触发合并完成事件 eventBus.emit(AREA_EVENT_TYPES.AREA_MERGE, { sourceAreaId: sourceArea.id, targetAreaHasContent, timestamp: Date.now() }); } catch (error) { console.error('处理Area合并事件时出错:', error); eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { operation: 'onAreaMerged', eventData, error: error.message, timestamp: Date.now() }); } } /** * 切换折叠状态(从DockLayout.vue迁移) * @param {string} areaId - Area ID */ toggleCollapse(areaId) { try { const areaState = this.areaStateManager.getState(areaId); if (!areaState) { console.warn('找不到Area:', areaId); return false; } const newCollapsedState = !areaState.collapsed; // 更新状态 this.areaStateManager.updateState(areaId, { collapsed: newCollapsedState }); // 触发折叠/展开事件 eventBus.emit(newCollapsedState ? AREA_EVENT_TYPES.AREA_COLLAPSE : AREA_EVENT_TYPES.AREA_EXPAND, { areaId, collapsed: newCollapsedState, timestamp: Date.now() }); return true; } catch (error) { console.error('切换Area折叠状态时出错:', error); eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { areaId, operation: 'toggleCollapse', error: error.message, timestamp: Date.now() }); return false; } } /** * 切换工具栏状态(从DockLayout.vue迁移) * @param {string} areaId - Area ID */ toggleToolbar(areaId) { try { const areaState = this.areaStateManager.getState(areaId); if (!areaState) { console.warn('找不到Area:', areaId); return false; } const newToolbarState = !areaState.toolbarExpanded; // 更新状态 this.areaStateManager.updateState(areaId, { toolbarExpanded: newToolbarState }); // 触发工具栏切换事件 eventBus.emit(AREA_EVENT_TYPES.AREA_TOGGLE_TOOLBAR, { areaId, expanded: newToolbarState, timestamp: Date.now() }); return true; } catch (error) { console.error('切换Area工具栏状态时出错:', error); eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { areaId, operation: 'toggleToolbar', error: error.message, timestamp: Date.now() }); return false; } } /** * 切换最大化状态(从DockLayout.vue迁移) * @param {string} areaId - Area ID * @param {Object} options - 选项 */ toggleMaximize(areaId, options = {}) { try { const areaState = this.areaStateManager.getState(areaId); if (!areaState) { console.warn('找不到Area:', areaId); return false; } const isCurrentlyMaximized = areaState.windowState === '最大化' || areaState.windowState === 'maximized'; const newWindowState = isCurrentlyMaximized ? '正常' : '最大化'; // 更新状态 this.areaStateManager.updateState(areaId, { windowState: newWindowState, maximized: !isCurrentlyMaximized }); // 触发最大化/还原事件 eventBus.emit(isCurrentlyMaximized ? AREA_EVENT_TYPES.AREA_RESTORE : AREA_EVENT_TYPES.AREA_MAXIMIZE, { areaId, windowState: newWindowState, timestamp: Date.now() }); // 如果是最大化状态,激活Area if (!isCurrentlyMaximized) { this.activateArea(areaId); } return true; } catch (error) { console.error('切换Area最大化状态时出错:', error); eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { areaId, operation: 'toggleMaximize', error: error.message, timestamp: Date.now() }); return false; } } /** * 激活Area * @param {string} areaId - Area ID */ activateArea(areaId) { try { // 添加到活跃区域集合 this.activeAreas.add(areaId); // 更新最后激活时间 this.areaStateManager.updateState(areaId, { lastActivated: Date.now(), active: true }); // 触发激活事件 eventBus.emit(AREA_EVENT_TYPES.AREA_ACTIVATION, { areaId, timestamp: Date.now() }); } catch (error) { console.error('激活Area时出错:', error); eventBus.emit(AREA_EVENT_TYPES.AREA_ERROR, { areaId, operation: 'activateArea', error: error.message, timestamp: Date.now() }); } } /** * 生成随机测试内容 * @private */ _generateRandomContent() { const contentTypes = ['图表', '数据', '配置', '文档', '代码', '日志']; const randomType = contentTypes[Math.floor(Math.random() * contentTypes.length)]; const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD']; const randomColor = colors[Math.floor(Math.random() * colors.length)]; return { type: randomType, color: randomColor, title: `${randomType}区域`, data: this._generateSampleData(), timestamp: new Date().toLocaleString() }; } /** * 生成样本数据 * @private * @param {number} dataIndex - 数据索引 */ _generateSampleData(dataIndex = 0) { const data = []; for (let i = 0; i < 5; i++) { data.push({ label: `项目 ${String.fromCharCode(65 + i)}`, value: Math.floor(Math.random() * 100) + 10, id: `data-${dataIndex}-${i}` }); } return data; } /** * 存储隐藏Area的TabPage信息 * @private */ _storeHiddenAreaTabPages(areaId, tabPages) { try { // 将TabPage信息存储到历史记录中 eventBus.emit(AREA_EVENT_TYPES.AREA_HIDE, { areaId, reason: 'merge_with_content', tabPages: [...tabPages], timestamp: Date.now() }); } catch (error) { console.error('存储隐藏Area的TabPage信息时出错:', error); } } /** * 注册事件监听器 */ _registerEventListeners() { const events = Object.values(AREA_EVENT_TYPES); events.forEach(eventType => { const listener = this._onAreaEvent; eventBus.on(eventType, listener, { priority: 1, deduplication: { type: 'TTL_BASED', ttl: 100 } }); this.areaListeners.set(eventType, listener); }); } /** * 处理Area事件 * @param {Object} data - 事件数据 */ async _onAreaEvent(data) { const { eventType } = data; try { switch (eventType) { case AREA_EVENT_TYPES.AREA_DRAG_START: await this._handleAreaDragStart(data); break; case AREA_EVENT_TYPES.AREA_DRAG_MOVE: await this._handleAreaDragMove(data); break; case AREA_EVENT_TYPES.AREA_DRAG_END: await this._handleAreaDragEnd(data); break; case AREA_EVENT_TYPES.AREA_DOCK_CENTER: await this._handleAreaDockCenter(data); break; case AREA_EVENT_TYPES.AREA_MERGE: await this._handleAreaMerge(data); break; case AREA_EVENT_TYPES.AREA_RESIZE_START: await this._handleAreaResizeStart(data); break; case AREA_EVENT_TYPES.AREA_RESIZE: await this._handleAreaResize(data); break; case AREA_EVENT_TYPES.AREA_RESIZE_END: await this._handleAreaResizeEnd(data); break; case AREA_EVENT_TYPES.AREA_FLOATING_CREATE: await this._handleFloatingAreaCreate(data); break; default: // 记录其他事件但不处理 console.log(`📍 Area事件处理器: ${eventType}`, data); } } catch (error) { console.error(`❌ Area事件处理错误 (${eventType}):`, error); eventBus.recordError(`areaHandler_${eventType}`, error); } } /** * 处理Area拖拽开始事件 * @param {Object} data - 事件数据 */ async _handleAreaDragStart(data) { const { areaId, event, source = 'direct' } = data; // 记录拖拽状态 this.areaStateManager.setDragState(areaId, { isDragging: true, source, startPosition: { x: event.clientX, y: event.clientY }, startTime: Date.now(), dragType: 'area' }); // 激活Area this.activeAreas.add(areaId); // 触发层级管理 eventBus.emit(AREA_EVENT_TYPES.AREA_ZINDEX_MANAGEMENT, { areaId, action: 'activate', reason: 'drag_start' }); } /** * 处理Area拖拽移动事件 * @param {Object} data - 事件数据 */ async _handleAreaDragMove(data) { const { areaId, event } = 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; // 更新拖拽状态 dragState.lastPosition = { x: event.clientX, y: event.clientY }; 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 }); } // 触发拖拽移动事件 eventBus.emit(AREA_EVENT_TYPES.AREA_DRAG_MOVE, { areaId, delta: { x: deltaX, y: deltaY }, position: { x: event.clientX, y: event.clientY }, isDragging: dragState.isDragging }); } /** * 处理Area拖拽结束事件 * @param {Object} data - 事件数据 */ async _handleAreaDragEnd(data) { const { areaId, event } = data; const dragState = this.areaStateManager.getDragState(areaId); if (!dragState) return; const dragDuration = Date.now() - dragState.startTime; const distance = dragState.delta ? Math.sqrt(dragState.delta.x ** 2 + dragState.delta.y ** 2) : 0; // 清理拖拽状态 dragState.isDragging = false; dragState.endTime = Date.now(); dragState.endPosition = { x: event.clientX, y: event.clientY }; dragState.totalDistance = distance; dragState.duration = dragDuration; // 触发拖拽结束事件 eventBus.emit(AREA_EVENT_TYPES.AREA_DRAG_END, { areaId, dragInfo: { duration: dragDuration, distance: distance, startPosition: dragState.startPosition, endPosition: dragState.endPosition, delta: dragState.delta, source: dragState.source } }); // 延迟清理拖拽状态 setTimeout(() => { this.areaStateManager.clearDragState(areaId); }, 1000); } /** * 处理Area中心停靠事件 * @param {Object} data - 事件数据 */ async _handleAreaDockCenter(data) { const { areaId, targetAreaId = 'main', mergeStrategy = 'auto' } = data; const areaState = this.areaStateManager.getState(areaId); // 验证停靠条件 if (!areaState || !areaState.tabPages || areaState.tabPages.length === 0) { eventBus.emit(AREA_EVENT_TYPES.AREA_DOCK_CENTER, { areaId, success: false, reason: 'invalid_area_state', message: 'Area状态无效或没有TabPage' }); return; } // 执行停靠逻辑 const dockingResult = { success: true, areaId, targetAreaId, strategy: mergeStrategy, timestamp: Date.now(), mergedTabPages: areaState.tabPages }; // 触发停靠成功事件 eventBus.emit(AREA_EVENT_TYPES.AREA_DOCK_CENTER, dockingResult); // 如果停靠成功,从浮动区域移除 if (dockingResult.success && areaState.type === 'floating') { this.areaStateManager.closeFloatingArea(areaId); } } /** * 处理Area合并事件 * @param {Object} data - 事件数据 */ async _handleAreaMerge(data) { const { sourceAreaId, targetAreaId, mergeType = 'tabPage', mergeOptions = {} } = data; const sourceState = this.areaStateManager.getState(sourceAreaId); const targetState = this.areaStateManager.getState(targetAreaId); if (!sourceState || !targetState) { console.warn(`❌ 合并失败:找不到源Area ${sourceAreaId} 或目标Area ${targetAreaId}`); return; } // 执行合并逻辑 const mergeResult = { sourceAreaId, targetAreaId, mergeType, sourceTabPages: sourceState.tabPages || [], targetTabPages: targetState.tabPages || [], options: mergeOptions, timestamp: Date.now(), success: true }; // 触发合并事件 eventBus.emit(AREA_EVENT_TYPES.AREA_MERGE, mergeResult); // 隐藏源Area(保存到隐藏列表) this.areaStateManager.addToHiddenList(sourceAreaId); } /** * 处理Area调整大小开始事件 * @param {Object} data - 事件数据 */ async _handleAreaResizeStart(data) { const { areaId, resizeType = 'split', direction = 'both' } = data; // 记录调整大小状态 this.areaStateManager.setResizeState(areaId, { isResizing: true, resizeType, direction, startTime: Date.now(), originalSize: data.originalSize || {} }); // 触发调整大小开始事件 eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE_START, { areaId, resizeType, direction, timestamp: Date.now() }); } /** * 处理Area调整大小事件 * @param {Object} data - 事件数据 */ async _handleAreaResize(data) { const { areaId, size, delta } = data; const resizeState = this.areaStateManager.getResizeState(areaId); if (!resizeState || !resizeState.isResizing) return; // 更新调整大小状态 resizeState.currentSize = size; resizeState.delta = delta; resizeState.lastUpdate = Date.now(); // 更新Area状态 const areaState = this.areaStateManager.getState(areaId); if (areaState) { this.areaStateManager.updateState(areaId, { width: size.width, height: size.height, ratio: size.ratio }); } // 触发调整大小事件 eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE, { areaId, size, delta, resizeType: resizeState.resizeType, timestamp: Date.now() }); } /** * 处理Area调整大小结束事件 * @param {Object} data - 事件数据 */ async _handleAreaResizeEnd(data) { const { areaId, finalSize } = data; const resizeState = this.areaStateManager.getResizeState(areaId); if (!resizeState) return; const resizeDuration = Date.now() - resizeState.startTime; // 清理调整大小状态 resizeState.isResizing = false; resizeState.endTime = Date.now(); resizeState.duration = resizeDuration; resizeState.finalSize = finalSize; // 更新最终的Area状态 if (finalSize) { this.areaStateManager.updateState(areaId, { width: finalSize.width, height: finalSize.height, ratio: finalSize.ratio, lastResizedAt: Date.now() }); } // 触发调整大小结束事件 eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE_END, { areaId, resizeInfo: { duration: resizeDuration, originalSize: resizeState.originalSize, finalSize, delta: resizeState.delta }, timestamp: Date.now() }); // 延迟清理调整大小状态 setTimeout(() => { this.areaStateManager.clearResizeState(areaId); }, 500); } /** * 处理浮动Area创建事件 * @param {Object} data - 事件数据 */ async _handleFloatingAreaCreate(data) { const { areaId, config } = data; // 激活浮动Area this.activeAreas.add(areaId); // 设置默认z-index const zIndex = config.zIndex || 1001 + this.areaStateManager.floatingAreas.size; // 更新z-index状态 this.areaStateManager.updateState(areaId, { zIndex, lastActivatedAt: Date.now() }); // 触发层级管理事件 eventBus.emit(AREA_EVENT_TYPES.AREA_ZINDEX_MANAGEMENT, { areaId, action: 'create_floating', zIndex, timestamp: Date.now() }); } /** * 启动内存保护机制 */ _startMemoryProtection() { setInterval(() => { this._onMemoryCheck(); }, this.memoryProtection.cleanupInterval); } /** * 内存检查和清理 */ _onMemoryCheck() { const now = Date.now(); // 清理过期历史记录 this.areaStateManager.cleanupHistory(); // 检查Area数量限制 if (this.areaStateManager.states.size > this.memoryProtection.maxAreas) { console.warn(`⚠️ Area数量超过限制: ${this.areaStateManager.states.size}`); // 清理最旧的活动Area const inactiveAreas = Array.from(this.areaStateManager.states.entries()) .filter(([_, state]) => !state.active && !state.floating) .sort((a, b) => (a[1].lastActivatedAt || 0) - (b[1].lastActivatedAt || 0)); const toRemove = inactiveAreas.slice(0, 5); // 移除5个最旧的 toRemove.forEach(([areaId]) => { this.areaStateManager.states.delete(areaId); console.log(`🗑️ 清理过期Area: ${areaId}`); }); } this.memoryProtection.lastCleanup = now; } /** * 获取Area状态 * @param {string} areaId - Area ID * @returns {Object} Area状态 */ getAreaState(areaId) { return this.areaStateManager.getState(areaId); } /** * 获取所有活动Area * @returns {Array} 活动Area ID列表 */ getActiveAreas() { return Array.from(this.activeAreas); } /** * 获取拖拽状态 * @param {string} areaId - Area ID * @returns {Object} 拖拽状态 */ getDragState(areaId) { return this.areaStateManager.getDragState(areaId); } /** * 获取调整大小状态 * @param {string} areaId - Area ID * @returns {Object} 调整大小状态 */ getResizeState(areaId) { return this.areaStateManager.getResizeState(areaId); } /** * 获取统计信息 * @returns {Object} 统计信息 */ getStats() { return { ...this.areaStateManager.getStats(), activeAreas: this.activeAreas.size }; } /** * 销毁事件处理器 */ destroy() { // 清理事件监听器 this.areaListeners.forEach((listener, eventType) => { eventBus.off(eventType, listener); }); this.areaListeners.clear(); // 清理状态 this.areaStateManager.states.clear(); this.areaStateManager.floatingAreas.clear(); this.areaStateManager.dragState.clear(); this.areaStateManager.resizeState.clear(); this.activeAreas.clear(); console.log('🗑️ Area事件处理器已销毁'); } } // 创建单例实例 const areaHandler = new AreaEventHandler(); // Area便捷操作函数 export const areaActions = { /** * 创建浮动Area * @param {Object} config - Area配置 * @returns {string} Area ID */ createFloating: (config = {}) => { const areaId = areaHandler.areaStateManager.createFloatingArea(config); return areaId; }, /** * 关闭浮动Area * @param {string} areaId - Area ID * @returns {boolean} 是否成功 */ closeFloating: (areaId) => { return areaHandler.areaStateManager.closeFloatingArea(areaId); }, /** * 更新浮动Area位置 * @param {string} areaId - Area ID * @param {Object} position - 位置信息 * @returns {boolean} 是否成功 */ updatePosition: (areaId, position) => { return areaHandler.areaStateManager.updateFloatingAreaPosition(areaId, position); }, /** * 开始Area拖拽 * @param {string} areaId - Area ID * @param {Event} event - 拖拽事件 * @param {string} source - 拖拽源 */ startDrag: (areaId, event, source = 'direct') => { eventBus.emit(AREA_EVENT_TYPES.AREA_DRAG_START, { areaId, event, source, timestamp: Date.now() }); }, /** * Area拖拽移动 * @param {string} areaId - Area ID * @param {Event} event - 拖拽事件 */ moveDrag: (areaId, event) => { eventBus.emit(AREA_EVENT_TYPES.AREA_DRAG_MOVE, { areaId, event, timestamp: Date.now() }); }, /** * 结束Area拖拽 * @param {string} areaId - Area ID * @param {Event} event - 拖拽事件 */ endDrag: (areaId, event) => { eventBus.emit(AREA_EVENT_TYPES.AREA_DRAG_END, { areaId, event, timestamp: Date.now() }); }, /** * Area停靠到中心 * @param {string} areaId - Area ID * @param {string} targetAreaId - 目标Area ID * @param {string} mergeStrategy - 合并策略 */ dockToCenter: (areaId, targetAreaId = 'main', mergeStrategy = 'auto') => { eventBus.emit(AREA_EVENT_TYPES.AREA_DOCK_CENTER, { areaId, targetAreaId, mergeStrategy, timestamp: Date.now() }); }, /** * Area合并 * @param {string} sourceAreaId - 源Area ID * @param {string} targetAreaId - 目标Area ID * @param {string} mergeType - 合并类型 * @param {Object} mergeOptions - 合并选项 */ merge: (sourceAreaId, targetAreaId, mergeType = 'tabPage', mergeOptions = {}) => { eventBus.emit(AREA_EVENT_TYPES.AREA_MERGE, { sourceAreaId, targetAreaId, mergeType, mergeOptions, timestamp: Date.now() }); }, /** * 开始调整Area大小 * @param {string} areaId - Area ID * @param {Object} originalSize - 原始大小 * @param {string} resizeType - 调整类型 * @param {string} direction - 调整方向 */ startResize: (areaId, originalSize, resizeType = 'split', direction = 'both') => { eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE_START, { areaId, originalSize, resizeType, direction, timestamp: Date.now() }); }, /** * Area调整大小 * @param {string} areaId - Area ID * @param {Object} size - 当前大小 * @param {Object} delta - 大小变化 */ resize: (areaId, size, delta) => { eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE, { areaId, size, delta, timestamp: Date.now() }); }, /** * 结束调整Area大小 * @param {string} areaId - Area ID * @param {Object} finalSize - 最终大小 */ endResize: (areaId, finalSize) => { eventBus.emit(AREA_EVENT_TYPES.AREA_RESIZE_END, { areaId, finalSize, timestamp: Date.now() }); }, /** * 最大化Area * @param {string} areaId - Area ID * @param {Object} options - 选项 */ maximize: (areaId, options = {}) => { eventBus.emit(AREA_EVENT_TYPES.AREA_MAXIMIZE, { areaId, ...options, timestamp: Date.now() }); }, /** * 恢复Area * @param {string} areaId - Area ID * @param {Object} options - 选项 */ restore: (areaId, options = {}) => { eventBus.emit(AREA_EVENT_TYPES.AREA_RESTORE, { areaId, ...options, timestamp: Date.now() }); }, /** * 折叠Area * @param {string} areaId - Area ID * @param {Object} options - 选项 */ collapse: (areaId, options = {}) => { eventBus.emit(AREA_EVENT_TYPES.AREA_COLLAPSE, { areaId, ...options, timestamp: Date.now() }); }, /** * 展开Area * @param {string} areaId - Area ID * @param {Object} options - 选项 */ expand: (areaId, options = {}) => { eventBus.emit(AREA_EVENT_TYPES.AREA_EXPAND, { areaId, ...options, timestamp: Date.now() }); }, /** * 关闭Area * @param {string} areaId - Area ID * @param {Object} options - 选项 */ close: (areaId, options = {}) => { eventBus.emit(AREA_EVENT_TYPES.AREA_CLOSE, { areaId, ...options, timestamp: Date.now() }); }, /** * 切换工具栏 * @param {string} areaId - Area ID * @param {Object} options - 选项 */ toggleToolbar: (areaId, options = {}) => { eventBus.emit(AREA_EVENT_TYPES.AREA_TOGGLE_TOOLBAR, { areaId, ...options, timestamp: Date.now() }); }, /** * 更新Area状态 * @param {string} areaId - Area ID * @param {Object} updates - 状态更新 */ updateState: (areaId, updates) => { areaHandler.areaStateManager.updateState(areaId, updates); } }; // 导出事件处理器和相关API export default areaHandler; // 便利的Area拖拽处理函数 export const triggerAreaDrag = { /** * 开始Area拖拽 * @param {string} areaId - Area ID * @param {Event} event - 拖拽事件 */ start: (areaId, event) => { areaActions.startDrag(areaId, event, 'direct'); }, /** * 处理Area拖拽移动 * @param {string} areaId - Area ID * @param {Event} event - 拖拽事件 */ move: (areaId, event) => { areaActions.moveDrag(areaId, event); }, /** * 结束Area拖拽 * @param {string} areaId - Area ID * @param {Event} event - 拖拽事件 */ end: (areaId, event) => { areaActions.endDrag(areaId, event); } };