From f3e909923a65aa042977598b1a7febdf6321cf17 Mon Sep 17 00:00:00 2001 From: Jasery Date: Fri, 31 Oct 2025 16:25:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=A8=A1=E6=9D=BF=E5=88=9B=E5=BB=BA):=20?= =?UTF-8?q?=E6=94=B9=E8=BF=9B=E6=96=87=E4=BB=B6=E9=80=89=E6=8B=A9=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E6=95=B0=E6=8D=AE=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构文件对话框组件,分离文件和文件夹选择功能 更新TreeNode接口,增加sourceType字段区分来源类型 优化文件选择逻辑,提供更清晰的用户指引 --- src/main/IPCs.ts | 4 +- src/renderer/components/FileDialog.vue | 82 +++++++++++++++---- src/renderer/screens/CreateTemplateScreen.vue | 14 ++-- src/renderer/store/template.ts | 3 +- 4 files changed, 76 insertions(+), 27 deletions(-) diff --git a/src/main/IPCs.ts b/src/main/IPCs.ts index 7cc84c3..70f8fa4 100644 --- a/src/main/IPCs.ts +++ b/src/main/IPCs.ts @@ -75,7 +75,7 @@ export default class IPCs { const filePath = dialogResult.filePaths[0]; const fs = require('fs'); const isDirectory = fs.statSync(filePath).isDirectory(); - + return { canceled: false, filePath: filePath, @@ -86,7 +86,7 @@ export default class IPCs { return { canceled: true } }) - + // Find all files in a folder recursively ipcMain.handle( diff --git a/src/renderer/components/FileDialog.vue b/src/renderer/components/FileDialog.vue index 2add1f5..f5d4696 100644 --- a/src/renderer/components/FileDialog.vue +++ b/src/renderer/components/FileDialog.vue @@ -20,17 +20,30 @@ ref="inputRef" /> - + + + + @@ -44,6 +57,9 @@ 选择文件夹则会自动匹配该文件夹下的文件进行复制并且重命名 + + 文件和文件夹选择其中一个即可 + @@ -54,7 +70,7 @@ {{ isEditMode ? '保存' : '添加' }} @@ -76,7 +92,7 @@ interface Props { interface Emits { (e: 'update:modelValue', value: boolean): void - (e: 'confirm', data: { path: string; sourceFilePath?: string }): void + (e: 'confirm', data: { path: string; sourcePath?: string; sourceType?: 'file' | 'folder' }): void } const props = withDefaults(defineProps(), { @@ -91,7 +107,8 @@ const emit = defineEmits() const isVisible = ref(false) const formValid = ref(false) const filePath = ref('') -const selectedSourcePath = ref('') +const selectedFilePath = ref('') +const selectedFolderPath = ref('') const inputRef = ref(null) // Computed @@ -103,7 +120,8 @@ watch(() => props.modelValue, (newValue) => { if (newValue) { // Reset form when dialog opens filePath.value = props.editingItem?.path || '' - selectedSourcePath.value = props.editingItem?.sourceFilePath || '' + selectedFilePath.value = props.editingItem?.sourceType === 'file' ? props.editingItem?.sourcePath || '' : '' + selectedFolderPath.value = props.editingItem?.sourceType === 'folder' ? props.editingItem?.sourcePath || '' : '' autoFocusInput() } }) @@ -117,6 +135,12 @@ watch(isVisible, (newValue) => { const requiredRule = (fieldName: string) => (v: string | null | undefined) => !!v || `${fieldName}为必填项` +// File selection validation rule +const fileSelectionRule = () => { + if (isEditMode.value) return true // 编辑模式下不需要验证 + return !!selectedFilePath.value || !!selectedFolderPath.value || '请选择文件或文件夹' +} + // Methods const autoFocusInput = async () => { await nextTick() @@ -125,22 +149,45 @@ const autoFocusInput = async () => { } } -const selectSourceFileOrFolder = async () => { - // 使用现有的主进程API来选择文件或文件夹 - const result = await window.mainApi.invoke('msgSelectFileOrFolder') +const selectSourceFile = async () => { + // 使用主进程API来选择文件 + const result = await window.mainApi.invoke('msgOpenFile', 'any') - if (result && result.filePath) { - selectedSourcePath.value = result.filePath + if (result && !result.canceled && result.filePaths.length > 0) { + selectedFilePath.value = result.filePaths[0] + selectedFolderPath.value = '' // 清空文件夹选择 + } +} + +const selectSourceFolder = async () => { + // 使用主进程API来选择文件夹 + const result = await window.mainApi.invoke('msgSelectDirectory') + + if (result && !result.canceled && result.filePath) { + selectedFolderPath.value = result.filePath + selectedFilePath.value = '' // 清空文件选择 } } const confirm = () => { if (!filePath.value.trim()) return + // 确定选择的源类型和路径 + let sourcePathValue: string | undefined + let sourceType: 'file' | 'folder' | undefined + + if (selectedFilePath.value) { + sourcePathValue = selectedFilePath.value + sourceType = 'file' + } else if (selectedFolderPath.value) { + sourcePathValue = selectedFolderPath.value + sourceType = 'folder' + } emit('confirm', { path: filePath.value, - sourceFilePath: selectedSourcePath.value || undefined + sourcePath: sourcePathValue, + sourceType }) close() @@ -148,7 +195,8 @@ const confirm = () => { const reset = () => { filePath.value = '' - selectedSourcePath.value = '' + selectedFilePath.value = '' + selectedFolderPath.value = '' formValid.value = false } diff --git a/src/renderer/screens/CreateTemplateScreen.vue b/src/renderer/screens/CreateTemplateScreen.vue index 5b607ad..e2569b3 100644 --- a/src/renderer/screens/CreateTemplateScreen.vue +++ b/src/renderer/screens/CreateTemplateScreen.vue @@ -284,13 +284,11 @@ const handleDirectoryDialogConfirm = (data: { path: string }) => { path: path, type: 'directory' } - console.log('updatedNode', updatedNode) treeStructure.value = updateNodeInTree( treeStructure.value, - currentEditingItem.value.path, + currentEditingItem.value.id, updatedNode ) - console.log('update treeStructure', treeStructure.value) } else { // Create new directory node const newNode: TreeNode = { @@ -360,8 +358,8 @@ const updateNodeInTree = ( -const handleFileDialogConfirm = (data: { path: string; sourceFilePath?: string }) => { - const { path, sourceFilePath } = data +const handleFileDialogConfirm = (data: { path: string; sourcePath?: string; sourceType?: 'file' | 'folder' }) => { + const { path, sourcePath, sourceType } = data const newId = generateUniqueId('file') @@ -373,7 +371,8 @@ const handleFileDialogConfirm = (data: { path: string; sourceFilePath?: string } name: path, path: path, type: 'file', - sourceFilePath: sourceFilePath + sourcePath: sourcePath, + sourceType } treeStructure.value = updateNodeInTree( treeStructure.value, @@ -410,7 +409,8 @@ const handleFileDialogConfirm = (data: { path: string; sourceFilePath?: string } name: path, path: path, type: 'file', - sourceFilePath + sourcePath, + sourceType } // Add to tree structure diff --git a/src/renderer/store/template.ts b/src/renderer/store/template.ts index d130355..35c2ff3 100644 --- a/src/renderer/store/template.ts +++ b/src/renderer/store/template.ts @@ -8,7 +8,8 @@ export interface TreeNode { path: string // 完整路径 type: 'directory' | 'file' children?: TreeNode[] - sourceFilePath?: string + sourcePath?: string + sourceType?: 'file' | 'folder' // 记录选择的是文件还是文件夹 } export interface Template {