fix(web): 修复滚动到底部未生效的问题,并优化 markdown 渲染 padding

This commit is contained in:
Wenjie Zhang 2026-03-03 00:05:28 +08:00
parent a4e5486e51
commit b144b72de0
6 changed files with 45 additions and 27 deletions

View File

@ -7,19 +7,12 @@
- 集成 LangFuse (观望) 添加用户日志与用户反馈模块,可以在 AgentView 中查看信息
- 集成 neo4j mcp (或者自己构建工具)
- chat_model 的 call 需要异步
- 优化智能体文件系统:
- 使用 CompositeBackend 和 自定义后端系统,链接 minio 中的知识库文件。提供除检索以外的方法
- 考虑修改附件的处理逻辑,考虑使用文件系统,将附件解析后放到文件系统中,智能体按需读取(当前是完全解析,放进上下文)
- 【后续】用户可以使用 @ 来引用附件,例如 @file:reports.md 相较于现在的处理逻辑感觉会更加自然一点。
- skills 如何实现还需要继续调研
- 增加 paddle-vl 以及 deepseek-ocr 的支持deepseek-ocr 已支持),重构 OCR 的支持情况,并支持 Paddle 官方的解析 API https://aistudio.baidu.com/paddleocr/task
- 系统层面添加 apikey在智能体、知识库调用中支持 apikey 以支持外部调用
- 支持更多类型的文档源的导入功能(支持后端配置的白名单的 URL 导入)
- 部分场景应该使用默认模型作为默认值而不是空值
- 文件上传解析后,如何提示用户需要入库
- 检索测试中,添加问答
- 丰富当前智能体的 Prompt最好支持从 markdown 解析
- 探索 subagents 的体系
### Bugs
@ -33,6 +26,10 @@
- FileTable 的自动刷新失效
- 生成基准测试会把所有的向量都计算一遍不合理
## v0.6
## v0.5
### 新增
@ -50,6 +47,7 @@
- 优化 liaghtrag 的知识库调用结果,提供 content/graph/both 多个选项
- 优化数据库查询工具,可通过设计环境变量添加描述,让模型更好的调用
- 优化任务组件,改用 postgresql 存储,并新增删除任务的接口
- 支持更多类型的文档源的导入功能(支持后端配置的白名单的 URL 导入)
### 修复

View File

@ -49,11 +49,4 @@
font-weight: 600;
}
}
}
// 背景透明场景
.flat-md-preview--transparent {
.md-editor {
background: transparent;
}
}
}

View File

@ -40,7 +40,7 @@
@click="$emit('toggle-panel')"
title="查看工作状态"
>
<FolderCode :size="14" />
<FolderCode :size="18" />
<span>状态</span>
</div>
</div>
@ -187,7 +187,7 @@ defineExpose({
padding: 0 8px;
height: 28px;
border-radius: 8px;
font-size: 13px;
font-size: 14px;
color: var(--gray-600);
cursor: pointer;
transition: all 0.2s ease;

View File

@ -793,7 +793,6 @@ const stopResize = () => {
max-height: 60vh;
overflow-y: auto;
border-radius: 6px;
padding: 16px;
&::-webkit-scrollbar {
width: 8px;

View File

@ -6,7 +6,7 @@
:footer="null"
:destroyOnClose="true"
wrap-class-name="chunk-detail-modal"
:bodyStyle="{ maxHeight: '72vh', overflowY: 'auto', padding: '12px 16px' }"
:bodyStyle="{ maxHeight: '72vh', overflowY: 'auto', padding: '0' }"
>
<div v-if="chunk" class="detail-meta">
<span v-if="typeof chunk.score === 'number'" class="score"

View File

@ -68,12 +68,25 @@ export class ScrollController {
}, this.options.scrollDelay)
}
/**
* 等待 DOM 布局稳定
* @returns {Promise<void>}
*/
async waitForLayoutStable() {
// 使用 requestAnimationFrame 确保 DOM 渲染完成
await new Promise((resolve) => requestAnimationFrame(resolve))
// 额外等待一小段时间确保 CSS 布局完成
await new Promise((resolve) => setTimeout(resolve, 50))
}
/**
* 智能滚动到底部
* @param {boolean} force - 是否强制滚动
*/
async scrollToBottom(force = false) {
await nextTick()
// 等待 DOM 布局稳定
await this.waitForLayoutStable()
// 只有在应该自动滚动时才执行(除非强制)
if (!force && !this.shouldAutoScroll) return
@ -84,6 +97,9 @@ export class ScrollController {
// 标记为程序性滚动
this.isProgrammaticScroll = true
// 记录滚动前的容器高度
const initialHeight = container.scrollHeight
const scrollOptions = {
top: container.scrollHeight,
behavior: 'smooth'
@ -92,16 +108,28 @@ export class ScrollController {
// 立即滚动
container.scrollTo(scrollOptions)
// 多次重试确保滚动成功
this.options.retryDelays.forEach((delay, index) => {
// 多次重试确保滚动成功,包括等待输入框等动态元素布局完成
const retryDelays = [50, 100, 200, 400]
retryDelays.forEach((delay, index) => {
setTimeout(() => {
if (force || this.shouldAutoScroll) {
this.isProgrammaticScroll = true
const behavior = index === this.options.retryDelays.length - 1 ? 'auto' : 'smooth'
container.scrollTo({
top: container.scrollHeight,
behavior
})
const behavior = index === retryDelays.length - 1 ? 'auto' : 'smooth'
// 如果高度变化了,说明可能有动态内容正在渲染,再次等待
if (container.scrollHeight !== initialHeight && index < retryDelays.length - 1) {
this.waitForLayoutStable().then(() => {
container.scrollTo({
top: container.scrollHeight,
behavior
})
})
} else {
container.scrollTo({
top: container.scrollHeight,
behavior
})
}
}
}, delay)
})