ImageUrlInput.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import React from 'react';
  2. import {
  3. Input,
  4. Typography,
  5. Button,
  6. Switch,
  7. } from '@douyinfe/semi-ui';
  8. import { IconFile } from '@douyinfe/semi-icons';
  9. import {
  10. FileText,
  11. Plus,
  12. X,
  13. Image,
  14. } from 'lucide-react';
  15. const ImageUrlInput = ({ imageUrls, imageEnabled, onImageUrlsChange, onImageEnabledChange, disabled = false }) => {
  16. const handleAddImageUrl = () => {
  17. const newUrls = [...imageUrls, ''];
  18. onImageUrlsChange(newUrls);
  19. };
  20. const handleUpdateImageUrl = (index, value) => {
  21. const newUrls = [...imageUrls];
  22. newUrls[index] = value;
  23. onImageUrlsChange(newUrls);
  24. };
  25. const handleRemoveImageUrl = (index) => {
  26. const newUrls = imageUrls.filter((_, i) => i !== index);
  27. onImageUrlsChange(newUrls);
  28. };
  29. return (
  30. <div className={disabled ? 'opacity-50' : ''}>
  31. <div className="flex items-center justify-between mb-2">
  32. <div className="flex items-center gap-2">
  33. <Image size={16} className={imageEnabled && !disabled ? "text-blue-500" : "text-gray-400"} />
  34. <Typography.Text strong className="text-sm">
  35. 图片地址
  36. </Typography.Text>
  37. {disabled && (
  38. <Typography.Text className="text-xs text-orange-600">
  39. (已在自定义模式中忽略)
  40. </Typography.Text>
  41. )}
  42. </div>
  43. <div className="flex items-center gap-2">
  44. <Switch
  45. checked={imageEnabled}
  46. onChange={onImageEnabledChange}
  47. checkedText="启用"
  48. uncheckedText="停用"
  49. size="small"
  50. className="flex-shrink-0"
  51. disabled={disabled}
  52. />
  53. <Button
  54. icon={<Plus size={14} />}
  55. size="small"
  56. theme="solid"
  57. type="primary"
  58. onClick={handleAddImageUrl}
  59. className="!rounded-full !w-4 !h-4 !p-0 !min-w-0"
  60. disabled={!imageEnabled || disabled}
  61. />
  62. </div>
  63. </div>
  64. {!imageEnabled ? (
  65. <Typography.Text className="text-xs text-gray-500 mb-2 block">
  66. {disabled ? '图片功能在自定义请求体模式下不可用' : '启用后可添加图片URL进行多模态对话'}
  67. </Typography.Text>
  68. ) : imageUrls.length === 0 ? (
  69. <Typography.Text className="text-xs text-gray-500 mb-2 block">
  70. {disabled ? '图片功能在自定义请求体模式下不可用' : '点击 + 按钮添加图片URL进行多模态对话'}
  71. </Typography.Text>
  72. ) : (
  73. <Typography.Text className="text-xs text-gray-500 mb-2 block">
  74. 已添加 {imageUrls.length} 张图片{disabled ? ' (自定义模式下不可用)' : ''}
  75. </Typography.Text>
  76. )}
  77. <div className={`space-y-2 max-h-32 overflow-y-auto image-list-scroll ${!imageEnabled || disabled ? 'opacity-50' : ''}`}>
  78. {imageUrls.map((url, index) => (
  79. <div key={index} className="flex items-center gap-2">
  80. <div className="flex-1">
  81. <Input
  82. placeholder={`https://example.com/image${index + 1}.jpg`}
  83. value={url}
  84. onChange={(value) => handleUpdateImageUrl(index, value)}
  85. className="!rounded-lg"
  86. size="small"
  87. prefix={<IconFile size='small' />}
  88. disabled={!imageEnabled || disabled}
  89. />
  90. </div>
  91. <Button
  92. icon={<X size={12} />}
  93. size="small"
  94. theme="borderless"
  95. type="danger"
  96. onClick={() => handleRemoveImageUrl(index)}
  97. className="!rounded-full !w-6 !h-6 !p-0 !min-w-0 !text-red-500 hover:!bg-red-50 flex-shrink-0"
  98. disabled={!imageEnabled || disabled}
  99. />
  100. </div>
  101. ))}
  102. </div>
  103. </div>
  104. );
  105. };
  106. export default ImageUrlInput;