import React, { useEffect, useState, useMemo } from 'react'; import { Filter, Tag, Users, Video, RefreshCw, Eye, Edit, Trash2 } from 'lucide-react'; import { invoke } from '@tauri-apps/api/core'; import { SearchInput } from './InteractiveInput'; import { InteractiveButton } from './InteractiveButton'; interface MaterialSegmentViewProps { projectId: string; } interface SegmentWithDetails { segment: { id: string; material_id: string; start_time: number; end_time: number; duration: number; file_path: string; }; material_name: string; material_type: string; classification?: { category: string; confidence: number; reasoning: string; features: string[]; product_match: boolean; quality_score: number; }; model?: { id: string; name: string; model_type: string; }; } interface ClassificationGroup { category: string; segment_count: number; total_duration: number; segments: SegmentWithDetails[]; } interface ModelGroup { model_id: string; model_name: string; segment_count: number; total_duration: number; segments: SegmentWithDetails[]; } interface MaterialSegmentView { project_id: string; by_classification: ClassificationGroup[]; by_model: ModelGroup[]; stats: { total_segments: number; classified_segments: number; unclassified_segments: number; classification_coverage: number; classification_counts: Record; model_counts: Record; total_duration: number; }; } /** * 素材片段管理组件 - 多条件检索标签页风格 */ export const MaterialSegmentView: React.FC = ({ projectId }) => { const [segmentView, setSegmentView] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [searchTerm, setSearchTerm] = useState(''); const [selectedClassification, setSelectedClassification] = useState('全部'); const [selectedModel, setSelectedModel] = useState('全部'); // 加载数据 const loadSegmentView = async () => { try { setLoading(true); setError(null); const data = await invoke('get_project_segment_view', { projectId }) as MaterialSegmentView; setSegmentView(data); } catch (err) { console.error('Failed to load segment view:', err); setError('加载片段数据失败'); } finally { setLoading(false); } }; // 初始加载 useEffect(() => { if (projectId) { loadSegmentView(); } }, [projectId]); // 格式化时长 const formatDuration = (seconds: number): string => { const minutes = Math.floor(seconds / 60); const remainingSeconds = Math.floor(seconds % 60); return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`; }; // 获取分类选项 const classificationOptions = useMemo(() => { if (!segmentView) return [{ label: '全部', value: '全部', count: 0 }]; const options = [ { label: '全部', value: '全部', count: segmentView.stats.total_segments } ]; Object.entries(segmentView.stats.classification_counts).forEach(([category, count]) => { options.push({ label: category || '未分类', value: category || '未分类', count }); }); return options; }, [segmentView]); // 获取模特选项 const modelOptions = useMemo(() => { if (!segmentView) return [{ label: '全部', value: '全部', count: 0 }]; const options = [ { label: '全部', value: '全部', count: segmentView.stats.total_segments } ]; Object.entries(segmentView.stats.model_counts).forEach(([modelName, count]) => { options.push({ label: modelName || '未指定', value: modelName || '未指定', count }); }); return options; }, [segmentView]); // 获取过滤后的片段 const filteredSegments = useMemo(() => { if (!segmentView) return []; // 获取所有片段 let segments: SegmentWithDetails[] = []; segmentView.by_classification.forEach(group => { segments.push(...group.segments); }); // 应用分类过滤 if (selectedClassification !== '全部') { segments = segments.filter(segment => segment.classification?.category === selectedClassification ); } // 应用模特过滤 if (selectedModel !== '全部') { segments = segments.filter(segment => segment.model?.name === selectedModel ); } // 应用搜索过滤 if (searchTerm.trim()) { const searchLower = searchTerm.toLowerCase(); segments = segments.filter(segment => segment.material_name.toLowerCase().includes(searchLower) || segment.classification?.category?.toLowerCase().includes(searchLower) || segment.model?.name?.toLowerCase().includes(searchLower) ); } return segments; }, [segmentView, selectedClassification, selectedModel, searchTerm]); // 渲染片段卡片 const renderSegmentCard = (segment: SegmentWithDetails) => { // 安全检查 if (!segment || !segment.segment || !segment.material_name) { return null; } return (
{/* 缩略图 */}
{/* 内容信息 */}

{segment.material_name || '未知素材'}

{formatDuration(segment.segment.start_time)} - {formatDuration(segment.segment.end_time)} 时长: {formatDuration(segment.segment.duration)}

{/* 操作按钮 */}
{/* 标签信息 */}
{segment.classification && ( {segment.classification.category} )} {segment.model && ( {segment.model.name} )} {segment.classification?.confidence && ( 置信度: {Math.round(segment.classification.confidence * 100)}% )}
); }; if (loading) { return (
加载片段数据中...
); } if (error) { return (

{error}

} > 重新加载
); } if (!segmentView) { return (

暂无片段数据

); } return (
{/* 搜索和刷新 */}
} > 刷新
{/* 筛选条件 */}
{/* AI分类筛选 - 单行显示 */}
AI分类:
{classificationOptions.map(option => ( ))}
{/* 模特筛选 - 单行显示 */}
模特:
{modelOptions.map(option => ( ))}
{/* 当前筛选条件显示 */} {(selectedClassification !== '全部' || selectedModel !== '全部') && (
当前筛选: {selectedClassification !== '全部' && ( AI分类: {selectedClassification} )} {selectedClassification !== '全部' && selectedModel !== '全部' && ( AND )} {selectedModel !== '全部' && ( 模特: {selectedModel} )}
)}
{/* 片段列表 */}
{filteredSegments.length > 0 ? ( filteredSegments.map(segment => renderSegmentCard(segment)) ) : (
)}
); };