Merge branch 'develop' of https://github.com/HBAI-Ltd/Toonflow-app into develop

This commit is contained in:
小帅 2026-04-04 18:35:07 +08:00
commit 78c869805f
2 changed files with 108 additions and 106 deletions

View File

@ -111,6 +111,7 @@ export default router.post(
.db("o_storyboard")
.where("id", item.id)
.update({
filePath: "",
reason: u.error(e).message,
state: "生成失败",
});

View File

@ -41,12 +41,16 @@ type GroupResult = {
} | null;
/** 将 scriptIds 数组按 groupSize 分组 */
function chunkArray<T>(arr: T[], groupSize: number): T[][] {
const chunks: T[][] = [];
for (let i = 0; i < arr.length; i += groupSize) {
chunks.push(arr.slice(i, i + groupSize));
function chunkArray(arr: number[], groupSize: number): number[][][] {
const chunks: number[][] = [];
for (let i = 0; i < arr.length; i += 5) {
chunks.push(arr.slice(i, i + 5));
}
return chunks;
const groupChunks = [];
for (let i = 0; i < chunks.length; i += groupSize) {
groupChunks.push(chunks.slice(i, i + groupSize));
}
return groupChunks;
}
export default router.post(
@ -60,8 +64,10 @@ export default router.post(
const { scriptIds, projectId, groupSize = 5 } = req.body;
if (!scriptIds.length) return res.status(400).send(error("请先选择剧本"));
console.log("%c Line:67 🍪 scriptIds", "background:#e41a6a", scriptIds);
const scripts = await u.db("o_script").whereIn("id", scriptIds);
// 构建 scriptId -> script 内容的映射
const scriptMap = new Map(scripts.map((s: o_script) => [s.id, s]));
@ -73,7 +79,8 @@ export default router.post(
let successCount = 0;
// 将 scriptIds 按 groupSize默认5分组每组一起发给 AI
const scriptGroups = chunkArray(scriptIds, groupSize);
const scriptGroups = chunkArray(scriptIds as number[], groupSize);
console.log("%c Line:83 🍿 scriptGroups", "background:#f5ce50", scriptGroups);
/** 一组剧本提取完成后统一入库并建立关联 */
async function persistGroupResult(result: GroupResult) {
@ -139,11 +146,12 @@ export default router.post(
});
}
res.send(success("开始提取资产"));
// 逐组处理(每组最多 groupSize 集剧本一起发给 AI
for (const group of scriptGroups) {
// 过滤有效剧本
function processGroup(group: number[][][]) {
group.map(async (itemIds) => {
const validScripts: { id: number; script: o_script }[] = [];
for (const scriptId of group as number[]) {
for (const scriptIds of itemIds as number[][]) {
for (const scriptId of scriptIds) {
const script = scriptMap.get(scriptId);
if (!script) {
errors.push({ scriptId, error: "未找到对应剧本" });
@ -156,7 +164,10 @@ export default router.post(
}
}
}
if (!validScripts.length) continue;
}
console.log("%c Line:161 🥕 validScripts", "background:#42b983", validScripts);
if (!validScripts.length) return;
const validScriptIds = validScripts.map((v) => v.id);
// 修改状态为正在提取中
await u.db("o_script").whereIn("id", validScriptIds).update({
@ -171,10 +182,9 @@ export default router.post(
.map(({ id, script }) => `===== 【剧本ID: ${id}${script.name || ""} =====\n${script.content}`)
.join("\n\n");
// 用闭包收集 AI 返回的资产
let collectedNew: NewAsset[] = [];
let collectedExisting: ExistingAssetRef[] = [];
try {
const resultTool = tool({
description: "返回结果时必须调用这个工具",
inputSchema: z.object({
@ -192,13 +202,10 @@ export default router.post(
return "无需回复用户任何内容";
},
});
try {
const data = await u.db("o_prompt").where("type", "scriptAssetExtraction").first("data");
const existingHint = existingAssetsList
? `\n\n【已有资产列表】${existingAssetsList}\n对于已有资产如果在剧本中出现只需在 existingAssetRefs 中给出资产名称和对应的 scriptIds 数组即可,无需重复生成 desc/type。对于新发现的资产不在已有列表中请在 newAssets 中给出完整信息。`
: "";
const output = await u.Ai.Text("universalAi").invoke({
messages: [
{
@ -215,11 +222,13 @@ export default router.post(
],
tools: { resultTool },
});
console.log("%c Line:extractAssets 🍧 output", "background:#f5ce50", output.text);
} catch (e: any) {
const msg = e?.message || String(e);
const scriptNames = validScripts.map((v) => v.script.name).join(", ");
console.error(`[extractAssets] group=[${validScriptIds.join(",")}] 提取失败:`, msg);
await persistGroupResult({
batchScriptIds: validScriptIds,
newAssets: collectedNew,
existingRefs: collectedExisting,
});
} catch (e) {
console.error(`[extractAssets] group=[${validScriptIds.join(",")}] 提取失败:`, e);
for (const { id, script } of validScripts) {
errors.push({ scriptId: id, error: (script.name || "") + ":" + u.error(e).message });
await u
@ -227,25 +236,17 @@ export default router.post(
.where("id", id)
.update({ extractState: -1, errorReason: u.error(e).message });
}
continue;
return;
}
if (!collectedNew.length && !collectedExisting.length) {
for (const { id } of validScripts) {
errors.push({ scriptId: id, error: "AI 未返回任何资产" });
await u.db("o_script").where("id", id).update({ extractState: -1, errorReason: "AI 未返回任何资产" });
}
continue;
return;
}
successCount += validScripts.length;
// 入库
await persistGroupResult({
batchScriptIds: validScriptIds,
newAssets: collectedNew,
existingRefs: collectedExisting,
});
}
processGroup(scriptGroups);
},
);