feat: support AI search in resource list page

This commit is contained in:
2025-10-29 16:09:14 +08:00
parent 38676ec2d0
commit a8170f45be
6 changed files with 117 additions and 48 deletions

View File

@@ -1,25 +1,54 @@
import React from 'react';
import { Input, Upload, message, Button, Spin } from 'antd';
import { PictureOutlined, SendOutlined, LoadingOutlined } from '@ant-design/icons';
import { postInput, postInputImage } from '../apis';
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<InputPanelProps> = ({ onResult }) => {
const InputPanel: React.FC<InputPanelProps> = ({ onResult, showUpload = true, mode = 'input' }) => {
const [value, setValue] = React.useState('');
const [fileList, setFileList] = React.useState<any[]>([]);
const [loading, setLoading] = React.useState(false);
const send = async () => {
const hasText = value.trim().length > 0;
const hasImage = fileList.length > 0;
if (!hasText && !hasImage) {
message.info('请输入内容或上传图片');
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;
}
@@ -39,8 +68,8 @@ const InputPanel: React.FC<InputPanelProps> = ({ onResult }) => {
response = await postInputImage(file);
} else {
// 只有文本时,调用文本处理 API
console.log('处理文本:', value.trim());
response = await postInput(value.trim());
console.log('处理文本:', trimmed);
response = await postInput(trimmed);
}
console.log('API响应:', response);
@@ -88,7 +117,7 @@ const InputPanel: React.FC<InputPanelProps> = ({ onResult }) => {
<TextArea
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="请输入个人信息描述,或上传图片…"
placeholder={showUpload ? '请输入个人信息描述,或上传图片…' : '请输入个人信息描述…'}
autoSize={{ minRows: 6, maxRows: 12 }}
style={{ fontSize: 14 }}
onKeyDown={onKeyDown}
@@ -96,23 +125,26 @@ const InputPanel: React.FC<InputPanelProps> = ({ onResult }) => {
/>
</Spin>
<div className="input-actions">
<Upload
accept="image/*"
beforeUpload={() => false}
fileList={fileList}
onChange={({ fileList }) => setFileList(fileList as any)}
maxCount={9}
showUploadList={{ showPreviewIcon: false }}
disabled={loading}
>
<Button type="text" icon={<PictureOutlined />} disabled={loading} />
</Upload>
{showUpload && (
<Upload
accept="image/*"
beforeUpload={() => false}
fileList={fileList}
onChange={({ fileList }) => setFileList(fileList as any)}
maxCount={9}
showUploadList={{ showPreviewIcon: false }}
disabled={loading}
>
<Button type="text" icon={<PictureOutlined />} disabled={loading} />
</Upload>
)}
<Button
type="primary"
icon={loading ? <LoadingOutlined /> : <SendOutlined />}
icon={loading ? <LoadingOutlined /> : (mode === 'search' ? <SearchOutlined /> : <SendOutlined />)}
onClick={send}
loading={loading}
disabled={loading}
aria-label={mode === 'search' ? '搜索' : '发送'}
/>
</div>
</div>