docs: update menu and right-key component documentation
This commit is contained in:
@@ -1,66 +1,318 @@
|
|||||||
# Menu 组件文档
|
# Menu 组件详细文档
|
||||||
|
|
||||||
|
> 本文档详细描述 Menu 组件的实现细节,包括 API、UI 结构、逻辑流程等,供 AI 根据文档重现组件。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 1. 组件概述
|
## 1. 组件概述
|
||||||
|
|
||||||
`BimMenu` 是一个通用的菜单列表组件。
|
### 1.1 基本信息
|
||||||
- **位置**: `src/components/menu/index.ts`
|
- **组件名称**: `BimMenu`
|
||||||
- **功能**: 渲染一组 `BimMenuItem`,支持分组、排序、图标、快捷键提示和多级子菜单。
|
- **文件路径**: `src/components/menu/index.ts`
|
||||||
- **特点**: 数据驱动(通过 Item 类实例),支持国际化。
|
- **类型定义**: `src/components/menu/item.ts` (配置), `src/components/menu/types.ts` (选项)
|
||||||
|
- **样式文件**: `src/components/menu/index.css`
|
||||||
|
- **实现接口**: `IBimComponent`, `IRightKeyContent`
|
||||||
|
- **用途**: 渲染一组菜单项,支持分组、排序、图标、快捷键提示和无限级递归子菜单。
|
||||||
|
- **特点**: 纯数据驱动(基于 `MenuItemConfig`),内置国际化支持。
|
||||||
|
|
||||||
## 2. 组件类 API
|
### 1.2 在 SDK 中的位置
|
||||||
|
- Menu 组件主要由 `RightKeyManager` 使用,作为右键菜单的内容载体。
|
||||||
|
- 也可以单独实例化并挂载到任何容器中。
|
||||||
|
- `RightKeyManager` 位于 `src/managers/right-key-manager.ts`。
|
||||||
|
|
||||||
### `BimMenu`
|
---
|
||||||
|
|
||||||
#### 构造函数
|
## 2. 组件类 API 文档
|
||||||
`new BimMenu(options: MenuOptions)`
|
|
||||||
|
|
||||||
#### 方法
|
### 2.1 构造函数
|
||||||
|
|
||||||
| 方法名 | 参数 | 返回值 | 描述 |
|
|
||||||
|:----|:---|:---|:---|
|
|
||||||
| `init` | `()` | `void` | 初始化,渲染 DOM |
|
|
||||||
| `destroy` | `()` | `void` | 销毁,清理事件和子菜单 |
|
|
||||||
| `getElement` | `()` | `HTMLElement` | 获取根 DOM 元素 (实现 IRightKeyContent) |
|
|
||||||
|
|
||||||
### `BimMenuItem` (基类)
|
|
||||||
|
|
||||||
所有菜单项必须继承此抽象类。
|
|
||||||
|
|
||||||
| 方法/属性 | 类型 | 描述 |
|
|
||||||
|:----|:---|:---|
|
|
||||||
| `id` | `string` | 唯一标识 |
|
|
||||||
| `group` | `string` | 分组 ID (默认 'default') |
|
|
||||||
| `order` | `number` | 排序权重 |
|
|
||||||
| `getLabel()` | `string` | 获取显示文本 |
|
|
||||||
| `onClick()` | `void` | 点击回调 |
|
|
||||||
| `getIcon()` | `string?` | 获取图标 HTML |
|
|
||||||
| `getChildren()` | `BimMenuItem[]?` | 获取子菜单项 |
|
|
||||||
|
|
||||||
## 3. UI 详细描述
|
|
||||||
|
|
||||||
- **根元素**: `<ul class="bim-menu">`
|
|
||||||
- **分组分割线**: `<li class="bim-menu-divider">`
|
|
||||||
- **菜单项**: `<li class="bim-menu-item">`
|
|
||||||
- 图标槽: `.bim-menu-item-icon`
|
|
||||||
- 文本槽: `.bim-menu-item-label`
|
|
||||||
- 箭头槽: `.bim-menu-item-arrow` (仅当有子菜单时)
|
|
||||||
|
|
||||||
## 4. 逻辑流程
|
|
||||||
|
|
||||||
1. **分组与排序**:
|
|
||||||
- 根据 `item.group` 将项归类。
|
|
||||||
- 根据 `options.groupOrder` 对组进行排序。
|
|
||||||
- 组内根据 `item.order` 排序。
|
|
||||||
2. **多级菜单**:
|
|
||||||
- 鼠标进入 (`mouseenter`) 带子菜单的项时,创建新的 `BimMenu` 实例。
|
|
||||||
- 将新实例挂载到临时的 fixed 容器中。
|
|
||||||
- 自动计算位置(通常在父项右侧,空间不足时翻转)。
|
|
||||||
|
|
||||||
## 5. 类型定义
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
export interface MenuOptions {
|
constructor(options: MenuOptions)
|
||||||
items: BimMenuItem[];
|
```
|
||||||
|
|
||||||
|
**参数**:
|
||||||
|
- `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[];
|
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 |
|
||||||
@@ -1,58 +1,211 @@
|
|||||||
# RightKey 组件文档
|
# RightKey 组件详细文档
|
||||||
|
|
||||||
|
> 本文档详细描述 RightKey 组件的实现细节,包括 API、UI 结构、逻辑流程等,供 AI 根据文档重现组件。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 1. 组件概述
|
## 1. 组件概述
|
||||||
|
|
||||||
`BimRightKey` 是一个通用的右键浮层容器组件。
|
### 1.1 基本信息
|
||||||
- **位置**: `src/components/right-key/index.ts`
|
- **组件名称**: `BimRightKey`
|
||||||
- **功能**: 负责在指定坐标 (x, y) 显示内容,处理边界检测防止溢出屏幕,以及点击外部自动关闭。
|
- **文件路径**: `src/components/right-key/index.ts`
|
||||||
- **特点**: 它不关心内容是什么,通过 `mount()` 方法挂载任意实现 `IRightKeyContent` 接口的内容组件。
|
- **类型定义**: `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 文档
|
||||||
|
|
||||||
| 方法名 | 参数 | 返回值 | 描述 |
|
### 2.1 构造函数
|
||||||
|:----|:---|:---|:---|
|
|
||||||
| `init` | `()` | `void` | 初始化,绑定全局点击事件 |
|
|
||||||
| `mount` | `(content: IRightKeyContent)` | `void` | 挂载内容组件 |
|
|
||||||
| `show` | `(x: number, y: number)` | `void` | <20><><EFBFBD>指定位置显示,会自动调整位置防止溢出 |
|
|
||||||
| `hide` | `()` | `void` | 隐藏容器 |
|
|
||||||
| `destroy` | `()` | `void` | 销毁容器,解绑事件 |
|
|
||||||
| `setOnClose` | `(callback: () => void)` | `void` | 设置关闭时的回调 |
|
|
||||||
|
|
||||||
## 3. Manager API
|
```typescript
|
||||||
|
constructor(options?: RightKeyOptions)
|
||||||
|
```
|
||||||
|
|
||||||
### `RightKeyManager`
|
**<EFBFBD><EFBFBD>数**:
|
||||||
|
- `options`:
|
||||||
|
- `zIndex`: number (默认 10000)
|
||||||
|
- `className`: string
|
||||||
|
|
||||||
- **位置**: `src/managers/right-key-manager.ts`
|
### 2.2 公共方法
|
||||||
- **功能**: 监听容器的 `contextmenu` 事件,决定显示什么内容。
|
|
||||||
|
|
||||||
#### 方法
|
#### `init(): void`
|
||||||
|
初始化组件(实现 `IBimComponent` 接口)
|
||||||
|
|
||||||
| 方法名 | 参数 | 返回值 | 描述 |
|
**功能**:
|
||||||
|:----|:---|:---|:---|
|
- 创建 DOM 结构
|
||||||
| `registerHandler` | `(handler: (e) => BimMenuItem[])` | `void` | 注册上下文处理器 |
|
- 将容器挂载到 `document.body`(或其他指定容器,当前实现是 body)
|
||||||
| `showMenu` | `(x, y, items, groupOrder?)` | `void` | 手动显示菜单 |
|
- 绑定全局 `mousedown` 事件用于检测“点击外部”
|
||||||
| `hide` | `()` | `void` | 隐藏 |
|
|
||||||
|
#### `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. UI 详细描述
|
||||||
|
|
||||||
- **容器**: `<div class="bim-right-key"></div>`
|
### 4.1 DOM 结构
|
||||||
- **定位**: `position: fixed`
|
|
||||||
- **层级**: `z-index: 10000` (默认)
|
|
||||||
|
|
||||||
## 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`(向左展开)。同理处理垂直方向。
|
### 4.2 CSS 类名
|
||||||
- **点击外部关闭**: 监听 `document` 的 `mousedown` 事件,如果点击目标不在容器内,则调用 `hide()`。
|
|
||||||
|
#### `.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. 类型定义
|
||||||
|
|
||||||
|
### 6.1 IRightKeyContent
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
export interface IRightKeyContent {
|
interface IRightKeyContent {
|
||||||
getElement(): HTMLElement;
|
getElement(): HTMLElement;
|
||||||
destroy(): void;
|
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 |
|
||||||
Reference in New Issue
Block a user