LaiTool V3.1.1.
This commit is contained in:
@@ -37,3 +37,33 @@ export async function RetryWithBackoff<T>(fn: () => Promise<T>, retries: number
|
||||
}
|
||||
throw new Error('所有重试失败'); // 理论上不会到达这里
|
||||
}
|
||||
|
||||
/**
|
||||
* 并发执行任务(控制同时执行的任务数)
|
||||
* @param tasks 总的任务列表
|
||||
* @param concurrentCount 同时执行的数量
|
||||
* @returns
|
||||
*/
|
||||
export async function ExecuteConcurrently(tasks: Array<() => Promise<any>>, concurrentCount: number): Promise<any[]> {
|
||||
let activeTasks: Array<Promise<any>> = [];
|
||||
let results: Array<Promise<any>> = [];
|
||||
|
||||
while (tasks.length > 0) {
|
||||
if (activeTasks.length < concurrentCount) {
|
||||
let task = tasks.shift();
|
||||
let promise = task().then(result => {
|
||||
activeTasks = activeTasks.filter(t => t !== promise);
|
||||
return result;
|
||||
}).catch(error => {
|
||||
// 抛出任务,停止所有的任务
|
||||
tasks.length = 0;
|
||||
throw error
|
||||
});
|
||||
activeTasks.push(promise);
|
||||
results.push(promise);
|
||||
} else {
|
||||
await Promise.race(activeTasks);
|
||||
}
|
||||
}
|
||||
return Promise.all(results);
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
import fs from 'fs'
|
||||
import { isEmpty } from 'lodash'
|
||||
import path from 'path'
|
||||
import util from 'util'
|
||||
import { exec } from 'child_process'
|
||||
const execAsync = util.promisify(exec)
|
||||
const fspromises = fs.promises
|
||||
|
||||
/**
|
||||
@@ -253,3 +256,21 @@ export async function GetSubdirectories(folderPath: string): Promise<string[]> {
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除目标图片,然后将原图片的exif信息删除,然后将原图片复制到目标图片地址
|
||||
* @param {*} exiftoolPath exiftool的地址
|
||||
* @param {*} source 原图片地址
|
||||
* @param {*} target 目标图片地址
|
||||
*/
|
||||
export async function DeleteFileExifData(exiftoolPath: string, source: string, target: string) {
|
||||
try {
|
||||
if (await CheckFileOrDirExist(target)) {
|
||||
await fspromises.unlink(target)
|
||||
}
|
||||
let script = `"${exiftoolPath}" -all= -overwrite_original "${source}" -o "${target}"`
|
||||
const output = await execAsync(script, { maxBuffer: 1024 * 1024 * 10, encoding: 'utf-8' })
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from 'path'
|
||||
import sharp from 'sharp'
|
||||
import { CheckFileOrDirExist } from './file'
|
||||
import { CheckFileOrDirExist, CheckFolderExistsOrCreate } from './file'
|
||||
import fs from 'fs'
|
||||
import https from 'https'
|
||||
|
||||
@@ -237,7 +237,7 @@ export async function Base64ToFile(base64: string, outFilePath: string): Promise
|
||||
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 CheckFolderExistsOrCreate(out_folder)
|
||||
await fs.promises.writeFile(outFilePath, dataBuffer)
|
||||
// await this.tools.writeArrayToFile(dataBuffer, out_file);
|
||||
} catch (error) {
|
||||
|
||||
@@ -15,6 +15,7 @@ export class BookBackTaskList extends Realm.Object<BookBackTaskList> {
|
||||
updateTime: Date
|
||||
startTime: number
|
||||
endTime: number
|
||||
messageName?: string
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'BookBackTaskList',
|
||||
@@ -31,7 +32,8 @@ export class BookBackTaskList extends Realm.Object<BookBackTaskList> {
|
||||
createTime: 'date',
|
||||
updateTime: 'date',
|
||||
startTime: 'int',
|
||||
endTime: 'int'
|
||||
endTime: 'int',
|
||||
messageName: 'string?'
|
||||
},
|
||||
primaryKey: 'id'
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ export class BookTaskDetailModel extends Realm.Object<BookTaskDetailModel> {
|
||||
timeLimit: string | null // 事件实现(0 -- 3000)
|
||||
subValue: string | null // 包含的字幕数据
|
||||
characterTags: string[] | null // 角色标签
|
||||
sceneTags: string[] | null // 场景标签
|
||||
gptPrompt: string | null // GPT提示词
|
||||
mjMessage: MJMessage | null // MJ消息
|
||||
outImagePath: string | null // 输出图片地址
|
||||
@@ -174,6 +175,7 @@ export class BookTaskDetailModel extends Realm.Object<BookTaskDetailModel> {
|
||||
subValue: 'string?',
|
||||
reversePrompt: { type: 'list', objectType: 'ReversePrompt' },
|
||||
characterTags: { type: 'list', objectType: 'string' },
|
||||
sceneTags: 'string[]',
|
||||
gptPrompt: 'string?',
|
||||
mjMessage: 'MJMessage?',
|
||||
outImagePath: 'string?',
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import Realm, { ObjectSchema } from 'realm'
|
||||
|
||||
export class PresetModel extends Realm.Object<PresetModel> {
|
||||
id: string
|
||||
label: string
|
||||
type: string
|
||||
showImage?: string
|
||||
prompt: string
|
||||
chinesePrompt?: string
|
||||
imageUrl?: string
|
||||
srefSw?: number
|
||||
crefCw?: number
|
||||
lora?: string
|
||||
loraWeight?: number
|
||||
isShow: boolean
|
||||
children?: string
|
||||
static schema: ObjectSchema = {
|
||||
name: 'PresetModel',
|
||||
properties: {
|
||||
id: 'string',
|
||||
label: 'string',
|
||||
type: 'string',
|
||||
showImage: 'string?',
|
||||
imageUrl: 'string?',
|
||||
prompt: 'string',
|
||||
chinesePrompt: 'string?',
|
||||
srefSw: 'int?',
|
||||
crefCw: 'int?',
|
||||
lora: 'string?',
|
||||
loraWeight: 'int?',
|
||||
isShow: 'bool',
|
||||
children: 'string?'
|
||||
},
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,8 @@ export class BookBackTaskListService extends BaseRealmService {
|
||||
taskType: BookBackTaskType,
|
||||
executeType = TaskExecuteType.AUTO,
|
||||
bookTaskId = null,
|
||||
bookTaskDetailId = null
|
||||
bookTaskDetailId = null,
|
||||
responseMessageName: string = null
|
||||
): GeneralResponse.SuccessItem | GeneralResponse.ErrorItem {
|
||||
try {
|
||||
// 通过bookid获取book信息
|
||||
@@ -181,6 +182,7 @@ export class BookBackTaskListService extends BaseRealmService {
|
||||
status: BookBackTaskStatus.WAIT,
|
||||
createTime: new Date(),
|
||||
updateTime: new Date(),
|
||||
messageName: responseMessageName,
|
||||
startTime: 0,
|
||||
endTime: 0
|
||||
} as TaskModal.Task
|
||||
|
||||
@@ -162,6 +162,20 @@ const migration = (oldRealm: Realm, newRealm: Realm) => {
|
||||
newBookTask[i].watermarkPosition = '[]'
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 23) {
|
||||
const oldBookTask = oldRealm.objects('BookTaskDetail')
|
||||
const newBookTask = newRealm.objects('BookTaskDetail')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].subImagePath = '[]'
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 24) {
|
||||
const oldBookTask = oldRealm.objects('BookBackTaskList')
|
||||
const newBookTask = newRealm.objects('BookBackTaskList')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].messageName = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class BaseRealmService extends BaseService {
|
||||
@@ -203,7 +217,7 @@ export class BaseRealmService extends BaseService {
|
||||
BookTaskDetailModel
|
||||
],
|
||||
path: this.dbpath,
|
||||
schemaVersion: 22,
|
||||
schemaVersion: 24,
|
||||
migration: migration
|
||||
}
|
||||
this.realm = await Realm.open(config)
|
||||
|
||||
@@ -195,6 +195,9 @@ export class BookService extends BaseRealmService {
|
||||
await CheckFolderExistsOrCreate(bookTaskImageFolder) // 创建默认的任务文件夹
|
||||
// 修改数据
|
||||
book.oldVideoPath = path.relative(define.project_path, oldVideoPath)
|
||||
if (book.type == BookType.ORIGINAL) {
|
||||
book.oldVideoPath = null
|
||||
}
|
||||
|
||||
let imageCategory = BookImageCategory.MJ
|
||||
if (book.type == BookType.SD_REVERSE) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Realm from 'realm'
|
||||
import path from 'path'
|
||||
import { define } from '../../../define.js'
|
||||
import { define } from '../../../define'
|
||||
import { BookTaskModel } from '../../model/Book/bookTask.js'
|
||||
import { successMessage } from '../../../../main/Public/generalTools'
|
||||
import { BaseRealmService } from './bookBasic'
|
||||
@@ -72,6 +72,7 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
return JoinPath(define.project_path, subImage)
|
||||
}),
|
||||
characterTags: item.characterTags ? item.characterTags.map((tag) => tag) : null,
|
||||
sceneTags: item.sceneTags ? item.sceneTags.map((tag) => tag) : null,
|
||||
subValue: isEmpty(item.subValue) ? null : JSON.parse(item.subValue),
|
||||
reversePrompt: item.reversePrompt.map((reversePrompt) => {
|
||||
return {
|
||||
@@ -116,7 +117,7 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
* 添加一条小说任务对应的详细数据
|
||||
* @param BookTaskDetail
|
||||
*/
|
||||
public AddBookTaskDetail(bookTaskDetail) {
|
||||
public AddBookTaskDetail(bookTaskDetail: Book.SelectBookTaskDetail) {
|
||||
try {
|
||||
// 判断是不是又小说ID
|
||||
if (isEmpty(bookTaskDetail.bookId) || isEmpty(bookTaskDetail.bookTaskId)) {
|
||||
@@ -191,7 +192,6 @@ export class BookTaskDetailService extends BaseRealmService {
|
||||
*/
|
||||
UpdateBookTaskDetailMjMessage(bookTaskDetailId: string, mjMessage: Book.MJMessage): void {
|
||||
try {
|
||||
console.log('UpdateBookTaskDetailMjMessage', bookTaskDetailId, mjMessage)
|
||||
this.transaction(() => {
|
||||
let mjMessageRes = this.realm.objectForPrimaryKey('MJMessage', bookTaskDetailId)
|
||||
let bookTaskDetail = this.realm.objectForPrimaryKey('BookTaskDetail', bookTaskDetailId)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Realm from 'realm'
|
||||
import path from 'path'
|
||||
import { define } from '../../../define.js'
|
||||
import { define } from '../../../define'
|
||||
import { BookTaskModel } from '../../model/Book/bookTask.js'
|
||||
import { BookBackTaskStatus, BookImageCategory, BookTaskStatus } from '../../../enum/bookEnum.js'
|
||||
import { successMessage } from '../../../../main/Public/generalTools'
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import Realm, { UpdateMode } from 'realm'
|
||||
import path from 'path'
|
||||
import { errorMessage, successMessage } from '../../../../main/Public/generalTools'
|
||||
import { BaseSoftWareService } from './softwareBasic.js'
|
||||
import { isEmpty } from 'lodash'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
export class ImageStyleService extends BaseSoftWareService {
|
||||
static instance: ImageStyleService | null = null
|
||||
realm: Realm
|
||||
private constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前实例对象,为空则创建一个新的
|
||||
* @returns
|
||||
*/
|
||||
public static async getInstance() {
|
||||
if (ImageStyleService.instance === null) {
|
||||
ImageStyleService.instance = new ImageStyleService()
|
||||
await super.getInstance()
|
||||
}
|
||||
return ImageStyleService.instance
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import Realm, { UpdateMode } from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService'
|
||||
import { define } from '../../../define.js'
|
||||
import { define } from '../../../define'
|
||||
import { SoftwareModel } from '../../model/SoftWare/software'
|
||||
import { ComponentSize, SoftwareThemeType } from '../../../enum/softwareEnum.js'
|
||||
import { errorMessage, successMessage } from '../../../../main/Public/generalTools'
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
RemoteMJModel
|
||||
} from '../../model/SoftWare/mjSetting'
|
||||
import { MJImageType, MJRobotType } from '../../../enum/mjEnum'
|
||||
import { PresetModel } from '../../model/SoftWare/preset'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
let dbPath = path.resolve(define.db_path, 'software.realm')
|
||||
@@ -155,6 +156,9 @@ const migration = (oldRealm: Realm, newRealm: Realm) => {
|
||||
}
|
||||
})
|
||||
}
|
||||
if (oldRealm.schemaVersion < 22) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export class BaseSoftWareService extends BaseService {
|
||||
@@ -190,10 +194,11 @@ export class BaseSoftWareService extends BaseService {
|
||||
BrowserMJModel,
|
||||
RemoteMJModel,
|
||||
APIMjModel,
|
||||
MjSettingModel
|
||||
MjSettingModel,
|
||||
PresetModel
|
||||
],
|
||||
path: dbPath,
|
||||
schemaVersion: 21, // 当前版本号
|
||||
schemaVersion: 23, // 当前版本号
|
||||
migration: migration
|
||||
}
|
||||
// 判断当前全局是不是又当前这个
|
||||
|
||||
@@ -25,15 +25,25 @@ export class SoftwareService extends BaseSoftWareService {
|
||||
}
|
||||
|
||||
// 修改数据库中行中的某个属性数据
|
||||
UpdateSoftware(software: SoftwareSettingModel.SoftwareSetting): GeneralResponse.SuccessItem {
|
||||
try {
|
||||
UpdateSoftware(software: SoftwareSettingModel.SoftwareSetting) {
|
||||
if (software.id) {
|
||||
this.realm.write(() => {
|
||||
this.realm.create('Software', software, UpdateMode.Modified)
|
||||
})
|
||||
// 返回成功信息
|
||||
return successMessage(null, '修改软件配置信息成功', 'SoftwareService_UpdateSoftware')
|
||||
} catch (error) {
|
||||
throw error
|
||||
} else {
|
||||
// 没有ID,就修改指定属性
|
||||
let softwareData = this.realm.objects('Software')
|
||||
if (softwareData.length <= 0) {
|
||||
throw new Error('数据库中没有软件配置信息')
|
||||
}
|
||||
let _software = softwareData[0]
|
||||
this.realm.write(() => {
|
||||
for (let key in software) {
|
||||
if (software[key] != undefined) {
|
||||
_software[key] = software[key]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export const DEFINE_STRING = {
|
||||
SHOW_GLOBAL_MESSAGE: "SHOW_GLOBAL_MESSAGE",
|
||||
SHOW_GLOBAL_MAIN_NOTIFICATION: 'SHOW_GLOBAL_MAIN_NOTIFICATION',
|
||||
OPEN_DEV_TOOLS_PASSWORD: 'OPEN_DEV_TOOLS_PASSWORD',
|
||||
OPEN_DEV_TOOLS: 'OPEN_DEV_TOOLS',
|
||||
@@ -7,7 +8,7 @@ export const DEFINE_STRING = {
|
||||
GET_DEFINE_CONFIG_JSON_BY_PROPERTY: 'GET_DEFINE_CONFIG_JSON_BY_PROPERTY',
|
||||
GET_IMAGE_GENERATE_CATEGORY: 'GET_IMAGE_GENERATE_CATEGORY',
|
||||
SHOW_MAIN_NOTIFICATION: 'SHOW_MAIN_NOTIFICATION',
|
||||
SHOW_GLOABAL_MESSAGE: 'SHOW_GLOABAL_MESSAGE',
|
||||
SHOW_MAIN_MESSAGE: "SHOW_MAIN_MESSAGE",
|
||||
CHECK_MACHINE_ID: 'CHECK_MACHINE_ID',
|
||||
GET_CUSTOMIZE_GPT_PROMPT: 'GET_CUSTOMIZE_GPT_PROMPT',
|
||||
GENERATE_GPT_EXAMPLE_OUT: 'GENERATE_GPT_EXAMPLE_OUT',
|
||||
@@ -149,11 +150,19 @@ export const DEFINE_STRING = {
|
||||
TRANSLATE_NOW_RETURN: 'TRANSLATE_NOW_RETURN',
|
||||
GET_TRANSLATE_SETTING: 'GET_TRANSLATE_SETTING',
|
||||
RESET_TRANSLATE_SETTING: 'RESET_TRANSLATE_SETTING',
|
||||
SAVE_TRANSLATE_SETTING: 'SAVE_TRANSLATE_SETTING'
|
||||
SAVE_TRANSLATE_SETTING: 'SAVE_TRANSLATE_SETTING',
|
||||
/**
|
||||
* GPT 反推提示词翻译返回数据
|
||||
*/
|
||||
GPT_PROMPT_TRANSLATE_RETRUN: "GPT_PROMPT_TRANSLATE_RETRUN"
|
||||
},
|
||||
SD: {
|
||||
LOAD_SD_SERVICE_DATA: 'LOAD_SD_SERVICE_DATA',
|
||||
TXT2IMG: 'TXT2IMG',
|
||||
|
||||
//#region SD生成图片相关
|
||||
|
||||
//#endregion
|
||||
},
|
||||
MJ: {
|
||||
SAVE_WORD_SRT: 'SAVE_WORD_SRT',
|
||||
@@ -206,7 +215,6 @@ export const DEFINE_STRING = {
|
||||
},
|
||||
BOOK: {
|
||||
MAIN_DATA_RETURN: 'MAIN_DATA_RETURN', // 监听任务返回
|
||||
|
||||
REPLACE_VIDEO_CURRENT_FRAME: 'REPLACE_VIDEO_CURRENT_FRAME',
|
||||
GET_BOOK_TYPE: 'GET_BOOK_TYPE',
|
||||
ADD_OR_MODIFY_BOOK: 'ADD_OR_MODIFY_BOOK',
|
||||
@@ -243,6 +251,41 @@ export const DEFINE_STRING = {
|
||||
REMOVE_GENERATE_IMAGE: 'REMOVE_GENERATE_IMAGE',
|
||||
ADD_NEW_BOOK_TASK: "ADD_NEW_BOOK_TASK",
|
||||
REPLACE_BOOK_DATA: "REPLACE_BOOK_DATA",
|
||||
SAVE_COPYWRITING: 'SAVE_COPYWRITING',
|
||||
|
||||
//#region 原创推理提示词
|
||||
ORIGINAL_GPT_PROMPT: "ORIGINAL_GPT_PROMPT",
|
||||
ORIGINAL_GPT_PROMPT_RETURN: "ORIGINAL_GPT_PROMPT_RETURN",
|
||||
//#endregion
|
||||
|
||||
//#region 生图返回相关
|
||||
|
||||
/**
|
||||
* MJ生图返回信息
|
||||
*/
|
||||
MJ_IMAGE_GENERATE_RETURN: 'MJ_IMAGE_GENERATE_RETURN',
|
||||
|
||||
/**
|
||||
* SD生图返回信息
|
||||
*/
|
||||
SD_IMAGE_GENERATE_RETURN: 'SD_IMAGE_GENERATE_RETURN',
|
||||
|
||||
/**
|
||||
* D3 出图返回信息
|
||||
*/
|
||||
D3_IMAGE_GENERATE_RETURN: 'D3_IMAGE_GENERATE_RETURN',
|
||||
|
||||
/**
|
||||
* flux forge 生图返回信息
|
||||
*/
|
||||
FLUX_FORGE_IMAGE_GENERATE_RETURN: "FLUX_FORGE_IMAGE_GENERATE_RETURN",
|
||||
|
||||
/**
|
||||
* flux api 生图返回信息
|
||||
*/
|
||||
FLUX_API_IMAGE_GENERATE_RETURN: "FLUX_API_IMAGE_GENERATE_RETURN",
|
||||
|
||||
//#endregion
|
||||
|
||||
COMPUTE_STORYBOARD: 'COMPUTE_STORYBOARD',
|
||||
|
||||
@@ -290,6 +333,19 @@ export const DEFINE_STRING = {
|
||||
GET_PROMPT_SORT_DATA: 'GET_PROMPT_SORT_DATA',
|
||||
OPEN_PROMPT_FILE_TXT: 'OPEN_PROMPT_FILE_TXT'
|
||||
},
|
||||
/**
|
||||
* IPC事件传递,预设相关
|
||||
*/
|
||||
PRESET: {
|
||||
/**
|
||||
* 获取任务的预设(只获取 label 和 id)
|
||||
*/
|
||||
GET_CHARACTER_PRESET: 'GET_CHARACTER_PRESET',
|
||||
/**
|
||||
* 获取场景的预设(只获取 label 和 id)
|
||||
*/
|
||||
GET_SCENE_PRESET: "GET_SCENE_PRESET"
|
||||
},
|
||||
TTS: {
|
||||
GET_TTS_CONFIG: 'GET_TTS_CONFIG',
|
||||
GENERATE_AUDIO: 'GENERATE_AUDIO',
|
||||
@@ -309,6 +365,21 @@ export const DEFINE_STRING = {
|
||||
DB: {
|
||||
UPDATE_BOOK_TASK_DATA: "UPDATE_BOOK_TASK_DATA",
|
||||
UPDATE_BOOK_TASK_DETAIL_DATA: "UPDATE_BOOK_TASK_DETAIL_DATA",
|
||||
UPDATE_BOOK_DATA: "UPDATE_BOOK_DATA"
|
||||
UPDATE_BOOK_DATA: "UPDATE_BOOK_DATA",
|
||||
UPDATE_SOFTWARE_SETTING: "UPDATE_SOFTWARE_SETTING"
|
||||
},
|
||||
/**
|
||||
* 后台任务相关
|
||||
*/
|
||||
TASK: {
|
||||
/**
|
||||
* 添加单个后台任务
|
||||
*/
|
||||
ADD_BOOK_BACK_TASK: "ADD_BOOK_BACK_TASK",
|
||||
|
||||
/**
|
||||
* 添加多个后台任务
|
||||
*/
|
||||
ADD_MULTI_BOOK_BACK_TASK: 'ADD_MULTI_BOOK_BACK_TASK'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
export enum BookType {
|
||||
// 原创
|
||||
ORIGINAL = 'original',
|
||||
// 区分老版本的原创
|
||||
NEW_ORIGINAL = 'new_original',
|
||||
// 反推
|
||||
SD_REVERSE = 'sd_reverse',
|
||||
// MJ 反推
|
||||
@@ -14,7 +16,11 @@ export enum BookImageCategory {
|
||||
// SD
|
||||
SD = 'sd',
|
||||
// D3
|
||||
D3 = 'd3'
|
||||
D3 = 'd3',
|
||||
// FLUX API
|
||||
FLUX_API = 'flux-api',
|
||||
// FLUX FORGE
|
||||
FLUX_FORGE = 'flux-forge'
|
||||
}
|
||||
|
||||
export enum AddBookTaskCopyData {
|
||||
@@ -67,6 +73,10 @@ export enum BookBackTaskType {
|
||||
MJ_IMAGE = 'mj_image',
|
||||
// SD 生成图片
|
||||
SD_IMAGE = 'sd_image',
|
||||
// flux forge 生成图片
|
||||
FLUX_FORGE_IMAGE = 'flux_forge_image',
|
||||
// flux api 生成图片
|
||||
FLUX_API_IMAGE = 'flux_api_image',
|
||||
// D3 生成图片
|
||||
D3_IMAGE = 'd3_image',
|
||||
// 高清
|
||||
@@ -256,3 +266,13 @@ export enum BookRepalceDataType {
|
||||
// 提示词
|
||||
PROMPT = 'prompt',
|
||||
}
|
||||
|
||||
/**
|
||||
* 小说选择标签的方式类型,可以是下拉和标签
|
||||
*/
|
||||
export enum BookTagSelectType {
|
||||
// 下拉
|
||||
DROP = 'drop',
|
||||
// 标签
|
||||
TAG = 'tag'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
/**
|
||||
* Flux 调用API时候的 生图模型
|
||||
*/
|
||||
export enum FLxuAPIImageType {
|
||||
FLUX = "flux",
|
||||
FLUX_PRO = "flux-pro",
|
||||
FLUX_DEV = "flux-dev",
|
||||
FLUX_SCHNELL = "flux-schnell",
|
||||
FLUX_PRO_MAX = "flux-pro-max"
|
||||
}
|
||||
|
||||
|
||||
export enum PresetType {
|
||||
// 角色
|
||||
CHARACTER = 'character',
|
||||
|
||||
// 本地风格
|
||||
LOCAL_STYLE = 'localStyle',
|
||||
|
||||
// 自定义风格
|
||||
CUSTOM_STYLE = 'customStyle',
|
||||
|
||||
// laitool预设风格
|
||||
LAITOOL_STYLE = 'laitoolStyle',
|
||||
}
|
||||
@@ -9,7 +9,16 @@ export enum MJImageType {
|
||||
BROWSER_MJ = 'browser_mj',
|
||||
|
||||
// API模式
|
||||
API_MJ = 'api_mj'
|
||||
API_MJ = 'api_mj',
|
||||
|
||||
// 本地 SD
|
||||
LOCAL_SD = 'local_sd',
|
||||
|
||||
// flux-api
|
||||
FLUX_API = 'flux-api',
|
||||
|
||||
// flxu-forge
|
||||
FLUX_FORGE = 'flux-forge'
|
||||
}
|
||||
|
||||
export enum MJRobotType {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* 标签库预设的图片样式类型
|
||||
*/
|
||||
export enum PresetType {
|
||||
// 角色
|
||||
CHARACTER = 'character',
|
||||
|
||||
// 本地风格
|
||||
LOCAL_STYLE = 'localStyle',
|
||||
|
||||
// 自定义风格
|
||||
CUSTOM_STYLE = 'customStyle',
|
||||
|
||||
// laitool预设风格
|
||||
LAITOOL_STYLE = 'laitoolStyle',
|
||||
}
|
||||
+260
-230
@@ -1,245 +1,275 @@
|
||||
import { Tools } from "../../main/tools";
|
||||
import { define } from "../define";
|
||||
import path from "path";
|
||||
import { DEFINE_STRING } from "../define_string";
|
||||
import { get, has } from "lodash";
|
||||
let tools = new Tools();
|
||||
const { v4: uuidv4 } = require('uuid'); // 引入UUID库来生成唯一标识符
|
||||
import { Tools } from '../../main/tools'
|
||||
import { define } from '../define'
|
||||
import path from 'path'
|
||||
import { DEFINE_STRING } from '../define_string'
|
||||
import { get, has } from 'lodash'
|
||||
let tools = new Tools()
|
||||
const { v4: uuidv4 } = require('uuid') // 引入UUID库来生成唯一标识符
|
||||
|
||||
export const ImageSetting = {
|
||||
|
||||
/**
|
||||
* 获取自动保存图片的方式
|
||||
* @returns
|
||||
*/
|
||||
async GetAutoSaveImageClassifyOptions() {
|
||||
return {
|
||||
code: 1,
|
||||
data: [{
|
||||
label: "不分类",
|
||||
value: "one"
|
||||
},
|
||||
// {
|
||||
// label: "按模型",
|
||||
// value: "model"
|
||||
// },
|
||||
{
|
||||
label: "按风格",
|
||||
value: "style"
|
||||
},
|
||||
{
|
||||
label: "风格+模型",
|
||||
value: "theme"
|
||||
}]
|
||||
/**
|
||||
* 获取自动保存图片的方式
|
||||
* @returns
|
||||
*/
|
||||
async GetAutoSaveImageClassifyOptions() {
|
||||
return {
|
||||
code: 1,
|
||||
data: [
|
||||
{
|
||||
label: '不分类',
|
||||
value: 'one'
|
||||
},
|
||||
// {
|
||||
// label: "按模型",
|
||||
// value: "model"
|
||||
// },
|
||||
{
|
||||
label: '按风格',
|
||||
value: 'style'
|
||||
},
|
||||
{
|
||||
label: '风格+模型',
|
||||
value: 'theme'
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取自动保存图片的方式(sd,mj,d3 等)
|
||||
*/
|
||||
async GetImageGenerateCategory() {
|
||||
return {
|
||||
code: 1,
|
||||
data: [{
|
||||
label: "SD",
|
||||
value: "sd"
|
||||
/**
|
||||
* 获取自动保存图片的方式(sd,mj,d3 等)
|
||||
*/
|
||||
async GetImageGenerateCategory() {
|
||||
return {
|
||||
code: 1,
|
||||
data: [
|
||||
{
|
||||
label: 'SD',
|
||||
value: 'sd'
|
||||
},
|
||||
{
|
||||
label: 'MJ',
|
||||
value: 'mj'
|
||||
},
|
||||
{
|
||||
label: 'D3',
|
||||
value: 'd3'
|
||||
},
|
||||
{
|
||||
label: 'Flux-Forge',
|
||||
value: 'flux-forge'
|
||||
},
|
||||
{
|
||||
label: 'Flux-API',
|
||||
value: 'flux-api'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存自动保存图片的设置
|
||||
*/
|
||||
async SaveImageAutoSaveSetting(value) {
|
||||
try {
|
||||
value = JSON.parse(value)
|
||||
await tools.writeJsonFilePropertyValue(define.img_base, 'auto_save_image', value)
|
||||
return {
|
||||
code: 1
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存自动保存图片的设置
|
||||
*/
|
||||
async GetImageAutoSaveSetting() {
|
||||
try {
|
||||
let res = await tools.getJsonFilePropertyValue(define.img_base, 'auto_save_image', {}, false)
|
||||
return {
|
||||
code: 1,
|
||||
data: res
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存图片到指定文件夹,只是将任务添加到队列中
|
||||
*/
|
||||
async SaveImageToOtherFolder(output = [], value) {
|
||||
try {
|
||||
let show = false
|
||||
if (value) {
|
||||
value = JSON.parse(value)
|
||||
show = false
|
||||
} else {
|
||||
let auto_save_image = await tools.getJsonFilePropertyValue(
|
||||
define.img_base,
|
||||
'auto_save_image',
|
||||
{},
|
||||
false
|
||||
)
|
||||
value = {
|
||||
save_match_count: auto_save_image.save_match_count,
|
||||
save_folder: auto_save_image.main_save_folder
|
||||
}
|
||||
if (!auto_save_image.auto_save) {
|
||||
return {
|
||||
code: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let batch = DEFINE_STRING.QUEUE_BATCH.IMAGE_SAVE_TO_OTHER_FOLDER
|
||||
// 获取当前的所有的output文件夹
|
||||
if (output.length == 0) {
|
||||
output = await tools.getSubFolderList(
|
||||
path.join(global.config.project_path, 'tmp/bak/'),
|
||||
'start',
|
||||
'output_crop_'
|
||||
)
|
||||
}
|
||||
for (let i = 0; i < output.length; i++) {
|
||||
const element = path.join(global.config.project_path, 'tmp/bak/' + output[i])
|
||||
// 获取指定的文件夹里面的文件
|
||||
let png_files = await tools.getFilesWithExtensions(element, '.png')
|
||||
console.log(png_files)
|
||||
// 判断当前的png_files中的数据是不是大于value.save_match_count,大于的话,删除数组里面的数据
|
||||
if (value.save_match_count && png_files.length > value.save_match_count) {
|
||||
// 删除数组
|
||||
png_files.splice(value.save_match_count)
|
||||
}
|
||||
|
||||
for (let j = 0; j < png_files.length; j++) {
|
||||
const item = png_files[j]
|
||||
global.fileQueue.enqueue(
|
||||
async () => {
|
||||
// 复制文件到指定的文件夹
|
||||
let dst = path.join(
|
||||
value.save_folder,
|
||||
`${Date.now().toString()}_${uuidv4().split('-')[0]}.png`
|
||||
)
|
||||
|
||||
await tools.copyFileOrDirectory(item, dst)
|
||||
},
|
||||
{
|
||||
label: "MJ",
|
||||
value: "mj"
|
||||
},
|
||||
{
|
||||
label: "D3",
|
||||
value: "d3"
|
||||
}]
|
||||
`${batch}_${item}`,
|
||||
batch
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存自动保存图片的设置
|
||||
*/
|
||||
async SaveImageAutoSaveSetting(value) {
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
await tools.writeJsonFilePropertyValue(define.img_base, "auto_save_image", value);
|
||||
return {
|
||||
code: 1,
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存自动保存图片的设置
|
||||
*/
|
||||
async GetImageAutoSaveSetting() {
|
||||
try {
|
||||
let res = await tools.getJsonFilePropertyValue(define.img_base, "auto_save_image", {}, false);
|
||||
return {
|
||||
code: 1,
|
||||
data: res
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存图片到指定文件夹,只是将任务添加到队列中
|
||||
*/
|
||||
async SaveImageToOtherFolder(output = [], value) {
|
||||
try {
|
||||
let show = false;
|
||||
if (value) {
|
||||
value = JSON.parse(value);
|
||||
show = false;
|
||||
} else {
|
||||
let auto_save_image = await tools.getJsonFilePropertyValue(define.img_base, "auto_save_image", {}, false);
|
||||
value = {
|
||||
save_match_count: auto_save_image.save_match_count,
|
||||
save_folder: auto_save_image.main_save_folder
|
||||
}
|
||||
if (!auto_save_image.auto_save) {
|
||||
return {
|
||||
code: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let batch = DEFINE_STRING.QUEUE_BATCH.IMAGE_SAVE_TO_OTHER_FOLDER;
|
||||
// 获取当前的所有的output文件夹
|
||||
if (output.length == 0) {
|
||||
output = await tools.getSubFolderList(path.join(global.config.project_path, "tmp/bak/"), "start", "output_crop_");
|
||||
}
|
||||
for (let i = 0; i < output.length; i++) {
|
||||
const element = path.join(global.config.project_path, 'tmp/bak/' + output[i]);
|
||||
// 获取指定的文件夹里面的文件
|
||||
let png_files = await tools.getFilesWithExtensions(element, ".png");
|
||||
console.log(png_files);
|
||||
// 判断当前的png_files中的数据是不是大于value.save_match_count,大于的话,删除数组里面的数据
|
||||
if (value.save_match_count && png_files.length > value.save_match_count) {
|
||||
// 删除数组
|
||||
png_files.splice(value.save_match_count);
|
||||
}
|
||||
|
||||
for (let j = 0; j < png_files.length; j++) {
|
||||
const item = png_files[j];
|
||||
global.fileQueue.enqueue(async () => {
|
||||
// 复制文件到指定的文件夹
|
||||
let dst = path.join(value.save_folder, `${Date.now().toString()}_${uuidv4().split('-')[0]}.png`);
|
||||
|
||||
await tools.copyFileOrDirectory(item, dst);
|
||||
}, `${batch}_${item}`, batch)
|
||||
}
|
||||
}
|
||||
global.fileQueue.setBatchCompletionCallback(batch, (failedTasks) => {
|
||||
if (failedTasks.length > 0) {
|
||||
let message = `
|
||||
}
|
||||
global.fileQueue.setBatchCompletionCallback(batch, (failedTasks) => {
|
||||
if (failedTasks.length > 0) {
|
||||
let message = `
|
||||
转存任务都已完成。
|
||||
但是以下任务执行失败:
|
||||
`
|
||||
failedTasks.forEach(({ taskId, error }) => {
|
||||
message += `${taskId}-, \n 错误信息: ${error}` + '\n';
|
||||
});
|
||||
failedTasks.forEach(({ taskId, error }) => {
|
||||
message += `${taskId}-, \n 错误信息: ${error}` + '\n'
|
||||
})
|
||||
|
||||
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
|
||||
code: 0,
|
||||
message: message
|
||||
})
|
||||
} else {
|
||||
if (show) {
|
||||
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
|
||||
code: 1,
|
||||
message: "所有图片转存完成"
|
||||
})
|
||||
}
|
||||
}
|
||||
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
|
||||
code: 0,
|
||||
message: message
|
||||
})
|
||||
} else {
|
||||
if (show) {
|
||||
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
|
||||
code: 1,
|
||||
message: '所有图片转存完成'
|
||||
})
|
||||
|
||||
return {
|
||||
code: 1
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取指定的配置文件里面指定的属性的数据
|
||||
* @param {*} value 执行方法必要的信息
|
||||
* 0 define中的指定属性(指定的配置文件)
|
||||
* 1 要获取的什么属性信息 property,property 为null,赶回当前配置文件的所有数据
|
||||
* 2 是不是要校验属性不存在
|
||||
* 3 属性没有找到的默认值
|
||||
* @returns
|
||||
*/
|
||||
async GetDefineConfigJsonByProperty(value) {
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
let defin_property = value[0];
|
||||
let property = value[1];
|
||||
let need_check = value[2];
|
||||
let default_data = value[3];
|
||||
// 判断define中的属性是不是存在
|
||||
let hasProperty = has(define, defin_property);
|
||||
if (!hasProperty) {
|
||||
throw new Error(`${defin_property} 属性不存在。`);
|
||||
}
|
||||
let data = await tools.getJsonFilePropertyValue(define[defin_property], property, default_data, need_check);
|
||||
return {
|
||||
code: 1,
|
||||
data: data
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: "获取配置信息失败,错误信息入下 : " + error.message.toString()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存指定的配置文件里面指定的属性的数据
|
||||
* @param {*} value
|
||||
* 0 define中的指定属性(指定的配置文件)
|
||||
* 1 要获取的什么属性信息 property,property 为null,赶回当前配置文件的所有数据
|
||||
* 2 要写入的值
|
||||
* 3 是不是要校验属性不存在
|
||||
*/
|
||||
async SaveDefineConfigJsonByProperty(value) {
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
let defin_property = value[0];
|
||||
let property = value[1];
|
||||
let data = value[2];
|
||||
let need_check = value[3] ? value[3] : false;
|
||||
// 判断define中的属性是不是存在
|
||||
let hasProperty = has(define, defin_property);
|
||||
if (!hasProperty) {
|
||||
throw new Error(`${defin_property} 属性不存在。`);
|
||||
}
|
||||
await tools.writeJsonFilePropertyValue(define[defin_property], property, data, need_check);
|
||||
return {
|
||||
code: 1,
|
||||
message: "保存指定的配置成功"
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: "保存配置信息失败,错误信息入下 : " + error.message.toString()
|
||||
}
|
||||
}
|
||||
return {
|
||||
code: 1
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
/**
|
||||
* 获取指定的配置文件里面指定的属性的数据
|
||||
* @param {*} value 执行方法必要的信息
|
||||
* 0 define中的指定属性(指定的配置文件)
|
||||
* 1 要获取的什么属性信息 property,property 为null,赶回当前配置文件的所有数据
|
||||
* 2 是不是要校验属性不存在
|
||||
* 3 属性没有找到的默认值
|
||||
* @returns
|
||||
*/
|
||||
async GetDefineConfigJsonByProperty(value) {
|
||||
try {
|
||||
value = JSON.parse(value)
|
||||
let defin_property = value[0]
|
||||
let property = value[1]
|
||||
let need_check = value[2]
|
||||
let default_data = value[3]
|
||||
// 判断define中的属性是不是存在
|
||||
let hasProperty = has(define, defin_property)
|
||||
if (!hasProperty) {
|
||||
throw new Error(`${defin_property} 属性不存在。`)
|
||||
}
|
||||
let data = await tools.getJsonFilePropertyValue(
|
||||
define[defin_property],
|
||||
property,
|
||||
default_data,
|
||||
need_check
|
||||
)
|
||||
return {
|
||||
code: 1,
|
||||
data: data
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: '获取配置信息失败,错误信息入下 : ' + error.message.toString()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 保存指定的配置文件里面指定的属性的数据
|
||||
* @param {*} value
|
||||
* 0 define中的指定属性(指定的配置文件)
|
||||
* 1 要获取的什么属性信息 property,property 为null,赶回当前配置文件的所有数据
|
||||
* 2 要写入的值
|
||||
* 3 是不是要校验属性不存在
|
||||
*/
|
||||
async SaveDefineConfigJsonByProperty(value) {
|
||||
try {
|
||||
value = JSON.parse(value)
|
||||
let defin_property = value[0]
|
||||
let property = value[1]
|
||||
let data = value[2]
|
||||
let need_check = value[3] ? value[3] : false
|
||||
// 判断define中的属性是不是存在
|
||||
let hasProperty = has(define, defin_property)
|
||||
if (!hasProperty) {
|
||||
throw new Error(`${defin_property} 属性不存在。`)
|
||||
}
|
||||
await tools.writeJsonFilePropertyValue(define[defin_property], property, data, need_check)
|
||||
return {
|
||||
code: 1,
|
||||
message: '保存指定的配置成功'
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: '保存配置信息失败,错误信息入下 : ' + error.message.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user