2026-03-26 11:34:56 +08:00

211 lines
7.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import express from "express";
import u from "@/utils";
import { z } from "zod";
import { success, error } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware";
const router = express.Router();
import { FlowData } from "@/agents/productionAgent/tools";
export default router.post(
"/",
validateFields({
projectId: z.number(),
episodesId: z.number(),
}),
async (req, res) => {
const { projectId, episodesId }: { projectId: number; episodesId: number } = req.body;
const sqlData = await u
.db("o_agentWorkData")
.where("projectId", String(projectId))
.andWhere("episodesId", String(episodesId))
.select("data")
.first();
const scriptData = await u.db("o_script").where("projectId", projectId).where("id", episodesId).first();
const scriptAssets = await u.db("o_scriptAssets").where("scriptId", episodesId);
const assetIds = scriptAssets.map((i) => i.assetId);
const assetsData = await u
.db("o_assets")
.leftJoin("o_image", "o_assets.imageId", "o_image.id")
.select("o_assets.*", "o_image.filePath")
// @ts-ignore
.where("o_assets.id", "in", assetIds)
.whereNull("o_assets.assetsId")
.where("o_assets.projectId", projectId);
let childAssetsData = await u
.db("o_assets")
.leftJoin("o_image", "o_assets.imageId", "o_image.id")
.select("o_assets.*", "o_image.filePath")
.where("o_assets.projectId", projectId)
// @ts-ignore
.where("o_assets.id", "in", assetIds)
.whereNotNull("o_assets.assetsId");
if (!sqlData) {
const flowData: FlowData = {
script: scriptData?.content ?? "",
scriptPlan: "",
assets: await Promise.all(
assetsData.map(async (item) => ({
id: item.id,
name: item.name ?? "",
type: item.type ?? "",
prompt: item.prompt ?? "",
desc: item.describe ?? "",
src: item.filePath && (await u.oss.getFileUrl(item.filePath!)),
derive: await Promise.all(
childAssetsData
.filter((child) => child.assetsId === item.id)
.map(async (child) => ({
id: child.id,
assetsId: item.id,
name: child.name ?? "",
type: child.type,
prompt: child.prompt,
desc: child.describe ?? "",
src: child.filePath && (await u.oss.getFileUrl(child.filePath!)),
state: child.state ?? "未生成", //todo矫正状态值
})),
),
})),
),
storyboardTable: "",
storyboard: [],
//todo矫正workbench数据
workbench: {
name: scriptData?.name ?? "",
duration: "01:03",
resolution: "1920×1080",
fps: "30fps",
gradient: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
},
//todo矫正封面数据
poster: {
items: [],
},
};
return res.status(200).send(success(flowData));
} else {
try {
const storyboardData = await u.db("o_storyboard").where("scriptId", episodesId);
console.log("%c Line:90 🍡 storyboardData", "background:#ed9ec7", storyboardData.length);
await Promise.all(
storyboardData.map(async (i) => {
if (i.filePath) {
try {
i.filePath = await u.oss.getFileUrl(i.filePath);
} catch {
i.filePath = "";
}
} else {
i.filePath = "";
}
}),
);
const storyboardIds = storyboardData.map((i) => i.id);
const assetsIds = await u.db("o_assets2Storyboard").whereIn("storyboardId", storyboardIds);
const assets2StoryboardMap: Record<number, number[]> = {};
assetsIds.forEach((i) => {
if (!assets2StoryboardMap[i.storyboardId!]) {
assets2StoryboardMap[i.storyboardId!] = [];
}
assets2StoryboardMap[i.storyboardId!].push(i.assetId!);
});
const flowData = JSON.parse(sqlData!.data ?? "{}");
// 将原有 flowData.assets 按 id 建立索引,以便后续合并保留旧字段
const existingAssetsMap: Record<number, any> = {};
if (Array.isArray(flowData.assets)) {
flowData.assets.forEach((a: any) => {
existingAssetsMap[a.id] = a;
});
}
flowData.assets = await Promise.all(
assetsData.map(async (item) => {
const existing = existingAssetsMap[item.id] ?? {};
// 将原有 derive 按 id 建立索引
const existingDeriveMap: Record<number, any> = {};
if (Array.isArray(existing.derive)) {
existing.derive.forEach((d: any) => {
existingDeriveMap[d.id] = d;
});
}
return {
...existing,
id: item.id,
name: item.name ?? "",
type: item.type ?? "",
prompt: item.prompt ?? "",
desc: item.describe ?? "",
src: item.filePath && (await u.oss.getFileUrl(item.filePath!)),
derive: await Promise.all(
childAssetsData
.filter((child) => child.assetsId === item.id)
.map(async (child) => ({
...(existingDeriveMap[child.id] ?? {}),
id: child.id,
assetsId: item.id,
name: child.name ?? "",
prompt: child.prompt,
type: child.type,
desc: child.describe ?? "",
src: child.filePath && (await u.oss.getFileUrl(child.filePath!)),
state: child.state ?? "未生成", //todo矫正状态值
})),
),
};
}),
);
// 将数据库 storyboardData 按 id 建立索引
const dbStoryboardMap: Record<number, (typeof storyboardData)[number]> = {};
storyboardData.forEach((i) => {
dbStoryboardMap[i.id!] = i;
});
// 用于构造单条 storyboard 的辅助函数
const buildStoryboardItem = (i: (typeof storyboardData)[number], existing: any = {}) => ({
...existing,
id: i.id,
title: i.title,
description: i.description,
camera: i.camera,
duration: i.duration ? +i.duration : 0,
frameMode: i.frameMode,
prompt: i.prompt,
lines: i.lines,
sound: i.sound,
associateAssetsIds: assets2StoryboardMap[i.id!] ?? [],
src: i.filePath,
state: i.state,
});
// 保持旧数据顺序,新增的追加到最后
const usedIds = new Set<number>();
const orderedStoryboard: any[] = [];
// 1. 按旧数据顺序遍历,若数据库中仍存在则合并更新
if (Array.isArray(flowData.storyboard)) {
flowData.storyboard.forEach((s: any) => {
const dbItem = dbStoryboardMap[s.id];
if (dbItem) {
orderedStoryboard.push(buildStoryboardItem(dbItem, s));
usedIds.add(s.id);
}
});
}
// 2. 数据库中新增的(旧数据中没有的)追加到最后
storyboardData.forEach((i) => {
if (!usedIds.has(i.id!)) {
orderedStoryboard.push(buildStoryboardItem(i));
}
});
flowData.storyboard = orderedStoryboard;
res.status(200).send(success(flowData));
} catch (err) {
res.status(400).send(error());
}
}
},
);