feat(*): 创作工作台 - 完善媒体上传预览与连线交互并修复任务章节及日志筛选

This commit is contained in:
ddCat committed 2026-09-08 17:26:34 +08:00
1 parent 95b004ec0f
commit 068a8daea6
56 files changed
+3316 -274

No files matched your search

@@ -1,6 +1,7 @@
import { runBackendCanvasGenerationTask } from "@/lib/canvas/canvas-project-generation";
import { storyboardRowsFromTask } from "@/lib/canvas/canvas-project-domain";
import { parseCharacterBreakdown, type CharacterBreakdown } from "@/lib/canvas/canvas-character-reference";
import { parseChapterAssetBreakdown, type ChapterAssetBreakdown } from "@/lib/canvas/chapter-asset-breakdown";
import { parseCharacterBreakdown } from "@/lib/canvas/canvas-character-reference";
import { backendProviderConfig, parseBackendGenerationResult } from "@/services/api/generation-task";
import { createGenerationTask, waitForGenerationTask, type GenerationTask } from "@/services/api/task-center";
import type { Skill } from "@/services/api/skills";
@@ -38,24 +39,28 @@ export function chapterTaskIdentity(task: GenerationTask): { chapterId: string;
return null;
}
export function chapterCharactersFromGenerationTask(task: GenerationTask) {
export function chapterAssetsFromGenerationTask(task: GenerationTask) {
const result = parseBackendGenerationResult(task);
if (!result.text?.trim()) throw new Error("模型没有返回可用的角色提取结果");
return parseCharacterBreakdown(result.text);
if (!result.text?.trim()) throw new Error("模型没有返回可用的章节资产提取结果");
// 历史角色任务的输出契约只有角色;仅按明确的模板操作恢复,不能给新任务缺字段兜底。
if (generationTaskMetadata(task.inputJson).promptTemplateOperation === "character_extract") {
return { characters: parseCharacterBreakdown(result.text), scenes: [], props: [] };
}
return parseChapterAssetBreakdown(result.text);
}
export function chapterStoryboardFromGenerationTask(task: GenerationTask) {
return storyboardRowsFromTask(task);
}
export async function extractChapterCharacters(input: ChapterAnalysisInput, options?: ChapterTaskOptions): Promise<CharacterBreakdown[]> {
export async function extractChapterAssets(input: ChapterAnalysisInput, options?: ChapterTaskOptions): Promise<ChapterAssetBreakdown> {
const result = await runProjectTextTask(input, "chapter_character_breakdown", {
项目名称: input.projectName,
章节名称: input.chapterTitle,
项目画风: input.projectStyle || "项目尚未指定画风,保持视觉描述中性、可执行。",
章节正文: input.sourceText,
}, options);
return parseCharacterBreakdown(result);
return parseChapterAssetBreakdown(result);
}
type ChapterStoryboardGenerationInput = {
@@ -118,9 +123,9 @@ async function runProjectTextTask(input: ChapterAnalysisInput, operation: string
projectId: input.projectId,
nodeId: `${operation}:${input.chapterId}`,
mode: "text",
prompt: "使用当前启用的角色卡提取模板。",
prompt: "使用当前启用的章节角色、场景与道具提取模板。",
config: { ...input.config, model },
metadata: { domainProjectId: input.projectId, chapterId: input.chapterId, operation, promptTemplateOperation: "character_extract", promptTemplateVariables },
metadata: { domainProjectId: input.projectId, chapterId: input.chapterId, operation, promptTemplateOperation: "chapter_assets_extract", promptTemplateVariables },
onTaskCreated: options?.onTaskUpdate,
});
if (!result.text?.trim()) throw new Error("模型没有返回可用结果");