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
This commit is contained in:
@@ -55,6 +55,11 @@
|
|||||||
<div class="btn-container">
|
<div class="btn-container">
|
||||||
<button class="primary" @click="initEngine">初始化引擎</button>
|
<button class="primary" @click="initEngine">初始化引擎</button>
|
||||||
<button class="primary" @click="loadModel">加载模型</button>
|
<button class="primary" @click="loadModel">加载模型</button>
|
||||||
|
<button @click="switchModel">切换模型</button>
|
||||||
|
</div>
|
||||||
|
<div class="btn-container" style="margin-top: 8px;">
|
||||||
|
<button @click="pauseRendering">暂停渲染</button>
|
||||||
|
<button @click="resumeRendering">恢复渲染</button>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 10px; font-size: 0.85rem; color: #666;">
|
<div style="margin-top: 10px; font-size: 0.85rem; color: #666;">
|
||||||
<div>状态: <span :style="{ color: engineStatusColor }">{{ engineStatus }}</span></div>
|
<div>状态: <span :style="{ color: engineStatusColor }">{{ engineStatus }}</span></div>
|
||||||
@@ -290,7 +295,7 @@ const initEngine = () => {
|
|||||||
// 初始化引擎,使用默认配置
|
// 初始化引擎,使用默认配置
|
||||||
const success = engine.value.engine.initialize({
|
const success = engine.value.engine.initialize({
|
||||||
backgroundColor: 0x333333, // 深色背景
|
backgroundColor: 0x333333, // 深色背景
|
||||||
version: 'v1', // WebGL 版本
|
version: 'v2', // WebGL 版本
|
||||||
showStats: true, // 显示性能统计
|
showStats: true, // 显示性能统计
|
||||||
showViewCube: true // 显示视图立方体
|
showViewCube: true // 显示视图立方体
|
||||||
});
|
});
|
||||||
@@ -324,7 +329,7 @@ const loadModel = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 加载模型文件(从 model 目录)
|
// 加载模型文件(从 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, {
|
engine.value.engine.loadModel(modelUrl, {
|
||||||
position: [0, 0, 0], // 初始位置
|
position: [0, 0, 0], // 初始位置
|
||||||
@@ -337,6 +342,53 @@ const loadModel = () => {
|
|||||||
console.error('❌ 模型加载错误:', error);
|
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('✅ 渲染已恢复');
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -173,6 +173,11 @@
|
|||||||
<div class="btn-container">
|
<div class="btn-container">
|
||||||
<button class="primary" onclick="initEngine3D()">初始化引擎</button>
|
<button class="primary" onclick="initEngine3D()">初始化引擎</button>
|
||||||
<button class="primary" onclick="loadModel()">加载模型</button>
|
<button class="primary" onclick="loadModel()">加载模型</button>
|
||||||
|
<button onclick="switchModel()">切换模型</button>
|
||||||
|
</div>
|
||||||
|
<div class="btn-container" style="margin-top: 8px;">
|
||||||
|
<button onclick="pauseRendering()">暂停渲染</button>
|
||||||
|
<button onclick="resumeRendering()">恢复渲染</button>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 10px; font-size: 0.85rem; color: #666;">
|
<div style="margin-top: 10px; font-size: 0.85rem; color: #666;">
|
||||||
<div>状态: <span id="engine-status">未初始化</span></div>
|
<div>状态: <span id="engine-status">未初始化</span></div>
|
||||||
@@ -345,7 +350,7 @@
|
|||||||
// 初始化引擎,使用默认配置
|
// 初始化引擎,使用默认配置
|
||||||
const success = engine.engine.initialize({
|
const success = engine.engine.initialize({
|
||||||
backgroundColor: 0x333333, // 深色背景
|
backgroundColor: 0x333333, // 深色背景
|
||||||
version: 'v1', // WebGL 版本
|
version: 'v2', // WebGL 版本
|
||||||
showStats: true, // 显示性能统计
|
showStats: true, // 显示性能统计
|
||||||
showViewCube: true // 显示视图立方体
|
showViewCube: true // 显示视图立方体
|
||||||
});
|
});
|
||||||
@@ -381,7 +386,7 @@
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 加载模型文件(从 model 目录)
|
// 加载模型文件(从 model 目录)
|
||||||
const modelUrl = './model/test2';
|
const modelUrl = 'https://lyz-1259524260.cos.ap-guangzhou.myqcloud.com/iflow/models/8634e556-a94e-4ba7-be3e-2ea1507cced5/';
|
||||||
|
|
||||||
engine.engine.loadModel(modelUrl, {
|
engine.engine.loadModel(modelUrl, {
|
||||||
position: [0, 0, 0], // 初始位置
|
position: [0, 0, 0], // 初始位置
|
||||||
@@ -395,6 +400,62 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 暂停渲染
|
||||||
|
*/
|
||||||
|
function pauseRendering() {
|
||||||
|
if (!engine || !engine.engine || !engine.engine.isInitialized()) {
|
||||||
|
alert('请先初始化 3D 引擎!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
engine.engine.pauseRendering();
|
||||||
|
console.log('✅ 渲染已暂停');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 恢复渲染
|
||||||
|
*/
|
||||||
|
function resumeRendering() {
|
||||||
|
if (!engine || !engine.engine || !engine.engine.isInitialized()) {
|
||||||
|
alert('请先初始化 3D 引擎!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
engine.engine.resumeRendering();
|
||||||
|
console.log('✅ 渲染已恢复');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换模型 - 输入新的模型 URL
|
||||||
|
*/
|
||||||
|
function switchModel() {
|
||||||
|
if (!engine || !engine.engine) {
|
||||||
|
alert('引擎未创建,请先等待页面加载完成');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!engine.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.engine.loadModel(newUrl.trim(), {
|
||||||
|
position: [0, 0, 0],
|
||||||
|
rotation: [0, 0, 0],
|
||||||
|
scale: [1, 1, 1]
|
||||||
|
});
|
||||||
|
console.log('✅ 切换模型请求已发送:', newUrl);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ 切换模型错误:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开属性面板
|
* 打开属性面板
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -127,7 +127,7 @@
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 加载模型文件(从 model 目录)- 使用与 index.html 相同的模型路径
|
// 加载模型文件(从 model 目录)- 使用与 index.html 相同的模型路径
|
||||||
const modelUrl = './model/test2';
|
const modelUrl = 'https://lyz-1259524260.cos.ap-guangzhou.myqcloud.com/iflow/models/8634e556-a94e-4ba7-be3e-2ea1507cced5/';
|
||||||
|
|
||||||
engine.engine.loadModel(modelUrl, {
|
engine.engine.loadModel(modelUrl, {
|
||||||
position: [0, 0, 0], // 初始位置
|
position: [0, 0, 0], // 初始位置
|
||||||
|
|||||||
502
docs/ARCHITECTURE.md
Normal file
502
docs/ARCHITECTURE.md
Normal file
@@ -0,0 +1,502 @@
|
|||||||
|
# iflow-engine SDK 架构文档
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
iflow-engine 是一个面向开发者的 BIM 3D 引擎 SDK,采用分层架构设计,提供模型查看、测量、剖切、漫游等功能。
|
||||||
|
|
||||||
|
## 架构图
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ BimEngine │
|
||||||
|
│ (主入口 / 门面模式) │
|
||||||
|
├─────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ ManagerRegistry │ │
|
||||||
|
│ │ (单例 / 全局注册表) │ │
|
||||||
|
│ │ ┌─────────────────────────────────────────────────┐ │ │
|
||||||
|
│ │ │ EventEmitter (事件总线) │ │ │
|
||||||
|
│ │ └─────────────────────────────────────────────────┘ │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Managers Layer │ │
|
||||||
|
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
|
||||||
|
│ │ │EngineManager │ │ToolbarManager│ │ DialogManager│ │ │
|
||||||
|
│ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │
|
||||||
|
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
|
||||||
|
│ │ │MeasureDialog │ │SectionDialog │ │WalkControl │ │ │
|
||||||
|
│ │ │Manager │ │Manager │ │Manager │ │ │
|
||||||
|
│ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │
|
||||||
|
│ │ ... (15 个管理器) │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Components Layer │ │
|
||||||
|
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
|
||||||
|
│ │ │ Engine │ │ Dialog │ │ Tree │ │ Menu │ │ButtonGr│ │ │
|
||||||
|
│ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ │
|
||||||
|
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
|
||||||
|
│ │ │Collapse│ │ Tab │ │Descript│ │Measure │ │Section │ │ │
|
||||||
|
│ │ │ │ │ │ │ │ │Panel │ │Panel │ │ │
|
||||||
|
│ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ │
|
||||||
|
│ │ ... (20+ 个组件) │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Services Layer │ │
|
||||||
|
│ │ ┌──────────────────┐ ┌──────────────────┐ │ │
|
||||||
|
│ │ │ LocaleManager │ │ ThemeManager │ │ │
|
||||||
|
│ │ │ (国际化服务) │ │ (主题服务) │ │ │
|
||||||
|
│ │ └──────────────────┘ └──────────────────┘ │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Core Layer │ │
|
||||||
|
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
|
||||||
|
│ │ │ EventEmitter │ │ BaseManager │ │BaseDialog │ │ │
|
||||||
|
│ │ │ │ │ │ │Manager │ │ │
|
||||||
|
│ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ External Dependencies │
|
||||||
|
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
||||||
|
│ │ iflow-engine-base │ │ Three.js │ │
|
||||||
|
│ │ (第三方 3D 引擎核心) │ │ (3D 渲染库) │ │
|
||||||
|
│ └──────────────────────┘ └──────────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 分层说明
|
||||||
|
|
||||||
|
### 1. BimEngine (入口层)
|
||||||
|
|
||||||
|
**职责**: 作为 SDK 的唯一入口,整合所有功能,提供简洁的公开 API。
|
||||||
|
|
||||||
|
**设计模式**: 门面模式 (Facade Pattern)
|
||||||
|
|
||||||
|
**核心 API**:
|
||||||
|
- 初始化引擎和容器
|
||||||
|
- 设置主题和语言
|
||||||
|
- 访问各个管理器
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const engine = new BimEngine('container', {
|
||||||
|
locale: 'zh-CN',
|
||||||
|
theme: 'dark'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 访问管理器
|
||||||
|
engine.engine.loadModel('model.gltf');
|
||||||
|
engine.toolbar.show();
|
||||||
|
engine.measure.show();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. ManagerRegistry (注册表层)
|
||||||
|
|
||||||
|
**职责**: 全局单例,集中管理所有 Manager 实例,提供跨 Manager 通信。
|
||||||
|
|
||||||
|
**设计模式**: 单例模式 (Singleton) + 服务定位器 (Service Locator)
|
||||||
|
|
||||||
|
**特点**:
|
||||||
|
- 避免 Manager 之间的循环依赖
|
||||||
|
- 提供类型安全的事件系统
|
||||||
|
- 支持动态访问任意 Manager
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const registry = ManagerRegistry.getInstance();
|
||||||
|
registry.toolbar?.show();
|
||||||
|
registry.emit('engine:model-loaded', { url: 'model.gltf' });
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Managers Layer (管理器层)
|
||||||
|
|
||||||
|
**职责**: 处理业务逻辑,协调组件交互,管理组件生命周期。
|
||||||
|
|
||||||
|
**设计模式**: 模板方法模式 (Template Method)
|
||||||
|
|
||||||
|
**管理器分类**:
|
||||||
|
|
||||||
|
| 类别 | 管理器 | 职责 |
|
||||||
|
|------|--------|------|
|
||||||
|
| 核心 | EngineManager | 3D 引擎管理 |
|
||||||
|
| UI 容器 | ToolbarManager, DialogManager, ButtonGroupManager | 容器组件管理 |
|
||||||
|
| 交互 | RightKeyManager, PropertyPanelManager, ConstructTreeManagerBtn | 用户交互 |
|
||||||
|
| 工具 | MeasureDialogManager, SectionPlaneDialogManager, SectionAxisDialogManager, SectionBoxDialogManager | 3D 操作工具 |
|
||||||
|
| 漫游 | WalkControlManager, WalkPathDialogManager, WalkPlanViewDialogManager, MapDialogManager | 漫游功能 |
|
||||||
|
|
||||||
|
### 4. Components Layer (组件层)
|
||||||
|
|
||||||
|
**职责**: 纯 UI 渲染,不包含业务逻辑。
|
||||||
|
|
||||||
|
**设计模式**: 组合模式 (Composite Pattern)
|
||||||
|
|
||||||
|
**组件接口**:
|
||||||
|
```typescript
|
||||||
|
interface IBimComponent {
|
||||||
|
element: HTMLElement;
|
||||||
|
init(): void;
|
||||||
|
setTheme(theme: ThemeConfig): void;
|
||||||
|
setLocales?(): void;
|
||||||
|
destroy(): void;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**组件分类**:
|
||||||
|
|
||||||
|
| 类别 | 组件 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 核心 | Engine | 3D 视口容器 |
|
||||||
|
| 容器 | Dialog, Tree, Menu, ButtonGroup | 承载内容的容器组件 |
|
||||||
|
| 面板 | MeasurePanel, SectionPlanePanel, WalkControlPanel | 功能面板 |
|
||||||
|
| 展示 | Collapse, Tab, Description | 数据展示组件 |
|
||||||
|
|
||||||
|
### 5. Services Layer (服务层)
|
||||||
|
|
||||||
|
**职责**: 提供横切关注点的全局服务。
|
||||||
|
|
||||||
|
**设计模式**: 单例模式 + 观察者模式
|
||||||
|
|
||||||
|
| 服务 | 职责 |
|
||||||
|
|------|------|
|
||||||
|
| LocaleManager | 国际化,多语言支持 |
|
||||||
|
| ThemeManager | 主题管理,明暗切换 |
|
||||||
|
|
||||||
|
### 6. Core Layer (核心层)
|
||||||
|
|
||||||
|
**职责**: 提供基础设施和抽象。
|
||||||
|
|
||||||
|
| 类 | 职责 |
|
||||||
|
|-----|------|
|
||||||
|
| EventEmitter | 事件发布/订阅 |
|
||||||
|
| BaseManager | Manager 基类,提供注册表访问和事件管理 |
|
||||||
|
| BaseDialogManager | 对话框 Manager 基类,封装对话框生命周期 |
|
||||||
|
|
||||||
|
## 设计模式详解
|
||||||
|
|
||||||
|
### 1. 单例模式 (Singleton)
|
||||||
|
|
||||||
|
**应用**: ManagerRegistry, LocaleManager, ThemeManager
|
||||||
|
|
||||||
|
**目的**: 确保全局唯一实例,提供全局访问点。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export class ManagerRegistry {
|
||||||
|
private static instance: ManagerRegistry | null = null;
|
||||||
|
|
||||||
|
public static getInstance(): ManagerRegistry {
|
||||||
|
if (!ManagerRegistry.instance) {
|
||||||
|
ManagerRegistry.instance = new ManagerRegistry();
|
||||||
|
}
|
||||||
|
return ManagerRegistry.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static reset(): void {
|
||||||
|
ManagerRegistry.instance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 观察者模式 (Observer)
|
||||||
|
|
||||||
|
**应用**: EventEmitter, 服务订阅
|
||||||
|
|
||||||
|
**目的**: 解耦事件发送者和接收者,支持多对多通信。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 订阅
|
||||||
|
const unsubscribe = registry.on('engine:model-loaded', (payload) => {
|
||||||
|
console.log('Model loaded:', payload.url);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 发布
|
||||||
|
registry.emit('engine:model-loaded', { url: 'model.gltf' });
|
||||||
|
|
||||||
|
// 取消订阅
|
||||||
|
unsubscribe();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 模板方法模式 (Template Method)
|
||||||
|
|
||||||
|
**应用**: BaseManager, BaseDialogManager
|
||||||
|
|
||||||
|
**目的**: 定义算法骨架,允许子类重写特定步骤。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export abstract class BaseDialogManager extends BaseManager {
|
||||||
|
// 模板方法
|
||||||
|
public show(): void {
|
||||||
|
this.destroyDialog();
|
||||||
|
const content = this.createContent(); // 抽象方法
|
||||||
|
this.createDialog(content);
|
||||||
|
this.onDialogCreated(); // 钩子方法
|
||||||
|
}
|
||||||
|
|
||||||
|
// 抽象方法 - 子类必须实现
|
||||||
|
protected abstract createContent(): HTMLElement;
|
||||||
|
|
||||||
|
// 钩子方法 - 子类可选重写
|
||||||
|
protected onDialogCreated(): void {}
|
||||||
|
protected onDialogClose(): void {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 工厂模式 (Factory)
|
||||||
|
|
||||||
|
**应用**: BimEngine 初始化
|
||||||
|
|
||||||
|
**目的**: 封装对象创建逻辑,统一创建流程。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
private init() {
|
||||||
|
this.engine = new EngineManager(this.wrapper);
|
||||||
|
this.dialog = new DialogManager(this.wrapper);
|
||||||
|
this.toolbar = new ToolbarManager(this.wrapper);
|
||||||
|
// ... 创建其他管理器
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 数据流
|
||||||
|
|
||||||
|
### 1. 用户交互流
|
||||||
|
|
||||||
|
```
|
||||||
|
用户操作 (点击按钮)
|
||||||
|
↓
|
||||||
|
Toolbar 组件捕获事件
|
||||||
|
↓
|
||||||
|
ToolbarManager 处理
|
||||||
|
↓
|
||||||
|
发送事件到 Registry
|
||||||
|
↓
|
||||||
|
目标 Manager 响应
|
||||||
|
↓
|
||||||
|
更新相关组件 UI
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 主题变更流
|
||||||
|
|
||||||
|
```
|
||||||
|
用户调用 setTheme('dark')
|
||||||
|
↓
|
||||||
|
ThemeManager.setTheme()
|
||||||
|
↓
|
||||||
|
更新内部状态
|
||||||
|
↓
|
||||||
|
通知所有订阅者
|
||||||
|
↓
|
||||||
|
各组件 setTheme() 被调用
|
||||||
|
↓
|
||||||
|
更新 CSS 变量和样式
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 国际化变更流
|
||||||
|
|
||||||
|
```
|
||||||
|
用户调用 setLocale('en-US')
|
||||||
|
↓
|
||||||
|
LocaleManager.setLocale()
|
||||||
|
↓
|
||||||
|
更新内部状态
|
||||||
|
↓
|
||||||
|
通知所有订阅者
|
||||||
|
↓
|
||||||
|
各组件 setLocales() 被调用
|
||||||
|
↓
|
||||||
|
重新渲染文本内容
|
||||||
|
```
|
||||||
|
|
||||||
|
## 模块依赖关系
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
BimEngine --> ManagerRegistry
|
||||||
|
BimEngine --> LocaleManager
|
||||||
|
BimEngine --> ThemeManager
|
||||||
|
|
||||||
|
ManagerRegistry --> EventEmitter
|
||||||
|
|
||||||
|
EngineManager --> BaseManager
|
||||||
|
ToolbarManager --> BaseManager
|
||||||
|
DialogManager --> BaseManager
|
||||||
|
|
||||||
|
MeasureDialogManager --> BaseDialogManager
|
||||||
|
SectionPlaneDialogManager --> BaseDialogManager
|
||||||
|
WalkControlManager --> BaseManager
|
||||||
|
|
||||||
|
BaseDialogManager --> BaseManager
|
||||||
|
BaseManager --> ManagerRegistry
|
||||||
|
|
||||||
|
Engine --> ThemeManager
|
||||||
|
Dialog --> ThemeManager
|
||||||
|
Tree --> ThemeManager
|
||||||
|
Tree --> LocaleManager
|
||||||
|
Menu --> ThemeManager
|
||||||
|
Menu --> LocaleManager
|
||||||
|
|
||||||
|
ThemeManager --> darkTheme
|
||||||
|
ThemeManager --> lightTheme
|
||||||
|
LocaleManager --> zhCN
|
||||||
|
LocaleManager --> enUS
|
||||||
|
```
|
||||||
|
|
||||||
|
## 扩展点
|
||||||
|
|
||||||
|
### 1. 添加新 Manager
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { BaseManager } from '../core/base-manager';
|
||||||
|
|
||||||
|
export class CustomManager extends BaseManager {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public initialize(): void {
|
||||||
|
this.subscribe('engine:model-loaded', this.onModelLoaded.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private onModelLoaded(payload: any): void {
|
||||||
|
// 处理逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
public destroy(): void {
|
||||||
|
super.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 添加新对话框 Manager
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { BaseDialogManager } from '../core/base-dialog-manager';
|
||||||
|
|
||||||
|
export class CustomDialogManager extends BaseDialogManager {
|
||||||
|
protected get dialogId(): string {
|
||||||
|
return 'custom-dialog';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected get dialogTitle(): string {
|
||||||
|
return 'custom.dialogTitle';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected createContent(): HTMLElement {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
// 创建内容
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 添加新组件
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import type { ThemeConfig } from '../themes/types';
|
||||||
|
|
||||||
|
export class CustomComponent {
|
||||||
|
public element: HTMLElement;
|
||||||
|
|
||||||
|
constructor(private options: CustomOptions) {
|
||||||
|
this.element = document.createElement('div');
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(): void {
|
||||||
|
// 初始化
|
||||||
|
}
|
||||||
|
|
||||||
|
public setTheme(theme: ThemeConfig): void {
|
||||||
|
// 应用主题
|
||||||
|
}
|
||||||
|
|
||||||
|
public destroy(): void {
|
||||||
|
this.element.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 添加新语言
|
||||||
|
|
||||||
|
1. 创建语言文件 `src/locales/ja-JP.ts`
|
||||||
|
2. 更新类型 `src/locales/types.ts`
|
||||||
|
3. 注册到 LocaleManager
|
||||||
|
|
||||||
|
### 5. 添加新主题
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { createThemeFromPartial, lightTheme } from 'iflow-engine';
|
||||||
|
|
||||||
|
const customTheme = createThemeFromPartial(lightTheme, {
|
||||||
|
name: 'custom',
|
||||||
|
primary: '#ff6b6b',
|
||||||
|
// 其他自定义属性
|
||||||
|
});
|
||||||
|
|
||||||
|
themeManager.setCustomTheme(customTheme);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 事件系统
|
||||||
|
|
||||||
|
### 事件类型
|
||||||
|
|
||||||
|
| 类别 | 事件 | 数据 |
|
||||||
|
|------|------|------|
|
||||||
|
| UI | `ui:open-dialog` | `{ id: string; data?: any }` |
|
||||||
|
| UI | `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` | `{}` |
|
||||||
|
|
||||||
|
### 事件使用
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 发送事件
|
||||||
|
registry.emit('engine:model-loaded', { url: 'model.gltf' });
|
||||||
|
|
||||||
|
// 订阅事件
|
||||||
|
const unsubscribe = registry.on('engine:model-loaded', (payload) => {
|
||||||
|
console.log('Model loaded:', payload.url);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 在 Manager 中使用
|
||||||
|
this.subscribe('engine:model-loaded', this.handleModelLoaded.bind(this));
|
||||||
|
this.emit('custom:action', { data: 'value' });
|
||||||
|
```
|
||||||
|
|
||||||
|
## 性能考虑
|
||||||
|
|
||||||
|
### 1. 懒加载
|
||||||
|
|
||||||
|
- 组件按需创建,不预先实例化
|
||||||
|
- 对话框在首次 show() 时才创建 DOM
|
||||||
|
|
||||||
|
### 2. 事件清理
|
||||||
|
|
||||||
|
- BaseManager 自动追踪订阅,destroy 时统一清理
|
||||||
|
- 避免内存泄漏
|
||||||
|
|
||||||
|
### 3. DOM 操作优化
|
||||||
|
|
||||||
|
- 使用 requestAnimationFrame 节流拖拽/缩放
|
||||||
|
- 批量 DOM 更新
|
||||||
|
|
||||||
|
### 4. 主题切换
|
||||||
|
|
||||||
|
- 使用 CSS 变量,避免重绘整个组件树
|
||||||
|
- 订阅机制确保只更新必要的组件
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**文档生成时间**: 2026-01-23
|
||||||
|
**文档版本**: 1.0.0
|
||||||
388
docs/GETTING_STARTED.md
Normal file
388
docs/GETTING_STARTED.md
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
# iflow-engine SDK 快速开始
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
### NPM
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install iflow-engine
|
||||||
|
```
|
||||||
|
|
||||||
|
### Yarn
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn add iflow-engine
|
||||||
|
```
|
||||||
|
|
||||||
|
### PNPM
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm add iflow-engine
|
||||||
|
```
|
||||||
|
|
||||||
|
## 基础使用
|
||||||
|
|
||||||
|
### 1. 创建 HTML 容器
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="bim-container" style="width: 100%; height: 100vh;"></div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 初始化引擎
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { BimEngine } from 'iflow-engine';
|
||||||
|
|
||||||
|
// 创建引擎实例
|
||||||
|
const engine = new BimEngine('bim-container', {
|
||||||
|
locale: 'zh-CN', // 语言:'zh-CN' | 'en-US'
|
||||||
|
theme: 'light' // 主题:'light' | 'dark'
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 加载模型
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 初始化 3D 引擎
|
||||||
|
engine.engine?.initialize();
|
||||||
|
|
||||||
|
// 加载模型
|
||||||
|
engine.engine?.loadModel('https://example.com/model.gltf', {
|
||||||
|
autoFit: true // 自动适配视角
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## 完整示例
|
||||||
|
|
||||||
|
### Vue 3
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div ref="containerRef" class="bim-container"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, onUnmounted } from 'vue';
|
||||||
|
import { BimEngine } from 'iflow-engine';
|
||||||
|
|
||||||
|
const containerRef = ref<HTMLElement | null>(null);
|
||||||
|
let engine: BimEngine | null = null;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (containerRef.value) {
|
||||||
|
engine = new BimEngine(containerRef.value, {
|
||||||
|
locale: 'zh-CN',
|
||||||
|
theme: 'light'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化 3D 引擎
|
||||||
|
engine.engine?.initialize();
|
||||||
|
|
||||||
|
// 加载模型
|
||||||
|
engine.engine?.loadModel('/models/building.gltf');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
engine?.destroy();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.bim-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
### React
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { useRef, useEffect } from 'react';
|
||||||
|
import { BimEngine } from 'iflow-engine';
|
||||||
|
|
||||||
|
export function BimViewer() {
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const engineRef = useRef<BimEngine | null>(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 <div ref={containerRef} style={{ width: '100%', height: '100vh' }} />;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 原生 HTML
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>iflow-engine Demo</title>
|
||||||
|
<style>
|
||||||
|
#bim-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="bim-container"></div>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
import { BimEngine } from './lib/iflow-engine.es.js';
|
||||||
|
|
||||||
|
const engine = new BimEngine('bim-container', {
|
||||||
|
locale: 'zh-CN',
|
||||||
|
theme: 'light'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化 3D 引擎
|
||||||
|
engine.engine?.initialize();
|
||||||
|
|
||||||
|
// 加载模型
|
||||||
|
engine.engine?.loadModel('./models/building.gltf');
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 主题切换
|
||||||
|
|
||||||
|
```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: '<svg>...</svg>',
|
||||||
|
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
|
||||||
104
docs/INDEX.md
Normal file
104
docs/INDEX.md
Normal file
@@ -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
|
||||||
122
docs/MODULES/_INDEX.md
Normal file
122
docs/MODULES/_INDEX.md
Normal file
@@ -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
|
||||||
605
docs/MODULES/components.md
Normal file
605
docs/MODULES/components.md
Normal file
@@ -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<string, boolean>;
|
||||||
|
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<void>;
|
||||||
|
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<MeasureConfig>, 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
|
||||||
386
docs/MODULES/core.md
Normal file
386
docs/MODULES/core.md
Normal file
@@ -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<K extends keyof EngineEvents>(event: K, payload: EngineEvents[K]): void;
|
||||||
|
on<K extends keyof EngineEvents>(event: K, listener: (payload: EngineEvents[K]) => void): () => void;
|
||||||
|
off<K extends keyof EngineEvents>(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<K extends keyof EngineEvents>(
|
||||||
|
event: K,
|
||||||
|
handler: (payload: EngineEvents[K]) => void
|
||||||
|
): void;
|
||||||
|
|
||||||
|
protected emit<K extends keyof EngineEvents>(
|
||||||
|
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
|
||||||
489
docs/MODULES/managers.md
Normal file
489
docs/MODULES/managers.md
Normal file
@@ -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: '<svg>...</svg>',
|
||||||
|
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<MeasureConfig>, 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<SectionBoxRange>): 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
|
||||||
402
docs/MODULES/services.md
Normal file
402
docs/MODULES/services.md
Normal file
@@ -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
|
||||||
16
package-lock.json
generated
16
package-lock.json
generated
@@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "@fishdingding/bim-engine-sdk",
|
"name": "iflow-engine",
|
||||||
"version": "1.0.3",
|
"version": "1.0.5",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@fishdingding/bim-engine-sdk",
|
"name": "iflow-engine",
|
||||||
"version": "1.0.3",
|
"version": "1.0.5",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"iflow-engine-base": "^1.0.1",
|
"iflow-engine-base": "^1.0.5",
|
||||||
"three": "^0.182.0"
|
"three": "^0.182.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -1781,9 +1781,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/iflow-engine-base": {
|
"node_modules/iflow-engine-base": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/iflow-engine-base/-/iflow-engine-base-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/iflow-engine-base/-/iflow-engine-base-1.0.5.tgz",
|
||||||
"integrity": "sha512-jrFn1bvisBA6jCn0+9gx9ZAkd1UHUoXo6bVkMsaM5tXIdABog/XYkJNADhdSrWzdB0u58M5ySZq3nqIpGq9LLQ==",
|
"integrity": "sha512-UvlNg7Wha4EGJS11sB8+D1+7L15ylCZFQEkXPpU4Swt8c/fyY8YuFpR0/mAqgpKKs5HNepK+833G3wDUFHXV5g==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/three": "^0.181.0",
|
"@types/three": "^0.181.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "iflow-engine",
|
"name": "iflow-engine",
|
||||||
"version": "1.0.0",
|
"version": "1.0.5",
|
||||||
"description": "iFlow Engine SDK for Vue2, Vue3, React and HTML",
|
"description": "iFlow Engine SDK for Vue2, Vue3, React and HTML",
|
||||||
"main": "./dist/iflow-engine.umd.js",
|
"main": "./dist/iflow-engine.umd.js",
|
||||||
"module": "./dist/iflow-engine.es.js",
|
"module": "./dist/iflow-engine.es.js",
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
"vite-plugin-dts": "^4.5.4"
|
"vite-plugin-dts": "^4.5.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"iflow-engine-base": "^1.0.1",
|
"iflow-engine-base": "^1.0.5",
|
||||||
"three": "^0.182.0"
|
"three": "^0.182.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export class Engine implements IBimComponent {
|
|||||||
// 保存配置选项(设置默认值)
|
// 保存配置选项(设置默认值)
|
||||||
this.options = {
|
this.options = {
|
||||||
backgroundColor: 'linear-gradient(to bottom, rgb(214, 224, 235), rgb(246, 250, 255))', // 固定背景渐变色
|
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, // 默认不显示统计
|
showStats: options.showStats ?? false, // 默认不显示统计
|
||||||
showViewCube: options.showViewCube ?? true, // 默认显示视图立方体
|
showViewCube: options.showViewCube ?? true, // 默认显示视图立方体
|
||||||
};
|
};
|
||||||
@@ -179,6 +179,28 @@ export class Engine implements IBimComponent {
|
|||||||
return this.engine;
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== 测量功能方法 ====================
|
// ==================== 测量功能方法 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -105,6 +105,24 @@ export class EngineManager extends BaseManager {
|
|||||||
this.engineInstance.CameraGoHome();
|
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 测量模式
|
* @param mode 测量模式
|
||||||
|
|||||||
Reference in New Issue
Block a user