1583 lines
40 KiB
JavaScript
1583 lines
40 KiB
JavaScript
/**
|
||
* Area事件处理器
|
||
* 专门处理Area相关的所有事件,包括浮动区域管理、拖拽、停靠、合并等
|
||
*/
|
||
|
||
import { eventBus, EVENT_TYPES } from '../eventBus';
|
||
|
||
// Area事件类型常量(仅包含EVENT_TYPES中没有的)
|
||
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_TOGGLE_TOOLBAR: 'area.toggleToolbar',
|
||
|
||
// 停靠相关
|
||
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() {
|
||
// 监听 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 },
|
||
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);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 处理Area事件
|
||
* @param {Object} data - 事件数据
|
||
*/
|
||
async _onAreaEvent(data) {
|
||
const eventType = data.eventType;
|
||
|
||
try {
|
||
switch (eventType) {
|
||
case EVENT_TYPES.AREA_DRAG_START:
|
||
await this._handleAreaDragStart(data);
|
||
break;
|
||
case EVENT_TYPES.AREA_DRAG_MOVE:
|
||
await this._handleAreaDragMove(data);
|
||
break;
|
||
case 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;
|
||
case AREA_EVENT_TYPES.AREA_ZINDEX_MANAGEMENT:
|
||
await this._handleAreaZIndexManagement(data);
|
||
break;
|
||
default:
|
||
// 记录其他事件但不处理
|
||
console.log(`📍 Area事件处理器: ${eventType || 'unknown'}`, data);
|
||
}
|
||
} catch (error) {
|
||
console.error(`❌ Area事件处理错误 (${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, finalPosition, left, top } = 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();
|
||
|
||
// 使用 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;
|
||
|
||
// 触发拖拽结束事件
|
||
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()
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 处理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);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 启动内存保护机制
|
||
*/
|
||
_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事件处理器实例
|
||
* @returns {AreaEventHandler} AreaEventHandler实例
|
||
*/
|
||
export const getAreaHandler = () => areaHandler;
|
||
|
||
// 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);
|
||
}
|
||
}; |