video-flow-toon/src/lib/initDB.ts
ACT丶流星雨 6faa5c93d3 Merge branch '108' of https://github.com/HBAI-Ltd/Toonflow-app into 108
# Conflicts:
#	src/router.ts
#	src/types/database.d.ts
2026-03-24 09:50:35 +08:00

479 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Knex } from "knex";
import { v4 as uuid } from "uuid";
interface TableSchema {
name: string;
builder: (table: Knex.CreateTableBuilder) => void;
initData?: (knex: Knex) => Promise<void>;
}
export default async (knex: Knex, forceInit: boolean = false): Promise<void> => {
const tables: TableSchema[] = [
// 用户表
{
name: "o_user",
builder: (table) => {
table.integer("id").notNullable();
table.text("name");
table.text("password");
table.primary(["id"]);
table.unique(["id"]);
},
initData: async (knex) => {
await knex("o_user").insert([{ id: 1, name: "admin", password: "admin123" }]);
},
},
//项目表
{
name: "o_project",
builder: (table) => {
table.integer("id");
table.string("projectType");
table.text("name");
table.text("intro");
table.text("type");
table.text("artStyle");
table.text("videoRatio");
table.integer("createTime");
table.integer("userId");
table.primary(["id"]);
},
},
//风格表
{
name: "o_artStyle",
builder: (table) => {
table.integer("id").notNullable();
table.string("name");
table.text("styles");
table.primary(["id"]);
table.unique(["id"]);
},
initData: async (knex) => {},
},
//Agent配置表
{
name: "o_agentDeploy",
builder: (table) => {
table.integer("id").notNullable();
table.string("model");
table.string("key");
table.string("modelName");
table.integer("vendorId");
table.string("desc");
table.string("name");
table.boolean("disabled").defaultTo(false);
table.primary(["id"]);
table.unique(["id"]);
},
initData: async (knex) => {
await knex("o_agentDeploy").insert([
{
model: "",
modelName: "",
vendorId: null,
key: "scriptAgent",
name: "剧本Agent",
desc: "根据剧本自动生成分镜描述,将文字转化为画面指令",
disabled: false,
},
{
model: "",
modelName: "",
vendorId: null,
key: "productionAgent",
name: "生产Agent",
desc: "从小说原文提取关键情节,生成结构化剧本大纲",
disabled: false,
},
{
model: "",
modelName: "",
vendorId: null,
key: "assetsAgent",
name: "资产Agent",
desc: "根据角色和场景要素,生成精准的素材提示词",
disabled: false,
},
{
model: "",
modelName: "",
vendorId: null,
key: "polishingAgent",
name: "润色Agent",
desc: "将大纲扩展为完整剧本脚本,包含对话和场景描写",
disabled: false,
},
{
model: "",
modelName: "",
vendorId: null,
key: "eventExtractAgent",
name: "事件提取Agent",
desc: "从小说原文中提取事件,生成事件列表和事件关系",
disabled: false,
},
{
model: "",
modelName: "",
vendorId: null,
key: "ttsDubbing",
name: "TTS配音",
desc: "根据剧本内容生成角色配音,支持多种声音风格和情绪",
disabled: true,
},
]);
},
},
//设置表
{
name: "o_setting",
builder: (table) => {
table.text("key");
table.text("value");
table.primary(["key"]);
table.unique(["key"]);
},
initData: async (knex) => {
await knex("o_setting").insert([
{
key: "tokenKey",
value: uuid().slice(0, 8),
},
{
key: "messagesPerSummary",
value: 3,
},
{
key: "shortTermLimit",
value: 5,
},
{
key: "summaryMaxLength",
value: 500,
},
{
key: "summaryLimit",
value: 10,
},
{
key: "ragLimit",
value: 3,
},
{
key: "deepRetrieveSummaryLimit",
value: 5,
},
{
key: "modelOnnxFile",
value: '["all-MiniLM-L6-v2", "onnx", "model_fp16.onnx"]',
},
{
key: "modelDtype",
value: "fp16",
},
]);
},
},
//任务中心表
{
name: "o_tasks",
builder: (table) => {
table.integer("id").notNullable();
table.integer("projectId");
table.string("taskClass");
table.string("relatedObjects");
table.string("model");
table.text("describe");
table.string("state");
table.integer("startTime");
table.text("reason");
table.primary(["id"]);
table.unique(["id"]);
},
initData: async (knex) => {},
},
//小说原文表
{
name: "o_novel",
builder: (table) => {
table.integer("id").notNullable();
table.integer("chapterIndex");
table.text("reel");
table.text("chapter");
table.text("chapterData");
table.integer("projectId");
table.integer("eventState");
table.text("event");
table.text("errorReason");
table.integer("createTime");
table.primary(["id"]);
table.unique(["id"]);
},
},
//小说事件表
{
name: "o_event",
builder: (table) => {
table.integer("id").notNullable();
table.string("name");
table.string("detail");
table.integer("createTime");
table.primary(["id"]);
table.unique(["id"]);
},
},
//事件-章节表
{
name: "o_eventChapter",
builder: (table) => {
table.integer("id").notNullable();
table.integer("eventId").unsigned().references("id").inTable("o_event");
table.integer("novelId").unsigned().references("id").inTable("o_novel");
table.primary(["id"]);
table.unique(["id"]);
},
},
//大纲表
{
name: "o_outline",
builder: (table) => {
table.integer("id").notNullable();
table.integer("episode");
table.text("data");
table.integer("projectId");
table.primary(["id"]);
table.unique(["id"]);
},
},
//大纲-原文表
{
name: "o_outlineNovel",
builder: (table) => {
table.integer("id").notNullable();
table.integer("outlineId").unsigned().references("id").inTable("o_outline");
table.integer("novelId").unsigned().references("id").inTable("o_novel");
table.primary(["id"]);
table.unique(["id"]);
},
},
//剧本
{
name: "o_script",
builder: (table) => {
table.integer("id").notNullable();
table.text("name");
table.text("content");
table.integer("projectId");
table.integer("createTime");
table.primary(["id"]);
table.unique(["id"]);
},
},
//资产表
{
name: "o_assets",
builder: (table) => {
table.integer("id").notNullable();
table.text("name");
table.text("prompt");
table.text("remark");
table.text("type");
table.text("describe");
table.integer("scriptId"); //剧本id
table.integer("imageId").unsigned().references("id").inTable("o_image");
table.integer("sonId");
table.integer("projectId");
table.integer("startTime");
table.text("state");
table.primary(["id"]);
table.unique(["id"]);
},
initData: async (knex) => {},
},
//生成图片表
{
name: "o_image",
builder: (table) => {
table.integer("id").notNullable();
table.text("filePath");
table.text("type");
table.integer("assetsId");
table.text("model");
table.text("resolution");
table.text("state");
table.primary(["id"]);
table.unique(["id"]);
},
},
//分镜
{
name: "o_storyboard",
builder: (table) => {
table.integer("id").notNullable();
table.integer("scriptId");
table.text("title");
table.text("prompt");
table.text("description");
table.text("filePath");
table.text("model");
table.text("mode");
table.text("duration");
table.text("resolution");
table.text("frameMode");
table.text("camera");
table.text("sound");
table.integer("createTime");
table.primary(["id"]);
table.unique(["id"]);
},
},
//flowData-剧本
{
name: "o_agentWorkData",
builder: (table) => {
table.integer("id").notNullable();
table.integer("projectId");
table.integer("espisodeId");
table.string("key"); //用户其他方式索引
table.string("data");
table.integer("createTime");
table.integer("updateTime");
table.primary(["id"]);
table.unique(["id"]);
},
},
//视频
{
name: "o_video",
builder: (table) => {
table.integer("id").notNullable();
table.text("filePath");
table.text("errorReason");
table.integer("time");
table.text("state");
table.integer("scriptId");
table.integer("storyboardId");
table.primary(["id"]);
table.unique(["id"]);
},
},
{
name: "o_videoConfig",
builder: (table) => {
table.integer("id").notNullable();
table.integer("storyboardId");
table.integer("videoId");
table.integer("audio"); // 声音
table.text("model"); // 模型
table.text("mode"); // 模式:
table.text("data"); // 所选数据集图片 JSON
table.text("resolution"); // 分辨率
table.integer("duration"); // 时长
table.text("prompt"); // 提示词
table.integer("createTime"); // 创建时间
table.integer("updateTime"); // 更新时间
table.primary(["id"]);
table.unique(["id"]);
},
},
//供应商配置表
{
name: "o_vendorConfig",
builder: (table) => {
table.integer("id").notNullable();
table.text("name");
table.text("version");
table.text("icon");
table.text("inputs"); // 输入项配置 JSON
table.text("inputValues"); // 输入项值 JSON
table.text("models"); // 模型配置 JSON
table.text("code"); // 模型配置 JSON
table.integer("createTime");
table.primary(["id"]);
table.unique(["id"]);
},
},
//供应商配置表
{
name: "o_vendorConfig",
builder: (table) => {
table.integer("id").notNullable();
table.text("name");
table.text("version");
table.text("icon");
table.text("inputs"); // 输入项配置 JSON
table.text("inputValues"); // 输入项值 JSON
table.text("models"); // 模型配置 JSON
table.text("code"); // 模型配置 JSON
table.integer("createTime");
table.primary(["id"]);
table.unique(["id"]);
},
},
//记忆表message=原始消息, summary=压缩摘要)
{
name: "memories",
builder: (table) => {
table.text("id").notNullable();
table.text("isolationKey").notNullable(); // 记忆隔离键
table.text("type").notNullable(); // 'message' | 'summary'
table.text("role"); // 'user' | 'assistant'
table.text("content").notNullable();
table.text("embedding"); // 向量嵌入 JSON
table.text("relatedMessageIds"); // summary关联的message id列表 JSON
table.integer("summarized").defaultTo(0); // message是否已被总结 0/1
table.integer("createTime").notNullable();
table.primary(["id"]);
table.index(["isolationKey", "type"]);
table.index(["isolationKey", "summarized"]);
},
},
//分镜工作流表
{
name: "o_storyboardFlow",
builder: (table) => {
table.integer("id").notNullable();
table.text("flowData").notNullable();
table.integer("storyboardId").notNullable();
table.primary(["id"]);
table.unique(["id"]);
},
},
{
name: "o_assets2Storyboard",
builder: (table) => {
table.integer("storyboardId").notNullable();
table.integer("assetId").notNullable();
table.primary(["assetId", "assetId"]);
table.unique(["storyboardId", "assetId"]);
},
},
{
name: "o_scriptAssets",
builder: (table) => {
table.integer("scriptId").notNullable();
table.integer("assetId").notNullable();
table.primary(["scriptId", "assetId"]);
table.unique(["scriptId", "assetId"]);
},
},
];
for (const t of tables) {
const tableExists = await knex.schema.hasTable(t.name);
if (!tableExists || forceInit) {
if (tableExists && forceInit) {
await knex.schema.dropTable(t.name);
console.log("[初始化数据库] 已存在表删除并重建:", t.name);
} else {
console.log("[初始化数据库] 创建数据表:", t.name);
}
await knex.schema.createTable(t.name, t.builder);
if (t.initData) {
await t.initData(knex);
console.log("[初始化数据库] 表数据初始化:", t.name);
}
}
}
};