From 9f84ffe7f412a6ac9686c2b1ad968fcfda3995e6 Mon Sep 17 00:00:00 2001 From: imeepos Date: Thu, 17 Jul 2025 13:14:40 +0800 Subject: [PATCH] refactor: integrate export records into project details page - Add export records tab to ProjectDetails page - Optimize ExportRecordManager for compact tab display - Remove global export records navigation (now project-level) - Add showHeader and compact props to ExportRecordManager - Remove standalone ExportRecordsPage (no longer needed) - Update navigation structure to reflect project-level functionality Export records are now properly scoped to individual projects and accessible through the project details interface. --- apps/desktop/src/App.tsx | 2 - .../src/components/ExportRecordManager.tsx | 56 +++++++++++-------- apps/desktop/src/components/Navigation.tsx | 9 +-- apps/desktop/src/pages/ExportRecordsPage.tsx | 16 ------ apps/desktop/src/pages/ProjectDetails.tsx | 36 +++++++++++- 5 files changed, 67 insertions(+), 52 deletions(-) delete mode 100644 apps/desktop/src/pages/ExportRecordsPage.tsx diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx index da7863e..9b20475 100644 --- a/apps/desktop/src/App.tsx +++ b/apps/desktop/src/App.tsx @@ -8,7 +8,6 @@ import ModelDetail from './pages/ModelDetail'; import AiClassificationSettings from './pages/AiClassificationSettings'; import TemplateManagement from './pages/TemplateManagement'; import { MaterialModelBinding } from './pages/MaterialModelBinding'; -import ExportRecordsPage from './pages/ExportRecordsPage'; import Navigation from './components/Navigation'; import { NotificationSystem, useNotifications } from './components/NotificationSystem'; import { useProjectStore } from './store/projectStore'; @@ -79,7 +78,6 @@ function App() { } /> } /> } /> - } /> diff --git a/apps/desktop/src/components/ExportRecordManager.tsx b/apps/desktop/src/components/ExportRecordManager.tsx index 614ef52..285f315 100644 --- a/apps/desktop/src/components/ExportRecordManager.tsx +++ b/apps/desktop/src/components/ExportRecordManager.tsx @@ -11,11 +11,15 @@ import { interface ExportRecordManagerProps { projectId?: string; matchingResultId?: string; + showHeader?: boolean; // 是否显示标题和描述 + compact?: boolean; // 紧凑模式,适用于tab显示 } -const ExportRecordManager: React.FC = ({ - projectId, - matchingResultId +const ExportRecordManager: React.FC = ({ + projectId, + matchingResultId, + showHeader = true, + compact = false }) => { const [records, setRecords] = useState([]); const [statistics, setStatistics] = useState(null); @@ -55,7 +59,7 @@ const ExportRecordManager: React.FC = ({ const result = await invoke('list_export_records', { options }); setRecords(result); - + // 更新总数(这里简化处理,实际应该从后端返回) setPagination(prev => ({ ...prev, total: result.length })); } catch (err) { @@ -70,8 +74,8 @@ const ExportRecordManager: React.FC = ({ try { let stats: ExportRecordStatistics; if (projectId) { - stats = await invoke('get_project_export_statistics', { - projectId + stats = await invoke('get_project_export_statistics', { + projectId }); } else { stats = await invoke('get_global_export_statistics'); @@ -127,8 +131,8 @@ const ExportRecordManager: React.FC = ({ if (!days) return; try { - const count = await invoke('cleanup_expired_export_records', { - days: parseInt(days) + const count = await invoke('cleanup_expired_export_records', { + days: parseInt(days) }); alert(`已清理 ${count} 条过期记录`); await loadExportRecords(); @@ -184,31 +188,35 @@ const ExportRecordManager: React.FC = ({ }, [projectId, matchingResultId, filters, pagination.page]); return ( -
-
-

- 导出记录管理 - {projectId && (项目范围)} - {matchingResultId && (匹配结果范围)} -

+
+ {showHeader && ( +
+

+ 导出记录管理 + {projectId && (项目范围)} + {matchingResultId && (匹配结果范围)} +

+
+ )} +
{/* 统计信息 */} {statistics && ( -
-
-
{statistics.total_exports}
+
+
+
{statistics.total_exports}
总导出次数
-
-
{statistics.successful_exports}
+
+
{statistics.successful_exports}
成功导出
-
-
{statistics.failed_exports}
+
+
{statistics.failed_exports}
失败导出
-
-
+
+
{formatFileSize(statistics.total_file_size)}
总文件大小
diff --git a/apps/desktop/src/components/Navigation.tsx b/apps/desktop/src/components/Navigation.tsx index c4475f4..945b573 100644 --- a/apps/desktop/src/components/Navigation.tsx +++ b/apps/desktop/src/components/Navigation.tsx @@ -5,8 +5,7 @@ import { UserGroupIcon, CpuChipIcon, DocumentDuplicateIcon, - LinkIcon, - DocumentArrowDownIcon + LinkIcon } from '@heroicons/react/24/outline'; const Navigation: React.FC = () => { @@ -42,12 +41,6 @@ const Navigation: React.FC = () => { href: '/ai-classification-settings', icon: CpuChipIcon, description: '管理AI视频分类规则' - }, - { - name: '导出记录', - href: '/export-records', - icon: DocumentArrowDownIcon, - description: '查看和管理导出记录' } ]; diff --git a/apps/desktop/src/pages/ExportRecordsPage.tsx b/apps/desktop/src/pages/ExportRecordsPage.tsx deleted file mode 100644 index 50de048..0000000 --- a/apps/desktop/src/pages/ExportRecordsPage.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import ExportRecordManager from '../components/ExportRecordManager'; - -const ExportRecordsPage: React.FC = () => { - return ( -
-
-
- -
-
-
- ); -}; - -export default ExportRecordsPage; diff --git a/apps/desktop/src/pages/ProjectDetails.tsx b/apps/desktop/src/pages/ProjectDetails.tsx index 914ab98..822ec5c 100644 --- a/apps/desktop/src/pages/ProjectDetails.tsx +++ b/apps/desktop/src/pages/ProjectDetails.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState, useCallback, useMemo, useRef } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; -import { ArrowLeft, FolderOpen, Upload, FileVideo, FileAudio, FileImage, HardDrive, Brain, Loader2, Link, Layers, Calendar, MapPin, Users, CheckCircle, Filter, Shuffle } from 'lucide-react'; +import { ArrowLeft, FolderOpen, Upload, FileVideo, FileAudio, FileImage, HardDrive, Brain, Loader2, Link, Layers, Calendar, MapPin, Users, CheckCircle, Filter, Shuffle, Download } from 'lucide-react'; import { invoke } from '@tauri-apps/api/core'; import { useProjectStore } from '../store/projectStore'; import { useMaterialStore } from '../store/materialStore'; @@ -16,6 +16,7 @@ import { MaterialEditDialog } from '../components/MaterialEditDialog'; import { VideoClassificationProgress } from '../components/VideoClassificationProgress'; import { AiAnalysisLogViewer } from '../components/AiAnalysisLogViewer'; import MaterialCardSkeleton from '../components/MaterialCardSkeleton'; +import ExportRecordManager from '../components/ExportRecordManager'; import { ProjectTemplateBindingList } from '../components/ProjectTemplateBindingList'; import { ProjectTemplateBindingForm } from '../components/ProjectTemplateBindingForm'; import { MaterialMatchingResultDialog } from '../components/MaterialMatchingResultDialog'; @@ -123,7 +124,7 @@ export const ProjectDetails: React.FC = () => { const [editingBinding, setEditingBinding] = useState(null); const [showMaterialEditDialog, setShowMaterialEditDialog] = useState(false); const [editingMaterial, setEditingMaterial] = useState(null); - const [activeTab, setActiveTab] = useState<'overview' | 'materials' | 'segments' | 'templates' | 'matching-results' | 'usage-stats' | 'ai-logs'>('overview'); + const [activeTab, setActiveTab] = useState<'overview' | 'materials' | 'segments' | 'templates' | 'matching-results' | 'export-records' | 'usage-stats' | 'ai-logs'>('overview'); const [_batchClassificationResult, setBatchClassificationResult] = useState(null); // 素材匹配状态 @@ -976,6 +977,20 @@ export const ProjectDetails: React.FC = () => { 匹配
+
)} + {/* 导出记录选项卡 */} + {activeTab === 'export-records' && project && ( +
+
+

导出记录

+

+ 查看项目中所有导出操作的记录,包括导出状态、文件信息和统计数据。 +

+
+ +
+ )} + {/* 素材使用状态选项卡 */} {activeTab === 'usage-stats' && project && (