完善工作流图片编辑

This commit is contained in:
zhishi 2026-03-25 12:15:44 +08:00
parent 9ae2933d43
commit 9db10342d3
7 changed files with 116 additions and 68 deletions

View File

@ -11,7 +11,7 @@ export const deriveAssetSchema = z.object({
prompt: z.string().describe("生成提示词"), prompt: z.string().describe("生成提示词"),
name: z.string().describe("衍生资产名称"), name: z.string().describe("衍生资产名称"),
desc: z.string().describe("衍生资产描述"), desc: z.string().describe("衍生资产描述"),
src: z.string().describe("衍生资产资源路径"), src: z.string().nullable().describe("衍生资产资源路径"),
state: z.enum(["未生成", "生成中", "已完成", "生成失败"]).describe("衍生资产生成状态"), state: z.enum(["未生成", "生成中", "已完成", "生成失败"]).describe("衍生资产生成状态"),
type: z.enum(["role", "tool", "scene", "clip"]).describe("衍生资产类型"), type: z.enum(["role", "tool", "scene", "clip"]).describe("衍生资产类型"),
}); });
@ -168,7 +168,6 @@ export default (resTool: ResTool, toolsNames?: string[]) => {
describe: sub.desc, describe: sub.desc,
startTime: Date.now(), startTime: Date.now(),
}); });
console.log("%c Line:141 🍑 resTool.data.scriptId", "background:#ea7e5c", resTool.data.scriptId);
await u.db("o_scriptAssets").insert({ await u.db("o_scriptAssets").insert({
scriptId: resTool.data.scriptId, scriptId: resTool.data.scriptId,
assetId: insertedId, assetId: insertedId,

View File

@ -1,4 +1,4 @@
// @routes-hash 074af9af2c664d3497c2c676a3423399 // @routes-hash bf3c43509342cfaa6f58c3551570331d
import { Express } from "express"; import { Express } from "express";
import route1 from "./routes/agents/clearMemory"; import route1 from "./routes/agents/clearMemory";
@ -40,10 +40,10 @@ import route36 from "./routes/novel/updateNovel";
import route37 from "./routes/other/deleteAllData"; import route37 from "./routes/other/deleteAllData";
import route38 from "./routes/other/getCaptcha"; import route38 from "./routes/other/getCaptcha";
import route39 from "./routes/production/assets/getAssetsData"; import route39 from "./routes/production/assets/getAssetsData";
import route40 from "./routes/production/editStoryboard/generateStoryboardImage"; import route40 from "./routes/production/editImage/generateFlowImage";
import route41 from "./routes/production/editStoryboard/getStoryboardFlow"; import route41 from "./routes/production/editImage/getImageFlow";
import route42 from "./routes/production/editStoryboard/saveStoryboardFlow"; import route42 from "./routes/production/editImage/saveImageFlow";
import route43 from "./routes/production/editStoryboard/updateStoryboardFlow"; import route43 from "./routes/production/editImage/updateImageFlow";
import route44 from "./routes/production/exportImage"; import route44 from "./routes/production/exportImage";
import route45 from "./routes/production/getFlowData"; import route45 from "./routes/production/getFlowData";
import route46 from "./routes/production/getProductionData"; import route46 from "./routes/production/getProductionData";
@ -126,10 +126,10 @@ export default async (app: Express) => {
app.use("/api/other/deleteAllData", route37); app.use("/api/other/deleteAllData", route37);
app.use("/api/other/getCaptcha", route38); app.use("/api/other/getCaptcha", route38);
app.use("/api/production/assets/getAssetsData", route39); app.use("/api/production/assets/getAssetsData", route39);
app.use("/api/production/editStoryboard/generateStoryboardImage", route40); app.use("/api/production/editImage/generateFlowImage", route40);
app.use("/api/production/editStoryboard/getStoryboardFlow", route41); app.use("/api/production/editImage/getImageFlow", route41);
app.use("/api/production/editStoryboard/saveStoryboardFlow", route42); app.use("/api/production/editImage/saveImageFlow", route42);
app.use("/api/production/editStoryboard/updateStoryboardFlow", route43); app.use("/api/production/editImage/updateImageFlow", route43);
app.use("/api/production/exportImage", route44); app.use("/api/production/exportImage", route44);
app.use("/api/production/getFlowData", route45); app.use("/api/production/getFlowData", route45);
app.use("/api/production/getProductionData", route46); app.use("/api/production/getProductionData", route46);

View File

@ -78,9 +78,10 @@ export default router.post(
ratio: z.string(), ratio: z.string(),
prompt: z.string(), prompt: z.string(),
projectId: z.number(), projectId: z.number(),
type: z.enum(["role", "scene", "storyboard", "clip", "tool"]),
}), }),
async (req, res) => { async (req, res) => {
const { model, references = {}, quality, ratio, prompt, projectId } = req.body; const { model, references = {}, quality, ratio, prompt, projectId, type } = req.body;
const { prompt: userPrompt, images: base64Images } = await convertDirectiveAndImages(references, prompt); const { prompt: userPrompt, images: base64Images } = await convertDirectiveAndImages(references, prompt);
const imageClass = await u.Ai.Image(model).run({ const imageClass = await u.Ai.Image(model).run({
prompt: userPrompt, prompt: userPrompt,
@ -92,7 +93,7 @@ export default router.post(
relatedObjects: JSON.stringify(req.body), relatedObjects: JSON.stringify(req.body),
projectId: projectId, projectId: projectId,
}); });
const savePath = `${projectId}/storyboard/${u.uuid()}.jpg`; const savePath = `${projectId}/${type}/${u.uuid()}.jpg`;
await imageClass.save(savePath); await imageClass.save(savePath);
const url = await u.oss.getFileUrl(savePath); const url = await u.oss.getFileUrl(savePath);

View File

@ -9,22 +9,22 @@ export default router.post(
"/", "/",
validateFields({ validateFields({
id: z.number(), id: z.number(),
type: z.enum(["assets", "storyboard"]), type: z.enum(["role", "scene", "storyboard", "clip", "tool"]),
}), }),
async (req, res) => { async (req, res) => {
const { id, type } = req.body; const { id, type } = req.body;
const storyboardFlowData = await u const imageFlowData = await u
.db("o_imageFlow") .db("o_imageFlow")
.modify((qb) => { .modify((qb) => {
if (type === "assets") { if (type === "storyboard") {
qb.where("assetsId", id);
} else if (type === "storyboard") {
qb.where("storyboardId", id); qb.where("storyboardId", id);
} else {
qb.where("assetsId", id);
} }
}) })
.first(); .first();
if (storyboardFlowData?.flowData) { if (imageFlowData?.flowData) {
const parseFlow = JSON.parse(storyboardFlowData.flowData); const parseFlow = JSON.parse(imageFlowData.flowData);
await Promise.all( await Promise.all(
parseFlow.nodes.map(async (node: any) => { parseFlow.nodes.map(async (node: any) => {
if (node.type === "upload") { if (node.type === "upload") {
@ -34,7 +34,7 @@ export default router.post(
} }
}), }),
); );
return res.status(200).send(success(parseFlow)); return res.status(200).send(success({ ...parseFlow, id: imageFlowData.id }));
} }
return res.status(200).send(success(null)); return res.status(200).send(success(null));

View File

@ -0,0 +1,71 @@
import express from "express";
import u from "@/utils";
import { z } from "zod";
import { success } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware";
const router = express.Router();
export default router.post(
"/",
validateFields({
edges: z.any(),
nodes: z.any(),
imageUrl: z.string(),
id: z.number().nullable().optional(),
type: z.enum(["role", "scene", "storyboard", "clip", "tool"]),
}),
async (req, res) => {
const { edges, nodes, imageUrl, id, type } = req.body;
let imagePath = "";
try {
imagePath = new URL(imageUrl).pathname;
} catch (e) {}
nodes.forEach((node: any) => {
if (node.type == "upload") {
try {
node.data.image = new URL(node.data.image).pathname;
} catch (e) {
node.data.image = "";
}
}
if (node.type == "generated") {
try {
node.data.generatedImage = new URL(node.data.generatedImage).pathname;
} catch (e) {
node.data.generatedImage = "";
}
}
});
let insertFlowId;
if (imagePath) {
if (id) {
if (type == "storyboard") {
await u.db("o_storyboard").where("id", id).update({
filePath: imagePath,
});
} else {
const [imageId] = await u.db("o_image").insert({
filePath: imagePath,
assetsId: id,
state: "已完成",
});
await u.db("o_assets").where("id", id).update({ imageId });
}
insertFlowId = id;
} else {
const [storyboardId] = await u.db("o_storyboard").insert({
filePath: imagePath,
createTime: Date.now(),
});
insertFlowId = storyboardId;
}
}
await u.db("o_imageFlow").insert({
flowData: JSON.stringify({ edges, nodes }),
...(type == "assets" ? { assetsId: insertFlowId } : { storyboardId: insertFlowId }),
});
return res.status(200).send(success());
},
);

View File

@ -1,38 +0,0 @@
import express from "express";
import u from "@/utils";
import { z } from "zod";
import { success } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware";
const router = express.Router();
export default router.post(
"/",
validateFields({
edges: z.any(),
nodes: z.any(),
imageUrl: z.string(),
}),
async (req, res) => {
const { edges, nodes, imageUrl } = req.body;
if (!imageUrl.includes("http")) {
return res.status(400).send({ message: "图片地址不合法" });
}
nodes.forEach((node: any) => {
if (node.type == "upload") {
node.data.image = node.data.image ? new URL(node.data.image).pathname : "";
}
if (node.type == "generated") {
node.data.generatedImage = node.data.generatedImage ? new URL(node.data.generatedImage).pathname : "";
}
});
const [id] = await u.db("o_storyboard").insert({
filePath: new URL(imageUrl).pathname,
createTime: Date.now(),
});
await u.db("o_imageFlow").insert({
storyboardId: id,
flowData: JSON.stringify({ edges, nodes }),
});
return res.status(200).send(success());
},
);

View File

@ -12,12 +12,11 @@ export default router.post(
nodes: z.any(), nodes: z.any(),
id: z.number(), id: z.number(),
imageUrl: z.string(), imageUrl: z.string(),
type: z.enum(["role", "scene", "storyboard", "clip", "tool"]),
flowId: z.number(),
}), }),
async (req, res) => { async (req, res) => {
const { edges, nodes, id, imageUrl } = req.body; const { edges, nodes, id, imageUrl, flowId, type } = req.body;
if (!imageUrl.includes("http")) {
return res.status(400).send({ message: "图片地址不合法" });
}
nodes.forEach((node: any) => { nodes.forEach((node: any) => {
if (node.type == "upload") { if (node.type == "upload") {
node.data.image = node.data.image ? new URL(node.data.image).pathname : ""; node.data.image = node.data.image ? new URL(node.data.image).pathname : "";
@ -26,13 +25,29 @@ export default router.post(
node.data.generatedImage = node.data.generatedImage ? new URL(node.data.generatedImage).pathname : ""; node.data.generatedImage = node.data.generatedImage ? new URL(node.data.generatedImage).pathname : "";
} }
}); });
await u let imagePath = "";
.db("o_storyboard") try {
.where("id", id) imagePath = new URL(imageUrl).pathname;
.update({ filePath: new URL(imageUrl).pathname }); } catch (e) {}
if (imagePath) {
console.log("%c Line:34 🍰", "background:#33a5ff");
if (type == "storyboard") {
await u.db("o_storyboard").where("id", id).update({
filePath: imagePath,
});
} else {
const [imageId] = await u.db("o_image").insert({
filePath: imagePath,
assetsId: id,
state: "已完成",
});
await u.db("o_assets").where("id", id).update({ imageId });
}
}
await u await u
.db("o_imageFlow") .db("o_imageFlow")
.where("storyboardId", id) .where("id", flowId)
.update({ .update({
flowData: JSON.stringify({ edges, nodes }), flowData: JSON.stringify({ edges, nodes }),
}); });