From 458a19a55dfd699b0513dc483c0cd75daa59276c Mon Sep 17 00:00:00 2001 From: 2977094657 <2977094657@qq.com> Date: Mon, 16 Mar 2026 12:34:58 +0800 Subject: [PATCH] =?UTF-8?q?fix(chat-ui):=20=E4=BF=AE=E5=A4=8D=E5=8F=B3?= =?UTF-8?q?=E9=94=AE=E8=8F=9C=E5=8D=95=E8=B6=8A=E7=95=8C=E5=92=8C=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E6=A8=A1=E5=BC=8F=E7=8A=B6=E6=80=81=E4=B8=A2?= =?UTF-8?q?=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为聊天右键菜单增加视口内重定位,避免菜单显示到屏幕外 - 在异步加载编辑状态后重新计算位置,并限制菜单高度支持滚动 - 补回 searchContext 状态传递,恢复上下文模式下的筛选禁用和提示横幅 --- frontend/components/chat/ChatOverlays.vue | 3 +- frontend/composables/chat/useChatEditing.js | 49 ++++++++++++++++++++- frontend/pages/chat/[[username]].vue | 1 + 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/frontend/components/chat/ChatOverlays.vue b/frontend/components/chat/ChatOverlays.vue index 6820f54..0b8999e 100644 --- a/frontend/components/chat/ChatOverlays.vue +++ b/frontend/components/chat/ChatOverlays.vue @@ -1086,7 +1086,8 @@
diff --git a/frontend/composables/chat/useChatEditing.js b/frontend/composables/chat/useChatEditing.js index 50221ae..2d11360 100644 --- a/frontend/composables/chat/useChatEditing.js +++ b/frontend/composables/chat/useChatEditing.js @@ -1,4 +1,6 @@ -import { ref, toRaw } from 'vue' +import { nextTick, ref, toRaw } from 'vue' + +const CONTEXT_MENU_MARGIN = 8 const initialContextMenu = () => ({ visible: false, @@ -45,6 +47,7 @@ export const useChatEditing = ({ locateMessageByServerId }) => { const contextMenu = ref(initialContextMenu()) + const contextMenuElement = ref(null) const messageEditModal = ref(initialMessageEditModal()) const messageFieldsModal = ref(initialMessageFieldsModal()) @@ -52,6 +55,44 @@ export const useChatEditing = ({ contextMenu.value = initialContextMenu() } + const repositionContextMenu = () => { + if (!process.client || !contextMenu.value.visible) return + const menuEl = contextMenuElement.value + if (!menuEl) return + + const rect = menuEl.getBoundingClientRect() + const viewportWidth = Math.max(window.innerWidth || 0, document.documentElement?.clientWidth || 0) + const viewportHeight = Math.max(window.innerHeight || 0, document.documentElement?.clientHeight || 0) + if (!viewportWidth || !viewportHeight) return + + const maxX = Math.max(CONTEXT_MENU_MARGIN, viewportWidth - rect.width - CONTEXT_MENU_MARGIN) + const maxY = Math.max(CONTEXT_MENU_MARGIN, viewportHeight - rect.height - CONTEXT_MENU_MARGIN) + const currentX = Number(contextMenu.value.x || 0) + const currentY = Number(contextMenu.value.y || 0) + const nextX = Math.min(Math.max(currentX, CONTEXT_MENU_MARGIN), maxX) + const nextY = Math.min(Math.max(currentY, CONTEXT_MENU_MARGIN), maxY) + + if (nextX !== currentX || nextY !== currentY) { + contextMenu.value = { + ...contextMenu.value, + x: nextX, + y: nextY + } + } + } + + const scheduleContextMenuReposition = () => { + if (!process.client) return + void nextTick(() => { + const run = () => repositionContextMenu() + if (typeof window.requestAnimationFrame === 'function') { + window.requestAnimationFrame(run) + } else { + run() + } + }) + } + const loadContextMenuEditStatus = async (params) => { if (!process.client) return const account = String(params?.account || '').trim() @@ -67,16 +108,19 @@ export const useChatEditing = ({ const current = String(contextMenu.value?.message?.id || '').trim() if (contextMenu.value.visible && current === messageId) { contextMenu.value.editStatus = response || { modified: false } + scheduleContextMenuReposition() } } catch { const current = String(contextMenu.value?.message?.id || '').trim() if (contextMenu.value.visible && current === messageId) { contextMenu.value.editStatus = null + scheduleContextMenuReposition() } } finally { const current = String(contextMenu.value?.message?.id || '').trim() if (contextMenu.value.visible && current === messageId) { contextMenu.value.editStatusLoading = false + scheduleContextMenuReposition() } } } @@ -126,6 +170,8 @@ export const useChatEditing = ({ void loadContextMenuEditStatus({ account, username, message_id: messageId }) } } catch {} + + scheduleContextMenuReposition() } const prettyJson = (value) => { @@ -519,6 +565,7 @@ export const useChatEditing = ({ return { contextMenu, + contextMenuElement, messageEditModal, messageFieldsModal, closeContextMenu, diff --git a/frontend/pages/chat/[[username]].vue b/frontend/pages/chat/[[username]].vue index c456ac2..c062109 100644 --- a/frontend/pages/chat/[[username]].vue +++ b/frontend/pages/chat/[[username]].vue @@ -502,6 +502,7 @@ const chatState = { availableAccounts, contacts, selectedContact, + searchContext, filteredContacts, searchQuery, showSearchAccountSwitcher,