Merge branch '108' of https://github.com/HBAI-Ltd/Toonflow-app into 108
# Conflicts: # src/types/database.d.ts
This commit is contained in:
commit
bbb947f804
@ -1,4 +1,4 @@
|
||||
name
|
||||
123123水电费水电费水电费水电费水电费
|
||||
123123123
|
||||
12312312312
|
||||
123123123
|
||||
@ -1 +0,0 @@
|
||||
1212水电费水电费萨芬的水电费
|
||||
@ -1 +0,0 @@
|
||||
1212
|
||||
@ -1 +0,0 @@
|
||||
1212
|
||||
@ -1 +0,0 @@
|
||||
1212
|
||||
@ -1 +0,0 @@
|
||||
1212
|
||||
@ -1 +0,0 @@
|
||||
1212
|
||||
@ -1 +0,0 @@
|
||||
1212
|
||||
@ -1 +0,0 @@
|
||||
1212
|
||||
@ -1 +0,0 @@
|
||||
1212
|
||||
@ -1 +0,0 @@
|
||||
1212
|
||||
@ -1 +0,0 @@
|
||||
1212
|
||||
@ -1 +0,0 @@
|
||||
1212
|
||||
@ -96,7 +96,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "universalAgent",
|
||||
key: "universalAi",
|
||||
name: "通用AI",
|
||||
desc: "用于小说事件提取、资产提示词生成、台词提取等边缘功能,建议使用具备较强文本处理能力的模型",
|
||||
disabled: false,
|
||||
|
||||
192
src/router.ts
192
src/router.ts
@ -1,4 +1,4 @@
|
||||
// @routes-hash 5a19c42c22d44ec4c7fe2fc7245535d9
|
||||
// @routes-hash 48f3cafa7563a8ec5d646e1f88ef8bfd
|
||||
import { Express } from "express";
|
||||
|
||||
import route1 from "./routes/agents/clearMemory";
|
||||
@ -66,53 +66,54 @@ import route62 from "./routes/production/workbench/getVideoModelDetail";
|
||||
import route63 from "./routes/production/workbench/videoPolling";
|
||||
import route64 from "./routes/project/addProject";
|
||||
import route65 from "./routes/project/addVisual";
|
||||
import route66 from "./routes/project/deleteVisualManual";
|
||||
import route67 from "./routes/project/delProject";
|
||||
import route68 from "./routes/project/editProject";
|
||||
import route69 from "./routes/project/editVisualManual";
|
||||
import route70 from "./routes/project/getProject";
|
||||
import route71 from "./routes/project/getVisualManual";
|
||||
import route72 from "./routes/project/visualManual";
|
||||
import route73 from "./routes/script/addScript";
|
||||
import route74 from "./routes/script/delScript";
|
||||
import route75 from "./routes/script/exportScript";
|
||||
import route76 from "./routes/script/extractAssets";
|
||||
import route77 from "./routes/script/getScrptApi";
|
||||
import route78 from "./routes/script/pollScriptAssets";
|
||||
import route79 from "./routes/script/updateScript";
|
||||
import route80 from "./routes/scriptAgent/getPlanData";
|
||||
import route81 from "./routes/scriptAgent/setPlanData";
|
||||
import route82 from "./routes/setting/about/checkUpdate";
|
||||
import route83 from "./routes/setting/about/downloadApp";
|
||||
import route84 from "./routes/setting/agentDeploy/agentSetKey";
|
||||
import route85 from "./routes/setting/agentDeploy/deployAgentModel";
|
||||
import route86 from "./routes/setting/agentDeploy/getAgentDeploy";
|
||||
import route87 from "./routes/setting/dbConfig/clearData";
|
||||
import route88 from "./routes/setting/dev/getSwitchAiDevTool";
|
||||
import route89 from "./routes/setting/dev/updateSwitchAiDevTool";
|
||||
import route90 from "./routes/setting/fileManagement/openFolder";
|
||||
import route91 from "./routes/setting/getTextModel";
|
||||
import route92 from "./routes/setting/loginConfig/getUser";
|
||||
import route93 from "./routes/setting/loginConfig/updateUserPwd";
|
||||
import route94 from "./routes/setting/memoryConfig/delAllMemory";
|
||||
import route95 from "./routes/setting/memoryConfig/getMemory";
|
||||
import route96 from "./routes/setting/memoryConfig/sureMemory";
|
||||
import route97 from "./routes/setting/promptManage/getPrompt";
|
||||
import route98 from "./routes/setting/promptManage/updatePrompt";
|
||||
import route99 from "./routes/setting/skillManagement/getSkillContent";
|
||||
import route100 from "./routes/setting/skillManagement/getSkillList";
|
||||
import route101 from "./routes/setting/skillManagement/saveSkillContent";
|
||||
import route102 from "./routes/setting/vendorConfig/addVendor";
|
||||
import route103 from "./routes/setting/vendorConfig/deleteVendor";
|
||||
import route104 from "./routes/setting/vendorConfig/getVendorList";
|
||||
import route105 from "./routes/setting/vendorConfig/modelTest";
|
||||
import route106 from "./routes/setting/vendorConfig/updateCode";
|
||||
import route107 from "./routes/setting/vendorConfig/updateVendor";
|
||||
import route108 from "./routes/task/getProject";
|
||||
import route109 from "./routes/task/getTaskApi";
|
||||
import route110 from "./routes/task/getTaskCategories";
|
||||
import route111 from "./routes/task/taskDetails";
|
||||
import route112 from "./routes/test/test";
|
||||
import route66 from "./routes/project/addVisualManual";
|
||||
import route67 from "./routes/project/deleteVisualManual";
|
||||
import route68 from "./routes/project/delProject";
|
||||
import route69 from "./routes/project/editProject";
|
||||
import route70 from "./routes/project/editVisualManual";
|
||||
import route71 from "./routes/project/getProject";
|
||||
import route72 from "./routes/project/getVisualManual";
|
||||
import route73 from "./routes/project/visualManual";
|
||||
import route74 from "./routes/script/addScript";
|
||||
import route75 from "./routes/script/delScript";
|
||||
import route76 from "./routes/script/exportScript";
|
||||
import route77 from "./routes/script/extractAssets";
|
||||
import route78 from "./routes/script/getScrptApi";
|
||||
import route79 from "./routes/script/pollScriptAssets";
|
||||
import route80 from "./routes/script/updateScript";
|
||||
import route81 from "./routes/scriptAgent/getPlanData";
|
||||
import route82 from "./routes/scriptAgent/setPlanData";
|
||||
import route83 from "./routes/setting/about/checkUpdate";
|
||||
import route84 from "./routes/setting/about/downloadApp";
|
||||
import route85 from "./routes/setting/agentDeploy/agentSetKey";
|
||||
import route86 from "./routes/setting/agentDeploy/deployAgentModel";
|
||||
import route87 from "./routes/setting/agentDeploy/getAgentDeploy";
|
||||
import route88 from "./routes/setting/dbConfig/clearData";
|
||||
import route89 from "./routes/setting/dev/getSwitchAiDevTool";
|
||||
import route90 from "./routes/setting/dev/updateSwitchAiDevTool";
|
||||
import route91 from "./routes/setting/fileManagement/openFolder";
|
||||
import route92 from "./routes/setting/getTextModel";
|
||||
import route93 from "./routes/setting/loginConfig/getUser";
|
||||
import route94 from "./routes/setting/loginConfig/updateUserPwd";
|
||||
import route95 from "./routes/setting/memoryConfig/delAllMemory";
|
||||
import route96 from "./routes/setting/memoryConfig/getMemory";
|
||||
import route97 from "./routes/setting/memoryConfig/sureMemory";
|
||||
import route98 from "./routes/setting/promptManage/getPrompt";
|
||||
import route99 from "./routes/setting/promptManage/updatePrompt";
|
||||
import route100 from "./routes/setting/skillManagement/getSkillContent";
|
||||
import route101 from "./routes/setting/skillManagement/getSkillList";
|
||||
import route102 from "./routes/setting/skillManagement/saveSkillContent";
|
||||
import route103 from "./routes/setting/vendorConfig/addVendor";
|
||||
import route104 from "./routes/setting/vendorConfig/deleteVendor";
|
||||
import route105 from "./routes/setting/vendorConfig/getVendorList";
|
||||
import route106 from "./routes/setting/vendorConfig/modelTest";
|
||||
import route107 from "./routes/setting/vendorConfig/updateCode";
|
||||
import route108 from "./routes/setting/vendorConfig/updateVendor";
|
||||
import route109 from "./routes/task/getProject";
|
||||
import route110 from "./routes/task/getTaskApi";
|
||||
import route111 from "./routes/task/getTaskCategories";
|
||||
import route112 from "./routes/task/taskDetails";
|
||||
import route113 from "./routes/test/test";
|
||||
|
||||
export default async (app: Express) => {
|
||||
app.use("/api/agents/clearMemory", route1);
|
||||
@ -180,51 +181,52 @@ export default async (app: Express) => {
|
||||
app.use("/api/production/workbench/videoPolling", route63);
|
||||
app.use("/api/project/addProject", route64);
|
||||
app.use("/api/project/addVisual", route65);
|
||||
app.use("/api/project/deleteVisualManual", route66);
|
||||
app.use("/api/project/delProject", route67);
|
||||
app.use("/api/project/editProject", route68);
|
||||
app.use("/api/project/editVisualManual", route69);
|
||||
app.use("/api/project/getProject", route70);
|
||||
app.use("/api/project/getVisualManual", route71);
|
||||
app.use("/api/project/visualManual", route72);
|
||||
app.use("/api/script/addScript", route73);
|
||||
app.use("/api/script/delScript", route74);
|
||||
app.use("/api/script/exportScript", route75);
|
||||
app.use("/api/script/extractAssets", route76);
|
||||
app.use("/api/script/getScrptApi", route77);
|
||||
app.use("/api/script/pollScriptAssets", route78);
|
||||
app.use("/api/script/updateScript", route79);
|
||||
app.use("/api/scriptAgent/getPlanData", route80);
|
||||
app.use("/api/scriptAgent/setPlanData", route81);
|
||||
app.use("/api/setting/about/checkUpdate", route82);
|
||||
app.use("/api/setting/about/downloadApp", route83);
|
||||
app.use("/api/setting/agentDeploy/agentSetKey", route84);
|
||||
app.use("/api/setting/agentDeploy/deployAgentModel", route85);
|
||||
app.use("/api/setting/agentDeploy/getAgentDeploy", route86);
|
||||
app.use("/api/setting/dbConfig/clearData", route87);
|
||||
app.use("/api/setting/dev/getSwitchAiDevTool", route88);
|
||||
app.use("/api/setting/dev/updateSwitchAiDevTool", route89);
|
||||
app.use("/api/setting/fileManagement/openFolder", route90);
|
||||
app.use("/api/setting/getTextModel", route91);
|
||||
app.use("/api/setting/loginConfig/getUser", route92);
|
||||
app.use("/api/setting/loginConfig/updateUserPwd", route93);
|
||||
app.use("/api/setting/memoryConfig/delAllMemory", route94);
|
||||
app.use("/api/setting/memoryConfig/getMemory", route95);
|
||||
app.use("/api/setting/memoryConfig/sureMemory", route96);
|
||||
app.use("/api/setting/promptManage/getPrompt", route97);
|
||||
app.use("/api/setting/promptManage/updatePrompt", route98);
|
||||
app.use("/api/setting/skillManagement/getSkillContent", route99);
|
||||
app.use("/api/setting/skillManagement/getSkillList", route100);
|
||||
app.use("/api/setting/skillManagement/saveSkillContent", route101);
|
||||
app.use("/api/setting/vendorConfig/addVendor", route102);
|
||||
app.use("/api/setting/vendorConfig/deleteVendor", route103);
|
||||
app.use("/api/setting/vendorConfig/getVendorList", route104);
|
||||
app.use("/api/setting/vendorConfig/modelTest", route105);
|
||||
app.use("/api/setting/vendorConfig/updateCode", route106);
|
||||
app.use("/api/setting/vendorConfig/updateVendor", route107);
|
||||
app.use("/api/task/getProject", route108);
|
||||
app.use("/api/task/getTaskApi", route109);
|
||||
app.use("/api/task/getTaskCategories", route110);
|
||||
app.use("/api/task/taskDetails", route111);
|
||||
app.use("/api/test/test", route112);
|
||||
app.use("/api/project/addVisualManual", route66);
|
||||
app.use("/api/project/deleteVisualManual", route67);
|
||||
app.use("/api/project/delProject", route68);
|
||||
app.use("/api/project/editProject", route69);
|
||||
app.use("/api/project/editVisualManual", route70);
|
||||
app.use("/api/project/getProject", route71);
|
||||
app.use("/api/project/getVisualManual", route72);
|
||||
app.use("/api/project/visualManual", route73);
|
||||
app.use("/api/script/addScript", route74);
|
||||
app.use("/api/script/delScript", route75);
|
||||
app.use("/api/script/exportScript", route76);
|
||||
app.use("/api/script/extractAssets", route77);
|
||||
app.use("/api/script/getScrptApi", route78);
|
||||
app.use("/api/script/pollScriptAssets", route79);
|
||||
app.use("/api/script/updateScript", route80);
|
||||
app.use("/api/scriptAgent/getPlanData", route81);
|
||||
app.use("/api/scriptAgent/setPlanData", route82);
|
||||
app.use("/api/setting/about/checkUpdate", route83);
|
||||
app.use("/api/setting/about/downloadApp", route84);
|
||||
app.use("/api/setting/agentDeploy/agentSetKey", route85);
|
||||
app.use("/api/setting/agentDeploy/deployAgentModel", route86);
|
||||
app.use("/api/setting/agentDeploy/getAgentDeploy", route87);
|
||||
app.use("/api/setting/dbConfig/clearData", route88);
|
||||
app.use("/api/setting/dev/getSwitchAiDevTool", route89);
|
||||
app.use("/api/setting/dev/updateSwitchAiDevTool", route90);
|
||||
app.use("/api/setting/fileManagement/openFolder", route91);
|
||||
app.use("/api/setting/getTextModel", route92);
|
||||
app.use("/api/setting/loginConfig/getUser", route93);
|
||||
app.use("/api/setting/loginConfig/updateUserPwd", route94);
|
||||
app.use("/api/setting/memoryConfig/delAllMemory", route95);
|
||||
app.use("/api/setting/memoryConfig/getMemory", route96);
|
||||
app.use("/api/setting/memoryConfig/sureMemory", route97);
|
||||
app.use("/api/setting/promptManage/getPrompt", route98);
|
||||
app.use("/api/setting/promptManage/updatePrompt", route99);
|
||||
app.use("/api/setting/skillManagement/getSkillContent", route100);
|
||||
app.use("/api/setting/skillManagement/getSkillList", route101);
|
||||
app.use("/api/setting/skillManagement/saveSkillContent", route102);
|
||||
app.use("/api/setting/vendorConfig/addVendor", route103);
|
||||
app.use("/api/setting/vendorConfig/deleteVendor", route104);
|
||||
app.use("/api/setting/vendorConfig/getVendorList", route105);
|
||||
app.use("/api/setting/vendorConfig/modelTest", route106);
|
||||
app.use("/api/setting/vendorConfig/updateCode", route107);
|
||||
app.use("/api/setting/vendorConfig/updateVendor", route108);
|
||||
app.use("/api/task/getProject", route109);
|
||||
app.use("/api/task/getTaskApi", route110);
|
||||
app.use("/api/task/getTaskCategories", route111);
|
||||
app.use("/api/task/taskDetails", route112);
|
||||
app.use("/api/test/test", route113);
|
||||
}
|
||||
|
||||
@ -31,7 +31,6 @@ export default router.post(
|
||||
imageId: assets!.imageId ?? null,
|
||||
tempAssets,
|
||||
};
|
||||
console.log("%c Line:30 🥤 data", "background:#465975", data);
|
||||
res.status(200).send(success(data));
|
||||
},
|
||||
);
|
||||
|
||||
@ -84,16 +84,13 @@ export default router.post(
|
||||
});
|
||||
const result: ResultItem[] = Object.values(itemMap);
|
||||
|
||||
const typeConfig: Record<string, { promptKey: string; itemType: ItemType; label: string; nameLabel: string }> = {
|
||||
role: { promptKey: "role-polish", itemType: "characters", label: "角色标准四视图", nameLabel: "角色" },
|
||||
scene: { promptKey: "scene-polish", itemType: "scenes", label: "场景图", nameLabel: "场景" },
|
||||
tool: { promptKey: "tool-polish", itemType: "props", label: "道具图", nameLabel: "道具" },
|
||||
const typeConfig: Record<string, { promptKey: string; itemType: ItemType; label: string; nameLabel: string; visualManual: string }> = {
|
||||
role: { promptKey: "role-polish", itemType: "characters", label: "角色标准四视图", nameLabel: "角色", visualManual: "art_character" },
|
||||
scene: { promptKey: "scene-polish", itemType: "scenes", label: "场景图", nameLabel: "场景", visualManual: "art_scene" },
|
||||
tool: { promptKey: "tool-polish", itemType: "props", label: "道具图", nameLabel: "道具", visualManual: "art_prop" },
|
||||
};
|
||||
|
||||
const novelData = (await u.db("o_novel").whereIn("chapterIndex", [1]).select("*")) as NovelChapter[];
|
||||
const novelText = mergeNovelText(novelData);
|
||||
const data = await u.db("o_prompt").where("type", "assetsPromptGeneration").first("data");
|
||||
|
||||
// 批量更新所有 item 状态为生成中
|
||||
const assetsIds = items.map((item: { assetsId: number }) => item.assetsId);
|
||||
await u.db("o_assets").whereIn("id", assetsIds).update({ promptState: "生成中" });
|
||||
@ -105,11 +102,12 @@ export default router.post(
|
||||
limit(async () => {
|
||||
const config = typeConfig[item.type];
|
||||
if (!config) return;
|
||||
|
||||
//获取到视觉手册
|
||||
const visualManual = await u.getArtPrompt(project.artStyle as string, config.visualManual);
|
||||
if (!visualManual) return res.status(500).send(error("视觉手册未定义"));
|
||||
findItemByName(result, item.name, config.itemType);
|
||||
|
||||
const systemPrompt = `${data?.data}
|
||||
|
||||
const systemPrompt = `
|
||||
请根据以下参数生成${config.label}提示词:
|
||||
|
||||
**基础参数:**
|
||||
@ -122,6 +120,7 @@ export default router.post(
|
||||
- ${config.nameLabel}描述:${item.describe},
|
||||
|
||||
请严格按照skill规范生成${item.type === "role" ? "人物角色四视图" : config.label}提示词。
|
||||
${visualManual}
|
||||
`;
|
||||
|
||||
try {
|
||||
|
||||
@ -85,27 +85,26 @@ export default router.post(
|
||||
|
||||
const result: ResultItem[] = Object.values(itemMap);
|
||||
|
||||
const typeConfig: Record<string, { promptKey: string; itemType: ItemType; label: string; nameLabel: string }> = {
|
||||
role: { promptKey: "role-polish", itemType: "characters", label: "角色标准四视图", nameLabel: "角色" },
|
||||
scene: { promptKey: "scene-polish", itemType: "scenes", label: "场景图", nameLabel: "场景" },
|
||||
tool: { promptKey: "tool-polish", itemType: "props", label: "道具图", nameLabel: "道具" },
|
||||
const typeConfig: Record<string, { promptKey: string; itemType: ItemType; label: string; nameLabel: string; visualManual: string }> = {
|
||||
role: { promptKey: "role-polish", itemType: "characters", label: "角色标准四视图", nameLabel: "角色", visualManual: "art_character" },
|
||||
scene: { promptKey: "scene-polish", itemType: "scenes", label: "场景图", nameLabel: "场景", visualManual: "art_scene" },
|
||||
tool: { promptKey: "tool-polish", itemType: "props", label: "道具图", nameLabel: "道具", visualManual: "art_prop" },
|
||||
};
|
||||
|
||||
const config = typeConfig[type];
|
||||
if (!config) return res.status(500).send(error("不支持的类型"));
|
||||
|
||||
if (!config.visualManual) return res.status(500).send(error("视觉手册未定义"));
|
||||
//获取到视觉手册
|
||||
const visualManual = await u.getArtPrompt(project.artStyle as string, config.visualManual);
|
||||
if (!visualManual) return res.status(500).send(error("视觉手册未定义"));
|
||||
findItemByName(result, name, config.itemType);
|
||||
const novelData = (await u.db("o_novel").whereIn("chapterIndex", [1]).select("*")) as NovelChapter[];
|
||||
const novelText = mergeNovelText(novelData);
|
||||
|
||||
const data = await u.db("o_prompt").where("type", "assetsPromptGeneration").first("data");
|
||||
|
||||
const systemPrompt = `${data?.data}
|
||||
|
||||
const systemPrompt = `
|
||||
请根据以下参数生成${config.label}提示词:
|
||||
|
||||
**基础参数:**
|
||||
- 风格: ${project?.artStyle || "未指定"}
|
||||
- 小说类型: ${project?.type || "未指定"}
|
||||
- 小说背景: ${project?.intro || "未指定"}
|
||||
|
||||
@ -113,7 +112,8 @@ export default router.post(
|
||||
- ${config.nameLabel}名称:${name},
|
||||
- ${config.nameLabel}描述:${describe},
|
||||
|
||||
请严格按照skill规范生成${type === "role" ? "人物角色四视图" : config.label}提示词。
|
||||
请严格按照skill规范生成${type === "role" ? "人物角色四视图" : config.label}提示词
|
||||
${visualManual}。
|
||||
`;
|
||||
|
||||
try {
|
||||
|
||||
@ -6,28 +6,38 @@ import { validateFields } from "@/middleware/middleware";
|
||||
const router = express.Router();
|
||||
|
||||
export default router.post(
|
||||
"/",
|
||||
validateFields({
|
||||
projectId: z.number(),
|
||||
type: z.array(z.string()).optional(),
|
||||
}),
|
||||
async (req, res) => {
|
||||
const { projectId, type, } = req.body;
|
||||
const data = await u
|
||||
.db("o_assets")
|
||||
.leftJoin("o_image", "o_assets.imageId", "o_image.id")
|
||||
.select("o_assets.*", "o_image.filePath", "o_image.state", "o_image.model", "o_image.resolution")
|
||||
.where("o_assets.projectId", projectId)
|
||||
.andWhere("o_assets.type", "<>", "clip")
|
||||
.modify((qb) => {
|
||||
if (type && type.length > 0) qb.whereIn("o_assets.type", type);
|
||||
});
|
||||
const result = await Promise.all(
|
||||
data.map(async (parent: any) => ({
|
||||
...parent,
|
||||
filePath: parent.filePath && (await u.oss.getFileUrl(parent.filePath!)),
|
||||
})),
|
||||
"/",
|
||||
validateFields({
|
||||
projectId: z.number(),
|
||||
type: z.array(z.string()).optional(),
|
||||
}),
|
||||
async (req, res) => {
|
||||
const { projectId, type } = req.body;
|
||||
const data = await u
|
||||
.db("o_assets")
|
||||
.leftJoin("o_image", "o_assets.imageId", "o_image.id")
|
||||
.select("o_assets.*", "o_image.filePath", "o_image.state", "o_image.model", "o_image.resolution")
|
||||
.where("o_assets.projectId", projectId)
|
||||
.andWhere("o_assets.type", "<>", "clip")
|
||||
.modify((qb) => {
|
||||
if (type && type.length > 0) qb.whereIn("o_assets.type", type);
|
||||
});
|
||||
const result = await Promise.all(
|
||||
data.map(async (parent: any) => {
|
||||
const historyImages = await u.db("o_image").where("assetsId", parent.id).andWhere("state", "已完成").select("id", "filePath");
|
||||
const historyImagesWithUrl = await Promise.all(
|
||||
historyImages.map(async (img: any) => ({
|
||||
id: img.id,
|
||||
filePath: img.filePath && (await u.oss.getFileUrl(img.filePath)),
|
||||
})),
|
||||
);
|
||||
res.status(200).send(success(result));
|
||||
},
|
||||
return {
|
||||
...parent,
|
||||
filePath: parent.filePath && (await u.oss.getFileUrl(parent.filePath!)),
|
||||
historyImages: historyImagesWithUrl,
|
||||
};
|
||||
}),
|
||||
);
|
||||
res.status(200).send(success(result));
|
||||
},
|
||||
);
|
||||
|
||||
102
src/routes/project/addVisualManual.ts
Normal file
102
src/routes/project/addVisualManual.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import express from "express";
|
||||
import u from "@/utils";
|
||||
import { error, success } from "@/lib/responseFormat";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { validateFields } from "@/middleware/middleware";
|
||||
import { z } from "zod";
|
||||
const router = express.Router();
|
||||
|
||||
// 编辑视觉手册
|
||||
export default router.post(
|
||||
"/",
|
||||
validateFields({
|
||||
name: z.string(),
|
||||
images: z.array(z.string()),
|
||||
data: z.array(
|
||||
z.object({
|
||||
label: z.string(),
|
||||
value: z.string(),
|
||||
data: z.string(),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
async (req, res) => {
|
||||
try {
|
||||
const { name, images, data } = req.body as {
|
||||
name: string;
|
||||
images: string[];
|
||||
data: { label: string; value: string; data: string }[];
|
||||
};
|
||||
|
||||
if (/^\d+$/.test(name)) {
|
||||
res.status(400).send(error("名称不能为纯数字"));
|
||||
return;
|
||||
}
|
||||
|
||||
const mainPath = u.getPath(["skills", "art_prompts", name]);
|
||||
if (fs.existsSync(mainPath)) {
|
||||
return res.status(400).send(error("请勿填写重复名称的视觉手册"));
|
||||
}
|
||||
// 字段映射表(与 getVisualManual 保持一致)
|
||||
const DATA_MAP: { value: string; subDir?: string }[] = [
|
||||
{ value: "README" },
|
||||
{ value: "prefix" },
|
||||
{ value: "art_character", subDir: "art_prompt" },
|
||||
{ value: "art_character_derivative", subDir: "art_prompt" },
|
||||
{ value: "art_prop", subDir: "art_prompt" },
|
||||
{ value: "art_prop_derivative", subDir: "art_prompt" },
|
||||
{ value: "art_scene", subDir: "art_prompt" },
|
||||
{ value: "art_scene_derivative", subDir: "art_prompt" },
|
||||
{ value: "art_storyboard", subDir: "art_prompt" },
|
||||
{ value: "art_storyboard_video", subDir: "art_prompt" },
|
||||
{ value: "director_planning", subDir: "driector_skills" },
|
||||
{ value: "director_storyboard_table", subDir: "driector_skills" },
|
||||
];
|
||||
|
||||
// 根据 DATA_MAP 构建 value -> subDir 的映射
|
||||
const SUB_DIR_MAP = new Map(DATA_MAP.map(({ value, subDir }) => [value, subDir ?? ""]));
|
||||
|
||||
// 合法的 value 值集合,用于校验
|
||||
const VALID_KEYS = new Set(DATA_MAP.map(({ value }) => value));
|
||||
|
||||
for (const item of data) {
|
||||
if (!VALID_KEYS.has(item.value)) continue;
|
||||
|
||||
const subDir = SUB_DIR_MAP.get(item.value)!;
|
||||
const dirArr = subDir ? [mainPath, subDir] : [mainPath];
|
||||
const filePath = u.getPath([...dirArr, `${item.value}.md`]);
|
||||
|
||||
const fileDir = path.dirname(filePath);
|
||||
// 目录不存在时递归创建
|
||||
if (!fs.existsSync(fileDir)) {
|
||||
fs.mkdirSync(fileDir, { recursive: true });
|
||||
}
|
||||
fs.writeFileSync(filePath, item.data, "utf-8");
|
||||
}
|
||||
const ossImagesDir = u.getPath(["oss", name]);
|
||||
|
||||
let existingFiles: string[] = [];
|
||||
try {
|
||||
const allFiles = fs.readdirSync(ossImagesDir);
|
||||
existingFiles = allFiles.filter((f) => /\.(png|jpe?g|gif|webp|svg)$/i.test(f));
|
||||
} catch {}
|
||||
|
||||
const retainedFileNames = new Set(images.filter((item) => item.startsWith("http")).map((url) => path.basename(new URL(url).pathname)));
|
||||
|
||||
for (const file of existingFiles) {
|
||||
if (!retainedFileNames.has(file)) {
|
||||
await u.oss.deleteFile(`${name}/${file}`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of images) {
|
||||
if (!item.startsWith("http")) await u.oss.writeFile(`${name}/${u.uuid()}.jpg`, item);
|
||||
}
|
||||
|
||||
res.status(200).send(success());
|
||||
} catch (err) {
|
||||
res.status(500).send({ error: String(err) });
|
||||
}
|
||||
},
|
||||
);
|
||||
@ -1,6 +1,6 @@
|
||||
import express from "express";
|
||||
import u from "@/utils";
|
||||
import fs from "fs";
|
||||
import fs from "node:fs/promises";
|
||||
import { z } from "zod";
|
||||
import { error, success } from "@/lib/responseFormat";
|
||||
import { validateFields } from "@/middleware/middleware";
|
||||
@ -24,15 +24,21 @@ export default router.post(
|
||||
|
||||
const artPromptsDir = u.getPath(["skills", "art_prompts", name]);
|
||||
|
||||
// 1. 删除 skills/art_prompts 下的同名文件夹
|
||||
if (fs.existsSync(artPromptsDir)) {
|
||||
fs.rmSync(artPromptsDir, { recursive: true, force: true });
|
||||
// 2. 删除 oss 下的同名文件夹(存放图片)
|
||||
try {
|
||||
await u.oss.deleteDirectory(name);
|
||||
} catch {
|
||||
// oss 下不存在该目录则忽略
|
||||
try {
|
||||
const stat = await fs.stat(artPromptsDir);
|
||||
if (!stat.isDirectory()) {
|
||||
throw new Error(`${artPromptsDir} 不是文件夹`);
|
||||
}
|
||||
await fs.rm(artPromptsDir, { recursive: true, force: true });
|
||||
} catch (e) {
|
||||
console.error("[删除视觉手册] 删除失败:", artPromptsDir, e);
|
||||
}
|
||||
|
||||
// 2. 删除 oss 下的同名文件夹(存放图片),独立于 art_prompts 目录
|
||||
try {
|
||||
await u.oss.deleteDirectory(name);
|
||||
} catch (e) {
|
||||
console.warn("[删除视觉手册] oss 目录删除失败:", name, e);
|
||||
}
|
||||
|
||||
res.status(200).send(success({ message: "删除成功" }));
|
||||
|
||||
@ -35,21 +35,23 @@ export default router.post(
|
||||
}
|
||||
|
||||
const mainPath = u.getPath(["skills", "art_prompts", name]);
|
||||
|
||||
if (!fs.existsSync(mainPath)) {
|
||||
return res.status(400).send(error("视觉手册不存在"));
|
||||
}
|
||||
// 字段映射表(与 getVisualManual 保持一致)
|
||||
const DATA_MAP: { label: string; value: string; subDir?: string }[] = [
|
||||
{ label: "README", value: "README" },
|
||||
{ label: "前缀", value: "prefix" },
|
||||
{ label: "角色", value: "art_character", subDir: "art_prompt" },
|
||||
{ label: "角色衍生", value: "art_character_derivative", subDir: "art_prompt" },
|
||||
{ label: "道具", value: "art_prop", subDir: "art_prompt" },
|
||||
{ label: "道具衍生", value: "art_prop_derivative", subDir: "art_prompt" },
|
||||
{ label: "场景", value: "art_scene", subDir: "art_prompt" },
|
||||
{ label: "场景衍生", value: "art_scene_derivative", subDir: "art_prompt" },
|
||||
{ label: "分镜", value: "art_storyboard", subDir: "art_prompt" },
|
||||
{ label: "分镜视频", value: "art_storyboard_video", subDir: "art_prompt" },
|
||||
{ label: "技法-导演规划", value: "director_planning", subDir: "driector_skills" },
|
||||
{ label: "技法-分镜表设计", value: "director_storyboard_table", subDir: "driector_skills" },
|
||||
const DATA_MAP: { value: string; subDir?: string }[] = [
|
||||
{ value: "README" },
|
||||
{ value: "prefix" },
|
||||
{ value: "art_character", subDir: "art_prompt" },
|
||||
{ value: "art_character_derivative", subDir: "art_prompt" },
|
||||
{ value: "art_prop", subDir: "art_prompt" },
|
||||
{ value: "art_prop_derivative", subDir: "art_prompt" },
|
||||
{ value: "art_scene", subDir: "art_prompt" },
|
||||
{ value: "art_scene_derivative", subDir: "art_prompt" },
|
||||
{ value: "art_storyboard", subDir: "art_prompt" },
|
||||
{ value: "art_storyboard_video", subDir: "art_prompt" },
|
||||
{ value: "director_planning", subDir: "driector_skills" },
|
||||
{ value: "director_storyboard_table", subDir: "driector_skills" },
|
||||
];
|
||||
|
||||
// 根据 DATA_MAP 构建 value -> subDir 的映射
|
||||
|
||||
@ -15,14 +15,19 @@ export function getArtPrompt(styleName: string, fileName: string): string {
|
||||
return "";
|
||||
}
|
||||
|
||||
// 获取 prefix.md 内容
|
||||
const prefixFile = findFileRecursive(baseDir, "prefix.md");
|
||||
const prefixContent = prefixFile ? fs.readFileSync(prefixFile, "utf-8") : "";
|
||||
|
||||
const target = fileName.endsWith(".md") ? fileName : `${fileName}.md`;
|
||||
const found = findFileRecursive(baseDir, target);
|
||||
|
||||
if (!found) {
|
||||
return "";
|
||||
return prefixContent;
|
||||
}
|
||||
|
||||
return fs.readFileSync(found, "utf-8");
|
||||
const fileContent = fs.readFileSync(found, "utf-8");
|
||||
return prefixContent ? `${prefixContent}\n${fileContent}` : fileContent;
|
||||
}
|
||||
/**
|
||||
* 传入风格目录名,获取该风格下所有 .md 文件内容,按文件名映射返回
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user