# 窗口系统

<cite>
**本文引用的文件**
- [electron/main.ts](file://electron/main.ts)
- [electron/preload.ts](file://electron/preload.ts)
- [src/types/electron.d.ts](file://src/types/electron.d.ts)
- [src/components/layout/app-layout.tsx](file://src/components/layout/app-layout.tsx)
- [src/components/layout/title-bar.tsx](file://src/components/layout/title-bar.tsx)
- [src/components/ui/resize-handle.tsx](file://src/components/ui/resize-handle.tsx)
- [src/hooks/use-container-width.ts](file://src/hooks/use-container-width.ts)
- [src/components/layout/right-sidebar.tsx](file://src/components/layout/right-sidebar.tsx)
- [package.json](file://package.json)
- [electron-builder.json](file://electron-builder.json)
- [scripts/build-electron.mjs](file://scripts/build-electron.mjs)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本文件面向Electron主进程中的窗口系统，围绕BrowserWindow的创建流程、窗口属性配置与显示控制进行深入解析；同时覆盖窗口尺寸管理、最小尺寸限制与标题栏样式设置；解释窗口生命周期事件处理、关闭行为控制与内存清理机制；阐述外部链接处理、安全策略与沙箱配置；并包含窗口状态管理、多窗口协调与焦点控制；最后提供窗口优化建议、用户体验改进与跨平台适配方案。

## 项目结构
本项目采用“主进程 + 预加载 + 渲染侧React UI”的典型Electron架构：
- 主进程负责应用生命周期、窗口创建与系统级IPC、子进程（Next服务）管理
- 预加载脚本通过contextBridge暴露受控API给渲染侧
- 渲染侧由Next应用提供页面内容，UI组件负责窗口布局与交互

```mermaid
graph TB
subgraph "主进程"
M["electron/main.ts<br/>应用生命周期/窗口创建/IPC/子进程"]
P["electron/preload.ts<br/>contextBridge API 暴露"]
end
subgraph "构建与打包"
PKG["package.json<br/>开发/构建/打包脚本"]
EB["electron-builder.json<br/>打包配置/平台目标"]
BE["scripts/build-electron.mjs<br/>构建主进程产物"]
end
subgraph "渲染侧"
AL["src/components/layout/app-layout.tsx<br/>布局/视图/面板/事件"]
TB["src/components/layout/title-bar.tsx<br/>标题栏"]
RH["src/components/ui/resize-handle.tsx<br/>拖拽调整大小"]
RCW["src/hooks/use-container-width.ts<br/>容器宽度监听"]
RS["src/components/layout/right-sidebar.tsx<br/>右侧边栏/文件树"]
end
M --> P
M --> AL
P --> AL
AL --> TB
AL --> RH
AL --> RCW
AL --> RS
PKG --> BE --> EB
```

**图表来源**
- [electron/main.ts:177-311](file://electron/main.ts#L177-L311)
- [electron/preload.ts:1-24](file://electron/preload.ts#L1-L24)
- [src/components/layout/app-layout.tsx:1-566](file://src/components/layout/app-layout.tsx#L1-L566)
- [src/components/layout/title-bar.tsx:1-32](file://src/components/layout/title-bar.tsx#L1-L32)
- [src/components/ui/resize-handle.tsx:1-76](file://src/components/ui/resize-handle.tsx#L1-L76)
- [src/hooks/use-container-width.ts:1-20](file://src/hooks/use-container-width.ts#L1-L20)
- [src/components/layout/right-sidebar.tsx:136-236](file://src/components/layout/right-sidebar.tsx#L136-L236)
- [package.json:13-26](file://package.json#L13-L26)
- [electron-builder.json:1-126](file://electron-builder.json#L1-L126)
- [scripts/build-electron.mjs:31-73](file://scripts/build-electron.mjs#L31-L73)

**章节来源**
- [electron/main.ts:177-311](file://electron/main.ts#L177-L311)
- [electron/preload.ts:1-24](file://electron/preload.ts#L1-L24)
- [src/components/layout/app-layout.tsx:1-566](file://src/components/layout/app-layout.tsx#L1-L566)
- [package.json:13-26](file://package.json#L13-L26)
- [electron-builder.json:1-126](file://electron-builder.json#L1-L126)
- [scripts/build-electron.mjs:31-73](file://scripts/build-electron.mjs#L31-L73)

## 核心组件
- 主进程窗口创建与生命周期：在应用就绪后创建BrowserWindow，设置窗口初始尺寸、最小尺寸、标题栏样式、背景色与webPreferences，并注册窗口事件与全局事件处理
- 预加载桥接层：通过contextBridge向渲染侧暴露受限API，包括目录选择、文件系统监控、剪贴板读取、数据目录获取等
- 渲染侧窗口布局与交互：AppLayout负责多视图、左右侧边栏、编辑器面板与拖拽调整大小；TitleBar提供标题栏区域；ResizeHandle提供拖拽调整大小能力；useContainerWidth用于响应式布局

**章节来源**
- [electron/main.ts:141-175](file://electron/main.ts#L141-L175)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)
- [src/components/layout/app-layout.tsx:34-566](file://src/components/layout/app-layout.tsx#L34-L566)
- [src/components/layout/title-bar.tsx:6-31](file://src/components/layout/title-bar.tsx#L6-L31)
- [src/components/ui/resize-handle.tsx:13-76](file://src/components/ui/resize-handle.tsx#L13-L76)
- [src/hooks/use-container-width.ts:3-20](file://src/hooks/use-container-width.ts#L3-L20)

## 架构总览
下图展示从应用启动到窗口创建、IPC通信与渲染侧UI协作的整体流程：

```mermaid
sequenceDiagram
participant App as "Electron 应用(app)"
participant Main as "主进程(main.ts)"
participant BW as "BrowserWindow"
participant Pre as "预加载(preload.ts)"
participant Rnd as "渲染侧(Next/React)"
App->>Main : "app.whenReady()"
Main->>Main : "查找可用端口/启动Next服务"
Main->>BW : "new BrowserWindow(options)"
BW->>BW : "设置尺寸/最小尺寸/标题栏/背景/webPreferences"
BW->>BW : "loadURL(serverUrl)"
BW-->>Main : "ready-to-show 事件"
Main->>BW : "show()"
BW-->>Rnd : "加载页面"
Rnd->>Pre : "调用 exposed API"
Pre-->>Main : "ipcRenderer.invoke(...)"
Main-->>Pre : "ipcMain.handle(...) 处理结果"
Pre-->>Rnd : "返回结果"
```

**图表来源**
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [electron/main.ts:141-175](file://electron/main.ts#L141-L175)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)

## 详细组件分析

### BrowserWindow 创建与属性配置
- 尺寸与最小尺寸：窗口默认宽高与最小宽高在创建时设定，确保界面基础体验与可操作性
- 标题栏样式：使用隐藏式标题栏样式并在macOS上指定交通信号灯按钮位置，配合自绘标题栏组件实现一致的视觉风格
- 背景色：设置背景色以避免白屏闪烁
- 显示策略：首次加载时延迟显示，等待ready-to-show后再展示，提升首屏体验
- Web偏好：启用上下文隔离、禁用Node集成、关闭沙箱，配合预加载脚本与严格IPC实现安全边界

```mermaid
flowchart TD
Start(["创建窗口"]) --> SetSize["设置初始宽高与最小宽高"]
SetSize --> SetTitleBar["设置标题栏样式与交通信号灯位置"]
SetTitleBar --> SetBG["设置背景色"]
SetBG --> SetWebPrefs["设置webPreferences(上下文隔离/禁用Node集成/关闭沙箱)"]
SetWebPrefs --> LoadURL["加载URL"]
LoadURL --> ReadyToShow{"ready-to-show?"}
ReadyToShow --> |是| Show["显示窗口"]
ReadyToShow --> |否| Wait["等待事件"]
Show --> End(["完成"])
Wait --> ReadyToShow
```

**图表来源**
- [electron/main.ts:141-175](file://electron/main.ts#L141-L175)

**章节来源**
- [electron/main.ts:141-175](file://electron/main.ts#L141-L175)

### 外部链接处理与安全策略
- 窗口打开处理器：对http开头的外部链接进行拦截并交由系统默认浏览器打开，其余情况拒绝新窗口
- 预加载API：通过contextBridge暴露有限API，避免渲染侧直接访问Node/Electron原生能力
- 沙箱与上下文隔离：开启上下文隔离，关闭Node集成，降低XSS与代码注入风险

```mermaid
flowchart TD
OpenReq["webContents.setWindowOpenHandler 回调"] --> CheckProto{"协议为 http?"}
CheckProto --> |是| OpenExt["shell.openExternal(url) 打开系统浏览器"]
CheckProto --> |否| Deny["action: deny 拒绝新窗口"]
OpenExt --> End(["结束"])
Deny --> End
```

**图表来源**
- [electron/main.ts:165-170](file://electron/main.ts#L165-L170)

**章节来源**
- [electron/main.ts:165-170](file://electron/main.ts#L165-L170)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)

### 窗口生命周期事件与关闭行为控制
- 窗口关闭：监听closed事件并将窗口实例置空，防止内存泄漏
- 全局退出：window-all-closed事件触发后退出应用
- 应用激活：activate事件在无活动窗口时重新创建窗口
- 退出前清理：before-quit中关闭文件系统监视器与子进程，确保资源释放

```mermaid
sequenceDiagram
participant BW as "BrowserWindow"
participant App as "Electron 应用"
participant Watch as "FSWatcher"
participant Proc as "子进程(Next服务)"
BW-->>App : "closed"
App->>App : "mainWindow = null"
App->>App : "window-all-closed"
App->>App : "app.quit()"
App->>App : "activate"
App->>BW : "createWindow(serverUrl)"
App->>App : "before-quit"
App->>Watch : "close()"
App->>Proc : "kill()"
```

**图表来源**
- [electron/main.ts:172-175](file://electron/main.ts#L172-L175)
- [electron/main.ts:291-299](file://electron/main.ts#L291-L299)
- [electron/main.ts:301-310](file://electron/main.ts#L301-L310)

**章节来源**
- [electron/main.ts:172-175](file://electron/main.ts#L172-L175)
- [electron/main.ts:291-299](file://electron/main.ts#L291-L299)
- [electron/main.ts:301-310](file://electron/main.ts#L301-L310)

### 窗口尺寸管理与最小尺寸限制
- 窗口初始尺寸：在创建时设置默认宽高与最小宽高，保证最小可操作区域
- 布局内尺寸：AppLayout中维护左侧边栏、右侧边栏与编辑器面板的宽度状态，并通过refs避免闭包陷阱
- 动态最大值：根据窗口宽度与侧边栏折叠状态动态计算最大宽度，确保聊天区始终有足够空间
- 拖拽调整：ResizeHandle提供横向/纵向拖拽回调，结合防抖与边界约束更新状态

```mermaid
flowchart TD
Init(["初始化窗口尺寸"]) --> State["记录当前窗口宽度/折叠状态"]
State --> Drag["用户拖拽ResizeHandle"]
Drag --> CalcMax["计算最大允许宽度(考虑折叠/侧栏/最小聊天区)"]
CalcMax --> Constrain["边界约束(最小/最大)"]
Constrain --> Update["更新面板宽度状态"]
Update --> Render["重渲染布局"]
```

**图表来源**
- [src/components/layout/app-layout.tsx:365-392](file://src/components/layout/app-layout.tsx#L365-L392)
- [src/components/ui/resize-handle.tsx:17-53](file://src/components/ui/resize-handle.tsx#L17-L53)

**章节来源**
- [electron/main.ts:141-175](file://electron/main.ts#L141-L175)
- [src/components/layout/app-layout.tsx:365-392](file://src/components/layout/app-layout.tsx#L365-L392)
- [src/components/ui/resize-handle.tsx:17-53](file://src/components/ui/resize-handle.tsx#L17-L53)

### 标题栏样式设置与焦点控制
- 标题栏样式：通过BrowserWindow的titleBarStyle与trafficLightPosition设置隐藏式标题栏与交通信号灯位置
- 自绘标题栏：在渲染侧提供可拖拽的标题栏区域，左侧预留交通信号灯占用空间，右侧提供主题切换按钮
- 焦点控制：对话框与文件系统监控均基于当前聚焦窗口或主窗口，确保交互一致性

```mermaid
classDiagram
class BrowserWindow {
+number width
+number height
+number minWidth
+number minHeight
+string titleBarStyle
+object trafficLightPosition
+string backgroundColor
+boolean show
+object webPreferences
}
class TitleBar {
+toggleTheme()
}
BrowserWindow --> TitleBar : "配合自绘标题栏"
```

**图表来源**
- [electron/main.ts:141-175](file://electron/main.ts#L141-L175)
- [src/components/layout/title-bar.tsx:6-31](file://src/components/layout/title-bar.tsx#L6-L31)

**章节来源**
- [electron/main.ts:141-175](file://electron/main.ts#L141-L175)
- [src/components/layout/title-bar.tsx:6-31](file://src/components/layout/title-bar.tsx#L6-L31)

### 窗口状态管理、多窗口协调与焦点控制
- 状态管理：AppLayout集中管理活动视图、侧边栏折叠状态、面板宽度、当前会话与工作区等状态
- 多窗口协调：通过BrowserWindow.getFocusedWindow()与主窗口作为父窗口，确保对话框与系统交互在正确的窗口上下文中执行
- 文件系统监控：IPC监听文件变更事件，结合防抖与去重，减少渲染侧频繁刷新

```mermaid
sequenceDiagram
participant UI as "渲染侧(React)"
participant Pre as "预加载"
participant Main as "主进程"
participant BW as "BrowserWindow"
UI->>Pre : "openDirectoryDialog()"
Pre->>Main : "ipcRenderer.invoke('dialog : openDirectory')"
Main->>BW : "获取聚焦窗口或主窗口"
BW-->>Main : "返回父窗口句柄"
Main-->>Pre : "返回选中路径"
Pre-->>UI : "返回结果"
```

**图表来源**
- [electron/preload.ts:9](file://electron/preload.ts#L9)
- [electron/main.ts:179-189](file://electron/main.ts#L179-L189)

**章节来源**
- [src/components/layout/app-layout.tsx:344-352](file://src/components/layout/app-layout.tsx#L344-L352)
- [electron/preload.ts:9](file://electron/preload.ts#L9)
- [electron/main.ts:179-189](file://electron/main.ts#L179-L189)

### 安全策略与沙箱配置
- 上下文隔离：启用contextIsolation，阻止渲染侧直接访问Node原生模块
- 禁用Node集成：webPreferences.nodeIntegration=false，避免在渲染侧执行Node代码
- 关闭沙箱：webPreferences.sandbox=false，结合预加载与严格IPC实现可控的安全边界
- 外链拦截：仅允许http外链在系统浏览器打开，其他情况拒绝新窗口

**章节来源**
- [electron/main.ts:151-157](file://electron/main.ts#L151-L157)
- [electron/main.ts:165-170](file://electron/main.ts#L165-L170)

### 跨平台适配与打包配置
- 平台差异：标题栏样式与交通信号灯位置针对macOS定制；Windows/Linux平台由系统原生标题栏接管
- 打包目标：electron-builder配置了macOS DMG、Windows NSIS与Linux AppImage三种目标
- 构建流程：先编译主进程与预加载脚本，再构建Next静态产物并打包为standalone资源

**章节来源**
- [electron-builder.json:62-124](file://electron-builder.json#L62-L124)
- [package.json:13-26](file://package.json#L13-L26)
- [scripts/build-electron.mjs:31-73](file://scripts/build-electron.mjs#L31-L73)

## 依赖关系分析
主进程与渲染侧通过预加载桥接层建立受控通信，渲染侧类型定义来自src/types/electron.d.ts，确保IDE与TS检查的一致性。

```mermaid
graph LR
Main["electron/main.ts"] --> BW["BrowserWindow"]
Main --> IPC["ipcMain.handle(...)"]
Pre["electron/preload.ts"] --> IPC
Pre --> Types["src/types/electron.d.ts"]
Rnd["渲染侧(React)"] --> Pre
Types --> Rnd
```

**图表来源**
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)
- [src/types/electron.d.ts:1-20](file://src/types/electron.d.ts#L1-L20)

**章节来源**
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)
- [src/types/electron.d.ts:1-20](file://src/types/electron.d.ts#L1-L20)

## 性能考量
- 首屏显示：使用ready-to-show延迟显示，避免白屏，提升感知速度
- 文件系统监控：对目录变更事件进行防抖合并，降低渲染侧刷新频率
- 子进程管理：在before-quit阶段显式终止Next服务子进程，避免僵尸进程与资源泄露
- 布局计算：使用ResizeObserver与Refs避免不必要的重排与闭包捕获导致的性能问题

**章节来源**
- [electron/main.ts:161-163](file://electron/main.ts#L161-L163)
- [src/components/layout/right-sidebar.tsx:142-145](file://src/components/layout/right-sidebar.tsx#L142-L145)
- [electron/main.ts:301-310](file://electron/main.ts#L301-L310)
- [src/hooks/use-container-width.ts:10-17](file://src/hooks/use-container-width.ts#L10-L17)

## 故障排查指南
- 窗口无法显示或白屏
  - 检查ready-to-show事件是否触发以及show()调用
  - 确认webPreferences中contextIsolation已启用
  - 参考：[electron/main.ts:161-163](file://electron/main.ts#L161-L163)
- 外链点击无效或弹窗
  - 确认setWindowOpenHandler正确拦截http外链并调用shell.openExternal
  - 参考：[electron/main.ts:165-170](file://electron/main.ts#L165-L170)
- 对话框未在正确窗口中弹出
  - 使用BrowserWindow.getFocusedWindow()或主窗口作为父窗口
  - 参考：[electron/main.ts:180](file://electron/main.ts#L180)
- 文件系统监控不生效
  - 确认watchDirectory IPC已注册且未被旧监视器阻塞
  - 参考：[electron/main.ts:192-219](file://electron/main.ts#L192-L219)
- 应用退出后残留进程
  - 在before-quit中关闭FSWatcher与子进程
  - 参考：[electron/main.ts:301-310](file://electron/main.ts#L301-L310)

**章节来源**
- [electron/main.ts:161-163](file://electron/main.ts#L161-L163)
- [electron/main.ts:165-170](file://electron/main.ts#L165-L170)
- [electron/main.ts:180](file://electron/main.ts#L180)
- [electron/main.ts:192-219](file://electron/main.ts#L192-L219)
- [electron/main.ts:301-310](file://electron/main.ts#L301-L310)

## 结论
本窗口系统通过严格的主进程-预加载-渲染侧分层设计，在保证安全性的前提下实现了灵活的窗口创建、尺寸管理与多窗口协调。通过隐藏式标题栏与自绘UI、防抖文件监控与延迟显示等策略，兼顾了性能与用户体验。建议在后续版本中进一步完善沙箱配置与权限模型，以满足更严格的安全要求。

## 附录
- 类型定义：src/types/electron.d.ts声明了渲染侧可调用的API集合，便于IDE提示与类型检查
- 构建脚本：scripts/build-electron.mjs负责主进程与预加载脚本的构建与符号链接解析
- 打包配置：electron-builder.json定义了多平台目标与资源打包规则

**章节来源**
- [src/types/electron.d.ts:1-20](file://src/types/electron.d.ts#L1-L20)
- [scripts/build-electron.mjs:31-73](file://scripts/build-electron.mjs#L31-L73)
- [electron-builder.json:1-126](file://electron-builder.json#L1-L126)