From b144b72de0fa96aafdb6c7a5fa1be8efb9a904e6 Mon Sep 17 00:00:00 2001 From: Wenjie Zhang Date: Tue, 3 Mar 2026 00:05:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20=E4=BF=AE=E5=A4=8D=E6=BB=9A?= =?UTF-8?q?=E5=8A=A8=E5=88=B0=E5=BA=95=E9=83=A8=E6=9C=AA=E7=94=9F=E6=95=88?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20markdown=20=E6=B8=B2=E6=9F=93=20padding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/latest/changelog/roadmap.md | 14 +++---- web/src/assets/css/markdown-preview.less | 9 +--- web/src/components/AgentInputArea.vue | 4 +- web/src/components/AgentPanel.vue | 1 - .../components/sources/KbChunkDetailModal.vue | 2 +- web/src/utils/scrollController.js | 42 +++++++++++++++---- 6 files changed, 45 insertions(+), 27 deletions(-) diff --git a/docs/latest/changelog/roadmap.md b/docs/latest/changelog/roadmap.md index a3c850ce..4cba2bba 100644 --- a/docs/latest/changelog/roadmap.md +++ b/docs/latest/changelog/roadmap.md @@ -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 导入) ### 修复 diff --git a/web/src/assets/css/markdown-preview.less b/web/src/assets/css/markdown-preview.less index 9708fbd2..e1408b54 100644 --- a/web/src/assets/css/markdown-preview.less +++ b/web/src/assets/css/markdown-preview.less @@ -49,11 +49,4 @@ font-weight: 600; } } -} - -// 背景透明场景 -.flat-md-preview--transparent { - .md-editor { - background: transparent; - } -} +} \ No newline at end of file diff --git a/web/src/components/AgentInputArea.vue b/web/src/components/AgentInputArea.vue index 4fea3789..a3f0be4e 100644 --- a/web/src/components/AgentInputArea.vue +++ b/web/src/components/AgentInputArea.vue @@ -40,7 +40,7 @@ @click="$emit('toggle-panel')" title="查看工作状态" > - + 状态 @@ -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; diff --git a/web/src/components/AgentPanel.vue b/web/src/components/AgentPanel.vue index 476b28b4..4984c21b 100644 --- a/web/src/components/AgentPanel.vue +++ b/web/src/components/AgentPanel.vue @@ -793,7 +793,6 @@ const stopResize = () => { max-height: 60vh; overflow-y: auto; border-radius: 6px; - padding: 16px; &::-webkit-scrollbar { width: 8px; diff --git a/web/src/components/sources/KbChunkDetailModal.vue b/web/src/components/sources/KbChunkDetailModal.vue index d1626618..cd58bd84 100644 --- a/web/src/components/sources/KbChunkDetailModal.vue +++ b/web/src/components/sources/KbChunkDetailModal.vue @@ -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' }" >
} + */ + 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) })