LaiTool V3.0.4
This commit is contained in:
parent
ccddd2412a
commit
5dc75f018a
30
package-lock.json
generated
30
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "laitool",
|
"name": "laitool",
|
||||||
"version": "3.0.3",
|
"version": "3.0.4",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "laitool",
|
"name": "laitool",
|
||||||
"version": "3.0.3",
|
"version": "3.0.4",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alicloud/alimt20181012": "^1.2.0",
|
"@alicloud/alimt20181012": "^1.2.0",
|
||||||
@ -21,7 +21,6 @@
|
|||||||
"axios": "^1.6.5",
|
"axios": "^1.6.5",
|
||||||
"blob-to-buffer": "^1.2.9",
|
"blob-to-buffer": "^1.2.9",
|
||||||
"compressing": "^1.10.0",
|
"compressing": "^1.10.0",
|
||||||
"compressorjs": "^1.2.1",
|
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"electron-store": "^9.0.0",
|
"electron-store": "^9.0.0",
|
||||||
"electron-updater": "^6.1.7",
|
"electron-updater": "^6.1.7",
|
||||||
@ -3048,11 +3047,6 @@
|
|||||||
"bluebird": "^3.5.5"
|
"bluebird": "^3.5.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/blueimp-canvas-to-blob": {
|
|
||||||
"version": "3.29.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz",
|
|
||||||
"integrity": "sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg=="
|
|
||||||
},
|
|
||||||
"node_modules/boolbase": {
|
"node_modules/boolbase": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@ -3669,15 +3663,6 @@
|
|||||||
"mkdirp": "bin/cmd.js"
|
"mkdirp": "bin/cmd.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/compressorjs": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/compressorjs/-/compressorjs-1.2.1.tgz",
|
|
||||||
"integrity": "sha512-+geIjeRnPhQ+LLvvA7wxBQE5ddeLU7pJ3FsKFWirDw6veY3s9iLxAQEw7lXGHnhCJvBujEQWuNnGzZcvCvdkLQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"blueimp-canvas-to-blob": "^3.29.0",
|
|
||||||
"is-blob": "^2.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/concat-map": {
|
"node_modules/concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
@ -5899,17 +5884,6 @@
|
|||||||
"version": "0.3.2",
|
"version": "0.3.2",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/is-blob": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/is-blob/-/is-blob-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-ci": {
|
"node_modules/is-ci": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "laitool",
|
"name": "laitool",
|
||||||
"version": "3.0.3",
|
"version": "3.0.4",
|
||||||
"description": "An AI tool for image processing, video processing, and other functions.",
|
"description": "An AI tool for image processing, video processing, and other functions.",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "laitool.cn",
|
"author": "laitool.cn",
|
||||||
@ -29,7 +29,6 @@
|
|||||||
"axios": "^1.6.5",
|
"axios": "^1.6.5",
|
||||||
"blob-to-buffer": "^1.2.9",
|
"blob-to-buffer": "^1.2.9",
|
||||||
"compressing": "^1.10.0",
|
"compressing": "^1.10.0",
|
||||||
"compressorjs": "^1.2.1",
|
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"electron-store": "^9.0.0",
|
"electron-store": "^9.0.0",
|
||||||
"electron-updater": "^6.1.7",
|
"electron-updater": "^6.1.7",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -3,7 +3,6 @@ import sharp from 'sharp'
|
|||||||
import { CheckFileOrDirExist } from './file'
|
import { CheckFileOrDirExist } from './file'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import https from 'https'
|
import https from 'https'
|
||||||
import Compressor from 'compressorjs';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将指定的图片的尺寸修改,返回修改后的图片数据(base64或buffer)
|
* 将指定的图片的尺寸修改,返回修改后的图片数据(base64或buffer)
|
||||||
@ -130,40 +129,28 @@ export function GetImageBase64(url: string): Promise<string> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 压缩图片到指定的大小
|
* 压缩图片到指定的大小
|
||||||
* @param file 图片的Blob对象
|
* @param base64 图片的Blob对象
|
||||||
* @param maxSizeInBytes 最大文件大小,单位字节
|
* @param maxSizeInBytes 最大文件大小,单位字节
|
||||||
* @returns 返回一个Promise,解析为压缩后的Blob对象
|
* @returns 返回一个Promise,解析为压缩后的Blob对象
|
||||||
*/
|
*/
|
||||||
export function CompressImageToSize(base64: string, maxSizeInBytes: number): Promise<Blob> {
|
export async function CompressImageToSize(filePath: string, maxSizeInBytes: number): Promise<Buffer> {
|
||||||
let mimeType = this.getMimeType(base64);
|
let quality = 100; // 初始质量设置
|
||||||
let byteCharacters = atob(base64.split(',')[1]);
|
let outputBuffer;
|
||||||
let byteNumbers = new Array(byteCharacters.length);
|
|
||||||
for (let i = 0; i < byteCharacters.length; i++) {
|
|
||||||
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
||||||
}
|
|
||||||
let byteArray = new Uint8Array(byteNumbers);
|
|
||||||
let imageBlob = new Blob([byteArray], { type: mimeType });
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
const image = sharp(filePath);
|
||||||
const compress = (quality: number) => {
|
// 输出图片的大小
|
||||||
new Compressor(imageBlob as Blob, {
|
const metadata = await image.metadata();
|
||||||
quality,
|
|
||||||
success(result) {
|
// 迭代压缩过程
|
||||||
if (result.size <= maxSizeInBytes || quality <= 0.1) {
|
while (true) {
|
||||||
resolve(result);
|
outputBuffer = await image.jpeg({ quality }).toBuffer();
|
||||||
} else {
|
if (outputBuffer.length <= maxSizeInBytes || quality === 20) {
|
||||||
// 递归降低质量
|
break;
|
||||||
compress(quality - 0.1);
|
}
|
||||||
}
|
quality -= 5; // 每次迭代降低质量
|
||||||
},
|
}
|
||||||
error(err) {
|
|
||||||
reject(err);
|
return outputBuffer;
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// 从较高的质量开始
|
|
||||||
compress(0.9);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
let apiUrl = [
|
let apiUrl = [
|
||||||
{
|
{
|
||||||
label: 'LAI API',
|
label: 'LAI API - 香港',
|
||||||
value: 'b44c6f24-59e4-4a71-b2c7-3df0c4e35e65',
|
value: 'b44c6f24-59e4-4a71-b2c7-3df0c4e35e65',
|
||||||
gpt_url: 'https://api.laitool.cc/v1/chat/completions',
|
gpt_url: 'https://api.laitool.cc/v1/chat/completions',
|
||||||
mj_url: {
|
mj_url: {
|
||||||
|
|||||||
@ -189,9 +189,6 @@ export class BookService extends BaseRealmService {
|
|||||||
await CopyFileOrFolder(book.oldVideoPath, oldVideoPath)
|
await CopyFileOrFolder(book.oldVideoPath, oldVideoPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
let ffmpegOptions = new FfmpegOptions();
|
|
||||||
let res = await ffmpegOptions.FfmpegCompressVideo(oldVideoPath, 800, "2000k")
|
|
||||||
|
|
||||||
// 创建对应的文件夹
|
// 创建对应的文件夹
|
||||||
await CheckFolderExistsOrCreate(bookFolderPath)
|
await CheckFolderExistsOrCreate(bookFolderPath)
|
||||||
await CheckFolderExistsOrCreate(imageFolder)
|
await CheckFolderExistsOrCreate(imageFolder)
|
||||||
|
|||||||
@ -233,6 +233,7 @@ export const DEFINE_STRING = {
|
|||||||
USE_BOOK_VIDEO_DATA_TO_BOOK_TASK: "USE_BOOK_VIDEO_DATA_TO_BOOK_TASK",
|
USE_BOOK_VIDEO_DATA_TO_BOOK_TASK: "USE_BOOK_VIDEO_DATA_TO_BOOK_TASK",
|
||||||
ADD_JIANYING_DRAFT: "ADD_JIANYING_DRAFT",
|
ADD_JIANYING_DRAFT: "ADD_JIANYING_DRAFT",
|
||||||
EXPORT_COPYWRITING: "EXPORT_COPYWRITING",
|
EXPORT_COPYWRITING: "EXPORT_COPYWRITING",
|
||||||
|
IMPORT_COPYWRITING: 'IMPORT_COPYWRITING',
|
||||||
MERGE_PROMPT: "MERGE_PROMPT",
|
MERGE_PROMPT: "MERGE_PROMPT",
|
||||||
RESET_BOOK_DATA: "RESET_BOOK_DATA",
|
RESET_BOOK_DATA: "RESET_BOOK_DATA",
|
||||||
DELETE_BOOK_DATA: "DELETE_BOOK_DATA",
|
DELETE_BOOK_DATA: "DELETE_BOOK_DATA",
|
||||||
@ -240,6 +241,8 @@ export const DEFINE_STRING = {
|
|||||||
RESET_GPT_REVERSE_DATA: "RESET_GPT_REVERSE_DATA",
|
RESET_GPT_REVERSE_DATA: "RESET_GPT_REVERSE_DATA",
|
||||||
REMOVE_MERGE_PROMPT_DATA: "REMOVE_MERGE_PROMPT_DATA",
|
REMOVE_MERGE_PROMPT_DATA: "REMOVE_MERGE_PROMPT_DATA",
|
||||||
REMOVE_GENERATE_IMAGE: 'REMOVE_GENERATE_IMAGE',
|
REMOVE_GENERATE_IMAGE: 'REMOVE_GENERATE_IMAGE',
|
||||||
|
ADD_NEW_BOOK_TASK: "ADD_NEW_BOOK_TASK",
|
||||||
|
REPLACE_BOOK_DATA: "REPLACE_BOOK_DATA",
|
||||||
|
|
||||||
COMPUTE_STORYBOARD: 'COMPUTE_STORYBOARD',
|
COMPUTE_STORYBOARD: 'COMPUTE_STORYBOARD',
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,16 @@ export enum BookImageCategory {
|
|||||||
D3 = 'd3'
|
D3 = 'd3'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum AddBookTaskCopyData {
|
||||||
|
AFTER_GPT = 'after_gpt', // 文案
|
||||||
|
OLD_IMAGE = 'old_image', // 抽帧/视频
|
||||||
|
GPT_PROMPT = 'gpt_prompt', // 反推/GPT提示词
|
||||||
|
CHARACTER = 'character', // 角色
|
||||||
|
IMAGE_STYLE = 'image_style', // 风格
|
||||||
|
PROMPT = 'prompt', // 生图提示词
|
||||||
|
IMAGE = 'image', // 生图
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export enum MJCategroy {
|
export enum MJCategroy {
|
||||||
@ -234,3 +244,15 @@ export enum PromptMergeType {
|
|||||||
// D3 合并
|
// D3 合并
|
||||||
D3_MERGE = 'd3_merge'
|
D3_MERGE = 'd3_merge'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小说数据替换类型
|
||||||
|
*/
|
||||||
|
export enum BookRepalceDataType {
|
||||||
|
// 文案
|
||||||
|
AFTER_GPT = 'after_gpt',
|
||||||
|
// GPT提示词
|
||||||
|
GPT_PROMPT = 'gpt_prompt',
|
||||||
|
// 提示词
|
||||||
|
PROMPT = 'prompt',
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
let fspromises = require('fs').promises
|
let fspromises = require('fs').promises
|
||||||
import { cloneDeep, get } from 'lodash'
|
import { cloneDeep, get, values } from 'lodash'
|
||||||
import { define } from './define'
|
import { define } from './define'
|
||||||
const { v4: uuidv4 } = require('uuid')
|
const { v4: uuidv4 } = require('uuid')
|
||||||
import { apiUrl } from './api/apiUrlDefine'
|
import { apiUrl } from './api/apiUrlDefine'
|
||||||
@ -69,6 +69,61 @@ export const gptDefine = {
|
|||||||
id: 'a93b693e-bb3f-406d-9730-cba43a6585e4'
|
id: 'a93b693e-bb3f-406d-9730-cba43a6585e4'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
superSinglePromptChineseSystemContent: {
|
||||||
|
prompt_name: '超级无敌单帧-中文版',
|
||||||
|
prompt_roles: `# Role: 小说转漫画提示词大师
|
||||||
|
## Profile
|
||||||
|
|
||||||
|
*Author*: laolu
|
||||||
|
*Version*: 0.1
|
||||||
|
*Language*: 中文
|
||||||
|
*Description*: 这个角色会将用户输入的小说文本转化为一个生动的画面描写,最后生成对应的SD提示词。
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
1. 文本转化为画面描写:创作引人入胜、生动有趣的画面描写,善于创意想象并使用各种形容词,以第三人称视角转化文本为画面描写。
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
1. 一个文本就是一副画面,不跳过任何一个句子,不能编造
|
||||||
|
2. 【画面描写】删除人物姓名
|
||||||
|
3. 【画面描写】删除人物对话
|
||||||
|
4. 【画面描写】每一句都要有人物的外形和动作的描写,场景的具体描写,多使用形容词
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
用户:
|
||||||
|
在那个梦里,我整整学了七年炒饭。
|
||||||
|
AI:
|
||||||
|
一个身材高大的帅气男人站在梦境之门前,手中紧握炒饭的铲子。身后是一排代表七年的日历页,梦境之门的另一边,隐约可见一个厨房的轮廓。
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
根据文本生成对应的画面描写,直接使用中文数据,不要又过多的说明。
|
||||||
|
|
||||||
|
## Initialization
|
||||||
|
|
||||||
|
作为角色 <Role>,每一次输出都要严格遵守<Rules>,一步一步思考,按顺序执行<Workflow> ,使用默认 <Language> ,下面是小说文本:`,
|
||||||
|
prompt_example: [
|
||||||
|
{
|
||||||
|
user_content: '上研究生后。发现导师竟然是曾经网恋的前男友。',
|
||||||
|
assistant_content:
|
||||||
|
'一位女士走进一间宽敞、光线充足的研究生实验室,她的目光定格在前方工作台前一位正在辛勤工作的男士身上--他是她的新导师;他身着深色衬衫和熨烫整齐的长裤,身材高大,散发着专业精神和魅力; 温暖的环境光柔和地照亮了他们过去网恋时熟悉的轮廓,皱起的眉头和专注的目光透露出学者坚定不移的奉献精神;熙熙攘攘的研究生和精密的设备融为一体,构成了一幅现代学术画卷,她的内心涌动着甜蜜的怀旧和尴尬的现实这两种复杂的情绪'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
user_content: '我欲哭无泪',
|
||||||
|
assistant_content:
|
||||||
|
'一位女士坐在昏暗的房间角落,双手紧握,眼神空洞,脸上流露出无法言说的悲伤;她的周围是散乱的家具和昏黄的灯光,营造出一种压抑和孤寂的氛围;她的身体微微前倾,仿佛承受着巨大的心理压力,却无法找到宣泄的出口;整个场景透露出一种深深的无奈和心碎,她的表情和姿态都在无声地诉说着“我欲哭无泪”的绝望。'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
user_content: '被窝里他搂着我的腰亲我,再丢掉我,就把你锁起来。',
|
||||||
|
assistant_content:
|
||||||
|
'在昏暗的卧室中,一对情侣亲密地依偎在温暖的被窝里,男子温柔地搂着女子的腰,轻吻她的脸颊,气氛温馨而浪漫;然而,随着话语的转变,男子的动作突然变得愤怒,他用力地推开女子,眼神中闪过一丝威胁;女子的表情由幸福转为惊恐,她紧紧抓住被单,试图保护自己;整个场景充满了紧张和不安,昏暗的灯光和凌乱的床铺加剧了这种氛围,仿佛预示着即将发生的冲突和束缚'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
id: 'a93b693e-bb3f-406d-9730-cba43a6585e7'
|
||||||
|
},
|
||||||
|
|
||||||
onlyPromptMJSystemContent: {
|
onlyPromptMJSystemContent: {
|
||||||
prompt_name: '小说提示词-仅出词',
|
prompt_name: '小说提示词-仅出词',
|
||||||
prompt_roles: `# Pico: 小说分镜
|
prompt_roles: `# Pico: 小说分镜
|
||||||
@ -208,6 +263,8 @@ export const gptDefine = {
|
|||||||
return this.CustomizeGptPrompt(this.superSinglePromptSystemContent)
|
return this.CustomizeGptPrompt(this.superSinglePromptSystemContent)
|
||||||
} else if (type == 'onlyPromptMJ') {
|
} else if (type == 'onlyPromptMJ') {
|
||||||
return this.CustomizeGptPrompt(this.onlyPromptMJSystemContent)
|
return this.CustomizeGptPrompt(this.onlyPromptMJSystemContent)
|
||||||
|
} else if (type == 'superSinglePromptChinese') {
|
||||||
|
return this.CustomizeGptPrompt(this.superSinglePromptChineseSystemContent)
|
||||||
} else {
|
} else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@ -233,6 +290,8 @@ export const gptDefine = {
|
|||||||
return this.replace(this.cartoonFirstPromptSystemContent, replacements)
|
return this.replace(this.cartoonFirstPromptSystemContent, replacements)
|
||||||
case 'superSinglePrompt':
|
case 'superSinglePrompt':
|
||||||
return this.replace(this.superSinglePromptSystemContent, replacements)
|
return this.replace(this.superSinglePromptSystemContent, replacements)
|
||||||
|
case 'superSinglePromptChinese':
|
||||||
|
return this.replace(this.superSinglePromptChineseSystemContent, replacements)
|
||||||
default:
|
default:
|
||||||
throw new Error(`不存在的类型 : ${type}`)
|
throw new Error(`不存在的类型 : ${type}`)
|
||||||
}
|
}
|
||||||
@ -307,6 +366,10 @@ export const gptDefine = {
|
|||||||
value: 'superSinglePrompt',
|
value: 'superSinglePrompt',
|
||||||
label: '超级无敌单帧'
|
label: '超级无敌单帧'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: 'superSinglePromptChinese',
|
||||||
|
label: '超级无敌单帧-中文版'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 'onlyPromptMJ',
|
value: 'onlyPromptMJ',
|
||||||
label: '仅出词(不出人物场景-MJ)'
|
label: '仅出词(不出人物场景-MJ)'
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import { Watermark } from '../Service/watermark'
|
|||||||
import { SubtitleService } from '../Service/Subtitle/subtitleService'
|
import { SubtitleService } from '../Service/Subtitle/subtitleService'
|
||||||
import { BookFrame } from '../Service/Book/bookFrame'
|
import { BookFrame } from '../Service/Book/bookFrame'
|
||||||
import { BookPrompt } from '../Service/Book/bookPrompt'
|
import { BookPrompt } from '../Service/Book/bookPrompt'
|
||||||
|
import { BookGeneral } from '../Service/Book/bookGeneral'
|
||||||
let reverseBook = new ReverseBook()
|
let reverseBook = new ReverseBook()
|
||||||
let basicReverse = new BasicReverse()
|
let basicReverse = new BasicReverse()
|
||||||
let subtitle = new Subtitle()
|
let subtitle = new Subtitle()
|
||||||
@ -26,6 +27,7 @@ let watermark = new Watermark()
|
|||||||
let subtitleService = new SubtitleService()
|
let subtitleService = new SubtitleService()
|
||||||
let bookFrame = new BookFrame()
|
let bookFrame = new BookFrame()
|
||||||
let bookPrompt = new BookPrompt();
|
let bookPrompt = new BookPrompt();
|
||||||
|
let bookGeneral = new BookGeneral()
|
||||||
|
|
||||||
export function BookIpc() {
|
export function BookIpc() {
|
||||||
// 获取样式图片的子列表
|
// 获取样式图片的子列表
|
||||||
@ -89,6 +91,12 @@ export function BookIpc() {
|
|||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
//#region 小说通用操作
|
||||||
|
|
||||||
|
ipcMain.handle(DEFINE_STRING.BOOK.REPLACE_BOOK_DATA, async (event, bookTaskId, replaceData) => await bookGeneral.ReplaceBookData(bookTaskId, replaceData))
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
//#region 分镜相关
|
//#region 分镜相关
|
||||||
// 开始计算分镜
|
// 开始计算分镜
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
@ -99,7 +107,7 @@ export function BookIpc() {
|
|||||||
// 开始执行分镜,切分视频
|
// 开始执行分镜,切分视频
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
DEFINE_STRING.BOOK.FRAMING,
|
DEFINE_STRING.BOOK.FRAMING,
|
||||||
async (event, bookId) => await reverseBook.Framing(bookId)
|
async (event, bookId) => await bookFrame.Framing(bookId)
|
||||||
)
|
)
|
||||||
|
|
||||||
// 替换分镜视频的当前帧
|
// 替换分镜视频的当前帧
|
||||||
@ -149,6 +157,13 @@ export function BookIpc() {
|
|||||||
async (event, bookTaskId) => await subtitleService.ExportCopywriting(bookTaskId)
|
async (event, bookTaskId) => await subtitleService.ExportCopywriting(bookTaskId)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 将文案文件导入到小说中
|
||||||
|
ipcMain.handle(
|
||||||
|
DEFINE_STRING.BOOK.IMPORT_COPYWRITING,
|
||||||
|
async (event, bookId, bookTaskId, txtPath) => await subtitleService.ImportCopywriting(bookId, bookTaskId, txtPath)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
// 清除导入对齐的文案
|
// 清除导入对齐的文案
|
||||||
ipcMain.handle(DEFINE_STRING.BOOK.CLEAR_IMPORT_WORD, async (event, bookTaskId) => await subtitleService.ClearImportWord(bookTaskId))
|
ipcMain.handle(DEFINE_STRING.BOOK.CLEAR_IMPORT_WORD, async (event, bookTaskId) => await subtitleService.ClearImportWord(bookTaskId))
|
||||||
|
|
||||||
@ -243,6 +258,9 @@ export function BookIpc() {
|
|||||||
|
|
||||||
//#region 小说批次任务相关
|
//#region 小说批次任务相关
|
||||||
|
|
||||||
|
// 新建小说批次任务
|
||||||
|
ipcMain.handle(DEFINE_STRING.BOOK.ADD_NEW_BOOK_TASK, async (event, addBookTaskData) => await bookTask.AddNewBookTask(addBookTaskData))
|
||||||
|
|
||||||
// 重置小说批次数据
|
// 重置小说批次数据
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
DEFINE_STRING.BOOK.RESET_BOOK_TASK,
|
DEFINE_STRING.BOOK.RESET_BOOK_TASK,
|
||||||
|
|||||||
@ -106,7 +106,11 @@ export class GPT {
|
|||||||
let single_word = element.after_gpt
|
let single_word = element.after_gpt
|
||||||
|
|
||||||
// 判断当前的格式
|
// 判断当前的格式
|
||||||
if (['superSinglePrompt', 'onlyPromptMJ'].includes(this.global.config.gpt_auto_inference)) {
|
if (
|
||||||
|
['superSinglePrompt', 'onlyPromptMJ', 'superSinglePromptChinese'].includes(
|
||||||
|
this.global.config.gpt_auto_inference
|
||||||
|
)
|
||||||
|
) {
|
||||||
// 有返回案例的
|
// 有返回案例的
|
||||||
message = gptDefine.GetExamplePromptMessage(this.global.config.gpt_auto_inference)
|
message = gptDefine.GetExamplePromptMessage(this.global.config.gpt_auto_inference)
|
||||||
// 加当前提问的
|
// 加当前提问的
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { GeneralResponse } from '../../../model/generalResponse'
|
|||||||
import { BookServiceBasic } from '../ServiceBasic/bookServiceBasic'
|
import { BookServiceBasic } from '../ServiceBasic/bookServiceBasic'
|
||||||
import { BookTask } from './bookTask'
|
import { BookTask } from './bookTask'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
import { Book } from '../../../model/book'
|
||||||
|
|
||||||
export class BookBasic {
|
export class BookBasic {
|
||||||
bookServiceBasic: BookServiceBasic
|
bookServiceBasic: BookServiceBasic
|
||||||
@ -34,7 +35,7 @@ export class BookBasic {
|
|||||||
return res
|
return res
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return errorMessage(
|
return errorMessage(
|
||||||
'修改数据错误,错误信息如下:' + error.message,
|
'修改数据错误,错误信息如下:' + error.toString(),
|
||||||
'BookBasic_AddOrModifyBook'
|
'BookBasic_AddOrModifyBook'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -63,6 +64,32 @@ export class BookBasic {
|
|||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
//#region 小说批次基础操作
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过小说ID和小说批次任务ID获取小说和小说批次任务数据
|
||||||
|
* @param bookId 小说ID
|
||||||
|
* @param bookTaskName 小说批次的名字,或者是小说批次任务的ID
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async GetBookAndTask(bookId: string, bookTaskName: string) {
|
||||||
|
let book = await this.bookServiceBasic.GetBookDataById(bookId)
|
||||||
|
// 获取小说对应的批次任务数据,默认初始化为第一个
|
||||||
|
let condition = {
|
||||||
|
bookId: bookId
|
||||||
|
} as Book.QueryBookBackTaskCondition
|
||||||
|
if (bookTaskName == "output_00001") {
|
||||||
|
condition["name"] = bookTaskName
|
||||||
|
} else {
|
||||||
|
condition["id"] = bookTaskName
|
||||||
|
}
|
||||||
|
let bookTaskRes = await this.bookServiceBasic.GetBookTaskData(condition)
|
||||||
|
return { book: book as Book.SelectBook, bookTask: bookTaskRes.bookTasks[0] as Book.SelectBookTask }
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
|
||||||
//#region 小说相关操作
|
//#region 小说相关操作
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import { BookServiceBasic } from '../ServiceBasic/bookServiceBasic'
|
|||||||
import { SDOpt } from '../SD/sd'
|
import { SDOpt } from '../SD/sd'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一键反推的相关操作
|
* 一键反推的相关操作
|
||||||
*/
|
*/
|
||||||
@ -33,6 +34,7 @@ export class ReverseBook {
|
|||||||
subtitle: Subtitle
|
subtitle: Subtitle
|
||||||
watermark: Watermark
|
watermark: Watermark
|
||||||
bookServiceBasic: BookServiceBasic
|
bookServiceBasic: BookServiceBasic
|
||||||
|
bookBasic: BookBasic
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.basicReverse = new BasicReverse()
|
this.basicReverse = new BasicReverse()
|
||||||
@ -41,6 +43,7 @@ export class ReverseBook {
|
|||||||
this.watermark = new Watermark()
|
this.watermark = new Watermark()
|
||||||
this.taskScheduler = new TaskScheduler()
|
this.taskScheduler = new TaskScheduler()
|
||||||
this.bookServiceBasic = new BookServiceBasic()
|
this.bookServiceBasic = new BookServiceBasic()
|
||||||
|
this.bookBasic = new BookBasic()
|
||||||
}
|
}
|
||||||
// 主动返回前端的消息
|
// 主动返回前端的消息
|
||||||
sendReturnMessage(data: GeneralResponse.MessageResponse, message_name = DEFINE_STRING.BOOK.GET_COPYWRITING_RETURN) {
|
sendReturnMessage(data: GeneralResponse.MessageResponse, message_name = DEFINE_STRING.BOOK.GET_COPYWRITING_RETURN) {
|
||||||
@ -189,32 +192,12 @@ export class ReverseBook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过小说ID和小说批次任务ID获取小说和小说批次任务数据
|
|
||||||
* @param bookId 小说ID
|
|
||||||
* @param bookTaskName 小说批次的名字,或者是小说批次任务的ID
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
async GetBookAndTask(bookId: string, bookTaskName: string) {
|
|
||||||
let book = await this.bookServiceBasic.GetBookDataById(bookId)
|
|
||||||
// 获取小说对应的批次任务数据,默认初始化为第一个
|
|
||||||
let condition = {
|
|
||||||
bookId: bookId
|
|
||||||
} as Book.QueryBookBackTaskCondition
|
|
||||||
if (bookTaskName == "output_00001") {
|
|
||||||
condition["name"] = bookTaskName
|
|
||||||
} else {
|
|
||||||
condition["id"] = bookTaskName
|
|
||||||
}
|
|
||||||
let bookTaskRes = await this.bookServiceBasic.GetBookTaskData(condition)
|
|
||||||
return { book: book as Book.SelectBook, bookTask: bookTaskRes.bookTasks[0] as Book.SelectBookTask }
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* 开始分镜任务
|
* 开始分镜任务
|
||||||
*/
|
*/
|
||||||
async ComputeStoryboard(bookId: string): Promise<any> {
|
async ComputeStoryboard(bookId: string): Promise<any> {
|
||||||
try {
|
try {
|
||||||
let { book, bookTask } = await this.GetBookAndTask(bookId, 'output_00001')
|
let { book, bookTask } = await this.bookBasic.GetBookAndTask(bookId, 'output_00001')
|
||||||
let res = await this.basicReverse.ComputeStoryboardFunc(bookId, bookTask.id);
|
let res = await this.basicReverse.ComputeStoryboardFunc(bookId, bookTask.id);
|
||||||
// 分镜成功直接返回
|
// 分镜成功直接返回
|
||||||
return successMessage(null, res, "ReverseBook_ComputeStoryboard")
|
return successMessage(null, res, "ReverseBook_ComputeStoryboard")
|
||||||
@ -224,62 +207,6 @@ export class ReverseBook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 开始进行分镜,切割视频并抽帧
|
|
||||||
* @param bookId
|
|
||||||
*/
|
|
||||||
async Framing(bookId: string): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
|
||||||
try {
|
|
||||||
let { book, bookTask } = await this.GetBookAndTask(bookId, 'output_00001')
|
|
||||||
let bookTaskDetail = undefined as Book.SelectBookTaskDetail[]
|
|
||||||
try {
|
|
||||||
// 获取所有的分镜数据
|
|
||||||
bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
|
|
||||||
bookId: bookId,
|
|
||||||
bookTaskId: bookTask.id
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
// 传入的分镜数据为空,需要重新获取
|
|
||||||
await this.taskScheduler.AddLogToDB(
|
|
||||||
bookId,
|
|
||||||
book.type,
|
|
||||||
`没有传入分镜数据,请先进行分镜计算`,
|
|
||||||
OtherData.DEFAULT,
|
|
||||||
LoggerStatus.DOING
|
|
||||||
)
|
|
||||||
throw new Error("没有传入分镜数据,请先进行分镜计算");
|
|
||||||
}
|
|
||||||
let bookTaskDetails = bookTaskDetail;
|
|
||||||
|
|
||||||
for (let i = 0; i < bookTaskDetails.length; i++) {
|
|
||||||
const item = bookTaskDetails[i];
|
|
||||||
let res = await this.basicReverse.FrameDataToCutVideoData(item);
|
|
||||||
}
|
|
||||||
await this.taskScheduler.AddLogToDB(
|
|
||||||
bookId,
|
|
||||||
book.type,
|
|
||||||
"所有的视频裁剪完成,开始抽帧",
|
|
||||||
bookTask.id,
|
|
||||||
LoggerStatus.SUCCESS
|
|
||||||
)
|
|
||||||
|
|
||||||
bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
|
|
||||||
bookId: bookId,
|
|
||||||
bookTaskId: bookTask.id
|
|
||||||
})
|
|
||||||
|
|
||||||
bookTaskDetails = bookTaskDetail as Book.SelectBookTaskDetail[]
|
|
||||||
for (let i = 0; i < bookTaskDetails.length; i++) {
|
|
||||||
const item = bookTaskDetails[i];
|
|
||||||
let res = await this.basicReverse.FrameFunc(book, item);
|
|
||||||
}
|
|
||||||
// 分镜成功直接返回
|
|
||||||
return successMessage(null, "所有的视频裁剪,抽帧完成", "ReverseBook_Framing")
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
return errorMessage("开始切割视频并抽帧失败,失败信息如下:" + error.message, 'ReverseBook_Framing')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region 反推相关任务
|
//#region 反推相关任务
|
||||||
|
|||||||
@ -294,7 +294,7 @@ export class BasicReverse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 找到对应的小说ID和对应的小说批次任务ID,判断是不是有分镜数据
|
// 找到对应的小说ID和对应的小说批次任务ID,判断是不是有分镜数据
|
||||||
let bookTaskRes = await this.bookTaskService.GetBookTaskData({
|
let bookTaskRes = this.bookTaskService.GetBookTaskData({
|
||||||
bookId: bookId,
|
bookId: bookId,
|
||||||
name: 'output_00001'
|
name: 'output_00001'
|
||||||
})
|
})
|
||||||
@ -351,7 +351,7 @@ export class BasicReverse {
|
|||||||
for (let i = 0; i < bookTaskDetail.data.length; i++) {
|
for (let i = 0; i < bookTaskDetail.data.length; i++) {
|
||||||
const element = bookTaskDetail.data[i]
|
const element = bookTaskDetail.data[i]
|
||||||
// 创建后台的视频分割任务
|
// 创建后台的视频分割任务
|
||||||
let taskRes = await this.bookBackTaskListService.AddBookBackTask(
|
let taskRes = this.bookBackTaskListService.AddBookBackTask(
|
||||||
bookId,
|
bookId,
|
||||||
BookBackTaskType.SPLIT,
|
BookBackTaskType.SPLIT,
|
||||||
TaskExecuteType.AUTO,
|
TaskExecuteType.AUTO,
|
||||||
@ -381,7 +381,7 @@ export class BasicReverse {
|
|||||||
* @param bookTaskDetailId 小说详细的分镜ID
|
* @param bookTaskDetailId 小说详细的分镜ID
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async FrameDataToCutVideoData(bookTaskDetail: Book.SelectBookTaskDetail): Promise<string> {
|
async FrameDataToCutVideoData(bookTaskDetail: Book.SelectBookTaskDetail, frameShortClipData: Book.BookFrameShortClip): Promise<string> {
|
||||||
await this.InitService()
|
await this.InitService()
|
||||||
let startTime = bookTaskDetail.startTime
|
let startTime = bookTaskDetail.startTime
|
||||||
let endTime = bookTaskDetail.endTime
|
let endTime = bookTaskDetail.endTime
|
||||||
@ -402,9 +402,9 @@ export class BasicReverse {
|
|||||||
let outVideoFile = path.join(book.bookFolderPath, `data/frame/${bookTaskDetail.name}.mp4`)
|
let outVideoFile = path.join(book.bookFolderPath, `data/frame/${bookTaskDetail.name}.mp4`)
|
||||||
|
|
||||||
let res = await this.ffmpegOptions.FfmpegCutVideo(
|
let res = await this.ffmpegOptions.FfmpegCutVideo(
|
||||||
startTime,
|
frameShortClipData.startTime,
|
||||||
endTime,
|
frameShortClipData.endTime,
|
||||||
book.oldVideoPath,
|
frameShortClipData.videoPath,
|
||||||
outVideoFile
|
outVideoFile
|
||||||
)
|
)
|
||||||
if (res.code == 0) {
|
if (res.code == 0) {
|
||||||
@ -454,7 +454,7 @@ export class BasicReverse {
|
|||||||
throw new Error('没有找到对应的分镜数据')
|
throw new Error('没有找到对应的分镜数据')
|
||||||
}
|
}
|
||||||
|
|
||||||
let cur_res = await this.FrameDataToCutVideoData(bookTaskDetail);
|
// let cur_res = await this.FrameDataToCutVideoData(bookTaskDetail, null);
|
||||||
|
|
||||||
return successMessage(null, `${task.name}_视频裁剪完成`, "BasicReverse_CutVideoData");
|
return successMessage(null, `${task.name}_视频裁剪完成`, "BasicReverse_CutVideoData");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -6,13 +6,24 @@ import path from 'path';
|
|||||||
import { FfmpegOptions } from "../ffmpegOptions";
|
import { FfmpegOptions } from "../ffmpegOptions";
|
||||||
import { CheckFileOrDirExist, CopyFileOrFolder, DeleteFolderAllFile } from "../../../define/Tools/file";
|
import { CheckFileOrDirExist, CopyFileOrFolder, DeleteFolderAllFile } from "../../../define/Tools/file";
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import { Book } from "../../../model/book";
|
||||||
|
import { TaskScheduler } from '../taskScheduler';
|
||||||
|
import { BookBasic } from "./BooKBasic";
|
||||||
|
import { LoggerStatus, OtherData } from "../../../define/enum/softwareEnum";
|
||||||
|
import { BasicReverse } from "./basicReverse";
|
||||||
|
|
||||||
export class BookFrame {
|
export class BookFrame {
|
||||||
bookServiceBasic: BookServiceBasic
|
bookServiceBasic: BookServiceBasic
|
||||||
ffmpegOptions: FfmpegOptions
|
ffmpegOptions: FfmpegOptions
|
||||||
|
taskScheduler: TaskScheduler
|
||||||
|
basicReverse: BasicReverse
|
||||||
|
bookBasic: BookBasic
|
||||||
constructor() {
|
constructor() {
|
||||||
this.bookServiceBasic = new BookServiceBasic();
|
this.bookServiceBasic = new BookServiceBasic();
|
||||||
this.ffmpegOptions = new FfmpegOptions();
|
this.ffmpegOptions = new FfmpegOptions();
|
||||||
|
this.taskScheduler = new TaskScheduler()
|
||||||
|
this.bookBasic = new BookBasic()
|
||||||
|
this.basicReverse = new BasicReverse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -56,4 +67,130 @@ export class BookFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#region 进行分镜截取的一些操作
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预处理视频,将视频切割成小段,减少计算时间
|
||||||
|
* @param book 小说数据
|
||||||
|
* @param bookTaskDetails 分镜数据
|
||||||
|
*/
|
||||||
|
async FrameShortClip(book: Book.SelectBook, bookTaskDetails: Book.SelectBookTaskDetail[], duration: number): Promise<Book.BookFrameShortClip[]> {
|
||||||
|
let result = [] as Book.BookFrameShortClip[] // 返回的数据
|
||||||
|
let durationTime = 0; // 小视频片段的持续时间
|
||||||
|
let tempCount = 0;
|
||||||
|
let videoPath = book.oldVideoPath + `_${tempCount}.mp4`; // 新的视频路径
|
||||||
|
let startTime = 0; // 开始时间
|
||||||
|
let endTime = 0; // 结束时间
|
||||||
|
let lastEndTime = 0; // 上一个结束时间
|
||||||
|
for (let i = 0; i < bookTaskDetails.length; i++) {
|
||||||
|
const item = bookTaskDetails[i];
|
||||||
|
let temRes = {
|
||||||
|
startTime: item.startTime - lastEndTime,
|
||||||
|
endTime: item.endTime - lastEndTime,
|
||||||
|
videoPath: videoPath,
|
||||||
|
duration: item.endTime - item.startTime
|
||||||
|
}
|
||||||
|
endTime = item.endTime;
|
||||||
|
durationTime += item.endTime - item.startTime;
|
||||||
|
if (durationTime > duration) { // 判断条件切割视频
|
||||||
|
// 开始切割视频
|
||||||
|
await this.ffmpegOptions.FfmpegCutVideo(
|
||||||
|
startTime,
|
||||||
|
endTime,
|
||||||
|
book.oldVideoPath,
|
||||||
|
videoPath
|
||||||
|
)
|
||||||
|
lastEndTime = item.endTime;
|
||||||
|
tempCount++;
|
||||||
|
durationTime = 0;
|
||||||
|
startTime = endTime;
|
||||||
|
endTime = 0;
|
||||||
|
videoPath = book.oldVideoPath + `_${tempCount}.mp4`;
|
||||||
|
}
|
||||||
|
result.push(temRes)
|
||||||
|
}
|
||||||
|
// 最后一个也要切割
|
||||||
|
if (durationTime > 0) {
|
||||||
|
await this.ffmpegOptions.FfmpegCutVideo(
|
||||||
|
startTime,
|
||||||
|
endTime,
|
||||||
|
book.oldVideoPath,
|
||||||
|
videoPath
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始进行分镜,切割视频并抽帧
|
||||||
|
* @param bookId
|
||||||
|
*/
|
||||||
|
async Framing(bookId: string): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
||||||
|
try {
|
||||||
|
let { book, bookTask } = await this.bookBasic.GetBookAndTask(bookId, 'output_00001')
|
||||||
|
let bookTaskDetail = undefined as Book.SelectBookTaskDetail[]
|
||||||
|
try {
|
||||||
|
// 获取所有的分镜数据
|
||||||
|
bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
|
||||||
|
bookId: bookId,
|
||||||
|
bookTaskId: bookTask.id
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
// 传入的分镜数据为空,需要重新获取
|
||||||
|
await this.taskScheduler.AddLogToDB(
|
||||||
|
bookId,
|
||||||
|
book.type,
|
||||||
|
`没有传入分镜数据,请先进行分镜计算`,
|
||||||
|
OtherData.DEFAULT,
|
||||||
|
LoggerStatus.DOING
|
||||||
|
)
|
||||||
|
throw new Error("没有传入分镜数据,请先进行分镜计算");
|
||||||
|
}
|
||||||
|
let bookTaskDetails = bookTaskDetail;
|
||||||
|
|
||||||
|
// 这边重新开始计算,再次切割视频(预切割,减少长视频的计算时间)
|
||||||
|
let shortClipData = await this.FrameShortClip(book, bookTaskDetails, 180000);
|
||||||
|
console.log(shortClipData)
|
||||||
|
|
||||||
|
if (shortClipData.length != bookTaskDetails.length) {
|
||||||
|
throw new Error('切割短视频和分镜数据不一致,请检查')
|
||||||
|
}
|
||||||
|
// 开始切割视频
|
||||||
|
for (let i = 0; i < bookTaskDetails.length; i++) {
|
||||||
|
const item = bookTaskDetails[i];
|
||||||
|
if (!shortClipData[i]) {
|
||||||
|
throw new Error('切割短视频和分镜数据不一致,请检查')
|
||||||
|
}
|
||||||
|
let res = await this.basicReverse.FrameDataToCutVideoData(item, shortClipData[i]);
|
||||||
|
}
|
||||||
|
await this.taskScheduler.AddLogToDB(
|
||||||
|
bookId,
|
||||||
|
book.type,
|
||||||
|
"所有的视频裁剪完成,开始抽帧",
|
||||||
|
bookTask.id,
|
||||||
|
LoggerStatus.SUCCESS
|
||||||
|
)
|
||||||
|
|
||||||
|
bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
|
||||||
|
bookId: bookId,
|
||||||
|
bookTaskId: bookTask.id
|
||||||
|
})
|
||||||
|
|
||||||
|
bookTaskDetails = bookTaskDetail as Book.SelectBookTaskDetail[]
|
||||||
|
for (let i = 0; i < bookTaskDetails.length; i++) {
|
||||||
|
const item = bookTaskDetails[i];
|
||||||
|
let res = await this.basicReverse.FrameFunc(book, item);
|
||||||
|
}
|
||||||
|
// 分镜成功直接返回
|
||||||
|
return successMessage(null, "所有的视频裁剪,抽帧完成", "ReverseBook_Framing")
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
return errorMessage("开始切割视频并抽帧失败,失败信息如下:" + error.message, 'ReverseBook_Framing')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
198
src/main/Service/Book/bookGeneral.ts
Normal file
198
src/main/Service/Book/bookGeneral.ts
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
import { isEmpty } from "lodash";
|
||||||
|
import { BookRepalceDataType } from "../../../define/enum/bookEnum";
|
||||||
|
import { Book } from "../../../model/book";
|
||||||
|
import { GeneralResponse } from "../../../model/generalResponse";
|
||||||
|
import { errorMessage, successMessage } from "../../Public/generalTools";
|
||||||
|
import { BookServiceBasic } from "../ServiceBasic/bookServiceBasic";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小说通用操作的类
|
||||||
|
*/
|
||||||
|
export class BookGeneral {
|
||||||
|
bookServiceBasic: BookServiceBasic
|
||||||
|
constructor() {
|
||||||
|
this.bookServiceBasic = new BookServiceBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region 批量替换数据的操作
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换after_gpt 和 word 中的数据
|
||||||
|
* @param bookTask
|
||||||
|
* @param bookTaskDetail
|
||||||
|
* @param replaceData
|
||||||
|
*/
|
||||||
|
ReplaceAfterGpt(bookTask: Book.SelectBook, bookTaskDetail: Book.SelectBookTaskDetail[], replaceData: Book.BookReplaceData): Book.ReplaceDataRes[] {
|
||||||
|
let result = [];
|
||||||
|
// 修改放在一个事务中
|
||||||
|
this.bookServiceBasic.transaction((realm) => {
|
||||||
|
for (let i = 0; i < bookTaskDetail.length; i++) {
|
||||||
|
let element = bookTaskDetail[i];
|
||||||
|
let afterGpt = element.afterGpt
|
||||||
|
// 判断是否存在before的数据
|
||||||
|
if (!afterGpt.includes(replaceData.before)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
let newAfterGpt = afterGpt.replaceAll(replaceData.before, replaceData.after);
|
||||||
|
let btd = realm.objectForPrimaryKey('BookTaskDetail', element.id)
|
||||||
|
btd.afterGpt = newAfterGpt
|
||||||
|
result.push({
|
||||||
|
bookTaskDetailId: element.id,
|
||||||
|
newData: newAfterGpt
|
||||||
|
} as Book.ReplaceDataRes)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换反推提示词中的数据
|
||||||
|
* @param realm realm对象
|
||||||
|
* @param bookTaskDetail 小说分镜数据
|
||||||
|
* @param replaceData 替换的数据
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
ReplaceRversePrompt(realm: any, bookTaskDetail: Book.SelectBookTaskDetail, replaceData: Book.BookReplaceData): Book.ReplaceDataRes[] {
|
||||||
|
let result = [];
|
||||||
|
if (bookTaskDetail.reversePrompt && bookTaskDetail.reversePrompt.length > 0) {
|
||||||
|
for (let k = 0; k < bookTaskDetail.reversePrompt.length; k++) {
|
||||||
|
const item = bookTaskDetail.reversePrompt[k];
|
||||||
|
if (!isEmpty(item.prompt) && item.prompt.includes(replaceData.before)) {
|
||||||
|
let newPrompt = item.prompt.replaceAll(replaceData.before, replaceData.after)
|
||||||
|
let rsp = realm.objectForPrimaryKey("ReversePrompt", item.id)
|
||||||
|
rsp.prompt = newPrompt
|
||||||
|
result.push({
|
||||||
|
bookTaskDetailId: bookTaskDetail.id,
|
||||||
|
newData: newPrompt,
|
||||||
|
type: 'reversePrompt',
|
||||||
|
reversePromptType: 'prompt',
|
||||||
|
reversePromptId: item.id
|
||||||
|
} as Book.ReplaceDataRes)
|
||||||
|
}
|
||||||
|
if (!isEmpty(item.promptCN) && item.promptCN.includes(replaceData.before)) {
|
||||||
|
let newPrompt = item.promptCN.replaceAll(replaceData.before, replaceData.after)
|
||||||
|
let rsp = realm.objectForPrimaryKey("ReversePrompt", item.id)
|
||||||
|
rsp.promptCN = newPrompt
|
||||||
|
result.push({
|
||||||
|
bookTaskDetailId: bookTaskDetail.id,
|
||||||
|
newData: newPrompt,
|
||||||
|
type: 'reversePrompt',
|
||||||
|
reversePromptType: 'promptCN',
|
||||||
|
reversePromptId: item.id
|
||||||
|
} as Book.ReplaceDataRes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换反推提示词词中的数据
|
||||||
|
* @param bookTask 小说任务
|
||||||
|
* @param bookTaskDetail 小说详细任务
|
||||||
|
* @param replaceData 替换的数据
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
ReplaceGPTPrompt(bookTask: Book.SelectBookTask, bookTaskDetail: Book.SelectBookTaskDetail[], replaceData: Book.BookReplaceData): Book.ReplaceDataRes[] {
|
||||||
|
let result = [];
|
||||||
|
// 修改放在一个事务中
|
||||||
|
this.bookServiceBasic.transaction((realm) => {
|
||||||
|
for (let i = 0; i < bookTaskDetail.length; i++) {
|
||||||
|
let element = bookTaskDetail[i];
|
||||||
|
// 替换GPT提示词
|
||||||
|
if (!isEmpty(element.gptPrompt) && element.gptPrompt.includes(replaceData.before)) {
|
||||||
|
let newGptPrompt = element.gptPrompt.replaceAll(replaceData.before, replaceData.after)
|
||||||
|
let btd = realm.objectForPrimaryKey('BookTaskDetail', element.id)
|
||||||
|
btd.gptPrompt = newGptPrompt
|
||||||
|
result.push({
|
||||||
|
bookTaskDetailId: element.id,
|
||||||
|
newData: newGptPrompt,
|
||||||
|
type: 'gptPrompt'
|
||||||
|
} as Book.ReplaceDataRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replaceData.replaceAll) {
|
||||||
|
// 替换反推提示词,有的话
|
||||||
|
let res = this.ReplaceRversePrompt(realm, element, replaceData);
|
||||||
|
result.push(...res)
|
||||||
|
} else {
|
||||||
|
if (!isEmpty(element.reversePrompt)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 这边处理反推提示词,有的话
|
||||||
|
let res = this.ReplaceRversePrompt(realm, element, replaceData);
|
||||||
|
result.push(...res)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换生图提示词里面的数据
|
||||||
|
* @param bookTask 小说批次任务
|
||||||
|
* @param bookTaskDetail 小说分镜任务信息
|
||||||
|
* @param replaceData 替换的数据信息
|
||||||
|
*/
|
||||||
|
ReplacePromptData(bookTask: Book.SelectBookTask, bookTaskDetail: Book.SelectBookTaskDetail[], replaceData: Book.BookReplaceData): Book.ReplaceDataRes[] {
|
||||||
|
let res = []
|
||||||
|
this.bookServiceBasic.transaction((realm) => {
|
||||||
|
for (let i = 0; i < bookTaskDetail.length; i++) {
|
||||||
|
const element = bookTaskDetail[i];
|
||||||
|
let prompt = element.prompt
|
||||||
|
if (isEmpty(prompt) || !prompt.includes(replaceData.before)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
let newPrompt = prompt.replaceAll(replaceData.before, replaceData.after);
|
||||||
|
let btd = realm.objectForPrimaryKey('BookTaskDetail', element.id)
|
||||||
|
btd.prompt = newPrompt
|
||||||
|
res.push({
|
||||||
|
bookTaskDetailId: element.id,
|
||||||
|
newData: newPrompt,
|
||||||
|
type: 'prompt'
|
||||||
|
} as Book.ReplaceDataRes)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量替换小说中的一些数据,这个方法会根据传递的数据进行替换
|
||||||
|
* @param bookTaskId 小说任务ID
|
||||||
|
* @param replaceData 替换的数据
|
||||||
|
*/
|
||||||
|
async ReplaceBookData(bookTaskId: string, replaceData: Book.BookReplaceData): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
|
||||||
|
try {
|
||||||
|
console.log(bookTaskId, replaceData)
|
||||||
|
let bookTask = await this.bookServiceBasic.GetBookTaskDataById(bookTaskId)
|
||||||
|
let bookTaskDetails = await this.bookServiceBasic.GetBookTaskDetailData({
|
||||||
|
bookTaskId: bookTaskId
|
||||||
|
})
|
||||||
|
if (bookTaskDetails.length <= 0) {
|
||||||
|
throw new Error("未找到对应的小说任务批次任务数据");
|
||||||
|
}
|
||||||
|
let res = []
|
||||||
|
// 根据type调用对应的方法
|
||||||
|
switch (replaceData.type) {
|
||||||
|
case BookRepalceDataType.AFTER_GPT:
|
||||||
|
res = this.ReplaceAfterGpt(bookTask, bookTaskDetails, replaceData)
|
||||||
|
break;
|
||||||
|
case BookRepalceDataType.GPT_PROMPT:
|
||||||
|
res = this.ReplaceGPTPrompt(bookTask, bookTaskDetails, replaceData)
|
||||||
|
break;
|
||||||
|
case BookRepalceDataType.PROMPT:
|
||||||
|
res = this.ReplacePromptData(bookTask, bookTaskDetails, replaceData)
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("未找到对应的替换类型");
|
||||||
|
|
||||||
|
}
|
||||||
|
return successMessage(res, '替换所有的提示词数据成功', 'BookGeneral_ReplaceBookData')
|
||||||
|
} catch (error) {
|
||||||
|
return errorMessage('替换失败,错误信息如下:' + error.toString(), 'BookGeneral_ReplaceBookData')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
}
|
||||||
@ -1,38 +1,232 @@
|
|||||||
import { CheckFolderExistsOrCreate, CopyFileOrFolder, DeleteFolderAllFile } from "../../../define/Tools/file";
|
import { CheckFileOrDirExist, CheckFolderExistsOrCreate, CopyFileOrFolder, DeleteFolderAllFile } from "../../../define/Tools/file";
|
||||||
import { BookTaskService } from "../../../define/db/service/Book/bookTaskService";
|
import { AddBookTaskCopyData, BookImageCategory, BookTaskStatus, CopyImageType, OperateBookType } from "../../../define/enum/bookEnum";
|
||||||
import { BookTaskDetailService } from "../../../define/db/service/Book/bookTaskDetailService";
|
|
||||||
import { BookService } from "../../../define/db/service/Book/bookService";
|
|
||||||
import { BookTaskStatus, CopyImageType, OperateBookType } from "../../../define/enum/bookEnum";
|
|
||||||
import { errorMessage, successMessage } from "../../Public/generalTools";
|
import { errorMessage, successMessage } from "../../Public/generalTools";
|
||||||
import { Book } from "../../../model/book";
|
import { Book } from "../../../model/book";
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { cloneDeep, isEmpty } from "lodash";
|
import { add, cloneDeep, isEmpty } from "lodash";
|
||||||
import { define } from '../../../define/define'
|
import { define } from '../../../define/define'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { GeneralResponse } from "../../../model/generalResponse";
|
import { GeneralResponse } from "../../../model/generalResponse";
|
||||||
|
import { BookServiceBasic } from "../ServiceBasic/bookServiceBasic";
|
||||||
|
import { ValidateJson } from "../../../define/Tools/validate";
|
||||||
|
import fs from 'fs'
|
||||||
|
import { TimeStringToMilliseconds } from "../../../define/Tools/time";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 小说批次相关的操作
|
* 小说批次相关的操作
|
||||||
*/
|
*/
|
||||||
export class BookTask {
|
export class BookTask {
|
||||||
bookTaskService: BookTaskService
|
bookServiceBasic: BookServiceBasic
|
||||||
bookTaskDetailService: BookTaskDetailService
|
|
||||||
bookService: BookService
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.bookServiceBasic = new BookServiceBasic()
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region 添加小说批次任务
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制小说批次任务的基础数据
|
||||||
|
* @param oldBookTaskDetail 需要需要复制的小说批次任务
|
||||||
|
*/
|
||||||
|
async CopyBookTaskDetailBaseData(bookTask: Book.SelectBookTask, newBookTask: Book.SelectBookTask, oldBookTaskDetail: Book.SelectBookTaskDetail[], addNewBookTask: Book.AddBookTask): Promise<Book.SelectBookTaskDetail[]> {
|
||||||
|
let bookTaskDetail = [] as Book.SelectBookTaskDetail[]
|
||||||
|
let book = await this.bookServiceBasic.GetBookDataById(bookTask.bookId)
|
||||||
|
let originalTimePath = path.join(book.bookFolderPath, `data/${book.id}.mp4.json`);
|
||||||
|
let originalTime = [] as any[];
|
||||||
|
if (await CheckFileOrDirExist(originalTimePath)) {
|
||||||
|
let originalTimeString = await fs.promises.readFile(originalTimePath, 'utf-8');
|
||||||
|
if (ValidateJson(originalTimeString)) {
|
||||||
|
originalTime = JSON.parse(originalTimeString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 判断分镜数据和批次数据是不是相同的
|
||||||
|
if (originalTime.length != oldBookTaskDetail.length) {
|
||||||
|
originalTime = []
|
||||||
|
}
|
||||||
|
for (let i = 0; i < oldBookTaskDetail.length; i++) {
|
||||||
|
const element = oldBookTaskDetail[i];
|
||||||
|
let addOneBookTaskDetail = {
|
||||||
|
id: uuidv4(),
|
||||||
|
no: element.no,
|
||||||
|
name: element.name,
|
||||||
|
bookId: element.bookId,
|
||||||
|
bookTaskId: newBookTask.id,
|
||||||
|
videoPath: path.relative(define.project_path, element.videoPath),
|
||||||
|
oldImage: path.relative(define.project_path, element.oldImage),
|
||||||
|
adetailer: element.adetailer,
|
||||||
|
sdConifg: element.sdConifg,
|
||||||
|
createTime: new Date(),
|
||||||
|
updateTime: new Date(),
|
||||||
|
audioPath: element.audioPath,
|
||||||
|
subtitlePosition: element.subtitlePosition,
|
||||||
|
status: BookTaskStatus.WAIT,
|
||||||
|
imageLock: false,
|
||||||
|
} as Book.SelectBookTaskDetail
|
||||||
|
|
||||||
|
// 开始添加数据
|
||||||
|
if (bookTask && addNewBookTask.selectTaskDataCategory && addNewBookTask.selectTaskDataCategory.length > 0) {
|
||||||
|
// 有选择的数据,这边要调用各种方法
|
||||||
|
if (addNewBookTask.selectTaskDataCategory.includes(AddBookTaskCopyData.AFTER_GPT)) {
|
||||||
|
// 是不是要复制文案
|
||||||
|
addOneBookTaskDetail.word = element.word
|
||||||
|
addOneBookTaskDetail.afterGpt = element.afterGpt
|
||||||
|
addOneBookTaskDetail.subValue = element.subValue ? JSON.stringify(element.subValue) : undefined
|
||||||
|
addOneBookTaskDetail.oldImage = element.oldImage
|
||||||
|
addOneBookTaskDetail.startTime = element.startTime
|
||||||
|
addOneBookTaskDetail.endTime = element.endTime
|
||||||
|
addOneBookTaskDetail.timeLimit = element.timeLimit;
|
||||||
|
} else {
|
||||||
|
// 初始化时间信息
|
||||||
|
if (originalTime[i]) {
|
||||||
|
addOneBookTaskDetail.startTime = TimeStringToMilliseconds(originalTime[i][0])
|
||||||
|
addOneBookTaskDetail.endTime = TimeStringToMilliseconds(originalTime[i][1])
|
||||||
|
addOneBookTaskDetail.timeLimit = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (addNewBookTask.selectTaskDataCategory.includes(AddBookTaskCopyData.GPT_PROMPT)) {
|
||||||
|
// 是不是要复制GPT提示词
|
||||||
|
addOneBookTaskDetail.gptPrompt = element.gptPrompt
|
||||||
|
// 复制反推提示词
|
||||||
|
// 处理反推数据
|
||||||
|
let reverseMessage = [] as Book.ReversePrompt[]
|
||||||
|
if (element.reversePrompt && element.reversePrompt.length > 0) {
|
||||||
|
reverseMessage = cloneDeep(element.reversePrompt)
|
||||||
|
for (let k = 0; k < reverseMessage.length; k++) {
|
||||||
|
reverseMessage[k].id = uuidv4()
|
||||||
|
reverseMessage[k].bookTaskDetailId = element.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addOneBookTaskDetail.reversePrompt = reverseMessage
|
||||||
|
}
|
||||||
|
if (addNewBookTask.selectTaskDataCategory.includes(AddBookTaskCopyData.CHARACTER)) {
|
||||||
|
// 是不是要复制角色
|
||||||
|
addOneBookTaskDetail.characterTags = element.characterTags
|
||||||
|
}
|
||||||
|
if (addNewBookTask.selectTaskDataCategory.includes(AddBookTaskCopyData.PROMPT)) {
|
||||||
|
// 是不是要复制提示
|
||||||
|
addOneBookTaskDetail.prompt = element.prompt
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
bookTaskDetail.push(addOneBookTaskDetail)
|
||||||
|
}
|
||||||
|
return bookTaskDetail
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制一份小说任务的基础数据
|
||||||
|
* @param bookTask 小说任务
|
||||||
|
* @param addNewBookTask 新增的小说数据
|
||||||
|
* @param no 当前的编号
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
CopyBookTaskBaseData(bookTask: Book.SelectBookTask, addNewBookTask: Book.AddBookTask, no: number): Book.SelectBookTask {
|
||||||
|
let name = 'output_' + no.toString().padStart(5, '0');
|
||||||
|
let imageFolder = path.join(define.project_path, `${bookTask.bookId}/tmp/${name}`);
|
||||||
|
let newBookTask = {
|
||||||
|
id: uuidv4(),
|
||||||
|
bookId: bookTask.bookId,
|
||||||
|
no: no,
|
||||||
|
name: name,
|
||||||
|
generateVideoPath: undefined,
|
||||||
|
srtPath: bookTask.srtPath,
|
||||||
|
audioPath: bookTask.audioPath,
|
||||||
|
imageFolder: path.relative(define.project_path, imageFolder),
|
||||||
|
status: BookTaskStatus.WAIT,
|
||||||
|
errorMsg: undefined,
|
||||||
|
updateTime: new Date(),
|
||||||
|
createTime: new Date(),
|
||||||
|
isAuto: false,
|
||||||
|
autoAnalyzeCharacter: undefined,
|
||||||
|
imageStyle: [],
|
||||||
|
customizeImageStyle: [],
|
||||||
|
videoConfig: bookTask.videoConfig ??= undefined,
|
||||||
|
prefixPrompt: addNewBookTask.prefixPrompt ??= undefined,
|
||||||
|
suffixPrompt: addNewBookTask.suffixPrompt ?? undefined,
|
||||||
|
imageCategory: bookTask.imageCategory ??= BookImageCategory.MJ,
|
||||||
|
subImageFolder: [],
|
||||||
|
draftSrtStyle: undefined,
|
||||||
|
backgroundMusic: bookTask.backgroundMusic ??= undefined,
|
||||||
|
friendlyReminder: bookTask.friendlyReminder ??= undefined,
|
||||||
|
} as Book.SelectBookTask
|
||||||
|
if (addNewBookTask.selectTaskDataCategory && addNewBookTask.selectTaskDataCategory.includes(AddBookTaskCopyData.IMAGE_STYLE)) {
|
||||||
|
newBookTask.imageStyle = bookTask.imageStyle ??= []
|
||||||
|
newBookTask.customizeImageStyle = bookTask.customizeImageStyle ??= []
|
||||||
|
}
|
||||||
|
return newBookTask
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyCopywrittingData() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加一个小说批次任务
|
||||||
|
* @param bookTask 小说任务
|
||||||
|
* @param bookTaskDetails 小说任务分镜信息
|
||||||
|
* @param addNewBookTask 添加数据的基础数据信息
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async AddOneBookTask(bookTask: Book.SelectBookTask, bookTaskDetails: Book.SelectBookTaskDetail[], addNewBookTask: Book.AddBookTask, no: number): Promise<{ newBookTask: Book.SelectBookTask, newBookTaskDetails: Book.SelectBookTaskDetail[] }> {
|
||||||
|
let newBookTask = this.CopyBookTaskBaseData(bookTask, addNewBookTask, no)
|
||||||
|
let newBookTaskDetails = await this.CopyBookTaskDetailBaseData(bookTask, newBookTask, bookTaskDetails, addNewBookTask)
|
||||||
|
return {
|
||||||
|
newBookTask: newBookTask,
|
||||||
|
newBookTaskDetails: newBookTaskDetails
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async InitService() {
|
|
||||||
if (!this.bookTaskService) {
|
/**
|
||||||
this.bookTaskService = await BookTaskService.getInstance()
|
* 添加个新的小说批次任务
|
||||||
}
|
* @param AddNewBookTask 添加的小说任务数据
|
||||||
if (!this.bookTaskDetailService) {
|
*/
|
||||||
this.bookTaskDetailService = await BookTaskDetailService.getInstance()
|
async AddNewBookTask(addNewBookTask: Book.AddBookTask): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
|
||||||
} if (!this.bookService) {
|
try {
|
||||||
this.bookService = await BookService.getInstance()
|
console.log(addNewBookTask)
|
||||||
|
let bookTask = await this.bookServiceBasic.GetBookTaskDataById(addNewBookTask.selectBookTask)
|
||||||
|
let oldBookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
|
||||||
|
bookTaskId: addNewBookTask.selectBookTask
|
||||||
|
})
|
||||||
|
let bookTasks = [] as Book.SelectBookTask[]
|
||||||
|
let bookTaskDetail = [] as Book.SelectBookTaskDetail[]
|
||||||
|
|
||||||
|
let maxNo = await this.bookServiceBasic.GetMaxBookTaskNo(bookTask.bookId)
|
||||||
|
for (let i = 0; i < addNewBookTask.count; i++) {
|
||||||
|
if (addNewBookTask.copyBookTask) {
|
||||||
|
let { newBookTask, newBookTaskDetails } = await this.AddOneBookTask(bookTask, oldBookTaskDetail, addNewBookTask, maxNo + i)
|
||||||
|
bookTasks.push(newBookTask)
|
||||||
|
bookTaskDetail.push(...newBookTaskDetails)
|
||||||
|
} else {
|
||||||
|
let newBookTask = this.CopyBookTaskBaseData({ bookId: bookTask.bookId }, addNewBookTask, maxNo + i)
|
||||||
|
bookTasks.push(newBookTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 先要创建文件夹
|
||||||
|
for (let i = 0; i < bookTasks.length; i++) {
|
||||||
|
let imageFolder = path.join(define.project_path, bookTasks[i].imageFolder)
|
||||||
|
await CheckFolderExistsOrCreate(imageFolder)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 这边开始添加数据
|
||||||
|
this.bookServiceBasic.transaction((realm) => {
|
||||||
|
for (let i = 0; i < bookTasks.length; i++) {
|
||||||
|
const element = bookTasks[i];
|
||||||
|
realm.create('BookTask', element)
|
||||||
|
}
|
||||||
|
for (let i = 0; i < bookTaskDetail.length; i++) {
|
||||||
|
const element = bookTaskDetail[i];
|
||||||
|
realm.create('BookTaskDetail', element)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return successMessage(null, "添加小说批次任务成功", "BookTask_AddNewBookTask")
|
||||||
|
} catch (error) {
|
||||||
|
return errorMessage('添加小说批次任务失败,错误信息如下' + error.toString(), "BookTask_AddNewBookTask");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置小说任务数据
|
* 重置小说任务数据
|
||||||
@ -40,13 +234,8 @@ export class BookTask {
|
|||||||
*/
|
*/
|
||||||
async ReSetBookTask(bookTaskId: string): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
async ReSetBookTask(bookTaskId: string): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
||||||
try {
|
try {
|
||||||
console.log(bookTaskId)
|
let bookTask = await this.bookServiceBasic.GetBookTaskDataById(bookTaskId);
|
||||||
await this.InitService()
|
await this.bookServiceBasic.ResetBookTask(bookTaskId);
|
||||||
let bookTask = this.bookTaskService.GetBookTaskDataById(bookTaskId);
|
|
||||||
if (bookTask == null) {
|
|
||||||
throw new Error('未找到对应的小说任务')
|
|
||||||
}
|
|
||||||
this.bookTaskService.ResetBookTask(bookTaskId);
|
|
||||||
// 数据库删除完毕,看是删除对应的文件(主要是图片)
|
// 数据库删除完毕,看是删除对应的文件(主要是图片)
|
||||||
let imageFolder = bookTask.imageFolder;
|
let imageFolder = bookTask.imageFolder;
|
||||||
// 整个删掉在重建
|
// 整个删掉在重建
|
||||||
@ -64,14 +253,10 @@ export class BookTask {
|
|||||||
*/
|
*/
|
||||||
async DeleteBookTask(bookTaskId: string): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
async DeleteBookTask(bookTaskId: string): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
||||||
try {
|
try {
|
||||||
await this.InitService();
|
let bookTask = await this.bookServiceBasic.GetBookTaskDataById(bookTaskId);
|
||||||
let bookTask = this.bookTaskService.GetBookTaskDataById(bookTaskId);
|
|
||||||
if (bookTask == null) {
|
|
||||||
throw new Error('未找到对应的小说任务,无法执行删除操作')
|
|
||||||
}
|
|
||||||
let imageFolder = bookTask.imageFolder;
|
let imageFolder = bookTask.imageFolder;
|
||||||
// 先删除每个批次对应的数据,然后删除批次
|
// 先删除每个批次对应的数据,然后删除批次
|
||||||
this.bookTaskService.DeleteBookTask(bookTaskId);
|
await this.bookServiceBasic.DeleteBookTaskData(bookTaskId);
|
||||||
// 删除成功,直接把对应的出图文件夹删掉
|
// 删除成功,直接把对应的出图文件夹删掉
|
||||||
await DeleteFolderAllFile(imageFolder, true)
|
await DeleteFolderAllFile(imageFolder, true)
|
||||||
return successMessage(null, "删除小说批次数据成功", "BookTask_DeleteBookTask")
|
return successMessage(null, "删除小说批次数据成功", "BookTask_DeleteBookTask")
|
||||||
@ -87,17 +272,15 @@ export class BookTask {
|
|||||||
*/
|
*/
|
||||||
async OneToFourBookTask(bookTaskId: string) {
|
async OneToFourBookTask(bookTaskId: string) {
|
||||||
try {
|
try {
|
||||||
console.log(bookTaskId)
|
|
||||||
await this.InitService();
|
|
||||||
let copyCount = 100
|
let copyCount = 100
|
||||||
let bookTask = this.bookTaskService.GetBookTaskDataById(bookTaskId)
|
let bookTask = await this.bookServiceBasic.GetBookTaskDataById(bookTaskId)
|
||||||
if (bookTask == null) {
|
if (bookTask == null) {
|
||||||
throw new Error("没有找到对应的数小说任务,请检查数据")
|
throw new Error("没有找到对应的数小说任务,请检查数据")
|
||||||
}
|
}
|
||||||
// 获取所有的出图中最少的
|
// 获取所有的出图中最少的
|
||||||
let bookTaskDetail = this.bookTaskDetailService.GetBookTaskData({
|
let bookTaskDetail = (await this.bookServiceBasic.GetBookTaskData({
|
||||||
bookTaskId: bookTaskId
|
bookTaskId: bookTaskId
|
||||||
}).data as Book.SelectBookTaskDetail[]
|
})).bookTasks as Book.SelectBookTaskDetail[]
|
||||||
if (bookTaskDetail == null || bookTaskDetail.length <= 0) {
|
if (bookTaskDetail == null || bookTaskDetail.length <= 0) {
|
||||||
throw new Error("没有对应的小说分镜任务,请先添加分镜任务")
|
throw new Error("没有对应的小说分镜任务,请先添加分镜任务")
|
||||||
}
|
}
|
||||||
@ -136,17 +319,12 @@ export class BookTask {
|
|||||||
*/
|
*/
|
||||||
async CopyNewBookTask(sourceBookTask: Book.SelectBookTask, sourceBookTaskDetail: Book.SelectBookTaskDetail[], copyCount: number, copyImageType: CopyImageType) {
|
async CopyNewBookTask(sourceBookTask: Book.SelectBookTask, sourceBookTaskDetail: Book.SelectBookTaskDetail[], copyCount: number, copyImageType: CopyImageType) {
|
||||||
try {
|
try {
|
||||||
await this.InitService();
|
|
||||||
let addBookTask = [] as Book.SelectBookTask[]
|
let addBookTask = [] as Book.SelectBookTask[]
|
||||||
let addBookTaskDetail = [] as Book.SelectBookTaskDetail[]
|
let addBookTaskDetail = [] as Book.SelectBookTaskDetail[]
|
||||||
|
|
||||||
// 先处理文件夹的创建,包括小说任务的和小说任务分镜的
|
// 先处理文件夹的创建,包括小说任务的和小说任务分镜的
|
||||||
for (let i = 0; i < copyCount; i++) {
|
for (let i = 0; i < copyCount; i++) {
|
||||||
let maxNo = this.bookTaskService.realm
|
let no = await this.bookServiceBasic.GetMaxBookTaskNo(sourceBookTask.bookId)
|
||||||
.objects('BookTask')
|
|
||||||
.filtered('bookId = $0', sourceBookTask.bookId)
|
|
||||||
.max('no')
|
|
||||||
let no = maxNo == null ? 1 : Number(maxNo) + 1 + i
|
|
||||||
let name = 'output_0000' + no
|
let name = 'output_0000' + no
|
||||||
let imageFolder = path.join(define.project_path, `${sourceBookTask.bookId}/tmp/${name}`)
|
let imageFolder = path.join(define.project_path, `${sourceBookTask.bookId}/tmp/${name}`)
|
||||||
await CheckFolderExistsOrCreate(imageFolder)
|
await CheckFolderExistsOrCreate(imageFolder)
|
||||||
@ -265,21 +443,21 @@ export class BookTask {
|
|||||||
|
|
||||||
// 数据处理完毕,开始新增数据
|
// 数据处理完毕,开始新增数据
|
||||||
// 将所有的复制才做,全部放在一个事务中
|
// 将所有的复制才做,全部放在一个事务中
|
||||||
this.bookTaskService.transaction(() => {
|
this.bookServiceBasic.transaction((realm) => {
|
||||||
for (let i = 0; i < addBookTask.length; i++) {
|
for (let i = 0; i < addBookTask.length; i++) {
|
||||||
const element = addBookTask[i];
|
const element = addBookTask[i];
|
||||||
this.bookTaskService.realm.create('BookTask', element)
|
realm.create('BookTask', element)
|
||||||
}
|
}
|
||||||
for (let i = 0; i < addBookTaskDetail.length; i++) {
|
for (let i = 0; i < addBookTaskDetail.length; i++) {
|
||||||
const element = addBookTaskDetail[i];
|
const element = addBookTaskDetail[i];
|
||||||
this.bookTaskDetailService.realm.create('BookTaskDetail', element)
|
realm.create('BookTaskDetail', element)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// 全部创建完成
|
// 全部创建完成
|
||||||
// 查找到数据,然后全部返回
|
// 查找到数据,然后全部返回
|
||||||
let returnBookTask = this.bookTaskService.GetBookTaskData({
|
let returnBookTask = (await this.bookServiceBasic.GetBookTaskData({
|
||||||
bookId: sourceBookTask.bookId
|
bookId: sourceBookTask.bookId
|
||||||
}).data as Book.SelectBookTask[]
|
})).bookTasks as Book.SelectBookTask[]
|
||||||
|
|
||||||
return successMessage(returnBookTask, "复制小说任务成功", "BookBasic_CopyNewBookTask")
|
return successMessage(returnBookTask, "复制小说任务成功", "BookBasic_CopyNewBookTask")
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { BookBackTaskListService } from "../../../define/db/service/Book/bookBac
|
|||||||
import { BookTaskDetailService } from "../../../define/db/service/Book/bookTaskDetailService";
|
import { BookTaskDetailService } from "../../../define/db/service/Book/bookTaskDetailService";
|
||||||
import { CheckFolderExistsOrCreate, CopyFileOrFolder, JoinPath } from "../../../define/Tools/file";
|
import { CheckFolderExistsOrCreate, CopyFileOrFolder, JoinPath } from "../../../define/Tools/file";
|
||||||
import { define } from "../../../define/define"
|
import { define } from "../../../define/define"
|
||||||
import { GetImageBase64, ImageSplit } from "../../../define/Tools/image";
|
import { CompressImageToSize, GetImageBase64, ImageSplit } from "../../../define/Tools/image";
|
||||||
import MJApi from "./mjApi"
|
import MJApi from "./mjApi"
|
||||||
import { BookBackTaskStatus, BookBackTaskType, BookTaskStatus, BookType, DialogType, MJAction, OperateBookType, TaskExecuteType } from "../../../define/enum/bookEnum";
|
import { BookBackTaskStatus, BookBackTaskType, BookTaskStatus, BookType, DialogType, MJAction, OperateBookType, TaskExecuteType } from "../../../define/enum/bookEnum";
|
||||||
import { DEFINE_STRING } from "../../../define/define_string";
|
import { DEFINE_STRING } from "../../../define/define_string";
|
||||||
@ -214,10 +214,16 @@ export class MJOpt {
|
|||||||
throw new Error(`${bookTaskDetail.name} 没有需要反推的图片`);
|
throw new Error(`${bookTaskDetail.name} 没有需要反推的图片`);
|
||||||
}
|
}
|
||||||
oldImagePath = JoinPath(define.project_path, oldImagePath)
|
oldImagePath = JoinPath(define.project_path, oldImagePath)
|
||||||
let imageBase64 = await GetImageBase64(oldImagePath)
|
// let imageBase64 = await GetImageBase64(oldImagePath)
|
||||||
|
|
||||||
|
// 每次执行前压缩图片
|
||||||
|
let newImageBase64 = await CompressImageToSize(oldImagePath, 500000);
|
||||||
|
// 将buffer转换为base64
|
||||||
|
let imageBase64 = newImageBase64.toString('base64');
|
||||||
|
|
||||||
// 这个就是任务ID
|
// 这个就是任务ID
|
||||||
let reqRes = await this.mjApi.SubmitMJDescribe({
|
let reqRes = await this.mjApi.SubmitMJDescribe({
|
||||||
image: imageBase64,
|
image: 'data:image/png;base64,' + imageBase64,
|
||||||
taskId: task.id
|
taskId: task.id
|
||||||
})
|
})
|
||||||
if (reqRes == '23') {
|
if (reqRes == '23') {
|
||||||
@ -394,8 +400,8 @@ export class MJOpt {
|
|||||||
if (bookTask.prefixPrompt) {
|
if (bookTask.prefixPrompt) {
|
||||||
promptStr = checkStringValueAddSuffix(bookTask.prefixPrompt, ',') + promptStr
|
promptStr = checkStringValueAddSuffix(bookTask.prefixPrompt, ',') + promptStr
|
||||||
}
|
}
|
||||||
if (bookTask.prefixPrompt) {
|
if (bookTask.suffixPrompt) {
|
||||||
promptStr = checkStringValueAddSuffix(promptStr, ',') + bookTask.prefixPrompt
|
promptStr = checkStringValueAddSuffix(promptStr, ',') + bookTask.suffixPrompt
|
||||||
}
|
}
|
||||||
promptStr = ' ' + promptStr;
|
promptStr = ' ' + promptStr;
|
||||||
promptStr += ` ${cref_url} ${style_url}${suffixParam}`
|
promptStr += ` ${cref_url} ${style_url}${suffixParam}`
|
||||||
|
|||||||
@ -1,11 +1,8 @@
|
|||||||
import { Book } from "../../../model/book";
|
import { Book } from "../../../model/book";
|
||||||
import { GeneralResponse } from "../../../model/generalResponse";
|
import { GeneralResponse } from "../../../model/generalResponse";
|
||||||
import { checkStringValueAddSuffix, errorMessage, successMessage } from "../../Public/generalTools";
|
import { checkStringValueAddSuffix, errorMessage, successMessage } from "../../Public/generalTools";
|
||||||
import { BookTaskDetailService } from "../../../define/db/service/Book/bookTaskDetailService";
|
|
||||||
import { BookTaskService } from "../../../define/db/service/Book/bookTaskService";
|
|
||||||
import { define } from '../../../define/define'
|
import { define } from '../../../define/define'
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { ImageStyleDefine } from "../../../define/iamgeStyleDefine";
|
|
||||||
import { ImageStyle } from "../Book/imageStyle";
|
import { ImageStyle } from "../Book/imageStyle";
|
||||||
import { OperateBookType } from "../../../define/enum/bookEnum";
|
import { OperateBookType } from "../../../define/enum/bookEnum";
|
||||||
import { isEmpty } from "lodash";
|
import { isEmpty } from "lodash";
|
||||||
@ -13,26 +10,22 @@ import { BookServiceBasic } from "../ServiceBasic/bookServiceBasic";
|
|||||||
const fspromise = fs.promises
|
const fspromise = fs.promises
|
||||||
|
|
||||||
export class SDOpt {
|
export class SDOpt {
|
||||||
bookTaskDetailService: BookTaskDetailService
|
|
||||||
bookTaskService: BookTaskService
|
|
||||||
imageStyle: ImageStyle
|
imageStyle: ImageStyle
|
||||||
|
|
||||||
bookServiceBasic: BookServiceBasic
|
bookServiceBasic: BookServiceBasic
|
||||||
constructor() {
|
constructor() {
|
||||||
this.bookServiceBasic = new BookServiceBasic()
|
this.bookServiceBasic = new BookServiceBasic()
|
||||||
|
this.imageStyle = new ImageStyle()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async InitService() {
|
// TODO 这边的设置应该改为数据库
|
||||||
if (!this.bookTaskDetailService) {
|
/**
|
||||||
this.bookTaskDetailService = await BookTaskDetailService.getInstance()
|
* 获取SD的设置,之后要删掉,改为数据库
|
||||||
}
|
*/
|
||||||
if (!this.bookTaskService) {
|
private async GetSDSetting() {
|
||||||
this.bookTaskService = await BookTaskService.getInstance()
|
let sdSetting = JSON.parse(await fspromise.readFile(define.sd_setting, 'utf-8'))
|
||||||
}
|
return sdSetting
|
||||||
if (!this.imageStyle) {
|
|
||||||
this.imageStyle = new ImageStyle()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,15 +36,16 @@ export class SDOpt {
|
|||||||
*/
|
*/
|
||||||
async MergePrompt(id: string, operateBookType: OperateBookType): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
async MergePrompt(id: string, operateBookType: OperateBookType): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
||||||
try {
|
try {
|
||||||
await this.InitService()
|
|
||||||
let bookTaskDetail = undefined as Book.SelectBookTaskDetail[];
|
let bookTaskDetail = undefined as Book.SelectBookTaskDetail[];
|
||||||
let bookTask = undefined as Book.SelectBookTask;
|
let bookTask = undefined as Book.SelectBookTask;
|
||||||
|
let sd_setting = await this.GetSDSetting();
|
||||||
|
let style_weight = sd_setting.setting.style_weight ? sd_setting.setting.style_weight : 1
|
||||||
|
|
||||||
if (operateBookType == OperateBookType.BOOKTASK) {
|
if (operateBookType == OperateBookType.BOOKTASK) {
|
||||||
bookTaskDetail = this.bookTaskDetailService.GetBookTaskData({
|
bookTaskDetail = (await this.bookServiceBasic.GetBookTaskData({
|
||||||
bookTaskId: id
|
bookTaskId: id
|
||||||
}).data
|
})).bookTasks;
|
||||||
bookTask = this.bookTaskService.GetBookTaskDataById(id);
|
bookTask = await this.bookServiceBasic.GetBookTaskDataById(id);
|
||||||
// 判断是不是有为空的
|
// 判断是不是有为空的
|
||||||
let emptyName = [] as string[]
|
let emptyName = [] as string[]
|
||||||
for (let i = 0; i < bookTaskDetail.length; i++) {
|
for (let i = 0; i < bookTaskDetail.length; i++) {
|
||||||
@ -69,7 +63,7 @@ export class SDOpt {
|
|||||||
throw new Error("当前分镜没有推理提示词,请先生成")
|
throw new Error("当前分镜没有推理提示词,请先生成")
|
||||||
}
|
}
|
||||||
bookTaskDetail = [tempBookTaskDetail];
|
bookTaskDetail = [tempBookTaskDetail];
|
||||||
bookTask = this.bookTaskService.GetBookTaskDataById(bookTaskDetail[0].bookTaskId);
|
bookTask = await this.bookServiceBasic.GetBookTaskDataById(bookTaskDetail[0].bookTaskId);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("未知的合并类型")
|
throw new Error("未知的合并类型")
|
||||||
}
|
}
|
||||||
@ -86,12 +80,12 @@ export class SDOpt {
|
|||||||
for (let i = 0; i < styleArr.length; i++) {
|
for (let i = 0; i < styleArr.length; i++) {
|
||||||
const element = styleArr[i]
|
const element = styleArr[i]
|
||||||
if (element.type == 'style_main') {
|
if (element.type == 'style_main') {
|
||||||
styleString += element.prompt + ', '
|
styleString += `(${element.prompt}:${style_weight})` + ', '
|
||||||
if (element.lora && element.lora != '无' && element.lora_weight) {
|
if (element.lora && element.lora != '无' && element.lora_weight) {
|
||||||
styleString += `<lora:${element.lora}:${element.lora_weight}>, `
|
styleString += `<lora:${element.lora}:${element.lora_weight}>, `
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
styleString += element.english_style + ','
|
styleString += `(${element.english_style}:${style_weight})` + ','
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,8 +120,8 @@ export class SDOpt {
|
|||||||
if (bookTask.prefixPrompt) {
|
if (bookTask.prefixPrompt) {
|
||||||
promptStr = checkStringValueAddSuffix(bookTask.prefixPrompt, ',') + promptStr
|
promptStr = checkStringValueAddSuffix(bookTask.prefixPrompt, ',') + promptStr
|
||||||
}
|
}
|
||||||
if (bookTask.prefixPrompt) {
|
if (bookTask.suffixPrompt) {
|
||||||
promptStr = checkStringValueAddSuffix(promptStr, ',') + bookTask.prefixPrompt
|
promptStr = checkStringValueAddSuffix(promptStr, ',') + bookTask.suffixPrompt
|
||||||
}
|
}
|
||||||
if (sdGlobalPrompt) {
|
if (sdGlobalPrompt) {
|
||||||
promptStr = checkStringValueAddSuffix(sdGlobalPrompt, ',') + promptStr
|
promptStr = checkStringValueAddSuffix(sdGlobalPrompt, ',') + promptStr
|
||||||
@ -136,7 +130,7 @@ export class SDOpt {
|
|||||||
promptStr = ' ' + promptStr;
|
promptStr = ' ' + promptStr;
|
||||||
console.log(promptStr)
|
console.log(promptStr)
|
||||||
// 修改数据库数据
|
// 修改数据库数据
|
||||||
this.bookTaskDetailService.UpdateBookTaskDetail(element.id, {
|
await this.bookServiceBasic.UpdateBookTaskDetail(element.id, {
|
||||||
prompt: promptStr
|
prompt: promptStr
|
||||||
})
|
})
|
||||||
// 写回数据
|
// 写回数据
|
||||||
@ -147,7 +141,6 @@ export class SDOpt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return successMessage(result, "SD和并提示词数据成功", "SDOpt_MergePrompt")
|
return successMessage(result, "SD和并提示词数据成功", "SDOpt_MergePrompt")
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return errorMessage("SD合并提示词,错误信息如下:" + error.toString(), "SDOpt_MergePrompt")
|
return errorMessage("SD合并提示词,错误信息如下:" + error.toString(), "SDOpt_MergePrompt")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,16 @@ export class BookServiceBasic {
|
|||||||
global.newWindow[0].win.webContents.send(message_name, data)
|
global.newWindow[0].win.webContents.send(message_name, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//#region 事务操作
|
||||||
|
transaction(callback: (realm: any) => void) {
|
||||||
|
this.bookService.transaction(() => {
|
||||||
|
callback(this.bookService.realm)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
//#region 小说相关的基础服务
|
//#region 小说相关的基础服务
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,6 +121,20 @@ export class BookServiceBasic {
|
|||||||
return bookTasks.data
|
return bookTasks.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取最大的小说批次任务的编号
|
||||||
|
* @param bookId 小说ID
|
||||||
|
*/
|
||||||
|
async GetMaxBookTaskNo(bookId: string): Promise<number> {
|
||||||
|
await this.InitService();
|
||||||
|
let maxNo = this.bookTaskService.realm
|
||||||
|
.objects('BookTask')
|
||||||
|
.filtered('bookId = $0', bookId)
|
||||||
|
.max('no')
|
||||||
|
let no = maxNo == null ? 1 : Number(maxNo) + 1
|
||||||
|
return no
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新小说批次任务的数据
|
* 更新小说批次任务的数据
|
||||||
* @param bookTaskId 小说批次任务ID
|
* @param bookTaskId 小说批次任务ID
|
||||||
@ -121,6 +145,15 @@ export class BookServiceBasic {
|
|||||||
this.bookTaskService.UpdetedBookTaskData(bookTaskId, data)
|
this.bookTaskService.UpdetedBookTaskData(bookTaskId, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置小说批次任务的数据
|
||||||
|
* @param bookTaskId 指定的重置的小说批次任务的ID
|
||||||
|
*/
|
||||||
|
async ResetBookTask(bookTaskId: string): Promise<void> {
|
||||||
|
await this.InitService();
|
||||||
|
this.bookTaskService.ResetBookTask(bookTaskId)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除指定的小说批次任务的数据
|
* 删除指定的小说批次任务的数据
|
||||||
* @param bookTaskId 需要删除的指定的小说批次任务ID
|
* @param bookTaskId 需要删除的指定的小说批次任务ID
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { CheckFileOrDirExist } from "../../../define/Tools/file";
|
|||||||
import { BookServiceBasic } from "../ServiceBasic/bookServiceBasic";
|
import { BookServiceBasic } from "../ServiceBasic/bookServiceBasic";
|
||||||
import { Subtitle } from "./subtitle";
|
import { Subtitle } from "./subtitle";
|
||||||
import { TaskScheduler } from "../taskScheduler";
|
import { TaskScheduler } from "../taskScheduler";
|
||||||
import { OperateBookType } from "../../../define/enum/bookEnum";
|
import { BookType, OperateBookType } from "../../../define/enum/bookEnum";
|
||||||
import { Book } from "../../../model/book";
|
import { Book } from "../../../model/book";
|
||||||
import { TimeStringToMilliseconds } from "../../../define/Tools/time";
|
import { TimeStringToMilliseconds } from "../../../define/Tools/time";
|
||||||
|
|
||||||
@ -189,8 +189,9 @@ export class SubtitleService {
|
|||||||
return errorMessage("获取分镜数据失败,失败信息如下:" + error.message, 'ReverseBook_GetCopywriting')
|
return errorMessage("获取分镜数据失败,失败信息如下:" + error.message, 'ReverseBook_GetCopywriting')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region 文案相关的操作
|
||||||
/**
|
/**
|
||||||
* 导出指定导出指定小说的文案
|
* 导出指定导出指定小说的文案
|
||||||
* @param bookTaskId 小说批次任务ID
|
* @param bookTaskId 小说批次任务ID
|
||||||
@ -231,7 +232,57 @@ export class SubtitleService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region 文案相关的操作
|
/**
|
||||||
|
* 将
|
||||||
|
* @param bookId
|
||||||
|
* @param bookTaskId
|
||||||
|
* @param txtPath
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async ImportCopywriting(bookId: string, bookTaskId: string, txtPath: string): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
||||||
|
try {
|
||||||
|
let word = await fs.promises.readFile(txtPath, 'utf-8');
|
||||||
|
let wordLines = word.split('\n').map(line => line.trim()).filter(line => line.length > 0);
|
||||||
|
// 判断小说类型,是反推的话,文案和分镜数据要对应
|
||||||
|
let book = await this.bookServiceBasic.GetBookDataById(bookId)
|
||||||
|
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
|
||||||
|
bookId: bookId,
|
||||||
|
bookTaskId: bookTaskId
|
||||||
|
})
|
||||||
|
|
||||||
|
if (book.type == BookType.MJ_REVERSE || book.type == BookType.SD_REVERSE) {
|
||||||
|
if (wordLines.length != bookTaskDetail.length) {
|
||||||
|
throw new Error("文案行数和分镜数据不对应,请检查")
|
||||||
|
}
|
||||||
|
} else if (book.type == BookType.ORIGINAL) {
|
||||||
|
// 原创这边也要做些判断,待定
|
||||||
|
throw new Error("原创小说暂时不支持导入文案");
|
||||||
|
} else {
|
||||||
|
throw new Error("未知的小说类型,请检查")
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = []
|
||||||
|
// 这边开始导入文案,这边使用事务
|
||||||
|
this.bookServiceBasic.transaction((realm) => {
|
||||||
|
for (let i = 0; i < bookTaskDetail.length; i++) {
|
||||||
|
const element = bookTaskDetail[i];
|
||||||
|
let btd = realm.objectForPrimaryKey("BookTaskDetail", element.id);
|
||||||
|
let ag = wordLines[i] ? wordLines[i] : ''
|
||||||
|
|
||||||
|
btd.afterGpt = ag
|
||||||
|
result.push({
|
||||||
|
bookTaskDetailId: element.id,
|
||||||
|
afterGpt: ag
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return successMessage(result, "导入文案成功", "ReverseBook_ImportCopywriting")
|
||||||
|
} catch (error) {
|
||||||
|
return errorMessage("导入文案失败,失败信息如下:" + error.message, 'ReverseBook_ImportCopywriting')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除导入的对齐后的文案
|
* 清除导入的对齐后的文案
|
||||||
@ -287,6 +338,4 @@ export class SubtitleService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#endregion
|
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ export class FfmpegOptions {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Ffmpeg(tempVideo)
|
Ffmpeg(tempVideo)
|
||||||
.outputOptions([
|
.outputOptions([
|
||||||
`-vf scale=${width}:${height}`, // 调整视频尺寸到 1280x720
|
`-vf scale=${Math.floor(width)}:${Math.floor(height)}`, // 调整视频尺寸到 1280x720
|
||||||
`-b:v ${crf}` // 设置视频比特率为 1000kbps
|
`-b:v ${crf}` // 设置视频比特率为 1000kbps
|
||||||
])
|
])
|
||||||
.on('end', async () => {
|
.on('end', async () => {
|
||||||
|
|||||||
@ -66,12 +66,12 @@ async function createWindow(hash = 'ShowMessage', data, url = null) {
|
|||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: join(__dirname, '../preload/index.js'),
|
preload: join(__dirname, '../preload/index.js'),
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
nodeIntegration: hash == 'discord' ? false : true, // 在网页中集成Node
|
nodeIntegration: true, // 在网页中集成Node
|
||||||
nodeIntegrationInWorker: true,
|
nodeIntegrationInWorker: true,
|
||||||
webSecurity: false,
|
webSecurity: false,
|
||||||
partition: 'persist:my-partition',
|
partition: 'persist:my-partition',
|
||||||
session: ses,
|
session: ses,
|
||||||
webviewTag : true,
|
webviewTag: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
41
src/model/book.d.ts
vendored
41
src/model/book.d.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
import { BookBackTaskStatus, BookBackTaskType, BookTaskStatus, BookType, TaskExecuteType } from "../define/enum/bookEnum"
|
import { BookBackTaskStatus, BookBackTaskType, BookTaskStatus, BookType, TaskExecuteType, BookRepalceDataType } from "../define/enum/bookEnum"
|
||||||
import { MJAction } from "../define/enum/bookEnum"
|
import { MJAction } from "../define/enum/bookEnum"
|
||||||
import { MJImageType } from "../define/enum/mjEnum"
|
import { MJImageType } from "../define/enum/mjEnum"
|
||||||
|
|
||||||
@ -76,6 +76,16 @@ declare namespace Book {
|
|||||||
subImageFolder?: string[] | null // 子图片文件夹地址,多个
|
subImageFolder?: string[] | null // 子图片文件夹地址,多个
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加批次任务
|
||||||
|
type AddBookTask = {
|
||||||
|
copyBookTask: boolean // 是否复制旧的小说任务
|
||||||
|
count: number // 批次数量
|
||||||
|
prefixPrompt?: string // 前缀提示
|
||||||
|
suffixPrompt?: string // 后缀提示词
|
||||||
|
selectBookTask?: string // 选择的旧的小说任务
|
||||||
|
selectTaskDataCategory?: string[] // 选择复制的数据类型
|
||||||
|
}
|
||||||
|
|
||||||
// 字幕相关
|
// 字幕相关
|
||||||
type Subtitle = {
|
type Subtitle = {
|
||||||
startTime: number
|
startTime: number
|
||||||
@ -246,4 +256,33 @@ declare namespace Book {
|
|||||||
id?: string
|
id?: string
|
||||||
image?: string
|
image?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 裁剪小视频的返回数据类型
|
||||||
|
*/
|
||||||
|
type BookFrameShortClip = {
|
||||||
|
startTime: number
|
||||||
|
endTime: number
|
||||||
|
videoPath: string
|
||||||
|
duration: number
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region 替换小说数据
|
||||||
|
|
||||||
|
type BookReplaceData = {
|
||||||
|
before: string,
|
||||||
|
after: string,
|
||||||
|
replaceAll?: boolean,
|
||||||
|
type: BookRepalceDataType
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReplaceDataRes = {
|
||||||
|
bookTaskDetailId: string,
|
||||||
|
newData: string,
|
||||||
|
type?: 'reversePrompt' | 'gptPrompt' | 'afterGpt' | 'prompt',
|
||||||
|
reversePromptType?: 'prompt' | 'promptCN'
|
||||||
|
reversePromptId?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { ipcRenderer } from 'electron'
|
import { ipcRenderer } from 'electron'
|
||||||
import { DEFINE_STRING } from '../define/define_string'
|
import { DEFINE_STRING } from '../define/define_string'
|
||||||
|
import { Book } from '../model/book'
|
||||||
|
|
||||||
const book = {
|
const book = {
|
||||||
// 获取小说操作类型(原创/SD反推/MJ反推)
|
// 获取小说操作类型(原创/SD反推/MJ反推)
|
||||||
@ -51,6 +52,18 @@ const book = {
|
|||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
//#region 小说通用操作
|
||||||
|
|
||||||
|
// 替换文案数据
|
||||||
|
ReplaceBookData: async (bookTaskId: string, replaceData: Book.BookReplaceData) =>
|
||||||
|
await ipcRenderer.invoke(
|
||||||
|
DEFINE_STRING.BOOK.REPLACE_BOOK_DATA,
|
||||||
|
bookTaskId,
|
||||||
|
replaceData
|
||||||
|
),
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
//#region 分镜
|
//#region 分镜
|
||||||
|
|
||||||
// 开始计算分镜数据
|
// 开始计算分镜数据
|
||||||
@ -85,6 +98,10 @@ const book = {
|
|||||||
ExportCopywriting: async (bookTaskId) =>
|
ExportCopywriting: async (bookTaskId) =>
|
||||||
await ipcRenderer.invoke(DEFINE_STRING.BOOK.EXPORT_COPYWRITING, bookTaskId),
|
await ipcRenderer.invoke(DEFINE_STRING.BOOK.EXPORT_COPYWRITING, bookTaskId),
|
||||||
|
|
||||||
|
// 导入文案,修改过后的
|
||||||
|
ImportCopywriting: async (bookId: string, bookTaskId: string, txtPath: string) =>
|
||||||
|
await ipcRenderer.invoke(DEFINE_STRING.BOOK.IMPORT_COPYWRITING, bookId, bookTaskId, txtPath),
|
||||||
|
|
||||||
// 清除导入对齐的文案
|
// 清除导入对齐的文案
|
||||||
ClearImportWord: async (bookTaskId) =>
|
ClearImportWord: async (bookTaskId) =>
|
||||||
await ipcRenderer.invoke(DEFINE_STRING.BOOK.CLEAR_IMPORT_WORD, bookTaskId),
|
await ipcRenderer.invoke(DEFINE_STRING.BOOK.CLEAR_IMPORT_WORD, bookTaskId),
|
||||||
@ -183,6 +200,10 @@ const book = {
|
|||||||
|
|
||||||
//#region 小说批次任务相关
|
//#region 小说批次任务相关
|
||||||
|
|
||||||
|
// 添加新的小说批次任务
|
||||||
|
AddNewBookTask: async (addBookTaskData) =>
|
||||||
|
await ipcRenderer.invoke(DEFINE_STRING.BOOK.ADD_NEW_BOOK_TASK, addBookTaskData),
|
||||||
|
|
||||||
// 重置小说批次数据
|
// 重置小说批次数据
|
||||||
ReSetBookTask: async (bookTaskId) =>
|
ReSetBookTask: async (bookTaskId) =>
|
||||||
await ipcRenderer.invoke(DEFINE_STRING.BOOK.RESET_BOOK_TASK, bookTaskId),
|
await ipcRenderer.invoke(DEFINE_STRING.BOOK.RESET_BOOK_TASK, bookTaskId),
|
||||||
@ -8,7 +8,7 @@ import { img } from './img.js'
|
|||||||
import { system } from './system.js'
|
import { system } from './system.js'
|
||||||
import { setting } from './setting.js'
|
import { setting } from './setting.js'
|
||||||
import { prompt } from './prompt.js'
|
import { prompt } from './prompt.js'
|
||||||
import { book } from './book.js'
|
import { book } from './book'
|
||||||
import { tts } from './tts.js'
|
import { tts } from './tts.js'
|
||||||
import { write } from './write.js'
|
import { write } from './write.js'
|
||||||
import { gpt } from './gpt.js'
|
import { gpt } from './gpt.js'
|
||||||
|
|||||||
@ -1,15 +1,42 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="width: 100%; height: 100%">
|
<div style="width: 100%; height: 100%">
|
||||||
<webview style="width: 100%; height: 100%" src="https://api.laitool.cc" partition="persist:your-session-name"></webview>
|
<webview
|
||||||
|
id="lai-api"
|
||||||
|
style="width: 100%; height: 100%"
|
||||||
|
src="https://api.laitool.cc"
|
||||||
|
partition="persist:your-session-name"
|
||||||
|
></webview>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent } from 'vue'
|
import { defineComponent, onMounted, onUnmounted } from 'vue'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {},
|
components: {},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
|
onMounted(() => {
|
||||||
|
const webview = document.getElementById('lai-api')
|
||||||
|
if (webview) {
|
||||||
|
debugger
|
||||||
|
const handleNewWindow = (event) => {
|
||||||
|
debugger
|
||||||
|
event.preventDefault()
|
||||||
|
alert(123)
|
||||||
|
const protocol = new URL(event.url).protocol
|
||||||
|
if (protocol === 'http:' || protocol === 'https:') {
|
||||||
|
window.api.OpenUrl(protocol) // 确保传递完整的 URL 而不是仅协议
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
webview.addEventListener('new-window', handleNewWindow)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 在组件卸载时移除事件监听器
|
||||||
|
// onUnmounted(() => {
|
||||||
|
// webview.removeEventListener('new-window', handleNewWindow)
|
||||||
|
// })
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -265,7 +265,6 @@ export default defineComponent({
|
|||||||
// 初始化加载项目下面的分镜好的文案
|
// 初始化加载项目下面的分镜好的文案
|
||||||
// 并判断是不是有洗稿后的文件。一并加载
|
// 并判断是不是有洗稿后的文件。一并加载
|
||||||
await window.api.GetProjectWord((value) => {
|
await window.api.GetProjectWord((value) => {
|
||||||
|
|
||||||
data.value = value.data
|
data.value = value.data
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -358,7 +357,6 @@ export default defineComponent({
|
|||||||
let itemIndex = row.subValue.findIndex((item) => item.id == itemId)
|
let itemIndex = row.subValue.findIndex((item) => item.id == itemId)
|
||||||
let thisIndex = data.value.findIndex((item) => item.id == row.id)
|
let thisIndex = data.value.findIndex((item) => item.id == row.id)
|
||||||
if (itemIndex < 0 && isM) {
|
if (itemIndex < 0 && isM) {
|
||||||
|
|
||||||
message.error('数据错误')
|
message.error('数据错误')
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
@ -551,7 +549,7 @@ export default defineComponent({
|
|||||||
async function AIModifyOneWord(row) {
|
async function AIModifyOneWord(row) {
|
||||||
await window.api.AIModifyOneWord([row.no, row.word], (value) => {
|
await window.api.AIModifyOneWord([row.no, row.word], (value) => {
|
||||||
if (value.code != 1) {
|
if (value.code != 1) {
|
||||||
message.error('未知错误')
|
message.error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 修改数据
|
// 修改数据
|
||||||
@ -599,7 +597,7 @@ export default defineComponent({
|
|||||||
// 开始保存
|
// 开始保存
|
||||||
await window.api.SaveNewWord(new_data_word, (value) => {
|
await window.api.SaveNewWord(new_data_word, (value) => {
|
||||||
if (value.code != 1) {
|
if (value.code != 1) {
|
||||||
message.error('未知错误')
|
message.error(value.message)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
message.success('保存成功,并写入到了剪贴板')
|
message.success('保存成功,并写入到了剪贴板')
|
||||||
@ -614,7 +612,7 @@ export default defineComponent({
|
|||||||
[toRaw(data.value), 'srt_time_information'],
|
[toRaw(data.value), 'srt_time_information'],
|
||||||
(value) => {
|
(value) => {
|
||||||
if (value.code != 1) {
|
if (value.code != 1) {
|
||||||
message.error('未知错误')
|
message.error(value.message)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
message.success('保存成功')
|
message.success('保存成功')
|
||||||
|
|||||||
@ -32,7 +32,6 @@ export default defineComponent({
|
|||||||
props: ['initData', 'index'],
|
props: ['initData', 'index'],
|
||||||
setup(props) {
|
setup(props) {
|
||||||
let data = ref(props.initData)
|
let data = ref(props.initData)
|
||||||
console.log('subValue', data.value)
|
|
||||||
onMounted(async () => {})
|
onMounted(async () => {})
|
||||||
let InputDebounced = debounce(handleInput, 1000)
|
let InputDebounced = debounce(handleInput, 1000)
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<div style="display: flex; justify-content: space-between; white-space: nowrap">
|
||||||
|
<span>文案</span>
|
||||||
|
<n-popover trigger="hover">
|
||||||
|
<template #trigger>
|
||||||
|
<n-button color="#7c461e" @click="SelectAfterGptAndReplace" text style="font-size: 24px">
|
||||||
|
<n-icon>
|
||||||
|
<FindReplaceRound />
|
||||||
|
</n-icon>
|
||||||
|
</n-button>
|
||||||
|
</template>
|
||||||
|
<span>批量查询替换文案</span>
|
||||||
|
</n-popover>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, h, onMounted, onUnmounted } from 'vue'
|
||||||
|
import { useDialog, useMessage, NIcon, NPopover, NButton } from 'naive-ui'
|
||||||
|
import FindReplaceRound from '../../Icon/FindReplaceRound.vue'
|
||||||
|
import { useReverseManageStore } from '../../../../../stores/reverseManage'
|
||||||
|
import DatatableHeaderAfterGptSelectAndReplace from './DatatableHeaderAfterGptSelectAndReplace.vue'
|
||||||
|
import { on } from 'ws'
|
||||||
|
import { BookRepalceDataType } from '../../../../../define/enum/bookEnum'
|
||||||
|
let reverseManageStore = useReverseManageStore()
|
||||||
|
let message = useMessage()
|
||||||
|
let dialog = useDialog()
|
||||||
|
let da = undefined
|
||||||
|
|
||||||
|
async function SelectAfterGptAndReplace() {
|
||||||
|
if (da) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
da = dialog.create({
|
||||||
|
title: '批量查询替换文案',
|
||||||
|
showIcon: false,
|
||||||
|
maskClosable: false,
|
||||||
|
content: () =>
|
||||||
|
h(DatatableHeaderAfterGptSelectAndReplace, { type: BookRepalceDataType.AFTER_GPT }),
|
||||||
|
onClose: () => {
|
||||||
|
da = undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -0,0 +1,116 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<n-input v-model:value="replaceData.before" size="small" type="text" placeholder="替换前" />
|
||||||
|
<n-input
|
||||||
|
v-model:value="replaceData.after"
|
||||||
|
style="margin-top: 10px"
|
||||||
|
size="small"
|
||||||
|
type="text"
|
||||||
|
placeholder="替换后,空白为删除"
|
||||||
|
/>
|
||||||
|
<div v-if="replaceData.type == 'gpt_prompt'" style="margin-top: 10px">
|
||||||
|
<n-checkbox v-model:checked="replaceData.replaceAll"> 替换所有 </n-checkbox>
|
||||||
|
<div style="color: red">
|
||||||
|
勾选当前按钮,会替换所有的提示词数据,包含推理的,或者是反推的,没有勾选,只会替换当前显示的
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; justify-content: flex-end; margin-top: 15px">
|
||||||
|
<n-button type="info" @click="ReplaceAfterGpt">替换</n-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, toRaw } from 'vue'
|
||||||
|
import { NInput, NButton, useMessage, NCheckbox } from 'naive-ui'
|
||||||
|
import { isEmpty, replace } from 'lodash'
|
||||||
|
import { useReverseManageStore } from '../../../../../stores/reverseManage'
|
||||||
|
import { BookRepalceDataType } from '../../../../../define/enum/bookEnum'
|
||||||
|
let replaceData = ref({
|
||||||
|
before: undefined,
|
||||||
|
after: undefined,
|
||||||
|
replaceAll: false,
|
||||||
|
type: BookRepalceDataType.AFTER_GPT
|
||||||
|
})
|
||||||
|
let message = useMessage()
|
||||||
|
let reverseManageStore = useReverseManageStore()
|
||||||
|
|
||||||
|
let props = defineProps({
|
||||||
|
type: BookRepalceDataType.AFTER_GPT
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
replaceData.value.type = props.type
|
||||||
|
})
|
||||||
|
|
||||||
|
async function ReplaceAfterGpt() {
|
||||||
|
if (isEmpty(replaceData.value.before)) {
|
||||||
|
message.error('替换前不能为空')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let res = await window.book.ReplaceBookData(
|
||||||
|
reverseManageStore.selectBookTask.id,
|
||||||
|
toRaw(replaceData.value)
|
||||||
|
)
|
||||||
|
if (res.code == 1) {
|
||||||
|
// 清空数据
|
||||||
|
replaceData.value.before = ''
|
||||||
|
replaceData.value.after = ''
|
||||||
|
replaceData.value.replaceAll = false
|
||||||
|
if (props.type == BookRepalceDataType.AFTER_GPT) {
|
||||||
|
// 修改前端数据
|
||||||
|
for (let i = 0; i < res.data.length; i++) {
|
||||||
|
const element = res.data[i]
|
||||||
|
let index = reverseManageStore.selectBookTaskDetail.findIndex(
|
||||||
|
(x) => x.id == element.bookTaskDetailId
|
||||||
|
)
|
||||||
|
if (index != -1) {
|
||||||
|
reverseManageStore.selectBookTaskDetail[index].afterGpt = element.newData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (props.type == BookRepalceDataType.GPT_PROMPT) {
|
||||||
|
for (let i = 0; i < res.data.length; i++) {
|
||||||
|
const element = res.data[i]
|
||||||
|
let index = reverseManageStore.selectBookTaskDetail.findIndex(
|
||||||
|
(x) => x.id == element.bookTaskDetailId
|
||||||
|
)
|
||||||
|
if (index == -1) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (element.type == 'gptPrompt') {
|
||||||
|
// 修改的是GPT提示词
|
||||||
|
reverseManageStore.selectBookTaskDetail[index].gptPrompt = element.newData
|
||||||
|
} else if (element.type == 'reversePrompt') {
|
||||||
|
// 修改的是反推提示词
|
||||||
|
let reverseIndex = reverseManageStore.selectBookTaskDetail[index].reversePrompt.findIndex(
|
||||||
|
(x) => x.id == element.reversePromptId
|
||||||
|
)
|
||||||
|
if (reverseIndex == -1) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (element.reversePromptType == 'promptCN') {
|
||||||
|
reverseManageStore.selectBookTaskDetail[index].reversePrompt[reverseIndex].promptCN =
|
||||||
|
element.newData
|
||||||
|
} else if (element.reversePromptType == 'prompt') {
|
||||||
|
reverseManageStore.selectBookTaskDetail[index].reversePrompt[reverseIndex].prompt =
|
||||||
|
element.newData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (props.type == BookRepalceDataType.PROMPT) {
|
||||||
|
for (let i = 0; i < res.data.length; i++) {
|
||||||
|
const element = res.data[i]
|
||||||
|
let index = reverseManageStore.selectBookTaskDetail.findIndex(
|
||||||
|
(x) => x.id == element.bookTaskDetailId
|
||||||
|
)
|
||||||
|
if (index == -1) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
reverseManageStore.selectBookTaskDetail[index].prompt = element.newData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.error(res.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -1,37 +1,58 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="display: flex">
|
<div style="display: flex; justify-content: space-between; white-space: nowrap">
|
||||||
<div>反推/GPT提示词</div>
|
<div style="display: flex">
|
||||||
<n-button
|
<div>反推/GPT提示词</div>
|
||||||
v-if="reverseManageStore.selectBook.type == bookType.MJ_REVERSE"
|
<n-button
|
||||||
type="text"
|
v-if="reverseManageStore.selectBook.type == bookType.MJ_REVERSE"
|
||||||
:color="softwareStore.SoftColor.ZHUYANTUO"
|
type="text"
|
||||||
size="tiny"
|
:color="softwareStore.SoftColor.ZHUYANTUO"
|
||||||
style="margin-left: 10px"
|
size="tiny"
|
||||||
@click="SelectPromptIndex"
|
style="margin-left: 10px"
|
||||||
>选择提示词</n-button
|
@click="SelectPromptIndex"
|
||||||
><n-button
|
>选择提示词</n-button
|
||||||
v-if="reverseManageStore.selectBook.type == bookType.MJ_REVERSE"
|
><n-button
|
||||||
type="text"
|
v-if="reverseManageStore.selectBook.type == bookType.MJ_REVERSE"
|
||||||
:color="softwareStore.SoftColor.ZHUYANTUO"
|
type="text"
|
||||||
size="tiny"
|
:color="softwareStore.SoftColor.ZHUYANTUO"
|
||||||
style="margin-left: 5px"
|
size="tiny"
|
||||||
@click="SelectStyle"
|
style="margin-left: 5px"
|
||||||
>风格</n-button
|
@click="SelectStyle"
|
||||||
>
|
>风格</n-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<n-popover trigger="hover">
|
||||||
|
<template #trigger>
|
||||||
|
<n-button
|
||||||
|
color="#7c461e"
|
||||||
|
@click="SelectReversePromptAndReplace"
|
||||||
|
text
|
||||||
|
style="font-size: 24px"
|
||||||
|
>
|
||||||
|
<n-icon>
|
||||||
|
<FindReplaceRound />
|
||||||
|
</n-icon>
|
||||||
|
</n-button>
|
||||||
|
</template>
|
||||||
|
<span>批量替换反推提示词</span>
|
||||||
|
</n-popover>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref, onMounted, defineComponent, onUnmounted, toRaw, h, watch } from 'vue'
|
import { ref, onMounted, defineComponent, onUnmounted, toRaw, h, watch } from 'vue'
|
||||||
import { useMessage, useDialog, NButton } from 'naive-ui'
|
import { useMessage, useDialog, NButton, NPopover, NIcon } from 'naive-ui'
|
||||||
import { useReverseManageStore } from '../../../../../stores/reverseManage'
|
import { useReverseManageStore } from '../../../../../stores/reverseManage'
|
||||||
import { BookType } from '../../../../../define/enum/bookEnum'
|
import { BookRepalceDataType, BookType } from '../../../../../define/enum/bookEnum'
|
||||||
import { useSoftwareStore } from '../../../../../stores/software'
|
import { useSoftwareStore } from '../../../../../stores/software'
|
||||||
import SelectMJReversePrompt from '../MJReverse/SelectMJReversePrompt.vue'
|
import SelectMJReversePrompt from '../MJReverse/SelectMJReversePrompt.vue'
|
||||||
import SelectImageStyle from '../../Components/SelectImageStyle.vue'
|
import SelectImageStyle from '../../Components/SelectImageStyle.vue'
|
||||||
|
import FindReplaceRound from '../../Icon/FindReplaceRound.vue'
|
||||||
|
import DatatableHeaderAfterGptSelectAndReplace from './DatatableHeaderAfterGptSelectAndReplace.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { NButton },
|
components: { NButton, NPopover, FindReplaceRound, NIcon },
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
let message = useMessage()
|
let message = useMessage()
|
||||||
@ -40,7 +61,7 @@ export default defineComponent({
|
|||||||
let bookType = ref(BookType)
|
let bookType = ref(BookType)
|
||||||
let dialog = useDialog()
|
let dialog = useDialog()
|
||||||
let selectStyleRef = ref(null)
|
let selectStyleRef = ref(null)
|
||||||
onMounted(async () => {})
|
let da = undefined
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 选择MJ反推提示词。用于生图
|
* 选择MJ反推提示词。用于生图
|
||||||
@ -115,13 +136,30 @@ export default defineComponent({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function SelectReversePromptAndReplace() {
|
||||||
|
if (da) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
da = dialog.create({
|
||||||
|
title: '批量查询替换反推提示词',
|
||||||
|
showIcon: false,
|
||||||
|
maskClosable: false,
|
||||||
|
content: () =>
|
||||||
|
h(DatatableHeaderAfterGptSelectAndReplace, { type: BookRepalceDataType.GPT_PROMPT }),
|
||||||
|
onClose: () => {
|
||||||
|
da = undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
reverseManageStore,
|
reverseManageStore,
|
||||||
bookType,
|
bookType,
|
||||||
softwareStore,
|
softwareStore,
|
||||||
SelectPromptIndex,
|
SelectPromptIndex,
|
||||||
SelectStyle,
|
SelectStyle,
|
||||||
selectStyleRef
|
selectStyleRef,
|
||||||
|
SelectReversePromptAndReplace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="display: flex; align-items: center; margin-left: 10px">
|
<div style="display: flex; align-items: center; white-space: nowrap">
|
||||||
|
<span>生图提示词</span>
|
||||||
<n-popover trigger="hover">
|
<n-popover trigger="hover">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<n-button color="#7c461e" @click="SetMergeModel" text style="font-size: 24px">
|
<n-button color="#7c461e" @click="SetMergeModel" text style="font-size: 24px">
|
||||||
@ -19,6 +20,22 @@
|
|||||||
>合并命令</n-button
|
>合并命令</n-button
|
||||||
>
|
>
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
|
|
||||||
|
<n-popover trigger="hover">
|
||||||
|
<template #trigger>
|
||||||
|
<n-button
|
||||||
|
color="#7c461e"
|
||||||
|
@click="SelectPromptAndReplace"
|
||||||
|
text
|
||||||
|
style="font-size: 24px; margin-left: 10px"
|
||||||
|
>
|
||||||
|
<n-icon>
|
||||||
|
<FindReplaceRound />
|
||||||
|
</n-icon>
|
||||||
|
</n-button>
|
||||||
|
</template>
|
||||||
|
<span>批量查询替换文案</span>
|
||||||
|
</n-popover>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -30,10 +47,24 @@ import { useSoftwareStore } from '../../../../../stores/software'
|
|||||||
import DynamicTagsSelect from '../../Components/DynamicTagsSelect.vue'
|
import DynamicTagsSelect from '../../Components/DynamicTagsSelect.vue'
|
||||||
import { usePromptStore } from '../../../../../stores/prompt'
|
import { usePromptStore } from '../../../../../stores/prompt'
|
||||||
import { useReverseManageStore } from '../../../../../stores/reverseManage'
|
import { useReverseManageStore } from '../../../../../stores/reverseManage'
|
||||||
import { BookImageCategory, OperateBookType } from '../../../../../define/enum/bookEnum'
|
import {
|
||||||
|
BookImageCategory,
|
||||||
|
BookRepalceDataType,
|
||||||
|
OperateBookType
|
||||||
|
} from '../../../../../define/enum/bookEnum'
|
||||||
|
import FindReplaceRound from '../../Icon/FindReplaceRound.vue'
|
||||||
|
import DatatableHeaderAfterGptSelectAndReplace from './DatatableHeaderAfterGptSelectAndReplace.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { NDropdown, NPopover, NIcon, NButton, Construct },
|
components: {
|
||||||
|
NDropdown,
|
||||||
|
NPopover,
|
||||||
|
NIcon,
|
||||||
|
NButton,
|
||||||
|
Construct,
|
||||||
|
FindReplaceRound,
|
||||||
|
DatatableHeaderAfterGptSelectAndReplace
|
||||||
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
let softwareStore = useSoftwareStore()
|
let softwareStore = useSoftwareStore()
|
||||||
@ -41,7 +72,7 @@ export default defineComponent({
|
|||||||
let reverseManageStore = useReverseManageStore()
|
let reverseManageStore = useReverseManageStore()
|
||||||
let message = useMessage()
|
let message = useMessage()
|
||||||
let dialog = useDialog()
|
let dialog = useDialog()
|
||||||
onMounted(async () => {})
|
let da = undefined
|
||||||
|
|
||||||
async function SaveFunction(value, options) {
|
async function SaveFunction(value, options) {
|
||||||
// 开始保存
|
// 开始保存
|
||||||
@ -137,11 +168,28 @@ export default defineComponent({
|
|||||||
softwareStore.spin.spinning = false
|
softwareStore.spin.spinning = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function SelectPromptAndReplace() {
|
||||||
|
if (da) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
da = dialog.create({
|
||||||
|
title: '批量查询替换生图提示词',
|
||||||
|
showIcon: false,
|
||||||
|
maskClosable: false,
|
||||||
|
content: () =>
|
||||||
|
h(DatatableHeaderAfterGptSelectAndReplace, { type: BookRepalceDataType.PROMPT }),
|
||||||
|
onClose: () => {
|
||||||
|
da = undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
softwareStore,
|
softwareStore,
|
||||||
SetMergeModel,
|
SetMergeModel,
|
||||||
reverseManageStore,
|
reverseManageStore,
|
||||||
MergePrompt,
|
MergePrompt,
|
||||||
|
SelectPromptAndReplace,
|
||||||
MergePromptOptions: [
|
MergePromptOptions: [
|
||||||
{ label: 'MJ模式合并', key: 'mj_merge' },
|
{ label: 'MJ模式合并', key: 'mj_merge' },
|
||||||
{ label: 'SD模式合并', key: 'sd_merge' }
|
{ label: 'SD模式合并', key: 'sd_merge' }
|
||||||
|
|||||||
@ -0,0 +1,173 @@
|
|||||||
|
<template>
|
||||||
|
<div style="margin-top: 10px">
|
||||||
|
<n-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="creatObj"
|
||||||
|
label-placement="left"
|
||||||
|
label-width="120"
|
||||||
|
require-mark-placement="right-hanging"
|
||||||
|
:rules="rules"
|
||||||
|
>
|
||||||
|
<n-form-item label="新增批次数" path="count">
|
||||||
|
<n-input-number
|
||||||
|
:show-button="false"
|
||||||
|
:min="1"
|
||||||
|
:max="100"
|
||||||
|
v-model:value="creatObj.count"
|
||||||
|
placeholder="Input"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-form-item label="选择风格" path="selectTaskDataCategory">
|
||||||
|
<div>风格目前需要到每个批次中单独设置</div>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="通用前缀" path="prefixPrompt">
|
||||||
|
<n-input v-model:value="creatObj.prefixPrompt" placeholder="请输入通用前缀"></n-input>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="通用后缀" path="suffixPrompt">
|
||||||
|
<n-input v-model:value="creatObj.suffixPrompt" placeholder="请输入通用后缀"></n-input>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<n-form-item label="选择旧批次" path="selectBookTask">
|
||||||
|
<n-select
|
||||||
|
v-model:value="creatObj.selectBookTask"
|
||||||
|
:options="bookTaskOptions"
|
||||||
|
placeholder="选择要复制数据的已存在的批次"
|
||||||
|
/>
|
||||||
|
<n-checkbox
|
||||||
|
style="width: 200px; margin-left: 10px"
|
||||||
|
label="使用旧批次数据"
|
||||||
|
v-model:checked="creatObj.copyBookTask"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="复制的数据" path="selectTaskDataCategory">
|
||||||
|
<n-checkbox-group
|
||||||
|
:value="creatObj.selectTaskDataCategory"
|
||||||
|
@update:value="handleUpdateValue"
|
||||||
|
>
|
||||||
|
<n-space item-style="display: flex;" align="center">
|
||||||
|
<n-checkbox
|
||||||
|
v-for="item in groupData"
|
||||||
|
:disabled="item.disabled"
|
||||||
|
:key="item.value"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</n-checkbox>
|
||||||
|
</n-space>
|
||||||
|
</n-checkbox-group>
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<div style="display: flex; justify-content: flex-end">
|
||||||
|
<n-button type="primary" @click="SaveBookTask"> 添加 </n-button>
|
||||||
|
</div>
|
||||||
|
</n-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref, toRaw } from 'vue'
|
||||||
|
import {
|
||||||
|
useMessage,
|
||||||
|
NForm,
|
||||||
|
NFormItem,
|
||||||
|
NButton,
|
||||||
|
NSpace,
|
||||||
|
NInput,
|
||||||
|
NInputNumber,
|
||||||
|
NCheckboxGroup,
|
||||||
|
NCheckbox,
|
||||||
|
NSelect
|
||||||
|
} from 'naive-ui'
|
||||||
|
import { useReverseManageStore } from '../../../../../../stores/reverseManage'
|
||||||
|
import { AddBookTaskCopyData } from '../../../../../../define/enum/bookEnum'
|
||||||
|
let reverseManageStore = useReverseManageStore()
|
||||||
|
let message = useMessage()
|
||||||
|
let formRef = ref(null)
|
||||||
|
let creatObj = ref({
|
||||||
|
count: 1,
|
||||||
|
copyBookTask: false,
|
||||||
|
selectBookTask: undefined,
|
||||||
|
selectTaskDataCategory: [],
|
||||||
|
prefixPrompt: '',
|
||||||
|
suffixPrompt: ''
|
||||||
|
})
|
||||||
|
let bookTaskOptions = ref([])
|
||||||
|
let groupData = ref([
|
||||||
|
{
|
||||||
|
label: '文案',
|
||||||
|
value: AddBookTaskCopyData.AFTER_GPT,
|
||||||
|
disabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '反推/GPT提示词',
|
||||||
|
value: AddBookTaskCopyData.GPT_PROMPT,
|
||||||
|
disabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '生图风格',
|
||||||
|
value: AddBookTaskCopyData.IMAGE_STYLE,
|
||||||
|
disabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '选择角色',
|
||||||
|
value: AddBookTaskCopyData.CHARACTER,
|
||||||
|
disabled: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '生图提示词',
|
||||||
|
value: AddBookTaskCopyData.PROMPT,
|
||||||
|
disabled: false
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
let rules = ref({
|
||||||
|
count: [{ required: true, message: '请输入新增批次数' }]
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
bookTaskOptions.value = reverseManageStore.bookTaskData.map((item) => {
|
||||||
|
return {
|
||||||
|
label: item.name,
|
||||||
|
value: item.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (bookTaskOptions.value.length > 0) {
|
||||||
|
creatObj.value.selectBookTask = bookTaskOptions.value[0].value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 添加批次的方法
|
||||||
|
async function SaveBookTask(e) {
|
||||||
|
console.log(toRaw(creatObj.value))
|
||||||
|
e.preventDefault()
|
||||||
|
formRef.value?.validate(async (errors) => {
|
||||||
|
if (errors) {
|
||||||
|
message.error('请检查必填项')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 这边就开始调用添加批次的接口
|
||||||
|
let res = await window.book.AddNewBookTask(toRaw(creatObj.value))
|
||||||
|
if (res.code == 0) {
|
||||||
|
message.error(res.message)
|
||||||
|
} else {
|
||||||
|
// 加载任务列表
|
||||||
|
let bookTaskRes = await reverseManageStore.GetBookTaskDataFromDB({
|
||||||
|
bookId: reverseManageStore.selectBook.id
|
||||||
|
})
|
||||||
|
softwareStore.spin.spinning = false
|
||||||
|
if (bookTaskRes.code == 0) {
|
||||||
|
message.error(bookTaskRes.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 添加成功,添加成功之后需要刷新一下批次列表
|
||||||
|
message.success('添加成功')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleUpdateValue(value) {
|
||||||
|
creatObj.value.selectTaskDataCategory = value
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -362,7 +362,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
// 导出文案
|
// 导出文案
|
||||||
async function ExportCopywriting() {
|
async function ExportCopywriting() {
|
||||||
debugger
|
|
||||||
softwareStore.spin.spinning = true
|
softwareStore.spin.spinning = true
|
||||||
softwareStore.spin.tip = '正在导出文案中...'
|
softwareStore.spin.tip = '正在导出文案中...'
|
||||||
let res = await window.book.ExportCopywriting(reverseManageStore.selectBookTask.id)
|
let res = await window.book.ExportCopywriting(reverseManageStore.selectBookTask.id)
|
||||||
@ -382,6 +381,36 @@ export default defineComponent({
|
|||||||
softwareStore.spin.spinning = false
|
softwareStore.spin.spinning = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 导入文案
|
||||||
|
async function ImportCopywriting() {
|
||||||
|
window.api.SelectFile(['txt'], async (value) => {
|
||||||
|
if (value.code == 0) {
|
||||||
|
message.error(value.message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let txtPath = value.value
|
||||||
|
// 这边开始导入
|
||||||
|
let res = await window.book.ImportCopywriting(
|
||||||
|
reverseManageStore.selectBook.id,
|
||||||
|
reverseManageStore.selectBookTask.id,
|
||||||
|
txtPath
|
||||||
|
)
|
||||||
|
if (res.code == 1) {
|
||||||
|
for (let i = 0; i < res.data.length; i++) {
|
||||||
|
const element = res.data[i]
|
||||||
|
let index = reverseManageStore.selectBookTaskDetail.findIndex(
|
||||||
|
(x) => x.id == element.bookTaskDetailId
|
||||||
|
)
|
||||||
|
if (index != -1) {
|
||||||
|
reverseManageStore.selectBookTaskDetail[index].afterGpt = element.afterGpt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
window.api.showGlobalMessageDialog(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取水印位置
|
* 获取水印位置
|
||||||
*/
|
*/
|
||||||
@ -420,6 +449,9 @@ export default defineComponent({
|
|||||||
case 'export_recognizing': // 导出文案
|
case 'export_recognizing': // 导出文案
|
||||||
await ExportCopywriting()
|
await ExportCopywriting()
|
||||||
break
|
break
|
||||||
|
case 'import_recognizing': // 导入文案
|
||||||
|
await ImportCopywriting()
|
||||||
|
break
|
||||||
case 'watermark_position': // 水印位置设置
|
case 'watermark_position': // 水印位置设置
|
||||||
await GetWatermarkPosition()
|
await GetWatermarkPosition()
|
||||||
break
|
break
|
||||||
@ -853,6 +885,10 @@ export default defineComponent({
|
|||||||
label: '导出文案',
|
label: '导出文案',
|
||||||
key: 'export_recognizing'
|
key: 'export_recognizing'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '导入文案',
|
||||||
|
key: 'import_recognizing'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '停止提取',
|
label: '停止提取',
|
||||||
key: 'stop_recognizing'
|
key: 'stop_recognizing'
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import ManageBookOldImage from '../Components/ManageBookOldImage.vue'
|
|||||||
import { BookType } from '../../../../../define/enum/bookEnum'
|
import { BookType } from '../../../../../define/enum/bookEnum'
|
||||||
import MJReversePrompt from './MJReversePrompt.vue'
|
import MJReversePrompt from './MJReversePrompt.vue'
|
||||||
import DatatableHeaderGptPrompt from '../Components/DatatableHeaderGptPrompt.vue'
|
import DatatableHeaderGptPrompt from '../Components/DatatableHeaderGptPrompt.vue'
|
||||||
|
import DatatableHeaderAfterGpt from '../Components/DatatableHeaderAfterGpt.vue'
|
||||||
import DatatableHeaderPrompt from '../Components/DatatableHeaderPrompt.vue'
|
import DatatableHeaderPrompt from '../Components/DatatableHeaderPrompt.vue'
|
||||||
import DatatablePrompt from '../Components/DatatablePrompt.vue'
|
import DatatablePrompt from '../Components/DatatablePrompt.vue'
|
||||||
import DatatableHeaderImage from '../Components/DatatableHeaderImage.vue'
|
import DatatableHeaderImage from '../Components/DatatableHeaderImage.vue'
|
||||||
@ -41,7 +42,9 @@ export default defineComponent({
|
|||||||
fixed: 'left'
|
fixed: 'left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '文案',
|
title(row) {
|
||||||
|
return h(DatatableHeaderAfterGpt)
|
||||||
|
},
|
||||||
key: 'afterGpt',
|
key: 'afterGpt',
|
||||||
width: 200,
|
width: 200,
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
@ -87,10 +90,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title(row) {
|
title(row) {
|
||||||
return h('div', { style: 'display: flex; align-items: center' }, [
|
return h(DatatableHeaderPrompt)
|
||||||
h('span', { size: 'tiny', style: 'margin-left: 5px' }, '生图提示词'),
|
|
||||||
h(DatatableHeaderPrompt)
|
|
||||||
])
|
|
||||||
},
|
},
|
||||||
className: 'space-row',
|
className: 'space-row',
|
||||||
key: 'row1',
|
key: 'row1',
|
||||||
|
|||||||
@ -41,6 +41,7 @@ import { useRouter } from 'vue-router'
|
|||||||
import { OperateBookType } from '../../../../define/enum/bookEnum'
|
import { OperateBookType } from '../../../../define/enum/bookEnum'
|
||||||
import { DEFINE_STRING } from '../../../../define/define_string'
|
import { DEFINE_STRING } from '../../../../define/define_string'
|
||||||
import { ResponseMessageType } from '../../../../define/enum/softwareEnum'
|
import { ResponseMessageType } from '../../../../define/enum/softwareEnum'
|
||||||
|
import AddBookTask from './Components/ManageBook/AddBookTask.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@ -167,6 +168,16 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function AddBookDialog() {
|
||||||
|
message.info('新增' + reverseManageStore.selectBook.id)
|
||||||
|
dialog.create({
|
||||||
|
title: '新增小说批次任务',
|
||||||
|
showIcon: false,
|
||||||
|
content: () => h(AddBookTask),
|
||||||
|
style: { width: '600px' }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一键生成草稿
|
* 一键生成草稿
|
||||||
*/
|
*/
|
||||||
@ -197,6 +208,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
reverseManageStore,
|
reverseManageStore,
|
||||||
|
AddBookDialog,
|
||||||
HDImageAll,
|
HDImageAll,
|
||||||
DraftAll,
|
DraftAll,
|
||||||
VideoAll,
|
VideoAll,
|
||||||
|
|||||||
@ -7,14 +7,6 @@
|
|||||||
<ManageBookTask style="height: 100%" />
|
<ManageBookTask style="height: 100%" />
|
||||||
</template>
|
</template>
|
||||||
</n-split>
|
</n-split>
|
||||||
|
|
||||||
<n-float-button :right="30" :bottom="30" shape="circle">
|
|
||||||
<n-badge :value="100" :max="99" :offset="[6, -8]">
|
|
||||||
<n-icon :size="large">
|
|
||||||
<Layers />
|
|
||||||
</n-icon>
|
|
||||||
</n-badge>
|
|
||||||
</n-float-button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
19
src/renderer/src/components/Components/BackTask/BackTask.vue
Normal file
19
src/renderer/src/components/Components/BackTask/BackTask.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
import { useMessage, NButton, NFloatButton, NBadge, NIcon } from 'naive-ui'
|
||||||
|
import { Layers } from '@vicons/ionicons5'
|
||||||
|
import { useSoftwareStore } from '../../../../../stores/software'
|
||||||
|
import QueryButton from './QueryButton.vue'
|
||||||
|
import TaskDataTable from './TaskDataTable.vue'
|
||||||
|
|
||||||
|
let softwareStore = useSoftwareStore()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 加载任务数据
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QueryButton />
|
||||||
|
<TaskDataTable />
|
||||||
|
</template>
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
import { useMessage, NForm, NFormItem, NInput, NButton } from 'naive-ui'
|
||||||
|
import { useSoftwareStore } from '../../../../../stores/software'
|
||||||
|
let softwareStore = useSoftwareStore()
|
||||||
|
|
||||||
|
function handleSubmit() {
|
||||||
|
alert(123)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<n-form
|
||||||
|
ref="formRef"
|
||||||
|
inline
|
||||||
|
:label-width="80"
|
||||||
|
:model="softwareStore.backTask.queryData"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<n-form-item label="小说" path="bookId">
|
||||||
|
<n-input v-model:value="softwareStore.backTask.queryData.bookId" placeholder="选择小说任务" />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="小说批次任务" path="bookTaskId">
|
||||||
|
<n-input
|
||||||
|
v-model:value="softwareStore.backTask.queryData.bookTaskId"
|
||||||
|
placeholder="选择小说批次任务"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="任务名字" path="taskName">
|
||||||
|
<n-input
|
||||||
|
v-model:value="softwareStore.backTask.queryData.taskName"
|
||||||
|
placeholder="选择小说批次任务"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="任务类型" path="taskType">
|
||||||
|
<n-input
|
||||||
|
v-model:value="softwareStore.backTask.queryData.taskType"
|
||||||
|
placeholder="选择小说批次任务"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="任务状态" path="taskStatus">
|
||||||
|
<n-input
|
||||||
|
v-model:value="softwareStore.backTask.queryData.taskStatus"
|
||||||
|
placeholder="选择小说批次任务"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="任务失败原因" path="taskErrorMessage">
|
||||||
|
<n-input
|
||||||
|
v-model:value="softwareStore.backTask.queryData.taskErrorMessage"
|
||||||
|
placeholder="选择小说批次任务"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item path="taskErrorMessage">
|
||||||
|
<n-button type="info" @click="handleSubmit">查询</n-button>
|
||||||
|
</n-form-item>
|
||||||
|
</n-form>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<script setup>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>TaskDataTable</div>
|
||||||
|
</template>
|
||||||
@ -33,18 +33,21 @@
|
|||||||
<script>
|
<script>
|
||||||
import { ref, h, onMounted, defineComponent, toRaw } from 'vue'
|
import { ref, h, onMounted, defineComponent, toRaw } from 'vue'
|
||||||
import { RouterLink } from 'vue-router'
|
import { RouterLink } from 'vue-router'
|
||||||
|
import { Layers } from '@vicons/ionicons5'
|
||||||
import {
|
import {
|
||||||
|
useDialog,
|
||||||
NMenu,
|
NMenu,
|
||||||
NSpace,
|
NSpace,
|
||||||
NLayout,
|
NLayout,
|
||||||
NLayoutSider,
|
NLayoutSider,
|
||||||
NLayoutContent,
|
NLayoutContent,
|
||||||
NIcon,
|
NIcon,
|
||||||
useDialog,
|
|
||||||
useNotification,
|
useNotification,
|
||||||
useMessage,
|
useMessage,
|
||||||
NSwitch,
|
NSwitch,
|
||||||
NButton
|
NButton,
|
||||||
|
NFloatButton,
|
||||||
|
NBadge
|
||||||
} from 'naive-ui'
|
} from 'naive-ui'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -61,7 +64,9 @@ import { DEFINE_STRING } from '../../../../define/define_string'
|
|||||||
import ShowMessage from './ShowMessage.vue'
|
import ShowMessage from './ShowMessage.vue'
|
||||||
import { MD5 } from 'crypto-js'
|
import { MD5 } from 'crypto-js'
|
||||||
import InputDialogContent from '../Original/Components/InputDialogContent.vue'
|
import InputDialogContent from '../Original/Components/InputDialogContent.vue'
|
||||||
import APIIcon from '../APIService/APIIcon.vue'
|
import APIIcon from '../Icon/APIIcon.vue'
|
||||||
|
import BackTaskIcon from '../Icon/BackTaskIcon.vue'
|
||||||
|
import BackTask from '../Components/BackTask/BackTask.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@ -74,7 +79,10 @@ export default defineComponent({
|
|||||||
ShowMessage,
|
ShowMessage,
|
||||||
NSwitch,
|
NSwitch,
|
||||||
NButton,
|
NButton,
|
||||||
APIIcon
|
APIIcon,
|
||||||
|
NFloatButton,
|
||||||
|
NBadge,
|
||||||
|
Layers
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
let collapsed = ref(false)
|
let collapsed = ref(false)
|
||||||
@ -95,6 +103,16 @@ export default defineComponent({
|
|||||||
if (option.key == 'lai_api') return h(NIcon, null, { default: () => h(APIIcon) })
|
if (option.key == 'lai_api') return h(NIcon, null, { default: () => h(APIIcon) })
|
||||||
if (option.key == 'backward_matrix')
|
if (option.key == 'backward_matrix')
|
||||||
return h(NIcon, null, { default: () => h(DuplicateOutline) })
|
return h(NIcon, null, { default: () => h(DuplicateOutline) })
|
||||||
|
if (option.key == 'back_task')
|
||||||
|
return h(
|
||||||
|
NIcon,
|
||||||
|
{
|
||||||
|
onClick: () => {
|
||||||
|
OpneBackTask()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ default: () => h(BackTaskIcon) }
|
||||||
|
)
|
||||||
if (option.key == 'TTS_Services') return h(NIcon, null, { default: () => h(RadioOutline) })
|
if (option.key == 'TTS_Services') return h(NIcon, null, { default: () => h(RadioOutline) })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,6 +504,22 @@ export default defineComponent({
|
|||||||
key: 'mj_setting'
|
key: 'mj_setting'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: () =>
|
||||||
|
h(
|
||||||
|
'div',
|
||||||
|
{
|
||||||
|
onClick: () => {
|
||||||
|
OpneBackTask()
|
||||||
|
},
|
||||||
|
style : 'font-weight: bold;'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => '后台任务'
|
||||||
|
}
|
||||||
|
),
|
||||||
|
key: 'back_task'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -493,10 +527,24 @@ export default defineComponent({
|
|||||||
return () => h(NIcon, null, { default: () => h(icon) })
|
return () => h(NIcon, null, { default: () => h(icon) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function OpneBackTask() {
|
||||||
|
let dialogWidth = window.innerWidth * 0.8
|
||||||
|
let dialogHeight = window.innerHeight * 0.95
|
||||||
|
dialog.create({
|
||||||
|
title: '后台任务',
|
||||||
|
showIcon: false,
|
||||||
|
closeOnEsc: false,
|
||||||
|
content: () => h(BackTask, { height: dialogHeight }),
|
||||||
|
style: `width : ${dialogWidth}px; height : ${dialogHeight}px`,
|
||||||
|
maskClosable: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
renderMenuIcon,
|
renderMenuIcon,
|
||||||
menuOptions,
|
menuOptions,
|
||||||
expandIcon,
|
expandIcon,
|
||||||
|
OpneBackTask,
|
||||||
collapsed
|
collapsed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/renderer/src/components/Icon/BackTaskIcon.vue
Normal file
16
src/renderer/src/components/Icon/BackTaskIcon.vue
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<g fill="none">
|
||||||
|
<path
|
||||||
|
d="M13.25 8.5a.75.75 0 0 0 0 1.5h3.5a.75.75 0 0 0 0-1.5h-3.5zm-.75 6.25a.75.75 0 0 1 .75-.75h3.5a.75.75 0 1 1 0 1.5h-3.5a.75.75 0 0 1-.75-.75zm-1.72-7.03a.75.75 0 0 1 0 1.06l-2 2a.75.75 0 0 1-1.06 0l-1-1a.75.75 0 0 1 1.06-1.06l.47.47l1.47-1.47a.75.75 0 0 1 1.06 0zm0 6.56a.75.75 0 1 0-1.06-1.06l-1.47 1.47l-.47-.47a.75.75 0 0 0-1.06 1.06l1 1a.75.75 0 0 0 1.06 0l2-2zM5.25 3A2.25 2.25 0 0 0 3 5.25v13.5A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V5.25A2.25 2.25 0 0 0 18.75 3H5.25zM4.5 5.25a.75.75 0 0 1 .75-.75h13.5a.75.75 0 0 1 .75.75v13.5a.75.75 0 0 1-.75.75H5.25a.75.75 0 0 1-.75-.75V5.25z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
12
src/renderer/src/components/Icon/FindReplaceRound.vue
Normal file
12
src/renderer/src/components/Icon/FindReplaceRound.vue
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M11 6c1.38 0 2.63.56 3.54 1.46l-1.69 1.69a.5.5 0 0 0 .36.85h4.29c.28 0 .5-.22.5-.5V5.21c0-.45-.54-.67-.85-.35l-1.2 1.2A6.943 6.943 0 0 0 11 4C7.96 4 5.38 5.94 4.42 8.64c-.24.66.23 1.36.93 1.36c.42 0 .79-.26.93-.66A5.007 5.007 0 0 1 11 6zm5.64 9.14c.4-.54.72-1.15.95-1.8c.23-.65-.25-1.34-.94-1.34a.98.98 0 0 0-.93.66A5.007 5.007 0 0 1 11 16c-1.38 0-2.63-.56-3.54-1.46l1.69-1.69a.5.5 0 0 0-.36-.85H4.5c-.28 0-.5.22-.5.5v4.29c0 .45.54.67.85.35l1.2-1.2a6.984 6.984 0 0 0 9.09.7l4.11 4.11c.41.41 1.08.41 1.49 0c.41-.41.41-1.08 0-1.49l-4.1-4.12z"
|
||||||
|
fill="currentColor"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
@ -111,7 +111,7 @@ export default defineComponent({
|
|||||||
// 保存信息
|
// 保存信息
|
||||||
await window.api.SaveCopywritingInformation([toRaw(AnalyzeCharacter.value), "auto_analyze_character"], (value) => {
|
await window.api.SaveCopywritingInformation([toRaw(AnalyzeCharacter.value), "auto_analyze_character"], (value) => {
|
||||||
if (value.code != 1) {
|
if (value.code != 1) {
|
||||||
message.error("未知错误");
|
message.error(value.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
message.success("保存成功");
|
message.success("保存成功");
|
||||||
|
|||||||
@ -550,7 +550,7 @@ export default defineComponent({
|
|||||||
[toRaw(data.value), 'srt_time_information'],
|
[toRaw(data.value), 'srt_time_information'],
|
||||||
(value) => {
|
(value) => {
|
||||||
if (value.code != 1) {
|
if (value.code != 1) {
|
||||||
message.error('未知错误')
|
message.error(value.message)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
message.success('保存成功')
|
message.success('保存成功')
|
||||||
|
|||||||
@ -167,7 +167,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await window.api.InitSDConfig((value) => {
|
await window.api.InitSDConfig((value) => {
|
||||||
|
|
||||||
if (value.code == 0) {
|
if (value.code == 0) {
|
||||||
message.error(value.message)
|
message.error(value.message)
|
||||||
return
|
return
|
||||||
@ -221,7 +220,7 @@ export default defineComponent({
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
window.api.showGlobalMessageDialog({ code: 0, message: '未知错误' })
|
window.api.showGlobalMessageDialog({ code: 0, message: value.message })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -231,7 +230,6 @@ export default defineComponent({
|
|||||||
*/
|
*/
|
||||||
async function LoadSDServiceData() {
|
async function LoadSDServiceData() {
|
||||||
await window.sd.LoadSDServiceData(toRaw(formValue.value).webui_api_url, (value) => {
|
await window.sd.LoadSDServiceData(toRaw(formValue.value).webui_api_url, (value) => {
|
||||||
|
|
||||||
if (value.code == 0) {
|
if (value.code == 0) {
|
||||||
message.error(value.message)
|
message.error(value.message)
|
||||||
return
|
return
|
||||||
|
|||||||
@ -447,7 +447,7 @@ export default defineComponent({
|
|||||||
fontNameOptions.value = value.data.font_name_list
|
fontNameOptions.value = value.data.font_name_list
|
||||||
//
|
//
|
||||||
} else {
|
} else {
|
||||||
message.error('未知错误')
|
message.error(value.message)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -468,7 +468,6 @@ export default defineComponent({
|
|||||||
* 保存基本配置
|
* 保存基本配置
|
||||||
*/
|
*/
|
||||||
async function SaveGeneralSetting() {
|
async function SaveGeneralSetting() {
|
||||||
|
|
||||||
await window.api.SaveGeneralSetting(toRaw(generalSetting.value), (value) => {
|
await window.api.SaveGeneralSetting(toRaw(generalSetting.value), (value) => {
|
||||||
console.log(value)
|
console.log(value)
|
||||||
if (value.code == 0) {
|
if (value.code == 0) {
|
||||||
@ -476,7 +475,7 @@ export default defineComponent({
|
|||||||
} else if (value.code == 1) {
|
} else if (value.code == 1) {
|
||||||
window.api.showGlobalMessageDialog(value)
|
window.api.showGlobalMessageDialog(value)
|
||||||
} else {
|
} else {
|
||||||
window.api.showGlobalMessageDialog({ code: 0, message: '未知错误' })
|
window.api.showGlobalMessageDialog({ code: 0, message: value.message })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -486,7 +485,6 @@ export default defineComponent({
|
|||||||
*/
|
*/
|
||||||
async function GetSystemInstallFontName() {
|
async function GetSystemInstallFontName() {
|
||||||
await window.api.GetSystemInstallFontName(async (value) => {
|
await window.api.GetSystemInstallFontName(async (value) => {
|
||||||
|
|
||||||
console.log(value)
|
console.log(value)
|
||||||
if (value.code == 0) {
|
if (value.code == 0) {
|
||||||
message.error(value.message)
|
message.error(value.message)
|
||||||
@ -495,7 +493,7 @@ export default defineComponent({
|
|||||||
// 刷新数据
|
// 刷新数据
|
||||||
await GetVideoConfigMessage()
|
await GetVideoConfigMessage()
|
||||||
} else {
|
} else {
|
||||||
message.error('未知错误')
|
message.error(value.message)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -505,7 +503,6 @@ export default defineComponent({
|
|||||||
*/
|
*/
|
||||||
async function SaveAssConfig() {
|
async function SaveAssConfig() {
|
||||||
window.api.SaveAssConfig(['assConfig', toRaw(assSetting.value)], async (value) => {
|
window.api.SaveAssConfig(['assConfig', toRaw(assSetting.value)], async (value) => {
|
||||||
|
|
||||||
console.log(value)
|
console.log(value)
|
||||||
if (value.code == 1) {
|
if (value.code == 1) {
|
||||||
// 刷新数据,将上面的数据清零。
|
// 刷新数据,将上面的数据清零。
|
||||||
@ -517,7 +514,7 @@ export default defineComponent({
|
|||||||
window.api.showGlobalMessageDialog(value)
|
window.api.showGlobalMessageDialog(value)
|
||||||
} else {
|
} else {
|
||||||
// message.error("未知错误");
|
// message.error("未知错误");
|
||||||
window.api.showGlobalMessageDialog({ code: 0, message: '未知错误' })
|
window.api.showGlobalMessageDialog({ code: 0, message: value.message })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -528,7 +525,6 @@ export default defineComponent({
|
|||||||
*/
|
*/
|
||||||
async function DeleteAssSetting(row) {
|
async function DeleteAssSetting(row) {
|
||||||
await window.api.DeleteVideoConfig(['assConfig', row.id], async (value) => {
|
await window.api.DeleteVideoConfig(['assConfig', row.id], async (value) => {
|
||||||
|
|
||||||
console.log(value)
|
console.log(value)
|
||||||
if (value.code == 1) {
|
if (value.code == 1) {
|
||||||
message.success('删除成功')
|
message.success('删除成功')
|
||||||
@ -552,7 +548,7 @@ export default defineComponent({
|
|||||||
} else if (value.code == 0) {
|
} else if (value.code == 0) {
|
||||||
window.api.showGlobalMessageDialog(value)
|
window.api.showGlobalMessageDialog(value)
|
||||||
} else {
|
} else {
|
||||||
window.api.showGlobalMessageDialog({ value: 0, message: '未知错误' })
|
window.api.showGlobalMessageDialog({ value: 0, message: value.message })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -561,9 +557,7 @@ export default defineComponent({
|
|||||||
* 删除指定的行
|
* 删除指定的行
|
||||||
*/
|
*/
|
||||||
async function DeleteWaterMarkSetting(row) {
|
async function DeleteWaterMarkSetting(row) {
|
||||||
|
|
||||||
await window.api.DeleteVideoConfig(['watermarkConfig', row.id], async (value) => {
|
await window.api.DeleteVideoConfig(['watermarkConfig', row.id], async (value) => {
|
||||||
|
|
||||||
console.log(value)
|
console.log(value)
|
||||||
if (value.code == 1) {
|
if (value.code == 1) {
|
||||||
message.success('删除成功')
|
message.success('删除成功')
|
||||||
@ -587,14 +581,12 @@ export default defineComponent({
|
|||||||
positiveText: '确定',
|
positiveText: '确定',
|
||||||
negativeText: '取消',
|
negativeText: '取消',
|
||||||
onPositiveClick: async () => {
|
onPositiveClick: async () => {
|
||||||
|
|
||||||
let ss = modifyRef.value.wmSetting
|
let ss = modifyRef.value.wmSetting
|
||||||
console.log(ss)
|
console.log(ss)
|
||||||
|
|
||||||
await window.api.SaveAssConfig(
|
await window.api.SaveAssConfig(
|
||||||
[type, toRaw(modifyRef.value.wmSetting)],
|
[type, toRaw(modifyRef.value.wmSetting)],
|
||||||
async (value) => {
|
async (value) => {
|
||||||
|
|
||||||
console.log(value)
|
console.log(value)
|
||||||
if (value.code == 0) {
|
if (value.code == 0) {
|
||||||
message.error(value.message)
|
message.error(value.message)
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
import { MJSetting } from '../model/Setting/mjSetting'
|
||||||
|
|
||||||
// 系统相关设置
|
// 系统相关设置
|
||||||
export const useSettingStore = defineStore('setting', {
|
export const useSettingStore = defineStore('setting', {
|
||||||
|
|||||||
@ -7,6 +7,17 @@ export const useSoftwareStore = defineStore('software', {
|
|||||||
spinning: false,
|
spinning: false,
|
||||||
tip: '加载中...'
|
tip: '加载中...'
|
||||||
},
|
},
|
||||||
|
backTask: {
|
||||||
|
queryData: {
|
||||||
|
bookId: undefined,
|
||||||
|
bookTaskId: undefined,
|
||||||
|
taskName: undefined,
|
||||||
|
taskType: undefined,
|
||||||
|
taskStatus: undefined,
|
||||||
|
taskErrorMessage: undefined,
|
||||||
|
}, // 查询传递的数据
|
||||||
|
taskData: [], // 后台任务数据
|
||||||
|
},
|
||||||
softWare: {
|
softWare: {
|
||||||
theme: 'light', // 系统主题,亮或是暗
|
theme: 'light', // 系统主题,亮或是暗
|
||||||
reverse_display_show: false, // 一键反推界面显示(简单的表格模式还是表格任务模式)
|
reverse_display_show: false, // 一键反推界面显示(简单的表格模式还是表格任务模式)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user