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:
parent
25dc45c398
commit
c7bfd773e3
@ -27,6 +27,15 @@
|
|||||||
"Input": "Input",
|
"Input": "Input",
|
||||||
"Output": "Output"
|
"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": {
|
"home": {
|
||||||
"Quickly build AI question and answer library": "Quickly build AI question and answer library",
|
"Quickly build AI question and answer library": "Quickly build AI question and answer library",
|
||||||
"Start Now": "Start Now",
|
"Start Now": "Start Now",
|
||||||
|
|||||||
@ -27,6 +27,15 @@
|
|||||||
"Input": "输入",
|
"Input": "输入",
|
||||||
"Output": "输出"
|
"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": {
|
"home": {
|
||||||
"Quickly build AI question and answer library": "快速搭建 AI 问答系统",
|
"Quickly build AI question and answer library": "快速搭建 AI 问答系统",
|
||||||
"Start Now": "立即开始",
|
"Start Now": "立即开始",
|
||||||
|
|||||||
@ -136,7 +136,7 @@ const CsvImport = ({ kbId }: { kbId: string }) => {
|
|||||||
fileExtension={fileExtension}
|
fileExtension={fileExtension}
|
||||||
onSelectFile={onSelectFile}
|
onSelectFile={onSelectFile}
|
||||||
isLoading={selecting}
|
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}
|
py={emptyFiles ? '100px' : 5}
|
||||||
isCsv
|
isCsv
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import React from 'react';
|
import MyIcon from '@/components/Icon';
|
||||||
import { Box, Flex, type BoxProps } from '@chakra-ui/react';
|
|
||||||
import { useLoading } from '@/hooks/useLoading';
|
import { useLoading } from '@/hooks/useLoading';
|
||||||
import { useSelectFile } from '@/hooks/useSelectFile';
|
import { useSelectFile } from '@/hooks/useSelectFile';
|
||||||
|
import { useToast } from '@/hooks/useToast';
|
||||||
import MyIcon from '@/components/Icon';
|
|
||||||
import { fileDownload } from '@/utils/file';
|
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 {
|
interface Props extends BoxProps {
|
||||||
fileExtension: string;
|
fileExtension: string;
|
||||||
@ -23,13 +24,79 @@ const FileSelect = ({
|
|||||||
...props
|
...props
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { Loading: FileSelectLoading } = useLoading();
|
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 csvTemplate = `question,answer,source\n"什么是 laf","laf 是一个云函数开发平台……","laf git doc"\n"什么是 sealos","Sealos 是以 kubernetes 为内核的云操作系统发行版,可以……","sealos git doc"`;
|
||||||
|
|
||||||
|
const { toast } = useToast();
|
||||||
|
|
||||||
const { File, onOpen } = useSelectFile({
|
const { File, onOpen } = useSelectFile({
|
||||||
fileType: fileExtension,
|
fileType: fileExtension,
|
||||||
multiple: true
|
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 (
|
return (
|
||||||
<Box
|
<Box
|
||||||
display={'inline-block'}
|
display={'inline-block'}
|
||||||
@ -42,19 +109,28 @@ const FileSelect = ({
|
|||||||
w={'100%'}
|
w={'100%'}
|
||||||
position={'relative'}
|
position={'relative'}
|
||||||
{...props}
|
{...props}
|
||||||
|
onDragEnter={handleDragEnter}
|
||||||
|
onDragOver={handleDragEnter}
|
||||||
|
onDragLeave={handleDragLeave}
|
||||||
|
onDrop={handleDrop}
|
||||||
>
|
>
|
||||||
<Flex justifyContent={'center'} alignItems={'center'}>
|
<Flex justifyContent={'center'} alignItems={'center'}>
|
||||||
<MyIcon mr={1} name={'uploadFile'} w={'16px'} />
|
<MyIcon mr={1} name={'uploadFile'} w={'16px'} />
|
||||||
{/* 拖拽文件至此,或{' '} */}
|
{isDragging ? (
|
||||||
点击
|
t('file.Release the mouse to upload the file')
|
||||||
<Box ml={1} as={'span'} cursor={'pointer'} color={'myBlue.700'} onClick={onOpen}>
|
) : (
|
||||||
选择文件
|
<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>
|
</Box>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Box mt={1}>支持 {fileExtension} 文件</Box>
|
<Box mt={1}>{t('file.support', { fileExtension: fileExtension })}</Box>
|
||||||
{tipText && (
|
{tipText && (
|
||||||
<Box mt={1} fontSize={'sm'} color={'myGray.600'}>
|
<Box mt={1} fontSize={'sm'} color={'myGray.600'}>
|
||||||
{tipText}
|
{t(tipText)}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{isCsv && (
|
{isCsv && (
|
||||||
@ -72,7 +148,7 @@ const FileSelect = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
点击下载 CSV 模板
|
{t('file.Click to download CSV template')}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
<FileSelectLoading loading={isLoading} fixed={false} />
|
<FileSelectLoading loading={isLoading} fixed={false} />
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user