lq1405 863ac4d7f4 V 3.3.4
1. 新增MJ V7 模型
2. 添加MJ生图包
2025-04-08 14:37:35 +08:00

821 lines
31 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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

import { isEmpty } from "lodash";
import { Book } from "../../../model/book/book";
import { checkStringValueAddPrefix, checkStringValueAddSuffix, errorMessage, successMessage } from "../../Public/generalTools";
import { CheckFolderExistsOrCreate, CopyFileOrFolder, JoinPath } from "../../../define/Tools/file";
import { define } from "../../../define/define"
import { CompressImageToSize, GetImageBase64, ImageSplit } from "../../../define/Tools/image";
import MJApi from "./mjApi"
import { BookBackTaskStatus, BookBackTaskType, BookTaskStatus, BookType, DialogType, MJAction, OperateBookType, TaskExecuteType } from "../../../define/enum/bookEnum";
import { DEFINE_STRING } from "../../../define/define_string";
import { MJ } from "../../../model/mj";
import { MJImageType, MJRespoonseType } from "../../../define/enum/mjEnum";
import { MJSettingModel } from "../../../model/Setting/mjSetting";
import { GeneralResponse } from "../../../model/generalResponse"
import { LoggerStatus, ResponseMessageType } from "../../../define/enum/softwareEnum";
import { ImageStyle } from "../Book/imageStyle";
import { LogScheduler } from "../task/logScheduler";
import { Tools } from "../../../main/tools"
import { BookServiceBasic } from "../ServiceBasic/bookServiceBasic";
import { PresetService } from "../presetService";
import { SoftWareServiceBasic } from "../ServiceBasic/softwareServiceBasic";
import path from "path"
const { v4: uuidv4 } = require('uuid')
import fs from "fs"
import { TaskModal } from "@/model/task";
import { OptionServices } from "../Options/optionServices";
import { OptionKeyName } from "@/define/enum/option";
import { ValidateJson } from "@/define/Tools/validate";
const fspromise = fs.promises
export class MJOpt {
mjApi: MJApi;
mjSimpleSetting: MJSettingModel.MjSimpleSettingModel;
imageStyle: ImageStyle;
logScheduler: LogScheduler;
tools: Tools;
bookServiceBasic: BookServiceBasic
presetService: PresetService
softWareServiceBasic: SoftWareServiceBasic
mj_globalSetting: MJSettingModel.MJ_GlobalSettingModel
constructor() {
this.imageStyle = new ImageStyle()
this.logScheduler = new LogScheduler()
this.tools = new Tools()
this.bookServiceBasic = new BookServiceBasic();
this.presetService = new PresetService()
this.mjApi = new MJApi()
this.softWareServiceBasic = new SoftWareServiceBasic()
}
/**
* 获取MJ设置
*/
async GetMJSetting() {
let optionServices = new OptionServices()
let mjSettingData = await optionServices.GetOptionByKey(OptionKeyName.MJ_GlobalSetting);
if (mjSettingData.code == 0) {
throw new Error("加载MJ设置失败失败原因如下" + mjSettingData.message)
}
if (mjSettingData.data == null) {
throw new Error("加载MJ设置失败失败原因如下没有找到对应的MJ设置请先去MJ设置中设置")
}
if (!ValidateJson(mjSettingData.data.value)) {
throw new Error("MJ设置的数据格式不正确请检查数据格式")
}
this.mj_globalSetting = JSON.parse(mjSettingData.data.value) as MJSettingModel.MJ_GlobalSettingModel
this.mjSimpleSetting = this.mj_globalSetting.mj_simpleSetting
}
/**
* 返回MJ的数据到前端界面前端界面做出相应的改变
* @param {*} data
*/
sendChangeMessage(data: GeneralResponse.MessageResponse, message_name: string = DEFINE_STRING.BOOK.MAIN_DATA_RETURN) {
if (!message_name) {
message_name = DEFINE_STRING.BOOK.MAIN_DATA_RETURN
}
global.newWindow[0].win.webContents.send(message_name, data)
}
//#region 选择反推的提示词相关
/**
* MJ反推将反推的数据写入到GPT中
* @param bookTaskDetailId
* @param index
*/
async SingleReverseToGptPrompt(bookTaskDetailId: string, index: number): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
try {
await this.GetMJSetting()
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(bookTaskDetailId)
if (bookTaskDetail == null) {
throw new Error("没有找到对应的数据")
}
let reversePrompts = bookTaskDetail.reversePrompt
if (!reversePrompts || reversePrompts.length <= 0) {
throw new Error("没有找到对应的反推提示词数据")
}
let reversePrompt = reversePrompts[index]
let gptPrompt = reversePrompt.promptCN ? reversePrompt.promptCN : reversePrompt.prompt
// 开始修改
await this.bookServiceBasic.UpdateBookTaskDetail(bookTaskDetailId, {
gptPrompt: gptPrompt
})
// 保存完毕
return successMessage(gptPrompt, "反推数据写出成功", "ReverseBook_ReversePromptToGptPrompt")
} catch (error) {
return errorMessage("反推数据写出失败,错误信息如下:" + error.message, "ReverseBook_ReversePromptToGptPrompt")
}
}
//#endregion
//#region MJ反推相关
/**
* 循环请求数据,判断反推任务是不是完成,返回数据
* @param task
* @param reqRes
*/
async fetchWithRetry(task: TaskModal.Task, reqRes: string) {
while (true) {
try {
// 执行你的操作
let task_res = await this.mjApi.GetMJAPITaskById(reqRes, task.id);
// 判断他的状态是不是成功
if (task_res.code == 0) {
// 反推失败
await this.bookServiceBasic.UpdateBookTaskDetail(task.bookTaskDetailId, {
status: BookTaskStatus.REVERSE_FAIL
});
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.FAIL,
errorMessage: task_res.message
});
throw new Error(`${task_res.message}`);
} else {
if (task_res.progress == 100) {
task_res.type == MJRespoonseType.FINISHED;
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.DONE
});
// 这边还要再处理一下数据,将反推获取的数据进行切割处理
let reversePrompt = [];
if (task_res.prompt != undefined && task_res.prompt != "" && task_res.prompt != null) {
let string_res = task_res.prompt.split(/(?=\d⃣)/).map(part => part.replace(/^\d⃣\s*/, '').trim());
reversePrompt = string_res.map((item) => {
return {
id: uuidv4(),
bookTaskDetailId: task.bookTaskDetailId,
prompt: item,
promptCN: item,
isSelect: false
};
});
}
await this.bookServiceBasic.UpdateBookTaskDetail(task.bookTaskDetailId, {
status: BookTaskStatus.REVERSE_DONE,
reversePrompt: reversePrompt,
gptPrompt: undefined
});
task_res.prompt = JSON.stringify(reversePrompt);
task_res.id = task.bookTaskDetailId;
this.sendChangeMessage({
code: 1,
type: ResponseMessageType.MJ_REVERSE,
id: task.bookTaskDetailId,
data: task_res
}, task.messageName);
break;
} else {
// 当获取的图片的进度小于100的时候等待5秒继续监听
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
task_res.id = task.bookTaskDetailId;
this.sendChangeMessage({
code: 1,
type: ResponseMessageType.MJ_REVERSE,
id: task.bookTaskDetailId,
data: task_res
}, task.messageName);
} catch (error) {
throw error;
}
}
};
/**
* MJ反推
* @param task
*/
async MJImage2Text(task: TaskModal.Task): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
try {
if (isEmpty(task.bookTaskDetailId)) {
throw new Error("MJ反推没有找到对应的分镜信息")
}
await this.GetMJSetting()
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId);
let oldImagePath = bookTaskDetail.oldImage
if (isEmpty(oldImagePath)) {
throw new Error(`${bookTaskDetail.name} 没有需要反推的图片`);
}
oldImagePath = JoinPath(define.project_path, oldImagePath)
// let imageBase64 = await GetImageBase64(oldImagePath)
// 每次执行前压缩图片
let newImageBase64 = await CompressImageToSize(oldImagePath, 500000);
// 将buffer转换为base64
let imageBase64 = newImageBase64.toString('base64');
// 这个就是任务ID
let reqRes = await this.mjApi.SubmitMJDescribe({
image: 'data:image/png;base64,' + imageBase64,
taskId: task.id
})
if (reqRes == '23') {
// 任务队列过多,重新提交排队
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.RECONNECT,
})
// throw new Error(`任务队列过多,${task.bookTaskDetailId} 重新提交排队`);
return;
}
await this.bookServiceBasic.UpdateBookTaskDetail(task.bookTaskDetailId, {
status: BookTaskStatus.REVERSE
})
this.sendChangeMessage({
code: 1,
type: ResponseMessageType.MJ_REVERSE,
id: task.bookTaskDetailId,
data: {
code: 1,
type: MJRespoonseType.UPDATED,
mjType: MJAction.DESCRIBE,
category: this.mjSimpleSetting.type,
messageId: reqRes,
id: task.bookTaskDetailId,
progress: 0,
status: "success"
} as MJ.MJResponseToFront
}, task.messageName)
await this.fetchWithRetry(task, reqRes);
} catch (error) {
console.log(error.toString())
let errorMsg = "MJ反推失败失败信息如下" + error.toString()
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.FAIL,
errorMessage: errorMsg
})
this.sendChangeMessage({
code: 0,
id: task.bookTaskDetailId,
type: ResponseMessageType.MJ_REVERSE,
dialogType: DialogType.NOTIFICATION,
message: errorMsg,
data: {
code: 0,
type: MJRespoonseType.UPDATED,
mjType: MJAction.DESCRIBE,
category: this.mjSimpleSetting.type,
messageId: undefined,
id: task.bookTaskDetailId,
progress: 0,
message: error.toString(),
status: "failure"
}
}, task.messageName)
return errorMessage(errorMsg, "MJReverse_MJImage2Text")
}
}
//#endregion
//#region 合并提示词相关
/**
* 获取场景的提示词
* @param ids 需要获取的IDs
* @returns
*/
async GetScenePresetStringByIds(ids: string[]): Promise<string> {
let sceneString = ''
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
let scene = await this.presetService.GetScenePresetDetailById(id)
if (scene.code == 0) {
throw new Error(scene.message)
}
if (scene.data) {
// 这边开始拼接
sceneString += scene.data.prompt + ', '
}
}
return sceneString
}
/**
* 获取人物提示词,包括垫图链接
* @param ids 需要获取的IDs
* @returns
*/
async GetCharacterPresetStringByIds(ids: string[]): Promise<{ characterString: string, characterUrl: string }> {
let characterString = ''
let characterUrl = ''
let crefCw = undefined
for (let i = 0; i < ids.length; i++) {
const element = ids[i];
let character = await this.presetService.GetCharacterPresetDetailById(element)
if (character.code == 0) {
throw new Error(character.message)
}
if (character.data) {
characterString += character.data.prompt + ', '
if (character.data.image_url && character.data.image_url != '' && character.data.cref_cw) {
characterUrl += ` ${character.data.image_url} `
crefCw = character.data.cref_cw
}
}
}
//这边坐下合并s
if (characterUrl != '') {
characterUrl = ` --cref ${characterUrl} --cw ${crefCw}`
}
return { characterString, characterUrl }
}
/**
* MJ 进行合并提示词,通过类型进行判断是单个还是全部合并
* @param id 合并的ID
* @param mergeType 合并的类型
*/
async MergePrompt(id: string, operateBookType: OperateBookType): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
try {
let bookTaskDetail = undefined as Book.SelectBookTaskDetail[];
let bookTask = undefined as Book.SelectBookTask;
await this.GetMJSetting()
if (operateBookType == OperateBookType.BOOKTASK) {
bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
bookTaskId: id
})
bookTask = await this.bookServiceBasic.GetBookTaskDataById(id);
// 判断是不是有为空的
let emptyName = [] as string[]
for (let i = 0; i < bookTaskDetail.length; i++) {
const element = bookTaskDetail[i];
if (isEmpty(element.gptPrompt)) {
emptyName.push(element.name)
}
}
if (emptyName.length > 0) {
throw new Error(`${emptyName.join('')} 的提示词为空,请先推理`)
}
} else if (operateBookType == OperateBookType.BOOKTASKDETAIL) {
let tempBookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(id);
if (isEmpty(tempBookTaskDetail.gptPrompt)) {
throw new Error("当前分镜没有推理提示词,请先生成")
}
bookTaskDetail = [tempBookTaskDetail]
bookTask = await this.bookServiceBasic.GetBookTaskDataById(bookTaskDetail[0].bookTaskId);
} else {
throw new Error("未知的合并类型")
}
if (bookTaskDetail.length <= 0) {
throw new Error("没有找到对应的需要合并的分镜数据")
}
let book = await this.bookServiceBasic.GetBookDataById(bookTask.bookId);
// 获取合并的排序
let imageBaseSetting = JSON.parse(await fspromise.readFile(define.img_base, 'utf-8')); // 没有就直接报错
let promptSort = imageBaseSetting.prompt_sort; // 没有就直接报错
if (!promptSort) {
throw new Error("未找到提示词排序,请先设置")
}
// let suffixParam = imageBaseSetting.mj_config.image_suffix ; // 没有就直接报错
let suffixParam = this.mjSimpleSetting.imageSuffix
// let styleString = '';
// 拿到所有的风格
let styleArr = await this.imageStyle.GetAllImageStyleList(bookTask.imageStyle, bookTask.customizeImageStyle);
let result = []
for (let i = 0; i < bookTaskDetail.length; i++) {
const element = bookTaskDetail[i];
// 没有推理提示词,直接跳过
if (isEmpty(element.gptPrompt)) {
continue;
}
let promptStr = '';
for (let i = 0; i < promptSort.length; i++) {
const element = promptSort[i];
promptStr += `${'${' + element.value + '}'} `
}
// TODO 后面需要完善人物和场景的提示词
let characterString = '' // 人物
let characterUrl = ''
let sceneString = "" // 场景
// 获取当前的自定义风格的垫图字符串
if (book.type == BookType.ORIGINAL) {
let sceneIds = element.sceneTags ? element.sceneTags : []
let characterIds = element.characterTags ? element.characterTags : []
if (sceneIds && sceneIds.length > 0) {
sceneString = await this.GetScenePresetStringByIds(sceneIds)
}
if (characterIds && characterIds.length > 0) {
let res = await this.GetCharacterPresetStringByIds(characterIds)
characterString = res.characterString
characterUrl = res.characterUrl
}
}
let styleString = ""
let style_url = ''
let sw = undefined
styleArr.forEach((item) => {
if (item.type && item.type == 'style_main') {
if (sw == undefined) {
sw = item.sref_sw
}
if (!isEmpty(item.image_url)) {
let url = item.image_url ? item.image_url : ''
style_url += ' ' + url
}
if (item.prompt) {
styleString += item.prompt + ','
}
} else {
styleString += item.english_style + ','
}
})
style_url = checkStringValueAddPrefix(style_url, '--sref ')
if (sw != undefined) {
style_url = checkStringValueAddSuffix(style_url, ` --sw ${sw}`)
}
let cref_url = ''
promptStr = promptStr.replace('${style}', styleString)
promptStr = promptStr.replace('${character}', characterString)
promptStr = promptStr.replace('${scene}', sceneString)
promptStr = promptStr.replace(
'${prompt}',
checkStringValueAddSuffix(element.gptPrompt, ',')
)
// 判断是不是需要加前后缀
if (bookTask.prefixPrompt) {
promptStr = checkStringValueAddSuffix(bookTask.prefixPrompt, ',') + promptStr
}
if (bookTask.suffixPrompt) {
promptStr = checkStringValueAddSuffix(promptStr, ',') + bookTask.suffixPrompt
}
promptStr = ' ' + promptStr;
promptStr += ` ${characterUrl} ${style_url}${suffixParam}`
// 修改数据库数据
await this.bookServiceBasic.UpdateBookTaskDetail(element.id, {
prompt: promptStr
})
// 写回数据
result.push({
id: element.id,
prompt: promptStr
})
}
return successMessage(result, "MJ模式合并数据成功", "MJOpt_MergePrompt")
} catch (error) {
return errorMessage("MJ合并提示词失败错误信息如下" + error.message, "MJOpt_MergePrompt")
}
}
//#endregion
//#region MJ生成图片相关
/**
* 单个生成图片,将任务添加到队列中
* @param id 要添加的ID
* @param operateBookType 操作的类型
*/
async AddMJGenerateImageTask(id: string, operateBookType: OperateBookType, responseMessageName: string = null, coverData: boolean = true): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
try {
let bookTaskDetail = undefined as Book.SelectBookTaskDetail[];
// let bookTask = undefined as Book.SelectBookTask;
if (operateBookType == OperateBookType.BOOKTASK) {
bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
bookTaskId: id
})
if (!coverData) {
// 过滤掉已经生成的数据
bookTaskDetail = bookTaskDetail.filter((item) => !item.mjMessage)
}
// bookTask = this.bookTaskService.GetBookTaskDataById(id);
} else if (operateBookType == OperateBookType.BOOKTASKDETAIL) {
let bookTaskDetailRes = await this.bookServiceBasic.GetBookTaskDetailDataById(id)
bookTaskDetail = [bookTaskDetailRes]
// bookTask = this.bookTaskService.GetBookTaskDataById(bookTaskDetail[0].bookTaskId);
} else if (operateBookType == OperateBookType.UNDERBOOKTASK) {
let thisBookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(id);
if (thisBookTaskDetail == null) {
throw new Error("没有找到对应的数据")
}
// 获取批次的所有数据
bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
bookTaskId: thisBookTaskDetail.bookTaskId
})
// bookTask = this.bookTaskService.GetBookTaskDataById(thisBookTaskDetail.bookTaskId);
bookTaskDetail = bookTaskDetail.filter((item) => item.no >= thisBookTaskDetail.no) // 需要包含自己
}
else {
throw new Error("MJOpt_AddGenerateImageTask未知的操作类型")
}
// 将被锁定的数据过滤掉
bookTaskDetail = bookTaskDetail.filter((item) => item.imageLock == false)
if (bookTaskDetail.length <= 0) {
throw new Error("没有找到可以生成图片的分镜,可能是已经被锁定")
}
// 将任务添加到队列中
for (let i = 0; i < bookTaskDetail.length; i++) {
const element = bookTaskDetail[i];
let taskRes = await this.bookServiceBasic.AddBookBackTask(element.bookId, BookBackTaskType.MJ_IMAGE, TaskExecuteType.AUTO, element.bookTaskId, element.id, responseMessageName
);
// 添加返回日志
await this.logScheduler.AddLogToDB(element.bookId, BookBackTaskType.MJ_IMAGE, `添加 ${element.name} MJ生成任务成功`, element.bookTaskId, LoggerStatus.SUCCESS)
}
// 全部完毕
return successMessage(null, "MJ添加生成图片任务成功", "MJOpt_AddGenerateImageTask")
} catch (error) {
return errorMessage("MJ添加生成图片任务失败错误信息如下" + error.message, "MJOpt_AddGenerateImageTask")
}
}
/**
* 循环请求数据,判断反推任务是不是完成,返回数据
* @param task
* @param reqRes
*/
async FetchImageTask(task: TaskModal.Task, reqRes: string, book: Book.SelectBook, bookTask: Book.SelectBookTask, bookTaskDetail: Book.SelectBookTaskDetail) {
while (true) {
try {
await this.GetMJSetting()
// 执行你的操作
let task_res = await this.mjApi.GetMJAPITaskById(reqRes, task.id);
task_res.id = task.bookTaskDetailId;
// 判断他的状态是不是成功
if (task_res.code == 0) {
// 生图失败
await this.bookServiceBasic.UpdateBookTaskDetail(task.bookTaskDetailId, {
status: BookTaskStatus.IMAGE_FAIL,
});
let errorMsg = `MJ生成图片失败失败信息如下${task_res.message}`
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
mjApiUrl: this.mjApi.imagineUrl,
progress: 100,
category: this.mjApi.mjSimpleSetting.type,
imageClick: task_res.imageClick,
imageShow: task_res.imageShow,
messageId: task_res.messageId,
action: MJAction.IMAGINE,
status: 'error',
message: errorMsg
})
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.FAIL,
errorMessage: errorMsg
});
this.sendChangeMessage({
code: 0,
type: ResponseMessageType.MJ_IMAGE,
id: task.bookTaskDetailId,
data: {
...task_res,
status: "error",
message: errorMsg
},
message: errorMsg
}, task.messageName);
return;
// throw new Error(`${task_res.message}`);
} else {
if (task_res.progress == 100) {
task_res.type == MJRespoonseType.FINISHED;
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.DONE
});
// 下载图片
let imagePath = path.join(book.bookFolderPath, `data\\MJOriginalImage\\${task_res.messageId}.png`);
// 判断是不是生图包是的话需要替换图片的baseurl
if (this.mj_globalSetting.mj_simpleSetting.type == MJImageType.PACKAGE_MJ) {
let imageBaseUrl = this.mj_globalSetting.mj_imagePackageSetting.selectedProxy;
if (imageBaseUrl && imageBaseUrl != '') {
task_res.imageClick = task_res.imageClick.replace(/https?:\/\/[^/]+/, imageBaseUrl)
}
}
await CheckFolderExistsOrCreate(path.dirname(imagePath))
await this.tools.downloadFileUrl(task_res.imageClick, imagePath)
// 进行图片裁剪
let imageRes = await ImageSplit(imagePath, bookTaskDetail.name, path.join(book.bookFolderPath, 'data\\MJOriginalImage'));
if (imageRes && imageRes.length < 4) {
throw new Error("图片裁剪失败")
}
// 修改数据库数据,将图片保存到对应的文件夹中
let firstImage = imageRes[0];
if (book.type == BookType.ORIGINAL && bookTask.name == "output_00001") {
await CopyFileOrFolder(firstImage, path.join(book.bookFolderPath, `tmp\\input\\${bookTaskDetail.name}.png`));
}
let out_file = path.join(bookTask.imageFolder, `${bookTaskDetail.name}.png`)
await CopyFileOrFolder(firstImage, out_file);
task_res.outImagePath = out_file;
task_res.subImagePath = imageRes;
task_res.id = task.bookTaskDetailId;
// 修改分镜的数据
await this.bookServiceBasic.UpdateBookTaskDetail(task.bookTaskDetailId, {
outImagePath: path.relative(define.project_path, out_file),
subImagePath: imageRes.map((item) => path.relative(define.project_path, item))
})
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
mjApiUrl: this.mjApi.imagineUrl,
progress: 100,
category: this.mjApi.mjSimpleSetting.type,
imageClick: task_res.imageClick,
imageShow: task_res.imageShow,
messageId: task_res.messageId,
action: MJAction.IMAGINE,
status: task_res.status,
})
this.sendChangeMessage({
code: 1,
type: ResponseMessageType.MJ_IMAGE,
id: task.bookTaskDetailId,
data: task_res
}, task.messageName);
break;
}
}
// 这边也要修改数据
task_res.id = task.bookTaskDetailId;
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
mjApiUrl: this.mjApi.imagineUrl,
progress: task_res.progress,
category: this.mjApi.mjSimpleSetting.type,
imageClick: task_res.imageClick,
imageShow: task_res.imageShow,
messageId: task_res.messageId,
action: MJAction.IMAGINE,
status: task_res.status,
message: task_res.message
})
task_res.outImagePath = task_res.imagePath;
this.sendChangeMessage({
code: 1,
type: ResponseMessageType.MJ_IMAGE,
id: task.bookTaskDetailId,
data: task_res
}, task.messageName);
// 当获取的图片的进度小于100的时候等待5秒继续监听
await new Promise(resolve => setTimeout(resolve, 9000));
} catch (error) {
throw error;
}
}
};
/**
* MJ生成图片
* @param task
*/
async MJImagine(task: TaskModal.Task): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
try {
if (isEmpty(task.bookTaskDetailId)) {
throw new Error("MJ出图没有找到对应的分镜信息")
}
await this.GetMJSetting()
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId);
if (bookTaskDetail == null) {
throw new Error("没有找到对应的分镜信息")
}
let book = await this.bookServiceBasic.GetBookDataById(bookTaskDetail.bookId)
if (book == null) {
throw new Error("没有找到对应的小说信息")
}
let bookTask = await this.bookServiceBasic.GetBookTaskDataById(bookTaskDetail.bookTaskId)
if (bookTask == null) {
throw new Error("没有找到对应的任务信息")
}
let prompt = bookTaskDetail.prompt
if (isEmpty(prompt)) {
throw new Error(`${bookTaskDetail.name} 没有找到对应的提示词`)
}
// 这个就是任务ID
let reqRes = await this.mjApi.SubmitMJImagine(task.id, prompt)
if (reqRes == '23') {
// 任务队列过多,重新提交排队
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.RECONNECT,
})
this.sendChangeMessage({
code: 1,
type: ResponseMessageType.MJ_IMAGE,
id: task.bookTaskDetailId,
data: {
code: 1,
type: MJRespoonseType.UPDATED,
mjType: MJAction.IMAGINE,
category: this.mjSimpleSetting.type,
message_id: '',
id: task.bookTaskDetailId,
progress: 0,
status: "re_connect"
} as MJ.MJResponseToFront
}, task.messageName)
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
mjApiUrl: this.mjApi.imagineUrl,
progress: 0,
category: this.mjApi.mjSimpleSetting.type,
imageClick: "",
imageShow: "",
messageId: "",
action: MJAction.IMAGINE,
status: "re_connect",
})
// throw new Error(`任务队列过多,${task.bookTaskDetailId} 重新提交排队`);
return;
}
await this.bookServiceBasic.UpdateBookTaskDetail(task.bookTaskDetailId, {
status: BookTaskStatus.IMAGE
})
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.RUNNING
})
this.sendChangeMessage({
code: 1,
type: ResponseMessageType.MJ_IMAGE,
id: task.bookTaskDetailId,
data: {
code: 1,
type: MJRespoonseType.UPDATED,
mjType: MJAction.IMAGINE,
category: this.mjSimpleSetting.type,
message_id: reqRes,
id: task.bookTaskDetailId,
progress: 0,
status: "submited"
} as MJ.MJResponseToFront
}, task.messageName)
await this.FetchImageTask(task, reqRes, book, bookTask, bookTaskDetail);
} catch (error) {
console.log(error.toString())
let errorMsg = "MJ生图失败失败信息如下" + error.toString()
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.FAIL,
errorMessage: errorMsg
})
this.sendChangeMessage({
code: 0,
id: task.bookTaskDetailId,
type: ResponseMessageType.MJ_IMAGE,
dialogType: DialogType.NOTIFICATION,
message: errorMsg,
data: {
code: 0,
type: MJRespoonseType.UPDATED,
mjType: MJAction.IMAGINE,
category: this.mjSimpleSetting.type,
messageId: undefined,
id: task.bookTaskDetailId,
progress: 0,
message: errorMsg,
status: "error"
}
}, task.messageName)
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
mjApiUrl: this.mjApi.imagineUrl,
progress: 0,
category: this.mjApi.mjSimpleSetting.type,
imageClick: "",
imageShow: "",
messageId: "",
action: MJAction.IMAGINE,
status: "error",
message: errorMsg
})
return errorMessage(errorMsg, "MJReverse_MJImage2Text")
}
}
//#endregion
}