2025-11-20 13:14:31 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* Area事件处理器
|
|
|
|
|
|
* 专门处理Area相关的所有事件,包括浮动区域管理、拖拽、停靠、合并等
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2025-12-25 13:53:52 +08:00
|
|
|
|
import { eventBus } from '../eventBus';
|
2025-11-20 13:14:31 +08:00
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|