Files
PR-Helper/PLAN.md
T

798 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PR-Helper 项目规划
## 1. 项目概述
**PR-Helper** 是一个 Web 服务,帮助开发者:
- 根据 Git 仓库的 commit 历史和 diff,**自动生成 PR 描述**
- 使用 AI 对代码变更进行**自动代码审查**
技术栈:Go + Gin + SQLite + HTMX + D3.js + Tailwind CSS
部署方式:Docker
---
## 2. 技术架构
```
┌─────────────────────────────────────────────────┐
│ Browser (前端) │
│ Go 模板 + HTMX + D3.js + Tailwind CSS │
└──────────────────────┬──────────────────────────┘
│ HTTP / SSE
┌──────────────────────▼──────────────────────────┐
│ Gin HTTP Server │
│ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
│ │ 仓库管理 │ │ PR 生成 │ │ AI Review │ │
│ └────┬─────┘ └────┬─────┘ └──────┬────────┘ │
│ │ │ │ │
│ ┌────▼──────────────▼───────────────▼────────┐ │
│ │ Git 操作层 (go-git) │ │
│ └────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────┐ │
│ │ LLM 调用层 (OpenAI 兼容) │ │
│ └────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────┐ │
│ │ PDF 生成层 (chromedp) │ │
│ └────────────────────────────────────────────┘ │
│ ┌────────────────────────────────────────────┐ │
│ │ SQLite 数据库 │ │
│ └────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
```
### 2.1 后端
| 组件 | 技术选型 | 说明 |
|------|---------|------|
| Web 框架 | **Gin** | Go 生态最成熟的 Web 框架 |
| Git 操作 | **go-git** | 纯 Go 实现的 Git 库,无需系统 git |
| 数据库 | **SQLite** (go-sqlite3) | 轻量级,嵌入式,适合单实例部署 |
| 模板引擎 | **html/template** | Go 标准库 |
| 后台任务 | **goroutine + channel** | 简单直接,适合单实例场景 |
### 2.2 前端
| 组件 | 技术选型 | 说明 |
|------|---------|------|
| 交互增强 | **HTMX** | 局部更新,无需 SPA 框架 |
| Git 图可视化 | **D3.js** | 完整的交互式 Git Graph |
| CSS 框架 | **Tailwind CSS** | 原子化 CSS,灵活高效 |
| 流式输出 | **SSE (Server-Sent Events)** | LLM 生成结果的打字机效果 |
### 2.3 LLM 集成
- 使用 **OpenAI 兼容 API** 格式(支持 OpenAI、Deepseek、本地 Ollama 等)
- 通过 Web 设置页面配置 API Key、Endpoint、Model
- 使用 SSE 流式输出生成结果
- 大 diff 处理策略:**分文件处理 + Top-N 结合**(按文件拆分送 LLM,优先分析变更最大的 N 个文件,最后汇总)
---
## 3. 功能模块
### 3.1 PR 描述生成
**用户流程:**
1. 用户在首页输入 Git 仓库 URL
2. 服务端 clone 仓库(带进度反馈)
3. 前端展示完整的 **D3.js Git Graph** 可视化
- 展示所有分支、标签、commit 历史
- 节点可交互(hover 显示详情)
4. 用户在 Git Graph 上选择两个点(base 和 head)
5. 服务端计算 diff,聚合 commit messages
6. LLM 生成结构化 PR 描述:
- **标题**(简洁概括变更)
- **变更类型**(feat/fix/refactor/docs/chore 等)
- **变更摘要**(概述主要改动)
- **详细说明**(按模块/文件分组描述)
- **影响范围**(受影响的功能/模块)
7. 前端结构化展示,支持**一键复制 Markdown**
**数据流:**
```
Git URL → Clone → Git Graph 选择 → Diff + Commits → LLM → 结构化 PR 描述 → Markdown 复制
```
### 3.2 AI 代码审查
**用户流程:**
1. 复用已 clone 的仓库(或新输入 URL)
2. 在 Git Graph 上选择要审查的范围(base..head)
3. **配置审查参数**(前端表单):
- Top-N 文件数:输入框,默认读取全局设置值(`20`),用户可临时修改
- 例如设为 `10` 则只分析变更最大的 10 个文件
- 设为 `0` 或留空表示分析全部文件(不截断)
- 显示当前 diff 的总文件数,提示用户是否需要调整 Top-N
4. 服务端提取 diff,按文件拆分
5. LLM 逐文件分析,流式输出审查结果
6. 输出:
- **整体评估**:变更质量评分、总体评价
- **逐文件建议**:每个文件的具体问题和改进建议
- 严重程度(🔴 严重 / 🟡 建议 / 🟢 提示)
- 问题描述
- 建议的修改方案
7. 用户可在 AI 审查结果基础上**追加备注**(不修改 AI 原始输出)
8. 支持**导出为 PDF 文档**
**大 Diff 处理策略:**
- 按文件拆分 diff
- 按变更行数排序,优先处理 Top-N 个最大变更文件
- Top-N 优先级:**用户前端输入 > 全局设置默认值(20)**
- 每个文件独立送 LLM 分析
- 最后用一个汇总 prompt 整合所有文件的审查结果
- SSE 流式输出,逐文件展示进度
### 3.2.1 审查结果在线编辑
**编辑规则:**
- AI 生成的审查结果为**只读**,不可修改
- 用户可在以下位置追加自己的备注:
- 整体评估下方:追加总体备注
- 每个文件建议下方:追加文件级备注
- 每条具体建议下方:追加针对该建议的备注
- 备注支持 Markdown 格式
- 备注实时保存到数据库
**数据模型扩展:**
```sql
-- 用户备注表
CREATE TABLE review_notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
analysis_id INTEGER REFERENCES analyses(id),
scope TEXT NOT NULL, -- 'overall' | 'file' | 'suggestion'
scope_key TEXT NOT NULL, -- 整体为空,文件名为 key,建议 ID 为 key
content TEXT NOT NULL, -- 用户备注内容(Markdown)
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
```
### 3.2.2 PDF 导出
**PDF 内容(完整报告):**
```
┌─────────────────────────────────────────┐
│ PR-Helper 审查报告 │
├─────────────────────────────────────────┤
│ 元信息 │
│ · 仓库: https://github.com/xxx/xxx │
│ · 分支: main → feature/auth │
│ · 审查时间: 2026-06-18 22:30 │
│ · 变更文件数: 15 │
│ · 变更行数: +320 / -85 │
├─────────────────────────────────────────┤
│ 整体评估 │
│ · 评分: 7/10 │
│ · AI 评价: 代码结构清晰,但存在... │
│ · 用户备注: [追加的备注内容] │
├─────────────────────────────────────────┤
│ 逐文件审查 │
│ │
│ 📄 auth/middleware.go │
│ 🟡 建议: JWT 密钥硬编码在代码中... │
│ 💬 用户备注: [追加的备注内容] │
│ │
│ 📄 auth/handler.go │
│ 🔴 严重: SQL 注入风险... │
│ 💬 用户备注: [追加的备注内容] │
│ │
│ ... │
├─────────────────────────────────────────┤
│ 代码变更 (Diff) │
│ │
│ --- a/auth/middleware.go │
│ +++ b/auth/middleware.go │
│ @@ -10,3 +10,5 @@ │
│ + func NewAuth() {...} │
│ │
│ ... │
└─────────────────────────────────────────┘
```
**技术实现:**
- 使用 **chromedp**(Go 的 headless Chrome 库)将 HTML 转为 PDF
- 服务端渲染一个专用的报告 HTML 模板(带打印样式)
- chromedp 将该 HTML 页面转为 PDF
- Docker 镜像中安装 Chromium
- PDF 生成完成后返回下载链接
**PDF 样式要求:**
- 使用 Tailwind CSS 打印友好的样式
- 代码块使用等宽字体,语法高亮
- 严重程度使用颜色区分(红/黄/绿)
- 分页合理,避免代码块被截断
- 页眉页脚包含报告标题和页码
### 3.3 Git Graph 可视化
**核心功能:**
- 使用 D3.js 绘制完整的 Git 提交图
- 节点表示 commit,边表示父子关系
- 分支和标签以彩色标签显示
- 支持交互:
- 点击节点查看 commit 详情(作者、日期、message)
- 选择两个节点作为 base/head
- 缩放和拖拽浏览大型仓库
- 分支高亮
### 3.4 设置管理页面
**配置项:**
| 配置 | 说明 | 默认值 | 存储方式 |
|------|------|--------|---------|
| API Endpoint | OpenAI 兼容 API 地址 | `https://api.openai.com/v1` | SQLite |
| API Key | API 认证密钥 | (空,必填) | SQLite |
| Model Name | 使用的模型名称 | `gpt-4o` | SQLite |
| Top-N 文件数 | 大 diff 时优先分析的最大文件数 | `20` | SQLite |
| 仓库缓存 | 已 clone 的仓库列表、大小、最后使用时间 | - | SQLite |
| 缓存过期 | 自动清理策略(如 7 天未用自动清理) | `7` 天 | SQLite |
### 3.5 Diff 查看器组件
**参考 GitHub PR Diff 设计**,提供完整的代码变更查看体验。
**整体布局:**
```
┌──────────────────────────────────────────────────────────┐
│ ┌─────────────┐ ┌────────────────────────────────────┐ │
│ │ 文件树侧栏 │ │ Diff 主区域 │ │
│ │ │ │ │ │
│ │ 📁 src/ │ │ ┌─ auth/middleware.go ────────┐ │ │
│ │ 📄 main.go │ │ │ 15 additions, 3 deletions │ │ │
│ │ 📄 auth/ │ │ ├────────────────────────────┤ │ │
│ │ 📄 mw.go │ │ │ Split View (左右对比) │ │ │
│ │ 📄 hd.go │ │ │ │ │ │
│ │ 📁 models/ │ │ │ 旧代码 (红) │ 新代码 (绿) │ │ │
│ │ 📄 user.go │ │ │ │ │ │ │
│ │ │ │ │ ... │ ... │ │ │
│ │─────────────│ │ │ │ │ │ │
│ │ 变更统计 │ │ ├─ AI Review 建议 (行内) ────┤ │ │
│ │ +320 / -85 │ │ │ 🟡 建议: JWT 密钥硬编码... │ │ │
│ │ 15 files │ │ │ 💬 [追加备注...] │ │ │
│ └─────────────┘ │ └────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─ auth/handler.go ───────────┐ │ │
│ │ │ ... │ │ │
│ │ └────────────────────────────┘ │ │
│ └────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
**文件树侧边栏:**
- 树形结构展示变更文件,按目录分组
- 每个文件显示增删行数(`+15 -3` 绿/红标签)
- 点击文件跳转到对应的 Diff 区域(平滑滚动)
- 顶部显示变更统计(总文件数、总增删行数)
- 文件树可折叠/展开目录
- 当前滚动到的文件在侧边栏高亮
**Diff 主区域(diff2html Split 视图):**
- 使用 **diff2html** 库渲染
- **Split 视图**(左右对比)为默认,支持切换到 Unified 视图
- 每个文件一个卡片,包含:
- 文件头:文件路径、变更类型(新增/修改/删除/重命名)、增删行数
- 代码区域:左右两栏对比
- **语法高亮**:diff2html 内置 highlight.js 支持
- **上下文行**:默认显示变更行前后各 3 行,可点击展开更多
- 文件头可折叠整个文件的 Diff
**AI Review 行内显示:**
- 在 AI Review 模式下,审查建议直接嵌入到对应的代码行旁边
- 类似 GitHub 的 inline comment 设计:
- 在相关代码行下方插入一个建议卡片
- 卡片包含:严重程度图标 + 建议内容
- 卡片下方有备注输入框,用户可追加备注
- 严重程度样式:
- 🔴 `critical`:红色左边框 + 浅红背景
- 🟡 `warning`:黄色左边框 + 浅黄背景
- 🟢 `info`:绿色左边框 + 浅绿背景
**交互功能:**
- 文件树点击 → 平滑滚动到对应文件
- 滚动 Diff 区域 → 侧边栏高亮当前文件
- 文件头点击 → 折叠/展开该文件
- 上下文行「展开」按钮 → 加载更多上下文
- Split/Unified 视图切换按钮
- 行号点击 → 高亮该行(用于引用讨论)
---
## 4. 数据模型
### 4.1 SQLite 表结构
```sql
-- 系统配置(KV 存储)
CREATE TABLE settings (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
-- 仓库缓存记录
CREATE TABLE repositories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
url TEXT NOT NULL UNIQUE,
local_path TEXT NOT NULL,
size_bytes INTEGER DEFAULT 0,
cloned_at DATETIME DEFAULT CURRENT_TIMESTAMP,
last_used DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 分析历史(可选,记录生成/审查历史)
CREATE TABLE analyses (
id INTEGER PRIMARY KEY AUTOINCREMENT,
repo_id INTEGER REFERENCES repositories(id),
type TEXT NOT NULL, -- 'pr_description' | 'code_review'
base_ref TEXT NOT NULL,
head_ref TEXT NOT NULL,
result TEXT, -- LLM 输出结果(Markdown)
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
```
### 4.2 配置默认值
| Key | 默认值 | 说明 |
|-----|--------|------|
| `llm.endpoint` | `https://api.openai.com/v1` | API 地址 |
| `llm.api_key` | (空) | 必须配置 |
| `llm.model` | `gpt-4o` | 默认模型 |
| `cache.max_age_days` | `7` | 缓存过期天数 |
| `cache.max_size_mb` | `5000` | 最大缓存大小 (MB) |
| `review.top_n` | `20` | 大 diff 时优先分析的文件数 |
---
## 5. API 设计
### 5.1 页面路由
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/` | 首页(输入 Git URL) |
| GET | `/repo/:id` | 仓库详情页(Git Graph + 操作) |
| GET | `/repo/:id/generate` | PR 描述生成页 |
| GET | `/repo/:id/review` | AI Review 页 |
| GET | `/settings` | 设置页面 |
### 5.2 API 路由
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/repos` | clone 仓库(返回仓库 ID + 进度 SSE) |
| GET | `/api/repos/:id/graph` | 获取 Git Graph 数据(JSON) |
| GET | `/api/repos/:id/diff` | 获取两个 ref 之间的 diff(返回文件树 + 各文件 unified diff,供 diff2html 渲染) |
| POST | `/api/repos/:id/generate` | 生成 PR 描述(SSE 流式) |
| POST | `/api/repos/:id/review` | AI Review(SSE 流式),请求体含 `base`、`head`、`top_n`(可选,默认读全局设置) |
| POST | `/api/repos/:id/review/notes` | 保存审查备注 |
| GET | `/api/repos/:id/review/notes` | 获取审查备注 |
| POST | `/api/repos/:id/review/pdf` | 生成并下载 PDF 报告 |
| GET | `/api/settings` | 获取设置 |
| PUT | `/api/settings` | 更新设置 |
| GET | `/api/repos` | 获取缓存仓库列表 |
| DELETE | `/api/repos/:id` | 删除仓库缓存 |
| POST | `/api/repos/:id/cleanup` | 手动触发缓存清理 |
### 5.3 SSE 事件格式
**Clone 进度:**
```
event: progress
data: {"step": "cloning", "progress": 45, "message": "接收对象中..."}
```
**PR 描述生成(流式):**
```
event: title
data: {"content": "feat: 添加用户认证模块"}
event: type
data: {"content": "feat"}
event: summary
data: {"content": "本次变更添加了完整的用户认证..."}
event: detail
data: {"content": "### 认证模块\n- 新增 JWT 认证中间件\n..."}
event: done
data: {"content": ""}
```
**AI Review(流式):**
```
event: file_start
data: {"file": "auth/middleware.go"}
event: suggestion
data: {
"file": "auth/middleware.go",
"line": 15, // 关联的新代码行号(用于行内定位)
"side": "right", // "left"=旧代码侧, "right"=新代码侧
"severity": "warning", // critical / warning / info
"content": "JWT 密钥硬编码在代码中,建议使用环境变量"
}
event: file_end
data: {"file": "auth/middleware.go"}
event: summary
data: {"content": "整体评估:代码结构清晰,但存在安全隐患..."}
event: done
data: {"content": ""}
```
> **行内定位说明**:`line` + `side` 用于将建议定位到 Diff 视图中的具体代码行。
> 前端 diff-viewer.js 根据这两个字段将建议卡片插入到对应行的下方。
---
## 6. 目录结构
```
PR-Helper/
├── main.go # 入口,初始化配置、数据库、路由
├── go.mod
├── go.sum
├── Dockerfile
├── docker-compose.yml
├── PLAN.md
├── CLAUDE.md
│
├── config/
│ └── config.go # 配置加载和管理
│
├── models/
│ ├── repository.go # 仓库数据模型
│ ├── settings.go # 设置数据模型
│ └── analysis.go # 分析历史模型
│
├── database/
│ └── db.go # SQLite 初始化和迁移
│
├── handlers/
│ ├── pages.go # 页面路由 handler
│ ├── repos.go # 仓库 API handler
│ ├── generate.go # PR 生成 handler(含 SSE)
│ ├── review.go # AI Review handler(含 SSE)
│ └── settings.go # 设置 API handler
│
├── services/
│ ├── git.go # Git 操作封装(clone、diff、graph)
│ ├── llm.go # LLM 调用封装(OpenAI 兼容)
│ ├── generate.go # PR 描述生成业务逻辑
│ ├── review.go # AI Review 业务逻辑
│ ├── cache.go # 仓库缓存管理(过期清理)
│ └── pdf.go # PDF 生成服务(chromedp HTML→PDF)
│
├── templates/
│ ├── layouts/
│ │ └── base.html # 基础布局模板
│ ├── pages/
│ │ ├── index.html # 首页
│ │ ├── repo.html # 仓库详情(Git Graph)
│ │ ├── generate.html # PR 生成页
│ │ ├── review.html # AI Review 页(含 Top-N 配置输入框)
│ │ └── settings.html # 设置页
│ └── partials/
│ ├── graph.html # Git Graph 组件
│ ├── diff/
│ │ ├── container.html # Diff 查看器主容器(文件树 + Diff 区域)
│ │ ├── file-tree.html # 文件树侧边栏组件
│ │ ├── file-diff.html # 单文件 Diff 卡片
│ │ └── review-inline.html # 行内 AI Review 建议卡片
│ ├── stream.html # SSE 流式展示组件
│ └── note-editor.html # 备注编辑器组件
│
├── templates/
│ └── reports/
│ └── review.html # PDF 报告专用模板(打印样式)
│
├── static/
│ ├── css/
│ │ ├── style.css # Tailwind 编译输出 + 自定义样式(含文件树、Diff 布局)
│ ├── js/
│ │ ├── graph.js # D3.js Git Graph 实现(含点击选择 base/head)
│ │ ├── diff-viewer.js # Diff 查看器逻辑(文件树联动、滚动高亮、行内建议插入)
│ │ ├── review-inline.js # 行内 Review 建议渲染 + 备注交互
│ │ ├── sse.js # SSE 连接管理(POST-based fetch+ReadableStream)
│ │ └── htmx.min.js # HTMX 库
│ └── lib/
│ ├── d3.min.js # D3.js 库
│ ├── diff2html.min.js # diff2html 库
│ ├── diff2html.min.css # diff2html 样式
│ └── highlight.min.js # highlight.js(diff2html 语法高亮依赖)
│
└── data/ # 运行时数据目录(Docker volume)
├── pr-helper.db # SQLite 数据库文件
└── repos/ # Clone 的仓库缓存
```
---
## 7. 核心流程图
### 7.1 PR 描述生成流程
```
用户输入 Git URL
│
▼
POST /api/repos ──→ goroutine: git clone
│ │
│ SSE: 进度推送
│ │
▼ ▼
仓库就绪 ◄────────── clone 完成
│
▼
GET /api/repos/:id/graph ──→ go-git: 遍历 refs/commits
│
▼
前端渲染 D3.js Git Graph
│
▼
用户选择 base..head
│
▼
GET /api/repos/:id/diff ──→ go-git: 计算 diff
│
▼
POST /api/repos/:id/generate
│
▼
goroutine:
1. 聚合 commit messages
2. 分析 diff(按文件拆分)
3. 构建 prompt
4. 调用 LLM(SSE 流式)
5. 解析结构化输出
│
▼
前端 SSE 接收 → 结构化展示 + Markdown 复制按钮
```
### 7.2 AI Review 流程
```
用户选择 base..head(复用已 clone 仓库)
│
▼
前端显示 diff 统计(总文件数、变更行数)
· Top-N 输入框,默认值 = 全局设置(20)
· 用户可修改,或留空表示分析全部
│
▼
POST /api/repos/:id/review { base, head, top_n }
│
▼
goroutine:
1. 提取 diff,按文件拆分
2. 按变更行数排序
3. 取 Top-N 文件(top_n=0 则全部)
4. 逐文件调用 LLM(SSE 流式推送每个文件的结果)
5. 最后汇总 prompt → 整体评估
│
▼
前端 SSE 接收 → 逐文件展示建议 + 整体评估
│
▼
用户追加备注(可选)
· POST /api/repos/:id/review/notes
· 支持整体/文件/建议三级备注
· Markdown 格式,实时保存
│
▼
导出 PDF(可选)
· POST /api/repos/:id/review/pdf
· 服务端渲染报告 HTML 模板
· chromedp 转 PDF
· 返回 PDF 下载链接
```
---
## 8. LLM Prompt 设计
### 8.1 PR 描述生成 Prompt
```
你是一个专业的技术文档撰写助手。根据以下 Git 变更信息,生成一份结构化的 PR 描述。
## Commit 记录
{{range .Commits}}
- {{.Hash}} {{.Message}}
{{end}}
## 代码变更 (Diff)
{{.Diff}}
请按以下 JSON 格式输出:
{
"title": "简洁的 PR 标题",
"type": "变更类型: feat|fix|refactor|docs|chore|style|test|perf",
"summary": "一段话概述变更内容",
"details": "详细的变更说明,按模块分组,使用 Markdown 格式",
"impact": "影响范围说明"
}
```
### 8.2 AI Review Prompt(单文件)
```
你是一个资深代码审查专家。请审查以下代码变更,给出专业的 Review 意见。
## 文件: {{.FileName}}
## 变更类型: {{.ChangeType}}
## Diff
{{.Diff}}
请按以下格式输出审查意见:
- 严重程度: critical / warning / info
- 问题描述: 清晰描述问题
- 建议修改: 具体的修改建议(如有)
- 代码示例: 建议的代码(如有)
如果没有问题,说明代码质量良好。
请用中文回复。
```
### 8.3 AI Review 汇总 Prompt
```
以下是多个文件的代码审查结果,请给出整体评估:
{{range .FileReviews}}
### {{.FileName}}
{{.ReviewResult}}
{{end}}
请输出:
1. 整体评分(1-10)
2. 总体评价(2-3 句话)
3. 主要发现汇总(按严重程度排序)
4. 改进建议优先级列表
```
---
## 9. Docker 部署
### 9.1 Dockerfile
```dockerfile
# 构建阶段
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=1 go build -o pr-helper .
# 运行阶段
FROM alpine:3.19
RUN apk add --no-cache ca-certificates sqlite chromium
ENV CHROME_BIN=/usr/bin/chromium-browser
WORKDIR /app
COPY --from=builder /app/pr-helper .
COPY --from=builder /app/templates ./templates
COPY --from=builder /app/static ./static
VOLUME ["/app/data"]
EXPOSE 8080
CMD ["./pr-helper"]
```
> **注意**:chromedp 需要 Chromium。Docker 镜像中通过 `apk add chromium` 安装。
> 如果使用 Debian/Ubuntu 基础镜像,改用 `apt-get install chromium`。
> 也可以使用 `chromedp/headless-shell` 作为 sidecar 容器。
### 9.2 docker-compose.yml
```yaml
version: '3.8'
services:
pr-helper:
build: .
ports:
- "8080:8080"
volumes:
- pr-helper-data:/app/data
environment:
- GIN_MODE=release
restart: unless-stopped
volumes:
pr-helper-data:
```
---
## 10. 开发阶段
> **当前进度**:Phase 1-5 已完成,Phase 6 待完善
>
> - ✅ Phase 1(基础骨架):Go 项目、Gin 路由、SQLite、设置页面
> - ✅ Phase 2(Git 核心):clone、refs、diff、graph 数据、缓存管理
> - ✅ Phase 3(前端交互):Git Graph、Diff 查看器、文件树、SSE 流式展示、行内建议
> - ✅ Phase 4(LLM 集成):OpenAI 兼容 API、PR 描述生成、AI 代码审查、Top-N 策略
> - ✅ Phase 5(审查编辑与导出):备注编辑器、备注 CRUD API、PDF 报告生成
> - ⚠️ Phase 6(完善与部署):Docker 配置已完成,其他待完善
### Phase 1:基础骨架 ✅ 已完成
- [x] Go 项目初始化(go mod、目录结构)
- [x] Gin 路由和基础中间件
- [x] SQLite 数据库初始化和迁移
- [x] 基础 HTML 模板布局(Tailwind CSS)
- [x] 设置页面(LLM 配置)
### Phase 2:Git 核心 ✅ 已完成
- [x] go-git 集成:clone 仓库(SSE 进度推送)
- [x] go-git 集成:获取 refs、commits
- [x] go-git 集成:计算 diff
- [x] Git Graph 数据提取(构建节点和边)
- [x] 仓库缓存管理(过期清理)
### Phase 3:前端交互 ✅ 已完成
- [x] D3.js Git Graph 可视化(graph.js)
- [x] Diff 查看器组件(diff2html Split 视图)(diff-viewer.js)
- [x] 交互式分支/commit 选择(base/head 选择,点击 Graph 节点选择)
- [x] 文件树侧边栏(树形结构、点击跳转、滚动高亮联动)
- [x] Split/Unified 视图切换
- [x] AI Review 行内建议展示(嵌入代码行旁)
- [x] SSE 流式展示组件(sse.js)
### Phase 4:LLM 集成 ✅ 已完成
- [x] OpenAI 兼容 API 调用封装(services/llm.go)
- [x] PR 描述生成(prompt + SSE 流式)(services/generate.go)
- [x] AI 代码审查(分文件处理 + 汇总)(services/review.go)
- [x] 大 diff 处理(Top-N 策略)
### Phase 5:审查编辑与导出 ✅ 已完成
- [x] 备注编辑器组件(Markdown 支持,三级作用域)
- [x] 备注 CRUD API(保存/读取)
- [x] PDF 报告 HTML 模板(打印样式)
- [x] chromedp HTML→PDF 生成服务
- [x] PDF 下载接口
### Phase 6:完善与部署 ⚠️ 部分完成
- [ ] 错误处理和用户提示
- [x] Dockerfile + docker-compose(含 Chromium)
- [ ] 文档和使用说明
- [ ] 测试和优化
---
## 11. 关键依赖
```go
// go.mod 关键依赖
require (
github.com/gin-gonic/gin // Web 框架
github.com/mattn/go-sqlite3 // SQLite 驱动
github.com/go-git/go-git/v5 // Git 操作
github.com/sashabaranov/go-openai // OpenAI API 客户端
github.com/chromedp/chromedp // headless Chrome,HTML 转 PDF
)
```
前端(CDN 或本地):
- HTMX 2.x
- D3.js 7.x
- diff2html 3.x(Diff 渲染,内置 split/unified 视图 + 语法高亮)
- highlight.js 11.x(diff2html 依赖,代码语法高亮)
- Tailwind CSS 3.x(CLI 编译)
---
## 12. 注意事项
1. **安全性**:无认证设计意味着不应暴露到公网,仅限内网/本地使用
2. **性能**:大仓库 clone 可能耗时较长,需要进度反馈;考虑 shallow clone 选项
3. **LLM 成本**:大 diff 的 token 消耗可能很高,Top-N 策略控制成本
4. **并发**:goroutine 管理需要考虑优雅关闭和 panic 恢复
5. **存储**:仓库缓存可能占用大量磁盘空间,过期清理策略很重要