feat: 实现文件夹递归扫描功能
- 启用文件夹选择时的递归扫描,遍历所有子文件夹 - 添加递归扫描选项复选框,用户可以选择是否扫描子文件夹 - 动态更新按钮文本显示当前扫描模式 - 改进扫描状态反馈,显示扫描进度和结果统计 - 添加状态显示区域,实时显示扫描状态和结果 - 优化用户体验,提供清晰的视觉反馈 现在用户可以: - 选择文件夹时自动扫描所有子文件夹中的视频文件 - 通过复选框控制是否递归扫描 - 查看扫描进度和结果统计信息
This commit is contained in:
parent
fb173cb70c
commit
d77a3b244c
|
|
@ -55,6 +55,7 @@ const FrameExtractorTool: React.FC = () => {
|
|||
const [ffmpegAvailable, setFfmpegAvailable] = useState<boolean | null>(null);
|
||||
const [selectedVideoForPreview, setSelectedVideoForPreview] = useState<VideoFileInfo | null>(null);
|
||||
const [currentPlayTime, setCurrentPlayTime] = useState<number>(0);
|
||||
const [recursiveScan, setRecursiveScan] = useState<boolean>(true);
|
||||
|
||||
// 检查 FFmpeg 可用性
|
||||
useEffect(() => {
|
||||
|
|
@ -107,7 +108,7 @@ const FrameExtractorTool: React.FC = () => {
|
|||
|
||||
if (selected && typeof selected === 'string') {
|
||||
setSelectedFolder(selected);
|
||||
await scanVideoFiles(selected, false);
|
||||
await scanVideoFiles(selected, recursiveScan);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('选择文件夹失败:', error);
|
||||
|
|
@ -117,6 +118,8 @@ const FrameExtractorTool: React.FC = () => {
|
|||
// 扫描视频文件
|
||||
const scanVideoFiles = useCallback(async (folderPath: string, recursive: boolean) => {
|
||||
setIsScanning(true);
|
||||
setCurrentFile(`正在扫描文件夹: ${folderPath}${recursive ? ' (递归)' : ''}`);
|
||||
|
||||
try {
|
||||
const files = await invoke<VideoFileInfo[]>('scan_video_files', {
|
||||
request: {
|
||||
|
|
@ -125,10 +128,29 @@ const FrameExtractorTool: React.FC = () => {
|
|||
supported_formats: SUPPORTED_VIDEO_FORMATS,
|
||||
}
|
||||
});
|
||||
|
||||
setSelectedVideos(files.filter(f => f.is_valid));
|
||||
|
||||
const validFiles = files.filter(f => f.is_valid);
|
||||
setSelectedVideos(validFiles);
|
||||
|
||||
// 显示扫描结果
|
||||
const totalFiles = files.length;
|
||||
const validCount = validFiles.length;
|
||||
const invalidCount = totalFiles - validCount;
|
||||
|
||||
console.log(`扫描完成: 找到 ${totalFiles} 个文件,其中 ${validCount} 个有效,${invalidCount} 个无效`);
|
||||
setCurrentFile(`扫描完成: 找到 ${validCount} 个有效视频文件`);
|
||||
|
||||
// 2秒后清除状态信息
|
||||
setTimeout(() => {
|
||||
setCurrentFile('');
|
||||
}, 2000);
|
||||
|
||||
} catch (error) {
|
||||
console.error('扫描视频文件失败:', error);
|
||||
setCurrentFile('扫描失败,请重试');
|
||||
setTimeout(() => {
|
||||
setCurrentFile('');
|
||||
}, 3000);
|
||||
} finally {
|
||||
setIsScanning(false);
|
||||
}
|
||||
|
|
@ -266,9 +288,10 @@ const FrameExtractorTool: React.FC = () => {
|
|||
onClick={handleSelectFolder}
|
||||
disabled={isScanning || isExtracting}
|
||||
className="flex items-center gap-2 px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
title={recursiveScan ? "选择文件夹并递归扫描所有子文件夹中的视频文件" : "选择文件夹并扫描其中的视频文件"}
|
||||
>
|
||||
<FolderOpen className="w-4 h-4" />
|
||||
选择文件夹
|
||||
选择文件夹{recursiveScan ? ' (递归)' : ''}
|
||||
</button>
|
||||
|
||||
<button
|
||||
|
|
@ -279,6 +302,19 @@ const FrameExtractorTool: React.FC = () => {
|
|||
<Trash2 className="w-4 h-4" />
|
||||
清除选择
|
||||
</button>
|
||||
|
||||
{/* 递归扫描选项 */}
|
||||
<div className="flex items-center gap-2 ml-4 pl-4 border-l border-gray-200">
|
||||
<label className="flex items-center gap-2 text-sm text-gray-700 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={recursiveScan}
|
||||
onChange={(e) => setRecursiveScan(e.target.checked)}
|
||||
className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
<span>递归扫描子文件夹</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
|
|
@ -306,6 +342,18 @@ const FrameExtractorTool: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* 状态显示区域 */}
|
||||
{(isScanning || currentFile) && (
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-3">
|
||||
<div className="flex items-center gap-2">
|
||||
{isScanning && <RefreshCw className="w-4 h-4 text-blue-600 animate-spin" />}
|
||||
<span className="text-sm text-blue-800">
|
||||
{currentFile || '正在处理...'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 视图切换 */}
|
||||
<div className="flex items-center gap-2 bg-white rounded-lg p-1 shadow-sm border w-fit">
|
||||
<button
|
||||
|
|
|
|||
Loading…
Reference in New Issue