Feature/runtime cdn and plugin loader (#240)

* feat(ui): 完善 UI 布局系统和编辑器可视化工具

* refactor: 移除 ModuleRegistry,统一使用 PluginManager 插件系统

* fix: 修复 CodeQL 警告并提升测试覆盖率

* refactor: 分离运行时入口点,解决 runtime bundle 包含 React 的问题

* fix(ci): 添加 editor-core 和 editor-runtime 到 CI 依赖构建步骤

* docs: 完善 ServiceContainer 文档,新增 Symbol.for 模式和 @InjectProperty 说明

* fix(ci): 修复 type-check 失败问题

* fix(ci): 修复类型检查失败问题

* fix(ci): 修复类型检查失败问题

* fix(ci): behavior-tree 构建添加 @tauri-apps 外部依赖

* fix(ci): behavior-tree 添加 @tauri-apps/plugin-fs 类型依赖

* fix(ci): platform-web 添加缺失的 behavior-tree 依赖

* fix(lint): 移除正则表达式中不必要的转义字符
This commit is contained in:
YHH
2025-11-27 20:42:46 +08:00
committed by GitHub
parent 71869b1a58
commit 107439d70c
367 changed files with 10661 additions and 12473 deletions

View File

@@ -0,0 +1,190 @@
import { NodeTemplate } from '../../..';
import { Position, NodeType } from '../value-objects';
import { ValidationError } from '../errors';
/**
* 行为树节点领域实体
* 封装节点的业务逻辑和验证规则
*/
export class Node {
private readonly _id: string;
private readonly _template: NodeTemplate;
private _data: Record<string, unknown>;
private _position: Position;
private _children: string[];
private readonly _nodeType: NodeType;
constructor(
id: string,
template: NodeTemplate,
data: Record<string, unknown>,
position: Position,
children: string[] = []
) {
this._id = id;
this._template = template;
this._data = { ...data };
this._position = position;
this._children = [...children];
this._nodeType = NodeType.fromString(template.type);
}
get id(): string {
return this._id;
}
get template(): NodeTemplate {
return this._template;
}
get data(): Record<string, unknown> {
return { ...this._data };
}
get position(): Position {
return this._position;
}
get children(): ReadonlyArray<string> {
return this._children;
}
get nodeType(): NodeType {
return this._nodeType;
}
/**
* 更新节点位置
*/
moveToPosition(newPosition: Position): Node {
return new Node(
this._id,
this._template,
this._data,
newPosition,
this._children
);
}
/**
* 更新节点数据
*/
updateData(data: Record<string, unknown>): Node {
return new Node(
this._id,
this._template,
{ ...this._data, ...data },
this._position,
this._children
);
}
/**
* 添加子节点
* @throws ValidationError 如果违反业务规则
*/
addChild(childId: string): Node {
// 使用模板定义的约束undefined 表示无限制
const maxChildren = (this._template.maxChildren ?? Infinity) as number;
if (maxChildren === 0) {
throw ValidationError.leafNodeNoChildren();
}
if (this._children.length >= maxChildren) {
if (this._nodeType.isRoot()) {
throw ValidationError.rootNodeMaxChildren();
}
if (this._nodeType.isDecorator()) {
throw ValidationError.decoratorNodeMaxChildren();
}
throw new ValidationError(`节点 ${this._id} 已达到最大子节点数 ${maxChildren}`);
}
if (this._children.includes(childId)) {
throw new ValidationError(`子节点 ${childId} 已存在`);
}
return new Node(
this._id,
this._template,
this._data,
this._position,
[...this._children, childId]
);
}
/**
* 移除子节点
*/
removeChild(childId: string): Node {
return new Node(
this._id,
this._template,
this._data,
this._position,
this._children.filter((id) => id !== childId)
);
}
/**
* 检查是否可以添加子节点
*/
canAddChild(): boolean {
// 使用模板定义的最大子节点数undefined 表示无限制
const maxChildren = (this._template.maxChildren ?? Infinity) as number;
return this._children.length < maxChildren;
}
/**
* 检查是否有子节点
*/
hasChildren(): boolean {
return this._children.length > 0;
}
/**
* 检查是否为根节点
*/
isRoot(): boolean {
return this._nodeType.isRoot();
}
/**
* 转换为普通对象(用于序列化)
*/
toObject(): {
id: string;
template: NodeTemplate;
data: Record<string, unknown>;
position: { x: number; y: number };
children: string[];
} {
return {
id: this._id,
template: this._template,
data: this._data,
position: this._position.toObject(),
children: [...this._children]
};
}
/**
* 从普通对象创建节点
*/
static fromObject(obj: {
id: string;
template: NodeTemplate;
data: Record<string, unknown>;
position: { x: number; y: number };
children: string[];
}): Node {
return new Node(
obj.id,
obj.template,
obj.data,
Position.fromObject(obj.position),
obj.children
);
}
}