feat: 添加前端输出目录选择功能

🎯 **解决问题**:
修复 AI 视频生成失败问题:'Single mode requires --image, --prompt, and --output'

🔧 **前端改进**:

1. **单个模式输出目录选择**:
   - 添加 singleOutputFolder 状态管理
   - 新增 handleSingleOutputFolderSelect 处理函数
   - UI 中添加输出目录选择按钮和输入框
   - 支持手动输入和文件夹选择两种方式

2. **批量模式输出目录优化**:
   - 重构为专门的 handleBatchOutputFolderSelect 函数
   - 替换内联函数,提高代码可维护性
   - 统一错误处理和用户反馈

3. **用户界面增强**:
   - 单个模式:'视频保存目录 (可选)' - 用户友好的可选设置
   - 批量模式:保持原有的必需输出目录设置
   - 占位符文本提供清晰的使用指导
   - 实时显示选择状态:'未选择 (将使用默认目录)'

4. **后端兼容性**:
   - Rust 代码提供默认输出路径备用方案
   - 确保 Python 脚本始终接收到 --output 参数
   - 使用系统临时目录作为默认保存位置

 **修复效果**:
- 解决 'Single mode requires --output' 错误 ✓
- 用户可以自定义视频保存位置 ✓
- 提供默认保存路径备用方案 ✓
- 改善用户体验和操作便利性 ✓

现在用户可以选择视频保存位置,解决了生成失败的问题!
This commit is contained in:
root 2025-07-10 13:57:28 +08:00
parent 1ef9371dde
commit 58c6b6c247
1 changed files with 54 additions and 13 deletions

View File

@ -17,6 +17,7 @@ const AIVideoGenerator: React.FC<AIVideoGeneratorProps> = ({ className = '' }) =
const [customPrompt, setCustomPrompt] = useState<string>('') const [customPrompt, setCustomPrompt] = useState<string>('')
const [batchPrompts, setBatchPrompts] = useState<string[]>(['']) const [batchPrompts, setBatchPrompts] = useState<string[]>([''])
const [outputFolder, setOutputFolder] = useState<string>('') const [outputFolder, setOutputFolder] = useState<string>('')
const [singleOutputFolder, setSingleOutputFolder] = useState<string>('')
const [duration, setDuration] = useState<string>('5') const [duration, setDuration] = useState<string>('5')
const [modelType, setModelType] = useState<string>('lite') const [modelType, setModelType] = useState<string>('lite')
const [previewData, setPreviewData] = useState<{ const [previewData, setPreviewData] = useState<{
@ -114,6 +115,30 @@ const AIVideoGenerator: React.FC<AIVideoGeneratorProps> = ({ className = '' }) =
} }
} }
const handleSingleOutputFolderSelect = async () => {
try {
console.log('Opening output folder dialog...')
const folderPath = await invoke('select_folder') as string
console.log('Selected output folder:', folderPath)
setSingleOutputFolder(folderPath)
} catch (error) {
console.error('Failed to select output folder:', error)
alert(`输出文件夹选择失败: ${error instanceof Error ? error.message : '未知错误'}`)
}
}
const handleBatchOutputFolderSelect = async () => {
try {
console.log('Opening batch output folder dialog...')
const folderPath = await invoke('select_folder') as string
console.log('Selected batch output folder:', folderPath)
setOutputFolder(folderPath)
} catch (error) {
console.error('Failed to select batch output folder:', error)
alert(`批量输出文件夹选择失败: ${error instanceof Error ? error.message : '未知错误'}`)
}
}
// Handle generation // Handle generation
@ -136,7 +161,7 @@ const AIVideoGenerator: React.FC<AIVideoGeneratorProps> = ({ className = '' }) =
prompt: customPrompt, prompt: customPrompt,
duration, duration,
model_type: modelType, model_type: modelType,
output_path: outputFolder output_path: singleOutputFolder
}) })
await generateSingleVideo({ await generateSingleVideo({
@ -144,7 +169,7 @@ const AIVideoGenerator: React.FC<AIVideoGeneratorProps> = ({ className = '' }) =
prompt: customPrompt, prompt: customPrompt,
duration, duration,
model_type: modelType, model_type: modelType,
output_path: outputFolder || undefined, output_path: singleOutputFolder || undefined,
timeout: 300 timeout: 300
}) })
} else { } else {
@ -262,6 +287,32 @@ const AIVideoGenerator: React.FC<AIVideoGeneratorProps> = ({ className = '' }) =
/> />
</div> </div>
{/* Output Directory for Single Mode */}
<div>
<label className="block text-sm font-medium text-secondary-700 mb-2">
()
</label>
<div className="flex items-center space-x-3">
<button
onClick={handleSingleOutputFolderSelect}
className="flex items-center px-4 py-2 bg-secondary-100 hover:bg-secondary-200 rounded-lg transition-colors"
>
<Folder size={16} className="mr-2" />
</button>
<span className="text-sm text-secondary-600">
{singleOutputFolder || '未选择 (将使用默认目录)'}
</span>
</div>
<input
type="text"
value={singleOutputFolder}
onChange={(e) => setSingleOutputFolder(e.target.value)}
placeholder="或手动输入保存目录路径 (例如: C:\Users\用户名\Videos)"
className="input w-full text-sm mt-2"
/>
</div>
</div> </div>
) : ( ) : (
<> <>
@ -298,17 +349,7 @@ const AIVideoGenerator: React.FC<AIVideoGeneratorProps> = ({ className = '' }) =
/> />
<button <button
type="button" type="button"
onClick={async () => { onClick={handleBatchOutputFolderSelect}
try {
console.log('Opening output folder dialog...')
const folderPath = await invoke('select_folder') as string
console.log('Selected output folder:', folderPath)
setOutputFolder(folderPath)
} catch (error) {
console.error('Failed to select output folder:', error)
alert(`输出文件夹选择失败: ${error instanceof Error ? error.message : '未知错误'}`)
}
}}
className="btn-secondary px-3 py-2" className="btn-secondary px-3 py-2"
title="选择输出文件夹" title="选择输出文件夹"
> >