- Add real-time request body preview that updates when parameters change - Implement pre-constructed payload generation for debugging without sending requests - Add support for image URLs in preview payload construction - Upgrade debug panel to card-style tabs with custom arrow navigation - Add collapsible functionality and dropdown menu for tab selection - Integrate image-enabled messages with proper multimodal content structure - Refactor tab state management with internal useState and external sync - Remove redundant status labels and clean up component structure - Set preview tab as default active tab for better UX - Maintain backward compatibility with existing debug functionality This enhancement significantly improves the debugging experience by allowing developers to see exactly what request will be sent before actually sending it, with real-time updates as they adjust parameters, models, or image settings.
107 lines
3.3 KiB
JavaScript
107 lines
3.3 KiB
JavaScript
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';
|
||
|
||
const ImageUrlInput = ({ imageUrls, imageEnabled, onImageUrlsChange, onImageEnabledChange }) => {
|
||
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>
|
||
<div className="flex items-center justify-between mb-2">
|
||
<div className="flex items-center gap-2">
|
||
<Image size={16} className={imageEnabled ? "text-blue-500" : "text-gray-400"} />
|
||
<Typography.Text strong className="text-sm">
|
||
图片地址
|
||
</Typography.Text>
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<Switch
|
||
checked={imageEnabled}
|
||
onChange={onImageEnabledChange}
|
||
checkedText="启用"
|
||
uncheckedText="停用"
|
||
size="small"
|
||
className="flex-shrink-0"
|
||
/>
|
||
<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 || imageUrls.length >= 5}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{!imageEnabled ? (
|
||
<Typography.Text className="text-xs text-gray-500 mb-2 block">
|
||
图片发送已停用,启用后可添加图片URL进行多模态对话
|
||
</Typography.Text>
|
||
) : imageUrls.length === 0 ? (
|
||
<Typography.Text className="text-xs text-gray-500 mb-2 block">
|
||
点击 + 按钮添加图片URL,支持最多5张图片
|
||
</Typography.Text>
|
||
) : (
|
||
<Typography.Text className="text-xs text-gray-500 mb-2 block">
|
||
已添加 {imageUrls.length}/5 张图片
|
||
</Typography.Text>
|
||
)}
|
||
|
||
<div className={`space-y-2 max-h-32 overflow-y-auto ${!imageEnabled ? '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}
|
||
/>
|
||
</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}
|
||
/>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default ImageUrlInput;
|