diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 71a389d..01cd785 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -383,3 +383,21 @@ pub async fn test_ai_video_environment() -> Result { Ok(result.to_string()) } + +#[tauri::command] +pub async fn select_image_file() -> Result { + println!("Opening image file dialog..."); + + // For now, return an error to force fallback to plugin dialog + // This will be implemented when the dialog plugin is properly configured + Err("Custom dialog not implemented yet".to_string()) +} + +#[tauri::command] +pub async fn select_folder() -> Result { + println!("Opening folder dialog..."); + + // For now, return an error to force fallback to plugin dialog + // This will be implemented when the dialog plugin is properly configured + Err("Custom dialog not implemented yet".to_string()) +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 6779338..7f2ca03 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -31,7 +31,9 @@ pub fn run() { commands::load_project, commands::generate_ai_video, commands::batch_generate_ai_videos, - commands::test_ai_video_environment + commands::test_ai_video_environment, + commands::select_image_file, + commands::select_folder ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src/components/AIVideoGenerator.tsx b/src/components/AIVideoGenerator.tsx index c70e60a..b1a162e 100644 --- a/src/components/AIVideoGenerator.tsx +++ b/src/components/AIVideoGenerator.tsx @@ -2,6 +2,7 @@ import React, { useState, useRef } from 'react' import { Upload, Play, Settings, Folder, FileText, Clock, Cpu, Trash2, Download } from 'lucide-react' import { useAIVideoStore, useAIVideoJobs, useAIVideoProcessing, useAIVideoSettings } from '../stores/useAIVideoStore' import { open } from '@tauri-apps/plugin-dialog' +import { invoke } from '@tauri-apps/api/core' interface AIVideoGeneratorProps { className?: string @@ -44,29 +45,43 @@ const AIVideoGenerator: React.FC = ({ className = '' }) = const handleImageSelect = async () => { try { console.log('Opening file dialog...') - const selected = await open({ - multiple: false, - filters: [{ - name: 'Images', - extensions: ['jpg', 'jpeg', 'png', 'bmp', 'gif', 'tiff', 'webp'] - }] - }) - console.log('File dialog result:', selected) + // Try using custom Tauri command first + try { + const filePath = await invoke('select_image_file') as string + console.log('Selected image via Tauri command:', filePath) + setSelectedImage(filePath) + return + } catch (tauriError) { + console.log('Tauri command failed, trying plugin dialog:', tauriError) - if (selected) { - // Handle both string and array returns - const filePath = Array.isArray(selected) ? selected[0] : selected - if (filePath) { - setSelectedImage(filePath) - console.log('Selected image:', filePath) + // Fallback to plugin dialog + const selected = await open({ + multiple: false, + filters: [{ + name: 'Images', + extensions: ['jpg', 'jpeg', 'png', 'bmp', 'gif', 'tiff', 'webp'] + }] + }) + + console.log('Plugin dialog result:', selected) + + if (selected) { + const filePath = Array.isArray(selected) ? selected[0] : selected + if (filePath) { + setSelectedImage(filePath) + console.log('Selected image via plugin:', filePath) + return + } } - } else { - console.log('No file selected') } + + // If both methods fail, use HTML input + throw new Error('All Tauri methods failed') + } catch (error) { - console.error('Failed to select image:', error) - alert(`文件选择失败: ${error instanceof Error ? error.message : '未知错误'}\n\n请尝试手动输入文件路径或检查应用权限。`) + console.error('All file selection methods failed:', error) + console.log('Falling back to HTML file input') // Fallback to HTML file input fileInputRef.current?.click() @@ -74,33 +89,52 @@ const AIVideoGenerator: React.FC = ({ className = '' }) = } const handleImageChange = (e: React.ChangeEvent) => { - // This is now unused but kept for compatibility const file = e.target.files?.[0] if (file) { - setSelectedImage(file.name) + // Try to get the full path, fallback to name if not available + const fullPath = (file as any).path || file.name + setSelectedImage(fullPath) + console.log('Selected image via HTML input:', fullPath) + + if (fullPath === file.name) { + alert('⚠️ 注意:由于浏览器安全限制,只能获取文件名。\n\n建议使用桌面应用版本以获得完整的文件路径支持。') + } } } const handleFolderSelect = async () => { try { console.log('Opening folder dialog...') - const selected = await open({ - directory: true, - multiple: false - }) - console.log('Folder dialog result:', selected) + // Try using custom Tauri command first + try { + const folderPath = await invoke('select_folder') as string + console.log('Selected folder via Tauri command:', folderPath) + setSelectedFolder(folderPath) + return + } catch (tauriError) { + console.log('Tauri command failed, trying plugin dialog:', tauriError) - if (selected) { - // Handle both string and array returns - const folderPath = Array.isArray(selected) ? selected[0] : selected - if (folderPath) { - setSelectedFolder(folderPath) - console.log('Selected folder:', folderPath) + // Fallback to plugin dialog + const selected = await open({ + directory: true, + multiple: false + }) + + console.log('Plugin dialog result:', selected) + + if (selected) { + const folderPath = Array.isArray(selected) ? selected[0] : selected + if (folderPath) { + setSelectedFolder(folderPath) + console.log('Selected folder via plugin:', folderPath) + return + } } - } else { - console.log('No folder selected') } + + throw new Error('All folder selection methods failed') + } catch (error) { console.error('Failed to select folder:', error) alert(`文件夹选择失败: ${error instanceof Error ? error.message : '未知错误'}\n\n请尝试手动输入文件夹路径或检查应用权限。`) @@ -264,8 +298,14 @@ const AIVideoGenerator: React.FC = ({ className = '' }) = placeholder="或手动输入完整的图片文件路径 (例如: C:\Users\用户名\Pictures\image.jpg)" className="input w-full text-sm" /> -
- ⚠️ 重要: 请使用"选择文件"按钮或输入完整的文件路径,不要只输入文件名 +
+
⚠️ 重要提示:
+
+
• 请点击"选择文件"按钮来选择图片文件
+
• 或者手动输入完整的文件路径(包含盘符和文件夹)
+
• 不要只输入文件名,例如 "image.jpg"
+
• 正确示例: "C:\Users\用户名\Pictures\image.jpg"
+