feat(模板创建): 改进文件选择功能并优化数据结构

重构文件对话框组件,分离文件和文件夹选择功能
更新TreeNode接口,增加sourceType字段区分来源类型
优化文件选择逻辑,提供更清晰的用户指引
This commit is contained in:
zhanggy committed 2025-10-31 16:25:11 +08:00
1 parent 47fb017e21
commit f3e909923a
3 files changed
+74 -25

No files matched your search

+65 -17
View File
@@ -20,17 +20,30 @@
ref="inputRef"
/>
<!-- 文件路径选择输入框 -->
<!-- 文件选择输入框 -->
<v-text-field
v-model="selectedSourcePath"
label="文件或文件夹"
placeholder="点击输入框选择文件或文件夹"
v-model="selectedFilePath"
label="选择文件"
placeholder="点击输入框选择文件"
readonly
:rules="isEditMode ? [] : [requiredRule('文件或文件夹')]"
:rules="[fileSelectionRule]"
:append-inner-icon="'mdi-file'"
density="comfortable"
class="mt-4"
@click="selectSourceFileOrFolder()"
@click="selectSourceFile"
/>
<!-- 文件夹选择输入框 -->
<v-text-field
v-model="selectedFolderPath"
label="选择文件夹"
placeholder="点击输入框选择文件夹"
readonly
:rules="[fileSelectionRule]"
:append-inner-icon="'mdi-folder'"
density="comfortable"
class="mt-4"
@click="selectSourceFolder"
/>
<!-- 选择提示 -->
@@ -44,6 +57,9 @@
<span>
选择文件夹则会自动匹配该文件夹下的文件进行复制并且重命名
</span>
<span class="mt-1 font-weight-bold">
文件和文件夹选择其中一个即可
</span>
</div>
</v-alert>
</v-form>
@@ -54,7 +70,7 @@
<v-btn
color="primary"
@click="confirm"
:disabled="!formValid || (!selectedSourcePath && !isEditMode)"
:disabled="!formValid || (!selectedFilePath && !selectedFolderPath && !isEditMode)"
>
{{ isEditMode ? '保存' : '添加' }}
</v-btn>
@@ -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<Props>(), {
@@ -91,7 +107,8 @@ const emit = defineEmits<Emits>()
const isVisible = ref(false)
const formValid = ref(false)
const filePath = ref('')
const selectedSourcePath = ref<string>('')
const selectedFilePath = ref<string>('')
const selectedFolderPath = ref<string>('')
const inputRef = ref<HTMLInputElement | null>(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
}
@@ -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
+2 -1
View File
@@ -8,7 +8,8 @@ export interface TreeNode {
path: string // 完整路径
type: 'directory' | 'file'
children?: TreeNode[]
sourceFilePath?: string
sourcePath?: string
sourceType?: 'file' | 'folder' // 记录选择的是文件还是文件夹
}
export interface Template {