1. 添加软件高清倍率设置,实现自定义高清倍率(支持两倍、三倍和四倍,默认是两倍)
2. (聚合推文)新增导出草稿。可以依赖做好的草稿文件,只替换图片文件
3. (聚合推文)新增批量生成草稿
4. (聚合推文)修改小说批次任务进行详细界面操作为双击
This commit is contained in:
2024-10-23 22:59:29 +08:00
parent f4d042f699
commit 0c5988ed41
22 changed files with 1436 additions and 1225 deletions
+345 -310
View File
@@ -1,335 +1,370 @@
import path from "path";
import { define } from "../../define/define";
import { Tools } from "../tools";
import { DEFINE_STRING } from "../../define/define_string";
import { get, has } from "lodash";
const util = require('util');
const { spawn, exec } = require('child_process');
const execAsync = util.promisify(exec);
const fspromises = require("fs").promises;
import path from 'path'
import { define } from '../../define/define'
import { Tools } from '../tools'
import { DEFINE_STRING } from '../../define/define_string'
import { get, has } from 'lodash'
const util = require('util')
const { spawn, exec } = require('child_process')
const execAsync = util.promisify(exec)
const fspromises = require('fs').promises
export class PublicMethod {
constructor(global) {
this.global = global;
this.tools = new Tools();
constructor(global) {
this.global = global
this.tools = new Tools()
}
/**
* 修改config.json文件中的指定的属性
* @param {*} value 0: 要修改的数据 1: 要修改的属性 2: 是否需要解析
* @returns
*/
async SaveConfigJsonProperty(value) {
try {
let data = value[0]
let property = value[1]
let parse = value[2]
if (parse) {
data = JSON.parse(value[0])
}
let json_path = path.join(global.config.project_path, 'scripts/config.json')
// 判断文件是不是存在
let isExit = await this.tools.checkExists(json_path)
let json_data = {}
if (!isExit) {
const dirPath = path.dirname(json_path)
await fspromises.mkdir(dirPath, { recursive: true })
await fspromises.writeFile(json_path, '{}')
} else {
const o_data = await fspromises.readFile(json_path, 'utf8')
// 将读取的 JSON 字符串转换为 JavaScript 对象
let obj = JSON.parse(o_data)
json_data = obj
}
json_data[property] = data
await fspromises.writeFile(json_path, JSON.stringify(json_data))
return {
code: 1
}
} catch (error) {
throw error
}
}
/**
* 修改config.json文件中的指定的属性
* @param {*} value 0: 要修改的数据 1: 要修改的属性 2: 是否需要解析
* @returns
*/
async SaveConfigJsonProperty(value) {
/**
* 返回当前项目的config.json文件中的指定的属性信息,若是没有传入属性,则返回所有的信息
* @param {Array} value 0 要获取的属性 1 返回的默认值
* @param {Boolean} ckeck 是否需要校验属性不存在
* @returns
*/
async GetConfigJson(value, ckeck = true) {
try {
value = JSON.parse(value)
let srt_config_path = path.join(global.config.project_path, 'scripts/config.json')
let data = await this.tools.getJsonFilePropertyValue(
srt_config_path,
value[0],
value[1],
ckeck
)
return {
code: 1,
data: data
}
} catch (error) {
throw error
}
}
/**
* 修改生成图片的任务队列数据
* @param {传入的要修改的数据数组} value
*/
async ModifyImageTaskList(value) {
this.global.fileQueue.enqueue(
async () => {
try {
let data = value[0];
let property = value[1];
let parse = value[2];
if (parse) {
data = JSON.parse(value[0])
}
let json_path = path.join(global.config.project_path, "scripts/config.json");
// 判断文件是不是存在
let isExit = await this.tools.checkExists(json_path);
let json_data = {};
if (!isExit) {
const dirPath = path.dirname(json_path);
await fspromises.mkdir(dirPath, { recursive: true });
await fspromises.writeFile(json_path, '{}');
}
else {
const o_data = await fspromises.readFile(json_path, 'utf8');
// 将读取的 JSON 字符串转换为 JavaScript 对象
let obj = JSON.parse(o_data);
json_data = obj;
}
json_data[property] = data;
await fspromises.writeFile(json_path, JSON.stringify(json_data));
return {
code: 1
}
let task_list_path = path.join(this.global.config.project_path, 'scripts/task_list.json')
let isE = await this.tools.checkExists(task_list_path)
if (!isE) {
throw new Error('任务队列文件不存在。请先添加 批次任务')
}
let task_list_json = JSON.parse(await fspromises.readFile(task_list_path, 'utf-8'))
// 循环循环数据。修改
for (let i = 0; i < value.length; i++) {
const element = value[i]
let index = task_list_json.task_list.findIndex((item) => item.id == element.id)
task_list_json.task_list[index] = element
}
await fspromises.writeFile(task_list_path, JSON.stringify(task_list_json))
} catch (error) {
throw error;
throw error
}
}
/**
* 返回当前项目的config.json文件中的指定的属性信息,若是没有传入属性,则返回所有的信息
* @param {Array} value 0 要获取的属性 1 返回的默认值
* @param {Boolean} ckeck 是否需要校验属性不存在
* @returns
*/
async GetConfigJson(value, ckeck = true) {
try {
value = JSON.parse(value)
let srt_config_path = path.join(global.config.project_path, "scripts/config.json");
let data = await this.tools.getJsonFilePropertyValue(srt_config_path, value[0], value[1], ckeck);
return {
code: 1,
data: data
}
} catch (error) {
throw error;
},
'modifyFile',
'modifyFile',
'task_list'
)
this.global.fileQueue.setSubBatchCompletionCallback(
'modifyFile',
'task_list',
async (failedTasks) => {
// 报错
if (failedTasks.length > 0) {
let message = ''
failedTasks.forEach(({ taskId, error }) => {
message += `${taskId}-, \n 错误信息: ${error}` + '\n'
})
throw new Error(message)
// this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
// code: 0,
// message: message
// })
}
// else {
// this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
// code: 1,
// message: "修改成功"
// })
// }
return true
}
)
}
/**
* 高清指定的文件夹
* @param {要高清的文件夹} folder
*/
async ImproveFolder(folder) {
try {
let bakPath = path.join(this.global.config.project_path, 'tmp/bak')
let oldInput = path.join(this.global.config.project_path, 'tmp/' + folder)
let newInput = path.join(this.global.config.project_path, 'tmp/bak/' + folder)
// 创建文件夹
let existFolder = await this.tools.checkExists(bakPath)
if (!existFolder) {
await fspromises.mkdir(bakPath, { recursive: true })
}
let isExistNewFolder = await this.tools.checkExists(newInput)
if (isExistNewFolder) {
await fspromises.rm(newInput, { recursive: true, force: true })
}
// 备份文件
await fspromises.rename(oldInput, newInput)
//创建同名的文件,用作输出
await fspromises.mkdir(oldInput, { recursive: true })
// 开始高清
let command = `"${path.join(
define.package_path,
'Improve/rnv.exe'
)}" -i "${newInput}" -o "${oldInput}" -s ${this.global.config.hdScale ?? 2}`
let out = await execAsync(command, { maxBuffer: 1024 * 1024 * 10, encoding: 'utf-8' })
console.log(out)
await this.ModifyTaskStatus('out_folder', folder, 'video_improvied')
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.VIDEO_GENERATE_STATUS_REFRESH, {
out_folder: folder,
status: 'video_improvied'
})
} catch (error) {
await this.ModifyTaskStatus('out_folder', folder, 'video_improvie_error')
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.VIDEO_GENERATE_STATUS_REFRESH, {
out_folder: folder,
status: 'video_improvie_error'
})
throw error
}
}
/**
* 修改生成图片的任务队列数据
* @param {传入的要修改的数据数组} value
*/
async ModifyImageTaskList(value) {
this.global.fileQueue.enqueue(async () => {
try {
let task_list_path = path.join(this.global.config.project_path, "scripts/task_list.json");
let isE = await this.tools.checkExists(task_list_path);
if (!isE) {
throw new Error("任务队列文件不存在。请先添加 批次任务");
}
let task_list_json = JSON.parse(await fspromises.readFile(task_list_path, "utf-8"));
// 循环循环数据。修改
for (let i = 0; i < value.length; i++) {
const element = value[i];
let index = task_list_json.task_list.findIndex(item => item.id == element.id);
task_list_json.task_list[index] = element;
}
await fspromises.writeFile(task_list_path, JSON.stringify(task_list_json));
} catch (error) {
throw error;
}
}, "modifyFile", "modifyFile", "task_list")
this.global.fileQueue.setSubBatchCompletionCallback("modifyFile", "task_list", async (failedTasks) => {
// 报错
if (failedTasks.length > 0) {
let message = "";
failedTasks.forEach(({ taskId, error }) => {
message += `${taskId}-, \n 错误信息: ${error}` + '\n';
});
throw new Error(message);
// this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
// code: 0,
// message: message
// })
}
// else {
// this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
// code: 1,
// message: "修改成功"
// })
// }
return true;
})
}
/**
* 生成SD相对的JSON文件。删除反推的txt文件
*/
async AddWebuiJson() {
try {
// 读取所有txt文件
let txtfile = await this.tools.getFilesWithExtensions(
path.join(this.global.config.project_path, 'tmp/input_crop'),
'.txt'
)
let image = await this.tools.getFilesWithExtensions(
path.join(this.global.config.project_path, 'tmp/input_crop'),
'.png'
)
let promptJson = await this.tools.getFilesWithExtensions(
path.join(this.global.config.project_path, 'tmp/input_crop'),
'.json'
)
/**
* 高清指定的文件夹
* @param {要高清的文件夹} folder
*/
async ImproveFolder(folder) {
try {
let bakPath = path.join(this.global.config.project_path, "tmp/bak");
let oldInput = path.join(this.global.config.project_path, "tmp/" + folder);
let newInput = path.join(this.global.config.project_path, "tmp/bak/" + folder)
// 创建文件夹
let existFolder = await this.tools.checkExists(bakPath);
if (!existFolder) {
await fspromises.mkdir(bakPath, { recursive: true });
}
let isExistNewFolder = await this.tools.checkExists(newInput);
if (isExistNewFolder) {
await fspromises.rm(newInput, { recursive: true, force: true });
}
// 备份文件
await fspromises.rename(oldInput, newInput);
//创建同名的文件,用作输出
await fspromises.mkdir(oldInput, { recursive: true });
// 开始高清
let command = `"${path.join(define.package_path, "Improve/rnv.exe")}" -i "${newInput}" -o "${oldInput}"`;
let out = await execAsync(command, { maxBuffer: 1024 * 1024 * 10, encoding: 'utf-8' });
console.log(out);
await this.ModifyTaskStatus('out_folder', folder, "video_improvied");
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.VIDEO_GENERATE_STATUS_REFRESH, {
out_folder: folder,
status: "video_improvied"
})
} catch (error) {
await this.ModifyTaskStatus('out_folder', folder, "video_improvie_error");
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.VIDEO_GENERATE_STATUS_REFRESH, {
out_folder: folder,
status: "video_improvie_error"
})
throw error;
// json 已经存在,不做后续处理
if (image.length == promptJson.length) {
return {
code: 1
}
}
}
/**
* 生成SD相对的JSON文件。删除反推的txt文件
*/
async AddWebuiJson() {
try {
// 读取所有txt文件
let txtfile = await this.tools.getFilesWithExtensions(path.join(this.global.config.project_path, 'tmp/input_crop'), '.txt');
let image = await this.tools.getFilesWithExtensions(path.join(this.global.config.project_path, 'tmp/input_crop'), '.png');
let promptJson = await this.tools.getFilesWithExtensions(path.join(this.global.config.project_path, 'tmp/input_crop'), '.json');
if (txtfile.length != image.length) {
throw new Error('关键词文件和图片数量对不上,请检查!!')
}
let sd_config = JSON.parse(await fspromises.readFile(define.sd_setting, 'utf-8'))
// json 已经存在,不做后续处理
if (image.length == promptJson.length) {
return {
code: 1,
}
}
if (txtfile.length != image.length) {
throw new Error("关键词文件和图片数量对不上,请检查!!")
}
let sd_config = JSON.parse(await fspromises.readFile(define.sd_setting, 'utf-8'));
for (let i = 0; i < image.length; i++) {
const element = image[i];
let txtpath = element.split('.png')[0] + '.txt';
let prompt = await fspromises.readFile(txtpath, 'utf-8');
// console.log(txtpath)
let obj = {}
obj.model = sd_config.setting.type;
obj.api = sd_config.setting.webui_api_url + 'sdapi/v1/img2img';
obj.webui_config = {
sampler_name: sd_config.webui.sampler_name,
prompt: prompt + ',' + sd_config.webui.prompt,
negative_prompt: sd_config.webui.negative_prompt,
batch_size: 1,
steps: sd_config.webui.steps,
cfg_scale: sd_config.webui.cfg_scale,
denoising_strength: sd_config.webui.denoising_strength,
width: sd_config.webui.width,
height: sd_config.webui.height,
seed: sd_config.setting.seed,
init_images: element,
}
obj.adetailer = sd_config.webui.adetailer;
// 写入
await fspromises.writeFile(element + '.json', JSON.stringify(obj));
// 删除对应的txt文件
await fspromises.unlink(txtpath);
}
return {
code: 1,
}
} catch (error) {
throw error;
for (let i = 0; i < image.length; i++) {
const element = image[i]
let txtpath = element.split('.png')[0] + '.txt'
let prompt = await fspromises.readFile(txtpath, 'utf-8')
// console.log(txtpath)
let obj = {}
obj.model = sd_config.setting.type
obj.api = sd_config.setting.webui_api_url + 'sdapi/v1/img2img'
obj.webui_config = {
sampler_name: sd_config.webui.sampler_name,
prompt: prompt + ',' + sd_config.webui.prompt,
negative_prompt: sd_config.webui.negative_prompt,
batch_size: 1,
steps: sd_config.webui.steps,
cfg_scale: sd_config.webui.cfg_scale,
denoising_strength: sd_config.webui.denoising_strength,
width: sd_config.webui.width,
height: sd_config.webui.height,
seed: sd_config.setting.seed,
init_images: element
}
}
obj.adetailer = sd_config.webui.adetailer
/**
* 获取当前项目的生图任务列表
*/
async GetImageTask() {
try {
let json_path = path.join(this.global.config.project_path, "scripts/task_list.json");
let isExit = await this.tools.checkExists(json_path);
if (!isExit) {
return {
code: 1,
data: null
}
}
let json_data = JSON.parse(await fspromises.readFile(json_path));
return {
code: 1,
data: json_data
}
} catch (error) {
return {
code: 0,
message: error
}
// 写入
await fspromises.writeFile(element + '.json', JSON.stringify(obj))
// 删除对应的txt文件
await fspromises.unlink(txtpath)
}
return {
code: 1
}
} catch (error) {
throw error
}
}
/**
* 获取当前项目的生图任务列表
*/
async GetImageTask() {
try {
let json_path = path.join(this.global.config.project_path, 'scripts/task_list.json')
let isExit = await this.tools.checkExists(json_path)
if (!isExit) {
return {
code: 1,
data: null
}
}
let json_data = JSON.parse(await fspromises.readFile(json_path))
return {
code: 1,
data: json_data
}
} catch (error) {
return {
code: 0,
message: error
}
}
}
/**
* 修改任务的状态
* @param {查找的类型 id out_folder} type
* @param {查找的类型} id
* @param {新的状态} newStatus
*/
async ModifyTaskStatus(type, id, newStatus) {
this.global.fileQueue.enqueue(async () => {
try {
// 将修改数据写入到一个并发为 1 的队列中
let tmp_task = await fspromises.readFile(path.join(this.global.config.project_path, 'scripts/task_list.json'), 'utf-8');
console.log(tmp_task)
let task = JSON.parse(tmp_task);
if (type == "id") {
let index = task.task_list.findIndex(item => item.id == id);
if (index < 0) {
throw new Error("传入的数据未找到");
} else {
task.task_list[index].status = newStatus;
}
} else if (type == "out_folder") {
let index = task.task_list.findIndex(item => item.out_folder == id);
if (index < 0) {
throw new Error("传入的数据未找到");
} else {
task.task_list[index].status = newStatus;
}
} else {
throw new Error("输入类型错误")
}
await fspromises.writeFile(path.join(this.global.config.project_path, 'scripts/task_list.json'), JSON.stringify(task));
} catch (error) {
throw error;
}
}, "modifyFile", "modifyFile", "task_list")
this.global.fileQueue.setSubBatchCompletionCallback("modifyFile", "task_list", async (failedTasks) => {
// 报错
if (failedTasks.length > 0) {
let message = "";
failedTasks.forEach(({ taskId, error }) => {
message += `${taskId}-, \n 错误信息: ${error}` + '\n';
});
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
code: 0,
message: message
})
}
})
}
/**
* 获取指定文件夹下面特定条件的文件夹
* @param {指定的文件夹目录} parentFolder
* @param {查询条件 start end include} condition
* @param {查询的值} value
* @returns
*/
async getSubFolderList(parentFolder, condition, value) {
/**
* 修改任务的状态
* @param {查找的类型 id out_folder} type
* @param {查找的类型} id
* @param {新的状态} newStatus
*/
async ModifyTaskStatus(type, id, newStatus) {
this.global.fileQueue.enqueue(
async () => {
try {
// console.log(value);
let folders = await fspromises.readdir(parentFolder, { withFileTypes: true });
folders = folders.filter(item => item.isDirectory())
.map(item => item.name)
if (condition == "start") {
folders = folders.filter(item => item.startsWith(value));
} else if (condition == "end") {
folders = folders.filter(item => item.endsWith(value));
} else if (condition == "include") {
//包含过滤
folders = folders.filter(item => item.includes(value));
// 将修改数据写入到一个并发为 1 的队列中
let tmp_task = await fspromises.readFile(
path.join(this.global.config.project_path, 'scripts/task_list.json'),
'utf-8'
)
console.log(tmp_task)
let task = JSON.parse(tmp_task)
if (type == 'id') {
let index = task.task_list.findIndex((item) => item.id == id)
if (index < 0) {
throw new Error('传入的数据未找到')
} else {
throw new Error("条件参数错误");
task.task_list[index].status = newStatus
}
return folders;
} else if (type == 'out_folder') {
let index = task.task_list.findIndex((item) => item.out_folder == id)
if (index < 0) {
throw new Error('传入的数据未找到')
} else {
task.task_list[index].status = newStatus
}
} else {
throw new Error('输入类型错误')
}
await fspromises.writeFile(
path.join(this.global.config.project_path, 'scripts/task_list.json'),
JSON.stringify(task)
)
} catch (error) {
throw error;
throw error
}
},
'modifyFile',
'modifyFile',
'task_list'
)
this.global.fileQueue.setSubBatchCompletionCallback(
'modifyFile',
'task_list',
async (failedTasks) => {
// 报错
if (failedTasks.length > 0) {
let message = ''
failedTasks.forEach(({ taskId, error }) => {
message += `${taskId}-, \n 错误信息: ${error}` + '\n'
})
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
code: 0,
message: message
})
}
}
)
}
/**
* 获取指定文件夹下面特定条件的文件夹
* @param {指定的文件夹目录} parentFolder
* @param {查询条件 start end include} condition
* @param {查询的值} value
* @returns
*/
async getSubFolderList(parentFolder, condition, value) {
try {
// console.log(value);
let folders = await fspromises.readdir(parentFolder, { withFileTypes: true })
folders = folders.filter((item) => item.isDirectory()).map((item) => item.name)
if (condition == 'start') {
folders = folders.filter((item) => item.startsWith(value))
} else if (condition == 'end') {
folders = folders.filter((item) => item.endsWith(value))
} else if (condition == 'include') {
//包含过滤
folders = folders.filter((item) => item.includes(value))
} else {
throw new Error('条件参数错误')
}
return folders
} catch (error) {
throw error
}
}
}
}