import React, { useEffect, useState } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { ArrowLeft, FolderOpen, Calendar, Settings, Upload, FileVideo, FileAudio, FileImage, HardDrive } from 'lucide-react'; import { useProjectStore } from '../store/projectStore'; import { useMaterialStore } from '../store/materialStore'; import { Project } from '../types/project'; import { MaterialImportResult } from '../types/material'; import { LoadingSpinner } from '../components/LoadingSpinner'; import { ErrorMessage } from '../components/ErrorMessage'; import { MaterialImportDialog } from '../components/MaterialImportDialog'; import { FFmpegDebugPanel } from '../components/FFmpegDebugPanel'; import { MaterialCard } from '../components/MaterialCard'; import { VideoClassificationProgress } from '../components/VideoClassificationProgress'; import { AiAnalysisLogViewer } from '../components/AiAnalysisLogViewer'; import MaterialCardSkeleton from '../components/MaterialCardSkeleton'; /** * 项目详情页面组件 * 遵循 Tauri 开发规范的页面组件设计模式 */ export const ProjectDetails: React.FC = () => { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const { projects, isLoading, error, loadProjects } = useProjectStore(); const { materials, stats, loadMaterials, loadMaterialStats, isLoading: materialsLoading } = useMaterialStore(); const [project, setProject] = useState(null); const [showImportDialog, setShowImportDialog] = useState(false); const [activeTab, setActiveTab] = useState<'materials' | 'debug' | 'ai-logs'>('materials'); // 加载项目详情 useEffect(() => { if (!projects.length) { loadProjects(); } }, [projects.length, loadProjects]); // 根据ID查找项目 useEffect(() => { if (id && projects.length > 0) { const foundProject = projects.find(p => p.id === id); setProject(foundProject || null); // 加载项目素材 if (foundProject) { loadMaterials(foundProject.id); loadMaterialStats(foundProject.id); } } }, [id, projects, loadMaterials, loadMaterialStats]); // 返回项目列表 const handleBack = () => { navigate('/'); }; // 打开项目文件夹 const handleOpenFolder = async () => { if (project) { try { const { openPath } = await import('@tauri-apps/plugin-opener'); // 处理 Windows 路径格式,移除 \\?\ 前缀 let normalizedPath = project.path; if (normalizedPath.startsWith('\\\\?\\')) { normalizedPath = normalizedPath.substring(4); } console.log('尝试打开路径:', normalizedPath); await openPath(normalizedPath); } catch (error) { console.error('打开文件夹失败:', error); // 如果 openPath 失败,尝试使用 revealItemInDir try { const { revealItemInDir } = await import('@tauri-apps/plugin-opener'); let normalizedPath = project.path; if (normalizedPath.startsWith('\\\\?\\')) { normalizedPath = normalizedPath.substring(4); } console.log('尝试使用 revealItemInDir 打开:', normalizedPath); await revealItemInDir(normalizedPath); } catch (fallbackError) { console.error('备用方法也失败:', fallbackError); // 可以在这里显示用户友好的错误提示 alert('无法打开文件夹,请检查路径是否存在'); } } } }; // 素材导入处理 const handleMaterialImport = () => { setShowImportDialog(true); }; // 导入完成处理 const handleImportComplete = (result: MaterialImportResult) => { setShowImportDialog(false); console.log('导入完成:', result); // 重新加载素材列表 if (project) { loadMaterials(project.id); loadMaterialStats(project.id); } }; if (isLoading) { return (
); } if (error) { return ; } if (!project) { return (

项目未找到

请检查项目ID是否正确

); } return (
{/* 页面头部 */}
{/* 项目统计概览 */}
{/* 总素材数 */}

总素材数

{stats?.total_materials || 0}

{/* 视频文件 */}

视频文件

{stats?.video_count || 0}

{/* 音频文件 */}

音频文件

{stats?.audio_count || 0}

{/* 图片文件 */}

图片文件

{stats?.image_count || 0}

{/* 主要内容区域 */}
{/* 选项卡导航 */}
{/* 选项卡内容 */}
{/* 素材管理选项卡 */} {activeTab === 'materials' && (
{/* AI视频分类进度 */} {project && ( )} {/* 素材列表 */}

项目素材

{materialsLoading ? (
) : materials.length > 0 ? (
{materials.map((material) => ( ))}
) : (

暂无素材

开始导入视频、音频或图片素材,让AI帮助您进行智能分类和管理

)}
)} {/* 调试工具选项卡 */} {activeTab === 'debug' && (

调试工具

用于开发和调试的工具集合,包括FFmpeg测试和系统诊断功能。

)} {/* AI分析日志选项卡 */} {activeTab === 'ai-logs' && project && (

AI分析日志

查看项目中所有AI视频分类的详细日志,包括分类记录和任务执行情况。

)}
{/* 素材导入对话框 */} {project && ( setShowImportDialog(false)} onImportComplete={handleImportComplete} /> )}
); };