275e5cc886
- 01-architecture.md: 架构概览 - 02-backend-services.md: 后端服务层 - 03-frontend-interaction.md: 前端交互设计 - 04-database-design.md: 数据库设计 - 05-api-reference.md: API 接口文档 - 06-sse-streaming.md: SSE 流式传输 - 07-llm-integration.md: LLM 集成 - 08-deployment.md: 部署运维 - 09-development-guide.md: 开发指南 - 10-troubleshooting.md: 故障排查
340 lines
5.8 KiB
Markdown
340 lines
5.8 KiB
Markdown
# 前端交互设计
|
||
|
||
## 概述
|
||
|
||
PR-Helper 前端采用渐进式增强设计,结合 HTMX、D3.js、diff2html 等库,提供流畅的交互体验。
|
||
|
||
## 技术栈
|
||
|
||
| 技术 | 用途 |
|
||
|------|------|
|
||
| Go html/template | 服务端渲染 |
|
||
| HTMX 2.x | 动态交互 |
|
||
| D3.js 7.x | Git 图形可视化 |
|
||
| diff2html 3.x | 差异渲染 |
|
||
| highlight.js 11.x | 语法高亮 |
|
||
| marked.js | Markdown 渲染 |
|
||
| Tailwind CSS | 样式框架 |
|
||
|
||
## 核心组件
|
||
|
||
### 1. SSE 客户端 (sse.js)
|
||
|
||
#### 设计目标
|
||
|
||
- 支持 POST 请求的 SSE(EventSource 只支持 GET)
|
||
- 流式读取响应体
|
||
- 事件分发机制
|
||
|
||
#### API 设计
|
||
|
||
```javascript
|
||
const SSE = {
|
||
async post(url, body, handlers = {}) {
|
||
// 返回 controller,支持 abort()
|
||
return { abort: () => controller.abort() };
|
||
}
|
||
};
|
||
|
||
// 使用示例
|
||
SSE.post('/api/repos/1/review', { base: 'main', head: 'feature' }, {
|
||
start: (data) => console.log('开始', data),
|
||
content: (data) => console.log('内容', data.content),
|
||
suggestion: (data) => console.log('建议', data),
|
||
summary: (data) => console.log('汇总', data),
|
||
done: () => console.log('完成'),
|
||
error: (data) => console.error('错误', data.message)
|
||
});
|
||
```
|
||
|
||
#### 实现细节
|
||
|
||
- 使用 `fetch()` + `ReadableStream`
|
||
- 手动解析 SSE 协议(event: / data:)
|
||
- 支持中断请求
|
||
- 自动处理 JSON 解析
|
||
|
||
### 2. Git 图形 (graph.js)
|
||
|
||
#### 功能特性
|
||
|
||
- D3.js SVG 渲染
|
||
- 多分支彩色泳道
|
||
- 交互式 base/head 选择
|
||
- 分支标签右对齐
|
||
- 图例显示
|
||
|
||
#### 布局算法
|
||
|
||
```javascript
|
||
assignLanes() {
|
||
// 1. HEAD 分支获得泳道 0
|
||
// 2. 其他分支按顺序分配泳道
|
||
// 3. 合并提交的第二父提交获得新泳道
|
||
// 4. 未访问的提交分配到泳道 0
|
||
}
|
||
```
|
||
|
||
#### 交互设计
|
||
|
||
- **点击**: 选择 base/head 提交
|
||
- **悬停**: 高亮节点
|
||
- **选择状态**:
|
||
- 绿色: base 提交
|
||
- 橙色: head 提交
|
||
- 蓝色: 普通提交
|
||
|
||
#### 回调机制
|
||
|
||
```javascript
|
||
gitGraph.onSelectionChange = (baseHash, headHash) => {
|
||
// 更新 base/head 选择
|
||
// 触发差异加载
|
||
};
|
||
```
|
||
|
||
### 3. 差异查看器 (diff-viewer.js)
|
||
|
||
#### 功能特性
|
||
|
||
- diff2html 渲染
|
||
- 文件树侧边栏
|
||
- 增量渲染(非阻塞)
|
||
- 懒加载语法高亮
|
||
- 滚动同步
|
||
- 大型差异保护
|
||
|
||
#### 增量渲染
|
||
|
||
```javascript
|
||
_renderBatch(outputFormat, startIndex) {
|
||
const FILES_PER_BATCH = 5;
|
||
// 每帧渲染 5 个文件
|
||
// 使用 requestAnimationFrame
|
||
// 避免阻塞主线程
|
||
}
|
||
```
|
||
|
||
#### 大型差异保护
|
||
|
||
```javascript
|
||
_isTooLarge(files) {
|
||
const MAX_FILES = 300;
|
||
const MAX_LINES = 10000;
|
||
return files.length > MAX_FILES || (totalAdd + totalDel) > MAX_LINES;
|
||
}
|
||
```
|
||
|
||
- 超过阈值显示警告
|
||
- 用户确认后强制渲染
|
||
- 避免浏览器卡顿
|
||
|
||
#### 文件树
|
||
|
||
- 目录折叠/展开
|
||
- 文件类型图标
|
||
- 变更统计(+/-)
|
||
- 严重程度标记
|
||
|
||
#### 滚动同步
|
||
|
||
```javascript
|
||
_setupScrollSpy() {
|
||
// IntersectionObserver 监听文件可见性
|
||
// 自动高亮侧边栏对应文件
|
||
// 点击侧边栏滚动到文件
|
||
}
|
||
```
|
||
|
||
### 4. 内联建议 (review-inline.js)
|
||
|
||
#### 功能
|
||
|
||
- 在差异中嵌入 AI 建议
|
||
- 按严重程度着色
|
||
- 支持文件级和行级建议
|
||
|
||
#### 插入机制
|
||
|
||
```javascript
|
||
insertSuggestion(filename, line, side, severity, content, suggestionId) {
|
||
// 1. 懒加载文件索引
|
||
// 2. 查找目标行
|
||
// 3. 创建建议卡片
|
||
// 4. 插入到行后
|
||
}
|
||
```
|
||
|
||
#### 严重程度样式
|
||
|
||
```javascript
|
||
const severityStyles = {
|
||
critical: 'border-l-4 border-red-500 bg-red-50',
|
||
warning: 'border-l-4 border-yellow-500 bg-yellow-50',
|
||
info: 'border-l-4 border-green-500 bg-green-50',
|
||
};
|
||
```
|
||
|
||
### 5. Markdown 渲染 (markdown.js)
|
||
|
||
#### 功能
|
||
|
||
- 使用 marked.js 渲染
|
||
- 代码块语法高亮
|
||
- 支持内联代码
|
||
|
||
#### 集成
|
||
|
||
```javascript
|
||
function renderMarkdown(text) {
|
||
return marked.parse(text, {
|
||
highlight: function(code, lang) {
|
||
return hljs.highlightAuto(code).value;
|
||
}
|
||
});
|
||
}
|
||
```
|
||
|
||
### 6. 笔记编辑器 (note-editor.js)
|
||
|
||
#### 功能
|
||
|
||
- 内联编辑审查笔记
|
||
- 自动保存
|
||
- 三种作用域
|
||
|
||
## 页面结构
|
||
|
||
### 首页 (/)
|
||
|
||
- 仓库列表
|
||
- 克隆表单
|
||
- 快速操作
|
||
|
||
### 仓库详情页 (/repo/:id)
|
||
|
||
- Git 图形
|
||
- 分支选择器
|
||
- 差异查看器
|
||
- PR 生成
|
||
- AI 代码审查
|
||
|
||
### 设置页 (/settings)
|
||
|
||
- LLM 配置
|
||
- 审查参数
|
||
- 缓存设置
|
||
|
||
## HTMX 集成
|
||
|
||
### 动态加载
|
||
|
||
```html
|
||
<div hx-get="/api/repos/1/graph" hx-trigger="load">
|
||
<!-- 图形将在这里渲染 -->
|
||
</div>
|
||
```
|
||
|
||
### 表单提交
|
||
|
||
```html
|
||
<form hx-post="/api/repos" hx-target="#repo-list">
|
||
<input type="text" name="url" required>
|
||
<button type="submit">克隆</button>
|
||
</form>
|
||
```
|
||
|
||
### 事件触发
|
||
|
||
```html
|
||
<button hx-post="/api/repos/1/pull"
|
||
hx-trigger="click"
|
||
hx-indicator="#spinner">
|
||
拉取更新
|
||
</button>
|
||
```
|
||
|
||
## 响应式设计
|
||
|
||
### 断点
|
||
|
||
- 移动端: < 640px
|
||
- 平板: 640px - 1024px
|
||
- 桌面: > 1024px
|
||
|
||
### 适配策略
|
||
|
||
- 文件树侧边栏可折叠
|
||
- 差异查看器自适应宽度
|
||
- 图形可横向滚动
|
||
|
||
## 性能优化
|
||
|
||
### 1. 增量渲染
|
||
|
||
- 分批渲染文件
|
||
- requestAnimationFrame
|
||
- 避免长任务阻塞
|
||
|
||
### 2. 懒加载
|
||
|
||
- 语法高亮按需执行
|
||
- 文件索引按需构建
|
||
- IntersectionObserver
|
||
|
||
### 3. 虚拟滚动
|
||
|
||
- 大型差异只渲染可见部分
|
||
- 减少 DOM 节点数
|
||
|
||
### 4. 缓存
|
||
|
||
- 静态资源缓存
|
||
- API 响应缓存
|
||
- 本地状态缓存
|
||
|
||
## 错误处理
|
||
|
||
### 网络错误
|
||
|
||
- 显示错误消息
|
||
- 提供重试按钮
|
||
- 自动重连(SSE)
|
||
|
||
### 渲染错误
|
||
|
||
- 降级到纯文本
|
||
- 显示原始数据
|
||
- 记录错误日志
|
||
|
||
## 无障碍
|
||
|
||
### 键盘导航
|
||
|
||
- Tab 切换焦点
|
||
- Enter 确认选择
|
||
- Escape 取消操作
|
||
|
||
### 屏幕阅读器
|
||
|
||
- ARIA 标签
|
||
- 语义化 HTML
|
||
- 焦点管理
|
||
|
||
## 浏览器兼容性
|
||
|
||
### 支持的浏览器
|
||
|
||
- Chrome 90+
|
||
- Firefox 88+
|
||
- Safari 14+
|
||
- Edge 90+
|
||
|
||
### 依赖的现代 API
|
||
|
||
- fetch
|
||
- ReadableStream
|
||
- IntersectionObserver
|
||
- requestAnimationFrame
|
||
- CSS Grid/Flexbox
|