mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-26 13:19:34 +07:00
156 lines
4.9 KiB
Plaintext
156 lines
4.9 KiB
Plaintext
---
|
||
description: 当要做 electron 相关工作时
|
||
globs:
|
||
alwaysApply: false
|
||
---
|
||
|
||
# 桌面端新功能实现指南
|
||
|
||
## 桌面端应用架构概述
|
||
|
||
LobeChat 桌面端基于 Electron 框架构建,采用主进程-渲染进程架构:
|
||
|
||
1. **主进程 (Main Process)**:
|
||
- 位置:`apps/desktop/src/main`
|
||
- 职责:控制应用生命周期、系统API交互、窗口管理、后台服务
|
||
|
||
2. **渲染进程 (Renderer Process)**:
|
||
- 复用 Web 端代码,位于 `src` 目录
|
||
- 通过 IPC 与主进程通信
|
||
|
||
3. **预加载脚本 (Preload)**:
|
||
- 位置:`apps/desktop/src/preload`
|
||
- 职责:安全地暴露主进程功能给渲染进程
|
||
|
||
## 添加新桌面端功能流程
|
||
|
||
### 1. 确定功能需求与设计
|
||
|
||
首先确定新功能的需求和设计,包括:
|
||
|
||
- 功能描述和用例
|
||
- 是否需要系统级API(如文件系统、网络等)
|
||
- UI/UX设计(如必要)
|
||
- 与现有功能的交互方式
|
||
|
||
### 2. 在主进程中实现核心功能
|
||
|
||
1. **创建控制器 (Controller)**
|
||
- 位置:`apps/desktop/src/main/controllers/`
|
||
- 示例:创建 `NewFeatureCtr.ts`
|
||
- 需继承 `ControllerModule`,并设置 `static readonly groupName`(例如 `static override readonly groupName = 'newFeature';`)
|
||
- 按 `_template.ts` 模板格式实现,并在 `apps/desktop/src/main/controllers/registry.ts` 的 `controllerIpcConstructors` 中注册,保证类型推导与自动装配
|
||
|
||
2. **定义 IPC 事件处理器**
|
||
- 使用 `@IpcMethod()` 装饰器暴露渲染进程可访问的通道
|
||
- 通道名称基于 `groupName.methodName` 自动生成,不再手动拼接字符串
|
||
- 处理函数可通过 `getIpcContext()` 获取 `sender`、`event` 等上下文信息,并按照需要返回结构化结果
|
||
|
||
3. **实现业务逻辑**
|
||
- 可能需要调用 Electron API 或 Node.js 原生模块
|
||
- 对于复杂功能,可以创建专门的服务类 (`services/`)
|
||
|
||
### 3. 定义 IPC 通信类型
|
||
|
||
1. **在共享类型定义中添加新类型**
|
||
- 位置:`packages/electron-client-ipc/src/types.ts`
|
||
- 添加参数类型接口(如 `NewFeatureParams`)
|
||
- 添加返回结果类型接口(如 `NewFeatureResult`)
|
||
|
||
### 4. 在渲染进程实现前端功能
|
||
|
||
1. **创建服务层**
|
||
- 位置:`src/services/electron/`
|
||
- 添加服务方法调用 IPC
|
||
- 使用 `ensureElectronIpc()` 生成的类型安全代理,避免手动拼通道名称
|
||
|
||
```typescript
|
||
// src/services/electron/newFeatureService.ts
|
||
import type { NewFeatureParams } from '@lobechat/electron-client-ipc';
|
||
|
||
import { ensureElectronIpc } from '@/utils/electron/ipc';
|
||
|
||
const ipc = ensureElectronIpc();
|
||
|
||
export const newFeatureService = async (params: NewFeatureParams) => {
|
||
return ipc.newFeature.doSomething(params);
|
||
};
|
||
```
|
||
|
||
2. **实现 Store Action**
|
||
- 位置:`src/store/`
|
||
- 添加状态更新逻辑和错误处理
|
||
|
||
3. **添加 UI 组件**
|
||
- 根据需要在适当位置添加UI组件
|
||
- 通过 Store 或 Service 层调用功能
|
||
|
||
### 5. 如果是新增内置工具,遵循工具实现流程
|
||
|
||
参考 `desktop-local-tools-implement.mdc` 了解更多关于添加内置工具的详细步骤。
|
||
|
||
### 6. 添加测试
|
||
|
||
1. **单元测试**
|
||
- 位置:`apps/desktop/src/main/controllers/__tests__/`
|
||
- 测试主进程组件功能
|
||
|
||
2. **集成测试**
|
||
- 测试 IPC 通信和功能完整流程
|
||
|
||
## 最佳实践
|
||
|
||
1. **安全性考虑**
|
||
- 谨慎处理用户数据和文件系统访问
|
||
- 适当验证和清理输入数据
|
||
- 限制暴露给渲染进程的API范围
|
||
|
||
2. **性能优化**
|
||
- 对于耗时操作,考虑使用异步方法
|
||
- 大型数据传输考虑分批处理
|
||
|
||
3. **用户体验**
|
||
- 为长时间操作添加进度指示
|
||
- 提供适当的错误反馈
|
||
- 考虑操作的可撤销性
|
||
|
||
4. **代码组织**
|
||
- 遵循项目现有的命名和代码风格约定
|
||
- 为新功能添加适当的文档和注释
|
||
- 功能模块化,避免过度耦合
|
||
|
||
## 示例:实现系统通知功能
|
||
|
||
```typescript
|
||
// apps/desktop/src/main/controllers/NotificationCtr.ts
|
||
import type {
|
||
DesktopNotificationResult,
|
||
ShowDesktopNotificationParams,
|
||
} from '@lobechat/electron-client-ipc';
|
||
import { Notification } from 'electron';
|
||
|
||
import { ControllerModule, IpcMethod } from '@/controllers';
|
||
|
||
export default class NotificationCtr extends ControllerModule {
|
||
static override readonly groupName = 'notification';
|
||
|
||
@IpcMethod()
|
||
async showDesktopNotification(
|
||
params: ShowDesktopNotificationParams,
|
||
): Promise<DesktopNotificationResult> {
|
||
if (!Notification.isSupported()) {
|
||
return { error: 'Notifications not supported', success: false };
|
||
}
|
||
|
||
try {
|
||
const notification = new Notification({ body: params.body, title: params.title });
|
||
notification.show();
|
||
return { success: true };
|
||
} catch (error) {
|
||
console.error('[NotificationCtr] Failed to show notification:', error);
|
||
return { error: error instanceof Error ? error.message : 'Unknown error', success: false };
|
||
}
|
||
}
|
||
}
|
||
```
|