fix: 修复删除图片标签后无法重新添加的问题

- 改用 URL 而不是索引来删除附件,更可靠
- 优化 useEffect 中的附件去重逻辑
- 添加调试日志便于排查问题
This commit is contained in:
Your Name 2026-02-02 11:27:53 +08:00
parent dbed4020c0
commit 3fc00270c4

View File

@ -166,9 +166,12 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
const editableDiv = textareaRef.current as HTMLDivElement | null;
if (!editableDiv || !editableDiv.isContentEditable) return;
// 检查是否已存在该 URL 的标签
// 检查 DOM 中是否已存在该 URL 的标签(如果存在则不重复添加)
const existing = editableDiv.querySelector(`[data-attachment-url="${url}"]`);
if (existing) return;
if (existing) {
console.log('[CanvasChat] 标签已存在于 DOM 中,跳过:', url.substring(0, 50));
return;
}
const tagSpan = document.createElement('span');
tagSpan.contentEditable = 'false';
@ -194,32 +197,39 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
} else {
editableDiv.appendChild(tagSpan);
}
console.log('[CanvasChat] 已插入图片标签:', url.substring(0, 50));
}, []);
// 🆕 监听 pendingChatAttachments,当用户点击"添加到对话"按钮时添加标签
useEffect(() => {
if (pendingChatAttachments.length > 0) {
// 只添加还没在附件中的图片
setAttachments(prev => {
const existingUrls = new Set(prev.map(a => a.url));
const toAdd = pendingChatAttachments.filter(a => !existingUrls.has(a.url));
if (toAdd.length > 0) {
// 插入图片标签到编辑器
toAdd.forEach((att, i) => {
insertImageTagInEditor(att.url, att.name, prev.length + i);
});
// 聚焦到输入框
setTimeout(() => {
(textareaRef.current as HTMLDivElement | null)?.focus();
}, 0);
return [...prev, ...toAdd];
}
return prev;
});
// 获取当前附件列表
const currentAttachments = [...attachments];
const existingUrls = new Set(currentAttachments.map(a => a.url));
// 过滤出需要添加的图片(不在当前附件列表中的)
const toAdd = pendingChatAttachments.filter(a => !existingUrls.has(a.url));
if (toAdd.length > 0) {
// 插入图片标签到编辑器
toAdd.forEach((att, i) => {
insertImageTagInEditor(att.url, att.name, currentAttachments.length + i);
});
// 更新附件列表
setAttachments([...currentAttachments, ...toAdd]);
// 聚焦到输入框
setTimeout(() => {
(textareaRef.current as HTMLDivElement | null)?.focus();
}, 0);
}
// 清空待添加列表
clearPendingChatAttachments();
}
}, [pendingChatAttachments, insertImageTagInEditor, clearPendingChatAttachments]);
}, [pendingChatAttachments, attachments, insertImageTagInEditor, clearPendingChatAttachments]);
// 获取模型列表
const { data: modelsData } = useSWR<{
@ -737,7 +747,13 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
e.target.value = '';
};
// 移除附件
// 移除附件(通过 URL 删除,更可靠)
const removeAttachmentByUrl = (url: string) => {
setAttachments(prev => prev.filter(a => a.url !== url));
console.log('[CanvasChat] 已移除附件:', url.substring(0, 50));
};
// 移除附件(通过索引删除,保留兼容性)
const removeAttachment = (index: number) => {
setAttachments(prev => prev.filter((_, i) => i !== index));
};
@ -1062,11 +1078,12 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
if (range.collapsed && range.startOffset === 0) {
// 检查前一个兄弟节点是否是图片标签
const prevSibling = range.startContainer.previousSibling as HTMLElement;
if (prevSibling && prevSibling.getAttribute?.('data-attachment-index')) {
if (prevSibling && prevSibling.getAttribute?.('data-attachment-url')) {
e.preventDefault();
e.stopPropagation(); // 🆕 阻止事件冒泡,防止触发全局删除
const index = parseInt(prevSibling.getAttribute('data-attachment-index') || '0');
removeAttachment(index);
e.stopPropagation(); // 阻止事件冒泡,防止触发全局删除
// 使用 URL 来删除附件,更可靠
const url = prevSibling.getAttribute('data-attachment-url') || '';
removeAttachmentByUrl(url);
prevSibling.remove();
}
}