楼层、时间轴与历史
时间轴定位
时间轴同步当前楼层、日期和主题总楼层:
- 点击或拖动轨道可连续选择目标;
- 点击
#可输入楼层号,输入范围随主题总楼层更新;无效、超出范围或非整数输入不会提交; - 目标楼层未加载时,阅读器先补齐数据和虚拟窗口;
- 跳转会等待最新目标的数据、DOM 挂载和可见位置安静,并继续把锚点结算到 2 px 内;旧请求不会在随后覆盖新目标,新目标或用户直接滚动会取消旧结算;
- 跳转完成后目标楼层按设置闪烁;
- 点击相对时间可直接拉到帖子物理底部;长帖尚未完整加载时,阅读器会从 canonical 尾段按需向前补齐,找到最后一个主信息流正文根,不会把楼中楼尾楼或当前缓存尾部误作主题终点;
- 移动端点击任一楼层的相对时间会通过统一提示层显示具体日期时间;点击正文或其他控件会关闭提示,不会在正式楼层、楼中楼和离线文档中各维护一套状态;
- 到达真实底部后会显示“已经见底了~”,并连续结算 Reader 的物理最大滚动位置,不依赖最后正文卡片持续挂载;首次补尾的回复树投影短暂未就绪时,同一次点击仍会继续完成见底;
- 底部回顶按钮返回当前主题顶部,而不是宿主页面顶部。
大量楼层快速跳转需要经过“获取数据 → 挂载目标 → 定位”的顺序。不要在第一次等待时连续重复点击,否则会产生互相覆盖的目标。
直接触控或拖动滚动条时,虚拟窗口会在同一帧收到最后滚动位置提示;请求返回、图片展开和回复线变化产生的楼层尺寸会在滚动停稳后批量提交。前方多层正文也按批次共用一次投影与视口补偿,避免一边滚动一边逐楼层争抢位置而出现短暂空白、卡顿或上下跳位。

时间轴位于阅读工作区右侧:拖动滑块选择楼层,观察当前楼层与日期,底部按钮返回主题顶部。
只看楼主
标题区域显示楼主信息时,可以开启“只看楼主”。阅读器会:
- 仅在主信息流中展示楼主楼层;
- 保留目标跳转和过滤进度;
- 必要时补充尚未取得的楼主楼层;
- 关闭后恢复普通信息流。
从消息跳到非楼主楼层时,阅读器可能临时解除过滤,确保目标可见。
历史前后切换
阅读器保存主题 ID、标题、最近阅读锚点、首次查看和最后查看时间。左右按钮按历史链前进或后退,并恢复对应位置。
带侧键的鼠标可以直接使用“后退”键进入更早的阅读记录,使用“前进”键回到更新的阅读记录。阅读器打开时会拦截这两个按键的浏览器默认历史跳转;没有可用目标时只显示提示,不会离开当前页面。
0.1.15 的阅读锚点不再只有楼层号,还会记录当前虚拟流视口及偏移、完整讨论窗口的根楼层与分支位置,以及仍有效的引用高亮。切换到另一个主题前会先捕获当前状态,返回时再按“分支上下文 → 目标楼层 → 精确偏移”的顺序恢复。1.5.9 会在数据与 DOM 安静 120 ms 后继续结算,最长等待 2 秒;新的导航目标或用户滚动会立即取消旧恢复。文档标题随当前主题更新,关闭 Reader 后恢复宿主页面标题。
Reader 工作区获得焦点时,ArrowUp、ArrowDown、PageUp、PageDown、Home 和 End 由唯一滚动 owner 同步处理;输入框、按钮、编辑器等原生交互控件继续保留浏览器默认行为。

历史面板显示保存的主题和最近位置;阅读器边缘的前后按钮沿同一条历史链切换,不按主题列表顺序切换。
“设置 → 阅读与导航 → 历史前进与后退”提供:
- 始终显示前进和后退按钮;
- 边缘唤出按钮范围,范围 0%–15%;
- 最近打开排序或首次打开固定排序。
边缘触发只控制按钮何时出现,不改变历史顺序。
真实已读进度
阅读器在楼层正文成功预加载后只把它加入候选。候选必须在当前聚焦、前台可见的 Reader 视口内正面积相交并累计停留至少 1 秒,才进入 pending 并在当前阅读器中显示乐观已读;快速擦过、后台标签和失焦窗口不会取得上报资格。这个状态只用于当前会话的界面和阅读排序,不会在服务器确认前写入帖子缓存的权威 read 字段。
当前版本的已读上报:
- 每批最多提交 20 个楼层;
- 默认限制为同账号跨标签 10 RPM / 240 TPM;除滚动分钟上限外,RPM 还形成确定性最小启动间隔(默认至少 6 秒);普通 pending 不由定时器匀速排空,达到限制后保留到窗口释放,并由新的真实 Reader 可见活动继续;
- 按实际前台停留分别累计每个楼层的 timing 与独立
topic_time,并通过不可丢的后台请求让位于真实交互; - 已取得资格的楼层即使随后离屏也保留到服务器确认,跨标签成功账本避免同账号重复提交;
- 浏览器锁先合并同主题并发意图,但每个实际网络批次仍严格不超过 20 层;同一次可见活动留下的 backlog 不会自动连续续批;
- 阅读器打开时抑制原站 screen-track 对同一主题的重复计时;
- 只有服务器确认成功后才写入权威已读状态;失败楼层保留待重试,Cloudflare 验证失败时仍保持未确认。
这些约束让真正阅读过的候选有界进入 /topics/timings 批次,同时用真实计时、每批上限、滚动窗口 RPM/TPM、成功账本和跨标签锁减少重复请求。乐观已读不等于服务器已经确认;联网失败时最终状态仍以原站为准。
新回复到达时,主题活动与阅读器状态会同步;只有确认存在新楼层时,接近底部的阅读器才自动跟随,单纯刷新元数据不会改变滚动位置。原站创建或编辑帖子、切换回应时,阅读器还会让对应主题、楼层和回应缓存失效,当前主题则就地合并权威楼层。消息跳转会等待目标进入虚拟窗口后再定位。
主题分类、投票和队列
- 标题横向区域显示当前主题的父分类、分类和标签;SVG 图标会先安全内联,无法解析或不安全的图标会被丢弃,不影响文字链接。
- 站点启用 Topic Voting 时,同一区域显示当前票数;登录用户可以投票或取消投票,提交期间入口保持禁用,结果以服务端返回为准。
- 阅读队列用于准备接下来要读的多个主题,并在当前浏览器中跨刷新恢复。
- 浏览历史用于跨会话恢复已读主题和位置。
阅读队列与历史使用同一套锚点模型。队列切走当前主题时会保存完整位置;再次进入时,除非链接明确指定起始楼层,否则优先恢复完整讨论或主信息流视口。
当地址栏在同一主题内从一个楼层路由变到另一个楼层路由时,已经打开的阅读器会直接跳到新楼层,不会重新创建整个阅读工作区。重复的 Discourse 页面变化信号会按当前路由去重;原站搜索菜单中只有真实主题或楼层结果会被接管,搜索建议及其他菜单链接保持原生行为。

需要连续阅读多篇文章时打开队列面板;点击队列项切换主题,并通过进度与预加载状态判断是否已经准备完成。
三者用途不同,但最终都进入同一个受缓存和请求调度约束的阅读工作区。
