---
name: chat_block_scroll_anchor
description: 当需要优化聊天区域块展开/折叠滚动行为，或排查向上滚动后瞬间跳回问题时，应该索引本记忆
---

# 聊天区域块展开/折叠滚动行为优化记录

## 背景
聊天区域默认使用 `vue-stick-to-bottom` 保持底部锁定。块（thinking/tool）展开/折叠时，`stick-to-bottom` 的弹簧追底动画和 CSS 高度过渡不同步，会产生「向下展开一点、向上滚动一点」的顿挫感。

## 已尝试方案

### 1. 块展开锚定（useBlockExpansionAnchor）
- 在 `static/src/composables/useBlockExpansionAnchor.ts` 中实现
- 块展开/折叠的 CSS 过渡期间（约 260–300ms），用 `requestAnimationFrame` 持续覆盖 `scrollTop`
- 目标：让被操作块的底边或顶边保持在原来视口位置
- 方向判断：
  - 用**底边**判断比顶边更准确。高块即使顶边位于上半，底边仍可能在下半；用顶边判断会把高块误判为 `down` 模式
  - `up` 模式：底边不动，头部向上展开
  - `down` 模式：顶边不动，内容向下展开
- 方向在单次展开-收起周期内记忆（`preferredModes`），保证收起是展开的倒放；收起动画结束后清除记录

### 2. 运行期间策略
- 运行中的 thinking/tool 块（带 `.processing`/`.running`/`.thinking-animation`）保持旧逻辑，由 `stick-to-bottom` 追底，避免被输入栏遮挡
- 非运行中的块（包括运行期间的历史块）走锚定逻辑
- 已实现 commit：`f43b5ea7 fix(chat): 运行期间恢复旧滚动逻辑，堆叠块更多按钮也接入锚定`

### 3. 堆叠块「更多」按钮
- `StackedBlocks.vue` 在 toggleMore 时 emit `more-toggle`，`ChatArea.vue` 监听后对 more-block 元素启动锚定
- 注意：事件 payload 里的展开状态应使用 `payload.expanded`，避免 `ReferenceError`

## 未解决的向上滚动跳回问题

### 现象
- 在块较多的对话中，**向上滚动**后页面会瞬间跳回滚动前的位置
- 向下滚动不会出现
- 禁用 `anchorBlockElement` 调用、禁用 wheel-up 时的 `stopScroll()` 后问题依然存在

### 调试结论
- 不是 `anchorBlockElement` 直接导致
- 不是 `stopScroll()` 直接导致
- `heightDelta` 可能为负（内容高度减小），但 large-growth 检测未触发
- `escapedFromLock` 已为 `true`，`stick-state-change` 未出现异常变化
- 原因未最终定位，可能与 `vue-stick-to-bottom` 内部状态、浏览器原生滚动行为或内容高度变化后的布局抖动有关

## 当前代码状态
- 当前 HEAD：`f43b5ea7 fix(chat): 运行期间恢复旧滚动逻辑，堆叠块更多按钮也接入锚定`
- 工作区干净，所有调试和临时修改已撤回，stash 已清空
- 后续若继续优化，建议从 `f43b5ea7` 开始，并优先定位向上滚动跳回的根本原因
