Laitool v3.0.1-preview.1
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
import fs from 'node:fs';
|
||||
|
||||
const fspromises = fs.promises;
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
/**
|
||||
* 检查字符串中是不是包含中文或者标点符号
|
||||
* @param str 需要判断的字符串
|
||||
* @returns 返回的数据,有中文或者标点符号返回true,否则返回false
|
||||
*/
|
||||
export function ContainsChineseOrPunctuation(str: string): boolean {
|
||||
return /[\u4e00-\u9fa5]|[\u3000-\u301e\u2013\u2014\u2018\u2019\u201c\u201d\u2026\u203b\uff08\uff09\uff1a\uff1b\uff1f\uff01\uff0c\u3001\uff0e\u3002\uff1f\uff01\u2018\u2019\u201c\u201d]/.test(
|
||||
str
|
||||
)
|
||||
}
|
||||
@@ -34,7 +34,7 @@ export async function CheckFolderExistsOrCreate(folderPath) {
|
||||
* @param {*} subPath 子目录的消息
|
||||
* @returns
|
||||
*/
|
||||
export function JoinPath(rootPath, subPath) {
|
||||
export function JoinPath(rootPath: string, subPath: string): string {
|
||||
// 判断第二个地址是不是存在,不存在返回null,存在返回拼接后的地址
|
||||
if (subPath && !isEmpty(subPath)) {
|
||||
return path.resolve(rootPath, subPath)
|
||||
@@ -46,8 +46,9 @@ export function JoinPath(rootPath, subPath) {
|
||||
/**
|
||||
* 删除指定的文件中里面所有的文件和文件夹
|
||||
* @param {*} folderPath 文件夹地址
|
||||
* @param {*} isDeleteOut 是否删除最外层的文件夹,默认false,不删除
|
||||
*/
|
||||
export async function DeleteFolderAllFile(folderPath) {
|
||||
export async function DeleteFolderAllFile(folderPath: string, isDeleteOut: boolean = false): Promise<void> {
|
||||
try {
|
||||
let folderIsExist = await CheckFileOrDirExist(folderPath)
|
||||
if (!folderIsExist) {
|
||||
@@ -55,17 +56,22 @@ export async function DeleteFolderAllFile(folderPath) {
|
||||
}
|
||||
// 开始删除
|
||||
let files = await fspromises.readdir(folderPath)
|
||||
files.forEach(async (file) => {
|
||||
const curPath = path.join(folderPath, file)
|
||||
if ((await fspromises.stat(curPath)).isDirectory()) {
|
||||
for (const file of files) {
|
||||
const curPath = path.join(folderPath, file);
|
||||
const stat = await fspromises.stat(curPath);
|
||||
if (stat.isDirectory()) {
|
||||
// 判断是不是文件夹
|
||||
await DeleteFolderAllFile(curPath) // 递归删除文件夹内容
|
||||
fspromises.rmdir(curPath) // 删除空文件夹
|
||||
await DeleteFolderAllFile(curPath); // 递归删除文件夹内容
|
||||
await fspromises.rmdir(curPath); // 删除空文件夹
|
||||
} else {
|
||||
// 删除文件
|
||||
fspromises.unlink(curPath)
|
||||
await fspromises.unlink(curPath);
|
||||
}
|
||||
})
|
||||
}
|
||||
// 判断是不是要删除最外部的文件夹
|
||||
if (isDeleteOut) {
|
||||
await fspromises.rmdir(folderPath)
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
@@ -142,7 +148,7 @@ export async function IsDirectory(path) {
|
||||
* @param {*} source_path 源文件/文件夹地址
|
||||
* @param {*} target_path 目标文件/文件夹地址
|
||||
*/
|
||||
export async function BackupFileOrFolder(source_path, target_path) {
|
||||
export async function BackupFileOrFolder(source_path: string, target_path: string): Promise<void> {
|
||||
try {
|
||||
// 判断父文件夹是否存在,不存在创建
|
||||
const parent_path = path.dirname(target_path)
|
||||
@@ -158,7 +164,7 @@ export async function BackupFileOrFolder(source_path, target_path) {
|
||||
await fspromises.rename(source_path, target_path)
|
||||
} else {
|
||||
// 复制文件
|
||||
await fspromises.copyFile(source, target)
|
||||
await fspromises.copyFile(source_path, target_path)
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(error)
|
||||
@@ -171,7 +177,7 @@ export async function BackupFileOrFolder(source_path, target_path) {
|
||||
* @param {*} extensions 拓展地址
|
||||
* @returns 返回文件中指定的后缀文件地址(绝对地址)
|
||||
*/
|
||||
export async function GetFilesWithExtensions(folderPath, extensions) {
|
||||
export async function GetFilesWithExtensions(folderPath: string, extensions: string[]): Promise<string[]> {
|
||||
try {
|
||||
// 判断当前是不是文件夹
|
||||
if (!(await IsDirectory(folderPath))) {
|
||||
@@ -213,3 +219,20 @@ export async function GetFilesWithExtensions(folderPath, extensions) {
|
||||
throw new Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件的大小
|
||||
* @param filePath 文件的地址
|
||||
* @returns 返回的文件大小为 kb单位
|
||||
*/
|
||||
export async function GetFileSize(filePath: string): Promise<number> {
|
||||
try {
|
||||
if (!(await CheckFileOrDirExist(filePath))) {
|
||||
throw new Error("获取文件大小,指定的文件不存在");
|
||||
}
|
||||
const stats = await fspromises.stat(filePath);
|
||||
return stats.size / 1024
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
|
||||
import sharp from "sharp";
|
||||
import { CheckFileOrDirExist } from "./file"
|
||||
|
||||
|
||||
/**
|
||||
* 将指定的图片的尺寸修改,返回修改后的图片数据(base64或buffer)
|
||||
* @param {*} image_path
|
||||
* @param {*} width
|
||||
* @param {*} height
|
||||
* @param {*} type
|
||||
* @returns 返回修改后的图片数据(base64或buffer)
|
||||
*/
|
||||
export async function ResizeImage(image_path, width, height, type) {
|
||||
try {
|
||||
// 检查 type 参数
|
||||
if (type !== 'base64' && type !== 'buffer') {
|
||||
throw new Error('type 参数必须是 "base64" 或 "buffer"');
|
||||
}
|
||||
|
||||
// 判断是不是图片文件
|
||||
if (!image_path.match(/\.(jpg|jpeg|png)$/)) {
|
||||
throw new Error("输入的文件地址不是图片文件地址");
|
||||
}
|
||||
|
||||
// 判断文件是否存在
|
||||
if (!(await CheckFileOrDirExist(image_path))) {
|
||||
throw new Error("文件不存在");
|
||||
}
|
||||
|
||||
// 修改图片尺寸
|
||||
const image = sharp(image_path);
|
||||
image.resize(width, height);
|
||||
let data = await image.toBuffer();
|
||||
if (type === 'base64') {
|
||||
return data.toString('base64');
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定图片文件的宽高
|
||||
* @param {*} image_path 图片文件的路径
|
||||
* @returns 返回以一个对象,包含width和height属性
|
||||
*/
|
||||
|
||||
export async function GetImageSize(image_path) {
|
||||
try {
|
||||
// 判断文件是否存在
|
||||
if (!(await CheckFileOrDirExist(image_path))) {
|
||||
throw new Error("文件不存在");
|
||||
}
|
||||
|
||||
// 判断是不是图片文件
|
||||
if (!image_path.match(/\.(jpg|jpeg|png)$/)) {
|
||||
throw new Error("输入的文件地址不是图片文件地址");
|
||||
}
|
||||
|
||||
// 获取图片的宽高
|
||||
const metadata = await sharp(image_path).metadata();
|
||||
return {
|
||||
width: metadata.width,
|
||||
height: metadata.height
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
import path from 'path'
|
||||
import sharp from 'sharp'
|
||||
import { CheckFileOrDirExist } from './file'
|
||||
import fs from 'fs'
|
||||
import https from 'https'
|
||||
import Compressor from 'compressorjs';
|
||||
|
||||
/**
|
||||
* 将指定的图片的尺寸修改,返回修改后的图片数据(base64或buffer)
|
||||
* @param {*} image_path
|
||||
* @param {*} width
|
||||
* @param {*} height
|
||||
* @param {*} type
|
||||
* @returns 返回修改后的图片数据(base64或buffer)
|
||||
*/
|
||||
export async function ResizeImage(image_path: string, width: number | sharp.ResizeOptions, height: number, type: string) {
|
||||
try {
|
||||
// 检查 type 参数
|
||||
if (type !== 'base64' && type !== 'buffer') {
|
||||
throw new Error('type 参数必须是 "base64" 或 "buffer"')
|
||||
}
|
||||
|
||||
// 判断是不是图片文件
|
||||
if (!image_path.match(/\.(jpg|jpeg|png)$/)) {
|
||||
throw new Error('输入的文件地址不是图片文件地址')
|
||||
}
|
||||
|
||||
// 判断文件是否存在
|
||||
if (!(await CheckFileOrDirExist(image_path))) {
|
||||
throw new Error('文件不存在')
|
||||
}
|
||||
|
||||
// 修改图片尺寸
|
||||
const image = sharp(image_path)
|
||||
image.resize(width, height)
|
||||
let data = await image.toBuffer()
|
||||
if (type === 'base64') {
|
||||
return data.toString('base64')
|
||||
} else {
|
||||
return data
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定图片文件的宽高
|
||||
* @param {*} image_path 图片文件的路径
|
||||
* @returns 返回以一个对象,包含width和height属性
|
||||
*/
|
||||
|
||||
export async function GetImageSize(image_path: string) {
|
||||
try {
|
||||
// 判断文件是否存在
|
||||
if (!(await CheckFileOrDirExist(image_path))) {
|
||||
throw new Error('文件不存在')
|
||||
}
|
||||
|
||||
// 判断是不是图片文件
|
||||
if (!image_path.match(/\.(jpg|jpeg|png)$/)) {
|
||||
throw new Error('输入的文件地址不是图片文件地址')
|
||||
}
|
||||
|
||||
// 获取图片的宽高
|
||||
const metadata = await sharp(image_path).metadata()
|
||||
return {
|
||||
width: metadata.width,
|
||||
height: metadata.height
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件扩展名获取MIME类型
|
||||
* @param filePath 文件路径
|
||||
* @returns MIME类型字符串
|
||||
*/
|
||||
export function GetMimeType(filePath: string): string {
|
||||
const extension = path.extname(filePath).toLowerCase();
|
||||
const mimeTypes: { [key: string]: string } = {
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.png': 'image/png',
|
||||
'.gif': 'image/gif',
|
||||
'.webp': 'image/webp',
|
||||
// 添加更多文件类型和对应的MIME类型
|
||||
};
|
||||
return mimeTypes[extension] || 'application/octet-stream';
|
||||
}
|
||||
|
||||
/**
|
||||
* 将本地文件地址或网络图片地址转换为包含MIME类型的base64字符串
|
||||
* @param url 本地文件路径或网络图片URL
|
||||
* @returns Promise<string> 返回一个Promise,解析为包含MIME类型的base64字符串
|
||||
*/
|
||||
export function GetImageBase64(url: string): Promise<string> {
|
||||
if (!url) {
|
||||
return Promise.reject('URL不能为空');
|
||||
}
|
||||
if (url.startsWith('http://') || url.startsWith('https://')) {
|
||||
return new Promise((resolve, reject) => {
|
||||
https.get(url, (response) => {
|
||||
const mimeType = response.headers['content-type'] || 'application/octet-stream';
|
||||
const data: any[] = [];
|
||||
response.on('data', (chunk) => data.push(chunk));
|
||||
response.on('end', () => {
|
||||
const buffer = Buffer.concat(data);
|
||||
const base64Data = `data:${mimeType};base64,${buffer.toString('base64')}`;
|
||||
resolve(base64Data);
|
||||
});
|
||||
}).on('error', (err) => reject(err));
|
||||
});
|
||||
} else {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(url, (err, data) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
const mimeType = GetMimeType(url);
|
||||
const base64Data = `data:${mimeType};base64,${data.toString('base64')}`;
|
||||
resolve(base64Data);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩图片到指定的大小
|
||||
* @param file 图片的Blob对象
|
||||
* @param maxSizeInBytes 最大文件大小,单位字节
|
||||
* @returns 返回一个Promise,解析为压缩后的Blob对象
|
||||
*/
|
||||
export function CompressImageToSize(base64: string, maxSizeInBytes: number): Promise<Blob> {
|
||||
let mimeType = this.getMimeType(base64);
|
||||
let byteCharacters = atob(base64.split(',')[1]);
|
||||
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 compress = (quality: number) => {
|
||||
new Compressor(imageBlob as Blob, {
|
||||
quality,
|
||||
success(result) {
|
||||
if (result.size <= maxSizeInBytes || quality <= 0.1) {
|
||||
resolve(result);
|
||||
} else {
|
||||
// 递归降低质量
|
||||
compress(quality - 0.1);
|
||||
}
|
||||
},
|
||||
error(err) {
|
||||
reject(err);
|
||||
},
|
||||
});
|
||||
};
|
||||
// 从较高的质量开始
|
||||
compress(0.9);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成图片蒙板
|
||||
* 将选中的区域涂白,其他区域涂黑(这个颜色可以变)
|
||||
* @param inputPath 输入的文件路径
|
||||
* @param outputPath 输出的文件路径
|
||||
* @param region 范围对象,包含x, y, width, height属性
|
||||
* @param markColor 标记颜色,默认为黑色 { r: 255, g: 255, b: 255 }
|
||||
* @param backColor 背景颜色,默认为白色 { r: 0, g: 0, b: 0 }
|
||||
*/
|
||||
export async function ProcessImage(inputPath: string,
|
||||
outputPath: string,
|
||||
region: { width: any; height: any; x: any; y: any },
|
||||
markColor: { r: number; g: number; b: number } = { r: 255, g: 255, b: 255 },
|
||||
backColor: { r: number; g: number; b: number } = { r: 0, g: 0, b: 0 },
|
||||
): Promise<void> {
|
||||
try {
|
||||
// 读取图片并进行处理
|
||||
const image = sharp(inputPath);
|
||||
|
||||
// 获取图片的元数据
|
||||
const { width, height } = await image.metadata();
|
||||
|
||||
// 创建一个新的空白图片,背景为白色
|
||||
const whiteBackground = await sharp({
|
||||
create: {
|
||||
width,
|
||||
height,
|
||||
channels: 3, // RGB channels
|
||||
background: backColor // White color
|
||||
}
|
||||
}).png().toBuffer();
|
||||
|
||||
// 创建一个黑色的矩形
|
||||
const blackRegion = await sharp({
|
||||
create: {
|
||||
width: region.width,
|
||||
height: region.height,
|
||||
channels: 3, // RGB channels
|
||||
background: markColor // Black color
|
||||
}
|
||||
}).png().toBuffer();
|
||||
|
||||
// 在白色背景上叠加黑色矩形
|
||||
await sharp(whiteBackground)
|
||||
.composite([
|
||||
{
|
||||
input: blackRegion,
|
||||
left: region.x,
|
||||
top: Math.floor(region.y)
|
||||
}
|
||||
])
|
||||
.toFile(outputPath);
|
||||
|
||||
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将图片的base64写到本地文件
|
||||
* @param base64 base64字符串
|
||||
* @param outFilePath 写出的文件路径
|
||||
*/
|
||||
export async function Base64ToFile(base64: string, outFilePath: string): Promise<void> {
|
||||
try {
|
||||
let base64Data = base64.replace(/^data:image\/\w+;base64,/, '')
|
||||
let dataBuffer = Buffer.from(base64Data, 'base64')
|
||||
let out_folder = path.dirname(outFilePath)
|
||||
await this.tools.checkFolderExistsOrCreate(out_folder)
|
||||
await fs.promises.writeFile(outFilePath, dataBuffer)
|
||||
// await this.tools.writeArrayToFile(dataBuffer, out_file);
|
||||
} catch (error) {
|
||||
throw new Error('将base64转换为文件失败,失败信息如下:' + error.toString())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将图片分割为4份
|
||||
* @param inputPath 输入的文件路径
|
||||
* @param reName 重命名的名字,用做新文件名的前缀
|
||||
* @param outputDir 输出的文件夹路径
|
||||
* @returns
|
||||
*/
|
||||
export async function ImageSplit(inputPath: string, reName: string, outputDir: string) {
|
||||
try {
|
||||
const metadata = await sharp(inputPath).metadata()
|
||||
const smallWidth = metadata.width / 2
|
||||
const smallHeight = metadata.height / 2
|
||||
let times = new Date().getTime()
|
||||
let imgs = []
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const xOffset = i % 2 === 0 ? 0 : smallWidth
|
||||
const yOffset = Math.floor(i / 2) * smallHeight
|
||||
let out_file = path.join(outputDir, `/${reName}_${times}_${i}.png`)
|
||||
await sharp(inputPath)
|
||||
.extract({
|
||||
left: xOffset,
|
||||
top: yOffset,
|
||||
width: smallWidth,
|
||||
height: smallHeight
|
||||
})
|
||||
.resize(smallWidth, smallHeight)
|
||||
.toFile(out_file)
|
||||
|
||||
imgs.push(out_file)
|
||||
}
|
||||
return imgs
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import * as image from './image';
|
||||
import * as common from './common';
|
||||
import * as file from './file'
|
||||
import * as validate from './validate';
|
||||
|
||||
export {
|
||||
image,
|
||||
common,
|
||||
file
|
||||
file,
|
||||
validate
|
||||
};
|
||||
@@ -43,3 +43,12 @@ export function MillisecondsToTimeString(milliseconds) {
|
||||
timeString = timeString.replace(/(\.\d+)\./g, '$1')
|
||||
return timeString
|
||||
}
|
||||
|
||||
/**
|
||||
* 延时多少秒,返回一个Promise
|
||||
* @param time 延时时间,单位毫秒
|
||||
* @returns viod
|
||||
*/
|
||||
export async function TimeDelay(time: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, time));
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
/**
|
||||
* 校验是不是可以进行JSON解析
|
||||
* @param str 要解析的字符串
|
||||
* @returns 可以解析返回true,否则返回false
|
||||
*/
|
||||
export function ValidateJson(str: string): boolean {
|
||||
|
||||
try {
|
||||
JSON.parse(str);
|
||||
return true
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -28,35 +28,6 @@ let apiUrl = [
|
||||
mj_url: null,
|
||||
buy_url: null
|
||||
},
|
||||
{
|
||||
label: 'DrawAPI(MJ)',
|
||||
value: '2cabf684-ac48-4733-a427-8c41626f7d8f',
|
||||
gpt_url: null,
|
||||
mj_url: {
|
||||
imagine: 'https://mjapi.deepwl.net/api/mj/submit/imagine',
|
||||
describe: 'https://mjapi.deepwl.net/api/mj/submit/describe',
|
||||
update_file: 'https://mjapi.deepwl.net/api/mj/submit/upload-discord-images',
|
||||
once_get_task: 'https://mjapi.deepwl.net/api/mj/query/task/${id}',
|
||||
get_task_list: 'https://mjapi.deepwl.net/api/mj/task/list-by-condition'
|
||||
},
|
||||
d3_url: null,
|
||||
buy_url: 'https://mjapi.deepwl.net/#/home'
|
||||
},
|
||||
{
|
||||
label: 'ePhoneAPI',
|
||||
value: 'b8866543-8c27-4888-869c-00aa1eb31272',
|
||||
gpt_url: 'https://api.ephone.ai/v1/chat/completions',
|
||||
mj_url: {
|
||||
imagine: 'https://api.ephone.ai/mj/submit/imagine',
|
||||
describe: 'https://api.ephone.ai/mj/submit/describe',
|
||||
update_file: 'https://api.ephone.ai/mj/submit/upload-discord-images',
|
||||
once_get_task: 'https://api.ephone.ai/mj/task/${id}/fetch'
|
||||
},
|
||||
d3_url: {
|
||||
image: 'https://api.ephone.ai/v1/images/generations'
|
||||
},
|
||||
buy_url: 'https://ephone.ai/register?aff=55XT'
|
||||
},
|
||||
{
|
||||
label: 'KIMI',
|
||||
value: 'b5c8c8c5-f3c4-4c88-b25c-7f5a3d5f9d1f',
|
||||
|
||||
@@ -13,6 +13,8 @@ export class BookBackTaskList extends Realm.Object<BookBackTaskList> {
|
||||
executeType: TaskExecuteType // 任务执行类型,手动还是自动
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
startTime: number
|
||||
endTime: number
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'BookBackTaskList',
|
||||
@@ -27,7 +29,9 @@ export class BookBackTaskList extends Realm.Object<BookBackTaskList> {
|
||||
errorMessage: 'string?',
|
||||
executeType: { type: 'string', default: TaskExecuteType.AUTO },
|
||||
createTime: 'date',
|
||||
updateTime: 'date'
|
||||
updateTime: 'date',
|
||||
startTime: 'int',
|
||||
endTime: 'int'
|
||||
},
|
||||
primaryKey: 'id'
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Realm, { ObjectSchema } from 'realm'
|
||||
// @ts-ignore
|
||||
import Realm from 'realm'
|
||||
import { BookType } from '../../../enum/bookEnum'
|
||||
|
||||
export class BookModel extends Realm.Object<BookModel> {
|
||||
@@ -11,12 +12,21 @@ export class BookModel extends Realm.Object<BookModel> {
|
||||
oldVideoPath: string | null
|
||||
srtPath: string | null
|
||||
audioPath: string | null
|
||||
draftSrtStyle: string | null // 草稿字幕样式
|
||||
backgroundMusic: string | null // 背景音乐ID
|
||||
friendlyReminder: string | null // 友情提示
|
||||
updateTime: Date
|
||||
createTime: Date
|
||||
version: string
|
||||
imageStyle: string[] | null // 软件内置的样式
|
||||
autoAnalyzeCharacter: string | null // 自动分析角色设置
|
||||
customizeImageStyle: string[] | null // 自定义的样式
|
||||
videoConfig: string | null // 合成视频设置
|
||||
prefixPrompt: string | null // 前缀
|
||||
suffixPrompt: string | null // 后缀
|
||||
subtitlePosition: string | null
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
static schema: Realm.ObjectSchema = {
|
||||
name: 'Book',
|
||||
properties: {
|
||||
id: 'string',
|
||||
@@ -27,10 +37,19 @@ export class BookModel extends Realm.Object<BookModel> {
|
||||
oldVideoPath: 'string?',
|
||||
srtPath: 'string?',
|
||||
audioPath: 'string?',
|
||||
draftSrtStyle : 'string?',
|
||||
backgroundMusic: 'string?',
|
||||
friendlyReminder: 'string?',
|
||||
imageFolder: 'string?',
|
||||
updateTime: 'date',
|
||||
createTime: 'date',
|
||||
version: 'string',
|
||||
imageStyle: 'string?[]',
|
||||
autoAnalyzeCharacter: 'string?',
|
||||
customizeImageStyle: 'string?[]',
|
||||
videoConfig: "string?",
|
||||
prefixPrompt: "string?",
|
||||
suffixPrompt: "string?",
|
||||
subtitlePosition: 'string?'
|
||||
},
|
||||
// 主键为_id
|
||||
|
||||
@@ -1,5 +1,40 @@
|
||||
import Realm, { ObjectSchema } from 'realm'
|
||||
import { BookTaskStatus, BookType } from '../../../enum/bookEnum'
|
||||
import { BookImageCategory, BookTaskStatus, BookType } from '../../../enum/bookEnum'
|
||||
|
||||
export class ImageDefineModel extends Realm.Object<ImageDefineModel> {
|
||||
label: string
|
||||
key: string
|
||||
value: string
|
||||
children: string
|
||||
type: string
|
||||
prompt: string
|
||||
image_url: string
|
||||
cref_cw: number
|
||||
lora: string
|
||||
chinese_prompt: string
|
||||
lora_weight: number
|
||||
show_image: string
|
||||
isShow: true
|
||||
static schema: ObjectSchema = {
|
||||
name: 'ImageDefine',
|
||||
properties: {
|
||||
label: 'string',
|
||||
key: 'string',
|
||||
value: 'string',
|
||||
children: 'string',
|
||||
type: 'string',
|
||||
prompt: 'string',
|
||||
image_url: 'string',
|
||||
cref_cw: 'int',
|
||||
lora: 'string',
|
||||
chinese_prompt: 'string',
|
||||
lora_weight: 'int',
|
||||
show_image: 'string',
|
||||
isShow: 'bool'
|
||||
},
|
||||
primaryKey: 'key'
|
||||
}
|
||||
}
|
||||
|
||||
export class BookTaskModel extends Realm.Object<BookTaskModel> {
|
||||
id: string
|
||||
@@ -9,14 +44,24 @@ export class BookTaskModel extends Realm.Object<BookTaskModel> {
|
||||
generateVideoPath: string | null
|
||||
srtPath: string | null
|
||||
audioPath: string | null
|
||||
draftSrtStyle: string | null // 草稿字幕样式
|
||||
backgroundMusic: string | null // 背景音乐ID
|
||||
friendlyReminder: string | null // 友情提示
|
||||
imageFolder: string | null
|
||||
styleList: Realm.List<string> | null
|
||||
prefix: string | null
|
||||
imageStyle: string[] | null // 软件内置的样式
|
||||
autoAnalyzeCharacter: string | null // 自动分析角色设置
|
||||
customizeImageStyle: string[] | null // 自定义的样式
|
||||
videoConfig: string | null // 合成视频设置
|
||||
prefixPrompt: string | null // 前缀
|
||||
suffixPrompt: string | null // 后缀
|
||||
styleList: string[] | null
|
||||
status: BookTaskStatus
|
||||
errorMsg: string | null
|
||||
isAuto: boolean // 是否自动
|
||||
updateTime: Date
|
||||
createTime: Date
|
||||
imageCategory: BookImageCategory // 图片出图方式
|
||||
subImageFolder: string[] | null // 出图的子文件夹
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'BookTask',
|
||||
@@ -28,14 +73,23 @@ export class BookTaskModel extends Realm.Object<BookTaskModel> {
|
||||
generateVideoPath: 'string?',
|
||||
srtPath: 'string?',
|
||||
audioPath: 'string?',
|
||||
draftSrtStyle: 'string?',
|
||||
backgroundMusic: 'string?',
|
||||
friendlyReminder: 'string?',
|
||||
imageFolder: 'string?',
|
||||
styleList: 'string[]',
|
||||
prefix: 'string?',
|
||||
subImageFolder: "string?[]",
|
||||
imageStyle: 'string?[]',
|
||||
autoAnalyzeCharacter: 'string?',
|
||||
customizeImageStyle: 'string?[]',
|
||||
videoConfig: "string?",
|
||||
prefixPrompt: "string?",
|
||||
suffixPrompt: "string?",
|
||||
status: 'string',
|
||||
errorMsg: 'string?',
|
||||
isAuto: 'bool',
|
||||
updateTime: 'date',
|
||||
createTime: 'date'
|
||||
createTime: 'date',
|
||||
imageCategory: 'string',
|
||||
},
|
||||
// 主键为_id
|
||||
primaryKey: 'id'
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
BookTaskStatus,
|
||||
BookType,
|
||||
MJAction,
|
||||
MJCategroy
|
||||
} from '../../../enum/bookEnum'
|
||||
import { MJImageType } from '../../../enum/mjEnum'
|
||||
|
||||
export class Subtitle extends Realm.Object<Subtitle> {
|
||||
startTime: number
|
||||
@@ -29,7 +29,7 @@ export class MJMessage extends Realm.Object<MJMessage> {
|
||||
id: string
|
||||
mjApiUrl: string | null
|
||||
progress: number
|
||||
category: MJCategroy
|
||||
category: MJImageType
|
||||
imageClick: string | null // 图片点击(显示的小的)
|
||||
imageShow: string | null // 图片实际的地址
|
||||
messageId: string // 消息ID(可以是MJ中的,也可以是API中的)
|
||||
@@ -105,6 +105,26 @@ export class SDConfig extends Realm.Object<SDConfig> {
|
||||
}
|
||||
}
|
||||
|
||||
// 放反推的提示词的对象
|
||||
export class ReversePrompt extends Realm.Object<ReversePrompt> {
|
||||
id: string
|
||||
bookTaskDetailId: string
|
||||
prompt: string
|
||||
promptCN: string
|
||||
isSelect: boolean
|
||||
static schema: ObjectSchema = {
|
||||
name: 'ReversePrompt',
|
||||
properties: {
|
||||
id: 'string',
|
||||
bookTaskDetailId: "string",
|
||||
prompt: 'string',
|
||||
promptCN: 'string',
|
||||
isSelect: 'bool'
|
||||
},
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
|
||||
export class BookTaskDetailModel extends Realm.Object<BookTaskDetailModel> {
|
||||
id: string
|
||||
no: number
|
||||
@@ -119,16 +139,19 @@ export class BookTaskDetailModel extends Realm.Object<BookTaskDetailModel> {
|
||||
startTime: number | null // 开始时间
|
||||
endTime: number | null // 结束时间
|
||||
timeLimit: string | null // 事件实现(0 -- 3000)
|
||||
subValue: Realm.List<Subtitle> | null // 包含的字幕数据
|
||||
subValue: string | null // 包含的字幕数据
|
||||
characterTags: string[] | null // 角色标签
|
||||
gptPrompt: string | null // GPT提示词
|
||||
mjMessage: MJMessage | null // MJ消息
|
||||
outImagePath: string | null // 输出图片地址
|
||||
subImagePath: string[] | null // 子图片地址
|
||||
imageLock: boolean // 图片锁
|
||||
prompt: string | null // 提示
|
||||
adetailer: boolean // 是否开启修脸
|
||||
sdConifg: SDConfig | null // SD配置
|
||||
reversePrompt: ReversePrompt[] | null // 反推的提示词(数组)
|
||||
subtitlePosition: string | null // 字幕位置
|
||||
status: BookTaskStatus
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
|
||||
@@ -148,16 +171,19 @@ export class BookTaskDetailModel extends Realm.Object<BookTaskDetailModel> {
|
||||
startTime: 'int?',
|
||||
endTime: 'int?',
|
||||
timeLimit: 'string?',
|
||||
subValue: { type: 'list', objectType: 'Subtitle' },
|
||||
subValue: 'string?',
|
||||
reversePrompt: { type: 'list', objectType: 'ReversePrompt' },
|
||||
characterTags: { type: 'list', objectType: 'string' },
|
||||
gptPrompt: 'string?',
|
||||
mjMessage: 'MJMessage?',
|
||||
outImagePath: 'string?',
|
||||
subImagePath: 'string[]',
|
||||
imageLock: 'bool',
|
||||
prompt: 'string?',
|
||||
adetailer: 'bool',
|
||||
sdConifg: 'SDConfig?',
|
||||
subtitlePosition: 'string?',
|
||||
status: "string",
|
||||
createTime: 'date',
|
||||
updateTime: 'date'
|
||||
},
|
||||
|
||||
@@ -11,6 +11,8 @@ export class SoftwareModel extends Realm.Object<SoftwareModel> {
|
||||
ttsSetting: string | null // TTS设置的json字符串
|
||||
writeSetting: string | null // 文案的相关配置的json字符串
|
||||
aiSetting: string | null // AI相关的配置的json字符串
|
||||
watermarkSetting: string | null // 水印相关的配置的json字符串
|
||||
translationSetting: string | null // 翻译相关的配置的json字符串
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'Software',
|
||||
@@ -23,7 +25,9 @@ export class SoftwareModel extends Realm.Object<SoftwareModel> {
|
||||
globalSetting: 'string',
|
||||
ttsSetting: 'string?', // 可空
|
||||
writeSetting: 'string?',
|
||||
aiSetting: 'string?'
|
||||
aiSetting: 'string?',
|
||||
watermarkSetting: 'string?',
|
||||
translationSetting: 'string?'
|
||||
},
|
||||
// 主键为_id
|
||||
primaryKey: 'id'
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
import Realm from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { BookTaskModel } from '../../model/Book/bookTask.js'
|
||||
import {
|
||||
BookBackTaskStatus,
|
||||
BookBackTaskType,
|
||||
BookTaskStatus,
|
||||
TaskExecuteType
|
||||
} from '../../../enum/bookEnum.js'
|
||||
import { errorMessage, successMessage } from '../../../../main/generalTools.js'
|
||||
import { errorMessage, successMessage } from '../../../../main/Public/generalTools'
|
||||
import { BaseRealmService } from './bookBasic'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { DefaultObject } from 'realm/dist/public-types/schema.js'
|
||||
import { BookModel } from '../../model/Book/book.js'
|
||||
import { OtherData } from '../../../enum/softwareEnum.js'
|
||||
import { BookBackTaskList } from '../../model/Book/BookBackTaskListModel.js'
|
||||
import { Book } from '../../../../model/book.js'
|
||||
import { GeneralResponse } from '../../../../model/generalResponse.js'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
export class BookBackTaskListService extends BaseRealmService {
|
||||
@@ -44,7 +39,7 @@ export class BookBackTaskListService extends BaseRealmService {
|
||||
* bookId 和 status 必填一个
|
||||
* @param query bookId,bookTaskId,name,type,status
|
||||
*/
|
||||
GetBookBackTaskList(query) {
|
||||
GetBookBackTaskList(query: Book.QueryBookBackTaskCondition) {
|
||||
try {
|
||||
if (query == null) {
|
||||
throw new Error('查询后台队列任务失败,没有查询条件')
|
||||
@@ -53,33 +48,36 @@ export class BookBackTaskListService extends BaseRealmService {
|
||||
throw new Error('查询后台队列任务失败,没有查询条件')
|
||||
}
|
||||
|
||||
// 构建查询条件
|
||||
// 下面时可空的条件
|
||||
let queryString = ''
|
||||
if (query.bookId) {
|
||||
queryString = `bookId = ${query.bookId}`
|
||||
}
|
||||
if (query.bookTaskId) {
|
||||
queryString += ` && bookTaskId = ${query.bookTaskId}`
|
||||
}
|
||||
if (query.name) {
|
||||
queryString += ` && name = ${query.name}`
|
||||
}
|
||||
if (query.type) {
|
||||
queryString += ` && type = ${query.type}`
|
||||
}
|
||||
if (query.status) {
|
||||
queryString += ` && status = ${query.status}`
|
||||
}
|
||||
if (query.executeType) {
|
||||
queryString += ` && executeType = ${query.executeType}`
|
||||
}
|
||||
|
||||
// 获取数据
|
||||
let tasks = this.realm
|
||||
.objects('BookBackTaskList')
|
||||
.filtered(queryString)
|
||||
.sorted('createTime', true)
|
||||
|
||||
|
||||
// 构建查询条件
|
||||
if (query.id) {
|
||||
tasks.filtered('id = $0', query.id)
|
||||
}
|
||||
if (query.bookId) {
|
||||
tasks.filtered('bookId = $0', query.bookId)
|
||||
}
|
||||
if (query.bookTaskId) {
|
||||
tasks.filtered('bookTaskId = $0', query.bookTaskId)
|
||||
}
|
||||
if (query.name) {
|
||||
tasks.filtered('name = $0', query.name)
|
||||
}
|
||||
if (query.type) {
|
||||
tasks.filtered('type = $0', query.type)
|
||||
}
|
||||
if (query.status) {
|
||||
tasks.filtered('status = $0', query.status)
|
||||
}
|
||||
if (query.executeType) {
|
||||
tasks.filtered('executeType = $0', query.executeType)
|
||||
}
|
||||
|
||||
|
||||
let res
|
||||
if (query.count) {
|
||||
res = tasks.slice(0, query.count)
|
||||
@@ -107,12 +105,12 @@ export class BookBackTaskListService extends BaseRealmService {
|
||||
let tasks = this.realm
|
||||
.objects<BookBackTaskList>('BookBackTaskList')
|
||||
.filtered(
|
||||
'status == $0 && executeType == $1',
|
||||
'(status == $0 || status == $1) && executeType == $2',
|
||||
BookBackTaskStatus.WAIT,
|
||||
BookBackTaskStatus.RECONNECT,
|
||||
executeType ? executeType : TaskExecuteType.AUTO
|
||||
)
|
||||
.sorted('createTime', false)
|
||||
|
||||
if (count != null) {
|
||||
tasks = tasks.slice(0, count) as unknown as Realm.Results<BookBackTaskList>
|
||||
}
|
||||
@@ -169,9 +167,8 @@ export class BookBackTaskListService extends BaseRealmService {
|
||||
}
|
||||
|
||||
// 开始往数据库中写数据
|
||||
let name = `${book.name}-${bookTask ? bookTask.name : 'default'}-${
|
||||
bookTaskDetail ? bookTaskDetail.name : 'default'
|
||||
}-${taskType}`
|
||||
let name = `${book.name}-${bookTask ? bookTask.name : 'default'}-${bookTaskDetail ? bookTaskDetail.name : 'default'
|
||||
}-${taskType}`
|
||||
|
||||
let bookBackTask = {
|
||||
id: uuidv4(),
|
||||
@@ -183,15 +180,14 @@ export class BookBackTaskListService extends BaseRealmService {
|
||||
executeType: executeType,
|
||||
status: BookBackTaskStatus.WAIT,
|
||||
createTime: new Date(),
|
||||
updateTime: new Date()
|
||||
}
|
||||
updateTime: new Date(),
|
||||
startTime: 0,
|
||||
endTime: 0
|
||||
} as TaskModal.Task
|
||||
this.realm.write(() => {
|
||||
this.realm.create('BookBackTaskList', bookBackTask)
|
||||
})
|
||||
|
||||
// 添加成功之后,调用开始执行任务的方法
|
||||
await global.taskManager.ExecuteAutoTask()
|
||||
|
||||
return successMessage(
|
||||
bookBackTask,
|
||||
'新增后台队列任务到数据库成功',
|
||||
@@ -210,7 +206,7 @@ export class BookBackTaskListService extends BaseRealmService {
|
||||
* (对于后台的队列任务只能修改状态)和错误信息
|
||||
* @param bookBackTask 修改的数据
|
||||
*/
|
||||
UpdateTaskStatus(bookBackTask) {
|
||||
UpdateTaskStatus(bookBackTask: Book.UpdateBookTaskListStatus): GeneralResponse.SuccessItem {
|
||||
try {
|
||||
// 判断数据是不是存在
|
||||
if (isEmpty(bookBackTask.id) || isEmpty(bookBackTask.status)) {
|
||||
@@ -219,7 +215,7 @@ export class BookBackTaskListService extends BaseRealmService {
|
||||
// 开始修改
|
||||
this.transaction(() => {
|
||||
// 获取指定ID的队列任务
|
||||
let _bookBackTask = this.realm.objectForPrimaryKey('BookBackTaskList', bookBackTask.id)
|
||||
let _bookBackTask = this.realm.objectForPrimaryKey('BookBackTaskList', bookBackTask.id) as TaskModal.Task
|
||||
// 判断数据是不是存在
|
||||
if (_bookBackTask == null) {
|
||||
throw new Error('修改后台队列任务失败,数据不存在')
|
||||
@@ -229,6 +225,16 @@ export class BookBackTaskListService extends BaseRealmService {
|
||||
if (bookBackTask.errorMessage) {
|
||||
_bookBackTask.errorMessage = bookBackTask.errorMessage
|
||||
}
|
||||
// 根据状态修改结束和完成时间
|
||||
if (bookBackTask.status == BookBackTaskStatus.RUNNING) {
|
||||
_bookBackTask.startTime = new Date().getTime()
|
||||
} else if (bookBackTask.status == BookBackTaskStatus.DONE || bookBackTask.status == BookBackTaskStatus.FAIL || bookBackTask.status == BookBackTaskStatus.PAUSE) {
|
||||
_bookBackTask.endTime = new Date().getTime()
|
||||
} else if (bookBackTask.status == BookBackTaskStatus.RECONNECT) {
|
||||
_bookBackTask.startTime = 0;
|
||||
_bookBackTask.endTime = 0;
|
||||
}
|
||||
|
||||
})
|
||||
return successMessage(
|
||||
bookBackTask,
|
||||
|
||||
@@ -7,12 +7,13 @@ import path from 'path'
|
||||
import {
|
||||
BookTaskDetailModel,
|
||||
MJMessage,
|
||||
ReversePrompt,
|
||||
SDConfig,
|
||||
Subtitle,
|
||||
WebuiConfig
|
||||
} from '../../model/Book/bookTaskDetail'
|
||||
import { BookBackTaskList } from '../../model/Book/BookBackTaskListModel'
|
||||
import { TaskExecuteType } from '../../../enum/bookEnum'
|
||||
import { BookTaskStatus, TaskExecuteType } from '../../../enum/bookEnum'
|
||||
import { version } from '../../../../../package.json'
|
||||
|
||||
let dbPath = path.resolve(define.db_path, 'book.realm')
|
||||
@@ -77,6 +78,83 @@ const migration = (oldRealm: Realm, newRealm: Realm) => {
|
||||
newBookTask[i].subtitlePosition = null // 设置字幕位置的默认值
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 9) {
|
||||
const oldBookTask = oldRealm.objects('BookBackTaskList')
|
||||
const newBookTask = newRealm.objects('BookBackTaskList')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].startTime = 0
|
||||
newBookTask[i].endTime = 0
|
||||
}
|
||||
}
|
||||
|
||||
if (oldRealm.schemaVersion < 10) {
|
||||
const oldBookTask = oldRealm.objects('BookTaskDetail')
|
||||
const newBookTask = newRealm.objects('BookTaskDetail')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].status = BookTaskStatus.WAIT
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 11) {
|
||||
const oldBookTask = oldRealm.objects('BookTaskDetail')
|
||||
const newBookTask = newRealm.objects('BookTaskDetail')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].reversePrompt = null
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 13) {
|
||||
const oldBookTask = oldRealm.objects('ReversePrompt')
|
||||
const newBookTask = newRealm.objects('ReversePrompt')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].promptCN = null;
|
||||
newBookTask[i].isSelect = false;
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 15) {
|
||||
const oldBookTask = oldRealm.objects('BookTaskDetail')
|
||||
const newBookTask = newRealm.objects('BookTaskDetail')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].imageCategory = null;
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 16) {
|
||||
const oldBookTask = oldRealm.objects('BookTask')
|
||||
const newBookTask = newRealm.objects('BookTask')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].subImageFolder = null;
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 17) {
|
||||
const oldBookTask = oldRealm.objects('BookTaskDetail')
|
||||
const newBookTask = newRealm.objects('BookTaskDetail')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].imageLock = false;
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 19) {
|
||||
const oldBookTask = oldRealm.objects('Book')
|
||||
const newBookTask = newRealm.objects('Book')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].draftSrtStyle = null;
|
||||
newBookTask[i].backgroundMusic = null;
|
||||
newBookTask[i].friendlyReminder = null;
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 20) {
|
||||
const oldBookTask = oldRealm.objects('BookTask')
|
||||
const newBookTask = newRealm.objects('BookTask')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].draftSrtStyle = null;
|
||||
newBookTask[i].backgroundMusic = null;
|
||||
newBookTask[i].friendlyReminder = null;
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 21) {
|
||||
const oldBookTask = oldRealm.objects('BookTaskDetail')
|
||||
const newBookTask = newRealm.objects('BookTaskDetail')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].subValue = '[]'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class BaseRealmService extends BaseService {
|
||||
@@ -114,10 +192,11 @@ export class BaseRealmService extends BaseService {
|
||||
SDConfig,
|
||||
WebuiConfig,
|
||||
BookTaskModel,
|
||||
ReversePrompt,
|
||||
BookTaskDetailModel
|
||||
],
|
||||
path: this.dbpath,
|
||||
schemaVersion: 8,
|
||||
schemaVersion: 21,
|
||||
migration: migration
|
||||
}
|
||||
this.realm = await Realm.open(config)
|
||||
|
||||
@@ -3,13 +3,16 @@ import { BookModel } from '../../model/Book/book.js'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { BookTaskStatus, BookType } from '../../../enum/bookEnum.js'
|
||||
import { successMessage } from '../../../../main/generalTools.js'
|
||||
import { CheckFolderExistsOrCreate, CopyFileOrFolder } from '../../../Tools/file.js'
|
||||
import { BookImageCategory, BookTaskStatus, BookType } from '../../../enum/bookEnum.js'
|
||||
import { successMessage } from '../../../../main/Public/generalTools'
|
||||
import { CheckFolderExistsOrCreate, CopyFileOrFolder } from '../../../Tools/file'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
import { BookTaskService } from './bookTaskService'
|
||||
import { BaseRealmService } from './bookBasic.js'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { FfmpegOptions } from '../../../../main/Service/ffmpegOptions.js'
|
||||
import { version } from '../../../../../package.json'
|
||||
import { Book } from '../../../../model/book.js'
|
||||
|
||||
export class BookService extends BaseRealmService {
|
||||
static instance: BookService | null = null
|
||||
@@ -36,14 +39,14 @@ export class BookService extends BaseRealmService {
|
||||
* 获取小说信息,没有找到返回null
|
||||
* @param bookId
|
||||
*/
|
||||
GetBookDataById(bookId) {
|
||||
GetBookDataById(bookId): Book.SelectBook | null {
|
||||
try {
|
||||
if (isEmpty(bookId)) {
|
||||
throw new Error('获取小说信息失败,缺少小说ID')
|
||||
}
|
||||
let books = this.realm.objects<BookModel>('Book').filtered('id = $0', bookId)
|
||||
if (books.length <= 0) {
|
||||
return successMessage(null, '通过ID获取小说数据成功', 'ReverseBook_GetBookDataById')
|
||||
return null
|
||||
} else {
|
||||
// 对返回的数据进行处理
|
||||
let resBooks = Array.from(books).map((book) => {
|
||||
@@ -63,8 +66,7 @@ export class BookService extends BaseRealmService {
|
||||
}
|
||||
return bookObj
|
||||
})
|
||||
|
||||
return successMessage(resBooks[0], '通过ID获取小说数据成功', 'ReverseBook_GetBookDataById')
|
||||
return resBooks[0]
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
@@ -120,8 +122,10 @@ export class BookService extends BaseRealmService {
|
||||
: '',
|
||||
imageFolder: book.imageFolder
|
||||
? path.resolve(define.project_path, book.imageFolder.replace(/\\/g, '/'))
|
||||
: ''
|
||||
}
|
||||
: '',
|
||||
imageStyle: book.imageStyle ? Array.from(book.imageStyle) : [],
|
||||
customizeImageStyle: book.customizeImageStyle ? Array.from(book.imageStyle) : [],
|
||||
} as Book.SelectBook
|
||||
return bookObj
|
||||
})
|
||||
|
||||
@@ -186,14 +190,31 @@ export class BookService extends BaseRealmService {
|
||||
await CopyFileOrFolder(book.oldVideoPath, oldVideoPath)
|
||||
}
|
||||
|
||||
let ffmpegOptions = new FfmpegOptions();
|
||||
let res = await ffmpegOptions.FfmpegCompressVideo(oldVideoPath, 800, "2000k")
|
||||
|
||||
// 创建对应的文件夹
|
||||
await CheckFolderExistsOrCreate(bookFolderPath)
|
||||
await CheckFolderExistsOrCreate(imageFolder)
|
||||
await CheckFolderExistsOrCreate(bookTaskImageFolder) // 创建默认的任务文件夹
|
||||
// 修改数据
|
||||
book.oldVideoPath = path.relative(define.project_path, oldVideoPath)
|
||||
|
||||
let imageCategory = BookImageCategory.MJ
|
||||
if (book.type == BookType.SD_REVERSE) {
|
||||
imageCategory = BookImageCategory.SD
|
||||
} else if (book.type == BookType.MJ_REVERSE) {
|
||||
imageCategory = BookImageCategory.MJ
|
||||
} else if (book.type == BookType.ORIGINAL) {
|
||||
imageCategory = BookImageCategory.MJ
|
||||
} else {
|
||||
throw new Error('未知的小说类型')
|
||||
}
|
||||
|
||||
this.realm.write(() => {
|
||||
book.version = version
|
||||
this.realm.create('Book', book)
|
||||
|
||||
// 添加一个任务
|
||||
let bookTask = {
|
||||
id: uuidv4(),
|
||||
@@ -210,7 +231,9 @@ export class BookService extends BaseRealmService {
|
||||
errorMsg: null,
|
||||
isAuto: false,
|
||||
updateTime: new Date(),
|
||||
createTime: new Date()
|
||||
createTime: new Date(),
|
||||
version: version,
|
||||
imageCategory: imageCategory
|
||||
}
|
||||
|
||||
// 添加任务
|
||||
@@ -265,7 +288,7 @@ export class BookService extends BaseRealmService {
|
||||
|
||||
// 检查小说ID对应的数据是不是存在
|
||||
let bookRes = this.GetBookDataById(bookId)
|
||||
if (bookRes.data == null) {
|
||||
if (bookRes == null) {
|
||||
throw new Error('修改小说数据失败,小说ID对应的数据不存在')
|
||||
}
|
||||
|
||||
@@ -279,11 +302,11 @@ export class BookService extends BaseRealmService {
|
||||
})
|
||||
|
||||
bookRes = this.GetBookDataById(bookId)
|
||||
if (bookRes.data == null) {
|
||||
if (bookRes == null) {
|
||||
throw new Error('获取修改后的小说数据失败,小说ID对应的数据不存在')
|
||||
}
|
||||
|
||||
return successMessage(bookRes.data, '修改小说数据成功', 'ReverseBook_UpdateBookData')
|
||||
return successMessage(bookRes, '修改小说数据成功', 'ReverseBook_UpdateBookData')
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
|
||||
@@ -4,19 +4,21 @@ import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { BookTaskModel } from '../../model/Book/bookTask.js'
|
||||
import { BookTaskStatus } from '../../../enum/bookEnum.js'
|
||||
import { successMessage } from '../../../../main/generalTools.js'
|
||||
import { successMessage } from '../../../../main/Public/generalTools'
|
||||
import { BaseRealmService } from './bookBasic'
|
||||
import { endsWith, isEmpty } from 'lodash'
|
||||
import { cloneDeep, endsWith, isEmpty } from 'lodash'
|
||||
import { book } from '../../../../preload/book.js'
|
||||
import { DefaultObject } from 'realm/dist/public-types/schema.js'
|
||||
import { JoinPath } from '../../../Tools/file.js'
|
||||
import { BookTaskDetailModel } from '../../model/Book/bookTaskDetail.js'
|
||||
import { JoinPath } from '../../../Tools/file'
|
||||
import { BookTaskDetailModel, ReversePrompt } from '../../model/Book/bookTaskDetail.js'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
import { Book } from "../../../../model/book"
|
||||
import { GeneralResponse } from '../../../../model/generalResponse.js'
|
||||
|
||||
let dbPath = path.resolve(define.db_path, 'book.realm')
|
||||
|
||||
// 版本迁移
|
||||
const migration = (oldRealm: Realm, newRealm: Realm) => {}
|
||||
const migration = (oldRealm: Realm, newRealm: Realm) => { }
|
||||
|
||||
export class BookTaskDetailService extends BaseRealmService {
|
||||
static instance: BookTaskDetailService | null = null
|
||||
@@ -43,7 +45,7 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
* 更具条件查询执行的小说的分镜信息
|
||||
* @param condition 查询的条件,id,name,bookId,bookTaskId
|
||||
*/
|
||||
GetBookTaskData(condition) {
|
||||
GetBookTaskData(condition: Book.QueryBookTaskDetailCondition) {
|
||||
try {
|
||||
if (condition == null) {
|
||||
throw new Error('查询小说分镜信息,查询条件不能为空')
|
||||
@@ -62,6 +64,7 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
tasksToDelete = tasksToDelete.filtered('name==$0', condition.name)
|
||||
}
|
||||
|
||||
|
||||
let resData = Array.from(tasksToDelete).map((item) => {
|
||||
let resObj = {
|
||||
...item,
|
||||
@@ -71,9 +74,17 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
outImagePath: JoinPath(define.project_path, item.outImagePath),
|
||||
subImagePath: (item.subImagePath as string[])?.map((subImage) => {
|
||||
return JoinPath(define.project_path, subImage)
|
||||
})
|
||||
}),
|
||||
characterTags: item.characterTags ? item.characterTags.map((tag) => tag) : null,
|
||||
subValue: item.subValue,
|
||||
reversePrompt: item.reversePrompt.map((reversePrompt) => {
|
||||
return {
|
||||
...reversePrompt
|
||||
}
|
||||
}),
|
||||
mjMessage: item.mjMessage ? item.mjMessage.toJSON() : null,
|
||||
}
|
||||
return resObj
|
||||
return cloneDeep(resObj)
|
||||
})
|
||||
return successMessage(
|
||||
resData,
|
||||
@@ -89,7 +100,7 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
* 通过ID获取指定的小说任务分镜详细数据
|
||||
* @param bookTaskDetailId
|
||||
*/
|
||||
public GetBookTaskDetailDataById(bookTaskDetailId: string) {
|
||||
public GetBookTaskDetailDataById(bookTaskDetailId: string): Book.SelectBookTaskDetail {
|
||||
try {
|
||||
if (bookTaskDetailId == null) {
|
||||
throw new Error('获取小说任务详细信息失败,缺少ID')
|
||||
@@ -97,17 +108,9 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
|
||||
let bookTaskDetails = this.GetBookTaskData({ id: bookTaskDetailId })
|
||||
if (bookTaskDetails.data.length <= 0) {
|
||||
return successMessage(
|
||||
null,
|
||||
'未找到对应的小说任务详细信息',
|
||||
'BookTaskDetailService_GetBookTaskDetailDataById'
|
||||
)
|
||||
return null;
|
||||
} else {
|
||||
return successMessage(
|
||||
bookTaskDetails.data[0],
|
||||
'获取小说任务详细信息成功',
|
||||
'BookTaskDetailService_GetBookTaskDetailDataById'
|
||||
)
|
||||
return bookTaskDetails.data[0]
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
@@ -142,6 +145,7 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
|
||||
bookTaskDetail.name = name
|
||||
bookTaskDetail.id = uuidv4()
|
||||
bookTaskDetail.imageLock = false
|
||||
bookTaskDetail.createTime = new Date()
|
||||
bookTaskDetail.updateTime = new Date()
|
||||
bookTaskDetail.adetailer = false // 先写死false
|
||||
@@ -165,7 +169,7 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
* @param bookTaskDetailId
|
||||
* @param updateData
|
||||
*/
|
||||
UpdateBookTaskDetail(bookTaskDetailId: string, updateData) {
|
||||
UpdateBookTaskDetail(bookTaskDetailId: string, updateData: Book.SelectBookTaskDetail) {
|
||||
try {
|
||||
this.transaction(() => {
|
||||
let bookTaskDetail = this.realm.objectForPrimaryKey('BookTaskDetail', bookTaskDetailId)
|
||||
@@ -188,6 +192,53 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
}
|
||||
}
|
||||
|
||||
UpdateBookTaskDetailMjMessage(bookTaskDetailId: string, mjMessage: Book.MJMessage): void {
|
||||
try {
|
||||
this.transaction(() => {
|
||||
let mjMessageRes = this.realm.objectForPrimaryKey('MJMessage', bookTaskDetailId)
|
||||
let bookTaskDetail = this.realm.objectForPrimaryKey('BookTaskDetail', bookTaskDetailId)
|
||||
if (bookTaskDetail.mjMessage == null) {
|
||||
// 新增
|
||||
mjMessage.id = bookTaskDetailId
|
||||
bookTaskDetail.mjMessage = mjMessage
|
||||
} else {
|
||||
for (const key in mjMessage) {
|
||||
mjMessageRes[key] = mjMessage[key]
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新指定ID的反推提示词数据
|
||||
* @param bookTaskDetailId 分镜数据的ID
|
||||
* @param reversePromptId 反推出来的提示词ID
|
||||
* @param updateData 要更新的数据
|
||||
*/
|
||||
UpdateBookTaskDetailReversePrompt(bookTaskDetailId: string, reversePromptId: string, reversePrompt: Book.ReversePrompt): GeneralResponse.SuccessItem {
|
||||
try {
|
||||
this.transaction(() => {
|
||||
let bookTaskDetails = this.realm.objects<ReversePrompt>("ReversePrompt");
|
||||
bookTaskDetails = bookTaskDetails.filtered("id = $0 && bookTaskDetailId = $1", reversePromptId, bookTaskDetailId);
|
||||
|
||||
if (bookTaskDetails.length <= 0) {
|
||||
throw new Error("未找到执行的翻译数据,无法写回")
|
||||
}
|
||||
let bookTaskDetail = bookTaskDetails[0];
|
||||
// 直接写入
|
||||
for (const key in reversePrompt) {
|
||||
bookTaskDetail[key] = reversePrompt[key]
|
||||
}
|
||||
})
|
||||
return successMessage(null, `${reversePromptId} 更新完成`, "BookTaskDetailService_UpdateBookTaskDetailReversePrompt")
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除满足条件的对象吗,必传小说ID和小说任务ID
|
||||
* @param condition bookId,bookTaskId,name,id
|
||||
@@ -223,4 +274,18 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定ID的小说任务详细数据中的所有的反推提示词数据
|
||||
* @param bookTaskDetailId 小说分镜的ID
|
||||
*/
|
||||
DeleteBookTaskDetailReversePromptById(bookTaskDetailId: string): void {
|
||||
let bookTaskDetail = this.realm.objectForPrimaryKey('BookTaskDetail', bookTaskDetailId);
|
||||
if (bookTaskDetail == null) {
|
||||
throw new Error('删除小说任务详细信息的反推提示词失败,未找到对应的分镜信息')
|
||||
}
|
||||
this.transaction(() => {
|
||||
this.realm.delete(bookTaskDetail.reversePrompt)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,29 @@
|
||||
import Realm from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { BookTaskModel } from '../../model/Book/bookTask.js'
|
||||
import { BookBackTaskStatus, BookTaskStatus } from '../../../enum/bookEnum.js'
|
||||
import { successMessage } from '../../../../main/generalTools.js'
|
||||
import { BookBackTaskStatus, BookImageCategory, BookTaskStatus } from '../../../enum/bookEnum.js'
|
||||
import { successMessage } from '../../../../main/Public/generalTools'
|
||||
import { BaseRealmService } from './bookBasic'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { JoinPath } from '../../../Tools/file.js'
|
||||
import { JoinPath } from '../../../Tools/file'
|
||||
import { BookBackTaskList } from '../../model/Book/BookBackTaskListModel.js'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
import { Book } from '../../../../model/book'
|
||||
import { TagDefine } from '../../../tagDefine.js'
|
||||
import { ImageStyleDefine } from "../../../../define/iamgeStyleDefine"
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { GeneralResponse } from '../../../../model/generalResponse'
|
||||
|
||||
let dbPath = path.resolve(define.db_path, 'book.realm')
|
||||
|
||||
export class BookTaskService extends BaseRealmService {
|
||||
static instance: BookTaskService | null = null
|
||||
realm: Realm
|
||||
tagDefine: TagDefine
|
||||
|
||||
private constructor() {
|
||||
super()
|
||||
this.tagDefine = new TagDefine()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,7 +43,7 @@ export class BookTaskService extends BaseRealmService {
|
||||
* 查询满足条件的小说子任务信息
|
||||
* @param bookTaskCondition 查询条件 id,bookId,name,no,page, pageSize
|
||||
*/
|
||||
GetBookTaskData(bookTaskCondition) {
|
||||
GetBookTaskData(bookTaskCondition: Book.QueryBookTaskCondition): GeneralResponse.ErrorItem | GeneralResponse.SuccessItem {
|
||||
try {
|
||||
// 获取所有的小说数据,并进行时间降序排序
|
||||
let bookTasks = this.realm.objects<BookTaskModel>('BookTask')
|
||||
@@ -62,7 +67,7 @@ export class BookTaskService extends BaseRealmService {
|
||||
}
|
||||
let bookTask_length = bookTasks.length
|
||||
|
||||
bookTasks = bookTasks.sorted('updateTime', true)
|
||||
// bookTasks = bookTasks.sorted('updateTime', true)
|
||||
// 判断是不是有page和pageSize,有的话对查询返回的信息做分页
|
||||
if (bookTaskCondition.page && bookTaskCondition.pageSize) {
|
||||
bookTasks = bookTasks.slice(
|
||||
@@ -73,22 +78,24 @@ export class BookTaskService extends BaseRealmService {
|
||||
|
||||
// 做一下数据转换
|
||||
// 将realm对象数组转换为普通对象数组
|
||||
// 将realm对象数组转换为普通对象数组,并处理异步操作
|
||||
let res_bookTasks = Array.from(bookTasks).map((bookTask) => {
|
||||
// 这里可以直接操作普通对象
|
||||
let bookObj = {
|
||||
// 直接操作普通对象
|
||||
return {
|
||||
...bookTask,
|
||||
styleList: bookTask.styleList ? Array.from(bookTask.styleList) : [],
|
||||
imageStyle: bookTask.imageStyle ? Array.from(bookTask.imageStyle) : [],
|
||||
customizeImageStyle: bookTask.customizeImageStyle ? Array.from(bookTask.customizeImageStyle) : [],
|
||||
generateVideoPath: JoinPath(define.project_path, bookTask.generateVideoPath),
|
||||
srtPath: JoinPath(define.project_path, bookTask.srtPath),
|
||||
audioPath: JoinPath(define.project_path, bookTask.audioPath),
|
||||
imageFolder: JoinPath(define.project_path, bookTask.imageFolder)
|
||||
}
|
||||
return bookObj
|
||||
imageFolder: JoinPath(define.project_path, bookTask.imageFolder),
|
||||
imageCategory: bookTask.imageCategory ? bookTask.imageCategory : BookImageCategory.MJ, // 默认使用MJ出图
|
||||
} as Book.SelectBookTask;
|
||||
})
|
||||
|
||||
return successMessage(
|
||||
{
|
||||
bookTasks: res_bookTasks,
|
||||
bookTasks: JSON.parse(JSON.stringify(res_bookTasks)),
|
||||
total: bookTask_length
|
||||
},
|
||||
'查询小说任务成功',
|
||||
@@ -103,7 +110,7 @@ export class BookTaskService extends BaseRealmService {
|
||||
* 通过ID获取小说批次任务的数据
|
||||
* @param bookTaskId
|
||||
*/
|
||||
GetBookTaskDataById(bookTaskId: string) {
|
||||
GetBookTaskDataById(bookTaskId: string): Book.SelectBookTask {
|
||||
try {
|
||||
if (bookTaskId == null) {
|
||||
throw new Error('小说任务ID不能为空')
|
||||
@@ -111,13 +118,9 @@ export class BookTaskService extends BaseRealmService {
|
||||
|
||||
let bookTasks = this.GetBookTaskData({ id: bookTaskId })
|
||||
if (bookTasks.data.bookTasks.length <= 0) {
|
||||
return successMessage(null, '未找到对应的小说任务', 'BookTaskService_GetBookTaskDataById')
|
||||
throw new Error('未找到对应的小说任务')
|
||||
} else {
|
||||
return successMessage(
|
||||
bookTasks.data.bookTasks[0],
|
||||
'查询小说任务成功',
|
||||
'BookTaskService_GetBookTaskDataById'
|
||||
)
|
||||
return bookTasks.data.bookTasks[0]
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
@@ -183,6 +186,28 @@ export class BookTaskService extends BaseRealmService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改小说批次任务数据
|
||||
* @param bookTaskId 小说批次任务ID
|
||||
* @param data 要修改的数据
|
||||
*/
|
||||
UpdetedBookTaskData(bookTaskId: string, data: Book.SelectBookTask): void {
|
||||
try {
|
||||
this.transaction(() => {
|
||||
let updateData = this.realm.objectForPrimaryKey('BookTask', bookTaskId)
|
||||
if (updateData == null) {
|
||||
throw new Error('未找到对应的小说任务详细信息')
|
||||
}
|
||||
// 开始修改
|
||||
for (let key in data) {
|
||||
updateData[key] = data[key]
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 添加一条数据
|
||||
AddOrModifyBookTask(bookTask) {
|
||||
try {
|
||||
@@ -220,4 +245,73 @@ export class BookTaskService extends BaseRealmService {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
private resetBookTask(bookTaskId: string) {
|
||||
let modifyBookTask = this.realm.objectForPrimaryKey('BookTask', bookTaskId)
|
||||
modifyBookTask.status = BookTaskStatus.WAIT
|
||||
modifyBookTask.errorMsg = "";
|
||||
modifyBookTask.updateTime = new Date()
|
||||
modifyBookTask.imageStyle = []
|
||||
modifyBookTask.autoAnalyzeCharacter = undefined
|
||||
modifyBookTask.customizeImageStyle = []
|
||||
modifyBookTask.videoConfig = undefined
|
||||
modifyBookTask.prefixPrompt = undefined
|
||||
modifyBookTask.suffixPrompt = undefined
|
||||
modifyBookTask.subImageFolder = []
|
||||
|
||||
let bookTaskDetails = this.realm.objects('BookTaskDetail').filtered('bookTaskId = $0', bookTaskId)
|
||||
// 开始删除数据
|
||||
bookTaskDetails.forEach(bookTaskDetail => {
|
||||
// 删除MJMessage
|
||||
if (bookTaskDetail.mjMessage) {
|
||||
this.realm.delete(bookTaskDetail.mjMessage)
|
||||
}
|
||||
|
||||
if (bookTaskDetail.reversePrompt) {
|
||||
(bookTaskDetail.reversePrompt as any[]).forEach(item => {
|
||||
this.realm.delete(item)
|
||||
})
|
||||
}
|
||||
if (bookTaskDetail.sdConifg) {
|
||||
this.realm.delete(bookTaskDetail.sdConifg)
|
||||
}
|
||||
this.realm.delete(bookTaskDetail)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除对应的小说批次数据
|
||||
* @param bookTaskId 小说批次ID
|
||||
*/
|
||||
ResetBookTask(bookTaskId: string): void {
|
||||
try {
|
||||
// 开始重置数据,先重置小说批次数据,在重置其他
|
||||
this.transaction(() => {
|
||||
this.resetBookTask(bookTaskId)
|
||||
})
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除对应的小说批次数据
|
||||
* @param bookTaskId 要删除的批次的ID
|
||||
*/
|
||||
DeleteBookTask(bookTaskId: string): void {
|
||||
try {
|
||||
this.transaction(() => {
|
||||
// 先调用清除数据的方法
|
||||
this.resetBookTask(bookTaskId)
|
||||
// 删除批次数据
|
||||
let bookTask = this.realm.objectForPrimaryKey('BookTask', bookTaskId)
|
||||
if (bookTask == null) {
|
||||
throw new Error('未找到对应的小说任务,无法执行删除操作')
|
||||
}
|
||||
this.realm.delete(bookTask)
|
||||
})
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ import Realm, { UpdateMode } from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { SoftwareModel } from '../../model/SoftWare/software.js'
|
||||
import { SoftwareModel } from '../../model/SoftWare/software'
|
||||
import { ComponentSize, SoftwareThemeType } from '../../../enum/softwareEnum.js'
|
||||
import { errorMessage, successMessage } from '../../../../main/generalTools.js'
|
||||
import { errorMessage, successMessage } from '../../../../main/Public/generalTools'
|
||||
import { BaseSoftWareService } from './softwareBasic.js'
|
||||
import { isEmpty } from 'lodash'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
@@ -2,13 +2,14 @@ import Realm, { UpdateMode } from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService'
|
||||
import { define } from '../../../define.js'
|
||||
import { SoftwareModel } from '../../model/SoftWare/software.js'
|
||||
import { SoftwareModel } from '../../model/SoftWare/software'
|
||||
import { ComponentSize, SoftwareThemeType } from '../../../enum/softwareEnum.js'
|
||||
import { errorMessage, successMessage } from '../../../../main/generalTools.js'
|
||||
import { errorMessage, successMessage } from '../../../../main/Public/generalTools'
|
||||
import { BaseSoftWareService } from './softwareBasic.js'
|
||||
import { isEmpty, isNumber } from 'lodash'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
import { version } from '../../../../../package.json'
|
||||
import { GeneralResponse } from '../../../../model/generalResponse'
|
||||
|
||||
export class MJSettingService extends BaseSoftWareService {
|
||||
static instance: MJSettingService | null = null
|
||||
@@ -561,7 +562,7 @@ export class MJSettingService extends BaseSoftWareService {
|
||||
// 判断API设置的数据是不是存在
|
||||
let apiSetting = mjSetting.apiSetting ? mjSetting.apiSetting : null
|
||||
if (apiSetting != null) {
|
||||
let apiSettingRes: { code: number; data: any; message: any }
|
||||
let apiSettingRes: GeneralResponse.ErrorItem | GeneralResponse.SuccessItem
|
||||
if (isEmpty(apiSetting.id)) {
|
||||
// 新增
|
||||
apiSettingRes = this.AddAPIMjSetting(apiSetting)
|
||||
@@ -577,7 +578,7 @@ export class MJSettingService extends BaseSoftWareService {
|
||||
// 判断浏览器模式的数据是不是存在
|
||||
let browserSetting = mjSetting.browserSetting ? mjSetting.browserSetting : null
|
||||
if (browserSetting != null) {
|
||||
let browserSettingRes: { code: number; data: any; message: any }
|
||||
let browserSettingRes: GeneralResponse.ErrorItem | GeneralResponse.SuccessItem
|
||||
if (isEmpty(browserSetting.id)) {
|
||||
// 新增
|
||||
browserSettingRes = this.AddBrowserMJSetting(browserSetting)
|
||||
@@ -591,7 +592,7 @@ export class MJSettingService extends BaseSoftWareService {
|
||||
}
|
||||
|
||||
// 添加MJ的基础配置信息
|
||||
let mjSettingRes: { code: number; data: any; message: any }
|
||||
let mjSettingRes: GeneralResponse.ErrorItem | GeneralResponse.SuccessItem
|
||||
if (isEmpty(mjSetting.id)) {
|
||||
// 新增
|
||||
mjSettingRes = this.AddMJSetting(mjSetting)
|
||||
|
||||
@@ -131,6 +131,22 @@ const migration = (oldRealm: Realm, newRealm: Realm) => {
|
||||
}
|
||||
})
|
||||
}
|
||||
if (oldRealm.schemaVersion < 18) {
|
||||
newRealm.write(() => {
|
||||
const newSoftwares = newRealm.objects('Software')
|
||||
for (let software of newSoftwares) {
|
||||
software.watermarkSetting = null // 水印的默认设置
|
||||
}
|
||||
})
|
||||
}
|
||||
if (oldRealm.schemaVersion < 19) {
|
||||
newRealm.write(() => {
|
||||
const newSoftwares = newRealm.objects('Software')
|
||||
for (let software of newSoftwares) {
|
||||
software.translationSetting = null // 翻译的默认设置
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class BaseSoftWareService extends BaseService {
|
||||
@@ -169,7 +185,7 @@ export class BaseSoftWareService extends BaseService {
|
||||
MjSettingModel
|
||||
],
|
||||
path: dbPath,
|
||||
schemaVersion: 17, // 当前版本号
|
||||
schemaVersion: 19, // 当前版本号
|
||||
migration: migration
|
||||
}
|
||||
// 判断当前全局是不是又当前这个
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import Realm, { UpdateMode } from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { SoftwareModel } from '../../model/SoftWare/software.js'
|
||||
import { ComponentSize, SoftwareThemeType } from '../../../enum/softwareEnum.js'
|
||||
import { successMessage } from '../../../../main/generalTools.js'
|
||||
import { successMessage } from '../../../../main/Public/generalTools'
|
||||
import { BaseSoftWareService } from './softwareBasic.js'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
@@ -63,12 +58,26 @@ export class SoftwareService extends BaseSoftWareService {
|
||||
*/
|
||||
GetSoftwareData() {
|
||||
try {
|
||||
let software = this.realm.objects('Software')
|
||||
let softwares = this.realm.objects('Software')
|
||||
|
||||
let res = Array.from(softwares).map((software) => {
|
||||
// 这里可以直接操作普通对象
|
||||
let bookObj = {
|
||||
id: software.id,
|
||||
theme: software.theme,
|
||||
reverse_show_book_striped: software.reverse_show_book_striped,
|
||||
reverse_data_table_size: software.reverse_data_table_size,
|
||||
reverse_display_show: software.reverse_display_show,
|
||||
}
|
||||
return bookObj
|
||||
})
|
||||
|
||||
return successMessage(
|
||||
software.toJSON(),
|
||||
res,
|
||||
'获取软件配置信息成功',
|
||||
'SoftwareService_GetSoftwareData'
|
||||
)
|
||||
|
||||
} catch (error) {
|
||||
global.logger.error(
|
||||
'SoftwareService_GetSoftwareData',
|
||||
@@ -82,17 +91,15 @@ export class SoftwareService extends BaseSoftWareService {
|
||||
* 获取当前软件指定属性的数据
|
||||
* @param property 属性名称
|
||||
*/
|
||||
GetSoftWarePropertyData(property: string) {
|
||||
GetSoftWarePropertyData(property: string): string {
|
||||
try {
|
||||
let software = this.realm.objects('Software')
|
||||
if (software.length <= 0) {
|
||||
throw new Error('数据库中没有软件配置信息')
|
||||
}
|
||||
|
||||
let softwareData = software.toJSON()[0]
|
||||
let res = softwareData[property]
|
||||
|
||||
return successMessage(res, '获取软件配置信息成功', 'SoftwareService_GetSoftWarePropertyData')
|
||||
let res = softwareData[property] as string
|
||||
return res
|
||||
} catch (error) {
|
||||
global.logger.error(
|
||||
'SoftwareService_GetSoftWarePropertyData',
|
||||
|
||||
@@ -15,6 +15,8 @@ if (!app.isPackaged) {
|
||||
scripts_path: path.join(__dirname, '../../resources/scripts'),
|
||||
db_path: path.join(__dirname, '../../resources/scripts/db'),
|
||||
project_path: path.join(__dirname, '../../project'),
|
||||
tts_path: path.join(__dirname, '../../tts'),
|
||||
|
||||
logger_path: path.join(__dirname, '../../resources/logger'),
|
||||
package_path: path.join(__dirname, '../../resources/package'),
|
||||
image_path: path.join(__dirname, '../../resources/image'),
|
||||
@@ -82,6 +84,7 @@ if (!app.isPackaged) {
|
||||
scripts_path: path.join(__dirname, '../../../resources/scripts'),
|
||||
db_path: path.join(__dirname, '../../../resources/scripts/db'),
|
||||
project_path: path.join(__dirname, '../../../project'),
|
||||
tts_path: path.join(__dirname, '../../../tts'),
|
||||
logger_path: path.join(__dirname, '../../../resources/logger'),
|
||||
package_path: path.join(__dirname, '../../../resources/package'),
|
||||
discordScript: path.join(__dirname, '../../../resources/scripts/discordScript.js'),
|
||||
@@ -141,5 +144,7 @@ if (!app.isPackaged) {
|
||||
|
||||
define['remotemj_api'] = 'https://api.laitool.net/'
|
||||
define['serverUrl'] = 'http://lapi.laitool.cn'
|
||||
define['hkServerUrl'] = 'https://api.laitool.cc/'
|
||||
define['bakServerUrl'] = 'https://bakapi.laitool.cc/'
|
||||
define['API'] = 'f85d39ed5a40fd09966f13f12b6cf0f0'
|
||||
export { define }
|
||||
export { define }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export const DEFINE_STRING = {
|
||||
SHOW_GLOBAL_MAIN_NOTIFICATION: 'SHOW_GLOBAL_MAIN_NOTIFICATION',
|
||||
OPEN_DEV_TOOLS_PASSWORD: 'OPEN_DEV_TOOLS_PASSWORD',
|
||||
OPEN_DEV_TOOLS: 'OPEN_DEV_TOOLS',
|
||||
GET_FILE_BASE64: 'GET_FILE_BASE64',
|
||||
@@ -21,7 +22,6 @@ export const DEFINE_STRING = {
|
||||
SAVE_KEY_FRAME_SETTING: 'SAVE_KEY_FRAME_SETTING',
|
||||
MODIFY_SAMPLE_SETTING: 'MODIFY_SAMPLE_SETTING',
|
||||
GET_SETTING_Dafault_DATA: 'GET_SETTING_Dafault_DATA',
|
||||
GET_DRAFT_FILE_LIST: 'GET_DRAFT_FILE_LIST',
|
||||
GET_FRAME: 'GET_FRAME',
|
||||
PYTHON_ERROR: 'PYTHON_ERROR',
|
||||
PYTHON_CLOSE: 'PYTHON_CLOSE',
|
||||
@@ -144,9 +144,16 @@ export const DEFINE_STRING = {
|
||||
NORMAL_PERMISSION: 'NORMAL_PERMISSION',
|
||||
AUTO_SAVE_IMAGE_PERMISSION: 'AUTO_SAVE_IMAGE_PERMISSION'
|
||||
},
|
||||
TRANSLATE: {
|
||||
TRANSLATE_NOW_RETURN: 'TRANSLATE_NOW_RETURN',
|
||||
GET_TRANSLATE_SETTING: 'GET_TRANSLATE_SETTING',
|
||||
RESET_TRANSLATE_SETTING: 'RESET_TRANSLATE_SETTING',
|
||||
SAVE_TRANSLATE_SETTING: 'SAVE_TRANSLATE_SETTING'
|
||||
},
|
||||
SD: {
|
||||
LOAD_SD_SERVICE_DATA: 'LOAD_SD_SERVICE_DATA',
|
||||
TXT2IMG: 'TXT2IMG'
|
||||
TXT2IMG: 'TXT2IMG',
|
||||
SD_MERGE_PROMPT: "SD_MERGE_PROMPT"
|
||||
},
|
||||
MJ: {
|
||||
SAVE_WORD_SRT: 'SAVE_WORD_SRT',
|
||||
@@ -167,7 +174,10 @@ export const DEFINE_STRING = {
|
||||
GET_MJ_IMAGE_SCALE: 'GET_MJ_IMAGE_SCALE',
|
||||
GET_MJ_IMAGE_ROBOT_MODEL: 'GET_MJ_IMAGE_ROBOT_MODEL',
|
||||
MACTH_USER_RETURN: 'MACTH_USER_RETURN',
|
||||
AUTO_MATCH_USER: 'AUTO_MATCH_USER'
|
||||
AUTO_MATCH_USER: 'AUTO_MATCH_USER',
|
||||
MJ_MERGE_PROMPT: "MJ_MERGE_PROMPT",
|
||||
ADD_MJ_GENADD_MJ_GENERATE_IMAGE_TASK: "ADD_MJ_GENADD_MJ_GENERATE_IMAGE_TASK",
|
||||
MJ_IMAGE: "MJ_IMAGE"
|
||||
},
|
||||
DISCORD: {
|
||||
OPERATE_REFRASH_DISCORD_URL: 'OPERATE_REFRASH_DISCORD_URL',
|
||||
@@ -195,6 +205,8 @@ export const DEFINE_STRING = {
|
||||
BATCH_PROCESS_IMAGE_RESULT: 'BATCH_PROCESS_IMAGE_RESULT'
|
||||
},
|
||||
BOOK: {
|
||||
MAIN_DATA_RETURN: 'MAIN_DATA_RETURN', // 监听任务返回
|
||||
|
||||
GET_BOOK_TYPE: 'GET_BOOK_TYPE',
|
||||
ADD_OR_MODIFY_BOOK: 'ADD_OR_MODIFY_BOOK',
|
||||
GET_BOOK_DATA: 'GET_BOOK_DATA',
|
||||
@@ -204,7 +216,39 @@ export const DEFINE_STRING = {
|
||||
SAVE_BOOK_SUBTITLE_POSITION: 'SAVE_BOOK_SUBTITLE_POSITION',
|
||||
OPEN_BOOK_SUBTITLE_POSITION_SCREENSHOT: 'OPEN_BOOK_SUBTITLE_POSITION_SCREENSHOT',
|
||||
GET_CURRENT_FRAME_TEXT: 'GET_CURRENT_FRAME_TEXT',
|
||||
GET_VIDEO_FRAME_TEXT: 'GET_VIDEO_FRAME_TEXT'
|
||||
GET_VIDEO_FRAME_TEXT: 'GET_VIDEO_FRAME_TEXT',
|
||||
GET_BOOK_TASK_DETAIL: 'GET_BOOK_TASK_DETAIL',
|
||||
REVERSE_PROMPT_TO_GPT_PROMPT: 'REVERSE_PROMPT_TO_GPT_PROMPT',
|
||||
SINGLE_REVERSE_TO_GPT_PROMPT: 'SINGLE_REVERSE_TO_GPT_PROMPT',
|
||||
SAVE_IMAGE_STYLE: 'SAVE_IMAGE_STYLE',
|
||||
IMAGE_LOCK_OPERATION: "IMAGE_LOCK_OPERATION",
|
||||
DOWNLOAD_IMAGE_AND_SPLIT: "DOWNLOAD_IMAGE_AND_SPLIT",
|
||||
ONE_TO_FOUR_BOOK_TASK: "ONE_TO_FOUR_BOOK_TASK",
|
||||
RESET_BOOK_TASK: "RESET_BOOK_TASK",
|
||||
DELETE_BOOK_TASK: "DELETE_BOOK_TASK",
|
||||
GENERATE_IMAGE_ALL: "GENERATE_IMAGE_ALL",
|
||||
CHECK_IMAGE_FILE_SIZE: "CHECK_IMAGE_FILE_SIZE",
|
||||
HD_IMAGE: "HD_IMAGE",
|
||||
USE_BOOK_VIDEO_DATA_TO_BOOK_TASK: "USE_BOOK_VIDEO_DATA_TO_BOOK_TASK",
|
||||
ADD_JIANYING_DRAFT: "ADD_JIANYING_DRAFT",
|
||||
|
||||
COMPUTE_STORYBOARD: 'COMPUTE_STORYBOARD',
|
||||
|
||||
GET_FRAME: 'GET_FRAME',
|
||||
|
||||
FRAMING: 'FRAMING',
|
||||
|
||||
GET_COPYWRITING: 'GET_COPYWRITING',
|
||||
GET_COPYWRITING_RETURN: 'GET_COPYWRITING_RETURN',
|
||||
|
||||
REMOVE_WATERMARK: 'REMOVE_WATERMARK',
|
||||
REMOVE_WATERMARK_RETURN: 'REMOVE_WATERMARK_RETURN',
|
||||
|
||||
SPLI_TAUDIO: 'SPLI_TAUDIO',
|
||||
SPLI_TAUDIO_RETURN: 'SPLI_TAUDIO_RETURN',
|
||||
|
||||
ADD_REVERSE_PROMPT: 'ADD_REVERSE_PROMPT',
|
||||
REMOVE_REVERSE_DATA: 'REMOVE_REVERSE_DATA'
|
||||
},
|
||||
SYSTEM: {
|
||||
OPEN_FILE: 'OPEN_FILE',
|
||||
@@ -225,7 +269,9 @@ export const DEFINE_STRING = {
|
||||
GET_REMOTE_MJ_SETTINGS: 'GET_REMOTE_MJ_SETTINGS',
|
||||
ADD_REMOTE_MJ_SETTING: 'ADD_REMOTE_MJ_SETTING',
|
||||
UPDATE_REMOTE_MJ_SETTING: 'UPDATE_REMOTE_MJ_SETTING',
|
||||
DELETE_REMOTE_MJ_SETTING: 'DELETE_REMOTE_MJ_SETTING'
|
||||
DELETE_REMOTE_MJ_SETTING: 'DELETE_REMOTE_MJ_SETTING',
|
||||
GET_WATER_MARK_SETTING: 'GET_WATER_MARK_SETTING',
|
||||
SAVE_WATER_MARK_SETTING: 'SAVE_WATER_MARK_SETTING'
|
||||
},
|
||||
PROMPT: {
|
||||
GET_SORT_OPTIONS: 'GET_SORT_OPTIONS',
|
||||
@@ -235,11 +281,16 @@ export const DEFINE_STRING = {
|
||||
},
|
||||
TTS: {
|
||||
GET_TTS_CONFIG: 'GET_TTS_CONFIG',
|
||||
GENERATE_AUDIO: 'GENERATE_AUDIO',
|
||||
SAVE_TTS_CONFIG: 'SAVE_TTS_CONFIG'
|
||||
},
|
||||
WRITE: {
|
||||
GET_WRITE_CONFIG: 'GET_WRITE_CONFIG',
|
||||
SAVE_WRITE_CONFIG: 'SAVE_WRITE_CONFIG',
|
||||
ACTION_START: 'ACTION_START'
|
||||
},
|
||||
DB: {
|
||||
UPDATE_BOOK_TASK_DATA: "UPDATE_BOOK_TASK_DATA",
|
||||
UPDATE_BOOK_TASK_DETAIL_DATA: "UPDATE_BOOK_TASK_DETAIL_DATA"
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,16 @@ export enum BookType {
|
||||
MJ_REVERSE = 'mj_reverse'
|
||||
}
|
||||
|
||||
// 出图方式
|
||||
export enum BookImageCategory {
|
||||
// MJ
|
||||
MJ = 'mj',
|
||||
// SD
|
||||
SD = 'sd',
|
||||
// D3
|
||||
D3 = 'd3'
|
||||
}
|
||||
|
||||
|
||||
|
||||
export enum MJCategroy {
|
||||
@@ -39,10 +49,16 @@ export enum BookBackTaskType {
|
||||
RECOGNIZE = 'recognize',
|
||||
// 抽帧
|
||||
FRAME = 'frame',
|
||||
// 反推
|
||||
REVERSE = 'reverse',
|
||||
// 生成图片
|
||||
IMAGE = 'image',
|
||||
// MJ反推
|
||||
MJ_REVERSE = BookType.MJ_REVERSE,
|
||||
// SD反推
|
||||
SD_REVERSE = BookType.SD_REVERSE,
|
||||
// MJ生成图片
|
||||
MJ_IMAGE = 'mj_image',
|
||||
// SD 生成图片
|
||||
SD_IMAGE = 'sd_image',
|
||||
// D3 生成图片
|
||||
D3_IMAGE = 'd3_image',
|
||||
// 高清
|
||||
HD = 'hd',
|
||||
// 合成视频
|
||||
@@ -63,7 +79,9 @@ export enum BookBackTaskStatus {
|
||||
// 完成
|
||||
DONE = 'done',
|
||||
// 失败
|
||||
FAIL = 'fail'
|
||||
FAIL = 'fail',
|
||||
// 重连
|
||||
RECONNECT = 'reconnect'
|
||||
}
|
||||
|
||||
export enum TaskExecuteType {
|
||||
@@ -74,6 +92,16 @@ export enum TaskExecuteType {
|
||||
OPERATE = 'operate'
|
||||
}
|
||||
|
||||
// 弹窗类型
|
||||
export enum DialogType {
|
||||
// 单独弹窗
|
||||
DIALOG = 'dialog',
|
||||
// 消息提示
|
||||
MESSAGE = 'message',
|
||||
// 右上角通知
|
||||
NOTIFICATION = 'notification'
|
||||
}
|
||||
|
||||
/**
|
||||
* 小说任务状态
|
||||
*/
|
||||
@@ -162,3 +190,40 @@ export enum BookTaskStatus {
|
||||
// 合成视频失败
|
||||
COMPOSING_FAIL = 'composing_fail'
|
||||
}
|
||||
|
||||
export enum TagDefineType {
|
||||
// 默认风格
|
||||
DEFAULT_STYLE = "default_style",
|
||||
// 角色标签
|
||||
CHARACTER_MAIN = "character_main",
|
||||
|
||||
// 角色小标签
|
||||
CHARACTER_SUB = "min",
|
||||
|
||||
// 风格主标签
|
||||
STYLE_MAIN = "style_main",
|
||||
|
||||
// 场景主标签
|
||||
SCENE_MAIN = "scene_main",
|
||||
}
|
||||
|
||||
export enum MergeType {
|
||||
BOOKTASK = 'bookTask', // 整个小说批次分镜合并
|
||||
BOOKTASKDETAIL = 'bookTaskDetail' // 单个分镜合并
|
||||
}
|
||||
|
||||
export enum OperateBookType {
|
||||
BOOK = 'book', // 这个小说的所有批次
|
||||
BOOKTASK = 'bookTask', // 整个小说批次分镜合并
|
||||
BOOKTASKDETAIL = 'bookTaskDetail', // 单个分镜合并
|
||||
UNDERBOOKTASK = 'underBookTask' // 执行小说批次任务的指定ID以及后面的所有的东西
|
||||
}
|
||||
|
||||
export enum CopyImageType {
|
||||
// 所有,包括原图
|
||||
ALL = 'all',
|
||||
// 出原图外其他,一个个对应
|
||||
ONE = 'one',
|
||||
// 不包含图
|
||||
NONE = 'none'
|
||||
}
|
||||
|
||||
@@ -19,3 +19,31 @@ export enum MJRobotType {
|
||||
// niji
|
||||
NIJI = 'niji'
|
||||
}
|
||||
|
||||
export enum MJSpeed {
|
||||
// 快速
|
||||
FAST = 'fast',
|
||||
|
||||
// 休闲
|
||||
RELAX = 'relaxed'
|
||||
}
|
||||
|
||||
export enum MJRespoonseType {
|
||||
// 创建
|
||||
CREATED = "created",
|
||||
// 更新
|
||||
UPDATED = "updated",
|
||||
// 完成
|
||||
FINISHED = "finished",
|
||||
// 删除
|
||||
DELETE = "delete"
|
||||
}
|
||||
|
||||
export enum MJAction {
|
||||
// 出图
|
||||
IMAGINE = 'IMAGINE',
|
||||
|
||||
// 反推
|
||||
DESCRIBE = 'DESCRIBE'
|
||||
|
||||
}
|
||||
|
||||
@@ -45,6 +45,31 @@ export enum SoftColor {
|
||||
// 棕黄色
|
||||
BROWN_YELLOW = '#e18a3b',
|
||||
|
||||
// 橘色
|
||||
ORANGE = '#ee7959',
|
||||
|
||||
// 朱颜酡
|
||||
ZHUYANTUO = '#f29a76',
|
||||
|
||||
// 错误红色
|
||||
ERROR_RED = '#c8161d'
|
||||
|
||||
}
|
||||
|
||||
export enum ResponseMessageType {
|
||||
GET_TEXT = 'getText', // 获取文案
|
||||
REMOVE_WATERMARK = "REMOVE_WATERMARK",// 删除水印
|
||||
MJ_REVERSE = 'MJ_REVERSE',// MJ反推,返回反推结果
|
||||
PROMPT_TRANSLATE = 'PROMPT_TRANSLATE',// 提示词翻译
|
||||
MJ_IMAGE = 'MJ_IMAGE',// MJ 生成图片
|
||||
HD_IMAGE = 'HD_IMAGE',// HD 生成图片
|
||||
}
|
||||
|
||||
export enum LaiAPIType {
|
||||
// 主要的
|
||||
MAIN = "main",
|
||||
// 香港代理
|
||||
HK_PROXY = "hk-proxy",
|
||||
// 备用站点
|
||||
BAK_MAIN = 'bak-main'
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export enum TaskQueueType {
|
||||
// 内存添加
|
||||
CACHE_ADD = 'cache_add',
|
||||
// 数据库添加
|
||||
DB_ADD = 'db_add'
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// 翻译类型(主要用于后端逻辑处理)
|
||||
export enum TranslateType {
|
||||
// 反推提示词翻译
|
||||
REVERSE_PROMPT_TRANSLATE = 'reverse_prompt_translate',
|
||||
|
||||
// GPT提示词翻译
|
||||
GPT_PROMPT_TRANSLATE = 'gpt_prompt_translate',
|
||||
}
|
||||
|
||||
// 翻译API类型
|
||||
export enum TranslateAPIType {
|
||||
// 百度翻译
|
||||
BAIDU = 'baidu',
|
||||
|
||||
// 腾讯翻译
|
||||
TENCENT = 'tencent',
|
||||
|
||||
// 火山翻译
|
||||
VOLCENGINE = 'volcengine',
|
||||
|
||||
// 阿里翻译
|
||||
ALI = 'ali',
|
||||
}
|
||||
@@ -8,6 +8,23 @@ export enum SubtitleSavePositionType {
|
||||
// 分镜视频
|
||||
STORYBOARD_VIDEO = 'storyboard_video',
|
||||
|
||||
// 设置,只是框选
|
||||
SETTING = 'setting',
|
||||
|
||||
// 其他类型
|
||||
OTHER = 'other'
|
||||
}
|
||||
|
||||
// 图片去除水印方法,返回数据的格式
|
||||
export enum WaterMarkResponseDateType {
|
||||
// 返回的数据类型
|
||||
ArrayBuffer = "arrayBuffer",
|
||||
// 直接将文件写道本地
|
||||
File = "file"
|
||||
}
|
||||
|
||||
|
||||
export enum RemoveWatermarkType {
|
||||
LOCAL_LAMA = 'local_lama',
|
||||
IOPAINT = 'iopaint'
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
let fspromises = require('fs').promises;
|
||||
import { get, cloneDeep } from 'lodash';
|
||||
import { define } from '../define';
|
||||
import { errorMessage } from '../../main/generalTools';
|
||||
import { errorMessage } from '../../main/Public/generalTools';
|
||||
|
||||
export class DynamicSetting {
|
||||
constructor(global) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { successMessage } from "../../main/generalTools";
|
||||
import { successMessage } from "../../main/Public/generalTools";
|
||||
|
||||
export class MjSetting {
|
||||
constructor(golbal) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { get } from "lodash";
|
||||
import { define } from "../define";
|
||||
let fspromises = require("fs").promises;
|
||||
import { Tools } from "../../main/tools";
|
||||
import { errorMessage } from "../../main/generalTools";
|
||||
import { errorMessage } from "../../main/Public/generalTools";
|
||||
let tools = new Tools();
|
||||
|
||||
// Create a shared object
|
||||
|
||||
+183
-182
@@ -1,195 +1,196 @@
|
||||
|
||||
let fspromises = require('fs').promises;
|
||||
import { get, cloneDeep } from 'lodash';
|
||||
import { define } from './define';
|
||||
import path from 'path';
|
||||
import { Tools } from '../main/tools';
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
let fspromises = require('fs').promises
|
||||
import { get, cloneDeep } from 'lodash'
|
||||
import { define } from './define'
|
||||
import path from 'path'
|
||||
import { Tools } from '../main/tools'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
export class TagDefine {
|
||||
constructor(global) {
|
||||
this.global = global;
|
||||
this.tools = new Tools();
|
||||
}
|
||||
constructor(global) {
|
||||
this.global = global
|
||||
this.tools = new Tools()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取tag选择模式(标签和下拉select)
|
||||
*/
|
||||
async getTagSelectModel() {
|
||||
return {
|
||||
code: 1,
|
||||
data:
|
||||
[
|
||||
{ label: "标签", value: "tag" },
|
||||
{ label: "下拉", value: "drop" },
|
||||
]
|
||||
/**
|
||||
* 获取tag选择模式(标签和下拉select)
|
||||
*/
|
||||
async getTagSelectModel() {
|
||||
return {
|
||||
code: 1,
|
||||
data: [
|
||||
{ label: '标签', value: 'tag' },
|
||||
{ label: '下拉', value: 'drop' }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过指定的类型,获取数据
|
||||
* @param {*} type default:在代码中写死的 dynamic:用户自定义的 all:写死的和自定义的合并返回
|
||||
* @param {*} property 要返回的属性的名称,若是传入null,返回整个属性的数据
|
||||
* @param {*} defaultData 默认数据,默认值为null
|
||||
* @returns
|
||||
*/
|
||||
async getTagDataByTypeAndProperty(type, property, defaultData = null) {
|
||||
try {
|
||||
let res = []
|
||||
// 获取自定义的GPT数据
|
||||
let tag_setting = JSON.parse(await fspromises.readFile(define.tag_setting, 'utf-8'))
|
||||
let data = get(tag_setting, property, {})
|
||||
// 若是传入的属性名为null,直接返回当前tags里面的所有的数据
|
||||
if (property == null) {
|
||||
data = tag_setting
|
||||
}
|
||||
|
||||
if (type == 'default') {
|
||||
// res = get(this, property, defaultData);
|
||||
} else if (type == 'dynamic') {
|
||||
res = data
|
||||
} else if (type == 'all') {
|
||||
let tmp_arr = cloneDeep(get([], property, defaultData))
|
||||
tmp_arr = tmp_arr.concat(data)
|
||||
res = tmp_arr
|
||||
} else {
|
||||
throw new Error(`不存在的类型 : ${value}`)
|
||||
}
|
||||
if (property) {
|
||||
res.forEach((item) => {
|
||||
if (item.show_image && item.show_image != '') {
|
||||
item.show_image = path.join(define.image_path, item.show_image)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// 返回之前,判断里面是不是有预览图片路径
|
||||
if (res.hasOwnProperty('character_tags')) {
|
||||
res.character_tags.forEach((item) => {
|
||||
if (item.show_image && item.show_image != '') {
|
||||
item.show_image = path.join(define.image_path, item.show_image)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过指定的类型,获取数据
|
||||
* @param {*} type default:在代码中写死的 dynamic:用户自定义的 all:写死的和自定义的合并返回
|
||||
* @param {*} property 要返回的属性的名称,若是传入null,返回整个属性的数据
|
||||
* @param {*} defaultData 默认数据,默认值为null
|
||||
* @returns
|
||||
*/
|
||||
async getTagDataByTypeAndProperty(type, property, defaultData = null) {
|
||||
try {
|
||||
let res = [];
|
||||
// 获取自定义的GPT数据
|
||||
let tag_setting = JSON.parse(await fspromises.readFile(define.tag_setting, 'utf-8'));
|
||||
let data = get(tag_setting, property, {});
|
||||
// 若是传入的属性名为null,直接返回当前tags里面的所有的数据
|
||||
if (property == null) {
|
||||
data = tag_setting;
|
||||
}
|
||||
|
||||
if (type == "default") {
|
||||
// res = get(this, property, defaultData);
|
||||
} else if (type == "dynamic") {
|
||||
res = data;
|
||||
} else if (type == "all") {
|
||||
let tmp_arr = cloneDeep(get([], property, defaultData));
|
||||
tmp_arr = tmp_arr.concat(data);
|
||||
res = tmp_arr;
|
||||
}
|
||||
else {
|
||||
throw new Error(`不存在的类型 : ${value}`);
|
||||
}
|
||||
|
||||
// 返回之前,判断里面是不是有预览图片路径
|
||||
if (res.hasOwnProperty("character_tags")) {
|
||||
res.character_tags.forEach(item => {
|
||||
if (item.show_image && item.show_image != "") {
|
||||
item.show_image = path.join(define.image_path, item.show_image);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (res.hasOwnProperty("scene_tags")) {
|
||||
res.scene_tags.forEach(item => {
|
||||
if (item.show_image && item.show_image != "") {
|
||||
item.show_image = path.join(define.image_path, item.show_image);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (res.hasOwnProperty("style_tags")) {
|
||||
res.style_tags.forEach(item => {
|
||||
if (item.show_image && item.show_image != "") {
|
||||
item.show_image = path.join(define.image_path, item.show_image);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
code: 1,
|
||||
data: res
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
if (res.hasOwnProperty('scene_tags')) {
|
||||
res.scene_tags.forEach((item) => {
|
||||
if (item.show_image && item.show_image != '') {
|
||||
item.show_image = path.join(define.image_path, item.show_image)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存gpt指定的属性数据,判断value中的ID是不是存在,存在直接覆盖,不存在追加
|
||||
* @param {*} value
|
||||
* @param {*} property
|
||||
*/
|
||||
async saveTagPropertyData(value) {
|
||||
try {
|
||||
let property = value[1];
|
||||
value = JSON.parse(value[0]);
|
||||
let tmp_key = uuidv4();
|
||||
|
||||
// 特殊操作。为角色和场景的时候,需要copy图片
|
||||
if (property == "character_tags" || property == "scene_tags" || property == "style_tags") {
|
||||
let show_image = value.show_image;
|
||||
if (show_image && show_image != "") {
|
||||
let file_name = `c_s/${value.key ? value.key : tmp_key}.png`
|
||||
let new_image_path = path.join(define.image_path, file_name);
|
||||
await this.tools.copyFileOrDirectory(show_image, new_image_path);
|
||||
value.show_image = file_name;
|
||||
value.children?.forEach(item => {
|
||||
item.show_image = file_name;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 获取自定义的GPT数据
|
||||
let tag_setting = JSON.parse(await fspromises.readFile(define.tag_setting, 'utf-8'));
|
||||
let tag = get(tag_setting, property, []);
|
||||
if (value.key) {
|
||||
// 判断当前ID的数据是否存在,存在覆盖,不存在追加
|
||||
let index = tag.findIndex(item => item.key == value.key);
|
||||
value.value = value.key;
|
||||
if (index < 0) {
|
||||
// 判断相同名字的数据是不是存在,存在报错
|
||||
if (tag.some(item => item.label == value.label)) {
|
||||
throw new Error("已存在相同名称的数据,请修改名称后再保存");
|
||||
}
|
||||
tag.push(value);
|
||||
} else {
|
||||
tag[index] = value;
|
||||
}
|
||||
} else {
|
||||
// 判断相同名字的数据是不是存在,存在报错
|
||||
if (tag.some(item => item.label == value.label)) {
|
||||
throw new Error("已存在相同名称的数据,请修改名称后再保存");
|
||||
}
|
||||
value.key = tmp_key;
|
||||
value.value = value.key;
|
||||
tag.push(value);
|
||||
}
|
||||
tag_setting[property] = tag;
|
||||
// 写入文件
|
||||
await fspromises.writeFile(define.tag_setting, JSON.stringify(tag_setting));
|
||||
return {
|
||||
code: 1,
|
||||
message: "保存成功"
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
if (res.hasOwnProperty('style_tags')) {
|
||||
res.style_tags.forEach((item) => {
|
||||
if (item.show_image && item.show_image != '') {
|
||||
item.show_image = path.join(define.image_path, item.show_image)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
code: 1,
|
||||
data: res
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除自定义GPT指定属性中的指定ID的数据
|
||||
* @param {*} id
|
||||
* @param {*} property
|
||||
*/
|
||||
async deleteTagPropertyData(value) {
|
||||
try {
|
||||
let property = value[1];
|
||||
let id = value[0];
|
||||
// 获取自定义的GPT数据
|
||||
let tag_setting = JSON.parse(await fspromises.readFile(define.tag_setting, 'utf-8'));
|
||||
let tags = tag_setting[property] ? tag_setting[property] : [];
|
||||
// 判断当前ID的数据是否存在,存在删除
|
||||
let index = tags.findIndex(item => item.key == id);
|
||||
if (index >= 0) {
|
||||
tags.splice(index, 1);
|
||||
}
|
||||
// 将修改后的数据保存
|
||||
tag_setting[property] = tags;
|
||||
// 写入文件
|
||||
await fspromises.writeFile(define.tag_setting, JSON.stringify(tag_setting));
|
||||
return {
|
||||
code: 1,
|
||||
message: "删除成功"
|
||||
}
|
||||
/**
|
||||
* 保存gpt指定的属性数据,判断value中的ID是不是存在,存在直接覆盖,不存在追加
|
||||
* @param {*} value
|
||||
* @param {*} property
|
||||
*/
|
||||
async saveTagPropertyData(value) {
|
||||
try {
|
||||
let property = value[1]
|
||||
value = JSON.parse(value[0])
|
||||
let tmp_key = uuidv4()
|
||||
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
// 特殊操作。为角色和场景的时候,需要copy图片
|
||||
if (property == 'character_tags' || property == 'scene_tags' || property == 'style_tags') {
|
||||
let show_image = value.show_image
|
||||
if (show_image && show_image != '') {
|
||||
let file_name = `c_s/${value.key ? value.key : tmp_key}.png`
|
||||
let new_image_path = path.join(define.image_path, file_name)
|
||||
await this.tools.copyFileOrDirectory(show_image, new_image_path)
|
||||
value.show_image = file_name
|
||||
value.children?.forEach((item) => {
|
||||
item.show_image = file_name
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// 获取自定义的GPT数据
|
||||
let tag_setting = JSON.parse(await fspromises.readFile(define.tag_setting, 'utf-8'))
|
||||
let tag = get(tag_setting, property, [])
|
||||
if (value.key) {
|
||||
// 判断当前ID的数据是否存在,存在覆盖,不存在追加
|
||||
let index = tag.findIndex((item) => item.key == value.key)
|
||||
value.value = value.key
|
||||
if (index < 0) {
|
||||
// 判断相同名字的数据是不是存在,存在报错
|
||||
if (tag.some((item) => item.label == value.label)) {
|
||||
throw new Error('已存在相同名称的数据,请修改名称后再保存')
|
||||
}
|
||||
tag.push(value)
|
||||
} else {
|
||||
tag[index] = value
|
||||
}
|
||||
} else {
|
||||
// 判断相同名字的数据是不是存在,存在报错
|
||||
if (tag.some((item) => item.label == value.label)) {
|
||||
throw new Error('已存在相同名称的数据,请修改名称后再保存')
|
||||
}
|
||||
value.key = tmp_key
|
||||
value.value = value.key
|
||||
tag.push(value)
|
||||
}
|
||||
tag_setting[property] = tag
|
||||
// 写入文件
|
||||
await fspromises.writeFile(define.tag_setting, JSON.stringify(tag_setting))
|
||||
return {
|
||||
code: 1,
|
||||
message: '保存成功'
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除自定义GPT指定属性中的指定ID的数据
|
||||
* @param {*} id
|
||||
* @param {*} property
|
||||
*/
|
||||
async deleteTagPropertyData(value) {
|
||||
try {
|
||||
let property = value[1]
|
||||
let id = value[0]
|
||||
// 获取自定义的GPT数据
|
||||
let tag_setting = JSON.parse(await fspromises.readFile(define.tag_setting, 'utf-8'))
|
||||
let tags = tag_setting[property] ? tag_setting[property] : []
|
||||
// 判断当前ID的数据是否存在,存在删除
|
||||
let index = tags.findIndex((item) => item.key == id)
|
||||
if (index >= 0) {
|
||||
tags.splice(index, 1)
|
||||
}
|
||||
// 将修改后的数据保存
|
||||
tag_setting[property] = tags
|
||||
// 写入文件
|
||||
await fspromises.writeFile(define.tag_setting, JSON.stringify(tag_setting))
|
||||
return {
|
||||
code: 1,
|
||||
message: '删除成功'
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ type configure = {
|
||||
proxy?: string
|
||||
rate?: string
|
||||
pitch?: string
|
||||
volume?: string
|
||||
volumn?: string
|
||||
}
|
||||
|
||||
export class EdgeTTS {
|
||||
@@ -28,7 +28,7 @@ export class EdgeTTS {
|
||||
private proxy: string | null | undefined
|
||||
private rate: string
|
||||
private pitch: string
|
||||
private volume: string
|
||||
private volumn: string
|
||||
|
||||
constructor({
|
||||
voice = 'zh-CN-XiaoyiNeural',
|
||||
@@ -38,7 +38,7 @@ export class EdgeTTS {
|
||||
proxy,
|
||||
rate = 'default',
|
||||
pitch = 'default',
|
||||
volume = 'default'
|
||||
volumn = 'default'
|
||||
}: configure = {}) {
|
||||
this.voice = voice
|
||||
this.lang = lang
|
||||
@@ -47,7 +47,7 @@ export class EdgeTTS {
|
||||
this.proxy = proxy
|
||||
this.rate = rate
|
||||
this.pitch = pitch
|
||||
this.volume = volume
|
||||
this.volumn = volumn
|
||||
}
|
||||
|
||||
async _connectWebSocket(): Promise<WebSocket> {
|
||||
@@ -138,7 +138,9 @@ export class EdgeTTS {
|
||||
end: Math.floor((element['Data']['Offset'] + element['Data']['Duration']) / 10000)
|
||||
})
|
||||
})
|
||||
} catch {}
|
||||
} catch {
|
||||
throw new Error('解析元数据失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -148,7 +150,7 @@ export class EdgeTTS {
|
||||
` +
|
||||
`<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="${this.lang}">
|
||||
<voice name="${this.voice}">
|
||||
<prosody rate="${this.rate}" pitch="${this.pitch}" volume="${this.volume}">
|
||||
<prosody rate="${this.rate}" pitch="${this.pitch}" volumn="${this.volumn}">
|
||||
${text}
|
||||
</prosody>
|
||||
</voice>
|
||||
|
||||
Reference in New Issue
Block a user