fix: 修复 agents 页面侧边栏切回后自动关闭
This commit is contained in:
parent
ccf0d98eb6
commit
cd47227888
@ -57,6 +57,7 @@
|
||||
- 调整对话配置入口与侧边栏头尾交互:输入区配置按钮改为轻量 dropdown 触发器,默认保持透明、hover 才出现背景;下拉中直接提供配置切换、新建配置,以及查看/编辑当前配置的入口。配置侧边栏则移除头部配置切换和新建入口,改为仅显示当前配置名称、可点击星标和关闭图标,并将删除操作下沉到底部保存按钮右侧。
|
||||
- 为历史线程补充前端本地配置变更提示:当已有历史消息的对话中切换 Agent、切换配置或编辑任意配置项时,在聊天消息流中插入一条非持久化的信息提示,提醒继续在当前线程运行可能影响最终效果,建议新建对话;提示仅保留在前端当前线程状态中,不写入后端历史消息。后续补齐了 3 个关键边界:提示插入时主动滚动到底部确保可见、历史消息尚未加载完成时先挂起提示并在加载完成后落地、流式回复过程中切换配置时将提示锚定在当时完整对话流之后,避免把正在生成的回复错误归因到新配置。
|
||||
- 调整 Worker run 模式下的消息首屏反馈:前端发送消息时先乐观渲染用户消息,再将前端生成的 `request_id` 透传给 `/api/chat/runs` 与服务端 `init` 对账;“正在生成回复”动画改为仅在收到 `init` 确认后展示,修复 worker 轮询延迟导致的先转圈、后出现用户消息的问题。后续又补齐了线程切换场景:后端持久化 user message 时同步写入 `request_id`,前端在合并历史消息与 ongoing 消息时按 `request_id` 去掉重复的首条 human message,避免切回运行中的线程后出现连续两个 user message。
|
||||
- 修复 agents 页对话侧边栏在 `keep-alive` 路由切换后的误关闭问题:`AgentChatComponent` 的宽度监听现在会在页面 deactivated 时断开、activated 时重连,并忽略隐藏态的 `0` 宽度,避免从其他页面切回 `/agent` 时把用户持久化的侧边栏打开状态错误覆盖为关闭。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -281,7 +281,18 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, watch, nextTick, computed, onUnmounted, h } from 'vue'
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
onMounted,
|
||||
watch,
|
||||
nextTick,
|
||||
computed,
|
||||
onUnmounted,
|
||||
onActivated,
|
||||
onDeactivated,
|
||||
h
|
||||
} from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import AgentInputArea from '@/components/AgentInputArea.vue'
|
||||
import AgentMessageComponent from '@/components/AgentMessageComponent.vue'
|
||||
@ -902,6 +913,69 @@ const isSidebarFloating = ref(false)
|
||||
let chatMainResizeObserver = null
|
||||
// 初始化延迟标志,避免首次挂载时 ResizeObserver 立即触发导致侧边栏意外关闭
|
||||
let isResizeObserverReady = false
|
||||
let resizeObserverReadyTimer = null
|
||||
|
||||
const armResizeObserver = () => {
|
||||
if (resizeObserverReadyTimer) {
|
||||
clearTimeout(resizeObserverReadyTimer)
|
||||
}
|
||||
|
||||
isResizeObserverReady = false
|
||||
// keep-alive 切页回来时等布局稳定后再恢复宽度判断,避免隐藏态宽度污染侧边栏状态。
|
||||
resizeObserverReadyTimer = setTimeout(() => {
|
||||
isResizeObserverReady = true
|
||||
}, 50)
|
||||
}
|
||||
|
||||
const stopChatMainResizeObserver = () => {
|
||||
if (resizeObserverReadyTimer) {
|
||||
clearTimeout(resizeObserverReadyTimer)
|
||||
resizeObserverReadyTimer = null
|
||||
}
|
||||
|
||||
isResizeObserverReady = false
|
||||
|
||||
if (chatMainResizeObserver) {
|
||||
chatMainResizeObserver.disconnect()
|
||||
chatMainResizeObserver = null
|
||||
}
|
||||
}
|
||||
|
||||
const startChatMainResizeObserver = () => {
|
||||
if (!window.ResizeObserver || !chatMainRef.value || chatMainResizeObserver) {
|
||||
return
|
||||
}
|
||||
|
||||
localUIState.chatMainWidth = chatMainRef.value.clientWidth || window.innerWidth
|
||||
chatMainResizeObserver = new ResizeObserver((entries) => {
|
||||
// 初始化期间跳过检查,等待 layout 稳定
|
||||
if (!isResizeObserverReady) return
|
||||
|
||||
for (const entry of entries) {
|
||||
const width = entry.contentRect.width
|
||||
if (!width) continue
|
||||
|
||||
localUIState.chatMainWidth = width
|
||||
const isTakingSpace = chatUIStore.isSidebarOpen && !isSidebarFloating.value
|
||||
|
||||
if (isTakingSpace) {
|
||||
if (width < 600) {
|
||||
isSidebarFloating.value = true
|
||||
chatUIStore.isSidebarOpen = false
|
||||
localStorage.setItem('chat_sidebar_open', 'false')
|
||||
}
|
||||
} else {
|
||||
if (width >= 880) {
|
||||
isSidebarFloating.value = false
|
||||
} else {
|
||||
isSidebarFloating.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
chatMainResizeObserver.observe(chatMainRef.value)
|
||||
armResizeObserver()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
@ -910,50 +984,26 @@ onMounted(() => {
|
||||
chatMainContainer.addEventListener('scroll', scrollController.handleScroll, { passive: true })
|
||||
}
|
||||
|
||||
if (window.ResizeObserver && chatMainRef.value) {
|
||||
localUIState.chatMainWidth = chatMainRef.value.clientWidth || window.innerWidth
|
||||
chatMainResizeObserver = new ResizeObserver((entries) => {
|
||||
// 初始化期间跳过检查,等待 layout 稳定
|
||||
if (!isResizeObserverReady) return
|
||||
|
||||
for (const entry of entries) {
|
||||
const width = entry.contentRect.width
|
||||
localUIState.chatMainWidth = width
|
||||
const isTakingSpace = chatUIStore.isSidebarOpen && !isSidebarFloating.value
|
||||
|
||||
if (isTakingSpace) {
|
||||
if (width < 600) {
|
||||
isSidebarFloating.value = true
|
||||
chatUIStore.isSidebarOpen = false
|
||||
localStorage.setItem('chat_sidebar_open', 'false')
|
||||
}
|
||||
} else {
|
||||
if (width >= 880) {
|
||||
isSidebarFloating.value = false
|
||||
} else {
|
||||
isSidebarFloating.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
chatMainResizeObserver.observe(chatMainRef.value)
|
||||
}
|
||||
|
||||
// 延迟 50ms 后启用 ResizeObserver 检查,确保 layout 已稳定
|
||||
setTimeout(() => {
|
||||
isResizeObserverReady = true
|
||||
}, 50)
|
||||
startChatMainResizeObserver()
|
||||
})
|
||||
setTimeout(() => {
|
||||
localUIState.isInitialRender = false
|
||||
}, 300)
|
||||
})
|
||||
|
||||
onActivated(() => {
|
||||
nextTick(() => {
|
||||
startChatMainResizeObserver()
|
||||
})
|
||||
})
|
||||
|
||||
onDeactivated(() => {
|
||||
stopChatMainResizeObserver()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
scrollController.cleanup()
|
||||
if (chatMainResizeObserver) {
|
||||
chatMainResizeObserver.disconnect()
|
||||
}
|
||||
stopChatMainResizeObserver()
|
||||
if (sendCooldownTimer) {
|
||||
clearTimeout(sendCooldownTimer)
|
||||
sendCooldownTimer = null
|
||||
|
||||
Loading…
Reference in New Issue
Block a user