feat(phase7): add classification source filters
Deploy / Deploy Staging (push) Failing after 6s
Deploy / Deploy Production (push) Has been skipped
Tests / test (push) Failing after 32s
Tests / lint (push) Failing after 26s

This commit is contained in:
Xiaoxia AI
2026-06-17 19:55:03 +08:00
parent 63d09fac2b
commit 8b378ea6c9
+36 -36
View File
@@ -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<string>('');
const [classifyingAssetId, setClassifyingAssetId] = useState<string>('');
const [classificationFilter, setClassificationFilter] = useState<string>('all');
const [classificationSourceFilter, setClassificationSourceFilter] = useState<string>('all');
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [batchMode, setBatchMode] = useState<'unclassified_only' | 'include_classified'>('unclassified_only');
const [batchProgress, setBatchProgress] = useState<BatchProgressState>(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 = () => {
<Space>
<Tag color="blue">{classification}</Tag>
<Tag>{Math.round(confidence * 100)}%</Tag>
{autoClassification === 'completed' ? <Tag color="green">自动</Tag> : null}
{autoClassification === 'completed' ? <Tag color="green">自动</Tag> : <Tag>手动</Tag>}
</Space>
);
};
@@ -418,6 +417,7 @@ const ProjectAssets: React.FC = () => {
extra={
<Space>
<Select style={{ width: 180 }} value={classificationFilter} options={classificationOptions} onChange={setClassificationFilter} />
<Select style={{ width: 180 }} value={classificationSourceFilter} options={sourceOptions} onChange={setClassificationSourceFilter} />
<Select style={{ width: 180 }} value={batchMode} options={batchModeOptions} onChange={(value) => setBatchMode(value)} />
<Select
style={{ width: 280 }}