fix: 用户消息按parts原始顺序渲染图片标签和文字
This commit is contained in:
parent
323646f1d4
commit
2c8bcd14cd
@ -857,55 +857,53 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
|
|||||||
message.role === 'user' ? "items-end" : "items-start"
|
message.role === 'user' ? "items-end" : "items-start"
|
||||||
)}>
|
)}>
|
||||||
{message.role === 'user' ? (
|
{message.role === 'user' ? (
|
||||||
// 🆕 用户消息:使用图片标签样式(类似输入框)
|
// 🆕 用户消息:使用图片标签样式(类似竞品,按 parts 原始顺序渲染)
|
||||||
<div className="bg-card border rounded-2xl rounded-tr-sm px-3 py-2 shadow-sm">
|
<div className="bg-card border rounded-2xl rounded-tr-sm px-3 py-2 shadow-sm">
|
||||||
<div className="flex flex-wrap items-center gap-1.5">
|
<div className="flex flex-wrap items-center gap-1.5">
|
||||||
{/* 渲染图片标签和文字混合 */}
|
{/* 按 parts 原始顺序渲染图片标签和文字 */}
|
||||||
{(() => {
|
{cleanedMessage.parts?.map((part: any, idx: number) => {
|
||||||
const msgAttachments = (message as any).attachments || [];
|
if (part.type === 'file' && part.url) {
|
||||||
const fileParts = cleanedMessage.parts?.filter((p: any) => p.type === 'file' && p.url) || [];
|
// 图片标签
|
||||||
const textParts = cleanedMessage.parts?.filter((p: any) => p.type === 'text' && p.text) || [];
|
return (
|
||||||
|
|
||||||
// 合并所有图片
|
|
||||||
const allImages = [
|
|
||||||
...msgAttachments.map((att: any) => ({ url: att.url, name: att.name || 'Image' })),
|
|
||||||
...fileParts.map((p: any) => ({ url: p.url, name: p.name || 'Image' }))
|
|
||||||
];
|
|
||||||
|
|
||||||
// 获取纯文字内容(去掉标注提示前缀)
|
|
||||||
let textContent = textParts.map((p: any) => p.text).join(' ').trim();
|
|
||||||
// 移除标注提示前缀(这是后台处理用的,不需要显示给用户)
|
|
||||||
textContent = textContent.replace(/【注意:图片中有标注(箭头、圆圈、文字等)标记的区域是需要重点关注或修改的部分,请根据标注进行处理】\n?/g, '');
|
|
||||||
|
|
||||||
// 解析文字中的图片名称引用,构建混合显示
|
|
||||||
const elements: React.ReactNode[] = [];
|
|
||||||
|
|
||||||
// 先添加图片标签
|
|
||||||
allImages.forEach((img, idx) => {
|
|
||||||
elements.push(
|
|
||||||
<span
|
<span
|
||||||
key={`img-${idx}`}
|
key={`part-${idx}`}
|
||||||
className="inline-flex items-center gap-1 px-2 py-1 bg-background border rounded-lg text-xs"
|
className="inline-flex items-center gap-1 px-2 py-1 bg-background border rounded-lg text-xs"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={img.url}
|
src={part.url}
|
||||||
alt=""
|
alt=""
|
||||||
className="w-5 h-5 object-cover rounded"
|
className="w-5 h-5 object-cover rounded"
|
||||||
/>
|
/>
|
||||||
<span className="max-w-[80px] truncate text-foreground">{img.name}</span>
|
<span className="max-w-[80px] truncate text-foreground">{part.name || 'Image'}</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
if (part.type === 'text' && part.text) {
|
||||||
// 添加文字内容
|
// 文字(去掉标注提示前缀)
|
||||||
if (textContent) {
|
let text = part.text.replace(/【注意:图片中有标注(箭头、圆圈、文字等)标记的区域是需要重点关注或修改的部分,请根据标注进行处理】\n?/g, '').trim();
|
||||||
elements.push(
|
if (!text) return null;
|
||||||
<span key="text" className="text-sm text-foreground">{textContent}</span>
|
return (
|
||||||
|
<span key={`part-${idx}`} className="text-sm text-foreground">{text}</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
return elements;
|
})}
|
||||||
})()}
|
{/* 如果有 attachments 但没有 file parts,也显示 */}
|
||||||
|
{(!cleanedMessage.parts?.some((p: any) => p.type === 'file') && (message as any).attachments?.length > 0) &&
|
||||||
|
(message as any).attachments.map((att: any, idx: number) => (
|
||||||
|
<span
|
||||||
|
key={`att-${idx}`}
|
||||||
|
className="inline-flex items-center gap-1 px-2 py-1 bg-background border rounded-lg text-xs"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={att.url}
|
||||||
|
alt=""
|
||||||
|
className="w-5 h-5 object-cover rounded"
|
||||||
|
/>
|
||||||
|
<span className="max-w-[80px] truncate text-foreground">{att.name || 'Image'}</span>
|
||||||
|
</span>
|
||||||
|
))
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user