| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| import React from 'react';
|
| import { Input, Typography, Button, Switch } from '@douyinfe/semi-ui';
|
| import { IconFile } from '@douyinfe/semi-icons';
|
| import { FileText, Plus, X, Image } from 'lucide-react';
|
| import { useTranslation } from 'react-i18next';
|
|
|
| const ImageUrlInput = ({
|
| imageUrls,
|
| imageEnabled,
|
| onImageUrlsChange,
|
| onImageEnabledChange,
|
| disabled = false,
|
| }) => {
|
| const { t } = useTranslation();
|
| const handleAddImageUrl = () => {
|
| const newUrls = [...imageUrls, ''];
|
| onImageUrlsChange(newUrls);
|
| };
|
|
|
| const handleUpdateImageUrl = (index, value) => {
|
| const newUrls = [...imageUrls];
|
| newUrls[index] = value;
|
| onImageUrlsChange(newUrls);
|
| };
|
|
|
| const handleRemoveImageUrl = (index) => {
|
| const newUrls = imageUrls.filter((_, i) => i !== index);
|
| onImageUrlsChange(newUrls);
|
| };
|
|
|
| return (
|
| <div className={disabled ? 'opacity-50' : ''}>
|
| <div className='flex items-center justify-between mb-2'>
|
| <div className='flex items-center gap-2'>
|
| <Image
|
| size={16}
|
| className={
|
| imageEnabled && !disabled ? 'text-blue-500' : 'text-gray-400'
|
| }
|
| />
|
| <Typography.Text strong className='text-sm'>
|
| {t('图片地址')}
|
| </Typography.Text>
|
| {disabled && (
|
| <Typography.Text className='text-xs text-orange-600'>
|
| ({t('已在自定义模式中忽略')})
|
| </Typography.Text>
|
| )}
|
| </div>
|
| <div className='flex items-center gap-2'>
|
| <Switch
|
| checked={imageEnabled}
|
| onChange={onImageEnabledChange}
|
| checkedText={t('启用')}
|
| uncheckedText={t('停用')}
|
| size='small'
|
| className='flex-shrink-0'
|
| disabled={disabled}
|
| />
|
| <Button
|
| icon={<Plus size={14} />}
|
| size='small'
|
| theme='solid'
|
| type='primary'
|
| onClick={handleAddImageUrl}
|
| className='!rounded-full !w-4 !h-4 !p-0 !min-w-0'
|
| disabled={!imageEnabled || disabled}
|
| />
|
| </div>
|
| </div>
|
|
|
| {!imageEnabled ? (
|
| <Typography.Text className='text-xs text-gray-500 mb-2 block'>
|
| {disabled
|
| ? t('图片功能在自定义请求体模式下不可用')
|
| : t('启用后可添加图片URL进行多模态对话')}
|
| </Typography.Text>
|
| ) : imageUrls.length === 0 ? (
|
| <Typography.Text className='text-xs text-gray-500 mb-2 block'>
|
| {disabled
|
| ? t('图片功能在自定义请求体模式下不可用')
|
| : t('点击 + 按钮添加图片URL进行多模态对话')}
|
| </Typography.Text>
|
| ) : (
|
| <Typography.Text className='text-xs text-gray-500 mb-2 block'>
|
| {t('已添加')} {imageUrls.length} {t('张图片')}
|
| {disabled ? ` (${t('自定义模式下不可用')})` : ''}
|
| </Typography.Text>
|
| )}
|
|
|
| <div
|
| className={`space-y-2 max-h-32 overflow-y-auto image-list-scroll ${!imageEnabled || disabled ? 'opacity-50' : ''}`}
|
| >
|
| {imageUrls.map((url, index) => (
|
| <div key={index} className='flex items-center gap-2'>
|
| <div className='flex-1'>
|
| <Input
|
| placeholder={`https://example.com/image${index + 1}.jpg`}
|
| value={url}
|
| onChange={(value) => handleUpdateImageUrl(index, value)}
|
| className='!rounded-lg'
|
| size='small'
|
| prefix={<IconFile size='small' />}
|
| disabled={!imageEnabled || disabled}
|
| />
|
| </div>
|
| <Button
|
| icon={<X size={12} />}
|
| size='small'
|
| theme='borderless'
|
| type='danger'
|
| onClick={() => handleRemoveImageUrl(index)}
|
| className='!rounded-full !w-6 !h-6 !p-0 !min-w-0 !text-red-500 hover:!bg-red-50 flex-shrink-0'
|
| disabled={!imageEnabled || disabled}
|
| />
|
| </div>
|
| ))}
|
| </div>
|
| </div>
|
| );
|
| };
|
|
|
| export default ImageUrlInput;
|
|
|