feat: 用户消息显示图片标签样式,隐藏标注提示前缀
This commit is contained in:
parent
2e6f9d52bb
commit
323646f1d4
@ -856,63 +856,97 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
|
||||
"flex flex-col gap-2 max-w-[85%]",
|
||||
message.role === 'user' ? "items-end" : "items-start"
|
||||
)}>
|
||||
<div
|
||||
className={cn(
|
||||
"text-sm px-4 py-2.5 shadow-sm",
|
||||
message.role === 'user'
|
||||
? "bg-primary text-primary-foreground rounded-2xl rounded-tr-sm"
|
||||
: "bg-card border text-card-foreground rounded-2xl rounded-tl-sm"
|
||||
)}
|
||||
>
|
||||
{/* 附件预览 */}
|
||||
{(message as any).attachments && (message as any).attachments.length > 0 && (
|
||||
<div className="flex flex-wrap gap-2 mb-2">
|
||||
{(message as any).attachments.map((att: any, i: number) => (
|
||||
<img
|
||||
key={i}
|
||||
src={att.url}
|
||||
alt=""
|
||||
className="h-16 w-16 object-cover rounded-lg border bg-background"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 消息内容 */}
|
||||
<div className="whitespace-pre-wrap break-words leading-relaxed">
|
||||
{cleanedMessage.parts?.map((part: any, i: number) => {
|
||||
if (part.type === 'text') {
|
||||
// 提取并显示图片
|
||||
const imageUrls = extractImageUrls(part.text || '');
|
||||
const textWithoutImages = (part.text || '')
|
||||
.replace(/!\[(?:thumb)?\|\|\|[^|]+\|\|\|[^\]]*\]\([^)]+\)/g, '')
|
||||
.trim();
|
||||
{message.role === 'user' ? (
|
||||
// 🆕 用户消息:使用图片标签样式(类似输入框)
|
||||
<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">
|
||||
{/* 渲染图片标签和文字混合 */}
|
||||
{(() => {
|
||||
const msgAttachments = (message as any).attachments || [];
|
||||
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 (
|
||||
<div key={i}>
|
||||
{textWithoutImages && <span>{textWithoutImages}</span>}
|
||||
{imageUrls.length > 0 && (
|
||||
<div className="flex flex-wrap gap-2 mt-3">
|
||||
{imageUrls.map((url, idx) => (
|
||||
<div key={idx} className="relative group rounded-xl overflow-hidden border bg-background shadow-sm transition-all hover:shadow-md">
|
||||
<img
|
||||
src={url}
|
||||
alt=""
|
||||
className="max-w-full h-auto cursor-pointer hover:scale-105 transition-transform duration-300"
|
||||
style={{ maxHeight: '200px' }}
|
||||
onClick={() => window.open(url, '_blank')}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
// 合并所有图片
|
||||
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
|
||||
key={`img-${idx}`}
|
||||
className="inline-flex items-center gap-1 px-2 py-1 bg-background border rounded-lg text-xs"
|
||||
>
|
||||
<img
|
||||
src={img.url}
|
||||
alt=""
|
||||
className="w-5 h-5 object-cover rounded"
|
||||
/>
|
||||
<span className="max-w-[80px] truncate text-foreground">{img.name}</span>
|
||||
</span>
|
||||
);
|
||||
});
|
||||
|
||||
// 添加文字内容
|
||||
if (textContent) {
|
||||
elements.push(
|
||||
<span key="text" className="text-sm text-foreground">{textContent}</span>
|
||||
);
|
||||
}
|
||||
|
||||
return elements;
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
// AI 消息:保持原样式
|
||||
<div className="bg-card border text-card-foreground rounded-2xl rounded-tl-sm text-sm px-4 py-2.5 shadow-sm">
|
||||
{/* 消息内容 */}
|
||||
<div className="whitespace-pre-wrap break-words leading-relaxed">
|
||||
{cleanedMessage.parts?.map((part: any, i: number) => {
|
||||
if (part.type === 'text') {
|
||||
// 提取并显示图片
|
||||
const imageUrls = extractImageUrls(part.text || '');
|
||||
const textWithoutImages = (part.text || '')
|
||||
.replace(/!\[(?:thumb)?\|\|\|[^|]+\|\|\|[^\]]*\]\([^)]+\)/g, '')
|
||||
.trim();
|
||||
|
||||
return (
|
||||
<div key={i}>
|
||||
{textWithoutImages && <span>{textWithoutImages}</span>}
|
||||
{imageUrls.length > 0 && (
|
||||
<div className="flex flex-wrap gap-2 mt-3">
|
||||
{imageUrls.map((url, idx) => (
|
||||
<div key={idx} className="relative group rounded-xl overflow-hidden border bg-background shadow-sm transition-all hover:shadow-md">
|
||||
<img
|
||||
src={url}
|
||||
alt=""
|
||||
className="max-w-full h-auto cursor-pointer hover:scale-105 transition-transform duration-300"
|
||||
style={{ maxHeight: '200px' }}
|
||||
onClick={() => window.open(url, '_blank')}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user