Files
bim_engine/docs/components/右键菜单组件-RightKey.md

211 lines
5.4 KiB
Markdown
Raw Normal View History

# 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)
```
**<2A><>数**:
- `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 |