上传素材管控-历史素材success

This commit is contained in:
2026-07-08 16:25:03 +08:00
parent 657505e63b
commit d085a6d2ec
47 changed files with 5424 additions and 447 deletions
+47 -21
View File
@@ -33,7 +33,7 @@ import {
import { useAppStore } from '../store/useAppStore';
import { PrivatePortraitAssetPicker } from '../components/privatePortrait';
import type { PrivatePortraitLibraryType, PrivatePortraitSelectableAsset } from '../types';
import type { PrivatePortraitLibraryType, PrivatePortraitSelectableAsset, UploadResourceHistoryItem } from '../types';
import {
PlusOutlined,
@@ -78,8 +78,10 @@ interface MediaReference {
source?: string;
private_asset_id?: string;
remote_asset_id?: string;
upload_resource_id?: string;
}
interface Message {
id: string;
original_prompt: string;
@@ -1503,6 +1505,48 @@ const AIChatPage: React.FC = () => {
return true;
};
const normalizeUploadResourceHistoryItem = (item: UploadResourceHistoryItem): MediaReference | null => {
const media = item.mediaReference;
const refType = (media?.type || item.resourceType) as 'image' | 'video' | 'audio';
const url = media?.url || item.resourceUrl || item.displayUrl || item.previewUrl || '';
if (!url) {
message.error(`${item.fileName || item.id} 缺少素材地址,不能用于 AI 创作`);
return null;
}
if (refType === 'audio' && mediaType !== 'video') {
message.error('仅视频模式支持添加音频素材');
return null;
}
const duration = Number(media?.duration ?? item.durationSeconds);
return {
name: media?.name || item.fileName || item.id,
type: refType,
url,
source: 'upload_resource',
upload_resource_id: item.id,
label: '',
...((refType === 'video' || refType === 'audio') && Number.isFinite(duration) && duration > 0 ? { duration } : {}),
};
};
const handleUploadResourceHistorySelected = (items: UploadResourceHistoryItem[]) => {
const normalized = items
.map(normalizeUploadResourceHistoryItem)
.filter(Boolean) as MediaReference[];
if (!normalized.length) return;
const latestMedia = useAppStore.getState().currentMedia as MediaReference[];
if (!validateMediaReferencesBeforeAdd(latestMedia, normalized)) {
return;
}
const newList = [...latestMedia, ...normalized];
const labels = generateMediaLabels(newList);
setCurrentMedia(newList.map((m, i) => ({ ...m, label: labels[i] })));
message.success(`已添加 ${normalized.length} 个历史上传素材参考`);
};
const normalizePrivatePortraitAsset = (asset: PrivatePortraitSelectableAsset): MediaReference | null => {
if (asset.assetType === 'Audio') {
message.error('音频私域素材暂不支持用于 AI 创作');
@@ -2612,16 +2656,7 @@ const AIChatPage: React.FC = () => {
<UploadSelector
accept={mediaType === 'image' ? 'image/*' : 'image/*,video/*,audio/*'}
onLocalSelect={handleBatchUpload}
onHistorySelect={(items) => {
const newMedia = items.map((item: any) => ({
name: item.name,
type: item.type as 'image' | 'video' | 'audio',
url: '',
label: '',
}));
setCurrentMedia([...currentMedia, ...newMedia]);
message.success(`成功添加${items.length}个历史记录`);
}}
onHistorySelect={handleUploadResourceHistorySelected}
onPortraitLibrarySelect={(libraryType) => {
openPrivatePortraitPicker(libraryType);
}}
@@ -2792,16 +2827,7 @@ const AIChatPage: React.FC = () => {
<UploadSelector
accept={mediaType === 'image' ? 'image/*' : 'image/*,video/*,audio/*'}
onLocalSelect={handleBatchUpload}
onHistorySelect={(items) => {
const newMedia = items.map((item: any) => ({
name: item.name,
type: item.type as 'image' | 'video' | 'audio',
url: '',
label: '',
}));
setCurrentMedia([...currentMedia, ...newMedia]);
message.success(`成功添加${items.length}个历史记录`);
}}
onHistorySelect={handleUploadResourceHistorySelected}
onPortraitLibrarySelect={(libraryType) => {
openPrivatePortraitPicker(libraryType);
}}