Files
aida_front/src/component/Canvas/CanvasEditor/commands/Command.js
2025-07-14 01:00:23 +08:00

284 lines
7.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 基础命令类
* 所有命令都应该继承这个类
*/
export class Command {
constructor(options = {}) {
this.name = options.name || "未命名命令";
this.description = options.description || "";
this.undoable = options.undoable !== false; // 默认可撤销
this.timestamp = Date.now();
}
/**
* 执行命令
* @returns {*} 执行结果可以是Promise
*/
execute() {
throw new Error("子类必须实现execute方法");
}
/**
* 撤销命令
* @returns {*} 撤销结果可以是Promise
*/
undo() {
if (!this.undoable) {
throw new Error("此命令不支持撤销");
}
throw new Error("可撤销命令必须实现undo方法");
}
/**
* 获取命令信息
*/
getInfo() {
return {
name: this.name,
description: this.description,
undoable: this.undoable,
timestamp: this.timestamp,
};
}
}
/**
* 复合命令类
* 用于批量执行多个命令,替代事务系统
*/
export class CompositeCommand extends Command {
constructor(commands = [], options = {}) {
super({
name: options.name || "复合命令",
description: options.description || "批量执行多个命令",
...options,
});
this.commands = Array.isArray(commands) ? commands : [];
this.executedCommands = []; // 记录已执行的命令,用于撤销
this.isExecuting = false;
}
/**
* 添加子命令
*/
addCommand(command) {
if (!command || typeof command.execute !== "function") {
throw new Error("无效的命令对象");
}
this.commands.push(command);
return this;
}
/**
* 批量添加子命令
*/
addCommands(commands) {
if (Array.isArray(commands)) {
commands.forEach((cmd) => this.addCommand(cmd));
}
return this;
}
/**
* 执行所有子命令(串行执行)
*/
async execute() {
if (this.isExecuting) {
throw new Error("复合命令正在执行中");
}
this.isExecuting = true;
this.executedCommands = [];
try {
const results = [];
// 串行执行所有子命令
for (const command of this.commands) {
try {
console.log(`📦 复合命令执行子命令: ${command.constructor.name}`);
const result = command.execute();
// 如果是异步命令,等待完成
const finalResult = this._isPromise(result) ? await result : result;
results.push(finalResult);
this.executedCommands.push(command);
console.log(`✅ 子命令执行成功: ${command.constructor.name}`);
} catch (error) {
console.error(`❌ 子命令执行失败: ${command.constructor.name}`, error);
// 执行失败时,撤销已执行的命令
await this._rollbackExecutedCommands();
throw new Error(`复合命令执行失败:${error.message}`);
}
}
this.isExecuting = false;
console.log(`✅ 复合命令执行完成,共执行 ${results.length} 个子命令`);
return results;
} catch (error) {
this.isExecuting = false;
throw error;
}
}
/**
* 撤销所有已执行的子命令(逆序撤销)
*/
async undo() {
if (this.isExecuting) {
throw new Error("复合命令正在执行中,无法撤销");
}
if (this.executedCommands.length === 0) {
console.warn("没有已执行的子命令需要撤销");
return true;
}
console.log(`↩️ 开始撤销复合命令,共 ${this.executedCommands.length} 个子命令`);
try {
// 逆序撤销已执行的命令
const commands = [...this.executedCommands].reverse();
const results = [];
for (const command of commands) {
if (typeof command.undo === "function") {
try {
console.log(`↩️ 撤销子命令: ${command.constructor.name}`);
const result = command.undo();
// 如果是异步撤销,等待完成
const finalResult = this._isPromise(result) ? await result : result;
results.push(finalResult);
console.log(`✅ 子命令撤销成功: ${command.constructor.name}`);
} catch (error) {
console.error(`❌ 子命令撤销失败: ${command.constructor.name}`, error);
// 撤销失败不中断整个撤销过程,但要记录错误
}
} else {
console.warn(`⚠️ 子命令不支持撤销: ${command.constructor.name}`);
}
}
this.executedCommands = [];
console.log(`✅ 复合命令撤销完成`);
return results;
} catch (error) {
console.error("❌ 复合命令撤销过程中发生错误:", error);
throw error;
}
}
/**
* 回滚已执行的命令(内部使用)
* @private
*/
async _rollbackExecutedCommands() {
console.log(`🔄 开始回滚已执行的 ${this.executedCommands.length} 个子命令`);
const commands = [...this.executedCommands].reverse();
for (const command of commands) {
if (typeof command.undo === "function") {
try {
console.log(`🔄 回滚子命令: ${command.constructor.name}`);
const result = command.undo();
if (this._isPromise(result)) {
await result;
}
console.log(`✅ 子命令回滚成功: ${command.constructor.name}`);
} catch (error) {
console.error(`❌ 子命令回滚失败: ${command.constructor.name}`, error);
// 回滚失败不中断整个回滚过程
}
}
}
this.executedCommands = [];
console.log(`✅ 回滚完成`);
}
/**
* 检查返回值是否为Promise
* @private
*/
_isPromise(value) {
return (
value &&
typeof value === "object" &&
typeof value.then === "function" &&
typeof value.catch === "function"
);
}
/**
* 获取复合命令信息
*/
getInfo() {
return {
...super.getInfo(),
commandCount: this.commands.length,
executedCount: this.executedCommands.length,
isExecuting: this.isExecuting,
subCommands: this.commands.map((cmd) => (cmd.getInfo ? cmd.getInfo() : cmd.constructor.name)),
};
}
}
/**
* 函数命令包装器
* 将普通函数包装为命令对象
*/
export class FunctionCommand extends Command {
constructor(executeFn, undoFn = null, options = {}) {
super({
name: options.name || "函数命令",
undoable: typeof undoFn === "function",
...options,
});
if (typeof executeFn !== "function") {
throw new Error("执行函数不能为空");
}
this.executeFn = executeFn;
this.undoFn = undoFn;
this.executeResult = null; // 保存执行结果用于撤销
}
async execute() {
const result = this.executeFn();
this.executeResult = this._isPromise(result) ? await result : result;
return this.executeResult;
}
async undo() {
if (!this.undoFn) {
throw new Error("此函数命令不支持撤销");
}
const result = this.undoFn(this.executeResult);
return this._isPromise(result) ? await result : result;
}
/**
* 检查返回值是否为Promise
* @private
*/
_isPromise(value) {
return (
value &&
typeof value === "object" &&
typeof value.then === "function" &&
typeof value.catch === "function"
);
}
}