lq1405 6336b36ead V3.3.1
1. 初步接入 comfy UI 出图,设定工作流,导出API,直接添加到软件,选中对应的工作流调用出图
2. 文案处理模型改为选择,同步通用设置的模型列表和令牌,添加测试链接功能
3. 添加缓存区图片删除功能
4. 添加垫图/MJ提示词过滤,提示无效的垫图文件(在出图的时候和添加垫图链接的时候,主要过滤飞书链接)
5. 优化聚合推文选图逻辑,没有出过图也能拖拽
6. 优化处理软件所有的加载状态
7. 修复MJ设置初始化问题
2025-03-22 10:38:23 +08:00

195 lines
6.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

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 { BookServiceBasic } from "./ServiceBasic/bookServiceBasic";
import { define } from '../../define/define'
import fs from 'fs'
import { GptService } from "./GPT/gpt";
import { isEmpty } from "lodash";
import path from 'path'
import { CheckFolderExistsOrCreate, CopyFileOrFolder } from "../../define/Tools/file";
import { Base64ToFile, GetImageBase64 } from "../../define/Tools/image";
import { BookBackTaskStatus } from "../../define/enum/bookEnum";
import { MJAction, MJImageType } from "../../define/enum/mjEnum";
import axios from "axios";
import { TaskModal } from "@/model/task";
export class D3Opt {
bookServiceBasic: BookServiceBasic
gptService: GptService
constructor() {
this.gptService = new GptService()
this.bookServiceBasic = new BookServiceBasic()
}
/**
* 获取SD的设置之后要删掉改为数据库
*/
private async GetSDSetting() {
let sdSetting = JSON.parse(await fs.promises.readFile(define.sd_setting, 'utf-8'))
return sdSetting
}
//#region D3生图
/**
* 异步发送D3 API图像请求
* 该函数用于向指定的D3 API发送图像生成请求通过提供模型、提示和图像大小等参数来定制生成的图像
*
* @param url {string} - API的基础URL字符串指定了发送请求的目标地址
* @param key {string} - API密钥字符串用于认证请求使函数能够访问API服务
* @param body {object} - 包含模型、提示和图像大小的对象
* - model {string} 模型字段指定用于生成图像的AI模型
* - prompt {string} 提示字段,提供生成图像的文本描述或提示
* - size {string} 大小字段,定义生成图像的尺寸
* @returns 无返回值但函数内部可能包含对API的异步请求操作
*/
async D3APIImageRequest(url: string, key: string, body: { model: string; prompt: string; size: string; }) {
let response = await axios.post(url, { ...body, n: 1 }, {
headers: {
Authorization: 'Bearer ' + key
}
})
if (response.data && response.data.data && response.data.data.length > 0) {
return response.data.data[0].url
} else {
return undefined
}
}
/**
* 异步生成D3图像
* @param task 任务模型
* @returns Promise<void>
*/
async D3ImageGenerate(task: TaskModal.Task): Promise<void> {
let sdSetting = undefined
try {
console.log("D3ImageGenerate", task)
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId);
let bookTask = await this.bookServiceBasic.GetBookTaskDataById(bookTaskDetail.bookTaskId);
let book = await this.bookServiceBasic.GetBookDataById(bookTask.bookId);
sdSetting = await this.GetSDSetting()
await this.gptService.RefreshGptSetting();
let prompt = bookTaskDetail.prompt;
let requestUrl = this.gptService.gptUrl
let uil = new URL(requestUrl);
let url = `${uil.protocol}//${uil.hostname}` + "/v1/images/generations"
if (!isEmpty(sdSetting.webui.prompt)) {
prompt = sdSetting.webui.prompt + ', ' + prompt
}
let size = `${sdSetting.webui.width}x${sdSetting.webui.height}`
// 这边需要判断下size是不是合法的
if (!['1024x1024', '1024x1792', '1792x1024'].includes(size)) {
throw new Error('D3 生成图片的尺寸不合法,只支持 1024x1024、1024x1792、1792x1024')
}
let model = 'dall-e-3'
// 一次请求生成一张 多个请求
let SdOriginalImage = path.join(book.bookFolderPath, 'data/SdOriginalImage');
await CheckFolderExistsOrCreate(SdOriginalImage);
let outputFolder = bookTask.imageFolder;
await CheckFolderExistsOrCreate(outputFolder);
let inputFolder = path.join(book.bookFolderPath, 'tmp/input')
await CheckFolderExistsOrCreate(inputFolder);
let outImagePath = ''
let subImagePath = []
let batchSize = sdSetting.setting.batch_size; 7
for (let i = 0; i < batchSize; i++) {
const element = batchSize;
let imageUrl = await this.D3APIImageRequest(url, this.gptService.gptApiKey, {
model: model,
prompt: prompt,
size: size
})
// 这边开始处理返回的数据
if (isEmpty(imageUrl)) {
throw new Error('D3 生图返回的图片地址为空')
}
// 下载指定的文件
let base64 = await GetImageBase64(imageUrl)
// 将base64 写出
let imgPath = path.join(SdOriginalImage, `${bookTaskDetail.name}_${new Date().getTime()}_${i}.png`)
await Base64ToFile(base64, imgPath);
// 写出去
if (bookTask.name == 'output_00001') {
// 复制一个到input
let inputImgPath = path.join(inputFolder, `${bookTaskDetail.name}.png`)
await CopyFileOrFolder(imgPath, inputImgPath)
}
if (i == 0) {
// 复制到对应的文件夹里面
let outPath = path.join(outputFolder, `${bookTaskDetail.name}.png`)
await CopyFileOrFolder(imgPath, outPath)
outImagePath = outPath
}
subImagePath.push(imgPath)
}
// 结束 开始返回
// 修改数据库
await this.bookServiceBasic.UpdateBookTaskDetail(bookTaskDetail.id, {
outImagePath: path.relative(define.project_path, outImagePath),
subImagePath: subImagePath.map((item) => path.relative(define.project_path, item))
})
await this.bookServiceBasic.UpdateTaskStatus({
id: task.id,
status: BookBackTaskStatus.DONE
});
let resp = {
mjApiUrl: url,
progress: 100,
category: MJImageType.FLUX_API,
imageClick: subImagePath.join(','),
imageShow: subImagePath.join(','),
messageId: "",
action: MJAction.IMAGINE,
status: "success",
subImagePath: subImagePath,
outImagePath: outImagePath,
message: "D3 生成图片成功"
}
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, resp)
global.newWindow[0].win.webContents.send(task.messageName, {
code: 1,
message: "D3 生成图片成功",
data: {
...resp,
id: bookTaskDetail.id
}
})
} catch (error) {
let errorMsg = "D3 生成图片失败,错误信息如下:" + error.toString()
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
mjApiUrl: "",
progress: 0,
category: MJImageType.FLUX_API,
imageClick: "",
imageShow: "",
messageId: "",
action: MJAction.IMAGINE,
status: "error",
message: errorMsg,
})
global.newWindow[0].win.webContents.send(task.messageName, {
code: 0,
message: errorMsg,
data: {
status: 'error',
message: errorMsg,
id: task.bookTaskDetailId
}
})
throw error
}
}
}
//#endregion