387 lines
8.6 KiB
Markdown
387 lines
8.6 KiB
Markdown
# 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;
|
||
componentDetail: ComponentDetailManager | 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
|