import React, { useState, useEffect } from 'react'; import { FileVideo, FileAudio, FileImage, File, Loader2 } from 'lucide-react'; import { Material } from '../types/material'; import { invoke } from '@tauri-apps/api/core'; import { useLazyLoad } from '../hooks/useLazyLoad'; interface MaterialThumbnailProps { material: Material; size?: 'small' | 'medium' | 'large'; className?: string; thumbnailCache?: Map; setThumbnailCache?: (cache: Map) => void; } /** * Material缩略图组件 * 遵循Tauri开发规范的组件设计模式 * 支持懒加载、缓存机制、错误处理 */ export const MaterialThumbnail: React.FC = ({ material, size = 'medium', className = '', thumbnailCache = new Map(), setThumbnailCache = () => {}, }) => { const [loading, setLoading] = useState(false); const [thumbnailUrl, setThumbnailUrl] = useState(null); const [error, setError] = useState(false); // 使用懒加载Hook,当缩略图容器可见时才开始加载 const { isVisible, elementRef } = useLazyLoad(0.1, '100px'); // 根据size确定尺寸 const getSizeClasses = () => { switch (size) { case 'small': return 'w-12 h-12'; case 'medium': return 'w-16 h-16'; case 'large': return 'w-24 h-24'; default: return 'w-16 h-16'; } }; // 获取文件类型图标 const getTypeIcon = () => { const iconSize = size === 'small' ? 'w-6 h-6' : size === 'large' ? 'w-12 h-12' : 'w-8 h-8'; switch (material.material_type) { case 'Video': return ; case 'Audio': return ; case 'Image': return ; default: return ; } }; useEffect(() => { // 只有当元素可见时才加载缩略图 if (!isVisible) return; // 只为视频类型生成缩略图 if (material.material_type !== 'Video') return; const loadThumbnail = async () => { const materialId = material.id; // 检查缓存 if (thumbnailCache.has(materialId)) { const cachedUrl = thumbnailCache.get(materialId); setThumbnailUrl(cachedUrl || null); return; } // 加载缩略图 setLoading(true); setError(false); try { console.log('获取素材缩略图:', materialId); const dataUrl = await invoke('get_material_thumbnail_base64', { materialId: materialId }); console.log('获取缩略图成功'); setThumbnailUrl(dataUrl); // 更新缓存 const newCache = new Map(thumbnailCache); newCache.set(materialId, dataUrl); setThumbnailCache(newCache); } catch (error) { console.error('获取缩略图失败:', error); setError(true); } finally { setLoading(false); } }; loadThumbnail(); }, [isVisible, material.id, material.material_type, thumbnailCache, setThumbnailCache]); return (
{loading ? ( ) : thumbnailUrl && !error ? ( {`${material.name} { setError(true); setThumbnailUrl(null); }} /> ) : isVisible ? ( getTypeIcon() ) : ( // 未加载时显示占位符
)}
); };