import React from 'react'; import { Input, Upload, message, Button, Spin, Tag } from 'antd'; import { PictureOutlined, SendOutlined, LoadingOutlined, SearchOutlined } from '@ant-design/icons'; import { postInput, postInputImage, getPeoples } from '../apis'; import './InputPanel.css'; const { TextArea } = Input; interface InputPanelProps { onResult?: (data: any) => void; showUpload?: boolean; // 是否显示图片上传按钮,默认显示 mode?: 'input' | 'search'; // 输入面板工作模式,默认为表单填写(input) } const InputPanel: React.FC = ({ onResult, showUpload = true, mode = 'input' }) => { const [value, setValue] = React.useState(''); const [fileList, setFileList] = React.useState([]); const [loading, setLoading] = React.useState(false); const [savedText, setSavedText] = React.useState(''); // 统一显示短文件名:image.{ext} const getImageExt = (file: any): string => { const type = file?.type || ''; if (typeof type === 'string' && type.startsWith('image/')) { const sub = type.split('/')[1] || 'png'; return sub.toLowerCase(); } const name = file?.name || ''; const dot = name.lastIndexOf('.'); const ext = dot >= 0 ? name.slice(dot + 1) : ''; return (ext || 'png').toLowerCase(); }; const send = async () => { const trimmed = value.trim(); const hasText = trimmed.length > 0; const hasImage = showUpload && fileList.length > 0; // 搜索模式:仅以文本触发检索,忽略图片 if (mode === 'search') { if (!hasText) { message.info('请输入内容'); return; } setLoading(true); try { console.log('检索文本:', trimmed); const response = await getPeoples({ search: trimmed, top_k: 10 }); console.log('检索响应:', response); if (response.error_code === 0) { message.success('已获取检索结果'); onResult?.(response.data || []); // 清空输入 setValue(''); setFileList([]); } else { message.error(response.error_info || '检索失败,请重试'); } } catch (error) { console.error('检索调用失败:', error); message.error('网络错误,请检查连接后重试'); } finally { setLoading(false); } return; } setLoading(true); try { let response; // 如果有图片,优先处理图片上传 if (hasImage) { const file = fileList[0].originFileObj || fileList[0]; if (!file) { message.error('图片文件无效,请重新选择'); return; } console.log('上传图片:', file.name); response = await postInputImage(file); } else { // 只有文本时,调用文本处理 API console.log('处理文本:', trimmed); response = await postInput(trimmed); } console.log('API响应:', response); if (response.error_code === 0 && response.data) { message.success('处理完成!已自动填充表单'); // 将结果传递给父组件 onResult?.(response.data); message.info('输入已清空'); // 清空输入 setValue(''); setFileList([]); setSavedText(''); } else { message.error(response.error_info || '处理失败,请重试'); } } catch (error) { console.error('API调用失败:', error); message.error('网络错误,请检查连接后重试'); } finally { setLoading(false); } }; const onKeyDown = (e: React.KeyboardEvent) => { if (loading) return; // 加载中时禁用快捷键 if (e.key === 'Enter') { if (e.shiftKey) { // Shift+Enter 换行(保持默认行为) return; } // Enter 发送 e.preventDefault(); send(); } }; // 处理剪贴板粘贴图片:将图片加入上传列表,复用现有上传流程 const onPaste = (e: React.ClipboardEvent) => { if (!showUpload || loading) return; const items = e.clipboardData?.items; if (!items || items.length === 0) return; let pastedImage: File | null = null; for (let i = 0; i < items.length; i++) { const item = items[i]; if (item.kind === 'file') { const file = item.getAsFile(); if (file && file.type.startsWith('image/')) { pastedImage = file; break; // 只取第一张 } } } if (pastedImage) { // 避免图片内容以文本方式粘贴进输入框 e.preventDefault(); const ext = getImageExt(pastedImage); const name = `image.${ext}`; const entry = { uid: `${Date.now()}-${Math.random()}`, name, status: 'done', originFileObj: pastedImage, } as any; // 仅保留一张:新图直接替换旧图 if (fileList.length === 0) { setSavedText(value); } setValue(''); setFileList([entry]); message.success('已添加剪贴板图片'); } }; return (
} > {/** 根据禁用状态动态占位符文案 */} {(() => { return null; })()}