From 11ffdc2bb5e1fdef6cbd43858dec3236b91f02d7 Mon Sep 17 00:00:00 2001 From: JOJO <1498581755@qq.com> Date: Wed, 15 Jul 2026 04:37:26 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E6=B5=AE=E5=8A=A8?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E4=BD=8D=E7=BD=AE=E8=AE=A1=E7=AE=97=E4=B8=8E?= =?UTF-8?q?=20token=20=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../personalization/PersonalizationDrawer.vue | 63 ++++++++++++------- utils/context_manager/token_mixin.py | 12 +++- 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/static/src/components/personalization/PersonalizationDrawer.vue b/static/src/components/personalization/PersonalizationDrawer.vue index 92d5057..0883b27 100644 --- a/static/src/components/personalization/PersonalizationDrawer.vue +++ b/static/src/components/personalization/PersonalizationDrawer.vue @@ -2301,32 +2301,52 @@ const updateFloatingMenuPosition = async () => { const padding = 16; const gap = 10; - const menuHeight = menu?.getBoundingClientRect().height || 0; - let top: number; - if (menuHeight > 0) { - const spaceBelow = window.innerHeight - rect.bottom - padding; - const spaceAbove = rect.top - padding; - if (spaceBelow >= menuHeight) { - top = rect.bottom + gap; - } else if (spaceAbove >= menuHeight) { - top = rect.top - menuHeight - gap; - } else if (spaceBelow >= spaceAbove) { - // 下方空间相对更大:菜单贴底部,内容通过 max-height 滚动 - top = Math.max(rect.bottom + gap, window.innerHeight - menuHeight - padding); - } else { - // 上方空间相对更大:菜单贴顶部 - top = padding; - } - } else { - top = Math.max(padding, Math.min(rect.bottom + gap, window.innerHeight - 80)); + + // 测量单个选项高度,计算 4 选项固定 max-height + const optionEl = menu?.querySelector('.settings-menu-option'); + const optionHeight = optionEl ? optionEl.getBoundingClientRect().height : 44; + const menuPadding = 12; // menu padding 6px top + 6px bottom + const fixedMaxHeight = Math.round(optionHeight * 4) + menuPadding; + + // 先限制菜单高度为固定值,再次获取实际高度 + if (menu) { + menu.style.maxHeight = `${fixedMaxHeight}px`; } + // 重新读取受限后的菜单高度 + const menuHeight = menu?.getBoundingClientRect().height || fixedMaxHeight; + + const spaceBelow = window.innerHeight - rect.bottom - padding; + const spaceAbove = rect.top - padding; + + let top: number; + let maxHeight: number | undefined; + + if (spaceBelow >= menuHeight) { + // 下方空间足够完整显示 + top = rect.bottom + gap; + } else if (spaceAbove >= menuHeight) { + // 上方空间足够完整显示,翻转到上方 + top = rect.top - menuHeight - gap; + } else if (spaceBelow >= spaceAbove) { + // 上下都不够,下方空间相对更大:限制高度到可用空间,贴按钮向下 + const availableHeight = Math.max(80, spaceBelow - gap); + maxHeight = availableHeight; + top = rect.bottom + gap; + } else { + // 上方空间相对更大:限制高度到可用空间,翻转到上方 + const availableHeight = Math.max(80, spaceAbove - gap); + maxHeight = availableHeight; + top = Math.max(padding, rect.top - availableHeight - gap); + } + floatingMenuStyle.value = { position: 'fixed', top: `${Math.round(top)}px`, left: `${Math.round(left)}px`, right: 'auto', width: `${Math.round(menuWidth)}px`, - zIndex: '2147483647' + zIndex: '2147483647', + ...(maxHeight !== undefined ? { maxHeight: `${Math.round(maxHeight)}px` } : {}) }; }; @@ -3713,8 +3733,9 @@ const applyDefaultHideWorkspaceOption = async (hidden: boolean) => { right: auto; top: auto; width: 300px; - max-height: min(420px, 60vh); - overflow: auto; + max-height: calc(44px * 4 + 12px); + overflow-y: auto; + overflow-x: hidden; padding: 6px; border-radius: 20px; background: var(--settings-floating-menu-bg); diff --git a/utils/context_manager/token_mixin.py b/utils/context_manager/token_mixin.py index a0f74d9..8310bf9 100644 --- a/utils/context_manager/token_mixin.py +++ b/utils/context_manager/token_mixin.py @@ -144,17 +144,23 @@ class TokenMixin: return False try: - success = self.conversation_manager.update_token_statistics( + # 路由到正确的 conversation_manager(与 get_conversation_token_statistics 一致) + # 多智能体对话 ID 存储在 multi_agent_conversation_manager 中, + # 直接使用 self.conversation_manager 会找不到对话导致统计写入失败 + target_manager = getattr( + self, "_get_conversation_manager_for_id", lambda _: self.conversation_manager + )(self.current_conversation_id) + success = target_manager.update_token_statistics( self.current_conversation_id, prompt_tokens, completion_tokens, total_tokens, current_context_tokens=current_context_tokens, ) - + if success: self.safe_broadcast_token_update() - + return success except Exception as e: print(f"更新usage统计失败: {e}")