---
description:
globs:
alwaysApply: false
---
**桌面端菜单配置指南**

## 菜单系统概述

LobeChat 桌面应用有三种主要的菜单类型：

1. **应用菜单 (App Menu)**：显示在应用窗口顶部（macOS）或窗口标题栏（Windows/Linux）
2. **上下文菜单 (Context Menu)**：右键点击时显示的菜单
3. **托盘菜单 (Tray Menu)**：点击系统托盘图标显示的菜单

## 菜单相关文件结构

```
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 { app, BrowserWindow, Menu, MenuItem, MenuItemConstructorOptions } 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' }` 在逻辑上分隔不同组的菜单项
