完善数据库管理

This commit is contained in:
ACT丶流星雨 2026-04-13 18:27:27 +08:00
parent 7113e2c2eb
commit 6d0f0cc838
12 changed files with 1374 additions and 1337 deletions

View File

@ -1 +1 @@
1.1.5-dev 1.1.5

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{ {
"name": "toonflow", "name": "toonflow",
"version": "1.1.5-dev", "version": "1.1.5",
"description": "Toonflow 是一款 AI 短剧漫剧工具,能够利用 AI 技术将小说自动转化为剧本,并结合 AI 生成的图片和视频,实现高效的短剧创作。", "description": "Toonflow 是一款 AI 短剧漫剧工具,能够利用 AI 技术将小说自动转化为剧本,并结合 AI 生成的图片和视频,实现高效的短剧创作。",
"author": "HBAI-Ltd <ltlctools@outlook.com>", "author": "HBAI-Ltd <ltlctools@outlook.com>",
"license": "Apache-2.0", "license": "Apache-2.0",

View File

@ -1,4 +1,4 @@
// @routes-hash 0eb42cb2928b13229e60a26b83f977a9 // @routes-hash c02f29c05205a2e88fe50767bb47c392
import { Express } from "express"; import { Express } from "express";
import route1 from "./routes/agents/clearMemory"; import route1 from "./routes/agents/clearMemory";
@ -116,38 +116,42 @@ import route112 from "./routes/setting/agentDeploy/agentSetKey";
import route113 from "./routes/setting/agentDeploy/deployAgentModel"; import route113 from "./routes/setting/agentDeploy/deployAgentModel";
import route114 from "./routes/setting/agentDeploy/getAgentDeploy"; import route114 from "./routes/setting/agentDeploy/getAgentDeploy";
import route115 from "./routes/setting/dbConfig/clearData"; import route115 from "./routes/setting/dbConfig/clearData";
import route116 from "./routes/setting/dev/getSwitchAiDevTool"; import route116 from "./routes/setting/dbConfig/clearTable";
import route117 from "./routes/setting/dev/updateSwitchAiDevTool"; import route117 from "./routes/setting/dbConfig/dbInfo";
import route118 from "./routes/setting/fileManagement/openFolder"; import route118 from "./routes/setting/dbConfig/exportData";
import route119 from "./routes/setting/getTextModel"; import route119 from "./routes/setting/dbConfig/importData";
import route120 from "./routes/setting/loginConfig/getUser"; import route120 from "./routes/setting/dev/getSwitchAiDevTool";
import route121 from "./routes/setting/loginConfig/updateUserPwd"; import route121 from "./routes/setting/dev/updateSwitchAiDevTool";
import route122 from "./routes/setting/memoryConfig/delAllMemory"; import route122 from "./routes/setting/fileManagement/openFolder";
import route123 from "./routes/setting/memoryConfig/getMemory"; import route123 from "./routes/setting/getTextModel";
import route124 from "./routes/setting/memoryConfig/sureMemory"; import route124 from "./routes/setting/loginConfig/getUser";
import route125 from "./routes/setting/modelMap/bindingPrompt"; import route125 from "./routes/setting/loginConfig/updateUserPwd";
import route126 from "./routes/setting/modelMap/getImageAndVideoModel"; import route126 from "./routes/setting/memoryConfig/delAllMemory";
import route127 from "./routes/setting/promptManage/getPrompt"; import route127 from "./routes/setting/memoryConfig/getMemory";
import route128 from "./routes/setting/promptManage/updatePrompt"; import route128 from "./routes/setting/memoryConfig/sureMemory";
import route129 from "./routes/setting/skillManagement/getSkillContent"; import route129 from "./routes/setting/modelMap/bindingPrompt";
import route130 from "./routes/setting/skillManagement/getSkillList"; import route130 from "./routes/setting/modelMap/getImageAndVideoModel";
import route131 from "./routes/setting/skillManagement/saveSkillContent"; import route131 from "./routes/setting/promptManage/getPrompt";
import route132 from "./routes/setting/vendorConfig/addVendor"; import route132 from "./routes/setting/promptManage/updatePrompt";
import route133 from "./routes/setting/vendorConfig/addVendorModel"; import route133 from "./routes/setting/skillManagement/getSkillContent";
import route134 from "./routes/setting/vendorConfig/deleteVendor"; import route134 from "./routes/setting/skillManagement/getSkillList";
import route135 from "./routes/setting/vendorConfig/delVendorModel"; import route135 from "./routes/setting/skillManagement/saveSkillContent";
import route136 from "./routes/setting/vendorConfig/enableVendor"; import route136 from "./routes/setting/vendorConfig/addVendor";
import route137 from "./routes/setting/vendorConfig/getCodeByLink"; import route137 from "./routes/setting/vendorConfig/addVendorModel";
import route138 from "./routes/setting/vendorConfig/getVendorList"; import route138 from "./routes/setting/vendorConfig/deleteVendor";
import route139 from "./routes/setting/vendorConfig/modelTest"; import route139 from "./routes/setting/vendorConfig/delVendorModel";
import route140 from "./routes/setting/vendorConfig/updateCode"; import route140 from "./routes/setting/vendorConfig/enableVendor";
import route141 from "./routes/setting/vendorConfig/updateVendorInputs"; import route141 from "./routes/setting/vendorConfig/getCodeByLink";
import route142 from "./routes/setting/vendorConfig/upVendorModel"; import route142 from "./routes/setting/vendorConfig/getVendorList";
import route143 from "./routes/task/getProject"; import route143 from "./routes/setting/vendorConfig/modelTest";
import route144 from "./routes/task/getTaskApi"; import route144 from "./routes/setting/vendorConfig/updateCode";
import route145 from "./routes/task/getTaskCategories"; import route145 from "./routes/setting/vendorConfig/updateVendorInputs";
import route146 from "./routes/task/taskDetails"; import route146 from "./routes/setting/vendorConfig/upVendorModel";
import route147 from "./routes/test/test"; import route147 from "./routes/task/getProject";
import route148 from "./routes/task/getTaskApi";
import route149 from "./routes/task/getTaskCategories";
import route150 from "./routes/task/taskDetails";
import route151 from "./routes/test/test";
export default async (app: Express) => { export default async (app: Express) => {
app.use("/api/agents/clearMemory", route1); app.use("/api/agents/clearMemory", route1);
@ -265,36 +269,40 @@ export default async (app: Express) => {
app.use("/api/setting/agentDeploy/deployAgentModel", route113); app.use("/api/setting/agentDeploy/deployAgentModel", route113);
app.use("/api/setting/agentDeploy/getAgentDeploy", route114); app.use("/api/setting/agentDeploy/getAgentDeploy", route114);
app.use("/api/setting/dbConfig/clearData", route115); app.use("/api/setting/dbConfig/clearData", route115);
app.use("/api/setting/dev/getSwitchAiDevTool", route116); app.use("/api/setting/dbConfig/clearTable", route116);
app.use("/api/setting/dev/updateSwitchAiDevTool", route117); app.use("/api/setting/dbConfig/dbInfo", route117);
app.use("/api/setting/fileManagement/openFolder", route118); app.use("/api/setting/dbConfig/exportData", route118);
app.use("/api/setting/getTextModel", route119); app.use("/api/setting/dbConfig/importData", route119);
app.use("/api/setting/loginConfig/getUser", route120); app.use("/api/setting/dev/getSwitchAiDevTool", route120);
app.use("/api/setting/loginConfig/updateUserPwd", route121); app.use("/api/setting/dev/updateSwitchAiDevTool", route121);
app.use("/api/setting/memoryConfig/delAllMemory", route122); app.use("/api/setting/fileManagement/openFolder", route122);
app.use("/api/setting/memoryConfig/getMemory", route123); app.use("/api/setting/getTextModel", route123);
app.use("/api/setting/memoryConfig/sureMemory", route124); app.use("/api/setting/loginConfig/getUser", route124);
app.use("/api/setting/modelMap/bindingPrompt", route125); app.use("/api/setting/loginConfig/updateUserPwd", route125);
app.use("/api/setting/modelMap/getImageAndVideoModel", route126); app.use("/api/setting/memoryConfig/delAllMemory", route126);
app.use("/api/setting/promptManage/getPrompt", route127); app.use("/api/setting/memoryConfig/getMemory", route127);
app.use("/api/setting/promptManage/updatePrompt", route128); app.use("/api/setting/memoryConfig/sureMemory", route128);
app.use("/api/setting/skillManagement/getSkillContent", route129); app.use("/api/setting/modelMap/bindingPrompt", route129);
app.use("/api/setting/skillManagement/getSkillList", route130); app.use("/api/setting/modelMap/getImageAndVideoModel", route130);
app.use("/api/setting/skillManagement/saveSkillContent", route131); app.use("/api/setting/promptManage/getPrompt", route131);
app.use("/api/setting/vendorConfig/addVendor", route132); app.use("/api/setting/promptManage/updatePrompt", route132);
app.use("/api/setting/vendorConfig/addVendorModel", route133); app.use("/api/setting/skillManagement/getSkillContent", route133);
app.use("/api/setting/vendorConfig/deleteVendor", route134); app.use("/api/setting/skillManagement/getSkillList", route134);
app.use("/api/setting/vendorConfig/delVendorModel", route135); app.use("/api/setting/skillManagement/saveSkillContent", route135);
app.use("/api/setting/vendorConfig/enableVendor", route136); app.use("/api/setting/vendorConfig/addVendor", route136);
app.use("/api/setting/vendorConfig/getCodeByLink", route137); app.use("/api/setting/vendorConfig/addVendorModel", route137);
app.use("/api/setting/vendorConfig/getVendorList", route138); app.use("/api/setting/vendorConfig/deleteVendor", route138);
app.use("/api/setting/vendorConfig/modelTest", route139); app.use("/api/setting/vendorConfig/delVendorModel", route139);
app.use("/api/setting/vendorConfig/updateCode", route140); app.use("/api/setting/vendorConfig/enableVendor", route140);
app.use("/api/setting/vendorConfig/updateVendorInputs", route141); app.use("/api/setting/vendorConfig/getCodeByLink", route141);
app.use("/api/setting/vendorConfig/upVendorModel", route142); app.use("/api/setting/vendorConfig/getVendorList", route142);
app.use("/api/task/getProject", route143); app.use("/api/setting/vendorConfig/modelTest", route143);
app.use("/api/task/getTaskApi", route144); app.use("/api/setting/vendorConfig/updateCode", route144);
app.use("/api/task/getTaskCategories", route145); app.use("/api/setting/vendorConfig/updateVendorInputs", route145);
app.use("/api/task/taskDetails", route146); app.use("/api/setting/vendorConfig/upVendorModel", route146);
app.use("/api/test/test", route147); app.use("/api/task/getProject", route147);
app.use("/api/task/getTaskApi", route148);
app.use("/api/task/getTaskCategories", route149);
app.use("/api/task/taskDetails", route150);
app.use("/api/test/test", route151);
} }

View File

@ -40,7 +40,6 @@ export default router.post(
data.map((i:any) => i.id!), data.map((i:any) => i.id!),
) )
.select( "o_assets.id", "o_assets.name"); .select( "o_assets.id", "o_assets.name");
console.log("%c Line:36 🍎 assets2AudioData", "background:#3f7cff", assets2AudioData);
const repleAssets:Record<number,{id:number;name:string}[]> = {}; const repleAssets:Record<number,{id:number;name:string}[]> = {};
assets2AudioData.forEach((item) => { assets2AudioData.forEach((item) => {
if (!repleAssets[item.id]) repleAssets[item.id] = [item]; if (!repleAssets[item.id]) repleAssets[item.id] = [item];

View File

@ -25,22 +25,8 @@ export default router.post(
const zip = await axios.get(url, { responseType: "arraybuffer" }).then((res) => res.data); const zip = await axios.get(url, { responseType: "arraybuffer" }).then((res) => res.data);
fs.writeFileSync(`${rootDir}/latest.zip`, zip); fs.writeFileSync(`${rootDir}/latest.zip`, zip);
await compressing.zip.uncompress(`${rootDir}/latest.zip`, rootDir); await compressing.zip.uncompress(`${rootDir}/latest.zip`, rootDir);
const tempServerPath = u.getPath(["temp", "serve"]); const dataDir = u.getPath();
if (fs.existsSync(tempServerPath)) { fs.cpSync(rootDir, dataDir, { recursive: true, force: true });
fs.cpSync(tempServerPath, u.getPath(["serve"]), { recursive: true, force: true });
}
const webPath = u.getPath(["temp", "web"]);
if (fs.existsSync(webPath)) {
fs.cpSync(webPath, u.getPath(["web"]), { recursive: true, force: true });
}
const tempSkillsPath = u.getPath(["temp", "skills"]);
if (fs.existsSync(tempSkillsPath)) {
fs.cpSync(tempSkillsPath, u.getPath(["skills"]), { recursive: true, force: true });
}
const tempModelsPath = u.getPath(["temp", "models"]);
if (fs.existsSync(tempModelsPath)) {
fs.cpSync(tempModelsPath, u.getPath(["models"]), { recursive: true, force: true });
}
fs.rmSync(rootDir, { recursive: true, force: true }); fs.rmSync(rootDir, { recursive: true, force: true });
res.status(200).send(success(`更新${version}成功5秒后重启`)); res.status(200).send(success(`更新${version}成功5秒后重启`));
} }

View File

@ -43,97 +43,6 @@ export default router.post(
modelName: "toonflow:claude-haiku-4-5-20251001", modelName: "toonflow:claude-haiku-4-5-20251001",
vendorId: "toonflow", vendorId: "toonflow",
}); });
await u.db("o_agentDeploy").where("key", "scriptAgent:decisionAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "scriptAgent:supervisionAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "scriptAgent:storySkeletonAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "scriptAgent:adaptationStrategyAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "scriptAgent:scriptAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "productionAgent:decisionAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "productionAgent:supervisionAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "productionAgent:deriveAssetsAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "productionAgent:generateAssetsAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "productionAgent:directorPlanAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "productionAgent:storyboardGenAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "productionAgent:storyboardPanelAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
await u.db("o_agentDeploy").where("key", "productionAgent:storyboardTableAgent").update({
model: "claude-sonnet-4-6",
modelName: "toonflow:claude-sonnet-4-6",
vendorId: "toonflow",
temperature: 1,
maxOutputTokens: 8192,
});
res.status(200).send(success("一键填入成功")); res.status(200).send(success("一键填入成功"));
} }
} catch (err) { } catch (err) {

View File

@ -0,0 +1,29 @@
import express from "express";
import { success, error } from "@/lib/responseFormat";
import { db } from "@/utils/db";
const router = express.Router();
export default router.post("/", async (req, res) => {
try {
const { tableName } = req.body;
if (!tableName || typeof tableName !== "string") {
return res.status(400).send(error("请提供有效的表名"));
}
// 验证表名存在防止SQL注入
const tableExists: { name: string }[] = await db.raw(
`SELECT name FROM sqlite_master WHERE type='table' AND name=?`,
[tableName],
);
if (tableExists.length === 0) {
return res.status(400).send(error("表不存在"));
}
await db.raw(`DELETE FROM "${tableName}"`);
res.status(200).send(success(`${tableName} 已清空`));
} catch (err: any) {
res.status(500).send(error(err?.message || "清空表失败"));
}
});

View File

@ -0,0 +1,26 @@
import express from "express";
import { success, error } from "@/lib/responseFormat";
import { db } from "@/utils/db";
const router = express.Router();
export default router.get("/", async (req, res) => {
try {
const tables: { name: string }[] = await db.raw(
`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE 'knex_%'`,
);
const tableInfo = [];
for (const table of tables) {
const countResult = await db.raw(`SELECT COUNT(*) as count FROM "${table.name}"`);
tableInfo.push({
name: table.name,
rowCount: countResult[0]?.count ?? 0,
});
}
res.status(200).send(success(tableInfo));
} catch (err: any) {
res.status(500).send(error(err?.message || "获取数据库信息失败"));
}
});

View File

@ -0,0 +1,29 @@
import express from "express";
import { success, error } from "@/lib/responseFormat";
import { db } from "@/utils/db";
const router = express.Router();
export default router.get("/", async (req, res) => {
try {
const tables: { name: string }[] = await db.raw(
`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE 'knex_%'`,
);
const data: Record<string, any[]> = {};
for (const table of tables) {
data[table.name] = await db.raw(`SELECT * FROM "${table.name}"`);
}
const exportData = {
exportTime: Date.now(),
tables: data,
};
res.setHeader("Content-Type", "application/json");
res.setHeader("Content-Disposition", `attachment; filename=toonflow-backup-${Date.now()}.json`);
res.status(200).send(JSON.stringify(exportData, null, 2));
} catch (err: any) {
res.status(500).send(error(err?.message || "导出失败"));
}
});

View File

@ -0,0 +1,55 @@
import express from "express";
import { success, error } from "@/lib/responseFormat";
import { db } from "@/utils/db";
import initDB from "@/lib/initDB";
const router = express.Router();
export default router.post("/", async (req, res) => {
try {
const { tables: importTables } = req.body;
if (!importTables || typeof importTables !== "object") {
return res.status(400).send(error("无效的导入数据格式"));
}
// 删除所有现有表
const existingTables: { name: string }[] = await db.raw(
`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE 'knex_%'`,
);
await db.raw("PRAGMA foreign_keys = OFF");
for (const table of existingTables) {
await db.schema.dropTableIfExists(table.name);
}
await db.raw("PRAGMA foreign_keys = ON");
// 重新初始化表结构
await initDB(db as any);
// 导入数据
await db.raw("PRAGMA foreign_keys = OFF");
for (const [tableName, rows] of Object.entries(importTables)) {
if (!Array.isArray(rows) || rows.length === 0) continue;
// 验证表名合法性防止SQL注入
const tableExists = await db.raw(
`SELECT name FROM sqlite_master WHERE type='table' AND name=?`,
[tableName],
);
if (tableExists.length === 0) continue;
// 清空表数据后插入导入数据
await db.raw(`DELETE FROM "${tableName}"`);
// 分批插入每批100条
for (let i = 0; i < rows.length; i += 100) {
const batch = rows.slice(i, i + 100);
await db(tableName).insert(batch);
}
}
await db.raw("PRAGMA foreign_keys = ON");
res.status(200).send(success("数据库导入成功"));
} catch (err: any) {
res.status(500).send(error(err?.message || "导入失败"));
}
});

View File

@ -158,7 +158,6 @@ class AiText {
} }
async invoke(input: Omit<Parameters<typeof generateText>[0], "model">) { async invoke(input: Omit<Parameters<typeof generateText>[0], "model">) {
const config = await getModelConfig(this.AiType); const config = await getModelConfig(this.AiType);
console.log("%c Line:161 🥃 config", "background:#3f7cff", config);
return generateText({ return generateText({
...(input.tools && { stopWhen: stepCountIs(Object.keys(input.tools).length * 50) }), ...(input.tools && { stopWhen: stepCountIs(Object.keys(input.tools).length * 50) }),
@ -261,7 +260,6 @@ class AiVideo {
const exec = async (mn: `${string}:${string}`) => { const exec = async (mn: `${string}:${string}`) => {
const fn = await getVendorTemplateFn("videoRequest", mn); const fn = await getVendorTemplateFn("videoRequest", mn);
await referenceList2imageBase642(mn.split(/:(.+)/)[0], input); await referenceList2imageBase642(mn.split(/:(.+)/)[0], input);
console.log("%c Line:204 🍡 input", "background:#465975", input);
this.result = await fn(input); this.result = await fn(input);
if (this.result.startsWith("http")) this.result = await urlToBase64(this.result); if (this.result.startsWith("http")) this.result = await urlToBase64(this.result);