From 89ae01ffd7e210161468f287d8c5b3df1a160585 Mon Sep 17 00:00:00 2001 From: yuding <1023798085@qq.com> Date: Fri, 23 Jan 2026 16:27:04 +0800 Subject: [PATCH] feat: upgrade iflow-engine-base to v1.0.5, add pause/resume rendering API - Update iflow-engine-base from 1.0.1 to 1.0.5 - Change default engine version from v1 to v2 - Add pauseRendering() and resumeRendering() methods - Add switch model feature in demos - Update model URLs in demos - Add new documentation files --- demo-vue/src/App.vue | 56 ++- demo/index.html | 65 +++- demo/viewer.html | 2 +- docs/ARCHITECTURE.md | 502 +++++++++++++++++++++++++++ docs/GETTING_STARTED.md | 388 +++++++++++++++++++++ docs/INDEX.md | 104 ++++++ docs/MODULES/_INDEX.md | 122 +++++++ docs/MODULES/components.md | 605 +++++++++++++++++++++++++++++++++ docs/MODULES/core.md | 386 +++++++++++++++++++++ docs/MODULES/managers.md | 489 ++++++++++++++++++++++++++ docs/MODULES/services.md | 402 ++++++++++++++++++++++ package-lock.json | 16 +- package.json | 4 +- src/components/engine/index.ts | 24 +- src/managers/engine-manager.ts | 18 + 15 files changed, 3167 insertions(+), 16 deletions(-) create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/GETTING_STARTED.md create mode 100644 docs/INDEX.md create mode 100644 docs/MODULES/_INDEX.md create mode 100644 docs/MODULES/components.md create mode 100644 docs/MODULES/core.md create mode 100644 docs/MODULES/managers.md create mode 100644 docs/MODULES/services.md diff --git a/demo-vue/src/App.vue b/demo-vue/src/App.vue index 84f179c..ee8bc3a 100644 --- a/demo-vue/src/App.vue +++ b/demo-vue/src/App.vue @@ -55,6 +55,11 @@
+ +
+
+ +
状态: {{ engineStatus }}
@@ -290,7 +295,7 @@ const initEngine = () => { // 初始化引擎,使用默认配置 const success = engine.value.engine.initialize({ backgroundColor: 0x333333, // 深色背景 - version: 'v1', // WebGL 版本 + version: 'v2', // WebGL 版本 showStats: true, // 显示性能统计 showViewCube: true // 显示视图立方体 }); @@ -324,7 +329,7 @@ const loadModel = () => { try { // 加载模型文件(从 model 目录) - const modelUrl = '/model/gujianzhu.glb'; + const modelUrl = 'https://lyz-1259524260.cos.ap-guangzhou.myqcloud.com/iflow/models/8634e556-a94e-4ba7-be3e-2ea1507cced5/'; engine.value.engine.loadModel(modelUrl, { position: [0, 0, 0], // 初始位置 @@ -337,6 +342,53 @@ const loadModel = () => { console.error('❌ 模型加载错误:', error); } }; + +const switchModel = () => { + if (!engine.value || !engine.value.engine) { + alert('引擎未创建,请先等待页面加载完成'); + return; + } + + if (!engine.value.engine.isInitialized()) { + alert('请先初始化 3D 引擎!'); + return; + } + + const newUrl = prompt('请输入新的模型 URL:', 'https://lyz-1259524260.cos.ap-guangzhou.myqcloud.com/iflow/models/8634e556-a94e-4ba7-be3e-2ea1507cced5/'); + + if (!newUrl || newUrl.trim() === '') { + return; + } + + try { + engine.value.engine.loadModel(newUrl.trim(), { + position: [0, 0, 0], + rotation: [0, 0, 0], + scale: [1, 1, 1] + }); + console.log('✅ 切换模型请求已发送:', newUrl); + } catch (error: any) { + console.error('❌ 切换模型错误:', error); + } +}; + +const pauseRendering = () => { + if (!engine.value?.engine?.isInitialized()) { + alert('请先初始化 3D 引擎!'); + return; + } + engine.value.engine.pauseRendering(); + console.log('✅ 渲染已暂停'); +}; + +const resumeRendering = () => { + if (!engine.value?.engine?.isInitialized()) { + alert('请先初始化 3D 引擎!'); + return; + } + engine.value.engine.resumeRendering(); + console.log('✅ 渲染已恢复'); +}; +``` + +### React + +```tsx +import { useRef, useEffect } from 'react'; +import { BimEngine } from 'iflow-engine'; + +export function BimViewer() { + const containerRef = useRef(null); + const engineRef = useRef(null); + + useEffect(() => { + if (containerRef.current && !engineRef.current) { + engineRef.current = new BimEngine(containerRef.current, { + locale: 'zh-CN', + theme: 'light' + }); + + // 初始化 3D 引擎 + engineRef.current.engine?.initialize(); + + // 加载模型 + engineRef.current.engine?.loadModel('/models/building.gltf'); + } + + return () => { + engineRef.current?.destroy(); + engineRef.current = null; + }; + }, []); + + return
; +} +``` + +### 原生 HTML + +```html + + + + iflow-engine Demo + + + +
+ + + + +``` + +## 主题切换 + +```typescript +// 切换到暗色主题 +engine.setTheme('dark'); + +// 切换到亮色主题 +engine.setTheme('light'); + +// 自定义主题 +engine.setCustomTheme({ + name: 'custom', + primary: '#ff6b6b', + primaryHover: '#ff5252', + primaryActive: '#ff4757', + // ... 其他属性 +}); +``` + +## 语言切换 + +```typescript +// 切换到英文 +engine.setLocale('en-US'); + +// 切换到中文 +engine.setLocale('zh-CN'); +``` + +## 工具栏操作 + +```typescript +// 显示/隐藏工具栏 +engine.toolbar?.show(); +engine.toolbar?.hide(); + +// 添加自定义按钮 +engine.toolbar?.addButton({ + id: 'custom-btn', + type: 'button', + label: '自定义', + icon: '...', + onClick: () => { + console.log('Custom button clicked'); + } +}); + +// 设置按钮激活状态 +engine.toolbar?.setBtnActive('measure', true); +``` + +## 测量功能 + +```typescript +// 显示测量面板 +engine.measure?.show(); + +// 切换测量模式 +engine.measure?.switchMode('distance'); // 距离 +engine.measure?.switchMode('angle'); // 角度 +engine.measure?.switchMode('volume'); // 体积 +engine.measure?.switchMode('elevation'); // 标高 +engine.measure?.switchMode('slope'); // 坡度 + +// 获取测量配置 +const config = engine.measure?.getConfig(); +console.log(config); // { unit: 'mm', precision: 2 } + +// 设置测量配置 +engine.measure?.setConfig({ unit: 'cm', precision: 1 }); + +// 清除所有测量结果 +engine.measure?.clearAll(); +``` + +## 剖切功能 + +### 平面剖切 + +```typescript +// 显示剖切面板 +engine.sectionPlane?.show(); + +// 隐藏剖切面板 +engine.sectionPlane?.hide(); +``` + +### 轴向剖切 + +```typescript +// 显示轴向剖切 +engine.sectionAxis?.show(); + +// 设置剖切轴向 +engine.sectionAxis?.setActiveAxis('x'); // X 轴 +engine.sectionAxis?.setActiveAxis('y'); // Y 轴 +engine.sectionAxis?.setActiveAxis('z'); // Z 轴 +``` + +### 剖切盒 + +```typescript +// 显示剖切盒 +engine.sectionBox?.show(); + +// 获取剖切范围 +const range = engine.sectionBox?.getRange(); +console.log(range); // { minX, maxX, minY, maxY, minZ, maxZ } + +// 设置剖切范围 +engine.sectionBox?.setRange({ minX: 0, maxX: 100 }); + +// 反向剖切 +engine.sectionBox?.setReversedState(true); +``` + +## 漫游功能 + +```typescript +// 显示漫游控制面板 +engine.walkControl?.show(); + +// 隐藏漫游控制面板 +engine.walkControl?.hide(); +``` + +## 事件监听 + +```typescript +// 监听模型加载完成 +const unsubscribe = engine.on('engine:model-loaded', (payload) => { + console.log('Model loaded:', payload.url); +}); + +// 监听对象点击 +engine.on('engine:object-clicked', (payload) => { + console.log('Object clicked:', payload.objectId, payload.position); +}); + +// 监听主题变更 +engine.on('sys:theme-changed', (payload) => { + console.log('Theme changed:', payload.theme); +}); + +// 取消监听 +unsubscribe(); +``` + +## 销毁引擎 + +```typescript +// 在组件卸载或页面关闭时销毁 +engine.destroy(); +``` + +## TypeScript 类型 + +SDK 提供完整的 TypeScript 类型支持: + +```typescript +import type { + // 主入口 + BimEngine, + + // 配置类型 + EngineOptions, + ModelLoadOptions, + DialogOptions, + DialogPosition, + ButtonConfig, + ButtonGroupOptions, + TreeOptions, + TreeNodeConfig, + TreeNodeCheckState, + CollapseOptions, + CollapseItemConfig, + DescriptionOptions, + DescriptionItem, + + // 主题类型 + ThemeConfig, + ThemeType, + + // 事件类型 + EngineEvents, +} from 'iflow-engine'; +``` + +## 常见问题 + +### 1. 模型加载失败 + +- 检查模型 URL 是否正确 +- 确保模型格式受支持(GLTF/GLB/IFC) +- 检查 CORS 配置 + +### 2. 工具栏不显示 + +- 确保容器有足够的尺寸 +- 检查是否调用了 `engine.initialize()` + +### 3. 主题不生效 + +- 确保在引擎初始化后再设置主题 +- 检查自定义主题配置是否完整 + +### 4. 内存泄漏 + +- 确保在组件卸载时调用 `engine.destroy()` +- 取消不再需要的事件监听 + +## 下一步 + +- 查看 [架构文档](ARCHITECTURE.md) 了解设计原理 +- 查看 [模块文档](MODULES/_INDEX.md) 了解详细 API +- 查看 [demo](../demo/) 获取更多示例 + +--- + +**文档生成时间**: 2026-01-23 +**文档版本**: 1.0.0 diff --git a/docs/INDEX.md b/docs/INDEX.md new file mode 100644 index 0000000..797f461 --- /dev/null +++ b/docs/INDEX.md @@ -0,0 +1,104 @@ +# iflow-engine SDK 文档索引 + +> 🤖 **AI 代码助手入口文件** - 请从此文件开始了解项目结构 + +## 项目概述 + +| 项目 | 内容 | +|------|------| +| **名称** | iflow-engine | +| **版本** | 1.0.1 | +| **描述** | BIM 3D 引擎 SDK,支持 Vue2、Vue3、React 和原生 HTML | +| **类型** | 技术项目 / SDK | +| **语言** | TypeScript | +| **构建工具** | Vite | +| **核心依赖** | Three.js, iflow-engine-base | + +## 快速导航 + +| 文档 | 说明 | 适合人群 | +|------|------|---------| +| [ARCHITECTURE.md](ARCHITECTURE.md) | 架构设计、设计模式、模块依赖 | 架构师、核心开发 | +| [GETTING_STARTED.md](GETTING_STARTED.md) | 快速开始、安装、基础用法 | 新用户、集成开发 | +| [MODULES/_INDEX.md](MODULES/_INDEX.md) | 所有模块的详细文档索引 | 所有开发者 | + +## 模块概览 + +``` +src/ +├── bim-engine.ts # 主入口类 BimEngine +├── index.ts # 导出文件 +├── core/ # 核心基础设施 +├── managers/ # 管理器层(业务逻辑) +├── components/ # UI 组件层 +├── services/ # 全局服务(主题、国际化) +├── themes/ # 主题预设和类型 +├── locales/ # 国际化文案 +├── types/ # 公共类型定义 +└── utils/ # 工具函数 +``` + +## 核心模块 + +| 模块 | 路径 | 职责 | 文档 | +|------|------|------|------| +| **BimEngine** | `src/bim-engine.ts` | 主入口类,整合所有功能 | [详情](MODULES/bim-engine.md) | +| **core** | `src/core/` | 事件系统、管理器基类、注册表 | [详情](MODULES/core.md) | +| **managers** | `src/managers/` | 15 个管理器,处理业务逻辑 | [详情](MODULES/managers.md) | +| **components** | `src/components/` | 20+ 个 UI 组件 | [详情](MODULES/components.md) | +| **services** | `src/services/` | 主题管理、国际化服务 | [详情](MODULES/services.md) | + +## 架构分层 + +``` +┌─────────────────────────────────────┐ +│ BimEngine (主引擎) │ ← 用户 API 入口 +├─────────────────────────────────────┤ +│ ManagerRegistry (单例注册表) │ ← 全局状态管理 +├─────────────────────────────────────┤ +│ 管理器层 (15个Manager类) │ ← 业务逻辑 +├─────────────────────────────────────┤ +│ 组件层 (20+ UI组件) │ ← 视图渲染 +├─────────────────────────────────────┤ +│ 服务层 (LocaleManager, ThemeManager) │ ← 横切关注点 +├─────────────────────────────────────┤ +│ 核心基础设施 │ ← 事件、基类 +│ (EventEmitter, BaseManager) │ +└─────────────────────────────────────┘ +``` + +## 关键设计模式 + +| 模式 | 应用位置 | 说明 | +|------|---------|------| +| **单例模式** | ManagerRegistry, LocaleManager, ThemeManager | 全局唯一实例 | +| **观察者模式** | EventEmitter, 服务订阅 | 事件驱动通信 | +| **模板方法** | BaseManager, BaseDialogManager | 统一生命周期 | +| **工厂模式** | BimEngine 初始化 | 创建管理器实例 | + +## 公开 API 统计 + +| 类别 | 数量 | +|------|------| +| 管理器类 | 15 个 | +| UI 组件 | 20+ 个 | +| 事件类型 | 30+ 个 | +| 主题属性 | 70+ 个 | +| 国际化键 | 200+ 个 | + +## 技术栈 + +- **语言**: TypeScript 5.x +- **构建**: Vite 7.x +- **3D 引擎**: Three.js 0.182.x +- **核心 SDK**: iflow-engine-base 1.0.x + +## 相关链接 + +- **仓库**: http://123.60.156.158:13000/bim_engine/bimEngine +- **问题反馈**: http://123.60.156.158:13000/bim_engine/bimEngine/issues + +--- + +**文档生成时间**: 2026-01-23 +**文档版本**: 1.0.0 diff --git a/docs/MODULES/_INDEX.md b/docs/MODULES/_INDEX.md new file mode 100644 index 0000000..7578e81 --- /dev/null +++ b/docs/MODULES/_INDEX.md @@ -0,0 +1,122 @@ +# 模块文档索引 + +## 模块列表 + +| 模块 | 路径 | 职责 | 文档 | +|------|------|------|------| +| **core** | `src/core/` | 核心基础设施:事件系统、管理器基类、注册表 | [core.md](core.md) | +| **managers** | `src/managers/` | 15 个管理器,处理业务逻辑和组件协调 | [managers.md](managers.md) | +| **components** | `src/components/` | 20+ 个 UI 组件 | [components.md](components.md) | +| **services** | `src/services/` | 全局服务:国际化、主题管理 | [services.md](services.md) | + +## Core 模块 + +提供 SDK 的核心基础设施。 + +| 类 | 文件 | 职责 | +|-----|------|------| +| EventEmitter | `event-emitter.ts` | 事件发布/订阅系统 | +| ManagerRegistry | `manager-registry.ts` | 全局单例注册表 | +| BaseManager | `base-manager.ts` | Manager 抽象基类 | +| BaseDialogManager | `base-dialog-manager.ts` | 对话框 Manager 基类 | + +[查看详情 →](core.md) + +## Managers 模块 + +处理业务逻辑,协调组件交互。 + +### 核心管理器 + +| 管理器 | 职责 | +|--------|------| +| EngineManager | 3D 引擎管理 | +| ToolbarManager | 工具栏管理 | +| DialogManager | 对话框管理 | +| ButtonGroupManager | 按钮组管理 | +| RightKeyManager | 右键菜单管理 | + +### 功能管理器 + +| 管理器 | 职责 | +|--------|------| +| PropertyPanelManager | 属性面板管理 | +| ConstructTreeManagerBtn | 构件树管理 | +| MeasureDialogManager | 测量对话框管理 | +| SectionPlaneDialogManager | 平面剖切管理 | +| SectionAxisDialogManager | 轴向剖切管理 | +| SectionBoxDialogManager | 剖切盒管理 | +| WalkControlManager | 漫游控制管理 | +| WalkPathDialogManager | 漫游路径管理 | +| WalkPlanViewDialogManager | 漫游平面图管理 | +| MapDialogManager | 地图管理 | + +[查看详情 →](managers.md) + +## Components 模块 + +纯 UI 组件,不包含业务逻辑。 + +### 核心组件 + +| 组件 | 职责 | +|------|------| +| Engine | 3D 视口容器 | +| BimDialog | 通用对话框 | +| BimTree | 树形控件 | +| BimMenu | 菜单组件 | +| BimButtonGroup | 按钮组 | + +### 面板组件 + +| 组件 | 职责 | +|------|------| +| MeasurePanel | 测量面板 | +| SectionPlanePanel | 平面剖切面板 | +| SectionAxisPanel | 轴向剖切面板 | +| SectionBoxPanel | 剖切盒面板 | +| WalkControlPanel | 漫游控制面板 | +| WalkPathPanel | 漫游路径面板 | +| WalkPlanViewPanel | 漫游平面图面板 | +| MapPanel | 地图面板 | + +### 展示组件 + +| 组件 | 职责 | +|------|------| +| BimCollapse | 折叠面板 | +| BimTab | 标签页 | +| BimDescription | 描述列表 | + +[查看详情 →](components.md) + +## Services 模块 + +提供全局服务。 + +| 服务 | 职责 | +|------|------| +| LocaleManager | 国际化服务,多语言支持 | +| ThemeManager | 主题管理服务,明暗切换 | + +[查看详情 →](services.md) + +## 类型定义 + +| 文件 | 内容 | +|------|------| +| `types/component.ts` | 组件接口 IBimComponent | +| `types/events.ts` | 事件类型 EngineEvents | +| `types/measure.ts` | 测量类型定义 | +| `locales/types.ts` | 国际化类型 | +| `themes/types.ts` | 主题配置类型 | + +## 工具函数 + +| 文件 | 内容 | +|------|------| +| `utils/icon-manager.ts` | 图标管理器,提供 40+ SVG 图标 | + +--- + +**文档生成时间**: 2026-01-23 diff --git a/docs/MODULES/components.md b/docs/MODULES/components.md new file mode 100644 index 0000000..ed0e05b --- /dev/null +++ b/docs/MODULES/components.md @@ -0,0 +1,605 @@ +# Components 模块文档 + +## 模块概述 + +| 项目 | 内容 | +|------|------| +| **模块名** | components | +| **职责** | 提供 BIM 3D 引擎 SDK 的所有 UI 组件 | +| **公开 API** | 20+ 个组件类 | +| **状态** | ✅ 稳定 | + +## 代码地图 + +``` +src/components/ +├── engine/ # 3D 引擎组件 +├── dialog/ # 通用弹窗组件 +├── tree/ # 树形控件组件 +├── menu/ # 菜单组件 +├── button-group/ # 按钮组件 +├── collapse/ # 折叠面板组件 +├── tab/ # 标签页组件 +├── description/ # 描述列表组件 +├── measure-panel/ # 测量面板组件 +├── section-plane-panel/ # 平面剖切面板 +├── section-axis-panel/ # 轴向剖切面板 +├── section-box-panel/ # 剖切盒面板 +├── walk-control-panel/ # 漫游控制面板 +├── walk-path-panel/ # 漫游路径面板 +├── walk-plan-view-panel/ # 漫游平面图面板 +├── right-key/ # 右键菜单组件 +└── map-panel/ # 地图面板组件 +``` + +## 组件接口 + +所有组件实现统一接口: + +```typescript +interface IBimComponent { + element: HTMLElement; + init(): void; + setTheme(theme: ThemeConfig): void; + setLocales?(): void; + destroy(): void; +} +``` + +--- + +## Engine(3D 引擎组件) + +### 概述 + +包装第三方 3D 引擎 SDK,提供模型加载、视角控制、测量功能。 + +### 配置 + +```typescript +interface EngineOptions { + container: HTMLElement; + backgroundColor?: number | string; + version?: 'v1' | 'v2'; + showStats?: boolean; + showViewCube?: boolean; +} +``` + +### API + +```typescript +class Engine { + init(): void; + loadModel(url: string, options?: ModelLoadOptions): void; + CameraGoHome(): void; + getEngine(): any; + activateMeasure(mode: MeasureMode): void; + deactivateMeasure(): void; + setTheme(theme: ThemeConfig): void; + destroy(): void; +} +``` + +### 测量模式 + +| 模式 | 说明 | +|------|------| +| `distance` | 距离测量 | +| `minDistance` | 最小距离 | +| `angle` | 角度测量 | +| `elevation` | 标高测量 | +| `volume` | 体积测量 | +| `laserDistance` | 激光测距 | +| `slope` | 坡度测量 | +| `spaceVolume` | 空间体积 | + +--- + +## BimDialog(通用弹窗组件) + +### 概述 + +通用弹窗容器,支持拖拽、缩放、自定义内容。 + +### 配置 + +```typescript +interface DialogOptions { + container: HTMLElement; + title?: string; + content?: HTMLElement | string; + width?: number | string; + height?: number | string; + position?: DialogPosition; + draggable?: boolean; + resizable?: boolean; + minWidth?: number; + minHeight?: number; + onOpen?: () => void; + onClose?: () => void; + backgroundColor?: string; + headerBackgroundColor?: string; + titleColor?: string; + textColor?: string; + borderColor?: string; +} + +type DialogPosition = + | 'center' + | 'top-left' | 'top-center' | 'top-right' + | 'left-center' | 'right-center' + | 'bottom-left' | 'bottom-center' | 'bottom-right' + | { x: number; y: number }; +``` + +### API + +```typescript +class BimDialog { + init(): void; + setContent(content: HTMLElement | string): void; + fitWidth(recenter?: boolean): void; + fitHeight(recenter?: boolean): void; + close(): void; + setTheme(theme: ThemeConfig): void; + destroy(): void; +} +``` + +--- + +## BimTree(树形控件组件) + +### 概述 + +递归树形结构展示,支持复选框、搜索、展开折叠。 + +### 配置 + +```typescript +interface TreeOptions { + data: TreeNodeConfig[]; + checkable?: boolean; + checkStrictly?: boolean; + indent?: number; + defaultExpandAll?: boolean; + enableSearch?: boolean; + searchPlaceholder?: string; + onNodeCheck?: (node: BimTreeNode) => void; + onNodeSelect?: (node: BimTreeNode) => void; + onNodeExpand?: (node: BimTreeNode) => void; +} + +interface TreeNodeConfig { + id: string; + label: string; + icon?: string; + children?: TreeNodeConfig[]; + expanded?: boolean; + checked?: boolean; + disabled?: boolean; + data?: any; +} +``` + +### API + +```typescript +class BimTree { + init(): void; + getNode(id: string): BimTreeNode | undefined; + checkNode(id: string, checked: boolean): void; + expandAll(expanded: boolean): void; + getCheckedNodes(includeHalf?: boolean): TreeNodeConfig[]; + revealNode(node: BimTreeNode): void; + setTheme(theme: ThemeConfig): void; + destroy(): void; +} +``` + +--- + +## BimMenu(菜单组件) + +### 概述 + +菜单列表渲染,支持分组、排序、递归子菜单。 + +### 配置 + +```typescript +interface MenuOptions { + items: MenuItemConfig[]; + groupOrder?: string[]; +} + +interface MenuItemConfig { + id: string; + label: string; + icon?: string; + group?: string; + order?: number; + visible?: boolean; + disabled?: boolean; + children?: MenuItemConfig[]; + onClick?: () => void; +} +``` + +### API + +```typescript +class BimMenu { + init(): void; + getElement(): HTMLElement; + setTheme(theme: ThemeConfig): void; + destroy(): void; +} +``` + +--- + +## BimButtonGroup(按钮组件) + +### 概述 + +分组按钮布局,支持下拉菜单、互斥激活。 + +### 配置 + +```typescript +interface ButtonGroupOptions { + container: HTMLElement | string; + position?: GroupPosition; + direction?: 'row' | 'column'; + align?: 'vertical' | 'horizontal'; + expand?: 'up' | 'down' | 'left' | 'right'; + type?: 'default' | 'glass-pill'; + showLabel?: boolean; + visibility?: Record; + backgroundColor?: string; + btnBackgroundColor?: string; + btnHoverColor?: string; + btnActiveColor?: string; + iconColor?: string; + iconActiveColor?: string; + textColor?: string; + textActiveColor?: string; +} + +interface ButtonConfig { + id: string; + type: 'button' | 'menu'; + label: string; + icon?: string; + keepActive?: boolean; + exclusive?: boolean; + isActive?: boolean; + disabled?: boolean; + onClick?: (button: any) => void; + children?: ButtonConfig[]; + groupId?: string; + parentId?: string; + align?: 'vertical' | 'horizontal'; + iconSize?: number; + minWidth?: number; +} +``` + +### API + +```typescript +class BimButtonGroup { + init(): Promise; + addGroup(groupId: string, beforeGroupId?: string): void; + addButton(config: ButtonConfig): void; + setBtnActive(id: string, active?: boolean): void; + setShowLabel(show: boolean): void; + updateButtonVisibility(id: string, visible: boolean): void; + setColors(colors: ButtonGroupColors): void; + setTheme(theme: ThemeConfig): void; + destroy(): void; +} +``` + +--- + +## BimCollapse(折叠面板组件) + +### 概述 + +可折叠/展开的面板组件,支持手风琴模式。 + +### 配置 + +```typescript +interface CollapseOptions { + container: HTMLElement | string; + items: CollapseItemConfig[]; + activeIds?: string[]; + accordion?: boolean; + bordered?: boolean; + ghost?: boolean; + className?: string; + onChange?: (activeIds: string[]) => void; +} + +interface CollapseItemConfig { + id: string; + title: string; + content: HTMLElement | string; + icon?: string; + extra?: HTMLElement | string; + disabled?: boolean; + className?: string; +} +``` + +### API + +```typescript +class BimCollapse { + init(): void; + toggleItem(id: string): void; + setTheme(theme: ThemeConfig): void; + destroy(): void; +} +``` + +--- + +## BimTab(标签页组件) + +### 概述 + +标签页容器,支持图标、禁用态。 + +### 配置 + +```typescript +interface TabOptions { + container: HTMLElement; + tabs: TabItem[]; + activeId?: string; + onChange?: (tabId: string, tab: TabItem) => void; +} + +interface TabItem { + id: string; + title: string; + icon?: string; + content: HTMLElement | string; + disabled?: boolean; +} +``` + +### API + +```typescript +class BimTab { + init(): void; + activateTab(tabId: string): void; + setTheme(theme: ThemeConfig): void; + setLocales(): void; + destroy(): void; +} +``` + +--- + +## BimDescription(描述列表组件) + +### 概述 + +Key-Value 数据展示组件。 + +### 配置 + +```typescript +interface DescriptionOptions { + container: HTMLElement | string; + items: DescriptionItem[]; + bordered?: boolean; + className?: string; + fontSize?: string; + labelColor?: string; + valueColor?: string; + labelWidth?: string; + labelPadding?: string; + valuePadding?: string; +} + +interface DescriptionItem { + label: string; + value: HTMLElement | string; + labelColor?: string; + valueColor?: string; + className?: string; +} +``` + +### API + +```typescript +class BimDescription { + init(): void; + setItems(items: DescriptionItem[]): void; + setTheme(theme: ThemeConfig): void; + destroy(): void; +} +``` + +--- + +## MeasurePanel(测量面板组件) + +### 概述 + +测量面板 UI,支持 8 种测量类型。 + +### 配置 + +```typescript +interface MeasurePanelOptions { + defaultMode?: MeasureMode; + defaultExpanded?: boolean; + onModeChange?: (mode: MeasureMode) => void; + onExpandedChange?: (expanded: boolean) => void; + onClearAll?: () => void; + onSettings?: () => void; +} +``` + +### API + +```typescript +class MeasurePanel { + init(): void; + getActiveMode(): MeasureMode; + switchMode(mode: MeasureMode): void; + setResult(result: MeasureResult | null): void; + clearAll(): void; + getConfig(): MeasureConfig; + setConfig(partial: Partial, persist?: boolean): void; + setExpanded(expanded: boolean): void; + getExpanded(): boolean; + setTheme(theme: ThemeConfig): void; + destroy(): void; +} +``` + +--- + +## SectionPlanePanel(平面剖切面板) + +### 概述 + +平面剖切控制面板。 + +### 配置 + +```typescript +interface SectionPlanePanelOptions { + onHide?: () => void; + onReverse?: () => void; + onReset?: () => void; +} +``` + +### API + +```typescript +class SectionPlanePanel { + init(): void; + setTheme(theme: ThemeConfig): void; + setLocales(): void; + destroy(): void; +} +``` + +--- + +## SectionAxisPanel(轴向剖切面板) + +### 概述 + +X/Y/Z 轴向剖切控制面板。 + +### 配置 + +```typescript +interface SectionAxisPanelOptions { + defaultAxis?: 'x' | 'y' | 'z'; + onHideToggle?: (isHidden: boolean) => void; + onReverse?: () => void; + onAxisChange?: (axis: 'x' | 'y' | 'z') => void; +} +``` + +--- + +## SectionBoxPanel(剖切盒面板) + +### 概述 + +六面体剖切盒控制面板。 + +### 配置 + +```typescript +interface SectionBoxPanelOptions { + onHideToggle?: (isHidden: boolean) => void; + onReverseToggle?: (isReversed: boolean) => void; + onFitToModel?: () => void; + onReset?: () => void; + onRangeChange?: (axis: string, value: number) => void; +} +``` + +--- + +## WalkControlPanel(漫游控制面板) + +### 概述 + +漫游模式控制面板。 + +### 配置 + +```typescript +interface WalkControlPanelOptions { + defaultSpeed?: number; + defaultGravity?: boolean; + defaultCollision?: boolean; + defaultCharacterModel?: 'construction-worker' | 'office-male'; + defaultWalkMode?: 'walk' | 'run'; + onPlanViewToggle?: (active: boolean) => void; + onPathModeToggle?: (active: boolean) => void; + onWalkModeToggle?: (active: boolean) => void; + onSpeedChange?: (speed: number) => void; + onGravityToggle?: (enabled: boolean) => void; + onCollisionToggle?: (enabled: boolean) => void; + onCharacterModelChange?: (model: string) => void; + onWalkModeChange?: (mode: string) => void; + onExit?: () => void; +} +``` + +### API + +```typescript +class WalkControlPanel { + init(): void; + getState(): WalkControlState; + setPlanViewActive(active: boolean): void; + setPathModeActive(active: boolean): void; + setTheme(theme: ThemeConfig): void; + setLocales(): void; + destroy(): void; +} + +interface WalkControlState { + mode: 'none' | 'path' | 'walk'; + isPlanViewActive: boolean; + speed: number; + gravity: boolean; + collision: boolean; + characterModel: string; + walkMode: string; +} +``` + +--- + +## 依赖关系 + +所有组件依赖: +- `ThemeManager` (主题) +- `LocaleManager` (国际化,部分组件) + +组件不直接依赖 Manager,由 Manager 创建和管理组件实例。 + +--- + +**文档生成时间**: 2026-01-23 diff --git a/docs/MODULES/core.md b/docs/MODULES/core.md new file mode 100644 index 0000000..0207621 --- /dev/null +++ b/docs/MODULES/core.md @@ -0,0 +1,386 @@ +# Core 模块文档 + +## 模块概述 + +| 项目 | 内容 | +|------|------| +| **模块名** | core | +| **职责** | 提供 SDK 的核心基础设施:事件发射、Manager 注册表、Manager 生命周期管理 | +| **公开 API** | 4 个类 | +| **状态** | ✅ 稳定 | + +## 代码地图 + +``` +src/core/ +├── event-emitter.ts # 事件发射器 +├── manager-registry.ts # Manager 注册表(单例) +├── base-manager.ts # Manager 抽象基类 +└── base-dialog-manager.ts # 对话框 Manager 基类 +``` + +| 文件 | 行数 | 职责 | 导出 | +|------|------|------|------| +| `event-emitter.ts` | 70 | 发布/订阅事件系统 | `EventEmitter` | +| `manager-registry.ts` | 127 | 全局单例注册表 | `ManagerRegistry` | +| `base-manager.ts` | 57 | Manager 基类 | `BaseManager` | +| `base-dialog-manager.ts` | 145 | 对话框 Manager 基类 | `BaseDialogManager` | + +## 架构设计 + +### 类关系图 + +``` +EventEmitter + ↑ (组合) +ManagerRegistry (单例) + ↑ (访问) +BaseManager (抽象类) + ↑ (继承) +BaseDialogManager (抽象类) + ↑ (继承) +具体 Manager 类 +``` + +### 设计模式 + +| 模式 | 应用 | 说明 | +|------|------|------| +| 单例模式 | ManagerRegistry | 全局唯一实例 | +| 发布/订阅 | EventEmitter | 解耦事件通信 | +| 模板方法 | BaseDialogManager | 定义对话框生命周期 | + +--- + +## EventEmitter + +### 概述 + +轻量级事件发射器,提供发布/订阅功能。 + +### API + +```typescript +class EventEmitter { + // 订阅事件,返回取消订阅函数 + on(event: string, listener: (payload: any) => void): () => void; + + // 取消订阅 + off(event: string, listener: (payload: any) => void): void; + + // 发送事件 + emit(event: string, payload?: any): void; + + // 清除所有监听器 + clear(): void; +} +``` + +### 使用示例 + +```typescript +const emitter = new EventEmitter(); + +// 订阅 +const unsubscribe = emitter.on('user:login', (data) => { + console.log('User logged in:', data); +}); + +// 发送 +emitter.emit('user:login', { userId: 123 }); + +// 取消订阅 +unsubscribe(); +``` + +--- + +## ManagerRegistry + +### 概述 + +全局单例注册表,集中管理所有 Manager 实例,提供跨 Manager 通信。 + +### API + +```typescript +class ManagerRegistry { + // 获取单例 + static getInstance(): ManagerRegistry; + + // 重置单例(用于测试) + static reset(): void; + + // 容器元素 + container: HTMLElement | null; + wrapper: HTMLElement | null; + + // Manager 实例 + toolbar: ToolbarManager | null; + dialog: DialogManager | null; + engine3d: EngineManager | null; + buttonGroup: ButtonGroupManager | null; + rightKey: RightKeyManager | null; + constructTree: ConstructTreeManagerBtn | null; + propertyPanel: PropertyPanelManager | null; + measure: MeasureDialogManager | null; + walkControl: WalkControlManager | null; + map: MapDialogManager | null; + sectionPlane: SectionPlaneDialogManager | null; + sectionAxis: SectionAxisDialogManager | null; + sectionBox: SectionBoxDialogManager | null; + + // 事件方法 + emit(event: K, payload: EngineEvents[K]): void; + on(event: K, listener: (payload: EngineEvents[K]) => void): () => void; + off(event: K, listener: (payload: EngineEvents[K]) => void): void; + clearEvents(): void; +} +``` + +### 使用示例 + +```typescript +const registry = ManagerRegistry.getInstance(); + +// 访问 Manager +registry.toolbar?.show(); +registry.measure?.switchMode('distance'); + +// 发送事件 +registry.emit('engine:model-loaded', { url: 'model.gltf' }); + +// 订阅事件 +const unsubscribe = registry.on('engine:object-clicked', (payload) => { + console.log('Object clicked:', payload.objectId); +}); +``` + +### 支持的事件 + +| 事件 | 数据类型 | 说明 | +|------|---------|------| +| `ui:open-dialog` | `{ id: string; data?: any }` | 打开对话框 | +| `ui:close-dialog` | `{ id: string }` | 关闭对话框 | +| `engine:model-loaded` | `{ url: string }` | 模型加载完成 | +| `engine:object-clicked` | `{ objectId: string; position: Point3D }` | 点击对象 | +| `ui:tree-node-check` | `{ id: string; checked: boolean; node: any }` | 树节点勾选 | +| `ui:tree-node-select` | `{ id: string; selected: boolean; node: any }` | 树节点选择 | +| `sys:theme-changed` | `{ theme: string }` | 主题变更 | +| `sys:locale-changed` | `{ locale: string }` | 语言变更 | +| `walk:speed-change` | `{ speed: number }` | 漫游速度变更 | +| `walk:path-mode-toggle` | `{ isActive: boolean }` | 路径模式切换 | +| `map:opened` | `{}` | 地图打开 | +| `map:closed` | `{}` | 地图关闭 | + +--- + +## BaseManager + +### 概述 + +所有 Manager 的抽象基类,提供注册表访问和事件订阅管理。 + +### API + +```typescript +abstract class BaseManager { + // 受保护属性 + protected registry: ManagerRegistry; + + // 受保护方法 + protected subscribe( + event: K, + handler: (payload: EngineEvents[K]) => void + ): void; + + protected emit( + event: K, + payload: EngineEvents[K] + ): void; + + // 公开方法 + destroy(): void; +} +``` + +### 使用示例 + +```typescript +export class CustomManager extends BaseManager { + constructor() { + super(); + } + + public initialize(): void { + // 订阅事件(自动管理生命周期) + this.subscribe('engine:model-loaded', (payload) => { + console.log('Model loaded:', payload.url); + }); + } + + public doSomething(): void { + // 发送事件 + this.emit('custom:action', { data: 'value' }); + + // 访问其他 Manager + this.registry.toolbar?.show(); + } + + public destroy(): void { + // 自动清理所有订阅 + super.destroy(); + } +} +``` + +### 特性 + +- **自动资源清理**: `destroy()` 时自动取消所有订阅 +- **类型安全**: 使用 TypeScript 泛型确保事件类型 +- **注册表访问**: 可通过 `this.registry` 访问所有 Manager + +--- + +## BaseDialogManager + +### 概述 + +对话框 Manager 的抽象基类,封装对话框的完整生命周期。 + +### API + +```typescript +abstract class BaseDialogManager extends BaseManager { + // 抽象属性(子类必须实现) + protected abstract get dialogId(): string; + protected abstract get dialogTitle(): string; + + // 抽象方法(子类必须实现) + protected abstract createContent(): HTMLElement; + + // 可选属性(子类可重写) + protected get dialogWidth(): number; // 默认: 300 + protected get dialogHeight(): number | 'auto'; // 默认: 'auto' + protected get dialogOptions(): DialogManagerOptions; + + // 钩子方法(子类可重写) + protected onDialogCreated(): void; + protected onDialogClose(): void; + protected onBeforeDestroy(): void; + protected getDialogPosition(): { x: number; y: number }; + + // 公开方法 + show(): void; + hide(): void; + toggle(): void; + isOpen(): boolean; + destroy(): void; +} + +interface DialogManagerOptions { + draggable?: boolean; // 默认 true + resizable?: boolean; // 默认 false +} +``` + +### 使用示例 + +```typescript +export class MeasureDialogManager extends BaseDialogManager { + private panel: MeasurePanel | null = null; + + protected get dialogId(): string { + return 'measure-dialog'; + } + + protected get dialogTitle(): string { + return 'measure.dialogTitle'; // i18n key + } + + protected get dialogWidth(): number { + return 250; + } + + protected createContent(): HTMLElement { + this.panel = new MeasurePanel({ + onModeChange: (mode) => { + this.registry.engine3d?.activateMeasure(mode); + } + }); + this.panel.init(); + + const wrapper = document.createElement('div'); + wrapper.appendChild(this.panel.element); + return wrapper; + } + + protected onDialogCreated(): void { + this.dialog?.fitHeight(false); + } + + protected onDialogClose(): void { + this.registry.toolbar?.setBtnActive('measure', false); + } + + protected onBeforeDestroy(): void { + this.panel?.destroy(); + this.panel = null; + } + + // 业务方法 + public switchMode(mode: string): void { + this.panel?.switchMode(mode); + } +} +``` + +### 生命周期 + +``` +show() + ↓ +销毁旧对话框 + ↓ +createContent() ← 子类实现 + ↓ +创建 BimDialog + ↓ +onDialogCreated() ← 钩子 + ↓ +显示中... + ↓ +hide() / 关闭按钮 + ↓ +onDialogClose() ← 钩子 + ↓ +onBeforeDestroy() ← 钩子 + ↓ +销毁对话框 +``` + +--- + +## 依赖关系 + +``` +BaseDialogManager + ↓ 继承 +BaseManager + ↓ 依赖 +ManagerRegistry + ↓ 组合 +EventEmitter +``` + +### 被依赖情况 + +| 模块 | 依赖方式 | +|------|---------| +| managers/* | 继承 BaseManager 或 BaseDialogManager | +| components/* | 间接依赖(通过 Manager) | +| BimEngine | 使用 ManagerRegistry | + +--- + +**文档生成时间**: 2026-01-23 diff --git a/docs/MODULES/managers.md b/docs/MODULES/managers.md new file mode 100644 index 0000000..282fad6 --- /dev/null +++ b/docs/MODULES/managers.md @@ -0,0 +1,489 @@ +# Managers 模块文档 + +## 模块概述 + +| 项目 | 内容 | +|------|------| +| **模块名** | managers | +| **职责** | 处理业务逻辑,协调组件交互,管理组件生命周期 | +| **公开 API** | 15 个 Manager 类 | +| **状态** | ✅ 稳定 | + +## 代码地图 + +``` +src/managers/ +├── engine-manager.ts # 3D 引擎管理器 +├── toolbar-manager.ts # 工具栏管理器 +├── dialog-manager.ts # 对话框管理器 +├── button-group-manager.ts # 按钮组管理器 +├── right-key-manager.ts # 右键菜单管理器 +├── property-panel-manager.ts # 属性面板管理器 +├── construct-tree-manager-btn.ts # 构件树管理器 +├── walk-control-manager.ts # 漫游控制管理器 +├── measure-dialog-manager.ts # 测量对话框管理器 +├── section-plane-dialog-manager.ts # 平面剖切对话框管理器 +├── section-box-dialog-manager.ts # 剖切盒对话框管理器 +├── section-axis-dialog-manager.ts # 轴向剖切对话框管理器 +├── map-dialog-manager.ts # 地图对话框管理器 +├── walk-path-dialog-manager.ts # 漫游路径对话框管理器 +└── walk-plan-view-dialog-manager.ts # 漫游平面图对话框管理器 +``` + +## 管理器分类 + +### 按继承关系 + +``` +BaseManager +├── EngineManager +├── ToolbarManager +├── DialogManager +├── ButtonGroupManager +├── RightKeyManager +├── PropertyPanelManager +├── ConstructTreeManagerBtn +└── WalkControlManager + +BaseDialogManager (继承自 BaseManager) +├── MeasureDialogManager +├── SectionPlaneDialogManager +├── SectionAxisDialogManager +├── SectionBoxDialogManager +├── MapDialogManager +├── WalkPathDialogManager +└── WalkPlanViewDialogManager +``` + +### 按功能分类 + +| 类别 | 管理器 | 职责 | +|------|--------|------| +| **核心** | EngineManager | 3D 引擎管理 | +| **UI 容器** | ToolbarManager, DialogManager, ButtonGroupManager | 容器组件管理 | +| **交互** | RightKeyManager, PropertyPanelManager, ConstructTreeManagerBtn | 用户交互 | +| **3D 工具** | MeasureDialogManager, SectionPlaneDialogManager, SectionAxisDialogManager, SectionBoxDialogManager | 3D 操作工具 | +| **漫游** | WalkControlManager, WalkPathDialogManager, WalkPlanViewDialogManager, MapDialogManager | 漫游功能 | + +--- + +## EngineManager + +### 概述 + +管理 3D 引擎的初始化、模型加载和测量功能。 + +### API + +```typescript +class EngineManager extends BaseManager { + initialize(options?: EngineOptions): void; + isInitialized(): boolean; + loadModel(url: string, options?: ModelLoadOptions): void; + getEngine(): any; + CameraGoHome(): void; + activateMeasure(mode: MeasureMode): void; + deactivateMeasure(): void; + getCurrentMeasureType(): MeasureMode | null; + destroy(): void; +} +``` + +### 使用示例 + +```typescript +const engine = new EngineManager(container); +engine.initialize(); +engine.loadModel('model.gltf', { autoFit: true }); +engine.activateMeasure('distance'); +``` + +--- + +## ToolbarManager + +### 概述 + +管理底部工具栏的按钮配置、显示控制、主题管理。 + +### API + +```typescript +class ToolbarManager extends BaseManager { + addGroup(groupId: string, beforeGroupId?: string): void; + addButton(config: ButtonConfig): void; + setBtnActive(id: string, active?: boolean): void; + setButtonVisibility(id: string, visible: boolean): void; + setShowLabel(show: boolean): void; + updateTheme(theme: ThemeConfig): void; + setBackgroundColor(color: string): void; + setColors(colors: ButtonGroupColors): void; + show(): void; + hide(): void; + setVisible(visible: boolean): void; + refresh(): void; + destroy(): void; +} +``` + +### 使用示例 + +```typescript +const toolbar = new ToolbarManager(container); + +toolbar.addGroup('custom-group'); +toolbar.addButton({ + id: 'custom-btn', + groupId: 'custom-group', + type: 'button', + label: 'Custom', + icon: '...', + onClick: () => console.log('Clicked') +}); + +toolbar.setBtnActive('custom-btn', true); +``` + +--- + +## DialogManager + +### 概述 + +创建和管理通用对话框实例。 + +### API + +```typescript +class DialogManager extends BaseManager { + create(options: DialogOptions): BimDialog; + showInfoDialog(): void; + updateTheme(theme: ThemeConfig): void; + destroy(): void; +} +``` + +### 使用示例 + +```typescript +const dialogManager = new DialogManager(container); + +const dialog = dialogManager.create({ + title: 'My Dialog', + content: element, + width: 400, + onClose: () => console.log('Closed') +}); +``` + +--- + +## MeasureDialogManager + +### 概述 + +管理测量工具的对话框和测量面板。 + +### API + +```typescript +class MeasureDialogManager extends BaseDialogManager { + getActiveMode(): MeasureMode; + switchMode(mode: MeasureMode): void; + setMeasureResult(result: MeasureResult | null): void; + getConfig(): MeasureConfig; + setConfig(partial: Partial, persist?: boolean): void; + clearAll(): void; + openSettings(): void; + show(): void; + hide(): void; + toggle(): void; +} +``` + +### 测量模式 + +| 模式 | 说明 | +|------|------| +| `distance` | 距离测量 | +| `minDistance` | 最小距离 | +| `angle` | 角度测量 | +| `elevation` | 标高测量 | +| `volume` | 体积测量 | +| `laserDistance` | 激光测距 | +| `slope` | 坡度测量 | +| `spaceVolume` | 空间体积 | + +### 使用示例 + +```typescript +const measure = new MeasureDialogManager(); +measure.show(); +measure.switchMode('distance'); + +const config = measure.getConfig(); +measure.setConfig({ unit: 'cm', precision: 1 }); +``` + +--- + +## SectionPlaneDialogManager + +### 概述 + +管理平面剖切工具对话框。 + +### API + +```typescript +class SectionPlaneDialogManager extends BaseDialogManager { + show(): void; + hide(): void; + toggle(): void; + isOpen(): boolean; +} +``` + +--- + +## SectionAxisDialogManager + +### 概述 + +管理轴向剖切工具对话框。 + +### API + +```typescript +class SectionAxisDialogManager extends BaseDialogManager { + getHiddenState(): boolean; + setHiddenState(isHidden: boolean): void; + getActiveAxis(): 'x' | 'y' | 'z'; + setActiveAxis(axis: 'x' | 'y' | 'z'): void; + show(): void; + hide(): void; + toggle(): void; +} +``` + +### 使用示例 + +```typescript +const sectionAxis = new SectionAxisDialogManager(); +sectionAxis.show(); +sectionAxis.setActiveAxis('y'); +``` + +--- + +## SectionBoxDialogManager + +### 概述 + +管理剖切盒工具对话框。 + +### API + +```typescript +class SectionBoxDialogManager extends BaseDialogManager { + getHiddenState(): boolean; + setHiddenState(isHidden: boolean): void; + getReversedState(): boolean; + setReversedState(isReversed: boolean): void; + getRange(): SectionBoxRange; + setRange(range: Partial): void; + show(): void; + hide(): void; + toggle(): void; +} + +interface SectionBoxRange { + minX: number; + maxX: number; + minY: number; + maxY: number; + minZ: number; + maxZ: number; +} +``` + +### 使用示例 + +```typescript +const sectionBox = new SectionBoxDialogManager(); +sectionBox.show(); + +const range = sectionBox.getRange(); +sectionBox.setRange({ minX: 0, maxX: 100 }); +sectionBox.setReversedState(true); +``` + +--- + +## WalkControlManager + +### 概述 + +管理漫游控制面板和相关交互。 + +### API + +```typescript +class WalkControlManager extends BaseManager { + init(): void; + show(): void; + hide(): void; + destroy(): void; +} +``` + +### 事件 + +| 事件 | 说明 | +|------|------| +| `walk:plan-view-toggle` | 平面图切换 | +| `walk:path-mode-toggle` | 路径模式切换 | +| `walk:walk-mode-toggle` | 漫游模式切换 | +| `walk:speed-change` | 速度变化 | +| `walk:gravity-toggle` | 重力开关 | +| `walk:collision-toggle` | 碰撞开关 | + +--- + +## PropertyPanelManager + +### 概述 + +管理构件属性面板的显示。 + +### API + +```typescript +class PropertyPanelManager extends BaseManager { + init(): void; + show(): void; + hide(): void; + isOpen(): boolean; + destroy(): void; +} +``` + +--- + +## ConstructTreeManagerBtn + +### 概述 + +管理构件树按钮和对话框。 + +### API + +```typescript +class ConstructTreeManagerBtn extends BaseManager { + openConstructTreeDialog(): void; + addGroup(groupId: string, beforeGroupId?: string): void; + addButton(config: ButtonConfig): void; + setButtonVisibility(id: string, visible: boolean): void; + setShowLabel(show: boolean): void; + setVisible(visible: boolean): void; + setBackgroundColor(color: string): void; + setColors(colors: ButtonGroupColors): void; + refresh(): void; + destroy(): void; +} +``` + +--- + +## RightKeyManager + +### 概述 + +管理右键上下文菜单。 + +### API + +```typescript +class RightKeyManager extends BaseManager { + registerHandler(handler: ContextMenuHandler): void; + showMenu(x: number, y: number, items: MenuItemConfig[], groupOrder?: string[]): void; + hide(): void; + destroy(): void; +} + +type ContextMenuHandler = (e: MouseEvent) => MenuItemConfig[]; +``` + +### 使用示例 + +```typescript +const rightKey = new RightKeyManager(container); + +rightKey.registerHandler((e) => [ + { id: 'view', label: 'View', onClick: () => {} }, + { id: 'delete', label: 'Delete', onClick: () => {} } +]); +``` + +--- + +## ButtonGroupManager + +### 概述 + +创建和管理多个按钮组实例。 + +### API + +```typescript +class ButtonGroupManager extends BaseManager { + create(id: string, options: ButtonGroupOptions): BimButtonGroup; + get(id: string): BimButtonGroup | undefined; + updateTheme(theme: ThemeConfig): void; + destroy(): void; +} +``` + +--- + +## 交互流程 + +### 工具栏按钮触发测量 + +``` +ToolbarManager (按钮点击) + ↓ +MeasureDialogManager.show() + ↓ +onModeChange 事件 + ↓ +EngineManager.activateMeasure(mode) + ↓ +3D 引擎进入测量模式 +``` + +### 漫游模式激活 + +``` +ToolbarManager (walk 按钮) + ↓ +WalkControlManager.show() + ↓ +隐藏底部工具栏 + ↓ +显示漫游控制面板 +``` + +--- + +## 依赖关系 + +所有 Manager 都依赖: +- `BaseManager` 或 `BaseDialogManager` +- `ManagerRegistry` + +各 Manager 之间通过事件系统通信,避免直接依赖。 + +--- + +**文档生成时间**: 2026-01-23 diff --git a/docs/MODULES/services.md b/docs/MODULES/services.md new file mode 100644 index 0000000..eeb4b2c --- /dev/null +++ b/docs/MODULES/services.md @@ -0,0 +1,402 @@ +# Services 模块文档 + +## 模块概述 + +| 项目 | 内容 | +|------|------| +| **模块名** | services | +| **职责** | 提供全局状态管理服务:国际化和主题系统 | +| **公开 API** | 2 个管理器类 + 辅助函数 | +| **状态** | ✅ 稳定 | + +## 代码地图 + +``` +src/ +├── services/ +│ ├── locale.ts # 国际化服务 +│ └── theme.ts # 主题服务 +├── locales/ +│ ├── types.ts # 翻译类型定义 +│ ├── zh-CN.ts # 中文翻译 +│ └── en-US.ts # 英文翻译 +└── themes/ + ├── types.ts # 主题类型定义 + └── presets.ts # 内置主题预设 +``` + +--- + +## LocaleManager(国际化服务) + +### 概述 + +管理应用语言、翻译文本,支持实时订阅。 + +### API + +```typescript +class LocaleManager { + getLocale(): LocaleType; + setLocale(locale: LocaleType): void; + t(key: string): string; + subscribe(listener: (locale: LocaleType) => void): () => void; +} + +type LocaleType = 'zh-CN' | 'en-US'; + +// 单例导出 +export const localeManager: LocaleManager; + +// 便捷函数 +export function t(key: string): string; +``` + +### 使用示例 + +```typescript +import { localeManager, t } from 'iflow-engine'; + +// 获取当前语言 +const locale = localeManager.getLocale(); // 'zh-CN' + +// 切换语言 +localeManager.setLocale('en-US'); + +// 翻译 +console.log(t('toolbar.home')); // 'Home' +console.log(t('measure.modes.distance')); // 'Distance' + +// 订阅语言变更 +const unsubscribe = localeManager.subscribe((locale) => { + console.log('Language changed:', locale); +}); +``` + +### 翻译键结构 + +| 域 | 说明 | 示例 | +|---|------|------| +| `common` | 通用文本 | `common.title` | +| `toolbar` | 工具栏按钮 | `toolbar.home`, `toolbar.measure` | +| `dialog` | 对话框 | `dialog.testTitle` | +| `menu` | 菜单项 | `menu.info` | +| `tree` | 树形控件 | `tree.searchPlaceholder` | +| `measure` | 测量工具 | `measure.modes.distance`, `measure.units.m` | +| `sectionPlane` | 平面剖切 | `sectionPlane.dialogTitle` | +| `sectionAxis` | 轴向剖切 | `sectionAxis.dialogTitle` | +| `sectionBox` | 剖切盒 | `sectionBox.dialogTitle` | +| `walkControl` | 漫游控制 | `walkControl.speed` | +| `map` | 地图 | `map.dialogTitle` | + +### 扩展新语言 + +1. 创建翻译文件 `src/locales/ja-JP.ts` +2. 更新类型 `src/locales/types.ts` +3. 注册到 LocaleManager + +```typescript +// src/locales/ja-JP.ts +export const jaJP: TranslationDictionary = { + common: { title: 'BimEngine' }, + toolbar: { home: 'ホーム', measure: '測定' }, + // ... +}; +``` + +--- + +## ThemeManager(主题服务) + +### 概述 + +管理应用主题、颜色方案,支持实时订阅。 + +### API + +```typescript +class ThemeManager { + getTheme(): ThemeConfig; + setTheme(themeName: 'dark' | 'light'): void; + setCustomTheme(theme: ThemeConfig): void; + subscribe(listener: (theme: ThemeConfig) => void): () => void; +} + +// 单例导出 +export const themeManager: ThemeManager; +``` + +### 使用示例 + +```typescript +import { themeManager } from 'iflow-engine'; + +// 获取当前主题 +const theme = themeManager.getTheme(); +console.log(theme.primary); // '#2563eb' + +// 切换预设主题 +themeManager.setTheme('dark'); + +// 自定义主题 +themeManager.setCustomTheme({ + name: 'custom', + primary: '#ff6b6b', + // ... +}); + +// 订阅主题变更 +const unsubscribe = themeManager.subscribe((theme) => { + console.log('Theme changed:', theme.name); +}); +``` + +### 预设主题 + +#### 亮色主题 (`lightTheme`) + +| 属性 | 值 | 说明 | +|------|-----|------| +| `primary` | `#2563eb` | 主色 | +| `bgBase` | `#f8fafc` | 页面背景 | +| `bgElevated` | `#ffffff` | 卡片背景 | +| `textPrimary` | `#0f172a` | 主文本 | +| `textSecondary` | `#475569` | 次要文本 | + +#### 暗色主题 (`darkTheme`) + +| 属性 | 值 | 说明 | +|------|-----|------| +| `primary` | `#3b82f6` | 主色 | +| `bgBase` | `#152232` | 页面背景 | +| `bgElevated` | `#1f2d3e` | 卡片背景 | +| `textPrimary` | `#ffffff` | 主文本 | +| `textSecondary` | `#94a3b8` | 次要文本 | + +### ThemeConfig 结构 + +```typescript +interface ThemeConfig { + name: string; + + // 品牌色 + primary: string; + primaryHover: string; + primaryActive: string; + primarySubtle: string; + + // 状态色 + success: string; + warning: string; + danger: string; + info: string; + + // 背景色 + bgBase: string; + bgElevated: string; + bgOverlay: string; + bgInset: string; + bgGlass: string; + bgGlassBlur: string; + + // 文字色 + textPrimary: string; + textSecondary: string; + textTertiary: string; + textDisabled: string; + textInverse: string; + textLink: string; + + // 图标色 + iconDefault: string; + iconHover: string; + iconActive: string; + iconDisabled: string; + + // 边框色 + borderDefault: string; + borderSubtle: string; + borderStrong: string; + divider: string; + + // 组件状态 + componentBg: string; + componentBgHover: string; + componentBgActive: string; + componentBgSelected: string; + + // 焦点 + focusRing: string; + selectionBg: string; + + // 阴影 + shadowSm: string; + shadowMd: string; + shadowLg: string; + shadowGlow: string; + + // 浮动层 + floatingBg: string; + floatingBorder: string; + floatingBtnBg: string; + floatingBtnBgHover: string; + floatingIconColor: string; + + // 面板 + panelBg: string; + panelBorder: string; + panelHeaderBg: string; + panelRadius: string; + + // 选项卡 + tabBg: string; + tabItemBg: string; + tabItemBgActive: string; + tabItemTextActive: string; + + // 组件覆盖(可选) + overrides?: { + dialog?: { headerBg?: string }; + toolbar?: { bg?: string; buttonBg?: string }; + input?: { bg?: string; placeholder?: string }; + }; +} +``` + +### 创建自定义主题 + +```typescript +import { createThemeFromPartial, lightTheme } from 'iflow-engine'; + +// 基于预设创建(推荐) +const customTheme = createThemeFromPartial(lightTheme, { + name: 'coral', + primary: '#ff6b6b', + primaryHover: '#ff5252', + primaryActive: '#ff4757', +}); + +themeManager.setCustomTheme(customTheme); +``` + +### CSS 变量映射 + +主题颜色自动映射到 CSS 变量: + +```css +.my-component { + background-color: var(--bim-bg-elevated); + color: var(--bim-text-primary); + border: 1px solid var(--bim-border-default); +} + +.my-button { + background-color: var(--bim-primary); + color: var(--bim-text-inverse); +} + +.my-button:hover { + background-color: var(--bim-primary-hover); +} +``` + +常用 CSS 变量: + +| 变量 | 说明 | +|------|------| +| `--bim-primary` | 主色 | +| `--bim-bg-base` | 页面背景 | +| `--bim-bg-elevated` | 卡片背景 | +| `--bim-text-primary` | 主文本 | +| `--bim-border-default` | 边框 | +| `--bim-shadow-sm` | 小阴影 | + +--- + +## React 集成 + +```typescript +import { useEffect, useState } from 'react'; +import { localeManager, themeManager } from 'iflow-engine'; + +// 语言 Hook +export function useLocale() { + const [locale, setLocale] = useState(() => localeManager.getLocale()); + + useEffect(() => { + return localeManager.subscribe(setLocale); + }, []); + + return { locale, setLocale: localeManager.setLocale.bind(localeManager) }; +} + +// 主题 Hook +export function useTheme() { + const [theme, setTheme] = useState(() => themeManager.getTheme()); + + useEffect(() => { + return themeManager.subscribe(setTheme); + }, []); + + return { theme, setTheme: themeManager.setTheme.bind(themeManager) }; +} +``` + +--- + +## 架构设计 + +### 单例模式 + +两个服务都采用单例模式: + +```typescript +export const localeManager = new LocaleManager(); +export const themeManager = new ThemeManager(); +``` + +### 观察者模式 + +支持订阅状态变更: + +```typescript +// 订阅 +const unsubscribe = themeManager.subscribe((theme) => { + // 更新 UI +}); + +// 取消订阅 +unsubscribe(); +``` + +### 与 BimEngine 集成 + +```typescript +const engine = new BimEngine('container', { + locale: 'zh-CN', + theme: 'dark' +}); + +// 动态切换 +engine.setLocale('en-US'); +engine.setTheme('light'); +engine.setCustomTheme(customTheme); +``` + +--- + +## 依赖关系 + +``` +BimEngine + ↓ +LocaleManager ←→ locales/*.ts + ↓ +ThemeManager ←→ themes/*.ts +``` + +Services 模块无外部依赖,完全自包含。 + +--- + +**文档生成时间**: 2026-01-23 diff --git a/package-lock.json b/package-lock.json index 0b953ad..32941fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { - "name": "@fishdingding/bim-engine-sdk", - "version": "1.0.3", + "name": "iflow-engine", + "version": "1.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@fishdingding/bim-engine-sdk", - "version": "1.0.3", + "name": "iflow-engine", + "version": "1.0.5", "license": "MIT", "dependencies": { - "iflow-engine-base": "^1.0.1", + "iflow-engine-base": "^1.0.5", "three": "^0.182.0" }, "devDependencies": { @@ -1781,9 +1781,9 @@ } }, "node_modules/iflow-engine-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/iflow-engine-base/-/iflow-engine-base-1.0.1.tgz", - "integrity": "sha512-jrFn1bvisBA6jCn0+9gx9ZAkd1UHUoXo6bVkMsaM5tXIdABog/XYkJNADhdSrWzdB0u58M5ySZq3nqIpGq9LLQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/iflow-engine-base/-/iflow-engine-base-1.0.5.tgz", + "integrity": "sha512-UvlNg7Wha4EGJS11sB8+D1+7L15ylCZFQEkXPpU4Swt8c/fyY8YuFpR0/mAqgpKKs5HNepK+833G3wDUFHXV5g==", "license": "ISC", "dependencies": { "@types/three": "^0.181.0", diff --git a/package.json b/package.json index 3663f4a..489d9d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iflow-engine", - "version": "1.0.0", + "version": "1.0.5", "description": "iFlow Engine SDK for Vue2, Vue3, React and HTML", "main": "./dist/iflow-engine.umd.js", "module": "./dist/iflow-engine.es.js", @@ -59,7 +59,7 @@ "vite-plugin-dts": "^4.5.4" }, "dependencies": { - "iflow-engine-base": "^1.0.1", + "iflow-engine-base": "^1.0.5", "three": "^0.182.0" } } diff --git a/src/components/engine/index.ts b/src/components/engine/index.ts index 128b3e9..829065b 100644 --- a/src/components/engine/index.ts +++ b/src/components/engine/index.ts @@ -59,7 +59,7 @@ export class Engine implements IBimComponent { // 保存配置选项(设置默认值) this.options = { backgroundColor: 'linear-gradient(to bottom, rgb(214, 224, 235), rgb(246, 250, 255))', // 固定背景渐变色 - version: options.version ?? 'v1', // 默认使用 v1 版本 + version: options.version ?? 'v2', // 默认使用 v2 版本 showStats: options.showStats ?? false, // 默认不显示统计 showViewCube: options.showViewCube ?? true, // 默认显示视图立方体 }; @@ -179,6 +179,28 @@ export class Engine implements IBimComponent { return this.engine; } + /** + * 暂停渲染 + */ + public pauseRendering(): void { + if (!this._isInitialized || !this.engine) { + console.warn('[Engine] Engine not initialized.'); + return; + } + this.engine.pauseRendering(); + } + + /** + * 恢复渲染 + */ + public resumeRendering(): void { + if (!this._isInitialized || !this.engine) { + console.warn('[Engine] Engine not initialized.'); + return; + } + this.engine.resumeRendering(); + } + // ==================== 测量功能方法 ==================== /** diff --git a/src/managers/engine-manager.ts b/src/managers/engine-manager.ts index fc24be3..29b3003 100644 --- a/src/managers/engine-manager.ts +++ b/src/managers/engine-manager.ts @@ -105,6 +105,24 @@ export class EngineManager extends BaseManager { this.engineInstance.CameraGoHome(); } + /** 暂停渲染 */ + public pauseRendering(): void { + if (!this.engineInstance) { + console.warn('[EngineManager] 3D Engine not initialized.'); + return; + } + this.engineInstance.pauseRendering(); + } + + /** 恢复渲染 */ + public resumeRendering(): void { + if (!this.engineInstance) { + console.warn('[EngineManager] 3D Engine not initialized.'); + return; + } + this.engineInstance.resumeRendering(); + } + /** * 激活测量模式 * @param mode 测量模式