import { CompositeCommand } from "../../commands/Command.js"; import { PerformanceManager } from "./PerformanceManager.js"; /** * 简化版命令管理器 * 基于经典撤销/重做模式,支持命令队列 * 使用复合命令替代事务处理 */ export class CommandManager { constructor(options = {}) { this.canvas = options.canvas; this.undoStack = []; this.redoStack = []; this.maxHistorySize = options.maxHistorySize || 50; this.executing = false; // 命令执行队列 this.commandQueue = []; this.processing = false; // 可选的性能管理器 this.performanceManager = options.performanceManager || null; // 状态变化回调 this.onStateChange = null; } // 兼容旧的executeCommand方法 async executeCommand(command) { return this.execute(command); } /** * 执行命令并添加到撤销栈 */ async execute(command) { if (!command || typeof command.execute !== "function") { throw new Error("无效的命令对象"); } return this._executeDirectly(command); } /** * 直接执行命令(绕过事务检查) * @private */ async _executeDirectly(command) { // 返回Promise,等待命令执行完成 return new Promise((resolve, reject) => { // 将命令添加到队列 this.commandQueue.push({ type: "execute", command, resolve, reject, }); // 开始处理队列 this._processQueue(); }); } /** * 撤销最后一个命令 */ async undo() { return new Promise((resolve, reject) => { // 检查是否可以撤销 if (this.undoStack.length === 0) { console.warn("无法撤销:撤销栈为空"); resolve(null); return; } // 将撤销操作添加到队列 this.commandQueue.push({ type: "undo", resolve, reject, }); // 开始处理队列 this._processQueue(); }); } /** * 重做最后一个撤销的命令 */ async redo() { return new Promise((resolve, reject) => { // 检查是否可以重做 if (this.redoStack.length === 0) { console.warn("无法重做:重做栈为空"); resolve(null); return; } // 将重做操作添加到队列 this.commandQueue.push({ type: "redo", resolve, reject, }); // 开始处理队列 this._processQueue(); }); } /** * 处理命令队列 * @private */ async _processQueue() { // 如果正在处理或队列为空,直接返回 if (this.processing || this.commandQueue.length === 0) { return; } this.processing = true; try { while (this.commandQueue.length > 0) { const task = this.commandQueue.shift(); try { let result = null; switch (task.type) { case "execute": result = await this._executeCommandInternal(task.command); break; case "undo": result = await this._undoInternal(); break; case "redo": result = await this._redoInternal(); break; default: throw new Error(`未知的任务类型: ${task.type}`); } task.resolve(result); } catch (error) { task.reject(error); } } } finally { this.processing = false; } } /** * 内部执行命令方法 * @private */ async _executeCommandInternal(command) { this.executing = true; const startTime = performance.now(); try { console.log(`🔄 执行命令: ${command.constructor.name}`); // 执行命令 const result = await this._executeCommand(command); // 只有可撤销的命令才加入撤销栈 if (command.undoable !== false) { this.undoStack.push(command); this.redoStack = []; // 清空重做栈 // 限制历史记录大小 this._trimHistory(); } // 记录性能 const duration = performance.now() - startTime; this._recordPerformance("execute", command.constructor.name, duration); // 通知状态变化 this._notifyStateChange(); console.log(`✅ 命令执行成功: ${command.constructor.name}`); return result; } catch (error) { console.error(`❌ 命令执行失败: ${command.constructor.name}`, error); throw error; } finally { this.executing = false; } } /** * 内部撤销方法 * @private */ async _undoInternal() { if (this.undoStack.length === 0) { console.warn("无法撤销:撤销栈为空"); return null; } this.executing = true; const startTime = performance.now(); try { this.canvas?.discardActiveObject(); const command = this.undoStack.pop(); console.log(`↩️ 撤销命令: ${command.constructor.name}`); const result = await this._undoCommand(command); this.redoStack.push(command); // 记录性能 const duration = performance.now() - startTime; this._recordPerformance("undo", command.constructor.name, duration); // 通知状态变化 this._notifyStateChange(); console.log(`✅ 命令撤销成功: ${command.constructor.name}`); return result; } catch (error) { console.error(`❌ 命令撤销失败`, error); throw error; } finally { this.executing = false; } } /** * 内部重做方法 * @private */ async _redoInternal() { if (this.redoStack.length === 0) { console.warn("无法重做:重做栈为空"); return null; } this.executing = true; const startTime = performance.now(); try { this.canvas?.discardActiveObject(); const command = this.redoStack.pop(); console.log(`↪️ 重做命令: ${command.constructor.name}`); const result = await this._executeCommand(command); this.undoStack.push(command); // 记录性能 const duration = performance.now() - startTime; this._recordPerformance("redo", command.constructor.name, duration); // 通知状态变化 this._notifyStateChange(); console.log(`✅ 命令重做成功: ${command.constructor.name}`); return result; } catch (error) { console.error(`❌ 命令重做失败`, error); throw error; } finally { this.executing = false; } } /** * 批量执行命令(使用 CompositeCommand) * 推荐使用此方法替代原来的事务机制 */ async executeBatch(commands, batchName = "批量操作") { if (!Array.isArray(commands) || commands.length === 0) { throw new Error("命令数组不能为空"); } const compositeCommand = new CompositeCommand(commands, { name: batchName, }); return this.execute(compositeCommand); } /** * 清空历史记录 */ clear() { // 清空队列中的所有任务 while (this.commandQueue.length > 0) { const task = this.commandQueue.shift(); task.reject(new Error("命令管理器已被清空")); } this.undoStack = []; this.redoStack = []; this._notifyStateChange(); console.log("📝 命令历史已清空"); } /** * 获取管理器状态 */ getState() { return { canUndo: this.undoStack.length > 0, canRedo: this.redoStack.length > 0, undoCount: this.undoStack.length, redoCount: this.redoStack.length, isExecuting: this.executing, isProcessing: this.processing, queueLength: this.commandQueue.length, lastCommand: this.undoStack.length > 0 ? this.undoStack[this.undoStack.length - 1].constructor.name : null, nextRedoCommand: this.redoStack.length > 0 ? this.redoStack[this.redoStack.length - 1].constructor.name : null, }; } /** * 获取命令历史信息 */ getHistory() { return { undoHistory: this.undoStack.map((cmd) => ({ name: cmd.constructor.name, info: cmd.getInfo ? cmd.getInfo() : {}, timestamp: cmd.timestamp, })), redoHistory: this.redoStack.map((cmd) => ({ name: cmd.constructor.name, info: cmd.getInfo ? cmd.getInfo() : {}, timestamp: cmd.timestamp, })), }; } setChangeCallback(callback) { if (typeof callback === "function") { this.onStateChange = callback; } else { throw new Error("回调必须是一个函数"); } } /** * 执行单个命令 * @private */ async _executeCommand(command) { const result = command.execute(); return this._isPromise(result) ? await result : result; } /** * 撤销单个命令 * @private */ async _undoCommand(command) { if (typeof command.undo !== "function") { throw new Error(`命令 ${command.constructor.name} 不支持撤销`); } const result = command.undo(); return this._isPromise(result) ? await result : result; } /** * 检查是否为Promise * @private */ _isPromise(value) { return ( value && typeof value === "object" && typeof value.then === "function" && typeof value.catch === "function" ); } /** * 限制历史记录大小 * @private */ _trimHistory() { if (this.undoStack.length > this.maxHistorySize) { this.undoStack.shift(); } } /** * 记录性能数据 * @private */ _recordPerformance(type, commandName, duration) { if (this.performanceManager) { if (type === "execute") { this.performanceManager.recordExecution(commandName, duration); } else if (type === "undo") { this.performanceManager.recordUndo(commandName, duration); } else if (type === "redo") { this.performanceManager.recordRedo(commandName, duration); } } } /** * 通知状态变化 * @private */ _notifyStateChange() { if (this.onStateChange) { try { this.onStateChange(this.getState()); } catch (error) { console.error("状态变化回调执行失败:", error); } } } } /** * 创建命令管理器实例的工厂函数 */ export function createCommandManager(options = {}) { return new CommandManager(options); }