Refactor/clean architecture phase1 (#215)

* refactor(editor): 建立Clean Architecture领域模型层

* refactor(editor): 实现应用层架构 - 命令模式、用例和状态管理

* refactor(editor): 实现展示层核心Hooks

* refactor(editor): 实现基础设施层和展示层组件

* refactor(editor): 迁移画布和连接渲染到 Clean Architecture 组件

* feat(editor): 集成应用层架构和命令模式,实现撤销/重做功能

* refactor(editor): UI组件拆分

* refactor(editor): 提取快速创建菜单逻辑

* refactor(editor): 重构BehaviorTreeEditor,提取组件和Hook

* refactor(editor): 提取端口连接和键盘事件Hook

* refactor(editor): 提取拖放处理Hook

* refactor(editor): 提取画布交互Hook和工具函数

* refactor(editor): 完成核心重构

* fix(editor): 修复节点无法创建和连接

* refactor(behavior-tree,editor): 重构节点子节点约束系统,实现元数据驱动的架构
This commit is contained in:
YHH
2025-11-03 21:22:16 +08:00
committed by GitHub
parent 40cde9c050
commit adfc7e91b3
104 changed files with 8232 additions and 2506 deletions

View File

@@ -0,0 +1,84 @@
import { ask } from '@tauri-apps/plugin-dialog';
import { BehaviorTreeNode } from '../../stores/behaviorTreeStore';
import { Node } from '../../domain/models/Node';
import { Position } from '../../domain/value-objects/Position';
import { NodeTemplate } from '@esengine/behavior-tree';
interface UseEditorHandlersParams {
isDraggingNode: boolean;
selectedNodeIds: string[];
setSelectedNodeIds: (ids: string[]) => void;
setNodes: (nodes: Node[]) => void;
setConnections: (connections: any[]) => void;
resetView: () => void;
triggerForceUpdate: () => void;
onNodeSelect?: (node: BehaviorTreeNode) => void;
rootNodeId: string;
rootNodeTemplate: NodeTemplate;
}
export function useEditorHandlers(params: UseEditorHandlersParams) {
const {
isDraggingNode,
selectedNodeIds,
setSelectedNodeIds,
setNodes,
setConnections,
resetView,
triggerForceUpdate,
onNodeSelect,
rootNodeId,
rootNodeTemplate
} = params;
const handleNodeClick = (e: React.MouseEvent, node: BehaviorTreeNode) => {
if (isDraggingNode) {
return;
}
if (e.ctrlKey || e.metaKey) {
if (selectedNodeIds.includes(node.id)) {
setSelectedNodeIds(selectedNodeIds.filter((id: string) => id !== node.id));
} else {
setSelectedNodeIds([...selectedNodeIds, node.id]);
}
} else {
setSelectedNodeIds([node.id]);
}
onNodeSelect?.(node);
};
const handleResetView = () => {
resetView();
requestAnimationFrame(() => {
triggerForceUpdate();
});
};
const handleClearCanvas = async () => {
const confirmed = await ask('确定要清空画布吗?此操作不可撤销。', {
title: '清空画布',
kind: 'warning'
});
if (confirmed) {
setNodes([
new Node(
rootNodeId,
rootNodeTemplate,
{ nodeType: 'root' },
new Position(400, 100),
[]
)
]);
setConnections([]);
setSelectedNodeIds([]);
}
};
return {
handleNodeClick,
handleResetView,
handleClearCanvas
};
}