init: consolidate all ephron.ren PRDs and docs

This commit is contained in:
Ubuntu
2026-05-15 10:39:54 +08:00
parent 9568533314
commit ee8cddf8b8
21 changed files with 6991 additions and 2 deletions

View File

@@ -0,0 +1,161 @@
# 博客目录高亮逻辑优化
> **版本**: v1.0
> **日期**: 2026-05-06
> **状态**: ✅ 已修复
---
## 一、问题描述
### 1.1 现象
博客正文页右侧目录的高亮逻辑存在边界问题当点击小标题H3页面正确滚动到该位置但目录实际高亮的是上方的大标题H2
### 1.2 复现步骤
1. 访问博客文章(如 `/posts/hermes-chrome-opencode-ai-agent-bug`
2. 找到一个小标题H3和它上方的大标题H2非常接近的章节
3. 点击目录中的小标题
4. 观察右侧目录的高亮状态
**预期行为**:小标题被高亮
**实际行为**:大标题被高亮
### 1.3 影响范围
- 影响所有博客文章页
- 影响标题间距较小的章节
---
## 二、根因分析
### 2.1 原始代码
```javascript
function updateTocHighlight() {
let current = '';
headings.forEach(heading => {
const rect = heading.getBoundingClientRect();
if (rect.top <= 80) {
current = heading.id;
}
});
}
```
### 2.2 问题根因
1. 当点击小标题H3H3 滚动到 `rect.top = 80`scroll-margin-top
2. 由于滚动精度问题H3 的 `rect.top` 可能是 `80.5``81`
3. 原逻辑使用 `<= 80` 判断H3 不满足条件
4. 而上方的 H2 满足条件(`rect.top <= 80`
5. 结果高亮选中了 H2
**核心问题**:阈值判断是硬性的,没有考虑滚动精度误差。
---
## 三、解决方案
### 3.1 方案对比
| 方案 | 实现 | 优点 | 缺点 |
|------|------|------|------|
| A. 扩大阈值 | `<= 82` | 简单 | 仍可能有边界问题 |
| B. 距离最近算法 | 选择距离 80px 最近的标题 | 精确 | 稍复杂 |
| C. 滚动后手动设置 | 点击时直接设置高亮 | 确定性高 | 需要额外逻辑 |
### 3.2 采用方案:距离最近算法
**原理**遍历所有标题找到距离目标位置80px最近的那个标题。
**实现**
```javascript
function updateTocHighlight() {
const SCROLL_OFFSET = 80;
let current = '';
let minDistance = Infinity;
headings.forEach(heading => {
const rect = heading.getBoundingClientRect();
// 只考虑在视口上方或接近顶部的标题
if (rect.top <= SCROLL_OFFSET + 20) {
// 计算距离目标位置的绝对值
const distance = Math.abs(rect.top - SCROLL_OFFSET);
// 选择距离最近的标题
if (distance < minDistance) {
minDistance = distance;
current = heading.id;
}
}
});
}
```
**优点**
- 精确:选择距离目标位置最近的标题
- 鲁棒:不受滚动精度影响
- 直观:符合用户预期
---
## 四、实现细节
### 4.1 修改文件
- `blog/templates/post.html`:修改 `updateTocHighlight()` 函数
### 4.2 算法说明
1. **目标位置**`SCROLL_OFFSET = 80px`(导航栏高度 64px + 留白 16px
2. **候选范围**`rect.top <= SCROLL_OFFSET + 20`(即 <= 100px
3. **选择标准**`Math.abs(rect.top - SCROLL_OFFSET)` 最小的标题
### 4.3 边界情况
- **标题在视口上方**rect.top < 0距离计算为 `|负数 - 80|`,值较大,不会被选中
- **标题恰好在 80px**:距离为 0优先选中
- **标题在 80px 以下**:不满足 `<= 100` 条件,不参与计算
---
## 五、测试验证
### 5.1 测试用例
| 编号 | 测试步骤 | 预期结果 |
|------|---------|---------|
| T-001 | 点击 H3 标题(与 H2 间距 < 50px | H3 被高亮 |
| T-002 | 点击 H2 标题 | H2 被高亮 |
| T-003 | 滚动页面(不点击) | 最接近顶部的标题被高亮 |
| T-004 | 快速连续点击多个标题 | 每次点击后高亮正确 |
### 5.2 验证方法
1. 部署后访问博客文章
2. 找到 H2 和 H3 间距较小的章节
3. 点击目录中的 H3
4. 确认 H3 被高亮(而非 H2
---
## 六、优先级与排期
| 优先级 | 任务 | 状态 |
|--------|------|------|
| P0 | 修改高亮算法 | ✅ 已完成 |
| P1 | 测试验证 | 待部署后验证 |
---
## 附录
### A. 相关文件
- `blog/templates/post.html`:目录生成和高亮逻辑
### B. 参考资料
- [MDN: getBoundingClientRect()](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect)