From b3de06ea398e5d043cb9efa45e3851ee9eeb39b0 Mon Sep 17 00:00:00 2001 From: chenpei Date: Mon, 27 Oct 2025 17:49:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=BC=BAAI=E8=81=8A=E5=A4=A9?= =?UTF-8?q?=E5=8A=A9=E6=89=8B=20-=20=E5=AE=8C=E6=95=B4=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增功能: ✅ 支持发送图片(点击上传、拖拽、粘贴) ✅ 支持接收AI返回的图片(Base64、inline data) ✅ 图片预览和下载功能 ✅ 点击图片新窗口查看 ✅ 拖拽上传可视化提示 ✅ 支持粘贴剪贴板图片 ✅ 最多支持5张图片同时发送 ✅ 对话历史保留图片信息 图片处理: - 自动转换为Base64格式 - 支持多种图片格式(PNG、JPG、GIF等) - 图片预览带删除按钮 - 图片下载功能 - Hover显示下载按钮 用户体验: - 拖拽区域高亮提示 - 实时图片预览 - 图片点击放大 - 支持键盘快捷键 - 响应式设计 这是一个功能完整的AI图片编辑助手! --- components/AIChatWidget.tsx | 133 +++++++++++++++++++++++++++++++++--- 1 file changed, 123 insertions(+), 10 deletions(-) diff --git a/components/AIChatWidget.tsx b/components/AIChatWidget.tsx index 1f7e0f08..a637d2a5 100644 --- a/components/AIChatWidget.tsx +++ b/components/AIChatWidget.tsx @@ -20,9 +20,11 @@ export default function AIChatWidget() { const [sending, setSending] = useState(false) const [images, setImages] = useState([]) const [imagePreviews, setImagePreviews] = useState([]) + const [isDragging, setIsDragging] = useState(false) const messagesEndRef = useRef(null) const fileInputRef = useRef(null) const containerRef = useRef(null) + const dropZoneRef = useRef(null) // 点击外部关闭 useEffect(() => { @@ -43,6 +45,36 @@ export default function AIChatWidget() { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }) }, [messages]) + // 处理粘贴图片 + useEffect(() => { + const handlePaste = (e: ClipboardEvent) => { + if (!isOpen) return + + const items = e.clipboardData?.items + if (!items) return + + for (let i = 0; i < items.length; i++) { + if (items[i].type.indexOf('image') !== -1) { + const file = items[i].getAsFile() + if (file) { + setImages(prev => [...prev, file].slice(0, 5)) + + const reader = new FileReader() + reader.onloadend = () => { + setImagePreviews(prev => [...prev, reader.result as string]) + } + reader.readAsDataURL(file) + } + } + } + } + + if (isOpen) { + document.addEventListener('paste', handlePaste) + } + return () => document.removeEventListener('paste', handlePaste) + }, [isOpen]) + // 处理图片选择 const handleImageSelect = (e: React.ChangeEvent) => { const files = Array.from(e.target.files || []) @@ -66,6 +98,35 @@ export default function AIChatWidget() { setImagePreviews(prev => prev.filter((_, i) => i !== index)) } + // 处理拖拽上传 + const handleDragOver = (e: React.DragEvent) => { + e.preventDefault() + setIsDragging(true) + } + + const handleDragLeave = (e: React.DragEvent) => { + e.preventDefault() + setIsDragging(false) + } + + const handleDrop = (e: React.DragEvent) => { + e.preventDefault() + setIsDragging(false) + + const files = Array.from(e.dataTransfer.files).filter(file => file.type.startsWith('image/')) + if (files.length > 0) { + setImages(prev => [...prev, ...files].slice(0, 5)) + + files.forEach(file => { + const reader = new FileReader() + reader.onloadend = () => { + setImagePreviews(prev => [...prev, reader.result as string]) + } + reader.readAsDataURL(file) + }) + } + } + // 发送消息 const handleSend = async () => { if ((!input.trim() && images.length === 0) || sending || !session) return @@ -104,11 +165,20 @@ export default function AIChatWidget() { }) }) - // 构建对话历史 - const conversationHistory = messages.map(msg => ({ - role: msg.role, - content: msg.content - })) + // 构建对话历史(保留图片信息) + const conversationHistory = messages.map(msg => { + if (msg.images && msg.images.length > 0) { + const parts: any[] = [] + if (msg.content) { + parts.push({ type: 'text', text: msg.content }) + } + msg.images.forEach(img => { + parts.push({ type: 'image_url', image_url: { url: img } }) + }) + return { role: msg.role, content: parts } + } + return { role: msg.role, content: msg.content } + }) conversationHistory.push({ role: 'user', @@ -216,12 +286,32 @@ export default function AIChatWidget() { {/* 消息列表 */} -
- {messages.length === 0 && ( +
+ {/* 拖拽提示 */} + {isDragging && ( +
+
+ + + +

松开鼠标上传图片

+

支持多张图片(最多5张)

+
+
+ )} + + {messages.length === 0 && !isDragging && (

👋 你好!我是AI助手

可以发送文字或图片与我聊天

支持图片编辑、内容生成等功能

+

💡 拖拽图片到此处快速上传

)} @@ -241,12 +331,35 @@ export default function AIChatWidget() { {msg.images && msg.images.length > 0 && (
{msg.images.map((img, idx) => ( -
+
{`Image { + // 点击图片在新窗口打开 + const win = window.open() + if (win) { + win.document.write(``) + } + }} /> + {/* 下载按钮 */} +
))}
@@ -322,7 +435,7 @@ export default function AIChatWidget() {

- 支持文字+图片聊天,可上传多张图片 + 💡 支持文字+图片聊天 · 可上传/拖拽/粘贴图片 · 最多5张