From 9aa2cdd49f3875f37de6678cb9cafb33d194f786 Mon Sep 17 00:00:00 2001 From: imeepos Date: Tue, 15 Jul 2025 13:12:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=B4=A0=E6=9D=90?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=92=8C=E9=87=8D=E6=96=B0=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在MaterialCard组件中添加删除按钮,使用DeleteConfirmDialog替代window.confirm - 在MaterialCard组件中添加重新处理按钮,当素材状态为Pending时显示 - 在ProjectDetails页面中添加删除和重新处理的处理函数 - 遵循Tauri开发规范和前端开发规范 - 实现了统一的删除确认对话框UI交互 --- apps/desktop/src/components/MaterialCard.tsx | 85 +++++++++++++++++++- apps/desktop/src/pages/ProjectDetails.tsx | 40 ++++++++- 2 files changed, 122 insertions(+), 3 deletions(-) diff --git a/apps/desktop/src/components/MaterialCard.tsx b/apps/desktop/src/components/MaterialCard.tsx index 7c6ff91..919bcd6 100644 --- a/apps/desktop/src/components/MaterialCard.tsx +++ b/apps/desktop/src/components/MaterialCard.tsx @@ -1,17 +1,20 @@ import React, { useState, useEffect } from 'react'; import { FileVideo, FileAudio, FileImage, File, Clock, ExternalLink, ChevronDown, ChevronUp, - Monitor, Volume2, Palette, Calendar, Hash, Zap, HardDrive, Film, Eye, Brain, Loader2, User, Edit2 + Monitor, Volume2, Palette, Calendar, Hash, Zap, HardDrive, Film, Eye, Brain, Loader2, User, Edit2, Trash2, RefreshCw } from 'lucide-react'; import { Material, MaterialSegment } from '../types/material'; import { useMaterialStore } from '../store/materialStore'; import { useVideoClassificationStore } from '../store/videoClassificationStore'; import { Model } from '../types/model'; import { invoke } from '@tauri-apps/api/core'; +import { DeleteConfirmDialog } from './DeleteConfirmDialog'; interface MaterialCardProps { material: Material; onEdit?: (material: Material) => void; + onDelete?: (materialId: string, materialName: string) => void; + onReprocess?: (materialId: string) => void; } // 格式化时间(秒转为 mm:ss 格式) @@ -60,7 +63,7 @@ const formatDate = (dateString: string): string => { * 素材卡片组件 * 显示素材信息和切分片段 */ -export const MaterialCard: React.FC = ({ material, onEdit }) => { +export const MaterialCard: React.FC = ({ material, onEdit, onDelete, onReprocess }) => { const { getMaterialSegments } = useMaterialStore(); const { startClassification, isLoading: classificationLoading } = useVideoClassificationStore(); const [segments, setSegments] = useState([]); @@ -69,6 +72,9 @@ export const MaterialCard: React.FC = ({ material, onEdit }) const [isClassifying, setIsClassifying] = useState(false); const [associatedModel, setAssociatedModel] = useState(null); const [loadingModel, setLoadingModel] = useState(false); + const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); + const [isDeleting, setIsDeleting] = useState(false); + const [isReprocessing, setIsReprocessing] = useState(false); // 获取素材类型图标 const getTypeIcon = (type: string) => { @@ -209,6 +215,43 @@ export const MaterialCard: React.FC = ({ material, onEdit }) } }; + // 处理删除素材 + const handleDeleteClick = () => { + setShowDeleteConfirm(true); + }; + + const handleDeleteConfirm = async () => { + if (!onDelete) return; + + setIsDeleting(true); + try { + await onDelete(material.id, material.name); + setShowDeleteConfirm(false); + } catch (error) { + console.error('删除素材失败:', error); + } finally { + setIsDeleting(false); + } + }; + + const handleDeleteCancel = () => { + setShowDeleteConfirm(false); + }; + + // 处理重新处理素材 + const handleReprocessClick = async () => { + if (!onReprocess) return; + + setIsReprocessing(true); + try { + await onReprocess(material.id); + } catch (error) { + console.error('重新处理素材失败:', error); + } finally { + setIsReprocessing(false); + } + }; + return (
{/* 素材基本信息 */} @@ -218,6 +261,22 @@ export const MaterialCard: React.FC = ({ material, onEdit })

{material.name}

+ {/* 重新处理按钮 - 仅在状态为 Pending 时显示 */} + {material.processing_status === 'Pending' && onReprocess && ( + + )} + {onEdit && ( )} + + {onDelete && ( + + )} + {material.processing_status} @@ -471,6 +541,17 @@ export const MaterialCard: React.FC = ({ material, onEdit }) )}
)} + + {/* 删除确认对话框 */} + ); }; diff --git a/apps/desktop/src/pages/ProjectDetails.tsx b/apps/desktop/src/pages/ProjectDetails.tsx index 5937aed..e325aa4 100644 --- a/apps/desktop/src/pages/ProjectDetails.tsx +++ b/apps/desktop/src/pages/ProjectDetails.tsx @@ -39,6 +39,8 @@ export const ProjectDetails: React.FC = () => { stats, loadMaterials, loadMaterialStats, + deleteMaterial, + processMaterials, isLoading: materialsLoading } = useMaterialStore(); const { @@ -287,6 +289,36 @@ export const ProjectDetails: React.FC = () => { } }; + // 素材删除处理函数 + const handleDeleteMaterial = async (materialId: string, _materialName: string) => { + try { + await deleteMaterial(materialId); + + // 重新加载素材列表 + if (project) { + loadMaterials(project.id); + } + } catch (error) { + console.error('删除素材失败:', error); + throw error; + } + }; + + // 素材重新处理函数 + const handleReprocessMaterial = async (materialId: string) => { + try { + await processMaterials([materialId]); + + // 重新加载素材列表 + if (project) { + loadMaterials(project.id); + } + } catch (error) { + console.error('重新处理素材失败:', error); + throw error; + } + }; + if (isLoading) { return (
@@ -527,7 +559,13 @@ export const ProjectDetails: React.FC = () => { ) : materials.length > 0 ? (
{materials.map((material) => ( - + ))}
) : (