mirror of
https://github.com/langgenius/dify.git
synced 2026-04-26 02:06:35 +08:00
Co-authored-by: zxhlyh <jasonapring2015@outlook.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
132 lines
3.6 KiB
TypeScript
132 lines
3.6 KiB
TypeScript
import {
|
|
useCallback,
|
|
useState,
|
|
} from 'react'
|
|
import {
|
|
FileContextProvider,
|
|
} from '../store'
|
|
import type { FileEntity } from '../types'
|
|
import { useUpload } from '../hooks/use-upload'
|
|
import ImageInput from './image-input'
|
|
import cn from '@/utils/classnames'
|
|
import { useTranslation } from 'react-i18next'
|
|
import { useFileStoreWithSelector } from '../store'
|
|
import ImageItem from './image-item'
|
|
import type { ImageInfo } from '@/app/components/datasets/common/image-previewer'
|
|
import ImagePreviewer from '@/app/components/datasets/common/image-previewer'
|
|
|
|
type ImageUploaderInRetrievalTestingProps = {
|
|
textArea: React.ReactNode
|
|
actionButton: React.ReactNode
|
|
showUploader?: boolean
|
|
className?: string
|
|
actionAreaClassName?: string
|
|
}
|
|
const ImageUploaderInRetrievalTesting = ({
|
|
textArea,
|
|
actionButton,
|
|
showUploader = true,
|
|
className,
|
|
actionAreaClassName,
|
|
}: ImageUploaderInRetrievalTestingProps) => {
|
|
const { t } = useTranslation()
|
|
const files = useFileStoreWithSelector(s => s.files)
|
|
const [previewIndex, setPreviewIndex] = useState(0)
|
|
const [previewImages, setPreviewImages] = useState<ImageInfo[]>([])
|
|
const {
|
|
dragging,
|
|
dragRef,
|
|
dropRef,
|
|
handleRemoveFile,
|
|
handleReUploadFile,
|
|
} = useUpload()
|
|
|
|
const handleImagePreview = useCallback((fileId: string) => {
|
|
const index = files.findIndex(item => item.id === fileId)
|
|
if (index === -1) return
|
|
setPreviewIndex(index)
|
|
setPreviewImages(files.map(item => ({
|
|
url: item.base64Url || item.sourceUrl || '',
|
|
name: item.name,
|
|
size: item.size,
|
|
})))
|
|
}, [files])
|
|
|
|
const handleClosePreview = useCallback(() => {
|
|
setPreviewImages([])
|
|
}, [])
|
|
|
|
return (
|
|
<div
|
|
ref={dropRef}
|
|
className={cn('relative flex w-full flex-col', className)}
|
|
>
|
|
{dragging && (
|
|
<div
|
|
className='absolute inset-0.5 z-10 flex items-center justify-center rounded-lg border-[1.5px] border-dashed border-components-dropzone-border-accent bg-components-dropzone-bg-accent'
|
|
>
|
|
<div>{t('datasetHitTesting.imageUploader.dropZoneTip')}</div>
|
|
<div ref={dragRef} className='absolute inset-0' />
|
|
</div>
|
|
)}
|
|
{textArea}
|
|
{
|
|
showUploader && !!files.length && (
|
|
<div className='flex flex-wrap gap-1 bg-background-default px-4 py-2'>
|
|
{
|
|
files.map(file => (
|
|
<ImageItem
|
|
key={file.id}
|
|
file={file}
|
|
showDeleteAction
|
|
onRemove={handleRemoveFile}
|
|
onReUpload={handleReUploadFile}
|
|
onPreview={handleImagePreview}
|
|
/>
|
|
))
|
|
}
|
|
</div>
|
|
)
|
|
}
|
|
<div
|
|
className={cn(
|
|
'flex',
|
|
showUploader ? 'justify-between' : 'justify-end',
|
|
actionAreaClassName,
|
|
)}>
|
|
{showUploader && <ImageInput />}
|
|
{actionButton}
|
|
</div>
|
|
{previewImages.length > 0 && (
|
|
<ImagePreviewer
|
|
images={previewImages}
|
|
initialIndex={previewIndex}
|
|
onClose={handleClosePreview}
|
|
/>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export type ImageUploaderInRetrievalTestingWrapperProps = {
|
|
value?: FileEntity[]
|
|
onChange: (files: FileEntity[]) => void
|
|
} & ImageUploaderInRetrievalTestingProps
|
|
|
|
const ImageUploaderInRetrievalTestingWrapper = ({
|
|
value,
|
|
onChange,
|
|
...props
|
|
}: ImageUploaderInRetrievalTestingWrapperProps) => {
|
|
return (
|
|
<FileContextProvider
|
|
value={value}
|
|
onChange={onChange}
|
|
>
|
|
<ImageUploaderInRetrievalTesting {...props} />
|
|
</FileContextProvider>
|
|
)
|
|
}
|
|
|
|
export default ImageUploaderInRetrievalTestingWrapper
|