diff --git a/components/canvas/CanvasChatPanel.tsx b/components/canvas/CanvasChatPanel.tsx
index cdf511a..c9518fe 100644
--- a/components/canvas/CanvasChatPanel.tsx
+++ b/components/canvas/CanvasChatPanel.tsx
@@ -1425,98 +1425,107 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
- {/* 🆕 标签悬停预览弹窗 */}
- {tagPreview && (
-
{
- // 鼠标进入预览弹窗,取消隐藏
- if (previewTimeoutRef.current) {
- clearTimeout(previewTimeoutRef.current);
- previewTimeoutRef.current = null;
- }
- }}
- onMouseLeave={() => {
- // 鼠标离开预览弹窗,隐藏
- setTagPreview(null);
- }}
- >
- {/* 图片全貌 */}
-
-

- {/* 如果是物品标签,显示标注位置 */}
- {tagPreview.pickedObject && (
- <>
- {/* 标注点 */}
-
- {/* 序号标记 */}
-
- {/* 脉冲动画背景 */}
-
- {/* 主标记点 */}
-
-
+ {/* 🆕 标签悬停预览弹窗 - 固定显示在标签上方 */}
+ {tagPreview && (() => {
+ // 计算弹窗位置,确保不超出视口
+ const previewWidth = 240;
+ const previewHeight = 280; // 预估高度
+ const padding = 16;
+
+ // 水平位置:居中对齐标签,但确保不超出左右边界
+ let left = tagPreview.x - previewWidth / 2;
+ if (left < padding) left = padding;
+ if (left + previewWidth > window.innerWidth - padding) {
+ left = window.innerWidth - previewWidth - padding;
+ }
+
+ // 垂直位置:显示在标签上方
+ let top = tagPreview.y - previewHeight - 12;
+ if (top < padding) {
+ // 如果上方空间不够,显示在标签下方
+ top = tagPreview.y + 30;
+ }
+
+ return (
+
{
+ // 鼠标进入预览弹窗,取消隐藏
+ if (previewTimeoutRef.current) {
+ clearTimeout(previewTimeoutRef.current);
+ previewTimeoutRef.current = null;
+ }
+ }}
+ onMouseLeave={() => {
+ // 鼠标离开预览弹窗,隐藏
+ setTagPreview(null);
+ }}
+ >
+ {/* 图片全貌 */}
+
+

+ {/* 如果是物品标签,显示标注位置 */}
+ {tagPreview.pickedObject && (
+ <>
+ {/* 标注点 */}
+
+ {/* 序号标记 */}
+
+ {/* 脉冲动画背景 */}
+
+ {/* 主标记点 */}
+
-
- {/* 物品名称标签 */}
-
- {tagPreview.pickedObject.objectName}
-
- >
- )}
-
- {/* 底部信息 */}
-
-
- {tagPreview.pickedObject ? tagPreview.pickedObject.objectName : tagPreview.name}
+ {/* 物品名称标签 */}
+
+ {tagPreview.pickedObject.objectName}
+
+ >
+ )}
- {tagPreview.pickedObject && (
-
- {tagPreview.pickedObject.objectPosition}
+ {/* 底部信息 */}
+
+
+ {tagPreview.pickedObject ? tagPreview.pickedObject.objectName : tagPreview.name}
- )}
+ {tagPreview.pickedObject && (
+
+ {tagPreview.pickedObject.objectPosition}
+
+ )}
+
- {/* 小三角箭头 */}
-
-
- )}
+ );
+ })()}
);
}