diff --git a/data/skills/art_prompts/chinese_sweet_romance/images/2b1cb9c6-54f9-4e19-bf15-b546c80147bc.jpg b/data/skills/art_prompts/chinese_sweet_romance/images/2b1cb9c6-54f9-4e19-bf15-b546c80147bc.jpg new file mode 100644 index 0000000..1f5ad89 Binary files /dev/null and b/data/skills/art_prompts/chinese_sweet_romance/images/2b1cb9c6-54f9-4e19-bf15-b546c80147bc.jpg differ diff --git a/data/skills/art_prompts/chinese_sweet_romance/images/b5bd58ee-c304-477f-9c18-b40f814a5901.jpg b/data/skills/art_prompts/chinese_sweet_romance/images/b5bd58ee-c304-477f-9c18-b40f814a5901.jpg new file mode 100644 index 0000000..9ec69a9 Binary files /dev/null and b/data/skills/art_prompts/chinese_sweet_romance/images/b5bd58ee-c304-477f-9c18-b40f814a5901.jpg differ diff --git a/data/skills/art_prompts/chinese_sweet_romance/images/e4b20248-54f1-4e63-ab2d-cb72cd1886b8.jpg b/data/skills/art_prompts/chinese_sweet_romance/images/e4b20248-54f1-4e63-ab2d-cb72cd1886b8.jpg new file mode 100644 index 0000000..1f5ad89 Binary files /dev/null and b/data/skills/art_prompts/chinese_sweet_romance/images/e4b20248-54f1-4e63-ab2d-cb72cd1886b8.jpg differ diff --git a/data/skills/art_prompts/chinese_sweet_romance/images/f0f89ce4-b197-4bd6-9794-3d14d1c3ab1e.jpg b/data/skills/art_prompts/chinese_sweet_romance/images/f0f89ce4-b197-4bd6-9794-3d14d1c3ab1e.jpg new file mode 100644 index 0000000..9ec69a9 Binary files /dev/null and b/data/skills/art_prompts/chinese_sweet_romance/images/f0f89ce4-b197-4bd6-9794-3d14d1c3ab1e.jpg differ diff --git a/src/app.ts b/src/app.ts index 280cb98..cffa3c5 100644 --- a/src/app.ts +++ b/src/app.ts @@ -12,6 +12,7 @@ import fs from "fs"; import u from "@/utils"; import jwt from "jsonwebtoken"; import socketInit from "@/socket/index"; +import path from "path"; const app = express(); const server = http.createServer(app); @@ -29,14 +30,28 @@ export default async function startServe(randomPort: Boolean = false) { app.use(express.json({ limit: "100mb" })); app.use(express.urlencoded({ extended: true, limit: "100mb" })); - // oss 静态资源 - const rootDir = u.getPath("oss"); - if (!fs.existsSync(rootDir)) { - fs.mkdirSync(rootDir, { recursive: true }); + const ossDir = u.getPath("oss"); + if (!fs.existsSync(ossDir)) { + fs.mkdirSync(ossDir, { recursive: true }); } - console.log("文件目录:", rootDir); - app.use(express.static(rootDir)); + console.log("文件目录:", ossDir); + app.use("/oss", express.static(ossDir)); + // skills 静态资源 + + const skillsDir = u.getPath("skills"); + if (!fs.existsSync(skillsDir)) { + fs.mkdirSync(skillsDir, { recursive: true }); + } + console.log("文件目录:", skillsDir); + // 只允许图片文件访问 + app.use( + "/skills", + (req, res, next) => { + /\.(jpe?g|png|gif|webp|svg|ico|bmp)$/i.test(req.path) ? next() : res.status(403).end(); + }, + express.static(skillsDir), + ); // data/web 静态网站 const webDir = u.getPath("web"); diff --git a/src/env.ts b/src/env.ts index e733138..d1af1b4 100644 --- a/src/env.ts +++ b/src/env.ts @@ -3,8 +3,8 @@ import path from "path"; // 默认环境变量(当 env 文件不存在时自动创建) const defaultEnvValues: Record = { - dev: `NODE_ENV=dev\nPORT=10588\nOSSURL=http://127.0.0.1:10588/`, - prod: `NODE_ENV=prod\nPORT=10588\nOSSURL=http://127.0.0.1:10588/`, + dev: `NODE_ENV=dev\nPORT=10588\nOSSURL=http://127.0.0.1:10588/oss/`, + prod: `NODE_ENV=prod\nPORT=10588\nOSSURL=http://127.0.0.1:10588/oss/`, }; // 判断是否为打包后的 Electron 环境 diff --git a/src/router.ts b/src/router.ts index c7cd0b2..8469a27 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,4 +1,4 @@ -// @routes-hash 3d1d48934f908135efd71196a7205556 +// @routes-hash 6b77c26005a9993d80cda7ab95d26702 import { Express } from "express"; import route1 from "./routes/agents/clearMemory"; @@ -70,66 +70,67 @@ import route66 from "./routes/production/storyboard/previewImage"; import route67 from "./routes/production/storyboard/removeFrame"; import route68 from "./routes/production/storyboard/updateStoryboardUrl"; import route69 from "./routes/production/workbench/addTrack"; -import route70 from "./routes/production/workbench/delVideo"; -import route71 from "./routes/production/workbench/generateVideo"; -import route72 from "./routes/production/workbench/generateVideoPrompt"; -import route73 from "./routes/production/workbench/getGenerateData"; -import route74 from "./routes/production/workbench/getVideoList"; -import route75 from "./routes/production/workbench/getVideoModelDetail"; -import route76 from "./routes/production/workbench/selectVideo"; -import route77 from "./routes/project/addProject"; -import route78 from "./routes/project/addVisual"; -import route79 from "./routes/project/addVisualManual"; -import route80 from "./routes/project/deleteVisualManual"; -import route81 from "./routes/project/delProject"; -import route82 from "./routes/project/editProject"; -import route83 from "./routes/project/editVisualManual"; -import route84 from "./routes/project/getProject"; -import route85 from "./routes/project/getVisualManual"; -import route86 from "./routes/project/visualManual"; -import route87 from "./routes/script/addScript"; -import route88 from "./routes/script/delScript"; -import route89 from "./routes/script/exportScript"; -import route90 from "./routes/script/extractAssets"; -import route91 from "./routes/script/getScrptApi"; -import route92 from "./routes/script/pollScriptAssets"; -import route93 from "./routes/script/updateScript"; -import route94 from "./routes/scriptAgent/getPlanData"; -import route95 from "./routes/scriptAgent/setPlanData"; -import route96 from "./routes/scriptAgent/updateData"; -import route97 from "./routes/setting/about/checkUpdate"; -import route98 from "./routes/setting/about/downloadApp"; -import route99 from "./routes/setting/agentDeploy/agentSetKey"; -import route100 from "./routes/setting/agentDeploy/deployAgentModel"; -import route101 from "./routes/setting/agentDeploy/getAgentDeploy"; -import route102 from "./routes/setting/dbConfig/clearData"; -import route103 from "./routes/setting/dev/getSwitchAiDevTool"; -import route104 from "./routes/setting/dev/updateSwitchAiDevTool"; -import route105 from "./routes/setting/fileManagement/openFolder"; -import route106 from "./routes/setting/getTextModel"; -import route107 from "./routes/setting/loginConfig/getUser"; -import route108 from "./routes/setting/loginConfig/updateUserPwd"; -import route109 from "./routes/setting/memoryConfig/delAllMemory"; -import route110 from "./routes/setting/memoryConfig/getMemory"; -import route111 from "./routes/setting/memoryConfig/sureMemory"; -import route112 from "./routes/setting/promptManage/getPrompt"; -import route113 from "./routes/setting/promptManage/updatePrompt"; -import route114 from "./routes/setting/skillManagement/getSkillContent"; -import route115 from "./routes/setting/skillManagement/getSkillList"; -import route116 from "./routes/setting/skillManagement/saveSkillContent"; -import route117 from "./routes/setting/vendorConfig/addVendor"; -import route118 from "./routes/setting/vendorConfig/deleteVendor"; -import route119 from "./routes/setting/vendorConfig/enableEnglishVendor"; -import route120 from "./routes/setting/vendorConfig/getCodeByLink"; -import route121 from "./routes/setting/vendorConfig/getVendorList"; -import route122 from "./routes/setting/vendorConfig/modelTest"; -import route123 from "./routes/setting/vendorConfig/updateCode"; -import route124 from "./routes/setting/vendorConfig/updateVendor"; -import route125 from "./routes/task/getProject"; -import route126 from "./routes/task/getTaskApi"; -import route127 from "./routes/task/getTaskCategories"; -import route128 from "./routes/task/taskDetails"; -import route129 from "./routes/test/test"; +import route70 from "./routes/production/workbench/deleteTrack"; +import route71 from "./routes/production/workbench/delVideo"; +import route72 from "./routes/production/workbench/generateVideo"; +import route73 from "./routes/production/workbench/generateVideoPrompt"; +import route74 from "./routes/production/workbench/getGenerateData"; +import route75 from "./routes/production/workbench/getVideoList"; +import route76 from "./routes/production/workbench/getVideoModelDetail"; +import route77 from "./routes/production/workbench/selectVideo"; +import route78 from "./routes/project/addProject"; +import route79 from "./routes/project/addVisual"; +import route80 from "./routes/project/addVisualManual"; +import route81 from "./routes/project/deleteVisualManual"; +import route82 from "./routes/project/delProject"; +import route83 from "./routes/project/editProject"; +import route84 from "./routes/project/editVisualManual"; +import route85 from "./routes/project/getProject"; +import route86 from "./routes/project/getVisualManual"; +import route87 from "./routes/project/visualManual"; +import route88 from "./routes/script/addScript"; +import route89 from "./routes/script/delScript"; +import route90 from "./routes/script/exportScript"; +import route91 from "./routes/script/extractAssets"; +import route92 from "./routes/script/getScrptApi"; +import route93 from "./routes/script/pollScriptAssets"; +import route94 from "./routes/script/updateScript"; +import route95 from "./routes/scriptAgent/getPlanData"; +import route96 from "./routes/scriptAgent/setPlanData"; +import route97 from "./routes/scriptAgent/updateData"; +import route98 from "./routes/setting/about/checkUpdate"; +import route99 from "./routes/setting/about/downloadApp"; +import route100 from "./routes/setting/agentDeploy/agentSetKey"; +import route101 from "./routes/setting/agentDeploy/deployAgentModel"; +import route102 from "./routes/setting/agentDeploy/getAgentDeploy"; +import route103 from "./routes/setting/dbConfig/clearData"; +import route104 from "./routes/setting/dev/getSwitchAiDevTool"; +import route105 from "./routes/setting/dev/updateSwitchAiDevTool"; +import route106 from "./routes/setting/fileManagement/openFolder"; +import route107 from "./routes/setting/getTextModel"; +import route108 from "./routes/setting/loginConfig/getUser"; +import route109 from "./routes/setting/loginConfig/updateUserPwd"; +import route110 from "./routes/setting/memoryConfig/delAllMemory"; +import route111 from "./routes/setting/memoryConfig/getMemory"; +import route112 from "./routes/setting/memoryConfig/sureMemory"; +import route113 from "./routes/setting/promptManage/getPrompt"; +import route114 from "./routes/setting/promptManage/updatePrompt"; +import route115 from "./routes/setting/skillManagement/getSkillContent"; +import route116 from "./routes/setting/skillManagement/getSkillList"; +import route117 from "./routes/setting/skillManagement/saveSkillContent"; +import route118 from "./routes/setting/vendorConfig/addVendor"; +import route119 from "./routes/setting/vendorConfig/deleteVendor"; +import route120 from "./routes/setting/vendorConfig/enableEnglishVendor"; +import route121 from "./routes/setting/vendorConfig/getCodeByLink"; +import route122 from "./routes/setting/vendorConfig/getVendorList"; +import route123 from "./routes/setting/vendorConfig/modelTest"; +import route124 from "./routes/setting/vendorConfig/updateCode"; +import route125 from "./routes/setting/vendorConfig/updateVendor"; +import route126 from "./routes/task/getProject"; +import route127 from "./routes/task/getTaskApi"; +import route128 from "./routes/task/getTaskCategories"; +import route129 from "./routes/task/taskDetails"; +import route130 from "./routes/test/test"; export default async (app: Express) => { app.use("/api/agents/clearMemory", route1); @@ -201,64 +202,65 @@ export default async (app: Express) => { app.use("/api/production/storyboard/removeFrame", route67); app.use("/api/production/storyboard/updateStoryboardUrl", route68); app.use("/api/production/workbench/addTrack", route69); - app.use("/api/production/workbench/delVideo", route70); - app.use("/api/production/workbench/generateVideo", route71); - app.use("/api/production/workbench/generateVideoPrompt", route72); - app.use("/api/production/workbench/getGenerateData", route73); - app.use("/api/production/workbench/getVideoList", route74); - app.use("/api/production/workbench/getVideoModelDetail", route75); - app.use("/api/production/workbench/selectVideo", route76); - app.use("/api/project/addProject", route77); - app.use("/api/project/addVisual", route78); - app.use("/api/project/addVisualManual", route79); - app.use("/api/project/deleteVisualManual", route80); - app.use("/api/project/delProject", route81); - app.use("/api/project/editProject", route82); - app.use("/api/project/editVisualManual", route83); - app.use("/api/project/getProject", route84); - app.use("/api/project/getVisualManual", route85); - app.use("/api/project/visualManual", route86); - app.use("/api/script/addScript", route87); - app.use("/api/script/delScript", route88); - app.use("/api/script/exportScript", route89); - app.use("/api/script/extractAssets", route90); - app.use("/api/script/getScrptApi", route91); - app.use("/api/script/pollScriptAssets", route92); - app.use("/api/script/updateScript", route93); - app.use("/api/scriptAgent/getPlanData", route94); - app.use("/api/scriptAgent/setPlanData", route95); - app.use("/api/scriptAgent/updateData", route96); - app.use("/api/setting/about/checkUpdate", route97); - app.use("/api/setting/about/downloadApp", route98); - app.use("/api/setting/agentDeploy/agentSetKey", route99); - app.use("/api/setting/agentDeploy/deployAgentModel", route100); - app.use("/api/setting/agentDeploy/getAgentDeploy", route101); - app.use("/api/setting/dbConfig/clearData", route102); - app.use("/api/setting/dev/getSwitchAiDevTool", route103); - app.use("/api/setting/dev/updateSwitchAiDevTool", route104); - app.use("/api/setting/fileManagement/openFolder", route105); - app.use("/api/setting/getTextModel", route106); - app.use("/api/setting/loginConfig/getUser", route107); - app.use("/api/setting/loginConfig/updateUserPwd", route108); - app.use("/api/setting/memoryConfig/delAllMemory", route109); - app.use("/api/setting/memoryConfig/getMemory", route110); - app.use("/api/setting/memoryConfig/sureMemory", route111); - app.use("/api/setting/promptManage/getPrompt", route112); - app.use("/api/setting/promptManage/updatePrompt", route113); - app.use("/api/setting/skillManagement/getSkillContent", route114); - app.use("/api/setting/skillManagement/getSkillList", route115); - app.use("/api/setting/skillManagement/saveSkillContent", route116); - app.use("/api/setting/vendorConfig/addVendor", route117); - app.use("/api/setting/vendorConfig/deleteVendor", route118); - app.use("/api/setting/vendorConfig/enableEnglishVendor", route119); - app.use("/api/setting/vendorConfig/getCodeByLink", route120); - app.use("/api/setting/vendorConfig/getVendorList", route121); - app.use("/api/setting/vendorConfig/modelTest", route122); - app.use("/api/setting/vendorConfig/updateCode", route123); - app.use("/api/setting/vendorConfig/updateVendor", route124); - app.use("/api/task/getProject", route125); - app.use("/api/task/getTaskApi", route126); - app.use("/api/task/getTaskCategories", route127); - app.use("/api/task/taskDetails", route128); - app.use("/api/test/test", route129); + app.use("/api/production/workbench/deleteTrack", route70); + app.use("/api/production/workbench/delVideo", route71); + app.use("/api/production/workbench/generateVideo", route72); + app.use("/api/production/workbench/generateVideoPrompt", route73); + app.use("/api/production/workbench/getGenerateData", route74); + app.use("/api/production/workbench/getVideoList", route75); + app.use("/api/production/workbench/getVideoModelDetail", route76); + app.use("/api/production/workbench/selectVideo", route77); + app.use("/api/project/addProject", route78); + app.use("/api/project/addVisual", route79); + app.use("/api/project/addVisualManual", route80); + app.use("/api/project/deleteVisualManual", route81); + app.use("/api/project/delProject", route82); + app.use("/api/project/editProject", route83); + app.use("/api/project/editVisualManual", route84); + app.use("/api/project/getProject", route85); + app.use("/api/project/getVisualManual", route86); + app.use("/api/project/visualManual", route87); + app.use("/api/script/addScript", route88); + app.use("/api/script/delScript", route89); + app.use("/api/script/exportScript", route90); + app.use("/api/script/extractAssets", route91); + app.use("/api/script/getScrptApi", route92); + app.use("/api/script/pollScriptAssets", route93); + app.use("/api/script/updateScript", route94); + app.use("/api/scriptAgent/getPlanData", route95); + app.use("/api/scriptAgent/setPlanData", route96); + app.use("/api/scriptAgent/updateData", route97); + app.use("/api/setting/about/checkUpdate", route98); + app.use("/api/setting/about/downloadApp", route99); + app.use("/api/setting/agentDeploy/agentSetKey", route100); + app.use("/api/setting/agentDeploy/deployAgentModel", route101); + app.use("/api/setting/agentDeploy/getAgentDeploy", route102); + app.use("/api/setting/dbConfig/clearData", route103); + app.use("/api/setting/dev/getSwitchAiDevTool", route104); + app.use("/api/setting/dev/updateSwitchAiDevTool", route105); + app.use("/api/setting/fileManagement/openFolder", route106); + app.use("/api/setting/getTextModel", route107); + app.use("/api/setting/loginConfig/getUser", route108); + app.use("/api/setting/loginConfig/updateUserPwd", route109); + app.use("/api/setting/memoryConfig/delAllMemory", route110); + app.use("/api/setting/memoryConfig/getMemory", route111); + app.use("/api/setting/memoryConfig/sureMemory", route112); + app.use("/api/setting/promptManage/getPrompt", route113); + app.use("/api/setting/promptManage/updatePrompt", route114); + app.use("/api/setting/skillManagement/getSkillContent", route115); + app.use("/api/setting/skillManagement/getSkillList", route116); + app.use("/api/setting/skillManagement/saveSkillContent", route117); + app.use("/api/setting/vendorConfig/addVendor", route118); + app.use("/api/setting/vendorConfig/deleteVendor", route119); + app.use("/api/setting/vendorConfig/enableEnglishVendor", route120); + app.use("/api/setting/vendorConfig/getCodeByLink", route121); + app.use("/api/setting/vendorConfig/getVendorList", route122); + app.use("/api/setting/vendorConfig/modelTest", route123); + app.use("/api/setting/vendorConfig/updateCode", route124); + app.use("/api/setting/vendorConfig/updateVendor", route125); + app.use("/api/task/getProject", route126); + app.use("/api/task/getTaskApi", route127); + app.use("/api/task/getTaskCategories", route128); + app.use("/api/task/taskDetails", route129); + app.use("/api/test/test", route130); } diff --git a/src/routes/assetsGenerate/batchPolishAssetsPrompt.ts b/src/routes/assetsGenerate/batchPolishAssetsPrompt.ts index 72c9c07..79a375a 100644 --- a/src/routes/assetsGenerate/batchPolishAssetsPrompt.ts +++ b/src/routes/assetsGenerate/batchPolishAssetsPrompt.ts @@ -83,21 +83,47 @@ export default router.post( }); }); const result: ResultItem[] = Object.values(itemMap); - - const typeConfig: Record = { - 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" }, - }; // 批量更新所有 item 状态为生成中 const assetsIds = items.map((item: { assetsId: number }) => item.assetsId); await u.db("o_assets").whereIn("id", assetsIds).update({ promptState: "生成中" }); + //查询所有资产,用于判断每个资产是否是衍生资产 + const assetsDataList = await u.db("o_assets").whereIn("id", assetsIds).select("id", "assetsId"); + if (!assetsDataList || assetsDataList.length === 0) return res.status(500).send(error("资产不存在")); + const assetsDataMap = new Map(assetsDataList.map((a: any) => [a.id, a])); + + const getTypeConfig = ( + isDerivative: boolean, + ): Record => ({ + role: { + promptKey: "role-polish", + itemType: "characters", + label: "角色标准四视图", + nameLabel: "角色", + visualManual: isDerivative ? "art_character_derivative" : "art_character", + }, + scene: { + promptKey: "scene-polish", + itemType: "scenes", + label: "场景图", + nameLabel: "场景", + visualManual: isDerivative ? "art_scene_derivative" : "art_scene", + }, + tool: { + promptKey: "tool-polish", + itemType: "props", + label: "道具图", + nameLabel: "道具", + visualManual: isDerivative ? "art_prop_derivative" : "art_prop", + }, + }); // 后台异步并发生成,不阻塞响应 const limit = pLimit(concurrentCount ?? 1); - const tasks = items.map((item: { assetsId: number; type: string; name: string; describe: string }) => limit(async () => { + const assetData = assetsDataMap.get(item.assetsId); + if (!assetData) return; + const typeConfig = getTypeConfig(!!assetData.assetsId); const config = typeConfig[item.type]; if (!config) return; //获取到视觉手册 diff --git a/src/routes/assetsGenerate/polishAssetsPrompt.ts b/src/routes/assetsGenerate/polishAssetsPrompt.ts index 438af1e..ee96a7d 100644 --- a/src/routes/assetsGenerate/polishAssetsPrompt.ts +++ b/src/routes/assetsGenerate/polishAssetsPrompt.ts @@ -76,11 +76,31 @@ export default router.post( }); const result: ResultItem[] = Object.values(itemMap); - + //查询资产是否是衍生资产 + const assetsData = await u.db("o_assets").where("id", assetsId).select("assetsId").first(); + if (!assetsData) return { code: 500, message: "资产不存在" }; const typeConfig: Record = { - 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" }, + role: { + promptKey: "role-polish", + itemType: "characters", + label: "角色标准四视图", + nameLabel: "角色", + visualManual: assetsData.assetsId ? "art_character_derivative" : "art_character", + }, + scene: { + promptKey: "scene-polish", + itemType: "scenes", + label: "场景图", + nameLabel: "场景", + visualManual: assetsData.assetsId ? "art_scene_derivative" : "art_scene", + }, + tool: { + promptKey: "tool-polish", + itemType: "props", + label: "道具图", + nameLabel: "道具", + visualManual: assetsData.assetsId ? "art_prop_derivative" : "art_prop", + }, }; const config = typeConfig[type]; diff --git a/src/routes/production/workbench/delVideo.ts b/src/routes/production/workbench/delVideo.ts index dd440cc..4b87855 100644 --- a/src/routes/production/workbench/delVideo.ts +++ b/src/routes/production/workbench/delVideo.ts @@ -8,12 +8,11 @@ const router = express.Router(); export default router.post( "/", validateFields({ - videoId: z.number(), + id: z.number(), }), async (req, res) => { - const { videoId } = req.body; - await u.db("o_video").where("id", videoId).delete(); - await u.db("o_videoConfig").where("videoId", videoId).update({ videoId: null, updateTime: Date.now() }); + const { id } = req.body; + await u.db("o_video").where("id", id).delete(); res.status(200).send(success({ message: "视频删除成功" })); }, ); diff --git a/src/routes/production/workbench/deleteTrack.ts b/src/routes/production/workbench/deleteTrack.ts new file mode 100644 index 0000000..5541175 --- /dev/null +++ b/src/routes/production/workbench/deleteTrack.ts @@ -0,0 +1,19 @@ +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({ + id: z.number(), + }), + async (req, res) => { + const { id } = req.body; + await u.db("o_videoTrack").where("id", id).delete(); + await u.db("o_storyboard").where("trackId", id).delete(); + res.status(200).send(success({ message: "视频段删除成功" })); + }, +); diff --git a/src/routes/production/workbench/getGenerateData.ts b/src/routes/production/workbench/getGenerateData.ts index b69f2d2..0a18465 100644 --- a/src/routes/production/workbench/getGenerateData.ts +++ b/src/routes/production/workbench/getGenerateData.ts @@ -23,6 +23,7 @@ interface TrackItem { prompt: string; state: "未生成" | "生成中" | "已完成" | "生成失败"; reason?: string; + duration?: number; selectVideoId?: number; medias: TrackMedia[]; videoList: VideoItem[]; @@ -53,6 +54,7 @@ export default router.post( const item = trackData.find((t) => t.id === trackId); trackList.push({ id: trackId, + duration: item?.duration ?? 0, prompt: item?.prompt || "", state: (item?.state as "未生成" | "生成中" | "已完成" | "生成失败") ?? "未生成", reason: item?.reason ?? "", diff --git a/src/routes/project/addVisualManual.ts b/src/routes/project/addVisualManual.ts index 434ed67..e8550fd 100644 --- a/src/routes/project/addVisualManual.ts +++ b/src/routes/project/addVisualManual.ts @@ -76,11 +76,11 @@ export default router.post( } fs.writeFileSync(filePath, item.data, "utf-8"); } - const ossImagesDir = u.getPath(["oss", stylePath]); + const imagesDir = path.join(mainPath, "images"); let existingFiles: string[] = []; try { - const allFiles = fs.readdirSync(ossImagesDir); + const allFiles = fs.readdirSync(imagesDir); existingFiles = allFiles.filter((f) => /\.(png|jpe?g|gif|webp|svg)$/i.test(f)); } catch {} @@ -88,12 +88,22 @@ export default router.post( for (const file of existingFiles) { if (!retainedFileNames.has(file)) { - await u.oss.deleteFile(`${stylePath}/${file}`); + const filePath = path.join(imagesDir, file); + if (fs.existsSync(filePath)) fs.unlinkSync(filePath); } } + if (!fs.existsSync(imagesDir)) { + fs.mkdirSync(imagesDir, { recursive: true }); + } + for (const item of images) { - if (!item.startsWith("http")) await u.oss.writeFile(`${stylePath}/${u.uuid()}.jpg`, item); + if (!item.startsWith("http")) { + const fileName = `${u.uuid()}.jpg`; + const targetPath = path.join(imagesDir, fileName); + const buffer = Buffer.from(item.replace(/^data:[^;]+;base64,/, ""), "base64"); + fs.writeFileSync(targetPath, buffer); + } } res.status(200).send(success()); diff --git a/src/routes/project/deleteVisualManual.ts b/src/routes/project/deleteVisualManual.ts index 5d35333..b0a1244 100644 --- a/src/routes/project/deleteVisualManual.ts +++ b/src/routes/project/deleteVisualManual.ts @@ -33,14 +33,6 @@ export default router.post( } 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: "删除成功" })); } catch (err) { res.status(500).send(error(u.error(err).message || "删除失败")); diff --git a/src/routes/project/editVisualManual.ts b/src/routes/project/editVisualManual.ts index 77c7ea3..69997b0 100644 --- a/src/routes/project/editVisualManual.ts +++ b/src/routes/project/editVisualManual.ts @@ -77,11 +77,11 @@ export default router.post( const content = item.value === "README" ? `${name}\n${item.data}` : item.data; fs.writeFileSync(filePath, content, "utf-8"); } - const ossImagesDir = u.getPath(["oss", stylePath]); + const imagesDir = path.join(mainPath, "images"); let existingFiles: string[] = []; try { - const allFiles = fs.readdirSync(ossImagesDir); + const allFiles = fs.readdirSync(imagesDir); existingFiles = allFiles.filter((f) => /\.(png|jpe?g|gif|webp|svg)$/i.test(f)); } catch {} @@ -89,12 +89,22 @@ export default router.post( for (const file of existingFiles) { if (!retainedFileNames.has(file)) { - await u.oss.deleteFile(`${stylePath}/${file}`); + const filePath = path.join(imagesDir, file); + if (fs.existsSync(filePath)) fs.unlinkSync(filePath); } } + if (!fs.existsSync(imagesDir)) { + fs.mkdirSync(imagesDir, { recursive: true }); + } + for (const item of images) { - if (!item.startsWith("http")) await u.oss.writeFile(`${stylePath}/${u.uuid()}.jpg`, item); + if (!item.startsWith("http")) { + const fileName = `${u.uuid()}.jpg`; + const targetPath = path.join(imagesDir, fileName); + const buffer = Buffer.from(item.replace(/^data:[^;]+;base64,/, ""), "base64"); + fs.writeFileSync(targetPath, buffer); + } } res.status(200).send(success()); diff --git a/src/routes/project/getVisualManual.ts b/src/routes/project/getVisualManual.ts index e227418..b997b96 100644 --- a/src/routes/project/getVisualManual.ts +++ b/src/routes/project/getVisualManual.ts @@ -33,11 +33,11 @@ function readMd(filePath: string): string { // 获取 images 文件夹下所有图片文件路径列表 async function readAllImages(imagesDir: string) { try { - const ossPath = u.getPath(["oss", imagesDir]); + const ossPath = u.getPath(path.join("skills", "art_prompts", imagesDir, "images")); const files = fs.readdirSync(ossPath); - const images = files.filter((f) => /\.(png|jpe?g|gif|webp|svg)$/i.test(f)).map((f) => path.join(imagesDir, f)); + const images = files.filter((f) => /\.(png|jpe?g|gif|webp|svg)$/i.test(f)).map((f) => path.join("art_prompts", imagesDir, "images", f)); if (images.length) { - return Promise.all(images.map(async (i) => await u.oss.getFileUrl(i))); + return Promise.all(images.map(async (i) => await u.oss.getFileUrl(i, "skills"))); } else { return []; } @@ -60,7 +60,6 @@ export default router.post("/", async (req, res) => { const result = await Promise.all( styleDirs.map(async (styleName) => { const styleDir = path.join(artPromptsDir, styleName); - const images = await readAllImages(styleName); const readmePath = path.join(styleDir, "README.md"); const readmeContent = fs.readFileSync(readmePath, "utf-8"); diff --git a/src/types/database.d.ts b/src/types/database.d.ts index ecbfe71..2911895 100644 --- a/src/types/database.d.ts +++ b/src/types/database.d.ts @@ -1,26 +1,11 @@ -// @db-hash 147d0f569132c3ba4fedb17a1039d15f +// @db-hash a6017ee44d67db4a339664cfe7bacb76 //该文件由脚本自动生成,请勿手动修改 -export interface _o_storyboard_old_20260402 { - 'createTime'?: number | null; - 'duration'?: string | null; - 'filePath'?: string | null; - 'flowId'?: number | null; - 'id'?: number; - 'index'?: number | null; - 'projectId'?: number | null; - 'prompt'?: string | null; - 'reason'?: string | null; - 'scriptId'?: number | null; - 'state'?: string | null; - 'trackId'?: number | null; -} export interface _o_vendorConfig_old_20260401 { 'author'?: string | null; 'code'?: string | null; 'createTime'?: number | null; 'description'?: string | null; - 'enableEnglish'?: number | null; 'icon'?: string | null; 'id'?: string; 'inputs'?: string | null; @@ -28,7 +13,13 @@ export interface _o_vendorConfig_old_20260401 { 'models'?: string | null; 'name'?: string | null; } -export interface _o_videoTrack_old_20260402 { +export interface _o_videoTrack_old_20260401 { + 'id'?: number; + 'projectId'?: number | null; + 'scriptId'?: number | null; + 'videoId'?: number | null; +} +export interface _o_videoTrack_old_20260401_1 { 'id'?: number; 'projectId'?: number | null; 'prompt'?: string | null; @@ -210,11 +201,8 @@ export interface o_storyboard { 'prompt'?: string | null; 'reason'?: string | null; 'scriptId'?: number | null; - 'shouldGenerateImage'?: number | null; 'state'?: string | null; - 'track'?: string | null; 'trackId'?: number | null; - 'videoPrompt'?: string | null; } export interface o_tasks { 'describe'?: string | null; @@ -237,7 +225,6 @@ export interface o_vendorConfig { 'code'?: string | null; 'createTime'?: number | null; 'description'?: string | null; - 'enable'?: number | null; 'enableEnglish'?: number | null; 'icon'?: string | null; 'id'?: string; @@ -263,14 +250,15 @@ export interface o_videoTrack { 'prompt'?: string | null; 'reason'?: string | null; 'scriptId'?: number | null; + 'selectVideoId'?: number | null; 'state'?: string | null; 'videoId'?: number | null; } export interface DB { - "_o_storyboard_old_20260402": _o_storyboard_old_20260402; "_o_vendorConfig_old_20260401": _o_vendorConfig_old_20260401; - "_o_videoTrack_old_20260402": _o_videoTrack_old_20260402; + "_o_videoTrack_old_20260401": _o_videoTrack_old_20260401; + "_o_videoTrack_old_20260401_1": _o_videoTrack_old_20260401_1; "memories": memories; "o_agentDeploy": o_agentDeploy; "o_agentWorkData": o_agentWorkData; diff --git a/src/utils/oss.ts b/src/utils/oss.ts index e3e9f0c..8ae4927 100644 --- a/src/utils/oss.ts +++ b/src/utils/oss.ts @@ -45,12 +45,13 @@ class OSS { * @param userRelPath 用户传入的相对文件路径(使用 / 作为分隔符) * @returns 文件的 http 链接(本地服务地址) */ - async getFileUrl(userRelPath: string): Promise { + async getFileUrl(userRelPath: string, prefix?: string): Promise { + if (!prefix) prefix = "oss"; await this.ensureInit(); const safePath = normalizeUserPath(userRelPath); // URL 始终使用 /,所以这里需要将系统分隔符转回 / - let url = process.env.OSSURL || `http://127.0.0.1:10588/`; - if (isEletron()) url = `http://localhost:${process.env.PORT}/`; + let url = `${process.env.OSSURL}${prefix}/` || `http://127.0.0.1:10588/${prefix}/`; + if (isEletron()) url = `http://localhost:${process.env.PORT}/${prefix}/`; return `${url}${safePath.split(path.sep).join("/")}`; } @@ -146,10 +147,7 @@ class OSS { await fs.mkdir(path.dirname(absPath), { recursive: true }); // 如果 data 是 string,则视为 base64 编码,先解码再写入 // 自动去除可能存在的 Data URL 前缀(如 "data:image/png;base64,") - const buffer = - typeof data === "string" - ? Buffer.from(data.replace(/^data:[^;]+;base64,/, ""), "base64") - : data; + const buffer = typeof data === "string" ? Buffer.from(data.replace(/^data:[^;]+;base64,/, ""), "base64") : data; await fs.writeFile(absPath, buffer); }