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,72 @@
import { useEffect } from 'react';
import { Connection, ROOT_NODE_ID } from '../../stores/behaviorTreeStore';
import { useNodeOperations } from './useNodeOperations';
import { useConnectionOperations } from './useConnectionOperations';
interface UseKeyboardShortcutsParams {
selectedNodeIds: string[];
selectedConnection: { from: string; to: string } | null;
connections: Connection[];
nodeOperations: ReturnType<typeof useNodeOperations>;
connectionOperations: ReturnType<typeof useConnectionOperations>;
setSelectedNodeIds: (ids: string[]) => void;
setSelectedConnection: (connection: { from: string; to: string } | null) => void;
}
export function useKeyboardShortcuts(params: UseKeyboardShortcutsParams) {
const {
selectedNodeIds,
selectedConnection,
connections,
nodeOperations,
connectionOperations,
setSelectedNodeIds,
setSelectedConnection
} = params;
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
const activeElement = document.activeElement;
const isEditingText = activeElement instanceof HTMLInputElement ||
activeElement instanceof HTMLTextAreaElement ||
activeElement instanceof HTMLSelectElement ||
(activeElement as HTMLElement)?.isContentEditable;
if (isEditingText) {
return;
}
if (e.key === 'Delete' || e.key === 'Backspace') {
e.preventDefault();
if (selectedConnection) {
const conn = connections.find(
(c: Connection) => c.from === selectedConnection.from && c.to === selectedConnection.to
);
if (conn) {
connectionOperations.removeConnection(
conn.from,
conn.to,
conn.fromProperty,
conn.toProperty
);
}
setSelectedConnection(null);
return;
}
if (selectedNodeIds.length > 0) {
const nodesToDelete = selectedNodeIds.filter((id: string) => id !== ROOT_NODE_ID);
if (nodesToDelete.length > 0) {
nodeOperations.deleteNodes(nodesToDelete);
setSelectedNodeIds([]);
}
}
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [selectedNodeIds, selectedConnection, nodeOperations, connectionOperations, connections, setSelectedNodeIds, setSelectedConnection]);
}