上传素材管控-历史素材success
This commit is contained in:
@@ -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);
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user