From 02f6aac04caa9524ebc80cbd8048d8ae8d7c3003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=B8=85?= <2944435683> Date: Tue, 31 Mar 2026 04:01:06 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E7=94=9F=E6=88=90=E8=A7=86=E9=A2=91api=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=8C=E4=BF=AE=E6=94=B9=E8=B5=84=E4=BA=A7?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E8=AF=8D=E7=94=9F=E6=88=90=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/assets/getMaterialData.ts | 2 +- .../assetsGenerate/batchPolishAssetsPrompt.ts | 26 +++---- .../assetsGenerate/polishAssetsPrompt.ts | 25 +++--- src/routes/production/getFlowData.ts | 23 ++++-- src/routes/production/getProductionData.ts | 77 +++++++------------ .../production/workbench/videoPolling.ts | 8 +- 6 files changed, 72 insertions(+), 89 deletions(-) diff --git a/src/routes/assets/getMaterialData.ts b/src/routes/assets/getMaterialData.ts index 06e7c64..d3c14cc 100644 --- a/src/routes/assets/getMaterialData.ts +++ b/src/routes/assets/getMaterialData.ts @@ -45,7 +45,7 @@ export default router.post( id: row.id, filePath: row.filePath ? await u.oss.getFileUrl(row.filePath) : "", selected: selectedIds.has(row.id), - storyboard: row.storyboardId, + videoParametersId: row.videoParametersId, })), ); diff --git a/src/routes/assetsGenerate/batchPolishAssetsPrompt.ts b/src/routes/assetsGenerate/batchPolishAssetsPrompt.ts index 130f7c0..56a29ce 100644 --- a/src/routes/assetsGenerate/batchPolishAssetsPrompt.ts +++ b/src/routes/assetsGenerate/batchPolishAssetsPrompt.ts @@ -107,25 +107,21 @@ export default router.post( if (!visualManual) return res.status(500).send(error("视觉手册未定义")); findItemByName(result, item.name, config.itemType); - const systemPrompt = ` - 请根据以下参数生成${config.label}提示词: - - **基础参数:** - - 小说类型: ${project?.type || "未指定"} - - 小说背景: ${project?.intro || "未指定"} - - **${config.nameLabel}设定:** - - ${config.nameLabel}名称:${item.name}, - - ${config.nameLabel}描述:${item.describe}, - - 请严格按照skill规范生成${item.type === "role" ? "人物角色四视图" : config.label}提示词。 - ${visualManual} - `; + const systemPrompt = visualManual; try { const { _output } = (await u.Ai.Text("universalAi").invoke({ system: systemPrompt, - messages: [{ role: "user", content: "小说原文" + novelText }], + messages: [ + { + role: "user", + content: ` + **基础参数:** + **${config.nameLabel}设定:** + - ${config.nameLabel}名称:${item.name}, + - ${config.nameLabel}描述:${item.describe},`, + }, + ], })) as any; if (!_output) { diff --git a/src/routes/assetsGenerate/polishAssetsPrompt.ts b/src/routes/assetsGenerate/polishAssetsPrompt.ts index bb12bc5..95ea549 100644 --- a/src/routes/assetsGenerate/polishAssetsPrompt.ts +++ b/src/routes/assetsGenerate/polishAssetsPrompt.ts @@ -101,25 +101,20 @@ export default router.post( const novelData = (await u.db("o_novel").whereIn("chapterIndex", [1]).select("*")) as NovelChapter[]; const novelText = mergeNovelText(novelData); - const systemPrompt = ` - 请根据以下参数生成${config.label}提示词: - - **基础参数:** - - 小说类型: ${project?.type || "未指定"} - - 小说背景: ${project?.intro || "未指定"} - - **${config.nameLabel}设定:** - - ${config.nameLabel}名称:${name}, - - ${config.nameLabel}描述:${describe}, - - 请严格按照skill规范生成${type === "role" ? "人物角色四视图" : config.label}提示词 - ${visualManual}。 - `; + const systemPrompt = visualManual; try { const { _output } = (await u.Ai.Text("universalAi").invoke({ system: systemPrompt, - messages: [{ role: "user", content: "小说原文" + novelText }], + messages: [ + { + role: "user", + content: `**基础参数:** + **${config.nameLabel}设定:** + - ${config.nameLabel}名称:${name}, + - ${config.nameLabel}描述:${describe},`, + }, + ], })) as any; if (!_output) return res.status(500).send("失败"); diff --git a/src/routes/production/getFlowData.ts b/src/routes/production/getFlowData.ts index ffa25b5..46a859d 100644 --- a/src/routes/production/getFlowData.ts +++ b/src/routes/production/getFlowData.ts @@ -73,11 +73,24 @@ export default router.post( storyboard: [], //todo:矫正workbench数据 workbench: { - name: scriptData?.name ?? "", - duration: "01:03", - resolution: "1920×1080", - fps: "30fps", - gradient: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)", + videoList: [ + { + id: 1, + prompt: "动起来", + filePath: await u.oss.getFileUrl("/artStyle/5d96256a-1610-43a6-a469-c2385cc2287e.jpg"), + duration: 4, + scriptId: 1, + selectedVideoId: 1, + }, + { + id: 2, + prompt: "跳起来", + filePath: await u.oss.getFileUrl("/artStyle/5d96256a-1610-43a6-a469-c2385cc2287e.jpg"), + duration: 4, + scriptId: 1, + selectedVideoId: 1, + }, + ], }, //todo:矫正封面数据 poster: { diff --git a/src/routes/production/getProductionData.ts b/src/routes/production/getProductionData.ts index 1c55f08..90b725e 100644 --- a/src/routes/production/getProductionData.ts +++ b/src/routes/production/getProductionData.ts @@ -7,36 +7,25 @@ const router = express.Router(); export default router.post( "/", validateFields({ - scriptId: z.number(), - projectId: z.number(), + ids: z.array(z.number()), }), async (req, res) => { - const { scriptId, projectId } = req.body; - - //查询分镜数据 - const storyboards = await u.db("o_storyboard").where("o_storyboard.scriptId", scriptId).select("*").orderBy("index", "asc"); - - //查询项目默认的视频模型 - const project = await u.db("o_project").where("id", projectId).first(); - - const storyboardsList = await Promise.all( - storyboards.map(async (item) => { - return { - ...item, - model: project?.videoModel || null, - filePath: item.filePath ? await u.oss.getFileUrl(item.filePath) : null, - }; - }), - ); - - const storyboardIds = storyboardsList.map((s) => s.id as number); + const { ids } = req.body; //查询分镜配置 - const storyboardConfigs = await u.db("o_videoConfig").whereIn("storyboardId", storyboardIds).select("*"); - const storyboardConfigsList = await Promise.all( - storyboardConfigs.map(async (item) => { - if (item.data) { - const parsedData = JSON.parse(item.data); + const storyboardConfigs = await u.db("o_videoConfig").whereIn("storyboardId", ids).select("*"); + + //查询视频数据 + const videos = await u.db("o_video").whereIn("storyboardId", ids).select("*"); + + //组装数据 + const data = await Promise.all( + ids.map(async (storyboardId: number) => { + // 处理配置 + const configRow = storyboardConfigs.find((item) => item.storyboardId === storyboardId) || null; + let config = null; + if (configRow?.data) { + const parsedData = JSON.parse(configRow.data); const dataWithFilePath = await Promise.all( parsedData.map(async (d: { type: string; id: number }) => { if (d.type === "assets" && d.id) { @@ -61,35 +50,25 @@ export default router.post( return null; }), ); - - return { - ...item, - data: dataWithFilePath, - }; + config = { ...configRow, data: dataWithFilePath }; } - }), - ); - //查询视频数据 - const videos = await u.db("o_video").whereIn("storyboardId", storyboardIds).select("*"); - const videosList = await Promise.all( - videos.map(async (item) => { + // 处理视频 + const storyboardVideos = videos.filter((v) => v.storyboardId === storyboardId); + const videosList = await Promise.all( + storyboardVideos.map(async (item) => ({ + ...item, + filePath: item.filePath ? await u.oss.getFileUrl(item.filePath) : null, + })), + ); + return { - ...item, - filePath: item.filePath ? await u.oss.getFileUrl(item.filePath) : null, + id: storyboardId, + config, + videos: videosList, }; }), ); - - //组装数据 - const data = storyboardsList.map((storyboard) => { - const config = storyboardConfigsList.find((item) => item?.storyboardId === storyboard.id) || null; - return { - ...storyboard, - config, - videos: videosList.filter((video) => video.storyboardId === storyboard.id), - }; - }); return res.status(200).send(success(data)); }, ); diff --git a/src/routes/production/workbench/videoPolling.ts b/src/routes/production/workbench/videoPolling.ts index 2d68b51..897c3d0 100644 --- a/src/routes/production/workbench/videoPolling.ts +++ b/src/routes/production/workbench/videoPolling.ts @@ -8,12 +8,12 @@ const router = express.Router(); export default router.post( "/", validateFields({ - scriptId: z.number(), + id: z.number(), specifyIds: z.array(z.number()), }), async (req, res) => { - const { scriptId, specifyIds } = req.body; - const data = await u.db("o_video").where("scriptId", scriptId).whereIn("id", specifyIds).andWhere("state", "生成中").select("*"); + const { id, specifyIds } = req.body; + const data = await u.db("o_video").where("id", id).whereIn("id", specifyIds).andWhere("state", "生成中").select("*"); res.status(200).send(success(data)); }, -); \ No newline at end of file +); From 448e0616e14d479c006e63900de40247d3019f58 Mon Sep 17 00:00:00 2001 From: zhishi <1951671751@qq.com> Date: Tue, 31 Mar 2026 15:14:20 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0xml=20=E5=88=86=E9=95=9C?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/agents/productionAgent/index.ts | 7 +- src/agents/productionAgent/tools.ts | 2 +- src/router.ts | 236 +++++++++--------- .../assets/batchGenerateAssetsImage.ts | 26 +- .../storyboard/batchAddStoryboardInfo.ts | 30 ++- .../storyboard/batchGenerateImage.ts | 118 +-------- .../storyboard/updateStoryboardInfo.ts | 22 -- src/routes/script/extractAssets.ts | 8 +- src/types/database.d.ts | 24 +- 9 files changed, 178 insertions(+), 295 deletions(-) delete mode 100644 src/routes/production/storyboard/updateStoryboardInfo.ts diff --git a/src/agents/productionAgent/index.ts b/src/agents/productionAgent/index.ts index d64fa90..082c430 100644 --- a/src/agents/productionAgent/index.ts +++ b/src/agents/productionAgent/index.ts @@ -138,6 +138,7 @@ function createSubAgent(parentCtx: AgentContext) { "你必须使用如下XML格式写入工作区:\n```", "拍摄计划:内容", "分镜表:内容", + "分镜面板: ", "```", ].join("\n"); // "剧本:", @@ -190,7 +191,7 @@ async function createArtSkills(artName: string) { } const res = { prompt: buildSkillPrompt(mainSkills), - tools: createSkillTools(mainSkills, { mainSkill: mainSkills, secondarySkills: [], tertiarySkills: [] },workerPath), + tools: createSkillTools(mainSkills, { mainSkill: mainSkills, secondarySkills: [], tertiarySkills: [] }, workerPath), }; - return res -} \ No newline at end of file + return res; +} diff --git a/src/agents/productionAgent/tools.ts b/src/agents/productionAgent/tools.ts index 738e1cf..96e1888 100644 --- a/src/agents/productionAgent/tools.ts +++ b/src/agents/productionAgent/tools.ts @@ -175,7 +175,7 @@ export default (toolCpnfig: ToolConfig) => { generate_storyboard: tool({ description: "生成分镜图片", inputSchema: z.object({ - ids: z.array(z.number()).describe("分镜面板中需要更新的分镜 ID 列表,传入id仅作对应分镜更新用,不传入则全部生成"), + ids: z.array(z.number()).describe("必须获取真实的分镜ID,支持批量生成"), }), execute: async ({ ids }) => { console.log("%c Line:176 🍒 ids", "background:#ea7e5c", ids); diff --git a/src/router.ts b/src/router.ts index 6d36176..6055df8 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,4 +1,4 @@ -// @routes-hash 01a3e214a845cf74065af521bc0794cc +// @routes-hash 8b0a09b55cd1b98ff83ad988d077fee3 import { Express } from "express"; import route1 from "./routes/agents/clearMemory"; @@ -65,65 +65,64 @@ import route61 from "./routes/production/storyboard/getStoryboardData"; import route62 from "./routes/production/storyboard/pollingImage"; import route63 from "./routes/production/storyboard/previewImage"; import route64 from "./routes/production/storyboard/removeFrame"; -import route65 from "./routes/production/storyboard/updateStoryboardInfo"; -import route66 from "./routes/production/workbench/confirmSelection"; -import route67 from "./routes/production/workbench/delVideo"; -import route68 from "./routes/production/workbench/generateVideo"; -import route69 from "./routes/production/workbench/generateVideoPrompt"; -import route70 from "./routes/production/workbench/getChatLines"; -import route71 from "./routes/production/workbench/getVideoModelDetail"; -import route72 from "./routes/production/workbench/videoPolling"; -import route73 from "./routes/project/addProject"; -import route74 from "./routes/project/addVisual"; -import route75 from "./routes/project/addVisualManual"; -import route76 from "./routes/project/deleteVisualManual"; -import route77 from "./routes/project/delProject"; -import route78 from "./routes/project/editProject"; -import route79 from "./routes/project/editVisualManual"; -import route80 from "./routes/project/getProject"; -import route81 from "./routes/project/getVisualManual"; -import route82 from "./routes/project/visualManual"; -import route83 from "./routes/script/addScript"; -import route84 from "./routes/script/delScript"; -import route85 from "./routes/script/exportScript"; -import route86 from "./routes/script/extractAssets"; -import route87 from "./routes/script/getScrptApi"; -import route88 from "./routes/script/pollScriptAssets"; -import route89 from "./routes/script/updateScript"; -import route90 from "./routes/scriptAgent/getPlanData"; -import route91 from "./routes/scriptAgent/setPlanData"; -import route92 from "./routes/scriptAgent/updateData"; -import route93 from "./routes/setting/about/checkUpdate"; -import route94 from "./routes/setting/about/downloadApp"; -import route95 from "./routes/setting/agentDeploy/agentSetKey"; -import route96 from "./routes/setting/agentDeploy/deployAgentModel"; -import route97 from "./routes/setting/agentDeploy/getAgentDeploy"; -import route98 from "./routes/setting/dbConfig/clearData"; -import route99 from "./routes/setting/dev/getSwitchAiDevTool"; -import route100 from "./routes/setting/dev/updateSwitchAiDevTool"; -import route101 from "./routes/setting/fileManagement/openFolder"; -import route102 from "./routes/setting/getTextModel"; -import route103 from "./routes/setting/loginConfig/getUser"; -import route104 from "./routes/setting/loginConfig/updateUserPwd"; -import route105 from "./routes/setting/memoryConfig/delAllMemory"; -import route106 from "./routes/setting/memoryConfig/getMemory"; -import route107 from "./routes/setting/memoryConfig/sureMemory"; -import route108 from "./routes/setting/promptManage/getPrompt"; -import route109 from "./routes/setting/promptManage/updatePrompt"; -import route110 from "./routes/setting/skillManagement/getSkillContent"; -import route111 from "./routes/setting/skillManagement/getSkillList"; -import route112 from "./routes/setting/skillManagement/saveSkillContent"; -import route113 from "./routes/setting/vendorConfig/addVendor"; -import route114 from "./routes/setting/vendorConfig/deleteVendor"; -import route115 from "./routes/setting/vendorConfig/getVendorList"; -import route116 from "./routes/setting/vendorConfig/modelTest"; -import route117 from "./routes/setting/vendorConfig/updateCode"; -import route118 from "./routes/setting/vendorConfig/updateVendor"; -import route119 from "./routes/task/getProject"; -import route120 from "./routes/task/getTaskApi"; -import route121 from "./routes/task/getTaskCategories"; -import route122 from "./routes/task/taskDetails"; -import route123 from "./routes/test/test"; +import route65 from "./routes/production/workbench/confirmSelection"; +import route66 from "./routes/production/workbench/delVideo"; +import route67 from "./routes/production/workbench/generateVideo"; +import route68 from "./routes/production/workbench/generateVideoPrompt"; +import route69 from "./routes/production/workbench/getChatLines"; +import route70 from "./routes/production/workbench/getVideoModelDetail"; +import route71 from "./routes/production/workbench/videoPolling"; +import route72 from "./routes/project/addProject"; +import route73 from "./routes/project/addVisual"; +import route74 from "./routes/project/addVisualManual"; +import route75 from "./routes/project/deleteVisualManual"; +import route76 from "./routes/project/delProject"; +import route77 from "./routes/project/editProject"; +import route78 from "./routes/project/editVisualManual"; +import route79 from "./routes/project/getProject"; +import route80 from "./routes/project/getVisualManual"; +import route81 from "./routes/project/visualManual"; +import route82 from "./routes/script/addScript"; +import route83 from "./routes/script/delScript"; +import route84 from "./routes/script/exportScript"; +import route85 from "./routes/script/extractAssets"; +import route86 from "./routes/script/getScrptApi"; +import route87 from "./routes/script/pollScriptAssets"; +import route88 from "./routes/script/updateScript"; +import route89 from "./routes/scriptAgent/getPlanData"; +import route90 from "./routes/scriptAgent/setPlanData"; +import route91 from "./routes/scriptAgent/updateData"; +import route92 from "./routes/setting/about/checkUpdate"; +import route93 from "./routes/setting/about/downloadApp"; +import route94 from "./routes/setting/agentDeploy/agentSetKey"; +import route95 from "./routes/setting/agentDeploy/deployAgentModel"; +import route96 from "./routes/setting/agentDeploy/getAgentDeploy"; +import route97 from "./routes/setting/dbConfig/clearData"; +import route98 from "./routes/setting/dev/getSwitchAiDevTool"; +import route99 from "./routes/setting/dev/updateSwitchAiDevTool"; +import route100 from "./routes/setting/fileManagement/openFolder"; +import route101 from "./routes/setting/getTextModel"; +import route102 from "./routes/setting/loginConfig/getUser"; +import route103 from "./routes/setting/loginConfig/updateUserPwd"; +import route104 from "./routes/setting/memoryConfig/delAllMemory"; +import route105 from "./routes/setting/memoryConfig/getMemory"; +import route106 from "./routes/setting/memoryConfig/sureMemory"; +import route107 from "./routes/setting/promptManage/getPrompt"; +import route108 from "./routes/setting/promptManage/updatePrompt"; +import route109 from "./routes/setting/skillManagement/getSkillContent"; +import route110 from "./routes/setting/skillManagement/getSkillList"; +import route111 from "./routes/setting/skillManagement/saveSkillContent"; +import route112 from "./routes/setting/vendorConfig/addVendor"; +import route113 from "./routes/setting/vendorConfig/deleteVendor"; +import route114 from "./routes/setting/vendorConfig/getVendorList"; +import route115 from "./routes/setting/vendorConfig/modelTest"; +import route116 from "./routes/setting/vendorConfig/updateCode"; +import route117 from "./routes/setting/vendorConfig/updateVendor"; +import route118 from "./routes/task/getProject"; +import route119 from "./routes/task/getTaskApi"; +import route120 from "./routes/task/getTaskCategories"; +import route121 from "./routes/task/taskDetails"; +import route122 from "./routes/test/test"; export default async (app: Express) => { app.use("/api/agents/clearMemory", route1); @@ -190,63 +189,62 @@ export default async (app: Express) => { app.use("/api/production/storyboard/pollingImage", route62); app.use("/api/production/storyboard/previewImage", route63); app.use("/api/production/storyboard/removeFrame", route64); - app.use("/api/production/storyboard/updateStoryboardInfo", route65); - app.use("/api/production/workbench/confirmSelection", route66); - app.use("/api/production/workbench/delVideo", route67); - app.use("/api/production/workbench/generateVideo", route68); - app.use("/api/production/workbench/generateVideoPrompt", route69); - app.use("/api/production/workbench/getChatLines", route70); - app.use("/api/production/workbench/getVideoModelDetail", route71); - app.use("/api/production/workbench/videoPolling", route72); - app.use("/api/project/addProject", route73); - app.use("/api/project/addVisual", route74); - app.use("/api/project/addVisualManual", route75); - app.use("/api/project/deleteVisualManual", route76); - app.use("/api/project/delProject", route77); - app.use("/api/project/editProject", route78); - app.use("/api/project/editVisualManual", route79); - app.use("/api/project/getProject", route80); - app.use("/api/project/getVisualManual", route81); - app.use("/api/project/visualManual", route82); - app.use("/api/script/addScript", route83); - app.use("/api/script/delScript", route84); - app.use("/api/script/exportScript", route85); - app.use("/api/script/extractAssets", route86); - app.use("/api/script/getScrptApi", route87); - app.use("/api/script/pollScriptAssets", route88); - app.use("/api/script/updateScript", route89); - app.use("/api/scriptAgent/getPlanData", route90); - app.use("/api/scriptAgent/setPlanData", route91); - app.use("/api/scriptAgent/updateData", route92); - app.use("/api/setting/about/checkUpdate", route93); - app.use("/api/setting/about/downloadApp", route94); - app.use("/api/setting/agentDeploy/agentSetKey", route95); - app.use("/api/setting/agentDeploy/deployAgentModel", route96); - app.use("/api/setting/agentDeploy/getAgentDeploy", route97); - app.use("/api/setting/dbConfig/clearData", route98); - app.use("/api/setting/dev/getSwitchAiDevTool", route99); - app.use("/api/setting/dev/updateSwitchAiDevTool", route100); - app.use("/api/setting/fileManagement/openFolder", route101); - app.use("/api/setting/getTextModel", route102); - app.use("/api/setting/loginConfig/getUser", route103); - app.use("/api/setting/loginConfig/updateUserPwd", route104); - app.use("/api/setting/memoryConfig/delAllMemory", route105); - app.use("/api/setting/memoryConfig/getMemory", route106); - app.use("/api/setting/memoryConfig/sureMemory", route107); - app.use("/api/setting/promptManage/getPrompt", route108); - app.use("/api/setting/promptManage/updatePrompt", route109); - app.use("/api/setting/skillManagement/getSkillContent", route110); - app.use("/api/setting/skillManagement/getSkillList", route111); - app.use("/api/setting/skillManagement/saveSkillContent", route112); - app.use("/api/setting/vendorConfig/addVendor", route113); - app.use("/api/setting/vendorConfig/deleteVendor", route114); - app.use("/api/setting/vendorConfig/getVendorList", route115); - app.use("/api/setting/vendorConfig/modelTest", route116); - app.use("/api/setting/vendorConfig/updateCode", route117); - app.use("/api/setting/vendorConfig/updateVendor", route118); - app.use("/api/task/getProject", route119); - app.use("/api/task/getTaskApi", route120); - app.use("/api/task/getTaskCategories", route121); - app.use("/api/task/taskDetails", route122); - app.use("/api/test/test", route123); + app.use("/api/production/workbench/confirmSelection", route65); + app.use("/api/production/workbench/delVideo", route66); + app.use("/api/production/workbench/generateVideo", route67); + app.use("/api/production/workbench/generateVideoPrompt", route68); + app.use("/api/production/workbench/getChatLines", route69); + app.use("/api/production/workbench/getVideoModelDetail", route70); + app.use("/api/production/workbench/videoPolling", route71); + app.use("/api/project/addProject", route72); + app.use("/api/project/addVisual", route73); + app.use("/api/project/addVisualManual", route74); + app.use("/api/project/deleteVisualManual", route75); + app.use("/api/project/delProject", route76); + app.use("/api/project/editProject", route77); + app.use("/api/project/editVisualManual", route78); + app.use("/api/project/getProject", route79); + app.use("/api/project/getVisualManual", route80); + app.use("/api/project/visualManual", route81); + app.use("/api/script/addScript", route82); + app.use("/api/script/delScript", route83); + app.use("/api/script/exportScript", route84); + app.use("/api/script/extractAssets", route85); + app.use("/api/script/getScrptApi", route86); + app.use("/api/script/pollScriptAssets", route87); + app.use("/api/script/updateScript", route88); + app.use("/api/scriptAgent/getPlanData", route89); + app.use("/api/scriptAgent/setPlanData", route90); + app.use("/api/scriptAgent/updateData", route91); + app.use("/api/setting/about/checkUpdate", route92); + app.use("/api/setting/about/downloadApp", route93); + app.use("/api/setting/agentDeploy/agentSetKey", route94); + app.use("/api/setting/agentDeploy/deployAgentModel", route95); + app.use("/api/setting/agentDeploy/getAgentDeploy", route96); + app.use("/api/setting/dbConfig/clearData", route97); + app.use("/api/setting/dev/getSwitchAiDevTool", route98); + app.use("/api/setting/dev/updateSwitchAiDevTool", route99); + app.use("/api/setting/fileManagement/openFolder", route100); + app.use("/api/setting/getTextModel", route101); + app.use("/api/setting/loginConfig/getUser", route102); + app.use("/api/setting/loginConfig/updateUserPwd", route103); + app.use("/api/setting/memoryConfig/delAllMemory", route104); + app.use("/api/setting/memoryConfig/getMemory", route105); + app.use("/api/setting/memoryConfig/sureMemory", route106); + app.use("/api/setting/promptManage/getPrompt", route107); + app.use("/api/setting/promptManage/updatePrompt", route108); + app.use("/api/setting/skillManagement/getSkillContent", route109); + app.use("/api/setting/skillManagement/getSkillList", route110); + app.use("/api/setting/skillManagement/saveSkillContent", route111); + app.use("/api/setting/vendorConfig/addVendor", route112); + app.use("/api/setting/vendorConfig/deleteVendor", route113); + app.use("/api/setting/vendorConfig/getVendorList", route114); + app.use("/api/setting/vendorConfig/modelTest", route115); + app.use("/api/setting/vendorConfig/updateCode", route116); + app.use("/api/setting/vendorConfig/updateVendor", route117); + app.use("/api/task/getProject", route118); + app.use("/api/task/getTaskApi", route119); + app.use("/api/task/getTaskCategories", route120); + app.use("/api/task/taskDetails", route121); + app.use("/api/test/test", route122); } diff --git a/src/routes/production/assets/batchGenerateAssetsImage.ts b/src/routes/production/assets/batchGenerateAssetsImage.ts index 1841709..9ba69a9 100644 --- a/src/routes/production/assets/batchGenerateAssetsImage.ts +++ b/src/routes/production/assets/batchGenerateAssetsImage.ts @@ -42,47 +42,27 @@ export default router.post( const rolePrompt = u.getArtPrompt(projectSettingData!.artStyle!, "art_character_derivative"); const toolPrompt = u.getArtPrompt(projectSettingData!.artStyle!, "art_prop_derivative"); const scenePrompt = u.getArtPrompt(projectSettingData!.artStyle!, "art_scene_derivative"); - const promptRecord: Record = { + const promptRecord: Record = { role: { prompt: rolePrompt, - label: "角色衍生资产", - focus: "注重人物的姿态、表情、服饰细节、体态特征与情绪表达,保持与原始角色设计的一致性(如发型、瞳色、服装风格),同时体现衍生场景下的变化。", }, tool: { prompt: toolPrompt, - label: "道具衍生资产", - focus: - "注重道具的材质质感、光影效果、结构细节与功能特征,保持与原始道具设计的一致性(如形状、配色、标志性元素),清晰展示道具在不同状态或角度下的视觉表现。", }, scene: { prompt: scenePrompt, - label: "场景衍生资产", - focus: - "注重场景的空间层次、光影氛围、环境细节与情绪渲染,保持与原始场景设计的一致性(如建筑风格、色调、标志性地标),体现不同时间段或天气条件下的视觉变化。", }, }; const imageData = []; for (const item of assetsDataArr) { const typeConfig = promptRecord[item.type!] || promptRecord["role"]; - const hasRefImage = !!imageUrlRecord[item.assetsId!]; const { text } = await u.Ai.Text("universalAi").invoke({ - system: `你是一位专业的 AI 绘画提示词工程师,擅长将资产描述转化为高质量的图片生成提示词。 - -## 任务 -根据用户提供的${typeConfig.label}名称与描述,结合项目美术风格规范,生成一段精准的图片生成提示词(Prompt)。 - -## 输出要求 -- 直接输出最终提示词,不要包含任何解释、标题或标记 -- ${typeConfig.focus} -${hasRefImage ? "- 当前资产有参考图作为风格锚点,提示词应侧重描述衍生变化部分,避免重复参考图已有的基础特征" : "- 当前资产无参考图,提示词需要完整描述视觉特征"} - -## 项目美术风格与提示词规范参考 -${typeConfig.prompt || "(未指定特定美术风格,请根据资产描述选择合适的画面风格)"}`, + system: `${typeConfig.prompt}`, messages: [ { role: "user", - content: `资产名称: ${item.name}\n资产描述: ${item.describe || "无详细描述"}`, + content: `资产描述: ${item.describe || "无详细描述"}`, }, ], }); diff --git a/src/routes/production/storyboard/batchAddStoryboardInfo.ts b/src/routes/production/storyboard/batchAddStoryboardInfo.ts index dbcc417..64fba53 100644 --- a/src/routes/production/storyboard/batchAddStoryboardInfo.ts +++ b/src/routes/production/storyboard/batchAddStoryboardInfo.ts @@ -11,6 +11,11 @@ export default router.post( data: z.array( z.object({ prompt: z.string(), + duration: z.number(), + group: z.number(), + state: z.string(), + src: z.string().nullable(), + associateAssetsIds: z.array(z.number()), }), ), scriptId: z.number(), @@ -18,14 +23,25 @@ export default router.post( async (req, res) => { const { data, scriptId } = req.body; if (!data.length) return res.status(400).send({ success: false, message: "数据不能为空" }); - await u.db("o_storyboard").insert( - data.map((i: { prompt: string }) => ({ - ...i, + for (const item of data) { + const [id] = await u.db("o_storyboard").insert({ + prompt: item.prompt, + duration: String(item.duration), + group: String(item.group), + state: item.state, scriptId, createTime: Date.now(), - state: "未生成", - })), - ); - return res.status(200).send(success()); + }); + if (item.associateAssetsIds?.length) { + await u.db("o_assets2Storyboard").insert( + item.associateAssetsIds.map((assetId: number) => ({ + assetId, + storyboardId: id, + })), + ); + } + } + const lastStoryboard = await u.db("o_storyboard").where("scriptId", scriptId); + return res.status(200).send(success(lastStoryboard)); }, ); diff --git a/src/routes/production/storyboard/batchGenerateImage.ts b/src/routes/production/storyboard/batchGenerateImage.ts index 77da460..ceed8ae 100644 --- a/src/routes/production/storyboard/batchGenerateImage.ts +++ b/src/routes/production/storyboard/batchGenerateImage.ts @@ -2,7 +2,7 @@ import express from "express"; import u from "@/utils"; import { z } from "zod"; import sharp from "sharp"; -import { success } from "@/lib/responseFormat"; +import { error, success } from "@/lib/responseFormat"; import { validateFields } from "@/middleware/middleware"; import { Output, tool } from "ai"; import { urlToBase64 } from "@/utils/vm"; @@ -13,115 +13,27 @@ export type AssetData = z.infer; export default router.post( "/", validateFields({ - storyboardIds: z.array(z.number()).optional(), + storyboardIds: z.array(z.number()), projectId: z.number(), scriptId: z.number(), - script: z.string(), - scriptPlan: z.string(), - storyboardTable: z.string(), - assets: z.array(assetItemSchema), }), async (req, res) => { const { storyboardIds, projectId, scriptId, - script, - scriptPlan, - storyboardTable, - assets, }: { storyboardIds: number[]; projectId: number; scriptId: number; - script: string; - scriptPlan: string; - storyboardTable: string; - assets: AssetData[]; } = req.body; + if (!storyboardIds || storyboardIds.length === 0) return res.status(400).send(error("storyboardIds不能为空")); // 当没有 storyboardIds 时,通过 AI 生成新的分镜面板数据 let finalStoryboardIds: number[] = storyboardIds || []; - if (!storyboardIds || storyboardIds.length === 0) { - await u.db("o_storyboard").where("scriptId", scriptId).delete(); - const createdIds: number[] = []; - const resultTools = tool({ - description: "结果输出工具(必须调用)", - inputSchema: z.object({ - items: z.array( - z.object({ - title: z.string().describe("分镜名称"), - description: z.string().describe("分镜详细描述"), - relatedAssets: z.array(z.number()).describe("关联衍生资产id数组"), - duration: z.number().describe("用于生成的视频时长(秒)"), - }), - ), - }), - execute: async (resData) => { - console.log("%c Line:46 🌰 resData", "background:#93c0a4", resData.items); - for (const item of resData.items) { - const [id] = await u.db("o_storyboard").insert({ - title: item.title, - description: item.description, - scriptId: scriptId, - duration: String(item.duration), - }); - createdIds.push(id); - if (item.relatedAssets.length === 0) continue; - await u.db("o_assets2Storyboard").insert(item.relatedAssets.map((i) => ({ storyboardId: id, assetId: i }))); - console.log("%c Line:68 🍷 createdIds", "background:#33a5ff", createdIds); - } - return true; - }, - }); - const { text } = await u.Ai.Text("universalAi").invoke({ - system: `你是一位专业的动画分镜师。你的任务是根据剧本内容、分镜表、拍摄计划和可用资产,拆分并生成完整的分镜面板数据。 - -## 工作流程 -1. 仔细阅读剧本,理解故事情节、角色关系和情感节奏。 -2. 参照分镜表和拍摄计划,确定每个分镜的镜头语言(景别、角度、运镜方式)。 -3. 将可用资产合理分配到对应分镜中,确保每个分镜关联的资产与画面内容一致。 -4. 为每个分镜撰写详细的画面描述,包含:场景环境、角色动作与表情、镜头构图、光影氛围。 -5. 根据镜头内容合理分配视频时长(一般 2~8 秒,对话或动作复杂的场景可适当延长)。 - -## 输出要求 -- 你 **必须** 调用 resultTools 工具来输出结果,不要在回复中添加任何文字说明。 -- items 数组中每个元素包含: - - title:简洁的分镜名称(如"开场远景"、"角色对话特写") - - description:详细的分镜画面描述(至少 50 字),需包含镜头景别、角色状态、环境氛围等具体视觉信息 - - relatedAssets:该分镜关联的衍生资产 ID 数组,仅关联与画面内容直接相关的资产 - - duration:建议视频时长(秒),根据画面复杂度和叙事节奏合理分配`, - messages: [ - { - role: "user", - content: `## 剧本 -${script} - -## 分镜表 -${storyboardTable} - -## 拍摄计划 -${scriptPlan} - -## 可用资产列表 -${assets.map((i) => i.derive.map((t) => `- 衍生资产名称: ${t.name} | 类型: ${t.type} | 资产ID: ${t.assetsId}`).join("\n")).join("\n")}`, - }, - ], - tools: { resultTools }, - }); - console.log("%c Line:52 🍢 text", "background:#93c0a4", text); - finalStoryboardIds = createdIds; - } await u.db("o_storyboard").whereIn("id", finalStoryboardIds).where("scriptId", scriptId).update({ state: "生成中" }); - console.log("%c Line:98 🍯 finalStoryboardIds", "background:#3f7cff", finalStoryboardIds); - - if (finalStoryboardIds.length === 0) { - res.status(200).send(success()); - return; - } const projectSettingData = await u.db("o_project").where("id", projectId).select("imageModel", "imageQuality", "artStyle").first(); - const sceneArkPrompt = u.getArtPrompt(projectSettingData?.artStyle || "", "art_storyboard"); const storyboardData = await u.db("o_storyboard").where("scriptId", scriptId).whereIn("id", finalStoryboardIds); const assetData = await u .db("o_assets") @@ -139,9 +51,7 @@ ${assets.map((i) => i.derive.map((t) => `- 衍生资产名称: ${t.name} | 类 success( storyboardData.map((i) => ({ id: i.id, - title: i.title, - description: i.description, - prompt: "", + prompt: i.prompt, associateAssetsIds: assetRecord[i.id!], src: null, state: i.state, @@ -149,30 +59,12 @@ ${assets.map((i) => i.derive.map((t) => `- 衍生资产名称: ${t.name} | 类 ), ); for (const item of storyboardData) { - const { text } = await u.Ai.Text("universalAi").invoke({ - system: `你是一位专业的 AI 绘画提示词工程师,擅长将分镜描述转化为高质量的图片生成提示词。 - -## 任务 -根据分镜的标题与描述,结合项目美术风格要求,生成一段精准的英文图片生成提示词(Prompt)。 - -## 项目美术风格与提示词规范参考 -${sceneArkPrompt || "(未指定特定美术风格,请根据分镜内容选择合适的画面风格)"}`, - messages: [ - { - role: "user", - content: `分镜标题: ${item.title}\n分镜描述: ${item.description}`, - }, - ], - }); - console.log("%c Line:27 🍫 text", "background:#ffdd4d", text); - const repeloadObj = { - prompt: text, + prompt: item.prompt!, size: projectSettingData?.imageQuality as "1K" | "2K" | "4K", aspectRatio: "16:9" as `${number}:${number}`, }; await u.db("o_storyboard").where("id", item.id).update({ - prompt: text, state: "生成中", }); u.Ai.Image(projectSettingData?.imageModel as `${string}:${string}`) diff --git a/src/routes/production/storyboard/updateStoryboardInfo.ts b/src/routes/production/storyboard/updateStoryboardInfo.ts deleted file mode 100644 index 4640c62..0000000 --- a/src/routes/production/storyboard/updateStoryboardInfo.ts +++ /dev/null @@ -1,22 +0,0 @@ -import express from "express"; -import u from "@/utils"; -import { z } from "zod"; -import { success } from "@/lib/responseFormat"; -import { validateFields } from "@/middleware/middleware"; -import { id } from "zod/locales"; -const router = express.Router(); - -export default router.post( - "/", - validateFields({ - id: z.number(), - prompt: z.string(), - }), - async (req, res) => { - const { id, prompt } = req.body; - await u.db("o_storyboard").where({ id }).update({ - prompt, - }); - res.status(200).send(success({ message: "更新提示词成功" })); - }, -); diff --git a/src/routes/script/extractAssets.ts b/src/routes/script/extractAssets.ts index 8aa7d4d..09e0fa5 100644 --- a/src/routes/script/extractAssets.ts +++ b/src/routes/script/extractAssets.ts @@ -11,7 +11,6 @@ const router = express.Router(); /** 新资产:AI 首次识别到的资产,需要完整信息 */ const NewAssetSchema = z.object({ - prompt: z.string().describe("生成提示词"), name: z.string().describe("资产名称,仅为名称不做其他任何表述"), desc: z.string().describe("资产描述"), type: z.enum(["role", "tool", "scene"]).describe("资产类型"), @@ -25,7 +24,6 @@ const ExistingAssetRefSchema = z.object({ }); export const AssetSchema = z.object({ - prompt: z.string().describe("生成提示词"), name: z.string().describe("资产名称,仅为名称不做其他任何表述"), desc: z.string().describe("资产描述"), type: z.enum(["role", "tool", "scene"]).describe("资产类型"), @@ -108,7 +106,6 @@ export default router.post( await u.db("o_assets").insert( toInsert.map((asset) => ({ name: asset.name, - prompt: asset.prompt, type: asset.type, describe: asset.desc, projectId: projectId, @@ -218,12 +215,11 @@ export default router.post( content: data?.data + "\n\n提取剧本中涉及的资产(角色、场景、道具),参考技能 script_assets_extract 规范,结果必须通过 resultTool 工具返回。" + - "\n\n注意:本次会同时提供多集剧本,每集剧本以 ===== 【剧本ID: xxx】 ===== 分隔。你需要分析每集剧本使用了哪些资产,并在输出中用 scriptIds 数组标明每个资产在哪些剧本中出现。" + - existingHint, + "\n\n注意:本次会同时提供多集剧本,每集剧本以 ===== 【剧本ID: xxx】 ===== 分隔。你需要分析每集剧本使用了哪些资产,并在输出中用 scriptIds 数组标明每个资产在哪些剧本中出现。", }, { role: "user", - content: `请根据以下${validScripts.length}集剧本提取对应的剧本资产(角色、场景、道具):\n\n${scriptsContent}`, + content: `当前已有资产列表:${existingHint}\n\n请根据以下${validScripts.length}集剧本提取对应的剧本资产(角色、场景、道具):\n\n${scriptsContent}`, }, ], tools: { resultTool }, diff --git a/src/types/database.d.ts b/src/types/database.d.ts index 4544078..feaaa52 100644 --- a/src/types/database.d.ts +++ b/src/types/database.d.ts @@ -1,4 +1,4 @@ -// @db-hash f7bc2fdb80756d5536929eb47155578b +// @db-hash 7c59ad1ffb7b9f9bb1a5058fb743232b //该文件由脚本自动生成,请勿手动修改 export interface _o_script_old_20260327 { @@ -8,6 +8,26 @@ export interface _o_script_old_20260327 { 'name'?: string | null; 'projectId'?: number | null; } +export interface _o_storyboard_old_20260331 { + 'camera'?: string | null; + 'createTime'?: number | null; + 'description'?: string | null; + 'duration'?: string | null; + 'filePath'?: string | null; + 'frameMode'?: string | null; + 'id'?: number; + 'index'?: string | null; + 'lines'?: string | null; + 'mode'?: string | null; + 'model'?: string | null; + 'prompt'?: string | null; + 'reason'?: string | null; + 'resolution'?: string | null; + 'scriptId'?: number | null; + 'sound'?: string | null; + 'state'?: string | null; + 'title'?: string | null; +} export interface memories { 'content': string; 'createTime': number; @@ -172,6 +192,7 @@ export interface o_storyboard { 'duration'?: string | null; 'filePath'?: string | null; 'frameMode'?: string | null; + 'group'?: string | null; 'id'?: number; 'index'?: string | null; 'lines'?: string | null; @@ -239,6 +260,7 @@ export interface o_videoConfig { export interface DB { "_o_script_old_20260327": _o_script_old_20260327; + "_o_storyboard_old_20260331": _o_storyboard_old_20260331; "memories": memories; "o_agentDeploy": o_agentDeploy; "o_agentWorkData": o_agentWorkData; From a5e8e469ca76923f31018391ecad569fee3f3110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=B8=85?= <2944435683> Date: Tue, 31 Mar 2026 16:22:58 +0800 Subject: [PATCH 3/3] no message --- src/types/database.d.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/types/database.d.ts b/src/types/database.d.ts index 2a3bc57..0aca397 100644 --- a/src/types/database.d.ts +++ b/src/types/database.d.ts @@ -1,4 +1,4 @@ -// @db-hash 93b2462070c45c2b449e9a18c4e88763 +// @db-hash 6be0a80e9c8f541987a4c1e907736237 //该文件由脚本自动生成,请勿手动修改 export interface memories { @@ -178,6 +178,7 @@ export interface o_storyboard { 'sound'?: string | null; 'state'?: string | null; 'title'?: string | null; + 'videoPrompt'?: string | null; } export interface o_tasks { 'describe'?: string | null; @@ -211,6 +212,7 @@ export interface o_video { 'errorReason'?: string | null; 'filePath'?: string | null; 'id'?: number; + 'projectId'?: number | null; 'scriptId'?: number | null; 'state'?: string | null; 'storyboardId'?: number | null;