---
description:
globs:
alwaysApply: false
---
**桌面端窗口管理指南**

## 窗口管理概述

LobeChat 桌面应用使用 Electron 的 `BrowserWindow` 管理应用窗口。主要的窗口管理功能包括：

1. **窗口创建和配置**
2. **窗口状态管理**（大小、位置、最大化等）
3. **多窗口协调**
4. **窗口事件处理**

## 相关文件结构

```
apps/desktop/src/main/
├── appBrowsers.ts               # 窗口管理的核心文件
├── controllers/
│   └── BrowserWindowsCtr.ts     # 窗口控制器
└── modules/
    └── browserWindowManager.ts  # 窗口管理模块
```

## 窗口管理流程

### 1. 窗口创建

在 `appBrowsers.ts` 或 `BrowserWindowsCtr.ts` 中定义窗口创建逻辑：

```typescript
export const createMainWindow = () => {
  const mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    minWidth: 600,
    minHeight: 400,
    webPreferences: {
      preload: path.join(__dirname, '../preload/index.js'),
      contextIsolation: true,
      nodeIntegration: false,
    },
    // 其他窗口配置项...
  });

  // 加载应用内容
  if (isDev) {
    mainWindow.loadURL('http://localhost:3000');
    mainWindow.webContents.openDevTools();
  } else {
    mainWindow.loadFile(path.join(__dirname, '../../renderer/index.html'));
  }

  return mainWindow;
};
```

### 2. 窗口状态管理

实现窗口状态持久化保存和恢复：

1. **保存窗口状态**
   ```typescript
   const saveWindowState = (window: BrowserWindow) => {
     if (!window.isMinimized() && !window.isMaximized()) {
       const position = window.getPosition();
       const size = window.getSize();

       settings.set('windowState', {
         x: position[0],
         y: position[1],
         width: size[0],
         height: size[1],
       });
     }
   };
   ```

2. **恢复窗口状态**
   ```typescript
   const restoreWindowState = (window: BrowserWindow) => {
     const savedState = settings.get('windowState');

     if (savedState) {
       window.setBounds({
         x: savedState.x,
         y: savedState.y,
         width: savedState.width,
         height: savedState.height,
       });
     }
   };
   ```

3. **监听窗口事件**
   ```typescript
   window.on('close', () => saveWindowState(window));
   window.on('moved', () => saveWindowState(window));
   window.on('resized', () => saveWindowState(window));
   ```

### 3. 实现多窗口管理

对于需要多窗口支持的功能：

1. **跟踪窗口**
   ```typescript
   export class WindowManager {
     private windows: Map<string, BrowserWindow> = new Map();

     createWindow(id: string, options: BrowserWindowConstructorOptions) {
       const window = new BrowserWindow(options);
       this.windows.set(id, window);

       window.on('closed', () => {
         this.windows.delete(id);
       });

       return window;
     }

     getWindow(id: string) {
       return this.windows.get(id);
     }

     getAllWindows() {
       return Array.from(this.windows.values());
     }
   }
   ```

2. **窗口间通信**
   ```typescript
   // 从一个窗口向另一个窗口发送消息
   sendMessageToWindow(targetWindowId, channel, data) {
     const targetWindow = this.getWindow(targetWindowId);
     if (targetWindow) {
       targetWindow.webContents.send(channel, data);
     }
   }
   ```

### 4. 窗口与渲染进程通信

通过 IPC 实现窗口操作：

1. **在主进程中注册 IPC 处理器**
   ```typescript
   // BrowserWindowsCtr.ts
   @ipcClientEvent('minimizeWindow')
   handleMinimizeWindow() {
     const focusedWindow = BrowserWindow.getFocusedWindow();
     if (focusedWindow) {
       focusedWindow.minimize();
     }
     return { success: true };
   }

   @ipcClientEvent('maximizeWindow')
   handleMaximizeWindow() {
     const focusedWindow = BrowserWindow.getFocusedWindow();
     if (focusedWindow) {
       if (focusedWindow.isMaximized()) {
         focusedWindow.restore();
       } else {
         focusedWindow.maximize();
       }
     }
     return { success: true };
   }

   @ipcClientEvent('closeWindow')
   handleCloseWindow() {
     const focusedWindow = BrowserWindow.getFocusedWindow();
     if (focusedWindow) {
       focusedWindow.close();
     }
     return { success: true };
   }
   ```

2. **在渲染进程中调用**
   ```typescript
   // src/services/electron/windowService.ts
   import { dispatch } from '@lobechat/electron-client-ipc';

   export const windowService = {
     minimize: () => dispatch('minimizeWindow'),
     maximize: () => dispatch('maximizeWindow'),
     close: () => dispatch('closeWindow'),
   };
   ```

### 5. 自定义窗口控制 (无边框窗口)

对于自定义窗口标题栏：

1. **创建无边框窗口**
   ```typescript
   const window = new BrowserWindow({
     frame: false,
     titleBarStyle: 'hidden',
     // 其他选项...
   });
   ```

2. **在渲染进程中实现拖拽区域**
   ```css
   /* CSS */
   .titlebar {
     -webkit-app-region: drag;
   }

   .titlebar-button {
     -webkit-app-region: no-drag;
   }
   ```

## 最佳实践

1. **性能考虑**
   - 避免创建过多窗口
   - 使用 `show: false` 创建窗口，在内容加载完成后再显示，避免白屏

2. **安全性**
   - 始终设置适当的 `webPreferences` 确保安全
   ```typescript
   webPreferences: {
     preload: path.join(__dirname, '../preload/index.js'),
     contextIsolation: true,
     nodeIntegration: false,
     sandbox: true,
   }
   ```

3. **跨平台兼容性**
   - 考虑不同操作系统的窗口行为差异
   - 使用 `process.platform` 为不同平台提供特定实现

4. **崩溃恢复**
   - 监听 `webContents.on('crashed')` 事件处理崩溃
   - 提供崩溃恢复选项

5. **内存管理**
   - 确保窗口关闭时清理所有相关资源
   - 使用 `window.on('closed')` 而不是 `window.on('close')` 进行最终清理

## 示例：创建设置窗口

```typescript
// apps/desktop/src/main/controllers/BrowserWindowsCtr.ts

@ipcClientEvent('openSettings')
handleOpenSettings() {
  // 检查设置窗口是否已经存在
  if (this.settingsWindow && !this.settingsWindow.isDestroyed()) {
    // 如果窗口已存在，将其置于前台
    this.settingsWindow.focus();
    return { success: true };
  }

  // 创建新窗口
  this.settingsWindow = new BrowserWindow({
    width: 800,
    height: 600,
    title: 'Settings',
    parent: this.mainWindow, // 设置父窗口，使其成为模态窗口
    modal: true,
    webPreferences: {
      preload: path.join(__dirname, '../preload/index.js'),
      contextIsolation: true,
      nodeIntegration: false,
    },
  });

  // 加载设置页面
  if (isDev) {
    this.settingsWindow.loadURL('http://localhost:3000/settings');
  } else {
    this.settingsWindow.loadFile(
      path.join(__dirname, '../../renderer/index.html'),
      { hash: 'settings' }
    );
  }

  // 监听窗口关闭事件
  this.settingsWindow.on('closed', () => {
    this.settingsWindow = null;
  });

  return { success: true };
}
```
