贡献指南
感谢你有兴趣为 Elftia 做贡献。本文档介绍参与开发的完整流程。
开发环境搭建
详细步骤参见 本地开发 指南。快速摘要:
{/* 前提条件 */}
{/* Node.js v24(见 .nvmrc)+ 原生构建工具 */}
git clone <repo-url> elftia
cd elftia
npm install
cp .env.example .env
npm run dev
分支策略
| 分支 | 用途 | 保护规则 |
|---|---|---|
main | 稳定版本,随时可发布 | 需要 PR + Review |
dev/* | 功能开发分支 | - |
fix/* | 缺陷修复分支 | - |
分支命名
{/* 新功能 */}
git checkout -b dev/feature-name
{/* 缺陷修复 */}
git checkout -b fix/bug-description
{/* 示例 */}
git checkout -b dev/notes-feature
git checkout -b fix/chat-scroll-issue
代码规范
完整规范参见 代码规范。核心要点:
ESLint
- error 级别规则阻止提交(import 排序、
no-var、eqeqeq、prefer-const、Hook 规则) - warn 级别规则允许提交但建议修复
- 提交前 Husky 自动运行
eslint --fix
文件大小
| 文件类型 | 推荐上限 | 禁止超过 |
|---|---|---|
| React 组件 | 400 行 | 800 行 |
| 自定义 Hook | 300 行 | 600 行 |
| 工具函数 | 150 行 | 300 行 |
| 类型定义 | 100 行 | 200 行 |
| Service | 300 行 | 600 行 |
命名
- 组件:PascalCase(
UserMessage.tsx) - Hook:usePascalCase(
useChatActions.ts) - 目录:kebab-case(
chat-messages/) - 语义化 Token(禁止硬编码颜色)
提交规范
使用 Conventional Commits 格式:
<type>: <description>
[optional body]
[optional footer]
类型说明
| 类型 | 说明 | 示例 |
|---|---|---|
feat | 新功能 | feat: add notes export feature |
fix | 缺陷修复 | fix: resolve chat scroll position reset |
refactor | 重构 | refactor: split ChatInterface into smaller components |
docs | 文档 | docs: update IPC channels reference |
style | 代码格式(不影响逻辑) | style: fix import ordering |
test | 测试 | test: add unit tests for useFavorites |
chore | 构建/工具变动 | chore: update Vite to v7.1 |
示例
git commit -m "feat: add favorites feature with session-scoped bookmarks
- Add FavoritesService with SQLite persistence
- Add FavoritesRouter with Zod validation
- Add useFavorites hook and FavoritesList component
- Add i18n support for en/zh/ja"
Pull Request 要求
基本原则
- 一个 PR 只做一件事 — 不要混合功能开发和 bug 修复
- Tests — 新功能包含测试
- Docs — 必要时更新文档
- CI Pass — 所有检查通过
PR 标题
简洁描述变更,使用 Conventional Commits 格式:
feat: add favorites feature
fix: resolve chat message duplication
refactor: extract message rendering into separate components
PR 描述模板
## 变更内容
- 简要描述变更 1
- 简要描述变更 2
## 测试方式
- [ ] 手动测试步骤 1
- [ ] 手动测试步骤 2
- [ ] 单元测试通过
## 截图(如有 UI 变更)
新功能开发检查清单
完整端到端流程参见 添加新功能。
后端
| 步骤 | 文件位置 | 说明 |
|---|---|---|
| 1. 共享类型 | packages/desktop/app/shared/contracts/ | 前后端共用的类型定义 |
| 2. Service | packages/desktop/app/main/services/ | 业务逻辑封装 |
| 3. Router | packages/desktop/app/main/services/routers/ | IPC 路由 + Zod 校验 |
| 4. 注册 | routers/index.ts → registerAllRouters() | 创建实例并注册 |
| 5. Preload | packages/desktop/app/preload/index.ts | 暴露到前端 |
前端
| 步骤 | 文件位置 | 说明 |
|---|---|---|
| 1. Hook | packages/renderer/src/features/<feature>/hooks/(跨功能放 shared/hooks/) | 数据获取和状态管理 |
| 2. 组件 | packages/renderer/src/features/<feature>/components/(共享 UI 在 components/ui/) | UI 渲染 |
| 3. 路由 | app/lazy/ (pages.tsx 等) + app/App.tsx | 新页面需要懒加载注册(旧 import 路径 from '../lazy' 通过 lazy/index.ts barrel 仍然兼容) |
| 4. i18n | packages/renderer/src/locales/{en,zh,ja}/ | 三语言翻译 |
文档
| 条件 | 需要更新 |
|---|---|
| 新增模块 | .claude/skills/architecture-index/SKILL.md |
| 用户可见功能 | docs/elfi-kb/ 知识库 |
| 新增路由 | docs/elfi-kb/INDEX.md 映射表 |
Code Review 关注点
前后端分离
- 前端是否只传递用户输入和配置参数?
- 后端是否负责所有外部调用?
- 返回数据是否为最终形态?
- 是否避免了 base64 等大数据在 IPC 中来回传输?
安全
- Router 参数是否经过 Zod 校验?
- API Key 是否仅在主进程中使用?
- 是否有潜在的 XSS 风险?
文件大小
- 新文件是否在推荐上限内?
- 修改后的文件是否超过警戒线?
- 是否需要拆分?
错误处理
- 网络请求是否有 try-catch?
- 错误信息是否对用户友好?
- 是否有适当的 loading 状态和空状态?
文档
- 是否更新了架构索引?
- 是否更新了知识库?
- i18n 是否三语言同步?
Bug 报告
报告模板
## 环境
- 操作系统: Windows 11 / macOS 15 / Ubuntu 24
- Elftia 版本: v0.5.0
- Node.js 版本: v24.x
## 复现步骤
1. 打开设置页面
2. 切换到「外观」选项卡
3. 点击壁纸设置
4. 选择图片后...
## 预期行为
壁纸应该正常显示。
## 实际行为
壁纸未显示,控制台报错:TypeError: Cannot read property 'path' of undefined
## 附加信息
- 诊断数据导出(设置 → 高级 → 导出诊断数据)
- 截图或录屏
- 控制台错误日志
诊断数据导出
在应用中导出诊断数据以帮助排查问题:
设置 → 高级 → 诊断工具 → 导出诊断数据
或通过 DevTools Console:
const data = await window.api.diagnostics.bundle({ includeLogs: true });
联系方式
- 项目 Issues — 功能请求和 Bug 报告
- Pull Requests — 代码贡献
- Discussions — 技术讨论和提问