mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 05:12:39 +00:00
feat: file drag and drop (#2)
* feat file drag and drop Signed-off-by: jingyang <3161362058@qq.com> * add file select i18n Signed-off-by: jingyang <3161362058@qq.com> * add i18n Interpolation Signed-off-by: jingyang <3161362058@qq.com> --------- Signed-off-by: jingyang <3161362058@qq.com>
This commit is contained in:
@@ -27,6 +27,15 @@
|
||||
"Input": "Input",
|
||||
"Output": "Output"
|
||||
},
|
||||
"file": {
|
||||
"Click to download CSV template": "Click to download CSV template",
|
||||
"Drag and drop": "Drag and drop files here, or click",
|
||||
"Release the mouse to upload the file": "Release the mouse to upload the file",
|
||||
"select a document": "select a document",
|
||||
"support": "support {{fileExtension}} file",
|
||||
"upload error description": "Only upload multiple files or one folder at a time",
|
||||
"If the imported file is garbled, please convert CSV to utf-8 encoding format": "If the imported file is garbled, please convert CSV to utf-8 encoding format"
|
||||
},
|
||||
"home": {
|
||||
"Quickly build AI question and answer library": "Quickly build AI question and answer library",
|
||||
"Start Now": "Start Now",
|
||||
@@ -65,4 +74,4 @@
|
||||
"Update password succseful": "Update password succseful",
|
||||
"Usage Record": "Usage"
|
||||
}
|
||||
}
|
||||
}
|
@@ -27,6 +27,15 @@
|
||||
"Input": "输入",
|
||||
"Output": "输出"
|
||||
},
|
||||
"file": {
|
||||
"Click to download CSV template": "点击下载 CSV 模板",
|
||||
"Drag and drop": "拖拽文件至此,或点击",
|
||||
"Release the mouse to upload the file": "松开鼠标上传文件",
|
||||
"select a document": "选择文件",
|
||||
"support": "支持 {{fileExtension}} 文件",
|
||||
"upload error description": "单次只支持上传多个文件或者一个文件夹",
|
||||
"If the imported file is garbled, please convert CSV to utf-8 encoding format": "如果导入文件乱码,请将 CSV 转成 utf-8 编码格式"
|
||||
},
|
||||
"home": {
|
||||
"Quickly build AI question and answer library": "快速搭建 AI 问答系统",
|
||||
"Start Now": "立即开始",
|
||||
@@ -65,4 +74,4 @@
|
||||
"Update password succseful": "修改密码成功",
|
||||
"Usage Record": "使用记录"
|
||||
}
|
||||
}
|
||||
}
|
@@ -136,7 +136,7 @@ const CsvImport = ({ kbId }: { kbId: string }) => {
|
||||
fileExtension={fileExtension}
|
||||
onSelectFile={onSelectFile}
|
||||
isLoading={selecting}
|
||||
tipText={'如果导入文件乱码,请将 CSV 转成 utf-8 编码格式'}
|
||||
tipText={'If the imported file is garbled, please convert CSV to utf-8 encoding format'}
|
||||
py={emptyFiles ? '100px' : 5}
|
||||
isCsv
|
||||
/>
|
||||
|
@@ -1,10 +1,11 @@
|
||||
import React from 'react';
|
||||
import { Box, Flex, type BoxProps } from '@chakra-ui/react';
|
||||
import MyIcon from '@/components/Icon';
|
||||
import { useLoading } from '@/hooks/useLoading';
|
||||
import { useSelectFile } from '@/hooks/useSelectFile';
|
||||
|
||||
import MyIcon from '@/components/Icon';
|
||||
import { useToast } from '@/hooks/useToast';
|
||||
import { fileDownload } from '@/utils/file';
|
||||
import { Box, Flex, Text, type BoxProps } from '@chakra-ui/react';
|
||||
import { DragEvent, useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
interface Props extends BoxProps {
|
||||
fileExtension: string;
|
||||
@@ -23,13 +24,79 @@ const FileSelect = ({
|
||||
...props
|
||||
}: Props) => {
|
||||
const { Loading: FileSelectLoading } = useLoading();
|
||||
const { t } = useTranslation();
|
||||
const csvTemplate = `question,answer,source\n"什么是 laf","laf 是一个云函数开发平台……","laf git doc"\n"什么是 sealos","Sealos 是以 kubernetes 为内核的云操作系统发行版,可以……","sealos git doc"`;
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
const { File, onOpen } = useSelectFile({
|
||||
fileType: fileExtension,
|
||||
multiple: true
|
||||
});
|
||||
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
|
||||
const handleDragEnter = (e: DragEvent<HTMLDivElement>) => {
|
||||
e.preventDefault();
|
||||
setIsDragging(true);
|
||||
};
|
||||
|
||||
const handleDragLeave = (e: DragEvent<HTMLDivElement>) => {
|
||||
e.preventDefault();
|
||||
setIsDragging(false);
|
||||
};
|
||||
|
||||
const handleDrop = useCallback(async (e: DragEvent<HTMLDivElement>) => {
|
||||
e.preventDefault();
|
||||
setIsDragging(false);
|
||||
|
||||
const items = e.dataTransfer.items;
|
||||
const fileList: File[] = [];
|
||||
|
||||
if (e.dataTransfer.items.length <= 1) {
|
||||
const traverseFileTree = async (item: any) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (item.isFile) {
|
||||
item.file((file: File) => {
|
||||
fileList.push(file);
|
||||
resolve();
|
||||
});
|
||||
} else if (item.isDirectory) {
|
||||
const dirReader = item.createReader();
|
||||
dirReader.readEntries(async (entries: any[]) => {
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
await traverseFileTree(entries[i]);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i].webkitGetAsEntry();
|
||||
if (item) {
|
||||
await traverseFileTree(item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const files = Array.from(e.dataTransfer.files);
|
||||
let isErr = files.some((item) => item.type === '');
|
||||
if (isErr) {
|
||||
return toast({
|
||||
title: t('file.upload error description'),
|
||||
status: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
fileList.push(files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
onSelectFile(fileList);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box
|
||||
display={'inline-block'}
|
||||
@@ -42,19 +109,28 @@ const FileSelect = ({
|
||||
w={'100%'}
|
||||
position={'relative'}
|
||||
{...props}
|
||||
onDragEnter={handleDragEnter}
|
||||
onDragOver={handleDragEnter}
|
||||
onDragLeave={handleDragLeave}
|
||||
onDrop={handleDrop}
|
||||
>
|
||||
<Flex justifyContent={'center'} alignItems={'center'}>
|
||||
<MyIcon mr={1} name={'uploadFile'} w={'16px'} />
|
||||
{/* 拖拽文件至此,或{' '} */}
|
||||
点击
|
||||
<Box ml={1} as={'span'} cursor={'pointer'} color={'myBlue.700'} onClick={onOpen}>
|
||||
选择文件
|
||||
</Box>
|
||||
{isDragging ? (
|
||||
t('file.Release the mouse to upload the file')
|
||||
) : (
|
||||
<Box>
|
||||
{t('file.Drag and drop')}
|
||||
<Text ml={1} as={'span'} cursor={'pointer'} color={'myBlue.700'} onClick={onOpen}>
|
||||
{t('file.select a document')}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Flex>
|
||||
<Box mt={1}>支持 {fileExtension} 文件</Box>
|
||||
<Box mt={1}>{t('file.support', { fileExtension: fileExtension })}</Box>
|
||||
{tipText && (
|
||||
<Box mt={1} fontSize={'sm'} color={'myGray.600'}>
|
||||
{tipText}
|
||||
{t(tipText)}
|
||||
</Box>
|
||||
)}
|
||||
{isCsv && (
|
||||
@@ -72,7 +148,7 @@ const FileSelect = ({
|
||||
})
|
||||
}
|
||||
>
|
||||
点击下载 CSV 模板
|
||||
{t('file.Click to download CSV template')}
|
||||
</Box>
|
||||
)}
|
||||
<FileSelectLoading loading={isLoading} fixed={false} />
|
||||
|
Reference in New Issue
Block a user