From 64ab5ce017ed4682f09311f7da328fb3bde916d1 Mon Sep 17 00:00:00 2001 From: icarus Date: Fri, 22 Aug 2025 17:42:44 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=96=87=E4=BB=B6=E9=80=89=E6=8B=A9):=20?= =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E6=96=87=E4=BB=B6=E9=80=89=E6=8B=A9=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=B9=B6=E6=B7=BB=E5=8A=A0=E6=B8=85=E9=99=A4=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为文件选择API添加返回类型声明 - 完善文件选择回调函数的文档注释 - 修改文件选择逻辑以返回选中的文件数组 - 添加清除文件列表的方法 --- src/preload/index.ts | 3 ++- src/renderer/src/hooks/useFiles.ts | 36 ++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/preload/index.ts b/src/preload/index.ts index b7d18edd70..46a64b01f8 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -134,7 +134,8 @@ const api = { checkS3Connection: (s3Config: S3Config) => ipcRenderer.invoke(IpcChannel.Backup_CheckS3Connection, s3Config) }, file: { - select: (options?: OpenDialogOptions) => ipcRenderer.invoke(IpcChannel.File_Select, options), + select: (options?: OpenDialogOptions): Promise => + ipcRenderer.invoke(IpcChannel.File_Select, options), upload: (file: FileMetadata) => ipcRenderer.invoke(IpcChannel.File_Upload, file), delete: (fileId: string) => ipcRenderer.invoke(IpcChannel.File_Delete, fileId), deleteDir: (dirPath: string) => ipcRenderer.invoke(IpcChannel.File_DeleteDir, dirPath), diff --git a/src/renderer/src/hooks/useFiles.ts b/src/renderer/src/hooks/useFiles.ts index ead49315ac..1f96c4e79a 100644 --- a/src/renderer/src/hooks/useFiles.ts +++ b/src/renderer/src/hooks/useFiles.ts @@ -22,26 +22,36 @@ export const useFiles = (props?: Props) => { } }, [props?.extensions]) + /** + * 选择文件的回调函数 + * @param multipleSelections - 是否允许多选文件,默认为 true + * @returns 返回选中的文件元数据数组 + * @description + * 1. 打开系统文件选择对话框 + * 2. 根据扩展名过滤文件 + * 3. 更新内部文件状态 + * 4. 当选择了不支持的文件类型时,会显示提示信息 + */ const onSelectFile = useCallback( - async (multipleSelections: boolean = true) => { + async (multipleSelections: boolean = true): Promise => { if (selecting) { - return + return [] } - const supportedExtensions = extensions ?? ['*'] + const selectProps: Electron.OpenDialogOptions['properties'] = multipleSelections ? ['openFile', 'multiSelections'] : ['openFile'] // when the number of extensions is greater than 20, use *.* to avoid selecting window lag - const useAllFiles = supportedExtensions.length > 20 + const useAllFiles = extensions.length > 20 setSelecting(true) - const _files: FileMetadata[] = await window.api.file.select({ + const _files = await window.api.file.select({ properties: selectProps, filters: [ { name: 'Files', - extensions: useAllFiles ? ['*'] : supportedExtensions.map((i) => i.replace('.', '')) + extensions: useAllFiles ? ['*'] : extensions.map((i) => i.replace('.', '')) } ] }) @@ -50,9 +60,9 @@ export const useFiles = (props?: Props) => { if (_files) { if (!useAllFiles) { setFiles([...files, ..._files]) - return + return _files } - const supportedFiles = await filterSupportedFiles(_files, supportedExtensions) + const supportedFiles = await filterSupportedFiles(_files, extensions) if (supportedFiles.length > 0) { setFiles([...files, ...supportedFiles]) } @@ -65,14 +75,22 @@ export const useFiles = (props?: Props) => { }) }) } + return _files + } else { + return [] } }, [extensions, files, selecting, t] ) + const clearFiles = useCallback(() => { + setFiles([]) + }, []) + return { files, setFiles, - onSelectFile + onSelectFile, + clearFiles } }