diff --git a/bricks/agent.js b/bricks/agent.js index 225d469..1a3b1a7 100644 --- a/bricks/agent.js +++ b/bricks/agent.js @@ -327,6 +327,31 @@ bricks.AgentIO = class extends bricks.VBox { this.inputw.bind('inputed', this.user_inputed.bind(this)); this.add_widget(this.msg_box); this.add_widget(this.inputw); + // 用户上翻看历史时暂停跟滚,滚回底部恢复(scroll_to_bottom 依据 _follow) + this.msg_box.bind('scroll', this._track_follow.bind(this)); + } + // 会话区保持最后输出可见(2026-09-01):内容超出显示范围时自动滚到底。 + // 仅当用户本就停在底部附近才跟滚——用户主动上翻看历史时不强行拉回; + // 滚回底部或发送新消息后恢复跟滚。rAF 延迟到本帧布局完成后滚, + // 保证 scrollHeight 已是新内容的尺寸(同步滚会拿到旧高度)。 + scroll_to_bottom(){ + if (this._scroll_pending) return; + this._scroll_pending = true; + requestAnimationFrame(function(){ + this._scroll_pending = false; + var e = this.msg_box && this.msg_box.dom_element; + if (!e) return; + if (this._follow === false) { + var near_bottom = (e.scrollHeight - e.scrollTop - e.clientHeight) < 80; + if (!near_bottom) return; + } + e.scrollTop = e.scrollHeight; + }.bind(this)); + } + _track_follow(){ + var e = this.msg_box && this.msg_box.dom_element; + if (!e) return; + this._follow = (e.scrollHeight - e.scrollTop - e.clientHeight) < 80; } chunk_response(mout, l){ l = l.trim(); @@ -338,6 +363,7 @@ bricks.AgentIO = class extends bricks.VBox { } console.log('l=', l, 'd=', d); mout.update_data(d); + this.scroll_to_bottom(); } chunk_ended(){ console.log('chunk end'); @@ -395,6 +421,9 @@ bricks.AgentIO = class extends bricks.VBox { box.add_widget(w); box.add_widget(img); this.msg_box.add_widget(box); + // 用户刚发的消息必须可见:强制跟滚到底 + this._follow = true; + this.scroll_to_bottom(); } }