# iflow-engine 外部 API(第三方接入) ## 1) 获取构件树 `getConstructTreeData()` ### 所属模块 - 调用入口:`bimEngine.engine` - 源码位置:`src/managers/engine-manager.ts` ### 方法签名 ```ts getConstructTreeData(): { level: EngineModelData[]; type: EngineModelData[]; major: EngineModelData[]; } ``` ### 入参 - 无入参。 ### 返回值 - 返回一个对象,包含三类构件树: - `level`: 楼层树 - `type`: 类型树 - `major`: 专业树 ```ts type EngineTreeNode = { name?: string; id?: string | null; ids?: string[] | null; children?: EngineTreeNode[] | null; isLeaf?: boolean; }; type EngineModelData = { name?: string; url: string; children?: EngineTreeNode[] | null; }; ``` ### 行为约定 - 当 3D 引擎未初始化(`engine.initialize(...)` 未成功)时,返回: ```ts { level: [], type: [], major: [] } ``` ### 调用示例 ```ts const treeData = bimEngine.engine?.getConstructTreeData(); if (treeData) { console.log('level tree:', treeData.level); console.log('type tree:', treeData.type); console.log('major tree:', treeData.major); } ``` --- ## 2) 获取构件信息 `getComponentProperties(url, id, callback)` ### 所属模块 - 调用入口:`bimEngine.engine` - 源码位置:`src/managers/engine-manager.ts` ### 方法签名 ```ts getComponentProperties(url: string, id: string, callback: (data: any) => void): void ``` ### 入参 - `url: string`:构件所属模型 URL - `id: string`:构件 ID - `callback: (data: any) => void`:异步回调,返回构件属性 ### 调用示例 ```ts bimEngine.engine?.getComponentProperties(modelUrl, componentId, (data) => { console.log('component properties:', data); }); ``` --- ## 3) 高亮指定构件 `highlightModel(models)` ### 所属模块 - 调用入口:`bimEngine.engine?.getEngineComponent()` - 源码位置:`src/components/engine/index.ts` ### 方法签名 ```ts highlightModel(models: { url: string; ids: number[] }[]): void ``` ### 入参 - `models`:构件列表(可批量) - `url: string`:模型 URL - `ids: number[]`:要高亮的构件 ID 数组 ### 调用示例 ```ts bimEngine.engine?.getEngineComponent()?.highlightModel([ { url: modelUrl, ids: [350518] } ]); ``` --- ## 4) 剖切指定构件(推荐流程) 当前引擎提供的是“剖切盒适配已高亮构件”的能力,推荐按两步调用: 1. 先高亮目标构件:`highlightModel(...)` 2. 再执行剖切盒适配:`fitSectionBoxToModel()` ### 方法签名 ```ts fitSectionBoxToModel(): void ``` ### 调用示例 ```ts const engineComp = bimEngine.engine?.getEngineComponent(); engineComp?.highlightModel([{ url: modelUrl, ids: [350518] }]); engineComp?.fitSectionBoxToModel(); ``` --- ## 5) 隐藏其他构件 `isolateModels(models)` ### 所属模块 - 调用入口:`bimEngine.engine?.getEngineComponent()` - 源码位置:`src/components/engine/index.ts` ### 方法签名 ```ts isolateModels(models: { url: string; ids: number[] }[]): void ``` ### 入参 - `models`:要保留显示的构件(其他构件将隐藏) ### 调用示例 ```ts bimEngine.engine?.getEngineComponent()?.isolateModels([ { url: modelUrl, ids: [350518] } ]); ``` --- ## 6) 启动一键编码 `startOneClickEncoding()` ### 所属模块 - 调用入口:`bimEngine.engine?.getEngineComponent()` - 源码位置:`src/components/engine/index.ts` ### 方法签名 ```ts startOneClickEncoding(): void ``` ### 入参 - 无入参。 ### 行为约定 - 调用前建议先订阅 `encoding:start`、`encoding:complete`、`encoding:error` 事件以获取编码进度和结果。 - 若引擎未初始化或底层 `oneClickEncoding` 模块不可用,会在控制台输出警告并静默返回。 - 多次调用将重复触发编码流程(底层行为由 `iflow-engine-base` 决定)。 ### 调用示例 ```ts const engineComp = bimEngine.engine?.getEngineComponent(); // 订阅编码事件 bimEngine.on('encoding:start', (data) => { console.log('编码开始', data); }); bimEngine.on('encoding:complete', (data) => { console.log('编码完成', data); }); bimEngine.on('encoding:error', (data) => { console.log('编码失败', data); }); // 启动编码 engineComp?.startOneClickEncoding(); // 需要时取消订阅 // unsubStart(); // unsubComplete(); // unsubError(); ``` --- ## 10) 视图控制(主视图保存/恢复) ### 所属模块 - 调用入口:`bimEngine.engine?.getEngineComponent()` - 事件总线:`bimEngine`(通过 `ManagerRegistry` 桥接) - 源码位置:`src/components/engine/index.ts` ### 方法签名 ```ts // 保存主视图 saveMainView(): any // 恢复主视图(重置) restoreMainView(): void // 设置主视图(传入缓存数据) setMainViewPort(viewData: any): void ``` ### 事件列表 | 事件名 | 触发时机 | payload | |--------|---------|---------| | `view:main-view-saved` | 用户点击"将当前视图设为主视图"后 | `{ viewData: any }` | | `view:main-view-restored` | 用户点击"重置主视图"后 | `{}` | ### 行为约定 - `saveMainView()`:调用底层 `viewCube.saveMainViewPort()` 获取视点数据,并触发 `view:main-view-saved` 事件。 - `restoreMainView()`:调用底层 `viewCube.resetMainViewPort()` 恢复默认主视图,并触发 `view:main-view-restored` 事件。 - `setMainViewPort(viewData)`:调用底层 `viewCube.setMainViewPort(viewData)` 恢复指定视点,**不触发事件**(用于程序初始化时恢复缓存)。 - 所有事件经 `Engine` 组件桥接后冒泡到 `bimEngine` 事件总线。 - 订阅方式与 SDK 其他事件一致:使用 `bimEngine.on(event, handler)`,返回的函数可用于取消订阅。 ### 调用示例 ```ts const engineComp = bimEngine.engine?.getEngineComponent(); // 1. 保存主视图(用户操作触发) engineComp?.saveMainView(); // 2. 监听保存事件,持久化到 localStorage const unsubSaved = bimEngine.on('view:main-view-saved', ({ viewData }) => { console.log('主视图已保存:', viewData); localStorage.setItem('mainView', JSON.stringify(viewData)); }); // 3. 监听重置事件,清理缓存 const unsubRestored = bimEngine.on('view:main-view-restored', () => { console.log('主视图已重置'); localStorage.removeItem('mainView'); }); // 4. 模型加载完成后,自动恢复缓存的主视图 bimEngine.on('engine:model-loading-completed', () => { const cached = localStorage.getItem('mainView'); if (cached) { engineComp?.setMainViewPort(JSON.parse(cached)); } }); // 需要时取消订阅 // unsubSaved(); // unsubRestored(); ``` --- ## 7) 检查模型编码 `hasModelCode()` ### 所属模块 - 调用入口:`bimEngine.engine?.getEngineComponent()` - 源码位置:`src/components/engine/index.ts` ### 方法签名 ```ts hasModelCode(): boolean ``` ### 入参 - 无入参。 ### 返回值 - `true`:所有已加载模型均已存在编码数据。 - `false`:至少有一个模型没有编码数据,或引擎未初始化、`oneClickEncoding` 模块不可用。 ### 行为约定 - 遍历当前 `engine.models` 数组,对每个模型调用底层 `oneClickEncoding.exitModelCode(url)`。 - 仅当所有模型的返回值为 `true` 时,才返回 `true`。 - 若当前没有加载任何模型,返回 `false`。 ### 调用示例 ```ts const hasCode = bimEngine.engine?.getEngineComponent()?.hasModelCode(); console.log('模型是否已编码:', hasCode); ``` --- ## 8) 读取缓存编码 `readModelCodeFormStoge()` ### 所属模块 - 调用入口:`bimEngine.engine?.getEngineComponent()` - 源码位置:`src/components/engine/index.ts` ### 方法签名 ```ts readModelCodeFormStoge(): void ``` ### 入参 - 无入参。 ### 行为约定 - 遍历当前 `engine.models` 数组,对每个模型调用底层 `oneClickEncoding.readModelCodeFormStoge(url)`。 - 若引擎未初始化或底层模块不可用,会在控制台输出警告并静默返回。 - 无返回值,仅触发读取动作。 ### 调用示例 ```ts bimEngine.engine?.getEngineComponent()?.readModelCodeFormStoge(); ``` --- ## 9) 一键编码事件 ### 所属模块 - 事件总线:`bimEngine`(通过 `ManagerRegistry` 桥接) - 源码位置:`src/components/engine/index.ts` ### 事件列表 | 事件名 | 触发时机 | payload | |--------|---------|---------| | `encoding:start` | 编码流程开始时 | `{ data?: any }` | | `encoding:complete` | 编码流程成功完成时 | `{ data?: any }` | | `encoding:error` | 编码流程失败时 | `{ data?: any }` | ### 行为约定 - 事件由底层 `oneClickEncoding` 模块触发,经 `Engine` 组件桥接后冒泡到 `bimEngine` 事件总线。 - 订阅方式与 SDK 其他事件一致:使用 `bimEngine.on(event, handler)`,返回的函数可用于取消订阅。 - 建议在调用 `startOneClickEncoding()` 之前完成事件订阅,避免漏掉 `encoding:start` 事件。 ### 调用示例 ```ts const unsubStart = bimEngine.on('encoding:start', (data) => { console.log('编码开始', data); }); const unsubComplete = bimEngine.on('encoding:complete', (data) => { console.log('编码完成', data); }); const unsubError = bimEngine.on('encoding:error', (data) => { console.log('编码失败', data); }); // 启动编码 bimEngine.engine?.getEngineComponent()?.startOneClickEncoding(); // 需要时取消订阅 // unsubStart(); // unsubComplete(); // unsubError(); ``` --- ## 11) 图钉(DrawingPin)管理 ### 所属模块 - 调用入口:`bimEngine.engine?.getEngineComponent()` / `bimEngine.emit()` / `bimEngine.on()` - 源码位置:`src/components/engine/index.ts`、`src/components/component-tree-drawer/pin-tab.ts` - 初始化要求:需先调用 `bimEngine.initConstructTreeBtn()` 初始化构件树面板 ### 概述 图钉功能用于保存和展示 3D 视图中的相机视角,支持文件夹分组管理。**外部系统完全掌控图钉的创建、编辑、删除和持久化**,SDK 仅负责渲染展示。 对接方式: - **批量传入配置**:`setPinRecords()` 一次性设置完整图钉列表 - **增删改**:通过 `bimEngine.emit()` 发送 `drawingPin:create|update|delete` 事件 - **监听变更**:订阅 `drawingPin:list-updated` 获取用户操作后的最新列表 ### 数据类型 ```ts interface DrawingPinRecord { id: string; // 唯一标识(外部生成) parentId?: string | null; // 父文件夹 ID,null/undefined 表示根节点 name: string; // 显示名称 type: 'pin' | 'folder'; // 类型:图钉 或 文件夹 seq: number; // 排序序号(同级内排序) data?: any; // 视角数据(仅 type='pin' 时有值,由外部系统生成) } ``` ### API 列表 #### A. 批量传入图钉配置 ```ts bimEngine.engine?.getEngineComponent()?.setPinRecords( records: DrawingPinRecord[] ): void ``` - **作用**:外部一次性传入完整图钉列表(平铺结构),SDK 内部自动构建树形层级。 - **场景**:初始化时从后端/缓存加载已有图钉配置。 - **注意**:会触发 `drawingPin:list-updated` 事件。 #### B. 创建 / 更新 / 删除(事件接口) 外部通过 `bimEngine.emit()` 向 SDK 发送操作指令: | 事件 | payload | 说明 | |------|---------|------| | `drawingPin:create` | `{ record: DrawingPinRecord }` | 创建图钉或文件夹 | | `drawingPin:update` | `{ id: string; patch: Partial> }` | 编辑图钉/文件夹 | | `drawingPin:delete` | `{ id: string }` | 删除图钉或文件夹 | #### C. 监听列表变更 | 事件 | 方向 | payload | 说明 | |------|------|---------|------| | `drawingPin:list-updated` | SDK → 外部 | `{ records: DrawingPinRecord[] }` | 列表发生任何变更时触发(含用户界面操作) | ### 调用示例 #### 1. 初始化时批量传入图钉配置 ```ts const engineComp = bimEngine.engine?.getEngineComponent(); // 从后端获取已有配置 const pinRecords: DrawingPinRecord[] = [ { id: 'folder_001', parentId: null, name: '一层图钉', type: 'folder', seq: 0, }, { id: 'pin_001', parentId: 'folder_001', name: '入口视角', type: 'pin', seq: 0, data: { /* 外部系统保存的视角数据 */ }, }, { id: 'pin_002', parentId: 'folder_001', name: '大厅视角', type: 'pin', seq: 1, data: { /* 外部系统保存的视角数据 */ }, }, ]; // 一次性传入 engineComp?.setPinRecords(pinRecords); ``` #### 2. 创建图钉(外部生成视角数据) ```ts // 外部系统自行生成视角数据 const viewData = { /* 外部系统生成的视角数据 */ }; const record: DrawingPinRecord = { id: `pin_${Date.now()}`, parentId: null, // 或指定文件夹 ID,实现分组 name: '新图钉', type: 'pin', seq: 0, data: viewData, }; bimEngine.emit('drawingPin:create', { record }); ``` #### 3. 创建文件夹 ```ts const record: DrawingPinRecord = { id: `folder_${Date.now()}`, parentId: null, // 或指定父文件夹 ID,实现嵌套 name: '新文件夹', type: 'folder', seq: 0, }; bimEngine.emit('drawingPin:create', { record }); ``` #### 4. 编辑(重命名 / 移动分组 / 调序) ```ts // 重命名 bimEngine.emit('drawingPin:update', { id: 'pin_001', patch: { name: '入口视角(已更新)' }, }); // 移动到另一个文件夹 bimEngine.emit('drawingPin:update', { id: 'pin_001', patch: { parentId: 'folder_002' }, }); // 调整排序 bimEngine.emit('drawingPin:update', { id: 'pin_001', patch: { seq: 2 }, }); ``` #### 5. 删除 ```ts bimEngine.emit('drawingPin:delete', { id: 'pin_001' }); ``` #### 6. 监听变更并持久化 ```ts bimEngine.on('drawingPin:list-updated', ({ records }) => { console.log('图钉列表已更新:', records); // 同步到后端或 localStorage localStorage.setItem('drawingPins', JSON.stringify(records)); }); ``` #### 7. 完整对接示例(初始化 + 双向同步) ```ts const engineComp = bimEngine.engine?.getEngineComponent(); // 1. 监听变更,持久化到后端 bimEngine.on('drawingPin:list-updated', ({ records }) => { fetch('/api/save-pins', { method: 'POST', body: JSON.stringify(records), }); }); // 2. 模型加载完成后,从后端恢复图钉配置 bimEngine.on('engine:model-loading-completed', () => { fetch('/api/get-pins') .then((res) => res.json()) .then((records: DrawingPinRecord[]) => { engineComp?.setPinRecords(records); }); }); // 3. 业务层提供"添加图钉"按钮 function onAddPinClick() { // 外部系统自行生成视角数据 const viewData = { /* 外部系统生成的视角数据 */ }; const record: DrawingPinRecord = { id: `pin_${Date.now()}`, parentId: null, name: '新视角', type: 'pin', seq: 0, data: viewData, }; bimEngine.emit('drawingPin:create', { record }); } ```