-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFileUpload.jsx
More file actions
120 lines (110 loc) · 3.42 KB
/
FileUpload.jsx
File metadata and controls
120 lines (110 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import React, { useCallback, useState } from 'react';
import { Upload, FileText } from 'lucide-react';
export function FileUpload({ onFilesUploaded, showTitle = true }) {
const [isDragOver, setIsDragOver] = useState(false);
const processFiles = useCallback((files) => {
const fileArray = Array.from(files);
const processedFiles = fileArray.map(file => ({
file,
name: file.name,
id: Math.random().toString(36).substr(2, 9),
data: null,
content: null
}));
// Read file contents
Promise.all(
processedFiles.map(fileObj =>
new Promise((resolve) => {
const reader = new FileReader();
reader.onload = (e) => {
fileObj.content = e.target.result;
resolve(fileObj);
};
reader.readAsText(fileObj.file);
})
)
).then(files => {
onFilesUploaded(files);
});
}, [onFilesUploaded]);
const handleDragEnter = useCallback((e) => {
e.preventDefault();
e.stopPropagation(); // 阻止事件冒泡到全局处理器
setIsDragOver(true);
}, []);
const handleDragOver = useCallback((e) => {
e.preventDefault();
e.stopPropagation(); // 阻止事件冒泡到全局处理器
setIsDragOver(true);
}, []);
const handleDragLeave = useCallback((e) => {
e.preventDefault();
e.stopPropagation(); // 阻止事件冒泡到全局处理器
setIsDragOver(false);
}, []);
const handleDrop = useCallback((e) => {
e.preventDefault();
e.stopPropagation(); // 阻止事件冒泡到全局处理器
setIsDragOver(false);
processFiles(e.dataTransfer.files);
}, [processFiles]);
const handleFileSelect = useCallback((e) => {
processFiles(e.target.files);
e.target.value = '';
}, [processFiles]);
return (
<div className="bg-white rounded-lg shadow-md p-3">
{showTitle && (
<h3
id="file-upload-heading"
className="text-base font-semibold text-gray-800 mb-2"
>
📁 文件上传
</h3>
)}
<div
className={`drag-area border-2 border-dashed rounded-lg p-4 text-center cursor-pointer ${
isDragOver ? 'border-blue-500 bg-blue-50' : 'border-gray-300 hover:border-gray-400'
}`}
onDragEnter={handleDragEnter}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
onClick={() => document.getElementById('fileInput').click()}
role="button"
tabIndex={0}
aria-labelledby="file-upload-heading"
aria-describedby="file-upload-description"
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
document.getElementById('fileInput').click();
}
}}
>
<Upload
className="mx-auto mb-2 text-gray-400"
size={32}
aria-hidden="true"
/>
<p className="text-sm text-gray-600 mb-1">
🎯 拖拽文件到此处或点击选择文件
</p>
<p
id="file-upload-description"
className="text-xs text-gray-500"
>
📄 支持所有文本格式文件
</p>
<input
id="fileInput"
type="file"
multiple
onChange={handleFileSelect}
className="sr-only"
aria-label="选择日志文件,支持所有文本格式"
/>
</div>
</div>
);
}