fix video bug
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m52s

This commit is contained in:
zyc 2026-03-13 15:47:11 +08:00
parent 566c3a476f
commit 7aa1788035
2 changed files with 88 additions and 17 deletions

View File

@ -29,13 +29,19 @@ export function PromptInput() {
editorRef.current?.focus();
}, []);
// Sync editor when editorHtml resets (e.g. after submit)
// Sync editor when editorHtml changes (e.g. after submit or reEdit)
useEffect(() => {
const el = editorRef.current;
if (!el) return;
if (editorHtml === '' && el.innerHTML !== '') {
el.innerHTML = '';
if (el.innerHTML !== editorHtml) {
el.innerHTML = editorHtml;
// If the HTML is plain text but we have references, rebuild mention spans
// This handles the case where editorHtml comes from backend (plain text only)
if (editorHtml && !editorHtml.includes('data-ref-id') && references.length > 0) {
rebuildMentionSpans(el);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [editorHtml]);
// Handle @ button from toolbar
@ -47,6 +53,57 @@ export function PromptInput() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [insertAtTrigger]);
// Rebuild mention spans from plain text @label patterns
const rebuildMentionSpans = useCallback((el: HTMLElement) => {
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const replacements: { node: Text; matches: { start: number; end: number; ref: UploadedFile }[] }[] = [];
let textNode: Text | null;
while ((textNode = walker.nextNode() as Text | null)) {
const text = textNode.textContent || '';
const matches: { start: number; end: number; ref: UploadedFile }[] = [];
for (const ref of references) {
const pattern = `@${ref.label}`;
let idx = text.indexOf(pattern);
while (idx !== -1) {
matches.push({ start: idx, end: idx + pattern.length, ref });
idx = text.indexOf(pattern, idx + pattern.length);
}
}
if (matches.length > 0) {
matches.sort((a, b) => a.start - b.start);
replacements.push({ node: textNode, matches });
}
}
for (const { node, matches } of replacements) {
const text = node.textContent || '';
const frag = document.createDocumentFragment();
let lastIdx = 0;
for (const m of matches) {
if (m.start > lastIdx) {
frag.appendChild(document.createTextNode(text.slice(lastIdx, m.start)));
}
const span = document.createElement('span');
span.className = styles.mention;
span.contentEditable = 'false';
span.dataset.refId = m.ref.id;
span.dataset.refType = m.ref.type;
span.textContent = `@${m.ref.label}`;
frag.appendChild(span);
lastIdx = m.end;
}
if (lastIdx < text.length) {
frag.appendChild(document.createTextNode(text.slice(lastIdx)));
}
node.parentNode?.replaceChild(frag, node);
}
if (replacements.length > 0) {
setEditorHtml(el.innerHTML);
}
}, [references, setEditorHtml]);
const openMentionPopup = useCallback(() => {
const el = editorRef.current;
if (!el) return;

View File

@ -314,20 +314,34 @@ export const useGenerationStore = create<GenerationState>((set, get) => ({
inputStore.switchMode(task.mode);
}
if (task.mode === 'universal') {
const references: UploadedFile[] = task.references.map((r) => ({
id: r.id,
type: r.type,
previewUrl: r.previewUrl,
label: r.label,
tosUrl: r.previewUrl,
}));
useInputBarStore.setState({
prompt: task.prompt,
editorHtml: task.editorHtml || task.prompt,
aspectRatio: task.aspectRatio,
duration: task.duration,
references: task.mode === 'universal' ? references : [],
references,
});
} else {
// Keyframe mode: restore firstFrame and lastFrame
const firstRef = task.references.find((r) => r.label === '首帧');
const lastRef = task.references.find((r) => r.label === '尾帧');
useInputBarStore.setState({
prompt: task.prompt,
editorHtml: task.editorHtml || task.prompt,
aspectRatio: task.aspectRatio,
duration: task.duration,
firstFrame: firstRef ? { id: firstRef.id, type: firstRef.type, previewUrl: firstRef.previewUrl, label: '首帧', tosUrl: firstRef.previewUrl } : null,
lastFrame: lastRef ? { id: lastRef.id, type: lastRef.type, previewUrl: lastRef.previewUrl, label: '尾帧', tosUrl: lastRef.previewUrl } : null,
});
}
},
regenerate: (id) => {