mirror of
https://github.com/lobehub/lobehub
synced 2026-04-21 09:37:28 +00:00
209 lines
5 KiB
Text
209 lines
5 KiB
Text
---
|
||
description:
|
||
globs:
|
||
alwaysApply: false
|
||
---
|
||
|
||
# 桌面端菜单配置指南
|
||
|
||
## 菜单系统概述
|
||
|
||
LobeChat 桌面应用有三种主要的菜单类型:
|
||
|
||
1. **应用菜单 (App Menu)**:显示在应用窗口顶部(macOS)或窗口标题栏(Windows/Linux)
|
||
2. **上下文菜单 (Context Menu)**:右键点击时显示的菜单
|
||
3. **托盘菜单 (Tray Menu)**:点击系统托盘图标显示的菜单
|
||
|
||
## 菜单相关文件结构
|
||
|
||
```plaintext
|
||
apps/desktop/src/main/
|
||
├── menus/ # 菜单定义
|
||
│ ├── appMenu.ts # 应用菜单配置
|
||
│ ├── contextMenu.ts # 上下文菜单配置
|
||
│ └── factory.ts # 菜单工厂函数
|
||
├── controllers/
|
||
│ ├── MenuCtr.ts # 菜单控制器
|
||
│ └── TrayMenuCtr.ts # 托盘菜单控制器
|
||
```
|
||
|
||
## 菜单配置流程
|
||
|
||
### 1. 应用菜单配置
|
||
|
||
应用菜单在 `apps/desktop/src/main/menus/appMenu.ts` 中定义:
|
||
|
||
1. **导入依赖**
|
||
|
||
```typescript
|
||
import { BrowserWindow, Menu, MenuItem, MenuItemConstructorOptions, app } from 'electron';
|
||
import { is } from 'electron-util';
|
||
```
|
||
|
||
2. **定义菜单项**
|
||
- 使用 `MenuItemConstructorOptions` 类型定义菜单结构
|
||
- 每个菜单项可以包含:label, accelerator (快捷键), role, submenu, click 等属性
|
||
|
||
3. **创建菜单工厂函数**
|
||
|
||
```typescript
|
||
export const createAppMenu = (win: BrowserWindow) => {
|
||
const template = [
|
||
// 定义菜单项...
|
||
];
|
||
|
||
return Menu.buildFromTemplate(template);
|
||
};
|
||
```
|
||
|
||
4. **注册菜单**
|
||
- 在 `MenuCtr.ts` 控制器中使用 `Menu.setApplicationMenu(menu)` 设置应用菜单
|
||
|
||
### 2. 上下文菜单配置
|
||
|
||
上下文菜单通常在特定元素上右键点击时显示:
|
||
|
||
1. **在主进程中定义菜单模板**
|
||
|
||
```typescript
|
||
// apps/desktop/src/main/menus/contextMenu.ts
|
||
export const createContextMenu = () => {
|
||
const template = [
|
||
// 定义菜单项...
|
||
];
|
||
|
||
return Menu.buildFromTemplate(template);
|
||
};
|
||
```
|
||
|
||
2. **在适当的事件处理器中显示菜单**
|
||
|
||
```typescript
|
||
const menu = createContextMenu();
|
||
menu.popup();
|
||
```
|
||
|
||
### 3. 托盘菜单配置
|
||
|
||
托盘菜单在 `TrayMenuCtr.ts` 中配置:
|
||
|
||
1. **创建托盘图标**
|
||
|
||
```typescript
|
||
this.tray = new Tray(trayIconPath);
|
||
```
|
||
|
||
2. **定义托盘菜单**
|
||
|
||
```typescript
|
||
const contextMenu = Menu.buildFromTemplate([
|
||
{ label: '显示主窗口', click: this.showMainWindow },
|
||
{ type: 'separator' },
|
||
{ label: '退出', click: () => app.quit() },
|
||
]);
|
||
```
|
||
|
||
3. **设置托盘菜单**
|
||
|
||
```typescript
|
||
this.tray.setContextMenu(contextMenu);
|
||
```
|
||
|
||
## 多语言支持
|
||
|
||
为菜单添加多语言支持:
|
||
|
||
1. **导入本地化工具**
|
||
|
||
```typescript
|
||
import { i18n } from '../locales';
|
||
```
|
||
|
||
2. **使用翻译函数**
|
||
|
||
```typescript
|
||
const template = [
|
||
{
|
||
label: i18n.t('menu.file'),
|
||
submenu: [
|
||
{ label: i18n.t('menu.new'), click: createNew },
|
||
// ...
|
||
],
|
||
},
|
||
// ...
|
||
];
|
||
```
|
||
|
||
3. **在语言切换时更新菜单** 在 `MenuCtr.ts` 中监听语言变化事件并重新创建菜单
|
||
|
||
## 添加新菜单项流程
|
||
|
||
1. **确定菜单位置**
|
||
- 决定添加到哪个菜单(应用菜单、上下文菜单或托盘菜单)
|
||
- 确定在菜单中的位置(主菜单项或子菜单项)
|
||
|
||
2. **定义菜单项**
|
||
|
||
```typescript
|
||
const newMenuItem: MenuItemConstructorOptions = {
|
||
label: '新功能',
|
||
accelerator: 'CmdOrCtrl+N',
|
||
click: (_, window) => {
|
||
// 处理点击事件
|
||
if (window) window.webContents.send('trigger-new-feature');
|
||
},
|
||
};
|
||
```
|
||
|
||
3. **添加到菜单模板** 将新菜单项添加到相应的菜单模板中
|
||
|
||
4. **对于与渲染进程交互的功能**
|
||
- 使用 `window.webContents.send()` 发送 IPC 消息到渲染进程
|
||
- 在渲染进程中监听该消息并处理
|
||
|
||
## 菜单项启用/禁用控制
|
||
|
||
动态控制菜单项状态:
|
||
|
||
1. **保存对菜单项的引用**
|
||
|
||
```typescript
|
||
this.menuItems = {};
|
||
const menu = Menu.buildFromTemplate(template);
|
||
this.menuItems.newFeature = menu.getMenuItemById('new-feature');
|
||
```
|
||
|
||
2. **根据条件更新状态**
|
||
|
||
```typescript
|
||
updateMenuState(state) {
|
||
if (this.menuItems.newFeature) {
|
||
this.menuItems.newFeature.enabled = state.canUseNewFeature;
|
||
}
|
||
}
|
||
```
|
||
|
||
## 最佳实践
|
||
|
||
1. **使用标准角色**
|
||
- 尽可能使用 Electron 预定义的角色(如 `role: 'copy'`)以获得本地化和一致的行为
|
||
|
||
2. **平台特定菜单**
|
||
- 使用 `process.platform` 检查为不同平台提供不同菜单
|
||
|
||
```typescript
|
||
if (process.platform === 'darwin') {
|
||
template.unshift({ role: 'appMenu' });
|
||
}
|
||
```
|
||
|
||
3. **快捷键冲突**
|
||
- 避免与系统快捷键冲突
|
||
- 使用 `CmdOrCtrl` 代替 `Ctrl` 以支持 macOS 和 Windows/Linux
|
||
|
||
4. **保持菜单简洁**
|
||
- 避免过多嵌套的子菜单
|
||
- 将相关功能分组在一起
|
||
|
||
5. **添加分隔符**
|
||
- 使用 `{ type: 'separator' }` 在逻辑上分隔不同组的菜单项
|