Files
bim_engine/docs/MODULES/核心模块.md
2026-03-16 16:13:36 +08:00

389 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 | 实例级 Manager 注册表 | `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 与事件总线,支持多实例隔离。
### API
```typescript
class ManagerRegistry {
// 创建实例
constructor();
// 容器元素
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;
componentDetail: ComponentDetailManager | null;
measure: MeasureDialogManager | null;
walkControl: WalkControlManager | null;
sectionPlane: SectionPlaneDialogManager | null;
sectionAxis: SectionAxisDialogManager | null;
sectionBox: SectionBoxDialogManager | null;
walkPath: WalkPathDialogManager | null;
walkPlanView: WalkPlanViewDialogManager | null;
engineInfo: EngineInfoDialogManager | null;
aiChat: AiChatManager | null;
setting: SettingDialogManager | 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;
reset(): void;
}
```
### 使用示例
```typescript
const registry = new ManagerRegistry();
// 由引擎入口在初始化时写入各个 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