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,