diff --git a/apps/web/src/pages/workspace/ProjectAssets.tsx b/apps/web/src/pages/workspace/ProjectAssets.tsx index 9cdb91467..3f6cd312f 100644 --- a/apps/web/src/pages/workspace/ProjectAssets.tsx +++ b/apps/web/src/pages/workspace/ProjectAssets.tsx @@ -47,6 +47,13 @@ const classificationOptions = [ { label: 'other', value: 'other' }, ]; +const sourceOptions = [ + { label: '全部来源', value: 'all' }, + { label: '自动分类', value: 'auto' }, + { label: '手动分类', value: 'manual' }, + { label: '未分类', value: 'unclassified' }, +]; + const batchModeOptions = [ { label: '仅未分类', value: 'unclassified_only' }, { label: '包含已分类重跑', value: 'include_classified' }, @@ -83,6 +90,7 @@ const ProjectAssets: React.FC = () => { const [classificationJobId, setClassificationJobId] = useState(''); const [classifyingAssetId, setClassifyingAssetId] = useState(''); const [classificationFilter, setClassificationFilter] = useState('all'); + const [classificationSourceFilter, setClassificationSourceFilter] = useState('all'); const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [batchMode, setBatchMode] = useState<'unclassified_only' | 'include_classified'>('unclassified_only'); const [batchProgress, setBatchProgress] = useState(defaultBatchProgress); @@ -166,9 +174,7 @@ const ProjectAssets: React.FC = () => { const pollBatchJobs = async () => { try { const results = await Promise.all(batchJobIds.map((jobId) => getClassificationJob(jobId))); - if (cancelled) { - return; - } + if (cancelled) return; const completedIds = results.filter((job) => job.status === 'completed').map((job) => job.id); const failedIds = results.filter((job) => job.status === 'failed').map((job) => job.id); @@ -230,11 +236,28 @@ const ProjectAssets: React.FC = () => { ); const filteredAssets = useMemo(() => { - const items = assetsQuery.data || []; - if (classificationFilter === 'all') return items; - if (classificationFilter === 'unclassified') return items.filter((item) => !item.metadata?.classification); - return items.filter((item) => item.metadata?.classification === classificationFilter); - }, [assetsQuery.data, classificationFilter]); + let items = assetsQuery.data || []; + + if (classificationFilter !== 'all') { + if (classificationFilter === 'unclassified') { + items = items.filter((item) => !item.metadata?.classification); + } else { + items = items.filter((item) => item.metadata?.classification === classificationFilter); + } + } + + if (classificationSourceFilter !== 'all') { + if (classificationSourceFilter === 'unclassified') { + items = items.filter((item) => !item.metadata?.classification); + } else if (classificationSourceFilter === 'auto') { + items = items.filter((item) => item.metadata?.auto_classification === 'completed'); + } else if (classificationSourceFilter === 'manual') { + items = items.filter((item) => !!item.metadata?.classification && item.metadata?.auto_classification !== 'completed'); + } + } + + return items; + }, [assetsQuery.data, classificationFilter, classificationSourceFilter]); const selectedAssets = useMemo( () => filteredAssets.filter((item) => selectedRowKeys.includes(item.id)), @@ -268,15 +291,7 @@ const ProjectAssets: React.FC = () => { return; } - setBatchProgress({ - total: selectedAssets.length, - submitted: 0, - failed: 0, - skipped: skippedAssets.length, - completed: 0, - running: true, - tracking: false, - }); + setBatchProgress({ total: selectedAssets.length, submitted: 0, failed: 0, skipped: skippedAssets.length, completed: 0, running: true, tracking: false }); setBatchJobIds([]); setBatchCompletedIds([]); setBatchFailedIds([]); @@ -297,27 +312,11 @@ const ProjectAssets: React.FC = () => { } catch { failed += 1; } - setBatchProgress({ - total: selectedAssets.length, - submitted, - failed, - skipped: skippedAssets.length, - completed: 0, - running: true, - tracking: false, - }); + setBatchProgress({ total: selectedAssets.length, submitted, failed, skipped: skippedAssets.length, completed: 0, running: true, tracking: false }); } setBatchJobIds(createdJobIds); - setBatchProgress({ - total: selectedAssets.length, - submitted, - failed, - skipped: skippedAssets.length, - completed: 0, - running: createdJobIds.length > 0, - tracking: createdJobIds.length > 0, - }); + setBatchProgress({ total: selectedAssets.length, submitted, failed, skipped: skippedAssets.length, completed: 0, running: createdJobIds.length > 0, tracking: createdJobIds.length > 0 }); if (failed === 0) { message.success(`批量分类已提交:成功 ${submitted},跳过 ${skippedAssets.length}`); @@ -343,7 +342,7 @@ const ProjectAssets: React.FC = () => { {classification} {Math.round(confidence * 100)}% - {autoClassification === 'completed' ? 自动 : null} + {autoClassification === 'completed' ? 自动 : 手动} ); }; @@ -418,6 +417,7 @@ const ProjectAssets: React.FC = () => { extra={