diff --git a/AI_COLLABORATION.md b/AI_COLLABORATION.md index 80beab1..60677d3 100644 --- a/AI_COLLABORATION.md +++ b/AI_COLLABORATION.md @@ -33,7 +33,7 @@ ``` engine/ ├── src/ # SDK 源代码 -│ ├── core/ # 核心基础类 +│ ├── core/ # 核心基础类(EventEmitter、BimComponent、ManagerRegistry、BaseManager、BaseDialogManager) │ ├── components/ # UI 组件 │ ├── managers/ # 管理器类 │ ├── services/ # 服务类(主题、语言) @@ -43,7 +43,7 @@ engine/ │ ├── bim-engine.ts # 主引擎类 │ └── index.ts # 入口文件 ├── dist/ # 构建产物 (ESM + UMD + .d.ts) -├── demo/ # HTML 示例 +├── demo/ # HTML 示例(index.html、multi-tab.html) ├── demo-vue/ # Vue 示例 ├── docs/ # 文档目录 │ └── components/ # 组件详细文档(每个组件一份) @@ -122,6 +122,23 @@ npm run dev:all - **ButtonGroupManager**: 管理通用按钮组 - **EngineManager**: 管理 3D 引擎(延迟初始化) +#### ManagerRegistry(实例化注册中心) +项目采用 **ManagerRegistry** 作为每个 BimEngine 实例的内部注册中心,管理该实例下的所有 Manager: + +- **非单例模式**: 每个 `BimEngine` 实例创建独立的 `ManagerRegistry`,支持同一页面多个引擎实例并存 +- **依赖注入**: `BimEngine` 在构造时创建 `ManagerRegistry`,通过构造函数注入到所有 Manager +- **BaseManager**: 所有 Manager 的基类,构造函数接收 `registry: ManagerRegistry` 参数 +- **BaseDialogManager**: 弹窗相关 Manager 的基类,继承 `BaseManager`,同样接收 `registry` 参数 +- **内部实现**: `ManagerRegistry` 不对外导出,SDK 使用者无感知 + +```typescript +// BimEngine 创建独立的 registry +const registry = new ManagerRegistry(); +this.toolbarManager = new ToolbarManager(registry); +this.dialogManager = new DialogManager(registry); +// ... 所有 Manager 共享同一个 registry 实例 +``` + #### 事件总线模式 项目采用 **混合通信模式**,根据场景选择最合适的方式: @@ -165,7 +182,6 @@ npm run dev:all - `Engine` 组件通过参数接收 `createEngine` 函数 - 可以在运行时决定使用哪个引擎实现 - 便于测试和切换不同的 3D 引擎 - ### 2.2 组件设计原则 #### IBimComponent 接口 @@ -224,11 +240,16 @@ interface IBimComponent { - **3D 引擎**: 采用延迟初始化,用户需主动调用 `initEngine()` 方法 - **原因**: 3D 引擎资源消耗大,延迟初始化可以优化性能 -#### 单例服务 -- **ThemeManager**: 全局单例,所有组件共享同一主题状态 -- **LocaleManager**: 全局单例,所有组件共享同一语言状态 +#### 单例服务与实例化服务 +- **ThemeManager**: 全局单例,所有 BimEngine 实例共享同一主题状态 +- **LocaleManager**: 全局单例,所有 BimEngine 实例共享同一语言状态 - **原因**: 主题和语言是全局状态,单例模式确保一致性 +#### ManagerRegistry(非单例) +- **ManagerRegistry**: 每个 BimEngine 实例创建独立的 ManagerRegistry +- **BaseManager / BaseDialogManager**: 通过构造函数接收 `registry` 参数,实现依赖注入 +- **原因**: 支持同一页面多个 BimEngine 实例并存,各实例的 Manager 互不干扰 +- **设计决策历史**: 早期采用单例模式 (`ManagerRegistry.getInstance()`),后重构为实例化模式以支持多实例场景 #### CSS 变量 - 组件使用 CSS 变量来应用主题颜色 - 主题变更时,只需更新 CSS 变量值 @@ -262,6 +283,30 @@ interface IBimComponent { - 定义抽象 `destroy()` 方法 - **使用**: 所有 Manager 类继承此类 +#### `manager-registry.ts` +- **作用**: Manager 注册中心,管理单个 BimEngine 实例下的所有 Manager +- **功能**: + - `register(name, manager)`: 注册 Manager 实例 + - `get(name)`: 获取已注册的 Manager + - `emit(event, payload)`: 通过事件总线发送事件 + - `reset()`: 重置所有注册的 Manager +- **使用**: 每个 `BimEngine` 实例创建独立的 `ManagerRegistry`,通过构造函数注入给所有 Manager +- **注意**: 不对外导出,纯内部实现 + +#### `base-manager.ts` +- **作用**: 所有 Manager 的基类 +- **功能**: + - 构造函数接收 `registry: ManagerRegistry` 参数 + - 提供 Manager 通用能力 +- **使用**: 所有非弹窗类 Manager 继承此类(如 ToolbarManager、EngineManager) + +#### `base-dialog-manager.ts` +- **作用**: 弹窗相关 Manager 的基类 +- **功能**: + - 继承 `BaseManager`,构造函数接收 `registry: ManagerRegistry` + - 提供弹窗管理通用能力(创建、显示、隐藏弹窗) +- **使用**: MeasureDialogManager、SectionPlaneDialogManager 等 7 个弹窗 Manager 继承此类 + ### 3.2 主引擎文件 #### `bim-engine.ts` @@ -538,6 +583,12 @@ const dialog = engine.dialog.create({ | `ConstructTreeManagerBtn` | `src/managers/construct-tree-manager-btn.ts` | 目录树按钮/弹窗管理器 | `BimComponent` | | `ComponentDetailManager` | `src/managers/component-detail-manager.ts` | 构件详情弹窗管理器 | `BimComponent` | +#### 4.1.0 ConstructTreeManagerBtn 补充说明 + +- 树节点 ID 生成:当节点 `id` 为空但存在 `ids` 数组时,会对 `ids` 做纯 JS 哈希(FNV-1a 32-bit 双哈希拼接),用于生成稳定且较短的节点唯一标识。 +- 设计动机:避免依赖 `crypto.subtle`(该 API 在非安全上下文,如 HTTP 站点下可能为 `undefined`),导致运行时报错。 +- 注意:该哈希仅用于 UI 树组件的 key/映射,不用于安全加密或鉴权。 + #### 4.1.1 剖切盒(SectionBox)对接说明 - 相关文件: