feat(registry): 注册 ComponentDetailManager 到全局 Registry 和 BimEngine
This commit is contained in:
616
docs-old/components/3D引擎组件-Engine.md
Normal file
616
docs-old/components/3D引擎组件-Engine.md
Normal file
@@ -0,0 +1,616 @@
|
||||
# Engine 组件详细文档
|
||||
|
||||
> 本文档详细描述 Engine 组件的实现细节,包括 API、UI 结构、逻辑流程等,供 AI 根据文档重现组件。
|
||||
|
||||
---
|
||||
|
||||
## 1. 组件概述
|
||||
|
||||
### 1.1 基本信息
|
||||
- **组件名称**: `Engine`
|
||||
- **文件路径**: `src/components/engine/index.ts`
|
||||
- **类型定义**: `src/components/engine/types.ts`
|
||||
- **实现接口**: `IBimComponent`
|
||||
- **用途**: 封装第三方 3D 引擎 SDK,提供统一的 3D 引擎管理接口
|
||||
|
||||
### 1.2 在 SDK 中的位置
|
||||
- Engine 组件是独立的 3D 引擎组件
|
||||
- 必须通过 `EngineManager` 使用,不允许直接使用
|
||||
- `EngineManager` 位于 `src/managers/engine-manager.ts`
|
||||
- 采用延迟初始化模式,需要用户主动调用 `init()` 方法
|
||||
|
||||
### 1.3 第三方 SDK 依赖
|
||||
- 依赖 `iflow-engine-base` npm 包中的 `createEngine` 函数
|
||||
- 通过依赖注入方式使用,不直接导入
|
||||
|
||||
---
|
||||
|
||||
## 2. 组件类 API 文档
|
||||
|
||||
### 2.1 构造函数
|
||||
|
||||
```typescript
|
||||
constructor(options: EngineOptions)
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `options`: `EngineOptions` - 3D 引擎配置选项
|
||||
|
||||
**默认配置**:
|
||||
```typescript
|
||||
{
|
||||
backgroundColor: 0x1a1a1a, // 默认深色背景
|
||||
version: 'v1', // 默认使用 v1 版本
|
||||
showStats: false, // 默认不显示统计
|
||||
showViewCube: true // 默认显示视图立方体
|
||||
}
|
||||
```
|
||||
|
||||
**行为**:
|
||||
- 解析容器元素
|
||||
- 如果容器没有 id,生成一个唯一的 id
|
||||
- 保存配置选项(设置默认值)
|
||||
|
||||
### 2.2 公共方法
|
||||
|
||||
#### `init(): void`
|
||||
初始化组件(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 检查是否已初始化或已销毁
|
||||
- 创建引擎配置对象
|
||||
- 调用 `createEngineSDK()` 创建引擎实例
|
||||
- 标记为已初始化
|
||||
- 订阅主题变化
|
||||
- 应用当前主题
|
||||
|
||||
**错误处理**:
|
||||
- 如果创建失败,抛出错误并标记为未初始化
|
||||
|
||||
#### `setTheme(theme: ThemeConfig): void`
|
||||
设置主题(实现 `IBimComponent` 接口)
|
||||
|
||||
**参数**:
|
||||
- `theme`: `ThemeConfig` - 全局主题配置
|
||||
|
||||
**功能**:
|
||||
- 根据主题名称选择背景色:
|
||||
- `dark`: 使用深色背景 `0x1a1a1a`
|
||||
- `light`: 使用浅色背景 `0xf5f5f5`
|
||||
- `custom`: 使用配置中的 `backgroundColor` 或默认值
|
||||
- 尝试更新引擎背景色:
|
||||
- 如果引擎有 `setBackgroundColor()` 方法,调用它
|
||||
- 否则,如果引擎有 `scene.background`,设置其颜色
|
||||
|
||||
#### `setLocales(): void`
|
||||
设置语言(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 3D 引擎组件暂时不需要本地化
|
||||
- 方法为空实现
|
||||
|
||||
#### `isInitialized(): boolean`
|
||||
检查是否已初始化
|
||||
|
||||
**返回**: `boolean` - 是否已初始化
|
||||
|
||||
#### `loadModel(url: string, options?: ModelLoadOptions): void`
|
||||
加载 3D 模型
|
||||
|
||||
**参数**:
|
||||
- `url`: `string` - 模型文件 URL(必需)
|
||||
- `options`: `ModelLoadOptions` (可选) - 加载选项
|
||||
|
||||
**功能**:
|
||||
- 检查引擎是否已初始化
|
||||
- 检查 URL 是否提供
|
||||
- 调用引擎的 `loader.loadModel()` 方法加载模型
|
||||
|
||||
**加载选项**:
|
||||
- `position`: `[number, number, number]` - 模型位置 [x, y, z]
|
||||
- `rotation`: `[number, number, number]` - 模型旋转(弧度)[x, y, z]
|
||||
- `scale`: `[number, number, number]` - 模型缩放 [x, y, z]
|
||||
- `id`: `string` - 模型 ID(可选)
|
||||
|
||||
#### `getEngine(): any`
|
||||
获取原始 3D 引擎实例
|
||||
|
||||
**返回**: 第三方 3D 引擎实例或 `null`
|
||||
|
||||
**功能**:
|
||||
- 返回底层 3D 引擎实例
|
||||
- 用于直接调用第三方引擎的其他 API
|
||||
|
||||
#### `destroy(): void`
|
||||
销毁组件(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 取消主题订阅
|
||||
- 清空容器内容
|
||||
- 标记为已销毁和未初始化
|
||||
|
||||
**注意**: 不销毁引擎实例本身(由第三方 SDK 管理)
|
||||
|
||||
---
|
||||
|
||||
## 3. 分化组件说明
|
||||
|
||||
**Engine 组件没有分化组件**。
|
||||
|
||||
---
|
||||
|
||||
## 4. Manager API 文档
|
||||
|
||||
### 4.1 EngineManager 类
|
||||
|
||||
**文件路径**: `src/managers/engine-manager.ts`
|
||||
|
||||
**继承关系**: `EngineManager extends BimComponent`
|
||||
|
||||
### 4.2 构造函数
|
||||
|
||||
```typescript
|
||||
constructor(engine: BimEngine, container: HTMLElement)
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `engine`: `BimEngine` - 引擎实例
|
||||
- `container`: `HTMLElement` - 3D 引擎挂载的目标容器
|
||||
|
||||
**行为**:
|
||||
- 保存容器引用
|
||||
- **不自动初始化引擎**(延迟初始化模式)
|
||||
|
||||
### 4.3 公共方法
|
||||
|
||||
#### `initialize(options?: Omit<EngineOptions, 'container'>): boolean`
|
||||
初始化 3D 引擎
|
||||
|
||||
**参数**:
|
||||
- `options`: `Omit<EngineOptions, 'container'>` (可选) - 引擎配置选项
|
||||
|
||||
**返回**: `boolean` - 是否初始化成功
|
||||
|
||||
**功能**:
|
||||
- 如果已经初始化,先销毁旧的实例
|
||||
- 创建 `Engine` 组件实例
|
||||
- 调用组件的 `init()` 方法初始化引擎
|
||||
- 返回初始化结果
|
||||
|
||||
**错误处理**:
|
||||
- 如果初始化失败,返回 `false` 并输出错误信息
|
||||
|
||||
#### `isInitialized(): boolean`
|
||||
检查 3D 引擎是否已初始化
|
||||
|
||||
**返回**: `boolean` - 是否已初始化
|
||||
|
||||
#### `loadModel(url: string, options?: ModelLoadOptions): void`
|
||||
加载 3D 模型
|
||||
|
||||
**参数**:
|
||||
- `url`: `string` - 模型文件 URL
|
||||
- `options`: `ModelLoadOptions` (可选) - 加载选项
|
||||
|
||||
**功能**:
|
||||
- 检查引擎是否已初始化
|
||||
- 如果未初始化,输出错误信息
|
||||
- 调用引擎组件的 `loadModel()` 方法
|
||||
|
||||
#### `getEngine(): any`
|
||||
获取原始 3D 引擎实例
|
||||
|
||||
**返回**: 第三方 3D 引擎实例或 `null`
|
||||
|
||||
**功能**:
|
||||
- 用于直接调用第三方引擎的其他 API
|
||||
- 如果引擎未初始化,返回 `null` 并输出警告
|
||||
|
||||
#### `destroy(): void`
|
||||
销毁 3D 引擎实例
|
||||
|
||||
**功能**:
|
||||
- 调用引擎组件的 `destroy()` 方法
|
||||
- 清空引擎实例引用
|
||||
|
||||
---
|
||||
|
||||
## 5. UI 详细描述
|
||||
|
||||
### 5.1 DOM 结构
|
||||
|
||||
**Engine 组件不直接创建 UI 元素**,而是:
|
||||
|
||||
1. **使用容器元素**:
|
||||
- 容器元素由外部提供(通过 `EngineOptions.container`)
|
||||
- 如果容器没有 id,组件会生成一个唯一的 id
|
||||
|
||||
2. **第三方 SDK 创建 UI**:
|
||||
- 第三方 SDK 的 `createEngine()` 函数会在容器内创建 3D 场景
|
||||
- 可能包括:
|
||||
- Canvas 元素(WebGL 渲染)
|
||||
- 统计面板(如果 `showStats: true`)
|
||||
- 视图立方体(如果 `showViewCube: true`)
|
||||
|
||||
### 5.2 容器 ID 生成
|
||||
|
||||
**算法**:
|
||||
```typescript
|
||||
containerId = `engine-container-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
```
|
||||
|
||||
**格式**: `engine-container-[时间戳]-[随机字符串]`
|
||||
|
||||
**示例**: `engine-container-1704067200000-k3j9x2m1p`
|
||||
|
||||
### 5.3 第三方 SDK 配置
|
||||
|
||||
**传递给 `createEngine()` 的配置对象**:
|
||||
```typescript
|
||||
{
|
||||
containerId: string, // 容器 ID
|
||||
backgroundColor: number, // 背景色(十六进制数字)
|
||||
version: 'v1' | 'v2', // WebGL 版本
|
||||
showStats: boolean, // 是否显示统计
|
||||
showViewCube: boolean // 是否显示视图立方体
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 逻辑流程详细描述
|
||||
|
||||
### 6.1 初始化流程
|
||||
|
||||
1. **构造函数调用**:
|
||||
- 解析容器元素
|
||||
- 生成或使用容器 ID
|
||||
- 保存配置选项(设置默认值)
|
||||
|
||||
2. **init() 方法执行**(用户主动调用):
|
||||
- 检查是否已初始化,如果是则返回
|
||||
- 检查是否已销毁,如果是则报错
|
||||
- 创建引擎配置对象
|
||||
- 调用 `createEngineSDK()` 创建引擎实例
|
||||
- 检查引擎实例是否创建成功
|
||||
- 标记为已初始化
|
||||
- 订阅主题变化:`themeManager.subscribe()`
|
||||
- 应用当前主题
|
||||
|
||||
### 6.2 生命周期
|
||||
|
||||
#### 创建阶段
|
||||
- 构造函数 → 保存配置
|
||||
|
||||
#### 初始化阶段(延迟)
|
||||
- 用户调用 `init()` → 创建引擎实例 → 订阅主题
|
||||
|
||||
#### 运行阶段
|
||||
- 响应主题变更:`setTheme()` 被调用
|
||||
- 加载模型:`loadModel()` 被调用
|
||||
- 用户交互:3D 场景交互(由第三方 SDK 处理)
|
||||
|
||||
#### 销毁阶段
|
||||
- `destroy()` 被调用
|
||||
- 取消主题订阅
|
||||
- 清空容器
|
||||
- 更新状态
|
||||
|
||||
### 6.3 主题变更流程
|
||||
|
||||
1. 主题变更 → `themeManager` 通知订阅者
|
||||
2. `setTheme()` 方法被调用
|
||||
3. 根据主题名称选择背景色:
|
||||
- `dark` → `0x1a1a1a`
|
||||
- `light` → `0xf5f5f5`
|
||||
- `custom` → 使用配置值或默认值
|
||||
4. 尝试更新引擎背景色:
|
||||
- 方法 1: 调用 `engine.setBackgroundColor(backgroundColor)`
|
||||
- 方法 2: 设置 `engine.scene.background.setHex(backgroundColor)`
|
||||
|
||||
### 6.4 模型加载流程
|
||||
|
||||
1. 用户调用 `loadModel(url, options)`
|
||||
2. 检查引擎是否已初始化
|
||||
3. 检查 URL 是否提供
|
||||
4. 调用 `engine.loader.loadModel(url, options)`
|
||||
5. 第三方 SDK 处理模型加载
|
||||
|
||||
### 6.5 状态管理
|
||||
|
||||
#### 内部状态
|
||||
- `_isInitialized`: 是否已初始化
|
||||
- `_isDestroyed`: 是否已销毁
|
||||
- `engine`: 第三方 3D 引擎实例
|
||||
- `containerId`: 容器 ID
|
||||
- `options`: 引擎配置选项
|
||||
|
||||
#### 订阅管理
|
||||
- `unsubscribeTheme`: 主题订阅取消函数
|
||||
|
||||
### 6.6 与其他组件的交互
|
||||
|
||||
- **与 EngineManager**: 通过 Manager 创建和管理
|
||||
- **与 ThemeManager**: 订阅主题变更
|
||||
- **与第三方 SDK**: 通过 `createEngine()` 函数创建引擎实例
|
||||
|
||||
---
|
||||
|
||||
## 7. 国际化支持
|
||||
|
||||
### 7.1 使用的翻译键
|
||||
|
||||
**Engine 组件不使用翻译键**(3D 引擎不需要国际化)。
|
||||
|
||||
### 7.2 语言变更处理
|
||||
|
||||
- `setLocales()` 方法为空实现
|
||||
- 不订阅语言变更
|
||||
|
||||
---
|
||||
|
||||
## 8. 主题支持
|
||||
|
||||
### 8.1 使用的主题变量
|
||||
|
||||
- 根据主题名称选择背景色:
|
||||
- `dark` 主题 → `0x1a1a1a`(深色背景)
|
||||
- `light` 主题 → `0xf5f5f5`(浅色背景)
|
||||
- `custom` 主题 → 使用配置值或默认值
|
||||
|
||||
### 8.2 主题变更处理
|
||||
|
||||
- 组件订阅 `themeManager.subscribe()`
|
||||
- 主题变更时,`setTheme()` 方法被调用
|
||||
- 根据主题名称选择背景色
|
||||
- 尝试更新引擎背景色(通过引擎 API)
|
||||
|
||||
### 8.3 实现细节
|
||||
|
||||
```typescript
|
||||
public setTheme(theme: ThemeConfig): void {
|
||||
let backgroundColor: number;
|
||||
if (theme.name === 'dark') {
|
||||
backgroundColor = 0x1a1a1a;
|
||||
} else if (theme.name === 'light') {
|
||||
backgroundColor = 0xf5f5f5;
|
||||
} else {
|
||||
backgroundColor = this.options.backgroundColor ?? 0x1a1a1a;
|
||||
}
|
||||
|
||||
// 尝试更新引擎背景色
|
||||
if (this.engine && typeof this.engine.setBackgroundColor === 'function') {
|
||||
this.engine.setBackgroundColor(backgroundColor);
|
||||
} else if (this.engine && this.engine.scene) {
|
||||
if (this.engine.scene.background) {
|
||||
this.engine.scene.background.setHex(backgroundColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 使用示例
|
||||
|
||||
### 9.1 基本使用(通过 EngineManager)
|
||||
|
||||
```typescript
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
const engine = new BimEngine('container');
|
||||
|
||||
// 初始化 3D 引擎(延迟初始化)
|
||||
const success = engine.initEngine({
|
||||
backgroundColor: 0x333333,
|
||||
version: 'v1',
|
||||
showStats: true,
|
||||
showViewCube: true
|
||||
});
|
||||
|
||||
if (success) {
|
||||
console.log('3D 引擎初始化成功');
|
||||
}
|
||||
|
||||
// 加载模型
|
||||
engine.engine.loadModel('/model/building.glb', {
|
||||
position: [0, 0, 0],
|
||||
rotation: [0, 0, 0],
|
||||
scale: [1, 1, 1]
|
||||
});
|
||||
```
|
||||
|
||||
### 9.2 高级使用
|
||||
|
||||
```typescript
|
||||
// 检查引擎是否已初始化
|
||||
if (engine.engine.isInitialized()) {
|
||||
// 加载模型
|
||||
engine.engine.loadModel('/model/model.glb');
|
||||
}
|
||||
|
||||
// 获取原始引擎实例,调用第三方 API
|
||||
const rawEngine = engine.engine.getEngine();
|
||||
if (rawEngine) {
|
||||
// 调用第三方 SDK 的其他方法
|
||||
rawEngine.someOtherMethod();
|
||||
}
|
||||
```
|
||||
|
||||
### 9.3 主题切换
|
||||
|
||||
```typescript
|
||||
// 切换主题会自动更新 3D 场景背景色
|
||||
engine.setTheme('dark'); // 深色背景
|
||||
engine.setTheme('light'); // 浅色背景
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 实现细节(供 AI 重现)
|
||||
|
||||
### 10.1 关键算法
|
||||
|
||||
#### 容器 ID 生成算法
|
||||
```typescript
|
||||
function generateContainerId(): string {
|
||||
const timestamp = Date.now();
|
||||
const random = Math.random().toString(36).substr(2, 9);
|
||||
return `engine-container-${timestamp}-${random}`;
|
||||
}
|
||||
```
|
||||
|
||||
#### 主题背景色选择算法
|
||||
```typescript
|
||||
function selectBackgroundColor(theme: ThemeConfig, defaultColor: number): number {
|
||||
if (theme.name === 'dark') {
|
||||
return 0x1a1a1a; // 深色背景
|
||||
} else if (theme.name === 'light') {
|
||||
return 0xf5f5f5; // 浅色背景
|
||||
} else {
|
||||
return defaultColor; // 自定义主题,使用配置值
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 引擎背景色更新算法
|
||||
```typescript
|
||||
function updateEngineBackground(engine: any, color: number): void {
|
||||
// 方法 1: 如果引擎有 setBackgroundColor 方法
|
||||
if (engine && typeof engine.setBackgroundColor === 'function') {
|
||||
engine.setBackgroundColor(color);
|
||||
return;
|
||||
}
|
||||
|
||||
// 方法 2: 如果引擎有 scene.background
|
||||
if (engine && engine.scene && engine.scene.background) {
|
||||
engine.scene.background.setHex(color);
|
||||
return;
|
||||
}
|
||||
|
||||
// 方法 3: 无法更新(引擎可能不支持)
|
||||
}
|
||||
```
|
||||
|
||||
### 10.2 性能优化点
|
||||
|
||||
1. **延迟初始化**:
|
||||
- 引擎不自动初始化,由用户主动调用
|
||||
- 减少不必要的资源消耗
|
||||
|
||||
2. **状态检查**:
|
||||
- 初始化前检查状态,避免重复初始化
|
||||
- 销毁后禁止初始化,避免错误
|
||||
|
||||
3. **错误处理**:
|
||||
- 所有操作都有错误检查
|
||||
- 提供有意义的错误信息
|
||||
|
||||
### 10.3 注意事项和边界情况
|
||||
|
||||
1. **容器 ID 唯一性**:
|
||||
- 容器 ID 必须唯一
|
||||
- 如果容器已有 id,使用现有 id
|
||||
- 如果容器没有 id,生成唯一 id
|
||||
|
||||
2. **延迟初始化**:
|
||||
- 引擎不会自动初始化
|
||||
- 用户必须主动调用 `init()` 或 `initialize()`
|
||||
- 初始化前调用其他方法会报错
|
||||
|
||||
3. **引擎实例管理**:
|
||||
- 引擎实例由第三方 SDK 创建
|
||||
- 组件不负责销毁引擎实例本身
|
||||
- 只负责清理订阅和容器
|
||||
|
||||
4. **主题更新兼容性**:
|
||||
- 不同第三方 SDK 的 API 可能不同
|
||||
- 需要尝试多种方式更新背景色
|
||||
- 如果都不支持,静默失败
|
||||
|
||||
5. **模型加载**:
|
||||
- 模型 URL 必须是可访问的
|
||||
- 模型格式由第三方 SDK 支持
|
||||
- 加载选项由第三方 SDK 处理
|
||||
|
||||
6. **错误处理**:
|
||||
- 初始化失败时,标记为未初始化
|
||||
- 提供有意义的错误信息
|
||||
- 不抛出未捕获的异常
|
||||
|
||||
7. **第三方 SDK 依赖**:
|
||||
- 依赖 `iflow-engine-base` npm 包
|
||||
- 通过 npm 包导入
|
||||
- 需要确保依赖已安装
|
||||
|
||||
---
|
||||
|
||||
## 11. 类型定义
|
||||
|
||||
### 11.1 EngineOptions
|
||||
|
||||
```typescript
|
||||
interface EngineOptions {
|
||||
container: HTMLElement; // 容器元素(必需)
|
||||
backgroundColor?: number; // 背景颜色(可选,默认 0x1a1a1a)
|
||||
version?: 'v1' | 'v2'; // WebGL 版本(可选,默认 'v1')
|
||||
showStats?: boolean; // 是否显示性能统计(可选,默认 false)
|
||||
showViewCube?: boolean; // 是否显示视图立方体(可选,默认 true)
|
||||
}
|
||||
```
|
||||
|
||||
### 11.2 ModelLoadOptions
|
||||
|
||||
```typescript
|
||||
interface ModelLoadOptions {
|
||||
position?: [number, number, number]; // 模型位置 [x, y, z](可选)
|
||||
rotation?: [number, number, number]; // 模型旋转(弧度)[x, y, z](可选)
|
||||
scale?: [number, number, number]; // 模型缩放 [x, y, z](可选)
|
||||
id?: string; // 模型 ID(可选)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. 文件清单
|
||||
|
||||
### 12.1 相关文件
|
||||
|
||||
- `src/components/engine/index.ts` - 主组件类
|
||||
- `src/components/engine/types.ts` - 类型定义
|
||||
- `src/managers/engine-manager.ts` - 管理器类
|
||||
- `iflow-engine-base` - 第三方 SDK(npm 依赖)
|
||||
|
||||
### 12.2 依赖文件
|
||||
|
||||
- `src/types/component.ts` - IBimComponent 接口
|
||||
- `src/themes/types.ts` - ThemeConfig 类型
|
||||
- `src/services/theme.ts` - ThemeManager
|
||||
|
||||
---
|
||||
|
||||
## 13. 更新记录
|
||||
|
||||
| 日期 | 修改内容 | 修改人 |
|
||||
|------|---------|--------|
|
||||
| 2024-XX-XX | 初始创建 | AI Assistant |
|
||||
|
||||
---
|
||||
|
||||
**重要提醒**: 本文档必须与组件代码保持同步。任何组件修改都必须更新本文档!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
211
docs-old/components/右键菜单组件-RightKey.md
Normal file
211
docs-old/components/右键菜单组件-RightKey.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# RightKey 组件详细文档
|
||||
|
||||
> 本文档详细描述 RightKey 组件的实现细节,包括 API、UI 结构、逻辑流程等,供 AI 根据文档重现组件。
|
||||
|
||||
---
|
||||
|
||||
## 1. 组件概述
|
||||
|
||||
### 1.1 基本信息
|
||||
- **组件名称**: `BimRightKey`
|
||||
- **文件路径**: `src/components/right-key/index.ts`
|
||||
- **类型定义**: `src/components/right-key/types.ts`
|
||||
- **样式文件**: `src/components/right-key/index.css`
|
||||
- **实现接口**: `IBimComponent`
|
||||
- **用途**: 提供一个全屏感知的定位容器,用于显示右键菜单等浮层内容。
|
||||
- **特点**: 自动边界检测(防止溢出屏幕)、点击外部自动关闭、内容无关性(支持挂载任意内容)。
|
||||
|
||||
### 1.2 在 SDK 中的位置
|
||||
- RightKey 是右键菜单系统的容器部分。
|
||||
- 必须通过 `RightKeyManager` 使用,不允许直接使用。
|
||||
- `RightKeyManager` 位于 `src/managers/right-key-manager.ts`。
|
||||
|
||||
---
|
||||
|
||||
## 2. 组件类 API 文档
|
||||
|
||||
### 2.1 构造函数
|
||||
|
||||
```typescript
|
||||
constructor(options?: RightKeyOptions)
|
||||
```
|
||||
|
||||
**<EFBFBD><EFBFBD>数**:
|
||||
- `options`:
|
||||
- `zIndex`: number (默认 10000)
|
||||
- `className`: string
|
||||
|
||||
### 2.2 公共方法
|
||||
|
||||
#### `init(): void`
|
||||
初始化组件(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 创建 DOM 结构
|
||||
- 将容器挂载到 `document.body`(或其他指定容器,当前实现是 body)
|
||||
- 绑定全局 `mousedown` 事件用于检测“点击外部”
|
||||
|
||||
#### `mount(content: IRightKeyContent): void`
|
||||
挂载内容组件
|
||||
|
||||
**参数**:
|
||||
- `content`: 实现了 `IRightKeyContent` 接口的对象(如 `BimMenu`)
|
||||
|
||||
**功能**:
|
||||
- 清空当前容器内容
|
||||
- 调用 `content.getElement()` 并将结果 append 到容器中
|
||||
- 保存 content 引用
|
||||
|
||||
#### `unmountContent(): void`
|
||||
卸载内容
|
||||
|
||||
**功能**:
|
||||
- 调用 `content.destroy()`
|
||||
- 清空容器 DOM
|
||||
|
||||
#### `show(x: number, y: number): void`
|
||||
显示容器
|
||||
|
||||
**参数**:
|
||||
- `x`, `y`: 屏幕坐标(通常是鼠标事件的 `clientX/Y`)
|
||||
|
||||
**功能**:
|
||||
- 计算容器尺寸
|
||||
- 执行边界检测算法,调整坐标防止溢出
|
||||
- 设置 `top/left` 样式
|
||||
- 设置 `display: block`
|
||||
|
||||
#### `hide(): void`
|
||||
隐藏容器
|
||||
|
||||
**功能**:
|
||||
- 设置 `display: none`
|
||||
- 触发 `onClose` 回调(如果设置了)
|
||||
|
||||
#### `setOnClose(callback: () => void): void`
|
||||
设置关闭回调
|
||||
|
||||
**功能**:
|
||||
- 注册一个回调函数,在容器被隐藏(如点击外部)时触发。通常用于通知 Manager 清理状态。
|
||||
|
||||
#### `destroy(): void`
|
||||
销毁组件
|
||||
|
||||
**功能**:
|
||||
- 解绑全局事件
|
||||
- 卸载内容
|
||||
- 移除自身 DOM
|
||||
|
||||
---
|
||||
|
||||
## 3. Manager API 文档
|
||||
|
||||
### 3.1 RightKeyManager 类
|
||||
|
||||
**文件路径**: `src/managers/right-key-manager.ts`
|
||||
|
||||
#### `registerHandler(handler: (e) => MenuItemConfig[] | null): void`
|
||||
注册上下文菜单处理器
|
||||
|
||||
**参数**:
|
||||
- `handler`: 函数,接收 MouseEvent,返回菜单配置数组或 null。
|
||||
|
||||
**功能**:
|
||||
- 将 handler 加入内部列表。
|
||||
- 右键点击时,遍历列表。只要有一个 handler 返回了非空数组,就显示这些菜单项。
|
||||
|
||||
#### `showMenu(x, y, items, groupOrder?): void`
|
||||
手动显示菜单
|
||||
|
||||
**功能**:
|
||||
- 创建 `BimMenu` 实例
|
||||
- 调用 `rightKeyPanel.mount(menu)`
|
||||
- 调用 `rightKeyPanel.show(x, y)`
|
||||
|
||||
---
|
||||
|
||||
## 4. UI 详细描述
|
||||
|
||||
### 4.1 DOM 结构
|
||||
|
||||
```html
|
||||
<!-- 容器 -->
|
||||
<div class="bim-right-key" style="z-index: 9000; display: none; left: ...; top: ...">
|
||||
<!-- 挂载的内容 (例如 BimMenu 的 ul) -->
|
||||
<ul class="bim-menu">...</ul>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 4.2 CSS 类名
|
||||
|
||||
#### `.bim-right-key`
|
||||
- `position: fixed`: 固定定位,相对于视口。
|
||||
- `display: none`: 默认隐藏。
|
||||
- `box-shadow`: 即使内容组件没有阴影,容器也可以提供(当前<E5BD93><E5898D>要由内容组件自己提供)。
|
||||
|
||||
---
|
||||
|
||||
## 5. 逻辑流程详细描述
|
||||
|
||||
### 5.1 全局点击检测 (`handleGlobalClick`)
|
||||
|
||||
组件初始化时,会在 `document` 上绑定 `mousedown` (捕获阶段或冒泡阶段,通常冒泡即可)。
|
||||
|
||||
1. 当 `mousedown` 发生时,检查 `event.target`。
|
||||
2. 如果 `target` 位于 `.bim-right-key` 容器内部,**不做处理**(认为是有效的内部交互)。
|
||||
3. 如果 `target` 在容器外部,调用 `hide()` 关闭菜单。
|
||||
|
||||
**注意**: 子菜单(SubMenu)通常挂载在 `body` 上,物理上位于 `.bim-right-key` 外部。为了防止点击子菜单时误关主菜单,子菜单容器必须阻止 `mousedown` 冒泡(见 Menu 组件文档)。
|
||||
|
||||
### 5.2 边界检测算法
|
||||
|
||||
在 `show(x, y)` 时执行:
|
||||
|
||||
1. 获取容器尺寸: `rect = element.getBoundingClientRect()`
|
||||
2. 获取视口尺寸: `winW = window.innerWidth`, `winH = window.innerHeight`
|
||||
3. **水平调整**:
|
||||
- 如果 `x + rect.width > winW`: `x = x - rect.width`(向左展开)
|
||||
- 否则: `x` 保持不变(向右展开)
|
||||
4. **垂直调整**:
|
||||
- 如果 `y + rect.height > winH`: `y = y - rect.height`(向上展开)
|
||||
- 否则: `y` 保持不变(向下展开)
|
||||
5. 应用调整后的 `x, y` 到 `style.left` 和 `style.top`。
|
||||
|
||||
---
|
||||
|
||||
## 6. 类型定义
|
||||
|
||||
### 6.1 IRightKeyContent
|
||||
|
||||
```typescript
|
||||
interface IRightKeyContent {
|
||||
getElement(): HTMLElement;
|
||||
destroy(): void;
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 RightKeyOptions
|
||||
|
||||
```typescript
|
||||
interface RightKeyOptions {
|
||||
className?: string;
|
||||
zIndex?: number;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 文件清单
|
||||
|
||||
- `src/components/right-key/index.ts`: 组件核心逻辑
|
||||
- `src/components/right-key/index.css`: 样式
|
||||
- `src/components/right-key/types.ts`: 类型定义
|
||||
- `src/managers/right-key-manager.ts`: 管理器
|
||||
|
||||
---
|
||||
|
||||
## 8. 更新记录
|
||||
|
||||
| 日期 | 修改内容 | 修改人 |
|
||||
|------|---------|--------|
|
||||
| 2024-XX-XX | 更新 Manager API 以支持 MenuItemConfig | AI Assistant |
|
||||
907
docs-old/components/弹窗组件-Dialog.md
Normal file
907
docs-old/components/弹窗组件-Dialog.md
Normal file
@@ -0,0 +1,907 @@
|
||||
# Dialog 组件详细文档
|
||||
|
||||
> 本文档详细描述 Dialog 组件的实现细节,包括 API、UI 结构、逻辑流程等,供 AI 根据文档重现组件。
|
||||
|
||||
---
|
||||
|
||||
## 1. 组件概述
|
||||
|
||||
### 1.1 基本信息
|
||||
- **组件名称**: `BimDialog`
|
||||
- **文件路径**: `src/components/dialog/index.ts`
|
||||
- **类型定义**: `src/components/dialog/index.type.ts`
|
||||
- **样式文件**: `src/components/dialog/index.css`
|
||||
- **实现接口**: `IBimComponent`
|
||||
- **用途**: 提供可拖拽、可缩放的通用弹窗组件,支持自定义内容和样式
|
||||
|
||||
### 1.2 在 SDK 中的位置
|
||||
- Dialog 组件是独立的 UI 组件
|
||||
- 必须通过 `DialogManager` 使用,不允许直接使用
|
||||
- `DialogManager` 位于 `src/managers/dialog-manager.ts`
|
||||
|
||||
---
|
||||
|
||||
## 2. 组件类 API 文档
|
||||
|
||||
### 2.1 构造函数
|
||||
|
||||
```typescript
|
||||
constructor(options: DialogOptions)
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `options`: `DialogOptions` - 弹窗配置选项(详见类型定义)
|
||||
|
||||
**默认配置**:
|
||||
```typescript
|
||||
{
|
||||
title: 'Dialog',
|
||||
width: 300,
|
||||
height: 'auto',
|
||||
position: 'center',
|
||||
draggable: true,
|
||||
resizable: false,
|
||||
minWidth: 200,
|
||||
minHeight: 100
|
||||
}
|
||||
```
|
||||
|
||||
**行为**:
|
||||
- 合并用户配置和默认配置
|
||||
- 创建 DOM 结构
|
||||
- 自动调用 `init()` 方法
|
||||
|
||||
### 2.2 公共方法
|
||||
|
||||
#### `init(): void`
|
||||
初始化组件功能(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 将弹窗元素添加到容器
|
||||
- 初始化位置
|
||||
- 如果 `draggable` 为 true,初始化拖拽功能
|
||||
- 如果 `resizable` 为 true,初始化缩放功能
|
||||
- 订阅主题和语言变更
|
||||
- 调用 `onOpen` 回调
|
||||
|
||||
**调用时机**: 构造函数中自动调用,也可手动调用
|
||||
|
||||
#### `setTheme(theme: ThemeConfig): void`
|
||||
设置主题(实现 `IBimComponent` 接口)
|
||||
|
||||
**参数**:
|
||||
- `theme`: `ThemeConfig` - 全局主题配置
|
||||
|
||||
**功能**:
|
||||
- 将主题颜色映射到 CSS 变量
|
||||
- 如果用户未自定义颜色,使用主题颜色
|
||||
- 如果用户已自定义颜色,保持用户自定义
|
||||
|
||||
**CSS 变量映射**:
|
||||
- `--bim-dialog-bg` ← `theme.panelBackground` (如果未自定义 `backgroundColor`)
|
||||
- `--bim-dialog-header-bg` ← `theme.componentHover` (如果未自定义 `headerBackgroundColor`)
|
||||
- `--bim-dialog-title-color` ← `theme.textPrimary` (如果未自定义 `titleColor`)
|
||||
- `--bim-dialog-text-color` ← `theme.textPrimary` (如果未自定义 `textColor`)
|
||||
- `--bim-dialog-border-color` ← `theme.border` (如果未自定义 `borderColor`)
|
||||
|
||||
#### `setLocales(): void`
|
||||
设置语言(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 更新标题文本(如果标题是翻译键)
|
||||
- 使用 `t()` 函数获取翻译后的文本
|
||||
|
||||
**行为**:
|
||||
- 查找 `.bim-dialog-title` 元素
|
||||
- 如果 `options.title` 存在,使用 `t(options.title)` 更新文本
|
||||
|
||||
#### `setContent(content: HTMLElement | string): void`
|
||||
动态设置弹窗内容
|
||||
|
||||
**参数**:
|
||||
- `content`: `HTMLElement | string` - 内容元素或 HTML 字符串
|
||||
|
||||
**功能**:
|
||||
- 清空当前内容
|
||||
- 设置新内容(支持 HTML 字符串或 DOM 元素)
|
||||
|
||||
#### `fitHeight(recenter: boolean = false): void`
|
||||
根据内容自动调整弹窗高度
|
||||
|
||||
**使用场景**:
|
||||
- 弹窗内容存在“展开/收起”等高度变化的交互(例如测量面板展开后需要增高弹窗,避免遮挡底部操作按钮)
|
||||
|
||||
**参数**:
|
||||
- `recenter`: 是否根据 `options.position` 重新计算定位(默认 `false`)
|
||||
|
||||
**行为**:
|
||||
- 先将高度设置为 `auto`,获取自然高度
|
||||
- 再将高度夹紧到 `[minHeight, containerHeight]` 范围内
|
||||
- 默认不重置用户拖拽后的 `left/top`,仅做边界夹紧;若 `recenter=true` 则按 `position` 重新定位
|
||||
|
||||
#### `close(): void`
|
||||
关闭弹窗并销毁
|
||||
|
||||
**功能**:
|
||||
- 清理 `requestAnimationFrame`(如果存在)
|
||||
- 取消主题和语言订阅
|
||||
- 从 DOM 中移除元素
|
||||
- 标记为已销毁
|
||||
- 调用 `onClose` 回调
|
||||
|
||||
#### `destroy(): void`
|
||||
销毁组件(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 调用 `close()` 方法
|
||||
|
||||
### 2.3 私有方法(供理解实现细节)
|
||||
|
||||
#### `createDom(): HTMLElement`
|
||||
创建弹窗的 DOM 结构
|
||||
|
||||
**返回**: 创建的弹窗根元素
|
||||
|
||||
**DOM 结构**:
|
||||
```html
|
||||
<div class="bim-dialog" [id="..."]>
|
||||
<div class="bim-dialog-header" [class="draggable"]>
|
||||
<span class="bim-dialog-title">标题文本</span>
|
||||
<span class="bim-dialog-close">×</span>
|
||||
</div>
|
||||
<div class="bim-dialog-content">
|
||||
<!-- 用户内容 -->
|
||||
</div>
|
||||
[<div class="bim-dialog-resize-handle"></div>] <!-- 如果 resizable -->
|
||||
</div>
|
||||
```
|
||||
|
||||
**关键实现**:
|
||||
1. 创建根元素,应用 CSS 变量和尺寸
|
||||
2. 创建标题栏,包含标题和关闭按钮
|
||||
3. 创建内容区域,支持 HTML 字符串或 DOM 元素
|
||||
4. 如果 `resizable` 为 true,创建缩放手柄
|
||||
5. **事件拦截**: 绑定所有鼠标/触摸事件,使用 `stopPropagation()` 阻止冒泡,防止传递给 3D 引擎
|
||||
|
||||
**事件拦截列表**:
|
||||
```typescript
|
||||
['click', 'dblclick', 'contextmenu', 'wheel',
|
||||
'mousedown', 'mouseup', 'mousemove',
|
||||
'touchstart', 'touchend', 'touchmove',
|
||||
'pointerdown', 'pointerup', 'pointermove',
|
||||
'pointerenter', 'pointerleave', 'pointerover', 'pointerout']
|
||||
```
|
||||
|
||||
#### `initPosition(): void`
|
||||
初始化弹窗位置
|
||||
|
||||
**功能**:
|
||||
- 根据 `position` 选项计算弹窗位置
|
||||
- 支持预设位置(如 'center', 'top-left' 等)或坐标对象 `{ x, y }`
|
||||
- 确保弹窗不超出容器边界
|
||||
|
||||
**位置计算逻辑**:
|
||||
- `center`: `left = (containerWidth - dialogWidth) / 2`, `top = (containerHeight - dialogHeight) / 2`
|
||||
- `top-left`: `left = 0`, `top = 0`
|
||||
- `top-center`: `left = (containerWidth - dialogWidth) / 2`, `top = 0`
|
||||
- `top-right`: `left = containerWidth - dialogWidth`, `top = 0`
|
||||
- `left-center`: `left = 0`, `top = (containerHeight - dialogHeight) / 2`
|
||||
- `right-center`: `left = containerWidth - dialogWidth`, `top = (containerHeight - dialogHeight) / 2`
|
||||
- `bottom-left`: `left = 0`, `top = containerHeight - dialogHeight`
|
||||
- `bottom-center`: `left = (containerWidth - dialogWidth) / 2`, `top = containerHeight - dialogHeight`
|
||||
- `bottom-right`: `left = containerWidth - dialogWidth`, `top = containerHeight - dialogHeight`
|
||||
- `{ x, y }`: 直接使用坐标值
|
||||
|
||||
**边界限制**:
|
||||
```typescript
|
||||
left = Math.max(0, Math.min(left, containerWidth - dialogWidth));
|
||||
top = Math.max(0, Math.min(top, containerHeight - dialogHeight));
|
||||
```
|
||||
|
||||
#### `initDrag(): void`
|
||||
初始化拖拽功能
|
||||
|
||||
**功能**:
|
||||
- 在标题栏上绑定 `mousedown` 事件
|
||||
- 实现拖拽移动功能
|
||||
- 使用 `requestAnimationFrame` 优化性能
|
||||
- 使用 `capture: true` 确保事件在捕获阶段处理
|
||||
|
||||
**拖拽流程**:
|
||||
1. `mousedown`: 记录起始位置和弹窗当前位置,缓存容器和弹窗尺寸
|
||||
2. `mousemove`: 计算偏移量,更新弹窗位置,限制在容器边界内
|
||||
3. `mouseup`: 清理事件监听和动画帧
|
||||
|
||||
**性能优化**:
|
||||
- 使用 `requestAnimationFrame` 节流更新
|
||||
- 缓存容器和弹窗尺寸,减少 reflow
|
||||
- 使用 `capture: true` 确保事件处理
|
||||
|
||||
#### `initResize(): void`
|
||||
初始化缩放功能
|
||||
|
||||
**功能**:
|
||||
- 在缩放手柄上绑定 `mousedown` 事件
|
||||
- 实现右下角拖拽缩放功能
|
||||
- 使用 `requestAnimationFrame` 优化性能
|
||||
- 限制最小尺寸
|
||||
|
||||
**缩放流程**:
|
||||
1. `mousedown`: 记录起始位置和弹窗当前尺寸
|
||||
2. `mousemove`: 计算偏移量,更新弹窗尺寸,限制最小尺寸
|
||||
3. `mouseup`: 清理事件监听和动画帧
|
||||
|
||||
**尺寸限制**:
|
||||
```typescript
|
||||
newWidth = Math.max(minWidth || 100, startWidth + deltaX);
|
||||
newHeight = Math.max(minHeight || 50, startHeight + deltaY);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 分化组件说明
|
||||
|
||||
### 3.1 BimInfoDialog
|
||||
|
||||
**文件路径**: `src/components/dialog/bimInfoDialog/index.ts`
|
||||
|
||||
**继承关系**: `BimInfoDialog extends BimDialog`
|
||||
|
||||
**特殊功能**:
|
||||
- 预定义了信息展示的内容结构
|
||||
- 包含标题、信息列表和操作按钮
|
||||
- 使用固定的配置(宽度 320px,可缩放,可拖拽)
|
||||
|
||||
**实现方式**:
|
||||
- 在构造函数中创建内容 DOM
|
||||
- 调用父类构造函数,传入预定义的配置
|
||||
- 不需要重写其他方法,直接继承父类功能
|
||||
|
||||
**内容结构**:
|
||||
```html
|
||||
<div class="bim-info-dialog-content">
|
||||
<h3>Model Information</h3>
|
||||
<ul>
|
||||
<li><strong>Name:</strong> Sample Project</li>
|
||||
<li><strong>Version:</strong> 1.0.0</li>
|
||||
<li><strong>Date:</strong> 当前日期</li>
|
||||
<li><strong>Status:</strong> <span style="color: green;">Active</span></li>
|
||||
</ul>
|
||||
<button>Update Status</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
**与父类的差异**:
|
||||
- 固定了内容结构
|
||||
- 固定了部分配置选项
|
||||
- 其他功能完全继承自 `BimDialog`
|
||||
|
||||
---
|
||||
|
||||
## 4. Manager API 文档
|
||||
|
||||
### 4.1 DialogManager 类
|
||||
|
||||
**文件路径**: `src/managers/dialog-manager.ts`
|
||||
|
||||
**继承关系**: `DialogManager extends BimComponent`
|
||||
|
||||
### 4.2 构造函数
|
||||
|
||||
```typescript
|
||||
constructor(engine: BimEngine, container: HTMLElement)
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `engine`: `BimEngine` - 引擎实例
|
||||
- `container`: `HTMLElement` - 弹窗挂载的目标容器
|
||||
|
||||
**行为**:
|
||||
- 保存容器引用
|
||||
- 监听 `ui:open-dialog` 事件
|
||||
- 如果事件 payload.id 是 'info',自动打开信息弹窗
|
||||
|
||||
### 4.3 公共方法
|
||||
|
||||
#### `create(options: Omit<DialogOptions, 'container'>): BimDialog`
|
||||
创建一个通用弹窗
|
||||
|
||||
**参数**:
|
||||
- `options`: `Omit<DialogOptions, 'container'>` - 弹窗配置(不需要传 container)
|
||||
|
||||
**返回**: `BimDialog` 实例
|
||||
|
||||
**功能**:
|
||||
- 自动使用 Manager 绑定的容器
|
||||
- 创建 `BimDialog` 实例
|
||||
- 应用当前主题
|
||||
- 将弹窗添加到活跃列表
|
||||
- 在 `onClose` 回调中自动从列表移除
|
||||
|
||||
**使用示例**:
|
||||
```typescript
|
||||
const dialog = engine.dialog.create({
|
||||
title: '测试弹窗',
|
||||
content: '这是内容',
|
||||
width: 400,
|
||||
height: 300
|
||||
});
|
||||
```
|
||||
|
||||
#### `showInfoDialog(): void`
|
||||
显示二次封装的模型信息弹窗
|
||||
|
||||
**功能**:
|
||||
- 创建 `BimInfoDialog` 实例
|
||||
- 直接显示信息弹窗
|
||||
|
||||
**注意**: 此方法创建的弹窗不会自动加入管理列表(遗留逻辑)
|
||||
|
||||
#### `updateTheme(theme: ThemeConfig): void`
|
||||
响应全局主题变更
|
||||
|
||||
**参数**:
|
||||
- `theme`: `ThemeConfig` - 全局主题配置
|
||||
|
||||
**功能**:
|
||||
- 遍历所有活跃弹窗
|
||||
- 调用每个弹窗的 `setTheme()` 方法
|
||||
|
||||
#### `destroy(): void`
|
||||
销毁管理器
|
||||
|
||||
**功能**:
|
||||
- 销毁所有活跃弹窗
|
||||
- 清空活跃列表
|
||||
|
||||
---
|
||||
|
||||
## 5. UI 详细描述
|
||||
|
||||
### 5.1 DOM 结构
|
||||
|
||||
**完整 HTML 结构**:
|
||||
```html
|
||||
<div class="bim-dialog" id="[可选ID]" style="[CSS变量和尺寸]">
|
||||
<!-- 标题栏 -->
|
||||
<div class="bim-dialog-header [draggable]">
|
||||
<span class="bim-dialog-title">标题文本</span>
|
||||
<span class="bim-dialog-close">×</span>
|
||||
</div>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="bim-dialog-content">
|
||||
<!-- 用户内容(HTML字符串或DOM元素) -->
|
||||
</div>
|
||||
|
||||
<!-- 缩放手柄(如果 resizable) -->
|
||||
<div class="bim-dialog-resize-handle"></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 5.2 CSS 类名和样式
|
||||
|
||||
#### `.bim-dialog` (根元素)
|
||||
- `position: absolute` - 绝对定位
|
||||
- `background-color: var(--bim-dialog-bg)` - 背景色(CSS 变量)
|
||||
- `border: 1px solid var(--bim-dialog-border-color)` - 边框
|
||||
- `border-radius: 6px` - 圆角
|
||||
- `box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3)` - 阴影
|
||||
- `display: flex` + `flex-direction: column` - 垂直布局
|
||||
- `z-index: 10001` - 层级(确保在 3D 引擎之上)
|
||||
- `min-width: 200px` - 最小宽度
|
||||
- `min-height: 100px` - 最小高度
|
||||
- `pointer-events: auto` - 确保可接收事件
|
||||
|
||||
#### `.bim-dialog-header` (标题栏)
|
||||
- `height: 32px` - 固定高度
|
||||
- `background-color: var(--bim-dialog-header-bg)` - 背景色
|
||||
- `display: flex` + `align-items: center` + `justify-content: space-between` - 水平布局
|
||||
- `padding: 0 10px` - 内边距
|
||||
- `cursor: default` - 默认光标
|
||||
- `user-select: none` - 禁止选中
|
||||
- `border-bottom: 1px solid var(--bim-dialog-border-color)` - 底边框
|
||||
|
||||
#### `.bim-dialog-header.draggable` (可拖拽标题栏)
|
||||
- `cursor: move` - 移动光标
|
||||
|
||||
#### `.bim-dialog-title` (标题文本)
|
||||
- `font-size: 14px` - 字体大小
|
||||
- `font-weight: 500` - 字体粗细
|
||||
- `white-space: nowrap` - 不换行
|
||||
- `overflow: hidden` - 隐藏溢出
|
||||
- `text-overflow: ellipsis` - 文本省略
|
||||
- `color: var(--bim-dialog-title-color)` - 文字颜色
|
||||
|
||||
#### `.bim-dialog-close` (关闭按钮)
|
||||
- `cursor: pointer` - 指针光标
|
||||
- `font-size: 18px` - 字体大小
|
||||
- `color: #999` - 默认颜色
|
||||
- `line-height: 1` - 行高
|
||||
- `margin-left: 8px` - 左边距
|
||||
|
||||
#### `.bim-dialog-close:hover` (关闭按钮悬停)
|
||||
- `color: #fff` - 悬停颜色
|
||||
|
||||
#### `.bim-dialog-content` (内容区域)
|
||||
- `flex: 1` - 占据剩余空间
|
||||
- `padding: 10px` - 内边距
|
||||
- `overflow: auto` - 内容溢出时滚动
|
||||
- `font-size: 14px` - 字体大小
|
||||
- `color: var(--bim-dialog-text-color)` - 文字颜色
|
||||
|
||||
#### `.bim-dialog-resize-handle` (缩放手柄)
|
||||
- `position: absolute` - 绝对定位
|
||||
- `width: 10px` + `height: 10px` - 尺寸
|
||||
- `bottom: 0` + `right: 0` - 右下角位置
|
||||
- `cursor: se-resize` - 缩放光标
|
||||
- `z-index: 10` - 层级
|
||||
|
||||
#### `.bim-dialog-resize-handle::after` (缩放装饰)
|
||||
- 使用伪元素创建右下角斜线装饰
|
||||
- `border-right` + `border-bottom` - 创建斜线效果
|
||||
|
||||
### 5.3 CSS 变量
|
||||
|
||||
**定义位置**: `:root` 或元素内联样式
|
||||
|
||||
**变量列表**:
|
||||
- `--bim-dialog-bg`: 窗体背景颜色(默认 `rgba(17, 17, 17, 0.95)`)
|
||||
- `--bim-dialog-header-bg`: 标题栏背景颜色(默认 `#2a2a2a`)
|
||||
- `--bim-dialog-title-color`: 标题文字颜色(默认 `#fff`)
|
||||
- `--bim-dialog-text-color`: 内容文字颜色(默认 `#ccc`)
|
||||
- `--bim-dialog-border-color`: 边框颜色(默认 `#444`)
|
||||
|
||||
### 5.4 交互行为
|
||||
|
||||
#### 拖拽
|
||||
- **触发区域**: 标题栏(`.bim-dialog-header`)
|
||||
- **触发条件**: `draggable: true`
|
||||
- **行为**:
|
||||
- 鼠标按下标题栏时开始拖拽
|
||||
- 鼠标移动时弹窗跟随移动
|
||||
- 鼠标释放时结束拖拽
|
||||
- 弹窗位置限制在容器边界内
|
||||
|
||||
#### 缩放
|
||||
- **触发区域**: 缩放手柄(`.bim-dialog-resize-handle`)
|
||||
- **触发条件**: `resizable: true`
|
||||
- **行为**:
|
||||
- 鼠标按下缩放手柄时开始缩放
|
||||
- 鼠标移动时弹窗尺寸跟随变化
|
||||
- 鼠标释放时结束缩放
|
||||
- 尺寸限制在最小尺寸以上
|
||||
|
||||
#### 关闭
|
||||
- **触发方式**:
|
||||
- 点击关闭按钮(`.bim-dialog-close`)
|
||||
- 调用 `close()` 方法
|
||||
- **行为**: 弹窗从 DOM 移除,调用 `onClose` 回调
|
||||
|
||||
### 5.5 响应式行为
|
||||
|
||||
- 弹窗位置会根据容器尺寸自动调整,确保不超出边界
|
||||
- 内容区域支持滚动(`overflow: auto`)
|
||||
- 标题文本过长时显示省略号(`text-overflow: ellipsis`)
|
||||
|
||||
---
|
||||
|
||||
## 6. 逻辑流程详细描述
|
||||
|
||||
### 6.1 初始化流程
|
||||
|
||||
1. **构造函数调用**:
|
||||
- 合并配置选项(用户配置 + 默认配置)
|
||||
- 调用 `createDom()` 创建 DOM 结构
|
||||
- 保存 header 和 contentArea 引用
|
||||
- 自动调用 `init()`
|
||||
|
||||
2. **init() 方法执行**:
|
||||
- 检查是否已初始化,如果是则返回
|
||||
- 将弹窗元素添加到容器
|
||||
- 调用 `initPosition()` 计算并设置位置
|
||||
- 如果 `draggable` 为 true,调用 `initDrag()`
|
||||
- 如果 `resizable` 为 true,调用 `initResize()`
|
||||
- 标记为已初始化
|
||||
- 调用 `onOpen` 回调(如果存在)
|
||||
- 订阅主题变更:`themeManager.subscribe()`
|
||||
- 订阅语言变更:`localeManager.subscribe()`
|
||||
|
||||
### 6.2 生命周期
|
||||
|
||||
#### 创建阶段
|
||||
- 构造函数 → `createDom()` → `init()`
|
||||
|
||||
#### 运行阶段
|
||||
- 响应主题变更:`setTheme()` 被调用
|
||||
- 响应语言变更:`setLocales()` 被调用
|
||||
- 用户交互:拖拽、缩放、关闭
|
||||
|
||||
#### 销毁阶段
|
||||
- `close()` 或 `destroy()` 被调用
|
||||
- 清理 `requestAnimationFrame`
|
||||
- 取消主题和语言订阅
|
||||
- 从 DOM 移除元素
|
||||
- 调用 `onClose` 回调
|
||||
|
||||
### 6.3 事件处理流程
|
||||
|
||||
#### 拖拽事件流程
|
||||
1. 用户在标题栏按下鼠标 → `mousedown` 事件
|
||||
2. 记录起始位置和弹窗当前位置
|
||||
3. 缓存容器和弹窗尺寸
|
||||
4. 在 document 上绑定 `mousemove` 和 `mouseup`(捕获阶段)
|
||||
5. 鼠标移动时 → `mousemove` 事件
|
||||
- 计算偏移量
|
||||
- 使用 `requestAnimationFrame` 更新位置
|
||||
- 限制在容器边界内
|
||||
6. 鼠标释放时 → `mouseup` 事件
|
||||
- 清理事件监听
|
||||
- 清理动画帧
|
||||
|
||||
#### 缩放事件流程
|
||||
1. 用户在缩放手柄按下鼠标 → `mousedown` 事件
|
||||
2. 记录起始位置和弹窗当前尺寸
|
||||
3. 在 document 上绑定 `mousemove` 和 `mouseup`(捕获阶段)
|
||||
4. 鼠标移动时 → `mousemove` 事件
|
||||
- 计算偏移量
|
||||
- 使用 `requestAnimationFrame` 更新尺寸
|
||||
- 限制在最小尺寸以上
|
||||
5. 鼠标释放时 → `mouseup` 事件
|
||||
- 清理事件监听
|
||||
- 清理动画帧
|
||||
|
||||
#### 事件拦截流程
|
||||
- 弹窗根元素上绑定所有鼠标/触摸事件
|
||||
- 使用 `stopPropagation()` 阻止事件冒泡
|
||||
- 防止事件传递给 3D 引擎
|
||||
- 使用 `passive: false` 允许阻止默认行为
|
||||
|
||||
### 6.4 状态管理
|
||||
|
||||
#### 内部状态
|
||||
- `_isInitialized`: 是否已初始化
|
||||
- `_isDestroyed`: 是否已销毁
|
||||
- `rafId`: `requestAnimationFrame` 的 ID(用于节流)
|
||||
|
||||
#### 订阅管理
|
||||
- `unsubscribeTheme`: 主题订阅取消函数
|
||||
- `unsubscribeLocale`: 语言订阅取消函数
|
||||
|
||||
### 6.5 与其他组件的交互
|
||||
|
||||
- **与 DialogManager**: 通过 Manager 创建和管理
|
||||
- **与 ThemeManager**: 订阅主题变更
|
||||
- **与 LocaleManager**: 订阅语言变更
|
||||
- **与 3D 引擎**: 通过事件拦截防止交互冲突
|
||||
|
||||
---
|
||||
|
||||
## 7. 国际化支持
|
||||
|
||||
### 7.1 使用的翻译键
|
||||
|
||||
- `options.title`: 弹窗标题(如果提供,会通过 `t()` 函数翻译)
|
||||
|
||||
### 7.2 语言变更处理
|
||||
|
||||
- 组件订阅 `localeManager.subscribe()`
|
||||
- 语言变更时,`setLocales()` 方法被调用
|
||||
- 更新标题文本:`titleEl.textContent = t(this.options.title)`
|
||||
|
||||
### 7.3 实现细节
|
||||
|
||||
```typescript
|
||||
public setLocales(): void {
|
||||
if (this.options.title) {
|
||||
const titleEl = this.header.querySelector('.bim-dialog-title');
|
||||
if (titleEl) {
|
||||
titleEl.textContent = t(this.options.title);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 主题支持
|
||||
|
||||
### 8.1 使用的主题变量
|
||||
|
||||
- `theme.panelBackground` → `--bim-dialog-bg`
|
||||
- `theme.componentHover` → `--bim-dialog-header-bg`
|
||||
- `theme.textPrimary` → `--bim-dialog-title-color` 和 `--bim-dialog-text-color`
|
||||
- `theme.border` → `--bim-dialog-border-color`
|
||||
|
||||
### 8.2 主题变更处理
|
||||
|
||||
- 组件订阅 `themeManager.subscribe()`
|
||||
- 主题变更时,`setTheme()` 方法被调用
|
||||
- 如果用户未自定义颜色,使用主题颜色
|
||||
- 如果用户已自定义颜色,保持用户自定义
|
||||
|
||||
### 8.3 实现细节
|
||||
|
||||
```typescript
|
||||
public setTheme(theme: ThemeConfig) {
|
||||
const style = this.element.style;
|
||||
if (!this.options.backgroundColor)
|
||||
style.setProperty('--bim-dialog-bg', theme.panelBackground);
|
||||
if (!this.options.headerBackgroundColor)
|
||||
style.setProperty('--bim-dialog-header-bg', theme.componentHover);
|
||||
// ... 其他颜色映射
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 使用示例
|
||||
|
||||
### 9.1 基本使用(通过 Manager)
|
||||
|
||||
```typescript
|
||||
import { BimEngine } from 'iflow-engine';
|
||||
|
||||
const engine = new BimEngine('container');
|
||||
|
||||
// 创建简单弹窗
|
||||
const dialog = engine.dialog.create({
|
||||
title: 'dialog.testTitle', // 使用翻译键
|
||||
content: '这是内容',
|
||||
width: 400,
|
||||
height: 300
|
||||
});
|
||||
|
||||
// 创建可缩放弹窗
|
||||
const resizableDialog = engine.dialog.create({
|
||||
title: '可缩放弹窗',
|
||||
content: '<div>内容</div>',
|
||||
width: 500,
|
||||
height: 400,
|
||||
resizable: true,
|
||||
draggable: true
|
||||
});
|
||||
|
||||
// 创建自定义位置弹窗
|
||||
const positionedDialog = engine.dialog.create({
|
||||
title: '自定义位置',
|
||||
content: '内容',
|
||||
position: { x: 100, y: 100 },
|
||||
width: 300,
|
||||
height: 200
|
||||
});
|
||||
```
|
||||
|
||||
### 9.2 高级使用
|
||||
|
||||
```typescript
|
||||
// 创建带自定义样式的弹窗
|
||||
const styledDialog = engine.dialog.create({
|
||||
title: '自定义样式',
|
||||
content: '<div>内容</div>',
|
||||
backgroundColor: 'rgba(100, 0, 0, 0.95)',
|
||||
headerBackgroundColor: '#cc0000',
|
||||
titleColor: '#ffffff',
|
||||
textColor: '#ffcccc',
|
||||
borderColor: '#ff6666',
|
||||
width: 300,
|
||||
height: 200
|
||||
});
|
||||
|
||||
// 创建带回调的弹窗
|
||||
const callbackDialog = engine.dialog.create({
|
||||
title: '带回调',
|
||||
content: '内容',
|
||||
onOpen: () => {
|
||||
console.log('弹窗已打开');
|
||||
},
|
||||
onClose: () => {
|
||||
console.log('弹窗已关闭');
|
||||
}
|
||||
});
|
||||
|
||||
// 动态更新内容
|
||||
const dynamicDialog = engine.dialog.create({
|
||||
title: '动态内容',
|
||||
content: '初始内容'
|
||||
});
|
||||
|
||||
// 稍后更新内容
|
||||
dynamicDialog.setContent('<div>新内容</div>');
|
||||
```
|
||||
|
||||
### 9.3 使用信息弹窗
|
||||
|
||||
```typescript
|
||||
// 通过 Manager 显示信息弹窗
|
||||
engine.dialog.showInfoDialog();
|
||||
|
||||
// 通过事件总线打开(如果配置了监听)
|
||||
engine.emit('ui:open-dialog', { id: 'info' });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 实现细节(供 AI 重现)
|
||||
|
||||
### 10.1 关键算法
|
||||
|
||||
#### 位置计算算法
|
||||
```typescript
|
||||
// 计算居中位置
|
||||
function calculateCenterPosition(containerWidth, containerHeight, dialogWidth, dialogHeight) {
|
||||
return {
|
||||
left: (containerWidth - dialogWidth) / 2,
|
||||
top: (containerHeight - dialogHeight) / 2
|
||||
};
|
||||
}
|
||||
|
||||
// 边界限制算法
|
||||
function clampPosition(left, top, containerWidth, containerHeight, dialogWidth, dialogHeight) {
|
||||
return {
|
||||
left: Math.max(0, Math.min(left, containerWidth - dialogWidth)),
|
||||
top: Math.max(0, Math.min(top, containerHeight - dialogHeight))
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### 拖拽算法
|
||||
```typescript
|
||||
// 拖拽位置更新
|
||||
function updateDragPosition(startX, startY, currentX, currentY, startLeft, startTop) {
|
||||
const deltaX = currentX - startX;
|
||||
const deltaY = currentY - startY;
|
||||
return {
|
||||
left: startLeft + deltaX,
|
||||
top: startTop + deltaY
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### 缩放算法
|
||||
```typescript
|
||||
// 缩放尺寸更新
|
||||
function updateResizeSize(startX, startY, currentX, currentY, startWidth, startHeight, minWidth, minHeight) {
|
||||
const deltaX = currentX - startX;
|
||||
const deltaY = currentY - startY;
|
||||
return {
|
||||
width: Math.max(minWidth, startWidth + deltaX),
|
||||
height: Math.max(minHeight, startHeight + deltaY)
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 10.2 性能优化点
|
||||
|
||||
1. **requestAnimationFrame 节流**:
|
||||
- 拖拽和缩放使用 `requestAnimationFrame` 节流更新
|
||||
- 避免频繁的 DOM 操作
|
||||
|
||||
2. **尺寸缓存**:
|
||||
- 拖拽开始时缓存容器和弹窗尺寸
|
||||
- 减少 `getBoundingClientRect()` 调用
|
||||
|
||||
3. **事件捕获**:
|
||||
- 使用 `capture: true` 确保事件在捕获阶段处理
|
||||
- 即使内部元素阻止冒泡,也能捕获事件
|
||||
|
||||
4. **CSS 变量**:
|
||||
- 使用 CSS 变量应用主题
|
||||
- 主题变更时无需重新渲染 DOM
|
||||
|
||||
### 10.3 注意事项和边界情况
|
||||
|
||||
1. **容器尺寸为 0**:
|
||||
- 位置计算时可能出现除零或负数
|
||||
- 使用 `Math.max()` 确保位置不为负
|
||||
|
||||
2. **弹窗尺寸大于容器**:
|
||||
- 位置计算时确保弹窗不超出容器
|
||||
- 使用边界限制算法
|
||||
|
||||
3. **快速连续操作**:
|
||||
- 使用 `rafId` 防止多个动画帧同时执行
|
||||
- 确保动画帧正确清理
|
||||
|
||||
4. **事件清理**:
|
||||
- 组件销毁时必须清理所有事件监听
|
||||
- 必须取消主题和语言订阅
|
||||
|
||||
5. **事件拦截**:
|
||||
- 必须拦截所有鼠标/触摸事件
|
||||
- 防止事件传递给 3D 引擎
|
||||
|
||||
6. **翻译键处理**:
|
||||
- 标题可能是翻译键或普通文本
|
||||
- 只有翻译键才需要通过 `t()` 函数处理
|
||||
|
||||
---
|
||||
|
||||
## 11. 类型定义
|
||||
|
||||
### 11.1 DialogOptions
|
||||
|
||||
```typescript
|
||||
interface DialogOptions extends DialogColors {
|
||||
container: HTMLElement; // 弹窗挂载的父容器(必需)
|
||||
title?: string; // 弹窗标题(可选,支持翻译键)
|
||||
content?: HTMLElement | string; // 弹窗内容(可选)
|
||||
width?: number | string; // 宽度(可选,默认 300)
|
||||
height?: number | string; // 高度(可选,默认 'auto')
|
||||
position?: DialogPosition; // 位置(可选,默认 'center')
|
||||
draggable?: boolean; // 是否可拖拽(可选,默认 true)
|
||||
resizable?: boolean; // 是否可缩放(可选,默认 false)
|
||||
minWidth?: number; // 最小宽度(可选,默认 200)
|
||||
minHeight?: number; // 最小高度(可选,默认 100)
|
||||
onClose?: () => void; // 关闭回调(可选)
|
||||
onOpen?: () => void; // 打开回调(可选)
|
||||
id?: string; // 弹窗 ID(可选)
|
||||
}
|
||||
```
|
||||
|
||||
### 11.2 DialogPosition
|
||||
|
||||
```typescript
|
||||
type DialogPosition =
|
||||
| 'center'
|
||||
| 'top-left' | 'top-center' | 'top-right'
|
||||
| 'left-center' | 'right-center'
|
||||
| 'bottom-left' | 'bottom-center' | 'bottom-right'
|
||||
| { x: number; y: number };
|
||||
```
|
||||
|
||||
### 11.3 DialogColors
|
||||
|
||||
```typescript
|
||||
interface DialogColors {
|
||||
backgroundColor?: string; // 窗体背景颜色
|
||||
headerBackgroundColor?: string; // 标题栏背景颜色
|
||||
titleColor?: string; // 标题文字颜色
|
||||
textColor?: string; // 内容文字颜色
|
||||
borderColor?: string; // 边框颜色
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. 文件清单
|
||||
|
||||
### 12.1 相关文件
|
||||
|
||||
- `src/components/dialog/index.ts` - 主组件类
|
||||
- `src/components/dialog/index.type.ts` - 类型定义
|
||||
- `src/components/dialog/index.css` - 样式文件
|
||||
- `src/components/dialog/bimInfoDialog/index.ts` - 信息弹窗(分化组件)
|
||||
- `src/components/dialog/bimInfoDialog/index.css` - 信息弹窗样式
|
||||
- `src/managers/dialog-manager.ts` - 管理器类
|
||||
|
||||
### 12.2 依赖文件
|
||||
|
||||
- `src/types/component.ts` - IBimComponent 接口
|
||||
- `src/themes/types.ts` - ThemeConfig 类型
|
||||
- `src/services/theme.ts` - ThemeManager
|
||||
- `src/services/locale.ts` - LocaleManager
|
||||
|
||||
---
|
||||
|
||||
## 13. 更新记录
|
||||
|
||||
| 日期 | 修改内容 | 修改人 |
|
||||
|------|---------|--------|
|
||||
| 2024-XX-XX | 初始创建 | AI Assistant |
|
||||
|
||||
---
|
||||
|
||||
**重要提醒**: 本文档必须与组件代码保持同步。任何组件修改都必须更新本文档!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
97
docs-old/components/折叠面板组件-Collapse.md
Normal file
97
docs-old/components/折叠面板组件-Collapse.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Collapse 折叠面板组件
|
||||
|
||||
`BimCollapse` 是一个通用的折叠面板组件,支持手风琴模式、自定义内容和标题。常用于属性面板、设置菜单等场景。
|
||||
|
||||
## 1. 组件概述
|
||||
|
||||
- **类名**: `BimCollapse`
|
||||
- **文件路径**: `src/components/collapse/index.ts`
|
||||
- **样式文件**: `src/components/collapse/index.css`
|
||||
- **类型定义**: `src/components/collapse/types.ts`
|
||||
|
||||
该组件实现了 `IBimComponent` 接口,具备完整的生命周期管理、主题响应和国际化支持能力。
|
||||
|
||||
## 2. API 文档
|
||||
|
||||
### 2.1 构造函数
|
||||
|
||||
```typescript
|
||||
const collapse = new BimCollapse(options: CollapseOptions);
|
||||
```
|
||||
|
||||
### 2.2 CollapseOptions 配置项
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|------|------|-------|------|
|
||||
| `container` | `HTMLElement \| string` | - | **(必填)** 挂载容器或其 ID |
|
||||
| `items` | `CollapseItemConfig[]` | - | **(必填)** 面板项列表 |
|
||||
| `accordion` | `boolean` | `false` | 是否开启手风琴模式(一次只能展开一项) |
|
||||
| `activeIds` | `string[]` | `[]` | 初始展开的面板 ID 列表 |
|
||||
| `bordered` | `boolean` | `true` | 是否显示外边框 |
|
||||
| `ghost` | `boolean` | `false` | 是否开启幽灵模式(无背景、无边框) |
|
||||
| `className` | `string` | - | 自定义类名 |
|
||||
| `onChange` | `(activeIds: string[]) => void` | - | 切换面板时的回调函数 |
|
||||
|
||||
### 2.3 CollapseItemConfig 面板项配置
|
||||
|
||||
| 属性 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | `string` | **(必填)** 唯一标识符 |
|
||||
| `title` | `string` | **(必填)** 标题文本的**翻译键** (例如 `'panel.property.base'`) |
|
||||
| `content` | `string \| HTMLElement` | **(必填)** 面板内容 |
|
||||
| `icon` | `string` | 标题左侧图标 (SVG 字符串) |
|
||||
| `extra` | `string \| HTMLElement` | 标题栏右侧额外内容 |
|
||||
| `disabled` | `boolean` | 是否禁用该面板 |
|
||||
| `className` | `string` | 自定义面板类名 |
|
||||
|
||||
### 2.4 实例方法
|
||||
|
||||
- **`toggleItem(id: string)`**: 切换指定面板的展开/折叠状态。
|
||||
- **`setTheme(theme: ThemeConfig)`**: 设置组件主题 (CSS 变量映射)。
|
||||
- **`setLocales()`**: 更新组件文本 (标题翻译)。
|
||||
- **`destroy()`**: 销毁组件,清理资源。
|
||||
|
||||
## 3. 使用示例
|
||||
|
||||
```typescript
|
||||
import { BimCollapse } from '../components/collapse/index';
|
||||
|
||||
const collapse = new BimCollapse({
|
||||
container: document.getElementById('panel'),
|
||||
accordion: true,
|
||||
activeIds: ['base'],
|
||||
items: [
|
||||
{
|
||||
id: 'base',
|
||||
title: 'panel.property.base', // 必须是翻译键
|
||||
content: document.createElement('div'), // 或 HTML 字符串
|
||||
icon: '<svg>...</svg>'
|
||||
},
|
||||
{
|
||||
id: 'advanced',
|
||||
title: 'panel.property.advanced',
|
||||
content: 'Advanced Content',
|
||||
disabled: true
|
||||
}
|
||||
],
|
||||
onChange: (ids) => {
|
||||
console.log('Current active panels:', ids);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 4. 主题支持
|
||||
|
||||
组件自动订阅主题变更,并通过 CSS 变量控制样式:
|
||||
|
||||
- **面板背景**: `theme.panelBackground`
|
||||
- **边框颜色**: `theme.border`
|
||||
- **文本颜色**: `theme.textPrimary`
|
||||
- **标题栏背景**: `theme.componentHover` (默认) / `theme.componentBackground`
|
||||
- **禁用态颜色**: `theme.textSecondary`
|
||||
|
||||
## 5. 国际化支持
|
||||
|
||||
组件自动订阅语言变更:
|
||||
- **标题 (`title`)**: 会自动使用 `t(config.title)` 进行翻译。确保传入的是有效的翻译键。
|
||||
- **内容 (`content`)**: 如果内容包含文本,请确保内容生成时已翻译,或内容本身具有响应国际化的能力(如使用 `BimDescription`)。
|
||||
1198
docs-old/components/按钮组组件-ButtonGroup.md
Normal file
1198
docs-old/components/按钮组组件-ButtonGroup.md
Normal file
File diff suppressed because it is too large
Load Diff
127
docs-old/components/描述列表组件-Description.md
Normal file
127
docs-old/components/描述列表组件-Description.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Description 描述列表组件
|
||||
|
||||
`BimDescription` 组件用于展示一组键值对(Key-Value)数据,常用于详情页、属性面板等场景。
|
||||
|
||||
## 1. 组件概述
|
||||
|
||||
- **类名**: `BimDescription`
|
||||
- **文件路径**: `src/components/description/index.ts`
|
||||
- **样式文件**: `src/components/description/index.css`
|
||||
- **类型定义**: `src/components/description/types.ts`
|
||||
|
||||
该组件是一个**纯展示组件**,其特点是:
|
||||
- **不内置国际化**: 为了最大灵活性,Label 和 Value 均直接显示传入的字符串/元素,不调用翻译函数。调用者应负责传入已翻译的文本。
|
||||
- **高度定制化**: 支持全局或行级的颜色、Padding、字体大小定制。
|
||||
- **布局灵活**: 支持普通列表模式和带边框的表格模式(Key-Value 间有纵向分割线)。
|
||||
|
||||
## 2. API 文档
|
||||
|
||||
### 2.1 构造函数
|
||||
|
||||
```typescript
|
||||
const description = new BimDescription(options: DescriptionOptions);
|
||||
```
|
||||
|
||||
### 2.2 DescriptionOptions 配置项
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|------|------|-------|------|
|
||||
| `container` | `HTMLElement \| string` | - | **(必填)** 挂载容器或其 ID |
|
||||
| `items` | `DescriptionItem[]` | - | **(必填)** 数据项列表 |
|
||||
| `bordered` | `boolean` | `false` | 是否显示边框。开启后会显示行间分割线以及 Key-Value 之间的纵向分割线 |
|
||||
| `labelWidth` | `string` | - | 标签列的固定宽度 (如 `'80px'`),不设置则自适应 |
|
||||
| `fontSize` | `string` | `'14px'` | 全局字体大小 (如 `'12px'`) |
|
||||
| `labelColor` | `string` | `theme.textSecondary` | 全局标签颜色 |
|
||||
| `valueColor` | `string` | `theme.textPrimary` | 全局内容颜色 |
|
||||
| `labelPadding` | `string` | `'0 4px'` | 标签单元格内边距 (CSS padding 语法) |
|
||||
| `valuePadding` | `string` | `'0 4px'` | 内容单元格内边距 (CSS padding 语法) |
|
||||
| `className` | `string` | - | 自定义类名 |
|
||||
|
||||
### 2.3 DescriptionItem 数据项
|
||||
|
||||
| 属性 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `label` | `string` | 标签文本 (直接显示,在非 bordered 模式下会自动添加冒号) |
|
||||
| `value` | `string \| HTMLElement` | 内容文本或 DOM 元素 |
|
||||
| `labelColor` | `string` | 行级自定义标签颜色 (优先级高于全局) |
|
||||
| `valueColor` | `string` | 行级自定义内容颜色 (优先级高于全局) |
|
||||
| `className` | `string` | 自定义行类名 |
|
||||
|
||||
### 2.4 实例方法
|
||||
|
||||
- **`setItems(items: DescriptionItem[])`**: 动态更新数据列表。
|
||||
- **`setTheme(theme: ThemeConfig)`**: <20><>置组件主题 (通常自动调用)。
|
||||
- **`destroy()`**: 销毁组件,清理 DOM 和事件订阅。
|
||||
|
||||
## 3. 使用示例
|
||||
|
||||
### 3.1 基础使用
|
||||
|
||||
```typescript
|
||||
new BimDescription({
|
||||
container: document.getElementById('container'),
|
||||
labelWidth: '80px',
|
||||
items: [
|
||||
{ label: 'Name', value: 'Wall-01' },
|
||||
{ label: 'ID', value: 'E-1001' },
|
||||
{ label: 'Level', value: 'Level 1' }
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
### 3.2 带边框的表格模式 (Bordered)
|
||||
|
||||
```typescript
|
||||
new BimDescription({
|
||||
container: document.getElementById('container'),
|
||||
bordered: true,
|
||||
fontSize: '12px',
|
||||
labelPadding: '4px 8px',
|
||||
valuePadding: '4px 8px',
|
||||
items: [
|
||||
{ label: 'Material', value: 'Concrete' },
|
||||
{ label: 'Density', value: '2400 kg/m³' }
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
### 3.3 自定义样式
|
||||
|
||||
```typescript
|
||||
new BimDescription({
|
||||
container: 'container',
|
||||
labelColor: '#999',
|
||||
valueColor: '#333',
|
||||
items: [
|
||||
{
|
||||
label: 'Status',
|
||||
value: '<span style="color: green">Active</span>',
|
||||
labelColor: 'blue' // 单独覆盖此行的标签颜色
|
||||
}
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
## 4. 主题支持
|
||||
|
||||
组件会自动响应系统主题变更。默认映射关系如下:
|
||||
|
||||
- **文本颜色**: `theme.textPrimary`
|
||||
- **标签颜色**: `theme.textSecondary`
|
||||
- **边框颜色**: `theme.border`
|
||||
- **标签背景 (仅 Bordered 模式)**: `theme.background` (用于轻微区分 Key 和 Value)
|
||||
|
||||
## 5. 国际化支持
|
||||
|
||||
**组件内部不进行翻译**。调用者应在传入 `label` 之前使用 `t()` 函数进行翻译。
|
||||
|
||||
```typescript
|
||||
import { t } from 'iflow-engine/services/locale';
|
||||
|
||||
new BimDescription({
|
||||
// ...
|
||||
items: [
|
||||
{ label: t('panel.property.id'), value: '123' }
|
||||
]
|
||||
});
|
||||
```
|
||||
92
docs-old/components/标签页组件-Tab.md
Normal file
92
docs-old/components/标签页组件-Tab.md
Normal file
@@ -0,0 +1,92 @@
|
||||
## 1. 组件概述
|
||||
- **名称**:BimTab
|
||||
- **位置**:`src/components/tab/`
|
||||
- **功能**:渲染固定标签页(不支持运行期增删),支持点击切换、禁用、可选内容托管。主题由全局 `ThemeManager` 提供,文案通过 `t()` 翻译。
|
||||
- **使用方式**:直接通过构造函数 + `init()` 创建;本项目内目前仅在 `ConstructTreeManagerBtn` 弹窗中使用(无专门 Manager)。
|
||||
|
||||
## 2. 组件类 API(BimTab)
|
||||
- `constructor(options: TabOptions)`:创建实例并挂载到 `options.container`。
|
||||
- `init(): void`:渲染头部与内容,订阅主题/语言。
|
||||
- `activateTab(tabId: string): void`:切换激活标签,触发 `onChange`。
|
||||
- `setTheme(theme: ThemeConfig): void`:应用主题变量。
|
||||
- `setLocales(): void`:刷新标题文案。
|
||||
- `destroy(): void`:解绑事件、取消订阅、移除 DOM。
|
||||
|
||||
## 3. 分化组件
|
||||
- 当前无子类或变体,后续可扩展滚动、溢出折叠等能力。
|
||||
|
||||
## 4. 使用场景说明
|
||||
- **ConstructTreeManagerBtn 弹窗**:顶部三段标签(构件/系统/空间),构件标签承载原有 Tree,系统/空间暂为空容器。
|
||||
- 适用于固定分区切换,内容简单或由外部回调控制。
|
||||
|
||||
## 5. UI 结构
|
||||
```
|
||||
div.bim-tab
|
||||
div.bim-tab__nav [role=tablist]
|
||||
button.bim-tab__item[role=tab][aria-selected][aria-disabled?]
|
||||
span.bim-tab__icon? (可选)
|
||||
span.bim-tab__title
|
||||
div.bim-tab__content
|
||||
div.bim-tab__panel[role=tabpanel][aria-labelledby=tab-xxx]
|
||||
...
|
||||
```
|
||||
- 状态类:`.is-active`、`.is-disabled`。
|
||||
- 内容区:仅切换显示,不强制填充(可为空)。
|
||||
|
||||
## 6. 逻辑流程
|
||||
1) `constructor`:创建根节点、头部、内容容器;缓存 tab 数据;挂载到传入容器。
|
||||
2) `init`:渲染头部按钮与内容面板,设置初始激活;应用当前主题/语言;订阅主题、语言变更。
|
||||
3) 交互:点击非禁用按钮 → `activateTab` 更新头部/面板状态 → 回调 `onChange`。
|
||||
4) 销毁:解绑点击监听、取消订阅、清空映射并移除 DOM。
|
||||
|
||||
## 7. 国际化
|
||||
- 标题:`t(tab.title)`,若翻译键不存在则回退原文。
|
||||
- 新增翻译键:`tab.component` / `tab.system` / `tab.space`(已在 `zh-CN.ts`、`en-US.ts` 注册)。
|
||||
- `setLocales()`:遍历头部按钮刷新标题文案;订阅 `localeManager` 自动响应语言切换。
|
||||
|
||||
## 8. 主题支持
|
||||
- 来自 `themeManager`,不从配置传入。
|
||||
- 使用的变量(设置在根节点上):
|
||||
- `--bim-tab-bg`、`--bim-tab-nav-bg`
|
||||
- `--bim-tab-text`、`--bim-tab-text-secondary`、`--bim-tab-text-active`
|
||||
- `--bim-tab-border`、`--bim-tab-hover-bg`、`--bim-tab-active-bg`
|
||||
- `--bim-tab-icon`
|
||||
- `setTheme(theme)`:根据 `ThemeConfig` 写入上述 CSS 变量。
|
||||
|
||||
## 9. 使用示例
|
||||
```ts
|
||||
const tabMount = document.createElement('div');
|
||||
const tab = new BimTab({
|
||||
container: tabMount,
|
||||
tabs: [
|
||||
{ id: 'component', title: 'tab.component', content: componentEl },
|
||||
{ id: 'system', title: 'tab.system', content: systemEl },
|
||||
{ id: 'space', title: 'tab.space', content: spaceEl },
|
||||
],
|
||||
activeId: 'component',
|
||||
onChange: (id) => {
|
||||
// 根据 id 做额外逻辑(如埋点、动态加载)
|
||||
},
|
||||
});
|
||||
tab.init();
|
||||
```
|
||||
|
||||
## 10. 实现细节
|
||||
- 仅支持固定 tabs:`TabOptions.tabs` 为初始化列表,不提供新增/删除接口。
|
||||
- 内容托管两种方式:`content: HTMLElement`(append)或 `content: string`(innerHTML)。未提供内容时面板为空。
|
||||
- 事件绑定:头部使用事件委托绑定 click,销毁时移除。
|
||||
- 访问性:头部 `role=tab`、`aria-selected`、`aria-disabled`;面板 `role=tabpanel` 且 `aria-labelledby` 对应头部 id。
|
||||
- 主题/语言订阅:`localeManager.subscribe`、`themeManager.subscribe`,销毁时必须取消。
|
||||
|
||||
## 11. 类型定义
|
||||
- 位置:`src/components/tab/index.type.ts`
|
||||
- 主要类型:
|
||||
- `TabItem`: `{ id; title; disabled?; icon?; content?; meta? }`
|
||||
- `TabOptions`: `{ container; tabs; activeId?; onChange? }`
|
||||
|
||||
## 12. 文件清单
|
||||
- `src/components/tab/index.ts`:组件实现
|
||||
- `src/components/tab/index.type.ts`:类型定义
|
||||
- `src/components/tab/index.css`:样式
|
||||
- (无 Manager)当前仅在 `ConstructTreeManagerBtn` 中直接使用
|
||||
|
||||
108
docs-old/components/树形控件组件-Tree.md
Normal file
108
docs-old/components/树形控件组件-Tree.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# Tree 组件文档
|
||||
|
||||
## 1. 组件概述
|
||||
**BimTree** 是一个通用的树形组件,支持多级嵌套、复选框、图标和自定义内容。它通常用于展示模型结构、文件目录或层级列表。
|
||||
该组件设计为被包裹在容器(如 Dialog)中,并通过 `ModelTreeManager` 进行创建和管理。
|
||||
|
||||
## 2. 组件类 API (BimTree)
|
||||
`src/components/tree/index.ts`
|
||||
|
||||
### 2.1 核心方法
|
||||
* `checkNode(id: string, checked: boolean)`: 勾选/取消勾选指定节点。支持父子联动。
|
||||
* `checkAll(checked: boolean)`: 全选或全不选。
|
||||
* `expandNode(id: string, expanded: boolean)`: 展开/折叠指定节点。
|
||||
* `expandAll(expanded: boolean)`: 展开/折叠所有层级。
|
||||
* `getCheckedNodes(includeHalfChecked?: boolean)`: 获取当前所有被勾选的节点配置列表。
|
||||
* `getNode(id: string)`: 获取指定 ID 的节点实例。
|
||||
|
||||
## 3. Manager API (ModelTreeManager)
|
||||
|
||||
`ModelTreeManager` 负责创建和管理 `BimTree` 实例。
|
||||
|
||||
### 方法
|
||||
|
||||
#### `createTree(options: TreeOptions): BimTree`
|
||||
创建一个新的树组件实例。
|
||||
|
||||
- **参数**: `options` (TreeOptions) - 树组件配置
|
||||
- **返回**: `BimTree` - 树组件实例
|
||||
- **功能**:
|
||||
- 实例化组件
|
||||
- 自动绑定组件事件到全局事件总线 (`ui:tree-node-check`, `ui:tree-node-select` 等)
|
||||
- 初始化组件
|
||||
|
||||
#### `showStructTree(data: TreeNodeConfig[], title: string): { tree: BimTree, dialog: BimDialog }`
|
||||
显示带复选框的模型结构树弹窗。
|
||||
|
||||
#### `showSimpleTree(data: TreeNodeConfig[], title: string): { tree: BimTree, dialog: BimDialog }`
|
||||
显示简单的树形弹窗 (无复选框)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 类型定义
|
||||
`src/components/tree/types.ts`
|
||||
|
||||
```typescript
|
||||
interface TreeNodeConfig {
|
||||
id: string;
|
||||
label: string; // 翻译键
|
||||
children?: TreeNodeConfig[];
|
||||
checked?: boolean;
|
||||
expanded?: boolean;
|
||||
disabled?: boolean;
|
||||
icon?: string;
|
||||
data?: any; // 业务数据
|
||||
}
|
||||
|
||||
interface TreeOptions {
|
||||
data: TreeNodeConfig[];
|
||||
checkable?: boolean; // 是否显示复选框
|
||||
checkStrictly?: boolean; // 是否父子联动 (默认 true)
|
||||
defaultExpandAll?: boolean;
|
||||
indent?: number;
|
||||
|
||||
// 事件回调
|
||||
onNodeCheck?: (node: BimTreeNode) => void;
|
||||
onNodeSelect?: (node: BimTreeNode) => void;
|
||||
onNodeExpand?: (node: BimTreeNode) => void;
|
||||
}
|
||||
```
|
||||
|
||||
## 5. UI 结构与样式
|
||||
* **容器**: `.bim-tree` (Flex column)
|
||||
* **节点**: `.bim-tree-node`
|
||||
* **内容行**: `.bim-tree-node-content` (Flex row, align-center)
|
||||
* **箭头**: `.bim-tree-switcher` (SVG, rotate transform)
|
||||
* **复选框**: `.bim-tree-checkbox` (自定义样式, support indeterminate)
|
||||
* **图标**: `.bim-tree-icon`
|
||||
* **文本**: `.bim-tree-title`
|
||||
* **子容器**: `.bim-tree-children` (padding-left 缩进)
|
||||
|
||||
## 6. 逻辑流程
|
||||
1. **初始化**:
|
||||
* 根据 `data` 递归创建 `BimTreeNode` 实例。
|
||||
* 建立 `id -> Node` 的 Map 索引。
|
||||
* 订阅主题和语言变更。
|
||||
2. **联动逻辑 (Check Cascade)**:
|
||||
* **向下**: 父节点状态变更 -> 递归强制设置所有子节点。
|
||||
* **向上**: 子节点状态变更 -> 冒泡检查兄弟节点状态 -> 更新父节点 (Checked/Unchecked/Indeterminate)。
|
||||
3. **事件**:
|
||||
* 点击复选框 -> 更新状态 -> 触发联动 -> 发送 `ui:tree-node-check`。
|
||||
* 点击内容 -> 发送 `ui:tree-node-select`。
|
||||
|
||||
## 7. 国际化支持
|
||||
* 节点 `label` 必须是翻译键。
|
||||
* 组件订阅 `localeManager`,语言变更时自动刷新文本。
|
||||
|
||||
## 8. 使用示例
|
||||
```typescript
|
||||
// 通过 ModelTreeManager 创建
|
||||
const tree = engine.modelTree.createTree({
|
||||
data: [
|
||||
{ id: 'root', label: 'tree.root', children: [...] }
|
||||
],
|
||||
checkable: true
|
||||
});
|
||||
// 挂载到 DOM
|
||||
document.body.appendChild(tree.element);
|
||||
```
|
||||
305
docs-old/components/测量面板组件-MeasurePanel.md
Normal file
305
docs-old/components/测量面板组件-MeasurePanel.md
Normal file
@@ -0,0 +1,305 @@
|
||||
# MeasurePanel 组件详细文档
|
||||
|
||||
> 本文档详细描述 `MeasurePanel`(测量面板)组件的实现细节,包括 API、UI 结构、逻辑流程等,供后续维护/AI 重现。
|
||||
>
|
||||
> 重要说明:**本组件仅实现 UI,不实现真实测量算法**(不做拾取、画线、计算等)。测量结果通过对外方法注入,仅用于展示。
|
||||
|
||||
---
|
||||
|
||||
## 1. 组件概述
|
||||
|
||||
### 1.1 基本信息
|
||||
- **组件名称**:`MeasurePanel`
|
||||
- **文件路径**:`src/components/measure-panel/index.ts`
|
||||
- **类型定义**:`src/components/measure-panel/types.ts`
|
||||
- **样式文件**:`src/components/measure-panel/index.css`
|
||||
- **实现接口**:`IBimComponent`
|
||||
|
||||
### 1.2 在 SDK 中的位置
|
||||
- `MeasurePanel` 是内部 UI 组件
|
||||
- 由 `MeasureDialogManager` 创建并挂载到 `BimDialog` 中
|
||||
- 外部业务(SDK 使用者)不直接 import 组件类,统一通过 `engine.measure`(Manager)调用
|
||||
|
||||
### 1.3 配置项(单位/精度)与缓存策略(新增)
|
||||
- **创建 `MeasurePanel` 不传入单位/精度**
|
||||
- 默认配置由组件内部维护:
|
||||
- `unit`: `'mm'`
|
||||
- `precision`: `2`(即 `0.00`)
|
||||
- 组件初始化时会读取缓存(`localStorage`):
|
||||
- key:`bim-engine:measure:config`
|
||||
- 若缓存存在且合法,则使用缓存值覆盖默认配置
|
||||
- 若缓存不存在/解析失败,则使用默认配置
|
||||
- 用户在设置面板点击“保存设置”后,组件会写入缓存
|
||||
|
||||
---
|
||||
|
||||
## 2. 组件类 API 文档
|
||||
|
||||
### 2.1 构造函数
|
||||
|
||||
```typescript
|
||||
constructor(options?: MeasurePanelOptions)
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `options.defaultMode?`: 默认测量方式(不传默认 `distance`)
|
||||
- `options.defaultExpanded?`: 是否默认展开(不传默认 `false`,即只显示前 4 个)
|
||||
- `options.onModeChange?`: 用户切换测量方式时回调
|
||||
- `options.onClearAll?`: 用户点击“删除全部”时回调
|
||||
- `options.onSettings?`: 用户点击“设置”时回调
|
||||
|
||||
### 2.2 公共方法
|
||||
|
||||
#### `init(): void`
|
||||
- 初始化订阅(主题/语言),并刷新 UI 状态(展开/选中态/结果区)。
|
||||
|
||||
#### `setTheme(theme: ThemeConfig): void`
|
||||
- 将主题色映射到 CSS 变量(按钮背景、hover、active、文字、分割线等)。
|
||||
|
||||
#### `setLocales(): void`
|
||||
- 更新所有用户可见文本:
|
||||
- 8 个按钮的 tooltip(图标占位时 tooltip 是主要可读文本)
|
||||
- 展开/收起按钮 tooltip
|
||||
- “删除全部”文本
|
||||
- “设置”tooltip
|
||||
- “当前测量方式”显示文本
|
||||
- 主值 label(随模式变化)
|
||||
- X/Y/Z 标签
|
||||
|
||||
#### `destroy(): void`
|
||||
- 取消主题/语言订阅并移除 DOM。
|
||||
|
||||
#### `getActiveMode(): MeasureMode`
|
||||
- 获取当前选中的测量方式。
|
||||
|
||||
#### `switchMode(mode: MeasureMode): void`
|
||||
- **切换类型的方法**:切换当前测量方式(等价于 `setActiveMode`)。
|
||||
|
||||
#### `setActiveMode(mode: MeasureMode): void`
|
||||
- 设置当前测量方式,并触发 `onModeChange`(如果提供)。
|
||||
|
||||
#### `setResult(result: MeasureResult | null): void`
|
||||
- 外部注入测量结果:
|
||||
- `null`:清空显示(主值与 xyz 均显示 `--`)
|
||||
- 非 null:根据当前 mode 显示对应字段的值
|
||||
|
||||
#### `clearAll(): void`
|
||||
- 清空结果展示并触发 `onClearAll`(如果提供)。
|
||||
|
||||
#### `openSettings(): void`
|
||||
- 进入组件内部“设置面板”(单位/精度选择)。
|
||||
- 同时触发 `onSettings`(如果提供,作为外部监听)。
|
||||
|
||||
#### `getConfig(): MeasureConfig`
|
||||
- 获取当前测量配置(单位/精度)。
|
||||
|
||||
#### `setConfig(partial: Partial<MeasureConfig>, persist = false): void`
|
||||
- 更新配置:
|
||||
- `persist=false`:仅更新内存,不写缓存
|
||||
- `persist=true`:更新并写入 `localStorage`
|
||||
|
||||
#### `setExpanded(expanded: boolean): void`
|
||||
- 展开/收起按钮区(收起时只显示前 4 个)。
|
||||
|
||||
#### `getExpanded(): boolean`
|
||||
- 获取当前是否展开。
|
||||
|
||||
---
|
||||
|
||||
## 3. 分化组件说明
|
||||
|
||||
- 无
|
||||
|
||||
---
|
||||
|
||||
## 4. Manager API 文档(关联)
|
||||
|
||||
### 4.1 MeasureDialogManager(关联文件)
|
||||
- `src/managers/measure-dialog-manager.ts`
|
||||
|
||||
### 4.2 相关对外方法(本次新增/补齐)
|
||||
- `getActiveMode(): MeasureMode | null`
|
||||
- `switchMode(mode: MeasureMode): void`
|
||||
- `setResult(result: MeasureResult | null): void`
|
||||
- `clearAll(): void`
|
||||
- `openSettings(): void`
|
||||
|
||||
---
|
||||
|
||||
## 5. UI 详细描述
|
||||
|
||||
### 5.1 DOM 结构(核心)
|
||||
|
||||
```html
|
||||
<div class="bim-measure-panel">
|
||||
<!-- 主视图 -->
|
||||
<div class="bim-measure-main">
|
||||
<div class="bim-measure-tools">
|
||||
<div class="bim-measure-tool-grid">
|
||||
<!-- 8 个按钮:收起时隐藏后 4 个 -->
|
||||
<button class="bim-measure-tool-btn is-active" data-mode="distance">
|
||||
<span class="bim-measure-tool-icon">(圆形占位 svg)</span>
|
||||
</button>
|
||||
<!-- ... -->
|
||||
</div>
|
||||
|
||||
<div class="bim-measure-toggle">
|
||||
<button class="bim-measure-toggle-btn">
|
||||
<!-- 箭头 svg,展开时旋转 180deg -->
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bim-measure-result">
|
||||
<div class="bim-measure-row">
|
||||
<span class="label">当前测量方式:</span>
|
||||
<span class="value">距离</span>
|
||||
</div>
|
||||
|
||||
<div class="bim-measure-row">
|
||||
<span class="label">距离:</span>
|
||||
<span class="value">--</span>
|
||||
</div>
|
||||
|
||||
<div class="bim-measure-xyz">
|
||||
<div class="bim-measure-row"><span class="label">X:</span><span class="value">--</span></div>
|
||||
<div class="bim-measure-row"><span class="label">Y:</span><span class="value">--</span></div>
|
||||
<div class="bim-measure-row"><span class="label">Z:</span><span class="value">--</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bim-measure-footer">
|
||||
<button class="bim-measure-clear-btn">删除全部</button>
|
||||
<button class="bim-measure-settings-btn">(齿轮 svg)</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 设置视图(点击设置按钮进入) -->
|
||||
<div class="bim-measure-settings">
|
||||
<div class="bim-measure-settings-title">设置</div>
|
||||
|
||||
<div class="bim-measure-settings-row">
|
||||
<div class="label">单位:</div>
|
||||
<select class="bim-measure-settings-select">
|
||||
<option value="m">m</option>
|
||||
<option value="cm">cm</option>
|
||||
<option value="mm">mm</option>
|
||||
<option value="km">km</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="bim-measure-settings-row">
|
||||
<div class="label">精度:</div>
|
||||
<select class="bim-measure-settings-select">
|
||||
<option value="0">0</option>
|
||||
<option value="1">0.0</option>
|
||||
<option value="2">0.00</option>
|
||||
<option value="3">0.000</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="bim-measure-settings-actions">
|
||||
<button class="bim-measure-settings-save">保存设置</button>
|
||||
<button class="bim-measure-settings-cancel">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 5.2 CSS 类名说明
|
||||
- `.bim-measure-tool-grid`: 4 列网格布局
|
||||
- `.bim-measure-tool-btn.is-active`: 当前选中态
|
||||
- `.bim-measure-toggle-btn.is-expanded`: 展开态(箭头旋转)
|
||||
- `.bim-measure-result`: 结果区,顶部与底部用分割线隔开
|
||||
|
||||
---
|
||||
|
||||
## 6. 逻辑流程详细描述
|
||||
|
||||
### 6.1 初始化
|
||||
- 构造函数创建 DOM,但不订阅
|
||||
- `init()`:
|
||||
- 订阅 `localeManager`、`themeManager`
|
||||
- 调用 `setLocales()`、`setTheme()`
|
||||
- 应用展开状态(隐藏/显示后 4 个按钮)
|
||||
- 应用选中态
|
||||
- 渲染结果(初始为 `--`)
|
||||
|
||||
### 6.2 切换测量方式
|
||||
- 点击按钮或调用 `switchMode/setActiveMode`
|
||||
- 更新内部 `activeMode`
|
||||
- 刷新按钮选中态
|
||||
- 更新“当前测量方式”文本
|
||||
- 更新主值 label
|
||||
- 触发 `onModeChange`(若提供)
|
||||
- 重新渲染结果
|
||||
|
||||
### 6.3 注入结果
|
||||
- 调用 `setResult(result)`
|
||||
- 保存 result 并刷新结果区:
|
||||
- 主值:根据 mode 显示对应字段
|
||||
- xyz:无则显示 `--`
|
||||
|
||||
---
|
||||
|
||||
## 7. 国际化支持
|
||||
|
||||
### 7.1 使用的翻译键(核心)
|
||||
- `measure.modes.*`:8 种模式名
|
||||
- `measure.actions.*`:展开/收起/删除全部/设置
|
||||
- `measure.labels.*`:当前方式、X/Y/Z、主值 label
|
||||
- `measure.units.*`:mm/°/m³/% 等单位
|
||||
|
||||
---
|
||||
|
||||
## 8. 主题支持
|
||||
|
||||
### 8.1 CSS 变量(核心)
|
||||
- `--bim-measure-border`
|
||||
- `--bim-measure-divider`
|
||||
- `--bim-measure-btn-bg` / `--bim-measure-btn-hover-bg` / `--bim-measure-btn-active-bg`
|
||||
- `--bim-measure-label-color` / `--bim-measure-value-color`
|
||||
- `--bim-measure-icon-color`
|
||||
|
||||
---
|
||||
|
||||
## 9. 使用示例(通过 Manager)
|
||||
|
||||
```typescript
|
||||
// 通过工具栏点击“测量”按钮打开弹窗后:外部可以这样注入展示数据
|
||||
engine.measure.switchMode('angle');
|
||||
engine.measure.setResult({ angleDeg: 12.34, xyz: { x: 1, y: 2, z: 3 } });
|
||||
|
||||
// 清空
|
||||
engine.measure.clearAll();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 实现细节(供 AI 重现)
|
||||
|
||||
### 10.1 关键点
|
||||
- 模式列表严格按需求顺序渲染
|
||||
- 收起时隐藏后 4 个按钮(通过 `style.display = 'none'`)
|
||||
- 图标占位统一用圆形 SVG
|
||||
- 主值显示使用 `formatWithUnit`(单位走国际化)
|
||||
|
||||
---
|
||||
|
||||
## 11. 类型定义
|
||||
|
||||
见 `src/components/measure-panel/types.ts`:
|
||||
- `MeasureMode`
|
||||
- `MeasureResult`
|
||||
- `MeasurePanelOptions`
|
||||
|
||||
---
|
||||
|
||||
## 12. 文件清单
|
||||
|
||||
- `src/components/measure-panel/index.ts`
|
||||
- `src/components/measure-panel/index.css`
|
||||
- `src/components/measure-panel/types.ts`
|
||||
- 关联:`src/managers/measure-dialog-manager.ts`
|
||||
|
||||
|
||||
594
docs-old/components/漫游控制面板组件-WalkControlPanel.md
Normal file
594
docs-old/components/漫游控制面板组件-WalkControlPanel.md
Normal file
@@ -0,0 +1,594 @@
|
||||
# WalkControlPanel 组件详细文档
|
||||
|
||||
> 本文档详细描述 WalkControlPanel 组件的实现细节,包括 API、UI 结构、逻辑流程等,供 AI 根据文档重现组件。
|
||||
|
||||
---
|
||||
|
||||
## 1. 组件概述
|
||||
|
||||
### 1.1 基本信息
|
||||
- **组件名称**: `WalkControlPanel`
|
||||
- **文件路径**: `src/components/walk-control-panel/index.ts`
|
||||
- **类型定义**: `src/components/walk-control-panel/types.ts`
|
||||
- **样式文件**: `src/components/walk-control-panel/index.css`
|
||||
- **实现接口**: `IBimComponent`
|
||||
- **用途**: 渲染漫游控制面板,提供平面图切换、路径漫游、人物漫游三种模式,以及速度、重力、碰撞、角色模型、行走模式等设置。
|
||||
- **特点**: 纯 UI 组件,通过回调函数通知外部状态变化,支持主题和国际化。
|
||||
|
||||
### 1.2 在 SDK 中的位置
|
||||
- WalkControlPanel 组件通常由 `WalkControlManager` 管理(如果存在)
|
||||
- 也可以单独实例化并挂载到任何容器中
|
||||
- 用于 3D 场景的漫游控制界面
|
||||
|
||||
---
|
||||
|
||||
## 2. 组件类 API 文档
|
||||
|
||||
### 2.1 构造函数
|
||||
|
||||
```typescript
|
||||
constructor(options: WalkControlPanelOptions = {})
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `options`: `WalkControlPanelOptions` - 漫游控制面板配置选项(可选)
|
||||
|
||||
**WalkControlPanelOptions 定义**:
|
||||
```typescript
|
||||
interface WalkControlPanelOptions {
|
||||
/** 平面图切换回调 */
|
||||
onPlanViewToggle?: (isActive: boolean) => void;
|
||||
/** 路径漫游模式切换回调 */
|
||||
onPathModeToggle?: (isActive: boolean) => void;
|
||||
/** 漫游模式切换回调 */
|
||||
onWalkModeToggle?: (isActive: boolean) => void;
|
||||
/** 速度变化回调 */
|
||||
onSpeedChange?: (speed: number) => void;
|
||||
/** 重力切换回调 */
|
||||
onGravityToggle?: (enabled: boolean) => void;
|
||||
/** 碰撞切换回调 */
|
||||
onCollisionToggle?: (enabled: boolean) => void;
|
||||
/** 角色模型变化回调 */
|
||||
onCharacterModelChange?: (model: CharacterModel) => void;
|
||||
/** 行走模式变化回调 */
|
||||
onWalkModeChange?: (mode: WalkMode) => void;
|
||||
/** 退出回调 */
|
||||
onExit?: () => void;
|
||||
|
||||
/** 默认速度 (1-10) */
|
||||
defaultSpeed?: number;
|
||||
/** 默认重力状态 */
|
||||
defaultGravity?: boolean;
|
||||
/** 默认碰撞状态 */
|
||||
defaultCollision?: boolean;
|
||||
/** 默认角色模型 */
|
||||
defaultCharacterModel?: CharacterModel;
|
||||
/** 默认行走模式 */
|
||||
defaultWalkMode?: WalkMode;
|
||||
}
|
||||
```
|
||||
|
||||
**行为**:
|
||||
- 创建面板 DOM 结构
|
||||
- 保存配置选项
|
||||
- 初始化状态
|
||||
|
||||
### 2.2 公共方法
|
||||
|
||||
#### `init(): void`
|
||||
初始化组件(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 创建并渲染 DOM 结构
|
||||
- 订阅语言变更:`localeManager.subscribe()`
|
||||
- 订阅主题变更:`themeManager.subscribe()`
|
||||
- 更新初始视图状态
|
||||
|
||||
#### `setTheme(theme: ThemeConfig): void`
|
||||
设置主题(实现 `IBimComponent` 接口)
|
||||
|
||||
**参数**:
|
||||
- `theme`: `ThemeConfig`
|
||||
|
||||
**功能**:
|
||||
- 将主题颜色映射到 CSS 变量:
|
||||
- `--bim-walk-control-bg` ← `theme.panelBackground`
|
||||
- `--bim-walk-btn-hover` ← `theme.componentHover`
|
||||
- `--bim-walk-btn-active` ← `theme.componentActive`
|
||||
- `--bim-primary-color` ← `theme.primary`
|
||||
- `--bim-primary-hover` ← `theme.primaryHover`
|
||||
- `--bim-icon-color` ← `theme.icon`
|
||||
- `--bim-text-color` ← `theme.textPrimary`
|
||||
- `--bim-divider-color` ← `theme.border`
|
||||
- 以及其他速度控制、下拉框相关的主题变量
|
||||
|
||||
#### `setLocales(): void`
|
||||
设置语言(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 更新速度标签文本:`t('walkControl.speed')`
|
||||
- 更新复选框标签:`t('walkControl.gravity')`, `t('walkControl.collision')`
|
||||
- 更新角色模型下拉框选项和标签
|
||||
- 更新行走模式下拉框选项和标签
|
||||
- 更新退出按钮文本:`t('walkControl.exit')`
|
||||
|
||||
#### `destroy(): void`
|
||||
销毁组件(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 取消语言和主题订阅
|
||||
- 从 DOM 中移除自身元素
|
||||
|
||||
#### `setPlanViewActive(active: boolean): void`
|
||||
设置平面图按钮激活状态
|
||||
|
||||
**参数**:
|
||||
- `active`: boolean - 是否激活
|
||||
|
||||
**功能**:
|
||||
- 更新内部状态
|
||||
- 更新按钮视觉状态
|
||||
|
||||
#### `setPathModeActive(active: boolean): void`
|
||||
设置路径模式按钮激活状态
|
||||
|
||||
**参数**:
|
||||
- `active`: boolean - 是否激活
|
||||
|
||||
**功能**:
|
||||
- 更新模式状态
|
||||
- 更新按钮视觉状态
|
||||
- 路径模式激活时禁用重力和碰撞选项
|
||||
|
||||
#### `getState(): WalkControlState`
|
||||
获取当前状态
|
||||
|
||||
**返回**: `WalkControlState` - 当前控制面板状态的副本
|
||||
|
||||
---
|
||||
|
||||
## 3. 分化组件说明
|
||||
|
||||
**WalkControlPanel 没有子类或分化组件**。
|
||||
|
||||
---
|
||||
|
||||
## 4. Manager API 文档
|
||||
|
||||
目前 WalkControlPanel 没有专门的 Manager,通常由使用方直接创建和管理。
|
||||
未来可以创建 `WalkControlManager` 来统一管理该组件的实例。
|
||||
|
||||
---
|
||||
|
||||
## 5. UI 详细描述
|
||||
|
||||
### 5.1 DOM 结构
|
||||
|
||||
```html
|
||||
<div class="walk-control-panel">
|
||||
<!-- 左侧按钮区 -->
|
||||
<div class="walk-control-left">
|
||||
<button class="walk-icon-btn walk-icon-btn-plan-view [active]">
|
||||
[平面图 SVG图标]
|
||||
</button>
|
||||
<button class="walk-icon-btn walk-icon-btn-path [active]">
|
||||
[路径 SVG图标]
|
||||
</button>
|
||||
<button class="walk-icon-btn walk-icon-btn-walk [active]">
|
||||
[漫游 SVG图标]
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 分割线 -->
|
||||
<div class="walk-divider"></div>
|
||||
|
||||
<!-- 中间设置区 -->
|
||||
<div class="walk-control-settings">
|
||||
<!-- 速度控件(路径模式显示) -->
|
||||
<div class="walk-speed-control">
|
||||
<label class="walk-speed-label">速度</label>
|
||||
<div class="walk-speed-group">
|
||||
<button class="walk-speed-btn">-</button>
|
||||
<div class="walk-speed-display">1X</div>
|
||||
<button class="walk-speed-btn">+</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 角色模型选择(漫游模式显示) -->
|
||||
<div class="walk-select-wrapper walk-select-wrapper-character-model">
|
||||
<label class="walk-select-label">角色模型</label>
|
||||
<select class="walk-select walk-select-character-model">
|
||||
<option value="construction-worker">建筑工人</option>
|
||||
<option value="office-male">办公室男性</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 行走模式选择(漫游模式显示) -->
|
||||
<div class="walk-select-wrapper walk-select-wrapper-walk-mode">
|
||||
<label class="walk-select-label">行走模式</label>
|
||||
<select class="walk-select walk-select-walk-mode">
|
||||
<option value="walk">行走</option>
|
||||
<option value="run">奔跑</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 重力复选框 -->
|
||||
<label class="walk-checkbox-wrapper walk-checkbox-gravity">
|
||||
<input type="checkbox" class="walk-checkbox" [disabled]>
|
||||
<span class="walk-checkbox-label">重力</span>
|
||||
</label>
|
||||
|
||||
<!-- 碰撞复选框 -->
|
||||
<label class="walk-checkbox-wrapper walk-checkbox-collision">
|
||||
<input type="checkbox" class="walk-checkbox" [disabled]>
|
||||
<span class="walk-checkbox-label">碰撞</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- 分割线 -->
|
||||
<div class="walk-divider"></div>
|
||||
|
||||
<!-- 右侧退出按钮 -->
|
||||
<button class="walk-exit-btn">退出</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 5.2 CSS 类名和样式
|
||||
|
||||
#### `.walk-control-panel` (根容器)
|
||||
- `display: flex`, `align-items: center`
|
||||
- `gap: 20px`, `padding: 8px 16px`
|
||||
- `background`: `var(--bim-walk-control-bg)`
|
||||
- `border-radius: 8px`
|
||||
- `user-select: none`
|
||||
|
||||
#### `.walk-icon-btn` (左侧图标按钮)
|
||||
- `width: 48px`, `height: 48px`
|
||||
- `padding: 8px` (实际图标 32x32)
|
||||
- `display: flex`, `align-items: center`, `justify-content: center`
|
||||
- `background: transparent`
|
||||
- `border: 2px solid transparent`, `border-radius: 6px`
|
||||
- `cursor: pointer`, `transition: all 0.2s`
|
||||
- `color`: `var(--bim-icon-color)`
|
||||
|
||||
#### `.walk-icon-btn:hover`
|
||||
- `background`: `var(--bim-walk-btn-hover)`
|
||||
|
||||
#### `.walk-icon-btn.active`
|
||||
- `background`: `var(--bim-walk-btn-active)`
|
||||
|
||||
#### `.walk-icon-btn svg`
|
||||
- `width: 32px`, `height: 32px`
|
||||
|
||||
#### `.walk-divider` (分割线)
|
||||
- `width: 1px`, `height: 40px`
|
||||
- `background`: `var(--bim-divider-color)`
|
||||
- `flex-shrink: 0`
|
||||
|
||||
#### `.walk-speed-control` (速度控件)
|
||||
- `display: flex`, `align-items: center`, `gap: 12px`
|
||||
|
||||
#### `.walk-speed-btn` (速度按钮)
|
||||
- `width: 32px`, `height: 32px`
|
||||
- `background`: `var(--bim-speed-btn-bg)`
|
||||
- `border: none`, `border-radius: 4px`
|
||||
- `cursor: pointer`
|
||||
- `:disabled` 时 `opacity: 0.5`, `cursor: not-allowed`
|
||||
|
||||
#### `.walk-checkbox-wrapper` (复选框包装)
|
||||
- `display: flex`, `align-items: center`, `gap: 8px`
|
||||
- `cursor: pointer`
|
||||
|
||||
#### `.walk-select-wrapper` (下拉框包装)
|
||||
- `display: flex`, `align-items: center`, `gap: 8px`
|
||||
|
||||
#### `.walk-exit-btn` (退出按钮)
|
||||
- `padding: 10px 24px`
|
||||
- `background`: `var(--bim-primary-color)`
|
||||
- `border: none`, `border-radius: 6px`
|
||||
- `color: #fff`, `font-size: 14px`, `font-weight: 600`
|
||||
- `cursor: pointer`, `transition: all 0.2s`
|
||||
|
||||
---
|
||||
|
||||
## 6. 逻辑流程详细描述
|
||||
|
||||
### 6.1 初始化流程 (`init`)
|
||||
|
||||
1. **创建面板**(`createPanel`):
|
||||
- 创建根容器 `.walk-control-panel`
|
||||
- 创建左侧按钮区(`createLeftButtons`)
|
||||
- 创建中间设置区(`createSettingsContainer`)
|
||||
- 创建右侧退出按钮(`createExitButton`)
|
||||
- 组装各部分并添加分割线
|
||||
|
||||
2. **订阅变更**:
|
||||
- 订阅语言变更:`localeManager.subscribe(() => this.setLocales())`
|
||||
- 订阅主题变更:`themeManager.subscribe((theme) => this.setTheme(theme))`
|
||||
|
||||
3. **初始设置**:
|
||||
- 调用 `setLocales()` 设置初始文本
|
||||
- 调用 `setTheme()` 应用当前主题
|
||||
- 调用 `updateSettingsView()` 根据初始模式显示/隐藏控件
|
||||
|
||||
### 6.2 模式切换流程
|
||||
|
||||
#### 模式类型
|
||||
- `'none'`: 无模式
|
||||
- `'path'`: 路径漫游模式
|
||||
- `'walk'`: 人物漫游模式
|
||||
|
||||
#### 模式切换逻辑 (`setMode`)
|
||||
1. **保存旧模式**:用于触发关闭事件
|
||||
|
||||
2. **触发旧模式关闭事件**:
|
||||
- 如果从 `'walk'` 切换出去,触发 `onWalkModeToggle(false)`
|
||||
- 如果从 `'path'` 切换出去,触发 `onPathModeToggle(false)`
|
||||
|
||||
3. **更新模式状态**:`this.state.mode = newMode`
|
||||
|
||||
4. **特殊处理**:
|
||||
- 路径模式时:禁用重力和碰撞复选框,并设置为 false
|
||||
- 其他模式:启用重力和碰撞复选框
|
||||
|
||||
5. **更新视图**:
|
||||
- `updateButtonStates()`: 更新按钮激活状态
|
||||
- `updateSettingsView()`: 显示/隐藏相应的设置控件
|
||||
- `updateSpeedButtonStates()`: 更新速度按钮禁用状态
|
||||
|
||||
### 6.3 设置视图更新 (`updateSettingsView`)
|
||||
|
||||
根据当前模式动态显示/隐藏控件:
|
||||
|
||||
**漫游模式 (`'walk'`)**:
|
||||
- 隐藏速度控件
|
||||
- 显示角色模型选择
|
||||
- 显示行走模式选择
|
||||
- 显示重力复选框
|
||||
- 显示碰撞复选框
|
||||
|
||||
**路径模式 (`'path'`)** 或 **无模式 (`'none'`)**:
|
||||
- 显示速度控件
|
||||
- 隐藏角色模型选择
|
||||
- 隐藏行走模式选择
|
||||
- 显示重力复选框
|
||||
- 显示碰撞复选框
|
||||
|
||||
### 6.4 图标管理
|
||||
|
||||
使用统一的图标管理器 (`icon-manager.ts`) 获取 SVG 图标:
|
||||
|
||||
```typescript
|
||||
private getIconSVG(type: string): string {
|
||||
const icons: Record<string, string> = {
|
||||
'plan-view': getIcon('地图'), // 平面图/鸟瞰
|
||||
'path': getIcon('地图'), // 路径漫游
|
||||
'walk': getIcon('漫游') // 人物漫游
|
||||
};
|
||||
return icons[type] || '';
|
||||
}
|
||||
```
|
||||
|
||||
**重要**: 所有按钮图标尺寸统一为 32x32,与 toolbar 底部工具栏保持一致。
|
||||
|
||||
---
|
||||
|
||||
## 7. 国际化支持
|
||||
|
||||
### 7.1 使用的翻译键
|
||||
|
||||
```typescript
|
||||
// 翻译键路径
|
||||
'walkControl.speed' // 速度标签
|
||||
'walkControl.gravity' // 重力标签
|
||||
'walkControl.collision' // 碰撞标签
|
||||
'walkControl.characterModel.label' // 角色模型标签
|
||||
'walkControl.characterModel.constructionWorker' // 建筑工人
|
||||
'walkControl.characterModel.officeMale' // 办公室男性
|
||||
'walkControl.walkMode.label' // 行走模式标签
|
||||
'walkControl.walkMode.walk' // 行走
|
||||
'walkControl.walkMode.run' // 奔跑
|
||||
'walkControl.exit' // 退出按钮
|
||||
```
|
||||
|
||||
### 7.2 实现方式
|
||||
- 使用 `src/services/locale.ts` 中的 `t()` 函数
|
||||
- 组件初始化时订阅语言变更,变更发生时更新所有文本 (`setLocales`)
|
||||
- 动态创建的下拉框选项也使用 `t()` 函数获取翻译文本
|
||||
|
||||
---
|
||||
|
||||
## 8. 主题支持
|
||||
|
||||
### 8.1 变量映射
|
||||
|
||||
在 `setTheme` 中设置内联样式变量:
|
||||
- `--bim-walk-control-bg`: 面板背景色
|
||||
- `--bim-walk-btn-hover`: 按钮悬停背景
|
||||
- `--bim-walk-btn-active`: 按钮激活背景
|
||||
- `--bim-primary-color`: 主色(退出按钮)
|
||||
- `--bim-primary-hover`: 主色悬停
|
||||
- `--bim-icon-color`: 图标颜色
|
||||
- `--bim-text-color`: 文本颜色
|
||||
- `--bim-divider-color`: 分割线颜色
|
||||
- `--bim-speed-group-bg`: 速度组背景
|
||||
- `--bim-speed-btn-bg`: 速度按钮背景
|
||||
- `--bim-speed-btn-hover`: 速度按钮悬停
|
||||
- `--bim-select-bg`: 下拉框背景
|
||||
- `--bim-select-border`: 下拉框边框
|
||||
- `--bim-select-option-bg`: 下拉框选项背景
|
||||
|
||||
---
|
||||
|
||||
## 9. 使用示例
|
||||
|
||||
### 9.1 基本使用
|
||||
|
||||
```typescript
|
||||
import { WalkControlPanel } from './components/walk-control-panel';
|
||||
|
||||
// 创建实例
|
||||
const walkPanel = new WalkControlPanel({
|
||||
defaultSpeed: 1,
|
||||
defaultGravity: false,
|
||||
defaultCollision: false,
|
||||
onPlanViewToggle: (isActive) => {
|
||||
console.log('平面图模式:', isActive);
|
||||
},
|
||||
onPathModeToggle: (isActive) => {
|
||||
console.log('路径模式:', isActive);
|
||||
// 启用/禁用路径漫游功能
|
||||
},
|
||||
onWalkModeToggle: (isActive) => {
|
||||
console.log('漫游模式:', isActive);
|
||||
// 启用/禁用人物漫游功能
|
||||
},
|
||||
onSpeedChange: (speed) => {
|
||||
console.log('速度:', speed);
|
||||
// 更新漫游速度
|
||||
},
|
||||
onGravityToggle: (enabled) => {
|
||||
console.log('重力:', enabled);
|
||||
},
|
||||
onCollisionToggle: (enabled) => {
|
||||
console.log('碰撞:', enabled);
|
||||
},
|
||||
onCharacterModelChange: (model) => {
|
||||
console.log('角色模型:', model);
|
||||
},
|
||||
onWalkModeChange: (mode) => {
|
||||
console.log('行走模式:', mode);
|
||||
},
|
||||
onExit: () => {
|
||||
console.log('退出漫游');
|
||||
// 销毁面板,退出漫游模式
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化
|
||||
walkPanel.init();
|
||||
|
||||
// 挂载到 DOM
|
||||
document.body.appendChild(walkPanel.element);
|
||||
```
|
||||
|
||||
### 9.2 外部控制状态
|
||||
|
||||
```typescript
|
||||
// 外部设置平面图激活状态
|
||||
walkPanel.setPlanViewActive(true);
|
||||
|
||||
// 外部设置路径模式激活状态
|
||||
walkPanel.setPathModeActive(true);
|
||||
|
||||
// 获取当前状态
|
||||
const state = walkPanel.getState();
|
||||
console.log('当前模式:', state.mode);
|
||||
console.log('当前速度:', state.speed);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 实现细节(供 AI 重现)
|
||||
|
||||
### 10.1 状态管理
|
||||
|
||||
组件内部维护一个状态对象 `WalkControlState`:
|
||||
|
||||
```typescript
|
||||
private state: WalkControlState = {
|
||||
mode: 'none', // 当前模式
|
||||
isPlanViewActive: false, // 平面图是否激活
|
||||
speed: 1, // 移动速度 1-10
|
||||
gravity: false, // 重力是否启用
|
||||
collision: false, // 碰撞是否启用
|
||||
characterModel: 'construction-worker', // 角色模型
|
||||
walkMode: 'walk' // 行走模式
|
||||
};
|
||||
```
|
||||
|
||||
状态变更时:
|
||||
1. 更新内部状态
|
||||
2. 更新 UI 视觉效果
|
||||
3. 触发对应的回调函数
|
||||
|
||||
### 10.2 模式互斥逻辑
|
||||
|
||||
三个按钮(平面图、路径、漫游)中:
|
||||
- **平面图**是独立的开关,不影响模式
|
||||
- **路径**和**漫游**是互斥的,激活一个会关闭另一个
|
||||
- 点击已激活的模式按钮会关闭该模式(回到 `'none'`)
|
||||
|
||||
### 10.3 路径模式的特殊处理
|
||||
|
||||
当进入路径模式时:
|
||||
1. 自动禁用并取消勾选重力和碰撞
|
||||
2. 禁用重力和碰撞复选框(设置 `disabled` 属性)
|
||||
3. 退出路径模式时重新启用这两个复选框
|
||||
|
||||
### 10.4 速度控制
|
||||
|
||||
- 速度范围: 1-10
|
||||
- 减速按钮在速度为 1 时禁用
|
||||
- 加速按钮在速度为 10 时禁用
|
||||
- 速度显示格式: `${speed}X`
|
||||
|
||||
### 10.5 下拉框动态创建
|
||||
|
||||
角色模型和行走模式的下拉框选项在 `setLocales()` 中动态创建:
|
||||
1. 清空现有选项:`select.innerHTML = ''`
|
||||
2. 创建新选项,使用 `t()` 获取翻译文本
|
||||
3. 根据当前状态设置选中项
|
||||
|
||||
这样可以确保语言切换时下拉框文本也会更新。
|
||||
|
||||
---
|
||||
|
||||
## 11. 类型定义
|
||||
|
||||
### 11.1 WalkControlMode
|
||||
```typescript
|
||||
export type WalkControlMode = 'none' | 'path' | 'walk';
|
||||
```
|
||||
|
||||
### 11.2 CharacterModel
|
||||
```typescript
|
||||
export type CharacterModel = 'office-male' | 'construction-worker';
|
||||
```
|
||||
|
||||
### 11.3 WalkMode
|
||||
```typescript
|
||||
export type WalkMode = 'walk' | 'run';
|
||||
```
|
||||
|
||||
### 11.4 WalkControlState
|
||||
```typescript
|
||||
export interface WalkControlState {
|
||||
mode: WalkControlMode;
|
||||
isPlanViewActive: boolean;
|
||||
speed: number;
|
||||
gravity: boolean;
|
||||
collision: boolean;
|
||||
characterModel: CharacterModel;
|
||||
walkMode: WalkMode;
|
||||
}
|
||||
```
|
||||
|
||||
### 11.5 WalkControlPanelOptions
|
||||
见 2.1 节
|
||||
|
||||
---
|
||||
|
||||
## 12. 文件清单
|
||||
|
||||
- `src/components/walk-control-panel/index.ts`: 组件核心逻辑
|
||||
- `src/components/walk-control-panel/index.css`: 组件样式
|
||||
- `src/components/walk-control-panel/types.ts`: 类型定义
|
||||
|
||||
---
|
||||
|
||||
## 13. 更新记录
|
||||
|
||||
| 日期 | 修改内容 | 修改人 |
|
||||
| ---------- | ----------------------------------------- | ------------ |
|
||||
| 2025-12-25 | 创建漫游控制面板组件文档,集成图标管理器 | AI Assistant |
|
||||
318
docs-old/components/菜单组件-Menu.md
Normal file
318
docs-old/components/菜单组件-Menu.md
Normal file
@@ -0,0 +1,318 @@
|
||||
# Menu 组件详细文档
|
||||
|
||||
> 本文档详细描述 Menu 组件的实现细节,包括 API、UI 结构、逻辑流程等,供 AI 根据文档重现组件。
|
||||
|
||||
---
|
||||
|
||||
## 1. 组件概述
|
||||
|
||||
### 1.1 基本信息
|
||||
- **组件名称**: `BimMenu`
|
||||
- **文件路径**: `src/components/menu/index.ts`
|
||||
- **类型定义**: `src/components/menu/item.ts` (配置), `src/components/menu/types.ts` (选项)
|
||||
- **样式文件**: `src/components/menu/index.css`
|
||||
- **实现接口**: `IBimComponent`, `IRightKeyContent`
|
||||
- **用途**: 渲染一组菜单项,支持分组、排序、图标、快捷键提示和无限级递归子菜单。
|
||||
- **特点**: 纯数据驱动(基于 `MenuItemConfig`),内置国际化支持。
|
||||
|
||||
### 1.2 在 SDK 中的位置
|
||||
- Menu 组件主要由 `RightKeyManager` 使用,作为右键菜单的内容载体。
|
||||
- 也可以单独实例化并挂载到任何容器中。
|
||||
- `RightKeyManager` 位于 `src/managers/right-key-manager.ts`。
|
||||
|
||||
---
|
||||
|
||||
## 2. 组件类 API 文档
|
||||
|
||||
### 2.1 构造函数
|
||||
|
||||
```typescript
|
||||
constructor(options: MenuOptions)
|
||||
```
|
||||
|
||||
**参数**:
|
||||
- `options`: `MenuOptions` - 菜单配置选项
|
||||
|
||||
**MenuOptions 定义**:
|
||||
```typescript
|
||||
interface MenuOptions {
|
||||
items: MenuItemConfig[]; // 菜单项配置列表
|
||||
groupOrder?: string[]; // 分组显示顺序
|
||||
}
|
||||
```
|
||||
|
||||
**行为**:
|
||||
- 创建根元素 `<ul>`
|
||||
- 保存配置选项
|
||||
|
||||
### 2.2 公共方法
|
||||
|
||||
#### `init(): void`
|
||||
初始化组件(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 调用 `render()` 渲染 DOM 结构
|
||||
- 订阅语言变更:`localeManager.subscribe()`
|
||||
- 订阅主题变更:`themeManager.subscribe()`(虽然目前主要通过 CSS 变量,但保留订阅以备扩展)
|
||||
|
||||
#### `setTheme(theme: ThemeConfig): void`
|
||||
设置主题(实现 `IBimComponent` 接口)
|
||||
|
||||
**参数**:
|
||||
- `theme`: `ThemeConfig`
|
||||
|
||||
**功能**:
|
||||
- 将主题颜色映射到 CSS 变量
|
||||
- `--bim-ui_bg_color` ← `theme.panelBackground`
|
||||
- `--bim-ui_text_primary` ← `theme.textPrimary`
|
||||
- `--bim-ui_border_color` ← `theme.border`
|
||||
- `--bim-ui_bg_hover` ← `theme.componentHover`
|
||||
|
||||
#### `setLocales(): void`
|
||||
设置语言(实现 `IBimComponent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 清空当前 DOM
|
||||
- 重新调用 `render()`,使 `t()` 函数获取最新的翻译文本
|
||||
|
||||
#### `destroy(): void`
|
||||
销毁组件(实现 `IBimComponent`, `IRightKeyContent` 接口)
|
||||
|
||||
**功能**:
|
||||
- 取消语言和主题订阅
|
||||
- 关闭并销毁所有打开的子菜<E5AD90><E88F9C>
|
||||
- 从 DOM 中移除自身元素
|
||||
|
||||
#### `getElement(): HTMLElement`
|
||||
获取组件根元素(实现 `IRightKeyContent` 接口)
|
||||
|
||||
**返回**: `HTMLElement` (根 `<ul>` 元素)
|
||||
|
||||
**功能**:
|
||||
- 允许父容器(如 `BimRightKey`)获取并挂载此菜单
|
||||
|
||||
---
|
||||
|
||||
## 3. 分化组件说明
|
||||
|
||||
**BimMenu 没有子类或分化组件**。它通过递归自身来实现多级菜单。
|
||||
|
||||
---
|
||||
|
||||
## 4. Manager API 文档
|
||||
|
||||
参见 [RightKey 组件文档](./right-key.md) 中的 `RightKeyManager`。`BimMenu` 本身是一个纯 UI 组件,通常不直接通过 Manager 管理,而是被 `RightKeyManager` 动态创建和销毁。
|
||||
|
||||
---
|
||||
|
||||
## 5. UI 详细描述
|
||||
|
||||
### 5.1 DOM 结构
|
||||
|
||||
```html
|
||||
<ul class="bim-menu">
|
||||
<!-- 分组 1 -->
|
||||
<li class="bim-menu-item [disabled]">
|
||||
<div class="bim-menu-item-icon">[SVG图标]</div>
|
||||
<div class="bim-menu-item-label">菜单文本</div>
|
||||
<!-- 如果有子菜单 -->
|
||||
<div class="bim-menu-item-arrow">
|
||||
<svg>...</svg> <!-- 右箭头 -->
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- 分组分割线 -->
|
||||
<li class="bim-menu-divider"></li>
|
||||
|
||||
<!-- 分组 2 -->
|
||||
<li class="bim-menu-item">...</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
### 5.2 CSS 类名和样式
|
||||
|
||||
#### `.bim-menu` (根容器)
|
||||
- `display: flex`, `flex-direction: column`
|
||||
- `background`: `var(--bim-ui_bg_color)`
|
||||
- `border-radius: 4px`
|
||||
- `padding: 4px 0`, `margin: 0`, `list-style: none` (关键:移除列表默认样式)
|
||||
- `min-width: 160px`
|
||||
- `box-shadow`: `0 4px 12px rgba(0,0,0,0.2)`
|
||||
- `user-select: none`
|
||||
|
||||
#### `.bim-menu-item` (菜单项)
|
||||
- `display: flex`, `align-items: center`
|
||||
- `padding: 6px 12px`
|
||||
- `cursor: pointer`
|
||||
- `position: relative`
|
||||
- `color`: `var(--bim-ui_text_primary)`
|
||||
|
||||
#### `.bim-menu-item:hover`
|
||||
- `background-color`: `var(--bim-ui_bg_hover)`
|
||||
|
||||
#### `.bim-menu-item.disabled`
|
||||
- `opacity: 0.5`
|
||||
- `cursor: not-allowed`
|
||||
- `pointer-events: none`
|
||||
|
||||
#### `.bim-menu-divider` (分割线)
|
||||
- `height: 1px`
|
||||
- `background-color`: `var(--bim-ui_border_color)`
|
||||
- `margin: 4px 0`
|
||||
|
||||
---
|
||||
|
||||
## 6. 逻辑流程详细描述
|
||||
|
||||
### 6.1 渲染流程 (`render`)
|
||||
|
||||
1. **数据分桶**: 遍历 `items`,根据 `item.group` (默认为 'default') 将菜单项放入不同的数组中。
|
||||
2. **确定顺序**:
|
||||
- 如果提供了 `groupOrder`,优先按其顺序排列组。
|
||||
- 未指定的组按遍历顺序追加。
|
||||
3. **渲染分组**:
|
||||
- 遍历排序后的组键。
|
||||
- 如果不是第一组,先插入一个 `.bim-menu-divider`。
|
||||
- 获取组内项,根据 `item.order` 升序排序。
|
||||
- 遍历组内项,如果 `item.visible !== false`,调用 `createItemElement` 创建 DOM。
|
||||
|
||||
### 6.2 交互流程
|
||||
|
||||
#### 点击事件
|
||||
- **绑定**: 在 `.bim-menu-item` 上绑定 `click`。
|
||||
- **逻辑**:
|
||||
- `e.stopPropagation()`: 阻止冒泡。
|
||||
- 检查 `!hasChildren`: 只有叶子节点才触发点击。
|
||||
- 调用 `item.onClick?.()`。
|
||||
- **注意**: 点击后,通常期望菜单关闭。这依赖于 `RightKeyManager` 或外部逻辑(通过 `onClick` 内部调用关闭,或者点击触发全局关闭)。
|
||||
|
||||
#### 子菜单展开 (`mouseenter`)
|
||||
- **触发**: 鼠标移入带有子项的菜单项。
|
||||
- **逻辑**:
|
||||
- 调用 `closeSubMenu()` 关闭当前可能已打开的其他子菜单。
|
||||
- 计算位置:通常位于父项右侧 (`rect.right`),顶部对齐 (`rect.top`)。
|
||||
- 创建子菜单容器 `div` (fixed 定位, z-index 10001)。
|
||||
- **关键修复**: 在容器上绑定 `mousedown` 并 `stopPropagation`,防止触发 `BimRightKey` 的全局关闭逻辑。
|
||||
- 实例化新的 `BimMenu` (递归) 并 `init()`。
|
||||
- 将新菜单挂载到容器,容器挂载到 `document.body`。
|
||||
- 保存引用到 `this.activeSubMenu`。
|
||||
- **边界检测**: 如果右侧超出屏幕,改为向左展开。
|
||||
|
||||
#### 子菜单关闭
|
||||
- **触发**: 鼠标移入**不带**子项的菜单项。
|
||||
- **逻辑**: 调用 `closeSubMenu()`,销毁实例并移除 DOM。
|
||||
|
||||
---
|
||||
|
||||
## 7. 国际化支持
|
||||
|
||||
### 7.1 实现方式
|
||||
- 使用 `src/services/locale.ts` 中的 `t()` 函数。
|
||||
- 在 `createItemElement` 中,直接使用 `t(item.label)` 设置文本。
|
||||
- 组件初始化时订阅语言变更,变更发生时清空并重绘 (`setLocales` -> `render`)。
|
||||
|
||||
---
|
||||
|
||||
## 8. 主题支持
|
||||
|
||||
### 8.1 变量映射
|
||||
- 在 `setTheme` 中设置内联样式变量:
|
||||
- `--bim-ui_bg_color`: 面板背景
|
||||
- `--bim-ui_text_primary`: 主要文字
|
||||
- `--bim-ui_border_color`: 边框/分割线
|
||||
- `--bim-ui_bg_hover`: 悬停背景
|
||||
|
||||
---
|
||||
|
||||
## 9. 使用示例
|
||||
|
||||
### 9.1 数据结构示例
|
||||
|
||||
```typescript
|
||||
const menuItems: MenuItemConfig[] = [
|
||||
{
|
||||
id: 'view',
|
||||
label: 'menu.view', // 翻译键
|
||||
group: 'view',
|
||||
children: [
|
||||
{
|
||||
id: 'home',
|
||||
label: 'menu.home',
|
||||
onClick: () => console.log('Go Home')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'delete',
|
||||
label: 'menu.delete',
|
||||
group: 'edit',
|
||||
icon: '<svg>...</svg>',
|
||||
onClick: () => console.log('Delete')
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
### 9.2 手动创建(通常不直接使用,而是通过 RightKeyManager)
|
||||
|
||||
```typescript
|
||||
const menu = new BimMenu({ items: menuItems });
|
||||
menu.init();
|
||||
document.body.appendChild(menu.getElement());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 实现细节(供 AI 重现)
|
||||
|
||||
### 10.1 递归设计
|
||||
组件自身不包含递归渲染 DOM 的逻辑,而是通过“交互触发”来递归实例化。即:子菜单**不是**一开始就渲染在 DOM 树中的,而是当用户鼠标悬停时,动态创建一个新的 `BimMenu` 实例并挂载到 `body` 上。这种设计避免了深层嵌套 DOM 带来的样式问题(如 `overflow: hidden` 截断子菜单)。
|
||||
|
||||
### 10.2 事件冲突处理
|
||||
由于子菜单挂载在 `body` 上,点击子菜单在 DOM 树看来是“点击了主菜单外部”。这会触发 `BimRightKey` 的“点击外部关闭”逻辑。
|
||||
**解决方案**: 子菜单容器监听 `mousedown` 并 `stopPropagation()`,欺骗 `BimRightKey` 认为点击没有发生(或者发生在内部)。
|
||||
|
||||
---
|
||||
|
||||
## 11. 类型定义
|
||||
|
||||
### 11.1 MenuItemConfig
|
||||
|
||||
```typescript
|
||||
interface MenuItemConfig {
|
||||
id: string;
|
||||
label: string;
|
||||
onClick?: () => void;
|
||||
icon?: string; // SVG 字符串
|
||||
group?: string; // 分组标识
|
||||
order?: number; // 排序权重
|
||||
children?: MenuItemConfig[];
|
||||
disabled?: boolean;
|
||||
visible?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### 11.2 MenuOptions
|
||||
|
||||
```typescript
|
||||
interface MenuOptions {
|
||||
items: MenuItemConfig[];
|
||||
groupOrder?: string[];
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. 文件清单
|
||||
|
||||
- `src/components/menu/index.ts`: 组件核心逻辑
|
||||
- `src/components/menu/index.css`: 组件样式
|
||||
- `src/components/menu/item.ts`: 仅包含类型定义 (`MenuItemConfig`)
|
||||
- `src/components/menu/types.ts`: 组件选项接口
|
||||
|
||||
---
|
||||
|
||||
## 13. 更新记录
|
||||
|
||||
| 日期 | 修改内容 | 修改人 |
|
||||
| ---------- | ----------------------------------------- | ------------ |
|
||||
| 2024-XX-XX | 重构为纯配置对象驱动,移除 BimMenuItem 类 | AI Assistant |
|
||||
Reference in New Issue
Block a user