diff --git a/src/lib/initDB.ts b/src/lib/initDB.ts index 03e12bb..f79a057 100644 --- a/src/lib/initDB.ts +++ b/src/lib/initDB.ts @@ -204,6 +204,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.integer("projectId"); table.integer("eventState"); table.text("event"); + table.text("errorReason"); table.integer("createTime"); table.primary(["id"]); table.unique(["id"]); @@ -447,6 +448,15 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.unique(["storyboardId", "assetId"]); }, }, + { + name: "o_scriptAssets", + builder: (table) => { + table.integer("scriptId").notNullable(); + table.integer("assetId").notNullable(); + table.primary(["scriptId", "assetId"]); + table.unique(["scriptId", "assetId"]); + }, + }, ]; for (const t of tables) { diff --git a/src/router.ts b/src/router.ts index 1dea5f9..15f2fc1 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,4 +1,4 @@ -// @routes-hash 0ea539b96a91286c69cc811893902704 +// @routes-hash d482a1b197a774825d3bc1c4ca8b70c5 import { Express } from "express"; import route1 from "./routes/agents/clearMemory"; @@ -49,37 +49,38 @@ import route45 from "./routes/production/saveFlowData"; import route46 from "./routes/production/workbench/confirmSelection"; import route47 from "./routes/production/workbench/delVideo"; import route48 from "./routes/production/workbench/generateVideo"; -import route49 from "./routes/production/workbench/getVideoModelDetail"; -import route50 from "./routes/production/workbench/videoPolling"; -import route51 from "./routes/project/addProject"; -import route52 from "./routes/project/delProject"; -import route53 from "./routes/project/editProject"; -import route54 from "./routes/project/getProject"; -import route55 from "./routes/script/addScript"; -import route56 from "./routes/script/delScript"; -import route57 from "./routes/script/exportScript"; -import route58 from "./routes/script/getScrptApi"; -import route59 from "./routes/script/updateScript"; -import route60 from "./routes/scriptAgent/getPlanData"; -import route61 from "./routes/scriptAgent/setPlanData"; -import route62 from "./routes/setting/agentDeploy/deployAgentModel"; -import route63 from "./routes/setting/agentDeploy/getAgentDeploy"; -import route64 from "./routes/setting/agentDeploy/updateKey"; -import route65 from "./routes/setting/dbConfig/clearData"; -import route66 from "./routes/setting/getTextModel"; -import route67 from "./routes/setting/loginConfig/getUser"; -import route68 from "./routes/setting/loginConfig/updateUserPwd"; -import route69 from "./routes/setting/memoryConfig/getMemory"; -import route70 from "./routes/setting/memoryConfig/sureMemory"; -import route71 from "./routes/setting/vendorConfig/addVendor"; -import route72 from "./routes/setting/vendorConfig/deleteVendor"; -import route73 from "./routes/setting/vendorConfig/getVendorList"; -import route74 from "./routes/setting/vendorConfig/modelTest"; -import route75 from "./routes/setting/vendorConfig/updateVendor"; -import route76 from "./routes/task/getTaskApi"; -import route77 from "./routes/task/getTaskCategories"; -import route78 from "./routes/task/taskDetails"; -import route79 from "./routes/test/test"; +import route49 from "./routes/production/workbench/getChatLines"; +import route50 from "./routes/production/workbench/getVideoModelDetail"; +import route51 from "./routes/production/workbench/videoPolling"; +import route52 from "./routes/project/addProject"; +import route53 from "./routes/project/delProject"; +import route54 from "./routes/project/editProject"; +import route55 from "./routes/project/getProject"; +import route56 from "./routes/script/addScript"; +import route57 from "./routes/script/delScript"; +import route58 from "./routes/script/exportScript"; +import route59 from "./routes/script/getScrptApi"; +import route60 from "./routes/script/updateScript"; +import route61 from "./routes/scriptAgent/getPlanData"; +import route62 from "./routes/scriptAgent/setPlanData"; +import route63 from "./routes/setting/agentDeploy/deployAgentModel"; +import route64 from "./routes/setting/agentDeploy/getAgentDeploy"; +import route65 from "./routes/setting/agentDeploy/updateKey"; +import route66 from "./routes/setting/dbConfig/clearData"; +import route67 from "./routes/setting/getTextModel"; +import route68 from "./routes/setting/loginConfig/getUser"; +import route69 from "./routes/setting/loginConfig/updateUserPwd"; +import route70 from "./routes/setting/memoryConfig/getMemory"; +import route71 from "./routes/setting/memoryConfig/sureMemory"; +import route72 from "./routes/setting/vendorConfig/addVendor"; +import route73 from "./routes/setting/vendorConfig/deleteVendor"; +import route74 from "./routes/setting/vendorConfig/getVendorList"; +import route75 from "./routes/setting/vendorConfig/modelTest"; +import route76 from "./routes/setting/vendorConfig/updateVendor"; +import route77 from "./routes/task/getTaskApi"; +import route78 from "./routes/task/getTaskCategories"; +import route79 from "./routes/task/taskDetails"; +import route80 from "./routes/test/test"; export default async (app: Express) => { app.use("/api/agents/clearMemory", route1); @@ -130,35 +131,36 @@ export default async (app: Express) => { app.use("/api/production/workbench/confirmSelection", route46); app.use("/api/production/workbench/delVideo", route47); app.use("/api/production/workbench/generateVideo", route48); - app.use("/api/production/workbench/getVideoModelDetail", route49); - app.use("/api/production/workbench/videoPolling", route50); - app.use("/api/project/addProject", route51); - app.use("/api/project/delProject", route52); - app.use("/api/project/editProject", route53); - app.use("/api/project/getProject", route54); - app.use("/api/script/addScript", route55); - app.use("/api/script/delScript", route56); - app.use("/api/script/exportScript", route57); - app.use("/api/script/getScrptApi", route58); - app.use("/api/script/updateScript", route59); - app.use("/api/scriptAgent/getPlanData", route60); - app.use("/api/scriptAgent/setPlanData", route61); - app.use("/api/setting/agentDeploy/deployAgentModel", route62); - app.use("/api/setting/agentDeploy/getAgentDeploy", route63); - app.use("/api/setting/agentDeploy/updateKey", route64); - app.use("/api/setting/dbConfig/clearData", route65); - app.use("/api/setting/getTextModel", route66); - app.use("/api/setting/loginConfig/getUser", route67); - app.use("/api/setting/loginConfig/updateUserPwd", route68); - app.use("/api/setting/memoryConfig/getMemory", route69); - app.use("/api/setting/memoryConfig/sureMemory", route70); - app.use("/api/setting/vendorConfig/addVendor", route71); - app.use("/api/setting/vendorConfig/deleteVendor", route72); - app.use("/api/setting/vendorConfig/getVendorList", route73); - app.use("/api/setting/vendorConfig/modelTest", route74); - app.use("/api/setting/vendorConfig/updateVendor", route75); - app.use("/api/task/getTaskApi", route76); - app.use("/api/task/getTaskCategories", route77); - app.use("/api/task/taskDetails", route78); - app.use("/api/test/test", route79); + app.use("/api/production/workbench/getChatLines", route49); + app.use("/api/production/workbench/getVideoModelDetail", route50); + app.use("/api/production/workbench/videoPolling", route51); + app.use("/api/project/addProject", route52); + app.use("/api/project/delProject", route53); + app.use("/api/project/editProject", route54); + app.use("/api/project/getProject", route55); + app.use("/api/script/addScript", route56); + app.use("/api/script/delScript", route57); + app.use("/api/script/exportScript", route58); + app.use("/api/script/getScrptApi", route59); + app.use("/api/script/updateScript", route60); + app.use("/api/scriptAgent/getPlanData", route61); + app.use("/api/scriptAgent/setPlanData", route62); + app.use("/api/setting/agentDeploy/deployAgentModel", route63); + app.use("/api/setting/agentDeploy/getAgentDeploy", route64); + app.use("/api/setting/agentDeploy/updateKey", route65); + app.use("/api/setting/dbConfig/clearData", route66); + app.use("/api/setting/getTextModel", route67); + app.use("/api/setting/loginConfig/getUser", route68); + app.use("/api/setting/loginConfig/updateUserPwd", route69); + app.use("/api/setting/memoryConfig/getMemory", route70); + app.use("/api/setting/memoryConfig/sureMemory", route71); + app.use("/api/setting/vendorConfig/addVendor", route72); + app.use("/api/setting/vendorConfig/deleteVendor", route73); + app.use("/api/setting/vendorConfig/getVendorList", route74); + app.use("/api/setting/vendorConfig/modelTest", route75); + app.use("/api/setting/vendorConfig/updateVendor", route76); + app.use("/api/task/getTaskApi", route77); + app.use("/api/task/getTaskCategories", route78); + app.use("/api/task/taskDetails", route79); + app.use("/api/test/test", route80); } diff --git a/src/routes/novel/addNovel.ts b/src/routes/novel/addNovel.ts index ed672de..f629679 100644 --- a/src/routes/novel/addNovel.ts +++ b/src/routes/novel/addNovel.ts @@ -40,7 +40,7 @@ export default router.post( await u .db("o_novel") .where("id", item.id) - .update({ event: item.event, eventState: item.event ? 1 : -1 }); + .update({ event: item.event, eventState: item.event ? 1 : -1, errorReason: item?.errReason ?? null }); }); novelClass.start(chapterAllList, projectId); diff --git a/src/routes/novel/event/generateEvents.ts b/src/routes/novel/event/generateEvents.ts index 1e50eee..96d10fc 100644 --- a/src/routes/novel/event/generateEvents.ts +++ b/src/routes/novel/event/generateEvents.ts @@ -26,7 +26,7 @@ export default router.post( await u .db("o_novel") .where("id", item.id) - .update({ event: item.event, eventState: item.event ? 1 : -1 }); + .update({ event: item.event, eventState: item.event ? 1 : -1, errorReason: item?.errorReason ?? null }); }); novel.start(allChapters, projectId); diff --git a/src/routes/novel/getNovel.ts b/src/routes/novel/getNovel.ts index da4ebc6..802c0b8 100644 --- a/src/routes/novel/getNovel.ts +++ b/src/routes/novel/getNovel.ts @@ -20,7 +20,7 @@ export default router.post( const data = await u .db("o_novel") .where("projectId", projectId) - .select("id", "chapterIndex as index", "reel", "chapter", "chapterData", "event", "eventState") + .select("id", "chapterIndex as index", "reel", "chapter", "chapterData", "event", "eventState", "errorReason") .andWhere((qb) => { if (search) { qb.where("chapter", "like", `%${search}%`); diff --git a/src/routes/production/workbench/getChatLines.ts b/src/routes/production/workbench/getChatLines.ts new file mode 100644 index 0000000..3e2b98a --- /dev/null +++ b/src/routes/production/workbench/getChatLines.ts @@ -0,0 +1,49 @@ +import express from "express"; +import u from "@/utils"; +import { z } from "zod"; +import { v4 as uuidv4 } from "uuid"; +import { success } from "@/lib/responseFormat"; +import { validateFields } from "@/middleware/middleware"; +import { Output } from "ai"; +const router = express.Router(); + +export default router.post("/", validateFields({}), async (req, res) => { + const {} = req.body; +}); + +async function getLines() { + const resText = await u.Ai.Text("eventExtractAgent").invoke({ + messages: [ + { + role: "system", + content: ` +你是一个专业的文本分析助手,请从以下文本中提取所有台词(对话内容)。 +## 提取规则: +1. 提取所有人物说话的内容,包括: + - 引号内的对话("..."、'...'、「...」、『...』) + - 旁白式独白 +2. 忽略说话者、叙述性文字、动作描写 +3. 保留台词的原始语气和标点 +4. 忽略非对话的叙述性文字 +5. 直接以 JSON 数组格式输出,不要任何额外说明 +示例输出格式: +["台词1", "台词2", "台词3"] + `, + }, + { + role: "user", + content: ` + + `, + }, + ], + output: Output.array({ + element: z.object({ + lines: z.string().describe("台词内容"), + }), + }), + }); + const parseLines = JSON.parse(resText.text); + const chatLines = parseLines.elements.map((i) => i.lines); + return chatLines; +} diff --git a/src/routes/script/addScript.ts b/src/routes/script/addScript.ts index a3ef01d..de7977d 100644 --- a/src/routes/script/addScript.ts +++ b/src/routes/script/addScript.ts @@ -7,20 +7,35 @@ const router = express.Router(); // 新增剧本 export default router.post( - "/", - validateFields({ - name: z.string(), - content: z.string(), - projectId: z.number(), - }), - async (req, res) => { - const { name, content, projectId } = req.body; - await u.db("o_script").insert({ - name, - content, - projectId, - createTime: Date.now(), + "/", + validateFields({ + name: z.string(), + content: z.string(), + projectId: z.number(), + assets: z.array(z.number()), + }), + async (req, res) => { + const { name, content, projectId, assets } = req.body; + const [scriptId] = await u.db("o_script").insert({ + name, + content, + projectId, + createTime: Date.now(), + }); + if (assets.length) { + const assetsData = await u.db("o_assets").whereIn("id", assets).select(); + if (assetsData.length) { + const assetsIds = assetsData.map((item) => item.id); + const insertData = assetsIds.map((i) => { + return { + scriptId, + assetId: i, + }; }); - res.status(200).send(success({ message: "添加剧本成功" })); - }, + await u.db("o_scriptAssets").insert(insertData); + } + } + + res.status(200).send(success({ message: "添加剧本成功" })); + }, ); diff --git a/src/routes/script/getScrptApi.ts b/src/routes/script/getScrptApi.ts index 75d169b..86dca99 100644 --- a/src/routes/script/getScrptApi.ts +++ b/src/routes/script/getScrptApi.ts @@ -6,18 +6,43 @@ import { validateFields } from "@/middleware/middleware"; const router = express.Router(); export default router.post( - "/", - validateFields({ - projectId: z.number(), - name: z.string().optional(), - }), - async (req, res) => { - const { projectId, name } = req.body; - let query = u.db("o_script").where("projectId", projectId).select("*"); - if (name) { - query = query.andWhere("name", "like", `%${name}%`); - } - const data = await query; - res.status(200).send(success(data)); - }, + "/", + validateFields({ + projectId: z.number(), + name: z.string().optional(), + }), + async (req, res) => { + const { projectId, name } = req.body; + let query = u.db("o_script").where("projectId", projectId).select("*"); + if (name) { + query = query.andWhere("name", "like", `%${name}%`); + } + + const data = await query; + const assetsData = await u + .db("o_assets") + .leftJoin("o_scriptAssets", "o_assets.id", "o_scriptAssets.assetId") + .whereIn( + "o_scriptAssets.scriptId", + data.map((i) => i.id), + ) + .select("o_assets.id", "o_assets.name", "o_scriptAssets.scriptId"); + console.log("%c Line:23 🍷 assetsData", "background:#ffdd4d", assetsData); + const scriptAssetsMap: Record = {}; + assetsData.forEach((i) => { + if (scriptAssetsMap[i.scriptId]) { + scriptAssetsMap[i.scriptId].push({ id: i.id, name: i.name }); + } else { + scriptAssetsMap[i.scriptId] = [{ id: i.id, name: i.name }]; + } + }); + const returnData = data.map((i) => ({ + id: i.id, + name: i.name, + content: i.content, + createTime: i.createTime, + assets: scriptAssetsMap[i.id!] || [], + })); + res.status(200).send(success(returnData)); + }, ); diff --git a/src/routes/script/updateScript.ts b/src/routes/script/updateScript.ts index 2a4cbfe..02ac819 100644 --- a/src/routes/script/updateScript.ts +++ b/src/routes/script/updateScript.ts @@ -7,18 +7,33 @@ const router = express.Router(); // 编辑剧本 export default router.post( - "/", - validateFields({ - id: z.number(), - name: z.string(), - content: z.string(), - }), - async (req, res) => { - const { id, name, content } = req.body; - await u.db("o_script").where({ id }).update({ - name, - content, + "/", + validateFields({ + id: z.number(), + name: z.string(), + content: z.string(), + assets: z.array(z.number()), + }), + async (req, res) => { + const { id, name, content, assets } = req.body; + await u.db("o_script").where({ id }).update({ + name, + content, + }); + if (assets.length) { + const assetsData = await u.db("o_assets").whereIn("id", assets).select(); + await u.db("o_scriptAssets").where({ scriptId: id }).delete(); + if (assetsData.length) { + const insertData = assetsData.map((item) => { + return { + scriptId: id, + assetId: item.id, + }; }); - res.status(200).send(success({ message: "编辑剧本成功" })); - }, + await u.db("o_scriptAssets").insert(insertData); + } + } + + res.status(200).send(success({ message: "编辑剧本成功" })); + }, ); diff --git a/src/types/database.d.ts b/src/types/database.d.ts index 83d0f35..8b966b5 100644 --- a/src/types/database.d.ts +++ b/src/types/database.d.ts @@ -1,4 +1,4 @@ -// @db-hash f73a46df6ee14425a01df5c1ff88fcb2 +// @db-hash b6146b9f91d8b9853e0f6fcb41c3145b //该文件由脚本自动生成,请勿手动修改 export interface memories { @@ -123,6 +123,10 @@ export interface o_script { 'name'?: string | null; 'projectId'?: number | null; } +export interface o_scriptAssets { + 'assetId'?: number; + 'scriptId'?: number; +} export interface o_setting { 'key'?: string | null; 'value'?: string | null; @@ -215,6 +219,7 @@ export interface DB { "o_outlineNovel": o_outlineNovel; "o_project": o_project; "o_script": o_script; + "o_scriptAssets": o_scriptAssets; "o_setting": o_setting; "o_storyboard": o_storyboard; "o_storyboardFlow": o_storyboardFlow; diff --git a/src/utils/cleanNovel.ts b/src/utils/cleanNovel.ts index 913b60a..171ade2 100644 --- a/src/utils/cleanNovel.ts +++ b/src/utils/cleanNovel.ts @@ -60,7 +60,7 @@ class CleanNovel { this.emitter.emit("item", { id: novel.id, event: preData }); totalEvent.push({ id: novel.id!, event: preData }); } catch (e) { - this.emitter.emit("item", { id: novel.id, event: null }); + this.emitter.emit("item", { id: novel.id, event: null, errorReason: u.error(e).message }); } } } catch (e) {