fix: 修复资产页素材库引用不可查看 + 重新编辑素材泄漏
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m52s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m52s
1. AdminAssetsPage/TeamAssetsPage: asset:// 协议 URL 改用 thumb_url 显示缩略图 2. generation.ts reEdit/regenerate: 过滤 isAssetRef,素材库引用不混入 references 数组 3. PromptInput extractText: 实时同步 assetMentions store,删除 @标签后不再残留旧数据 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
177a9c7dec
commit
0b770340c8
@ -254,6 +254,27 @@ export function PromptInput() {
|
||||
if (!el) return;
|
||||
setPrompt(el.textContent || '');
|
||||
setEditorHtml(el.innerHTML);
|
||||
// Sync assetMentions from DOM — prevents stale refs after deleting @mention spans
|
||||
const mentions: Record<string, unknown>[] = [];
|
||||
el.querySelectorAll('[data-ref-type="asset"]').forEach((span) => {
|
||||
const s = span as HTMLElement;
|
||||
if (s.dataset.assetId) {
|
||||
mentions.push({
|
||||
assetId: s.dataset.assetId,
|
||||
label: s.dataset.assetName || s.textContent?.replace('@', '') || '',
|
||||
thumbUrl: s.dataset.thumbUrl || '',
|
||||
assetType: s.dataset.assetType || 'Image',
|
||||
duration: parseFloat(s.dataset.duration || '0'),
|
||||
});
|
||||
} else if (s.dataset.assetGroupId) {
|
||||
mentions.push({
|
||||
groupId: s.dataset.assetGroupId,
|
||||
label: s.dataset.groupName || s.textContent?.replace('@', '') || '',
|
||||
thumbUrl: s.dataset.thumbUrl || '',
|
||||
});
|
||||
}
|
||||
});
|
||||
useInputBarStore.setState({ assetMentions: mentions });
|
||||
}, [setPrompt, setEditorHtml]);
|
||||
|
||||
// Remove orphaned mention spans when a reference is deleted
|
||||
|
||||
@ -31,14 +31,23 @@ function VideoThumbnail({ video, onClick }: { video: AssetVideo; onClick: () =>
|
||||
);
|
||||
}
|
||||
|
||||
function isAssetUrl(url: string): boolean {
|
||||
return url.startsWith('asset://') || url.startsWith('Asset://');
|
||||
}
|
||||
|
||||
function assetVideoToTask(v: AssetVideo): GenerationTask {
|
||||
const references = (v.reference_urls || []).map((ref, i) => ({
|
||||
const references = (v.reference_urls || []).map((ref, i) => {
|
||||
const url = ref.url || '';
|
||||
const assetRef = isAssetUrl(url);
|
||||
return {
|
||||
id: `ref_${v.task_id}_${i}`,
|
||||
type: (ref.type || 'image') as 'image' | 'video',
|
||||
previewUrl: ref.url,
|
||||
type: (ref.type || 'image') as 'image' | 'video' | 'audio',
|
||||
previewUrl: assetRef ? (ref.thumb_url || '') : url,
|
||||
label: ref.label || `素材${i + 1}`,
|
||||
role: ref.role,
|
||||
}));
|
||||
isAssetRef: assetRef || undefined,
|
||||
};
|
||||
});
|
||||
return {
|
||||
id: String(v.id),
|
||||
taskId: v.task_id,
|
||||
|
||||
@ -31,14 +31,23 @@ function VideoThumbnail({ video, onClick }: { video: AssetVideo; onClick: () =>
|
||||
);
|
||||
}
|
||||
|
||||
function isAssetUrl(url: string): boolean {
|
||||
return url.startsWith('asset://') || url.startsWith('Asset://');
|
||||
}
|
||||
|
||||
function assetVideoToTask(v: AssetVideo): GenerationTask {
|
||||
const references = (v.reference_urls || []).map((ref, i) => ({
|
||||
const references = (v.reference_urls || []).map((ref, i) => {
|
||||
const url = ref.url || '';
|
||||
const assetRef = isAssetUrl(url);
|
||||
return {
|
||||
id: `ref_${v.task_id}_${i}`,
|
||||
type: (ref.type || 'image') as 'image' | 'video',
|
||||
previewUrl: ref.url,
|
||||
type: (ref.type || 'image') as 'image' | 'video' | 'audio',
|
||||
previewUrl: assetRef ? (ref.thumb_url || '') : url,
|
||||
label: ref.label || `素材${i + 1}`,
|
||||
role: ref.role,
|
||||
}));
|
||||
isAssetRef: assetRef || undefined,
|
||||
};
|
||||
});
|
||||
return {
|
||||
id: String(v.id),
|
||||
taskId: v.task_id,
|
||||
|
||||
@ -618,8 +618,10 @@ export const useGenerationStore = create<GenerationState>((set, get) => ({
|
||||
}
|
||||
|
||||
if (task.mode === 'universal') {
|
||||
// task.references only contains file refs (assets filtered in backendToFrontend)
|
||||
const references: UploadedFile[] = task.references.map((r) => ({
|
||||
// Only include direct file refs — asset library refs are tracked via assetMentions
|
||||
const references: UploadedFile[] = task.references
|
||||
.filter((r) => !r.isAssetRef)
|
||||
.map((r) => ({
|
||||
id: r.id,
|
||||
type: r.type,
|
||||
previewUrl: r.previewUrl,
|
||||
@ -669,8 +671,10 @@ export const useGenerationStore = create<GenerationState>((set, get) => ({
|
||||
}
|
||||
|
||||
// For regeneration, we need to re-submit with the same TOS URLs
|
||||
// Set up the input bar state, then call addTask
|
||||
const references: UploadedFile[] = task.references.map((r) => ({
|
||||
// Only include direct file refs — asset library refs go via assetMentions fallback
|
||||
const references: UploadedFile[] = task.references
|
||||
.filter((r) => !r.isAssetRef)
|
||||
.map((r) => ({
|
||||
id: r.id,
|
||||
type: r.type,
|
||||
previewUrl: r.previewUrl,
|
||||
|
||||
@ -76,7 +76,7 @@ export interface BackendTask {
|
||||
result_url: string;
|
||||
thumbnail_url: string;
|
||||
error_message: string;
|
||||
reference_urls: { url: string; type: string; role: string; label: string }[];
|
||||
reference_urls: { url: string; type: string; role: string; label: string; thumb_url?: string }[];
|
||||
is_favorited: boolean;
|
||||
seed: number;
|
||||
created_at: string;
|
||||
@ -407,7 +407,7 @@ export interface AssetVideo {
|
||||
seconds_consumed: number;
|
||||
cost_amount?: number;
|
||||
aspect_ratio: string;
|
||||
reference_urls?: { url: string; type: string; role: string; label: string }[];
|
||||
reference_urls?: { url: string; type: string; role: string; label: string; thumb_url?: string }[];
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user