@@ -28,6 +28,61 @@ import { useAppDispatch, useAppSelector } from "@App/pages/store/hooks";
2828import { selectThemeMode , setDarkMode } from "@App/pages/store/features/config" ;
2929import { RiFileCodeLine , RiImportLine , RiPlayListAddLine , RiTerminalBoxLine , RiTimerLine } from "react-icons/ri" ;
3030import { scriptClient } from "@App/pages/store/features/script" ;
31+ import { useDropzone } from "react-dropzone" ;
32+
33+ const readFile = ( file : File ) : Promise < string > => {
34+ return new Promise ( ( resolve ) => {
35+ // 实例化 FileReader对象
36+ const reader = new FileReader ( ) ;
37+ reader . onload = async ( processEvent ) => {
38+ // 创建blob url
39+ const blob = new Blob ( [ processEvent . target ! . result ! ] , {
40+ type : "application/javascript" ,
41+ } ) ;
42+ const url = URL . createObjectURL ( blob ) ;
43+ resolve ( url ) ;
44+ } ;
45+ // 调用readerAsText方法读取文本
46+ reader . readAsText ( file ) ;
47+ } ) ;
48+ } ;
49+
50+ const uploadFiles = async ( files : File [ ] ) => {
51+ // const filterFiles = files.filter((f) => f.name.endsWith(".js"));
52+ const urls = await Promise . all (
53+ files . map ( ( file ) => {
54+ return readFile ( file ) ;
55+ } )
56+ ) ;
57+ importByUrls ( urls ) ;
58+ } ;
59+
60+ const importByUrls = async ( urls : string [ ] ) => {
61+ const stat = await scriptClient . importByUrls ( urls ) ;
62+ stat &&
63+ Modal . info ( {
64+ title : "脚本导入结果" ,
65+ content : (
66+ < Space direction = "vertical" style = { { width : "100%" } } >
67+ < div style = { { textAlign : "center" } } >
68+ < Space size = "small" style = { { fontSize : 18 } } >
69+ < IconCheckCircle style = { { color : "green" } } />
70+ { stat . success }
71+ { "" }
72+ < IconCloseCircle style = { { color : "red" } } />
73+ { stat . fail }
74+ </ Space >
75+ </ div >
76+ { stat . msg . length > 0 && (
77+ < >
78+ < b > 失败信息:</ b >
79+ { stat . msg }
80+ </ >
81+ ) }
82+ </ Space >
83+ ) ,
84+ } ) ;
85+ } ;
3186
3287const MainLayout : React . FC < {
3388 children : ReactNode ;
@@ -39,6 +94,13 @@ const MainLayout: React.FC<{
3994 const importRef = useRef < RefTextAreaType > ( null ) ;
4095 const [ importVisible , setImportVisible ] = useState ( false ) ;
4196 const { t } = useTranslation ( ) ;
97+ const { getRootProps, getInputProps, isDragActive } = useDropzone ( {
98+ accept : { "application/javascript" : [ ".js" ] } ,
99+ onDrop : ( acceptedFiles ) => {
100+ console . log ( acceptedFiles ) ;
101+ uploadFiles ( acceptedFiles ) ;
102+ } ,
103+ } ) ;
42104
43105 return (
44106 < ConfigProvider
@@ -59,35 +121,8 @@ const MainLayout: React.FC<{
59121 visible = { importVisible }
60122 onOk = { async ( ) => {
61123 const urls = importRef . current ! . dom . value . split ( "\n" ) . filter ( ( v ) => v ) ;
62- try {
63- const stat = await scriptClient . importByUrls ( urls ) ;
64- stat &&
65- Modal . info ( {
66- title : "链接导入结果" ,
67- content : (
68- < Space direction = "vertical" style = { { width : "100%" } } >
69- < div style = { { textAlign : "center" } } >
70- < Space size = "small" style = { { fontSize : 18 } } >
71- < IconCheckCircle style = { { color : "green" } } />
72- { stat . success }
73- { "" }
74- < IconCloseCircle style = { { color : "red" } } />
75- { stat . fail }
76- </ Space >
77- </ div >
78- { stat . msg . length > 0 && (
79- < >
80- < b > 失败信息:</ b >
81- { stat . msg }
82- </ >
83- ) }
84- </ Space >
85- ) ,
86- } ) ;
87- setImportVisible ( false ) ;
88- } catch ( e ) {
89- Message . error ( `${ t ( "import_link_failure" ) } : ${ e } ` ) ;
90- }
124+ importByUrls ( urls ) ;
125+ setImportVisible ( false ) ;
91126 } }
92127 onCancel = { ( ) => {
93128 setImportVisible ( false ) ;
@@ -129,37 +164,9 @@ const MainLayout: React.FC<{
129164 < Menu . Item
130165 key = "import_local"
131166 onClick = { ( ) => {
132- const el = document . getElementById ( "import-local" ) ;
133- el ! . onchange = ( e : Event ) => {
134- try {
135- // 获取文件
136- // @ts -ignore
137- const file = e . target . files [ 0 ] ;
138- // 实例化 FileReader对象
139- const reader = new FileReader ( ) ;
140- reader . onload = async ( processEvent ) => {
141- // 创建blob url
142- const blob = new Blob (
143- // @ts -ignore
144- [ processEvent . target ! . result ] ,
145- {
146- type : "application/javascript" ,
147- }
148- ) ;
149- const url = URL . createObjectURL ( blob ) ;
150- await scriptClient . importByUrl ( url ) ;
151- Message . success ( t ( "import_local_success" ) ) ;
152- } ;
153- // 调用readerAsText方法读取文本
154- reader . readAsText ( file ) ;
155- } catch ( error ) {
156- Message . error ( `${ t ( "import_local_failure" ) } : ${ e } ` ) ;
157- }
158- } ;
159- el ! . click ( ) ;
167+ document . getElementById ( "import-local" ) ?. click ( ) ;
160168 } }
161169 >
162- < input id = "import-local" type = "file" style = { { display : "none" } } accept = ".js" />
163170 < RiImportLine /> { t ( "import_by_local" ) }
164171 </ Menu . Item >
165172 < Menu . Item
@@ -230,7 +237,27 @@ const MainLayout: React.FC<{
230237 style = { {
231238 background : "var(--color-fill-2)" ,
232239 } }
240+ { ...getRootProps ( { onClick : ( e ) => e . stopPropagation ( ) } ) }
233241 >
242+ < input id = "import-local" { ...getInputProps ( { style : { display : "none" } } ) } />
243+ < div
244+ style = { {
245+ position : "absolute" ,
246+ zIndex : 100 ,
247+ display : isDragActive ? "flex" : "none" ,
248+ justifyContent : "center" ,
249+ alignItems : "center" ,
250+ inset : 0 ,
251+ margin : "auto" ,
252+ color : "grey" ,
253+ fontSize : 36 ,
254+ width : "100%" ,
255+ height : "100%" ,
256+ backdropFilter : "blur(4px)" ,
257+ } }
258+ >
259+ 拖拽脚本到此处上传
260+ </ div >
234261 { children }
235262 </ Layout >
236263 </ Layout >
0 commit comments