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: 故障排查
5.8 KiB
5.8 KiB
前端交互设计
概述
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 设计
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 选择
- 分支标签右对齐
- 图例显示
布局算法
assignLanes() {
// 1. HEAD 分支获得泳道 0
// 2. 其他分支按顺序分配泳道
// 3. 合并提交的第二父提交获得新泳道
// 4. 未访问的提交分配到泳道 0
}
交互设计
- 点击: 选择 base/head 提交
- 悬停: 高亮节点
- 选择状态:
- 绿色: base 提交
- 橙色: head 提交
- 蓝色: 普通提交
回调机制
gitGraph.onSelectionChange = (baseHash, headHash) => {
// 更新 base/head 选择
// 触发差异加载
};
3. 差异查看器 (diff-viewer.js)
功能特性
- diff2html 渲染
- 文件树侧边栏
- 增量渲染(非阻塞)
- 懒加载语法高亮
- 滚动同步
- 大型差异保护
增量渲染
_renderBatch(outputFormat, startIndex) {
const FILES_PER_BATCH = 5;
// 每帧渲染 5 个文件
// 使用 requestAnimationFrame
// 避免阻塞主线程
}
大型差异保护
_isTooLarge(files) {
const MAX_FILES = 300;
const MAX_LINES = 10000;
return files.length > MAX_FILES || (totalAdd + totalDel) > MAX_LINES;
}
- 超过阈值显示警告
- 用户确认后强制渲染
- 避免浏览器卡顿
文件树
- 目录折叠/展开
- 文件类型图标
- 变更统计(+/-)
- 严重程度标记
滚动同步
_setupScrollSpy() {
// IntersectionObserver 监听文件可见性
// 自动高亮侧边栏对应文件
// 点击侧边栏滚动到文件
}
4. 内联建议 (review-inline.js)
功能
- 在差异中嵌入 AI 建议
- 按严重程度着色
- 支持文件级和行级建议
插入机制
insertSuggestion(filename, line, side, severity, content, suggestionId) {
// 1. 懒加载文件索引
// 2. 查找目标行
// 3. 创建建议卡片
// 4. 插入到行后
}
严重程度样式
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 渲染
- 代码块语法高亮
- 支持内联代码
集成
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 集成
动态加载
<div hx-get="/api/repos/1/graph" hx-trigger="load">
<!-- 图形将在这里渲染 -->
</div>
表单提交
<form hx-post="/api/repos" hx-target="#repo-list">
<input type="text" name="url" required>
<button type="submit">克隆</button>
</form>
事件触发
<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