docs: update menu and right-key component documentation

This commit is contained in:
yuding
2025-12-10 09:46:22 +08:00
parent 9903a71015
commit 1f27d02788
2 changed files with 492 additions and 87 deletions

View File

@@ -1,58 +1,211 @@
# RightKey 组件文档
# RightKey 组件详细文档
> 本文档详细描述 RightKey 组件的实现细节,包括 API、UI 结构、逻辑流程等,供 AI 根据文档重现组件。
---
## 1. 组件概述
`BimRightKey` 是一个通用的右键浮层容器组件。
- **位置**: `src/components/right-key/index.ts`
- **功能**: 负责在指定坐标 (x, y) 显示内容,处理边界检测防止溢出屏幕,以及点击外部自动关闭。
- **特点**: 它不关心内容是什么,通过 `mount()` 方法挂载任意实现 `IRightKeyContent` 接口的内容组件。
### 1.1 基本信息
- **组件名称**: `BimRightKey`
- **文件路径**: `src/components/right-key/index.ts`
- **类型定义**: `src/components/right-key/types.ts`
- **样式文件**: `src/components/right-key/index.css`
- **实现接口**: `IBimComponent`
- **用途**: 提供一个全屏感知的定位容器,用于显示右键菜单等浮层内容。
- **特点**: 自动边界检测(防止溢出屏幕)、点击外部自动关闭、内容无关性(支持挂载任意内容)。
## 2. 组件类 API
### 1.2 在 SDK 中的位置
- RightKey 是右键菜单系统的容器部分。
- 必须通过 `RightKeyManager` 使用,不允许直接使用。
- `RightKeyManager` 位于 `src/managers/right-key-manager.ts`
### `BimRightKey`
---
#### 方法
## 2. 组件类 API 文档
| 方法名 | 参数 | 返回值 | 描述 |
|:----|:---|:---|:---|
| `init` | `()` | `void` | 初始化,绑定全局点击事件 |
| `mount` | `(content: IRightKeyContent)` | `void` | 挂载内容组件 |
| `show` | `(x: number, y: number)` | `void` | <20><><EFBFBD>指定位置显示会自动调整位置防止溢出 |
| `hide` | `()` | `void` | 隐藏容器 |
| `destroy` | `()` | `void` | 销毁容器,解绑事件 |
| `setOnClose` | `(callback: () => void)` | `void` | 设置关闭时的回调 |
### 2.1 构造函数
## 3. Manager API
```typescript
constructor(options?: RightKeyOptions)
```
### `RightKeyManager`
**<EFBFBD><EFBFBD>数**:
- `options`:
- `zIndex`: number (默认 10000)
- `className`: string
- **位置**: `src/managers/right-key-manager.ts`
- **功能**: 监听容器的 `contextmenu` 事件,决定显示什么内容。
### 2.2 公共方法
#### 方法
#### `init(): void`
初始化组件(实现 `IBimComponent` 接口)
| 方法名 | 参数 | 返回值 | 描述 |
|:----|:---|:---|:---|
| `registerHandler` | `(handler: (e) => BimMenuItem[])` | `void` | 注册上下文处理器 |
| `showMenu` | `(x, y, items, groupOrder?)` | `void` | 手动显示菜单 |
| `hide` | `()` | `void` | 隐藏 |
**功能**:
- 创建 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 详细描述
- **容器**: `<div class="bim-right-key"></div>`
- **定位**: `position: fixed`
- **层级**: `z-index: 10000` (默认)
### 4.1 DOM 结构
## 5. 实现细节
```html
<!-- 容器 -->
<div class="bim-right-key" style="z-index: 9000; display: none; left: ...; top: ...">
<!-- 挂载的内容 (例如 BimMenu 的 ul) -->
<ul class="bim-menu">...</ul>
</div>
```
- **边界检测**: 在 `show(x, y)` 时,会计算容器宽高和视口宽高。如果 `x + width > viewportWidth`,则 `x = x - width`(向左展开)。同理处理垂直方向。
- **点击外部关闭**: 监听 `document``mousedown` 事件,如果点击目标不在容器内,则调用 `hide()`
### 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
export interface IRightKeyContent {
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 |