import React, { useEffect, useState } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { ArrowLeft, FolderOpen, Calendar, Settings, Upload, FileVideo, Clock, ExternalLink } from 'lucide-react'; import { useProjectStore } from '../store/projectStore'; import { useMaterialStore } from '../store/materialStore'; import { Project } from '../types/project'; import { MaterialImportResult, Material, MaterialSegment } 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'; /** * 项目详情页面组件 * 遵循 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'>('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 (
{/* 页面头部 */}
{/* 项目基本信息 */}

{project.name}

{project.description && (

{project.description}

)}
{project.path}
创建于 {new Date(project.created_at).toLocaleDateString('zh-CN')}
{project.is_active ? '活跃' : '非活跃'}
{/* 项目内容区域 */}
{/* 素材管理 */}
{/* 选项卡导航 */}
{/* 选项卡内容 */} {activeTab === 'materials' && (
{/* 素材导入区域 */}

导入素材文件

支持视频、音频、图片等多种格式,系统将自动分析并处理

{/* 素材列表 */}

项目素材

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

暂无素材,请导入素材文件开始使用

)}
)} {/* 调试工具选项卡 */} {activeTab === 'debug' && ( )}
{/* 项目信息侧边栏 */}
{/* 项目统计 */}

项目统计

总素材数 {stats?.total_materials || 0}
视频文件 {stats?.video_count || 0}
音频文件 {stats?.audio_count || 0}
图片文件 {stats?.image_count || 0}
总大小 {stats ? (stats.total_size / 1024 / 1024 / 1024).toFixed(2) + ' GB' : '0 GB'}
{/* 最近活动 */}

最近活动

暂无活动记录

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