/** * 拖拽状态管理器 * 统一管理所有组件的拖拽状态,提供拖拽历史、性能监控、冲突检测等功能 */ import { eventBus } from '../eventBus'; import { GLOBAL_EVENT_TYPES, globalEventActions } from './GlobalEventManager'; // 拖拽状态类型 export const DRAG_STATE_TYPES = { // 拖拽操作 DRAG_START: 'drag.state.start', DRAG_MOVE: 'drag.state.move', DRAG_END: 'drag.state.end', DRAG_CANCEL: 'drag.state.cancel', // 拖拽状态变更 DRAG_STATE_CHANGE: 'drag.state.change', DRAG_STATE_ENTER: 'drag.state.enter', DRAG_STATE_EXIT: 'drag.state.exit', // 拖拽冲突 DRAG_CONFLICT_DETECT: 'drag.conflict.detect', DRAG_CONFLICT_RESOLVE: 'drag.conflict.resolve', DRAG_CONFLICT_ESCALATE: 'drag.conflict.escalate', // 拖拽目标 DRAG_TARGET_DETECT: 'drag.target.detect', DRAG_TARGET_ENTER: 'drag.target.enter', DRAG_TARGET_EXIT: 'drag.target.exit', DRAG_TARGET_VALIDATE: 'drag.target.validate', // 拖拽反馈 DRAG_FEEDBACK_UPDATE: 'drag.feedback.update', DRAG_FEEDBACK_SHOW: 'drag.feedback.show', DRAG_FEEDBACK_HIDE: 'drag.feedback.hide', // 拖拽性能 DRAG_PERFORMANCE_MONITOR: 'drag.performance.monitor', DRAG_PERFORMANCE_THRESHOLD: 'drag.performance.threshold', // 拖拽历史 DRAG_HISTORY_RECORD: 'drag.history.record', DRAG_HISTORY_ANALYZE: 'drag.history.analyze', DRAG_HISTORY_CLEANUP: 'drag.history.cleanup' }; // 拖拽区域类型 export const DRAG_AREA_TYPES = { PANEL: 'panel', TABPAGE: 'tabpage', AREA: 'area', WINDOW: 'window', DESKTOP: 'desktop' }; // 拖拽状态类 class DragState { constructor(dragId, componentType, sourceElement, options = {}) { this.dragId = dragId; this.componentType = componentType; this.sourceElement = sourceElement; this.startTime = Date.now(); this.lastUpdateTime = this.startTime; this.status = 'pending'; // pending, active, completed, cancelled, error this.currentPosition = { x: 0, y: 0 }; this.startPosition = { x: 0, y: 0 }; this.targetElement = null; this.targetArea = null; this.dragVector = { x: 0, y: 0 }; this.velocity = { x: 0, y: 0 }; this.acceleration = { x: 0, y: 0 }; this.conflicts = []; this.feedback = { visible: false, position: { x: 0, y: 0 }, content: '', type: 'default' // default, invalid, valid, warning }; this.performance = { totalDuration: 0, moveCount: 0, averageFrameTime: 0, fps: 0, maxFrameTime: 0 }; this.options = { ...options, threshold: options.threshold || 5, maxSpeed: options.maxSpeed || 1000, targetThreshold: options.targetThreshold || 20, feedbackDelay: options.feedbackDelay || 100, performanceThreshold: options.performanceThreshold || 16 // 60fps threshold }; this.metadata = options.metadata || {}; this.listeners = new Map(); this.history = []; } /** * 更新拖拽位置 * @param {number} x - X坐标 * @param {number} y - Y坐标 * @param {number} timestamp - 时间戳 */ updatePosition(x, y, timestamp = Date.now()) { const oldPosition = { ...this.currentPosition }; const deltaTime = timestamp - this.lastUpdateTime; // 更新位置 this.currentPosition = { x, y }; this.lastUpdateTime = timestamp; // 计算拖拽向量 this.dragVector = { x: x - this.startPosition.x, y: y - this.startPosition.y }; // 计算速度(像素/毫秒) if (deltaTime > 0) { this.velocity = { x: (x - oldPosition.x) / deltaTime * 1000, y: (y - oldPosition.y) / deltaTime * 1000 }; // 计算加速度 if (this.history.length > 0) { const prevVelocity = this.history[this.history.length - 1].velocity; this.acceleration = { x: (this.velocity.x - prevVelocity.x) / deltaTime * 1000, y: (this.velocity.y - prevVelocity.y) / deltaTime * 1000 }; } } // 记录历史 this.history.push({ timestamp, position: { ...this.currentPosition }, velocity: { ...this.velocity }, acceleration: { ...this.acceleration } }); // 限制历史大小 if (this.history.length > 100) { this.history.shift(); } // 更新性能指标 this._updatePerformanceMetrics(deltaTime); } /** * 更新性能指标 * @param {number} deltaTime - 时间间隔 */ _updatePerformanceMetrics(deltaTime) { this.performance.moveCount++; if (deltaTime > 0) { const frameTime = deltaTime; const newAverageTime = (this.performance.averageFrameTime * (this.performance.moveCount - 1) + frameTime) / this.performance.moveCount; this.performance.averageFrameTime = newAverageTime; this.performance.fps = 1000 / newAverageTime; this.performance.maxFrameTime = Math.max(this.performance.maxFrameTime, frameTime); } this.performance.totalDuration = Date.now() - this.startTime; } /** * 设置目标元素 * @param {Element} targetElement - 目标元素 * @param {string} targetArea - 目标区域类型 */ setTarget(targetElement, targetArea = null) { this.targetElement = targetElement; this.targetArea = targetArea; } /** * 添加冲突 * @param {Object} conflict - 冲突信息 */ addConflict(conflict) { this.conflicts.push({ ...conflict, timestamp: Date.now() }); } /** * 清除冲突 */ clearConflicts() { this.conflicts = []; } /** * 更新反馈 * @param {Object} feedback - 反馈信息 */ updateFeedback(feedback) { this.feedback = { ...this.feedback, ...feedback, visible: feedback.visible !== undefined ? feedback.visible : this.feedback.visible }; } /** * 获取状态摘要 * @returns {Object} 状态摘要 */ getSummary() { return { dragId: this.dragId, componentType: this.componentType, status: this.status, startPosition: this.startPosition, currentPosition: this.currentPosition, dragVector: this.dragVector, velocity: this.velocity, targetElement: this.targetElement !== null, targetArea: this.targetArea, conflictCount: this.conflicts.length, performance: this.performance, duration: Date.now() - this.startTime }; } /** * 完成拖拽 * @param {string} status - 完成状态 * @param {Object} result - 结果数据 */ complete(status = 'completed', result = {}) { this.status = status; this.performance.totalDuration = Date.now() - this.startTime; // 清理历史(保留最近50条) if (this.history.length > 50) { this.history = this.history.slice(-50); } } } // 拖拽冲突检测器 class DragConflictDetector { constructor() { this.activeDrags = new Map(); this.conflictRules = new Map(); this.conflictHistory = []; this.maxHistorySize = 200; this._initializeConflictRules(); } /** * 初始化冲突规则 */ _initializeConflictRules() { // 面板拖拽冲突规则 this.conflictRules.set('panel', { overlap: { threshold: 0.3, severity: 'warning' }, sameParent: { threshold: 0.5, severity: 'error' }, lockedElement: { threshold: 0, severity: 'error' } }); // TabPage拖拽冲突规则 this.conflictRules.set('tabpage', { overlap: { threshold: 0.5, severity: 'warning' }, sameTabContainer: { threshold: 0.8, severity: 'info' }, readonlyTab: { threshold: 0, severity: 'error' } }); // Area拖拽冲突规则 this.conflictRules.set('area', { overlap: { threshold: 0.4, severity: 'warning' }, minimumSize: { threshold: 0, severity: 'error' }, lockedArea: { threshold: 0, severity: 'error' } }); } /** * 注册拖拽 * @param {DragState} dragState - 拖拽状态 */ registerDrag(dragState) { this.activeDrags.set(dragState.dragId, dragState); } /** * 注销拖拽 * @param {string} dragId - 拖拽ID */ unregisterDrag(dragId) { this.activeDrags.delete(dragId); } /** * 检测冲突 * @param {string} dragId - 拖拽ID * @returns {Array} 冲突列表 */ detectConflicts(dragId) { const currentDrag = this.activeDrags.get(dragId); if (!currentDrag) return []; const conflicts = []; for (const [otherId, otherDrag] of this.activeDrags) { if (otherId === dragId) continue; // 跳过已完成的拖拽 if (otherDrag.status === 'completed' || otherDrag.status === 'cancelled') { continue; } const conflict = this._checkDragConflict(currentDrag, otherDrag); if (conflict) { conflicts.push(conflict); } } // 记录冲突历史 if (conflicts.length > 0) { this.conflictHistory.push({ dragId, conflicts, timestamp: Date.now() }); // 限制历史大小 if (this.conflictHistory.length > this.maxHistorySize) { this.conflictHistory.shift(); } } return conflicts; } /** * 检查两个拖拽之间的冲突 * @param {DragState} drag1 - 拖拽1 * @param {DragState} drag2 - 拖拽2 * @returns {Object|null} 冲突信息 */ _checkDragConflict(drag1, drag2) { const rules1 = this.conflictRules.get(drag1.componentType); const rules2 = this.conflictRules.get(drag2.componentType); if (!rules1 && !rules2) return null; // 计算元素重叠程度 const overlap = this._calculateOverlap(drag1, drag2); // 检查各种冲突类型 const conflicts = []; // 位置冲突 if (overlap > 0.3) { const severity = overlap > 0.7 ? 'error' : overlap > 0.5 ? 'warning' : 'info'; conflicts.push({ type: 'overlap', severity, value: overlap, message: `元素重叠度达到 ${(overlap * 100).toFixed(1)}%` }); } // 速度冲突 const relativeSpeed = Math.sqrt( Math.pow(drag1.velocity.x - drag2.velocity.x, 2) + Math.pow(drag1.velocity.y - drag2.velocity.y, 2) ); if (relativeSpeed > 500) { // 像素/秒 conflicts.push({ type: 'high_speed', severity: 'warning', value: relativeSpeed, message: `相对速度过高: ${relativeSpeed.toFixed(1)} px/s` }); } // 同级拖拽冲突 if (drag1.componentType === drag2.componentType) { const centerDistance = Math.sqrt( Math.pow(drag1.currentPosition.x - drag2.currentPosition.x, 2) + Math.pow(drag1.currentPosition.y - drag2.currentPosition.y, 2) ); if (centerDistance < 100) { conflicts.push({ type: 'proximity', severity: 'info', value: centerDistance, message: `拖拽元素距离过近: ${centerDistance.toFixed(1)}px` }); } } return conflicts.length > 0 ? { drag1Id: drag1.dragId, drag2Id: drag2.dragId, conflicts, timestamp: Date.now() } : null; } /** * 计算两个拖拽元素的重叠度 * @param {DragState} drag1 - 拖拽1 * @param {DragState} drag2 - 拖拽2 * @returns {number} 重叠度 (0-1) */ _calculateOverlap(drag1, drag2) { // 简化的重叠计算,假设元素尺寸为100x100 const elementSize = 100; const rect1 = { left: drag1.currentPosition.x, top: drag1.currentPosition.y, right: drag1.currentPosition.x + elementSize, bottom: drag1.currentPosition.y + elementSize }; const rect2 = { left: drag2.currentPosition.x, top: drag2.currentPosition.y, right: drag2.currentPosition.x + elementSize, bottom: drag2.currentPosition.y + elementSize }; // 计算重叠矩形 const overlapLeft = Math.max(rect1.left, rect2.left); const overlapTop = Math.max(rect1.top, rect2.top); const overlapRight = Math.min(rect1.right, rect2.right); const overlapBottom = Math.min(rect1.bottom, rect2.bottom); if (overlapRight <= overlapLeft || overlapBottom <= overlapTop) { return 0; // 无重叠 } const overlapWidth = overlapRight - overlapLeft; const overlapHeight = overlapBottom - overlapTop; const overlapArea = overlapWidth * overlapHeight; const elementArea = elementSize * elementSize; return Math.min(overlapArea / elementArea, 1); } /** * 获取冲突统计 * @returns {Object} 冲突统计 */ getConflictStats() { const totalConflicts = this.conflictHistory.length; const recentConflicts = this.conflictHistory.filter(c => Date.now() - c.timestamp < 60000 // 最近1分钟 ).length; const severityCounts = { error: 0, warning: 0, info: 0 }; this.conflictHistory.forEach(entry => { entry.conflicts.forEach(conflict => { severityCounts[conflict.severity] = (severityCounts[conflict.severity] || 0) + 1; }); }); return { totalConflicts, recentConflicts, activeDrags: this.activeDrags.size, severityCounts, conflictRate: totalConflicts > 0 ? totalConflicts / (this.activeDrags.size || 1) : 0 }; } } // 拖拽状态管理器主类 class DragStateManager { constructor() { this.activeDrags = new Map(); this.dragHistory = []; this.conflictDetector = new DragConflictDetector(); this.dragTargets = new Map(); this.performanceThresholds = { dragDuration: 5000, // 5秒 moveCount: 1000, // 1000次移动 fps: 30, // 30fps最低要求 maxVelocity: 2000 // 最大速度限制 }; this.isEnabled = true; this.debugMode = false; // 绑定方法 this._onDragEvent = this._onDragEvent.bind(this); this._cleanupExpiredData = this._cleanupExpiredData.bind(this); this._initialize(); } /** * 初始化 */ _initialize() { // 注册拖拽相关事件监听器 this._registerEventListeners(); // 启动清理调度器 this._startCleanupScheduler(); console.log('🎯 拖拽状态管理器初始化完成'); } /** * 注册事件监听器 */ _registerEventListeners() { // 防止重复注册监听器 if (this.eventListenersRegistered) { return; } const dragEvents = [ // Panel拖拽事件 'panel.drag.start', 'panel.drag.move', 'panel.drag.end', 'panel.drag.cancel', // TabPage拖拽事件 'tabpage.drag.start', 'tabpage.drag.move', 'tabpage.drag.end', 'tabpage.drag.cancel', // Area拖拽事件 'area.drag.start', 'area.drag.move', 'area.drag.end', 'area.drag.cancel' ]; dragEvents.forEach(eventType => { eventBus.on(eventType, this._onDragEvent, { priority: 1, deduplication: { type: 'EVENT_BASED', key: 'dragState' } }); }); this.eventListenersRegistered = true; } /** * 销毁管理器 */ destroy() { // 清理事件监听器 const dragEvents = [ // Panel拖拽事件 'panel.drag.start', 'panel.drag.move', 'panel.drag.end', 'panel.drag.cancel', // TabPage拖拽事件 'tabpage.drag.start', 'tabpage.drag.move', 'tabpage.drag.end', 'tabpage.drag.cancel', // Area拖拽事件 'area.drag.start', 'area.drag.move', 'area.drag.end', 'area.drag.cancel' ]; dragEvents.forEach(eventType => { eventBus.off(eventType, this._onDragEvent); }); // 清理清理调度器 this._stopCleanupScheduler(); // 清理拖拽状态 this.dragStates.clear(); this.dragHistory = []; console.log('🗑️ 拖拽状态管理器已销毁'); } /** * 处理拖拽事件 * @param {Object} data - 事件数据 */ async _onDragEvent(data) { if (!this.isEnabled) return; const monitorId = globalEventActions.startMonitor(`drag_${data.eventType || data.type}`); try { const { eventType = data.type, dragId, componentType, sourceElement } = data; switch (eventType) { case 'panel.drag.start': case 'tabpage.drag.start': case 'area.drag.start': await this._handleDragStart(data); break; case 'panel.drag.move': case 'tabpage.drag.move': case 'area.drag.move': await this._handleDragMove(data); break; case 'panel.drag.end': case 'tabpage.drag.end': case 'area.drag.end': await this._handleDragEnd(data); break; case 'panel.drag.cancel': case 'tabpage.drag.cancel': case 'area.drag.cancel': await this._handleDragCancel(data); break; } } catch (error) { console.error('❌ 拖拽状态管理错误:', error); eventBus.emit(GLOBAL_EVENT_TYPES.SYSTEM_ERROR, { component: 'dragStateManager', event: data, error: error.message }); } finally { globalEventActions.endMonitor(monitorId); } } /** * 处理拖拽开始 * @param {Object} data - 事件数据 */ async _handleDragStart(data) { const { dragId, componentType, sourceElement, position, options = {} } = data; // 创建拖拽状态 const dragState = new DragState(dragId, componentType, sourceElement, options); dragState.startPosition = { ...position }; dragState.currentPosition = { ...position }; dragState.status = 'active'; // 保存拖拽状态 this.activeDrags.set(dragId, dragState); // 注册到冲突检测器 this.conflictDetector.registerDrag(dragState); // 触发状态变更事件 eventBus.emit(DRAG_STATE_TYPES.DRAG_STATE_CHANGE, { dragId, newStatus: 'active', dragState: dragState.getSummary() }); // 发送初始反馈 if (this.debugMode) { this._updateDragFeedback(dragId, { visible: true, content: `开始拖拽 ${componentType}`, type: 'default', position: { ...position } }); } if (this.debugMode) { console.log(`🎯 拖拽开始: ${dragId} (${componentType})`, position); } } /** * 处理拖拽移动 * @param {Object} data - 事件数据 */ async _handleDragMove(data) { const { dragId, position, targetElement, targetArea } = data; const dragState = this.activeDrags.get(dragId); if (!dragState || dragState.status !== 'active') return; // 更新位置 dragState.updatePosition(position.x, position.y); // 设置目标 if (targetElement) { dragState.setTarget(targetElement, targetArea); } // 检测冲突 const conflicts = this.conflictDetector.detectConflicts(dragId); if (conflicts.length > 0) { conflicts.forEach(conflict => { dragState.addConflict(conflict); eventBus.emit(DRAG_STATE_TYPES.DRAG_CONFLICT_DETECT, { dragId, conflict }); }); // 更新反馈显示冲突 this._updateDragFeedback(dragId, { content: `检测到 ${conflicts.length} 个冲突`, type: 'warning' }); } else { // 清除冲突 dragState.clearConflicts(); // 更新反馈显示正常状态 this._updateDragFeedback(dragId, { content: '拖拽中...', type: 'valid' }); } // 检测目标 this._detectDragTargets(dragId, position); // 检查性能阈值 this._checkPerformanceThresholds(dragId); if (this.debugMode && dragState.performance.moveCount % 50 === 0) { console.log(`🎯 拖拽移动: ${dragId} (${dragState.performance.moveCount} 次移动, FPS: ${dragState.performance.fps.toFixed(1)})`); } } /** * 处理拖拽结束 * @param {Object} data - 事件数据 */ async _handleDragEnd(data) { const { dragId, finalPosition, dropTarget, success = true } = data; const dragState = this.activeDrags.get(dragId); if (!dragState) return; // 完成拖拽 dragState.complete('completed', { success, finalPosition, dropTarget }); // 记录到历史 this._recordDragHistory(dragState); // 清除反馈 this._hideDragFeedback(dragId); // 从活跃拖拽中移除 this.activeDrags.delete(dragId); // 从冲突检测器注销 this.conflictDetector.unregisterDrag(dragId); // 触发状态变更事件 eventBus.emit(DRAG_STATE_TYPES.DRAG_STATE_CHANGE, { dragId, newStatus: 'completed', dragState: dragState.getSummary(), finalPosition, dropTarget, success }); // 触发性能监控事件 eventBus.emit(DRAG_STATE_TYPES.DRAG_PERFORMANCE_MONITOR, { dragId, performance: dragState.performance, summary: dragState.getSummary() }); if (this.debugMode) { console.log(`🎯 拖拽结束: ${dragId} (${success ? '成功' : '失败'}, 耗时: ${dragState.performance.totalDuration}ms)`); } } /** * 处理拖拽取消 * @param {Object} data - 事件数据 */ async _handleDragCancel(data) { const { dragId, reason } = data; const dragState = this.activeDrags.get(dragId); if (!dragState) return; // 取消拖拽 dragState.complete('cancelled', { reason }); // 记录到历史 this._recordDragHistory(dragState); // 清除反馈 this._hideDragFeedback(dragId); // 从活跃拖拽中移除 this.activeDrags.delete(dragId); // 从冲突检测器注销 this.conflictDetector.unregisterDrag(dragId); // 触发状态变更事件 eventBus.emit(DRAG_STATE_TYPES.DRAG_STATE_CHANGE, { dragId, newStatus: 'cancelled', dragState: dragState.getSummary(), reason }); if (this.debugMode) { console.log(`🎯 拖拽取消: ${dragId} (原因: ${reason})`); } } /** * 检测拖拽目标 * @param {string} dragId - 拖拽ID * @param {Object} position - 位置 */ _detectDragTargets(dragId, position) { const dragState = this.activeDrags.get(dragId); if (!dragState) return; // 这里应该实现实际的拖拽目标检测逻辑 // 简化实现:检测是否在某个区域内 const targets = this._findPotentialTargets(position, dragState.componentType); if (targets.length > 0) { // 验证目标有效性 targets.forEach(target => { const isValid = this._validateDragTarget(dragState, target); eventBus.emit(DRAG_STATE_TYPES.DRAG_TARGET_DETECT, { dragId, target, position, valid: isValid }); if (isValid) { eventBus.emit(DRAG_STATE_TYPES.DRAG_TARGET_VALIDATE, { dragId, target, action: 'enter' }); } }); } } /** * 查找潜在拖拽目标 * @param {Object} position - 位置 * @param {string} componentType - 组件类型 * @returns {Array} 潜在目标列表 */ _findPotentialTargets(position, componentType) { // 简化的目标查找逻辑 // 实际实现应该检查DOM元素的实际位置 const targets = []; // 模拟不同类型的拖拽目标 const mockTargets = [ { id: 'area-center', type: 'area', bounds: { x: 200, y: 200, width: 400, height: 300 } }, { id: 'tab-container', type: 'tabpage', bounds: { x: 50, y: 50, width: 200, height: 100 } }, { id: 'panel-dock', type: 'panel', bounds: { x: 100, y: 400, width: 150, height: 50 } } ]; mockTargets.forEach(target => { const { x, y } = position; const { bounds } = target; if (x >= bounds.x && x <= bounds.x + bounds.width && y >= bounds.y && y <= bounds.y + bounds.height) { targets.push(target); } }); return targets; } /** * 验证拖拽目标 * @param {DragState} dragState - 拖拽状态 * @param {Object} target - 目标 * @returns {boolean} 是否有效 */ _validateDragTarget(dragState, target) { // 简化的验证逻辑 const maxDistance = 50; // 最大距离限制 const centerX = dragState.currentPosition.x + 50; // 假设元素宽度为100 const centerY = dragState.currentPosition.y + 50; const targetCenterX = target.bounds.x + target.bounds.width / 2; const targetCenterY = target.bounds.y + target.bounds.height / 2; const distance = Math.sqrt( Math.pow(centerX - targetCenterX, 2) + Math.pow(centerY - targetCenterY, 2) ); return distance <= maxDistance; } /** * 检查性能阈值 * @param {string} dragId - 拖拽ID */ _checkPerformanceThresholds(dragId) { const dragState = this.activeDrags.get(dragId); if (!dragState) return; const { performance } = dragState; const thresholdViolations = []; // 检查拖拽持续时间 if (performance.totalDuration > this.performanceThresholds.dragDuration) { thresholdViolations.push({ type: 'duration', value: performance.totalDuration, threshold: this.performanceThresholds.dragDuration, message: `拖拽持续时间超过阈值: ${performance.totalDuration}ms > ${this.performanceThresholds.dragDuration}ms` }); } // 检查移动次数 if (performance.moveCount > this.performanceThresholds.moveCount) { thresholdViolations.push({ type: 'moveCount', value: performance.moveCount, threshold: this.performanceThresholds.moveCount, message: `移动次数过多: ${performance.moveCount} > ${this.performanceThresholds.moveCount}` }); } // 检查FPS if (performance.fps < this.performanceThresholds.fps && performance.moveCount > 10) { thresholdViolations.push({ type: 'fps', value: performance.fps, threshold: this.performanceThresholds.fps, message: `帧率过低: ${performance.fps.toFixed(1)}fps < ${this.performanceThresholds.fps}fps` }); } // 检查速度 const speed = Math.sqrt(dragState.velocity.x ** 2 + dragState.velocity.y ** 2); if (speed > this.performanceThresholds.maxVelocity) { thresholdViolations.push({ type: 'velocity', value: speed, threshold: this.performanceThresholds.maxVelocity, message: `拖拽速度过快: ${speed.toFixed(1)}px/s > ${this.performanceThresholds.maxVelocity}px/s` }); } if (thresholdViolations.length > 0) { eventBus.emit(DRAG_STATE_TYPES.DRAG_PERFORMANCE_THRESHOLD, { dragId, violations: thresholdViolations, performance: dragState.performance }); } } /** * 更新拖拽反馈 * @param {string} dragId - 拖拽ID * @param {Object} feedback - 反馈信息 */ _updateDragFeedback(dragId, feedback) { const dragState = this.activeDrags.get(dragId); if (!dragState) return; dragState.updateFeedback(feedback); eventBus.emit(DRAG_STATE_TYPES.DRAG_FEEDBACK_UPDATE, { dragId, feedback: dragState.feedback }); } /** * 隐藏拖拽反馈 * @param {string} dragId - 拖拽ID */ _hideDragFeedback(dragId) { const dragState = this.activeDrags.get(dragId); if (!dragState) return; dragState.updateFeedback({ visible: false }); eventBus.emit(DRAG_STATE_TYPES.DRAG_FEEDBACK_HIDE, { dragId }); } /** * 记录拖拽历史 * @param {DragState} dragState - 拖拽状态 */ _recordDragHistory(dragState) { const historyEntry = { dragId: dragState.dragId, componentType: dragState.componentType, startTime: dragState.startTime, endTime: Date.now(), duration: dragState.performance.totalDuration, moveCount: dragState.performance.moveCount, conflictCount: dragState.conflicts.length, finalPosition: { ...dragState.currentPosition }, dragVector: { ...dragState.dragVector }, averageFPS: dragState.performance.fps, metadata: dragState.metadata }; this.dragHistory.push(historyEntry); // 限制历史大小 if (this.dragHistory.length > 1000) { this.dragHistory.shift(); } // 触发历史记录事件 eventBus.emit(DRAG_STATE_TYPES.DRAG_HISTORY_RECORD, { historyEntry, totalHistorySize: this.dragHistory.length }); } /** * 启动清理调度器 */ _startCleanupScheduler() { setInterval(() => { this._cleanupExpiredData(); }, 300000); // 每5分钟清理一次 } /** * 清理过期数据 */ _cleanupExpiredData() { const now = Date.now(); const maxAge = 3600000; // 1小时 // 清理过期的历史记录 this.dragHistory = this.dragHistory.filter(entry => (now - entry.endTime) < maxAge ); // 清理冲突历史 this.conflictDetector.conflictHistory = this.conflictDetector.conflictHistory.filter(entry => (now - entry.timestamp) < maxAge ); // 触发清理事件 eventBus.emit(DRAG_STATE_TYPES.DRAG_HISTORY_CLEANUP, { cleanedHistoryCount: this.dragHistory.length, cleanedConflictCount: this.conflictDetector.conflictHistory.length }); } /** * 获取拖拽状态 * @param {string} dragId - 拖拽ID * @returns {Object|null} 拖拽状态 */ getDragState(dragId) { const dragState = this.activeDrags.get(dragId); return dragState ? dragState.getSummary() : null; } /** * 获取所有活跃拖拽 * @returns {Array} 活跃拖拽列表 */ getActiveDrags() { return Array.from(this.activeDrags.values()).map(dragState => dragState.getSummary()); } /** * 获取拖拽历史 * @param {number} limit - 限制数量 * @returns {Array} 历史记录 */ getDragHistory(limit = 100) { return this.dragHistory.slice(-limit); } /** * 获取拖拽统计 * @returns {Object} 拖拽统计 */ getDragStats() { const activeCount = this.activeDrags.size; const historyCount = this.dragHistory.length; // 计算平均性能指标 const avgStats = { averageDuration: 0, averageMoveCount: 0, averageFPS: 0, totalConflicts: 0 }; if (historyCount > 0) { const recentHistory = this.dragHistory.slice(-100); avgStats.averageDuration = recentHistory.reduce((sum, entry) => sum + entry.duration, 0) / recentHistory.length; avgStats.averageMoveCount = recentHistory.reduce((sum, entry) => sum + entry.moveCount, 0) / recentHistory.length; avgStats.averageFPS = recentHistory.reduce((sum, entry) => sum + entry.averageFPS, 0) / recentHistory.length; avgStats.totalConflicts = recentHistory.reduce((sum, entry) => sum + entry.conflictCount, 0); } return { active: { count: activeCount, dragStates: this.getActiveDrags() }, history: { total: historyCount, recent: historyCount > 0 ? this.dragHistory.slice(-10) : [], average: avgStats }, conflicts: this.conflictDetector.getConflictStats(), performance: { thresholds: this.performanceThresholds, violations: this._getRecentPerformanceViolations() } }; } /** * 获取最近的性能违规 * @returns {Array} 违规记录 */ _getRecentPerformanceViolations() { const recent = this.dragHistory.filter(entry => Date.now() - entry.endTime < 60000 // 最近1分钟 ); const violations = []; recent.forEach(entry => { if (entry.duration > this.performanceThresholds.dragDuration) { violations.push({ dragId: entry.dragId, type: 'duration', value: entry.duration, threshold: this.performanceThresholds.dragDuration }); } if (entry.averageFPS < this.performanceThresholds.fps) { violations.push({ dragId: entry.dragId, type: 'fps', value: entry.averageFPS, threshold: this.performanceThresholds.fps }); } }); return violations; } /** * 设置调试模式 * @param {boolean} enabled - 是否启用 */ setDebugMode(enabled) { this.debugMode = enabled; console.log(`🔧 拖拽状态管理器调试模式${enabled ? '开启' : '关闭'}`); } /** * 启用/禁用管理器 * @param {boolean} enabled - 是否启用 */ setEnabled(enabled) { this.isEnabled = enabled; console.log(`🎯 拖拽状态管理器${enabled ? '启用' : '禁用'}`); } /** * 取消所有拖拽 */ cancelAllDrags() { const dragIds = Array.from(this.activeDrags.keys()); dragIds.forEach(dragId => { const dragState = this.activeDrags.get(dragId); if (dragState && dragState.status === 'active') { eventBus.emit(DRAG_STATE_TYPES.DRAG_CANCEL, { dragId, reason: 'manager_cancelled' }); } }); console.log(`🚫 已取消 ${dragIds.length} 个活跃拖拽`); } /** * 面板拖拽开始(从DockLayout.vue迁移) * @param {Object} eventData - 拖拽事件数据 */ onPanelDragStart(eventData) { try { const { event, panelId, element, type = 'panel', position = { x: 0, y: 0 }, ...options } = eventData; // 检查是否有其他活跃拖拽 if (this.activeDrags.size > 0) { console.warn('检测到其他活跃拖拽,暂停之前的拖拽'); this.cancelAllDrags(); } // 创建拖拽ID const dragId = `panel-${panelId}-${Date.now()}`; // 创建拖拽状态 const dragState = new DragState(dragId, DRAG_AREA_TYPES.PANEL, element, { panelId, 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: 'onPanelDragStart', timestamp: Date.now() }); console.log(`🎯 面板拖拽开始: ${panelId}, dragId: ${dragId}`); return dragId; } catch (error) { console.error('面板拖拽开始时出错:', error); eventBus.emit(DRAG_STATE_TYPES.DRAG_PERFORMANCE_MONITOR, { operation: 'onPanelDragStart', error: error.message, timestamp: Date.now() }); return null; } } /** * 面板拖拽移动(从DockLayout.vue迁移) * @param {Object} eventData - 拖拽事件数据 */ onPanelDragMove(eventData) { try { const { event, dragId, panelId, element, type = 'panel', position = { x: 0, y: 0 }, ...options } = eventData; // 查找拖拽状态 const activeDrag = this._findDragByIdOrPanelId(dragId, panelId); if (!activeDrag) { console.warn('找不到面板拖拽状态:', panelId); 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: 'onPanelDragMove', timestamp: Date.now() }); return true; } catch (error) { console.error('面板拖拽移动时出错:', error); eventBus.emit(DRAG_STATE_TYPES.DRAG_PERFORMANCE_MONITOR, { operation: 'onPanelDragMove', error: error.message, timestamp: Date.now() }); return false; } } /** * 面板拖拽结束(从DockLayout.vue迁移) * @param {Object} eventData - 拖拽事件数据 */ onPanelDragEnd(eventData) { try { const { event, dragId, panelId, type = 'panel', finalPosition = { x: 0, y: 0 }, dropTarget, ...options } = eventData; // 查找拖拽状态 const activeDrag = this._findDragByIdOrPanelId(dragId, panelId); if (!activeDrag) { console.warn('找不到面板拖拽状态:', panelId); 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: 'onPanelDragEnd', timestamp: Date.now() }); // 移动到历史记录 this.dragHistory.push(dragState.getSummary()); this.activeDrags.delete(activeDrag.dragId); console.log(`✅ 面板拖拽结束: ${panelId}, dragId: ${dragId}`); return true; } catch (error) { console.error('面板拖拽结束时出错:', error); eventBus.emit(DRAG_STATE_TYPES.DRAG_PERFORMANCE_MONITOR, { operation: 'onPanelDragEnd', error: error.message, timestamp: Date.now() }); return false; } } /** * TabPage拖拽开始(从DockLayout.vue迁移) * @param {Object} eventData - 拖拽事件数据 */ onPanelDragStartFromTabPage(eventData) { try { const { event, tabPageId, element, tabIndex, ...options } = eventData; // 创建拖拽ID const dragId = `tabpage-${tabPageId}-${Date.now()}`; // 创建拖拽状态 const dragState = new DragState(dragId, DRAG_AREA_TYPES.TABPAGE, element, { tabPageId, tabIndex, sourceType: 'tabpage', ...options }); // 设置起始位置 const startX = event.clientX; const startY = event.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: 'onPanelDragStartFromTabPage', timestamp: Date.now() }); console.log(`🎯 TabPage拖拽开始: ${tabPageId}, dragId: ${dragId}`); return dragId; } catch (error) { console.error('TabPage拖拽开始时出错:', error); eventBus.emit(DRAG_STATE_TYPES.DRAG_PERFORMANCE_MONITOR, { operation: 'onPanelDragStartFromTabPage', error: error.message, timestamp: Date.now() }); return null; } } /** * TabPage拖拽移动(从DockLayout.vue迁移) * @param {Object} eventData - 拖拽事件数据 */ onPanelDragMoveFromTabPage(eventData) { try { const { event, dragId, tabPageId, ...options } = eventData; // 查找拖拽状态 const activeDrag = this._findDragByIdOrTabPageId(dragId, tabPageId); if (!activeDrag) { console.warn('找不到TabPage拖拽状态:', tabPageId); return false; } const dragState = activeDrag.dragState; if (dragState.status !== 'active') { console.warn('拖拽状态不活跃:', dragId); return false; } // 更新位置 const currentX = event.clientX; const currentY = event.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: 'onPanelDragMoveFromTabPage', timestamp: Date.now() }); return true; } catch (error) { console.error('TabPage拖拽移动时出错:', error); eventBus.emit(DRAG_STATE_TYPES.DRAG_PERFORMANCE_MONITOR, { operation: 'onPanelDragMoveFromTabPage', error: error.message, timestamp: Date.now() }); return false; } } /** * TabPage拖拽结束(从DockLayout.vue迁移) * @param {Object} eventData - 拖拽事件数据 */ onPanelDragEndFromTabPage(eventData) { try { const { event, dragId, tabPageId, dropTarget, ...options } = eventData; // 查找拖拽状态 const activeDrag = this._findDragByIdOrTabPageId(dragId, tabPageId); if (!activeDrag) { console.warn('找不到TabPage拖拽状态:', tabPageId); return false; } const dragState = activeDrag.dragState; // 更新最终位置 const finalX = event.clientX; const finalY = event.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: 'onPanelDragEndFromTabPage', timestamp: Date.now() }); // 移动到历史记录 this.dragHistory.push(dragState.getSummary()); this.activeDrags.delete(activeDrag.dragId); console.log(`✅ TabPage拖拽结束: ${tabPageId}, dragId: ${dragId}`); return true; } catch (error) { console.error('TabPage拖拽结束时出错:', error); eventBus.emit(DRAG_STATE_TYPES.DRAG_PERFORMANCE_MONITOR, { operation: 'onPanelDragEndFromTabPage', error: error.message, timestamp: Date.now() }); return false; } } /** * 根据ID或Panel ID查找拖拽状态 * @private * @param {string} dragId - 拖拽ID * @param {string} panelId - 面板ID * @returns {Object|null} 拖拽状态 */ _findDragByIdOrPanelId(dragId, panelId) { // 首先尝试通过dragId查找 if (dragId && this.activeDrags.has(dragId)) { return { dragId, dragState: this.activeDrags.get(dragId) }; } // 如果找不到,尝试通过panelId查找 for (const [id, dragState] of this.activeDrags.entries()) { if (dragState.options.panelId === panelId) { return { dragId: id, dragState }; } } return null; } /** * 根据ID或TabPage ID查找拖拽状态 * @private * @param {string} dragId - 拖拽ID * @param {string} tabPageId - TabPage ID * @returns {Object|null} 拖拽状态 */ _findDragByIdOrTabPageId(dragId, tabPageId) { // 首先尝试通过dragId查找 if (dragId && this.activeDrags.has(dragId)) { return { dragId, dragState: this.activeDrags.get(dragId) }; } // 如果找不到,尝试通过tabPageId查找 for (const [id, dragState] of this.activeDrags.entries()) { if (dragState.options.tabPageId === tabPageId) { return { dragId: id, dragState }; } } 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 * @param {number} x - X坐标 * @param {number} y - Y坐标 * @returns {Object|null} 目标信息 */ _detectDragTarget(x, y) { try { // 这里可以实现具体的拖拽目标检测逻辑 // 例如:检测鼠标下的元素类型和区域 // 验证坐标是否为有限值,避免elementFromPoint抛出错误 if (!Number.isFinite(x) || !Number.isFinite(y)) { console.warn('检测拖拽目标时坐标无效:', { x, y }); return null; } // 简化实现:检查坐标是否在预设区域内 const targetAreas = ['main-area', 'floating-area', 'hidden-area']; const detectedArea = targetAreas[Math.floor(Math.random() * targetAreas.length)]; return { element: document.elementFromPoint(x, y), area: detectedArea, position: { x, y } }; } catch (error) { console.error('检测拖拽目标时出错:', error); return null; } } /** * 销毁管理器 */ 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 - 拖拽事件数据 * @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; } } } // 延迟创建单例实例 let dragStateManager = null; /** * 确保单例实例存在 */ function ensureDragStateManagerInstance() { if (!dragStateManager) { dragStateManager = new DragStateManager(); } return dragStateManager; } // 便捷操作函数 export const dragStateActions = { /** * 获取拖拽状态 * @param {string} dragId - 拖拽ID * @returns {Object} 拖拽状态 */ getDragState: (dragId) => ensureDragStateManagerInstance().getDragState(dragId), /** * 获取所有活跃拖拽 * @returns {Array} 活跃拖拽列表 */ getActiveDrags: () => ensureDragStateManagerInstance().getActiveDrags(), /** * 获取拖拽历史 * @param {number} limit - 限制数量 * @returns {Array} 历史记录 */ getHistory: (limit = 100) => ensureDragStateManagerInstance().getDragHistory(limit), /** * 获取统计信息 * @returns {Object} 统计信息 */ getStats: () => ensureDragStateManagerInstance().getDragStats(), /** * 设置调试模式 * @param {boolean} enabled - 是否启用 */ setDebugMode: (enabled) => ensureDragStateManagerInstance().setDebugMode(enabled), /** * 启用/禁用管理器 * @param {boolean} enabled - 是否启用 */ setEnabled: (enabled) => ensureDragStateManagerInstance().setEnabled(enabled), /** * 取消所有拖拽 */ cancelAll: () => ensureDragStateManagerInstance().cancelAllDrags(), /** * 面板拖拽开始 * @param {Object} eventData - 拖拽事件数据 * @returns {string} 拖拽ID */ onPanelDragStart: (eventData) => ensureDragStateManagerInstance().onPanelDragStart(eventData), /** * 面板拖拽移动 * @param {Object} eventData - 拖拽事件数据 * @returns {boolean} 是否成功 */ onPanelDragMove: (eventData) => ensureDragStateManagerInstance().onPanelDragMove(eventData), /** * 面板拖拽结束 * @param {Object} eventData - 拖拽事件数据 * @returns {boolean} 是否成功 */ onPanelDragEnd: (eventData) => ensureDragStateManagerInstance().onPanelDragEnd(eventData), /** * TabPage拖拽开始 * @param {Object} eventData - 拖拽事件数据 * @returns {string} 拖拽ID */ onPanelDragStartFromTabPage: (eventData) => ensureDragStateManagerInstance().onPanelDragStartFromTabPage(eventData), /** * TabPage拖拽移动 * @param {Object} eventData - 拖拽事件数据 * @returns {boolean} 是否成功 */ onPanelDragMoveFromTabPage: (eventData) => ensureDragStateManagerInstance().onPanelDragMoveFromTabPage(eventData), /** * TabPage拖拽结束 * @param {Object} eventData - 拖拽事件数据 * @returns {boolean} 是否成功 */ onPanelDragEndFromTabPage: (eventData) => ensureDragStateManagerInstance().onPanelDragEndFromTabPage(eventData), /** * Area拖拽开始 * @param {Object} eventData - 拖拽事件数据 * @returns {string} 拖拽ID */ onAreaDragStart: (eventData) => ensureDragStateManagerInstance().onAreaDragStart(eventData), /** * Area拖拽移动 * @param {Object} eventData - 拖拽事件数据 * @returns {boolean} 是否成功 */ onAreaDragMove: (eventData) => ensureDragStateManagerInstance().onAreaDragMove(eventData), /** * Area拖拽结束 * @param {Object} eventData - 拖拽事件数据 * @returns {boolean} 是否成功 */ onAreaDragEnd: (eventData) => ensureDragStateManagerInstance().onAreaDragEnd(eventData), /** * Tab拖拽开始 * @param {Object} eventData - 拖拽事件数据 * @returns {string} 拖拽ID */ onTabDragStart: (eventData) => ensureDragStateManagerInstance().onPanelDragStartFromTabPage(eventData), /** * Tab拖拽移动 * @param {Object} eventData - 拖拽事件数据 * @returns {boolean} 是否成功 */ onTabDragMove: (eventData) => ensureDragStateManagerInstance().onPanelDragMoveFromTabPage(eventData), /** * Tab拖拽结束 * @param {Object} eventData - 拖拽事件数据 * @returns {boolean} 是否成功 */ onTabDragEnd: (eventData) => ensureDragStateManagerInstance().onPanelDragEndFromTabPage(eventData), /** * 初始化拖拽管理器 */ initialize: () => ensureDragStateManagerInstance(), /** * 销毁拖拽管理器 */ destroy: () => { if (dragStateManager) { // 清理拖拽管理器资源 dragStateManager.activeDrags.clear(); dragStateManager.dragHistory = []; dragStateManager = null; console.log('🗑️ 拖拽状态管理器已销毁,所有资源已清理'); } } }; // 导出 export default { getInstance: ensureDragStateManagerInstance, actions: dragStateActions }; export { DragState };