+
+
+
???
+
?????? 9:16 ??????????????????
+
+
+ } onClick={() => setCreateLibraryOpen(true)}>?????
+
+
+
- {librariesQuery.isError && (
-
- )}
+
+
+
+
+
- {assetsQuery.isError && (
-
- )}
+ {!workspaceId &&
}
+ {librariesQuery.isError &&
}
+ {assetsQuery.isError &&
}
+ {ingestJobQuery.isError &&
}
+ {classificationJobQuery.isError &&
}
+ {ingestJobQuery.data &&
}
+ {classificationJobQuery.data &&
}
- {ingestJobQuery.isError && (
-
- )}
+ {batchProgress.total > 0 && (
+
+
??????
+
+ )}
- {classificationJobQuery.isError && (
-
- )}
+ {diagnosisQuery.isError &&
}
+ {diagnosisQuery.data && (
+
+
{diagnosisQuery.data.readiness_score}{diagnosisQuery.data.readiness_label}
+
+ ??? {diagnosisQuery.data.total_assets}Ready {diagnosisQuery.data.ready_assets}?? {diagnosisQuery.data.video_assets}?? {diagnosisQuery.data.image_assets}?? {diagnosisQuery.data.voice_assets}????? {diagnosisQuery.data.estimated_video_count}
+ {diagnosisQuery.data.smart_views.map((item) => setSmartViewFilter(item.key)}>{item.label}?{item.count})}
+
+
+ )}
- {ingestJobQuery.data && (
-
- )}
+
+
+
+ ????????????????
+ ?????????????????????? {uploading ? `(${activeUploadCount} ??????)` : '????????'}
+
+
- {classificationJobQuery.data && (
-
- )}
+ {filteredAssets.length ? (
+
+ {filteredAssets.map((asset, index) => {
+ const selected = selectedRowKeys.includes(asset.id);
+ const pill = assetPill(asset);
+ const hasClassification = !!asset.metadata?.classification;
+ const isCurrentClassifying = classifyingAssetId === asset.id;
+ const isAutoClassifying = asset.metadata?.auto_classification === 'queued';
+ return (
+
setSelectedRowKeys((keys) => selected ? keys.filter((key) => key !== asset.id) : [...keys, asset.id])}>
+
+ {asset.name}{pill.text}
+ {assetMeta(asset)}
+ {renderClassification(asset)}
+ event.stopPropagation()}>
+ } loading={isCurrentClassifying && classificationMutation.isPending} disabled={isAutoClassifying || (!!classifyingAssetId && classifyingAssetId !== asset.id) || batchProgress.running} onClick={() => { setClassifyingAssetId(asset.id); classificationMutation.mutate({ workspace_id: asset.workspace_id, project_id: asset.project_id, asset_id: asset.id }); }}>{isAutoClassifying ? '???' : hasClassification ? '???' : '??'}
+
+
+
+
+ );
+ })}
+
+ ) :
+
???????????????? 9:16 ???}
- {batchProgress.total > 0 && (
-
-
- )}
-
- {diagnosisQuery.isError && (
-
- )}
-
- {diagnosisQuery.data && (
-
-
-
-
- {diagnosisQuery.data.readiness_score}
- {diagnosisQuery.data.readiness_label}
-
-
-
-
- 总素材 {diagnosisQuery.data.total_assets}
- Ready {diagnosisQuery.data.ready_assets}
- 视频 {diagnosisQuery.data.video_assets}
- 图片 {diagnosisQuery.data.image_assets}
- 配音 {diagnosisQuery.data.voice_assets}
- 预计可生成 {diagnosisQuery.data.estimated_video_count}
- 未使用 {diagnosisQuery.data.unused_assets}
- 已使用 {diagnosisQuery.data.used_assets}
- 待复核 {diagnosisQuery.data.pending_review_assets}
-
-
-
- {diagnosisQuery.data.smart_views.map((item) => (
- setSmartViewFilter(item.key)}
- >
- {item.label}:{item.count}
-
- ))}
- {smartViewFilter !== 'all' && (
-
- )}
-
-
-
-
- {diagnosisQuery.data.gaps.length ? (
-
- {diagnosisQuery.data.gaps.map((gap) => (
-
- ))}
-
- ) : (
-
- )}
-
- )}
-
-
-
- 点击或拖拽文件到这里批量上传素材
-
- 支持一次选择多个视频、音频、图片文件;上传中 {uploading ? `(${activeUploadCount} 个文件处理中)` : '自动进入导入任务'}
-
-
-
- {filteredAssets.length ? (
-
- ) : (
-
- )}
-
-
-
-
-
setCreateLibraryOpen(false)} onOk={() => form.submit()} confirmLoading={createLibraryMutation.isPending} okButtonProps={{ disabled: !workspaceId }}>
-
-
-
-
+ setCreateLibraryOpen(false)} onOk={() => form.submit()} confirmLoading={createLibraryMutation.isPending} okButtonProps={{ disabled: !workspaceId }}>
+
+
diff --git a/apps/web/src/pages/workspace/ProjectGeneration.tsx b/apps/web/src/pages/workspace/ProjectGeneration.tsx
index 639144701..d0cc1ceef 100644
--- a/apps/web/src/pages/workspace/ProjectGeneration.tsx
+++ b/apps/web/src/pages/workspace/ProjectGeneration.tsx
@@ -1,6 +1,6 @@
import React, { useEffect, useMemo, useState } from 'react';
import { useLocation, useParams } from 'react-router-dom';
-import { Alert, Button, Card, Form, Input, List, Select, Space, Typography, message } from 'antd';
+import { Alert, Button, Form, Input, List, Select, Space, Typography, message } from 'antd';
import { useMutation, useQuery } from '@tanstack/react-query';
import { createGenerationTask, getGeneratedVideoDownloadUrl, getGenerationResults, getGenerationTask } from '@/api/generation';
import { getAssetLibraries, getProjectAssetDiagnosis } from '@/api/assets';
@@ -177,84 +177,127 @@ const ProjectGeneration: React.FC = () => {
};
return (
-