import { BookType, OperateBookType, TagDefineType } from '../../../define/enum/bookEnum' import { errorMessage, successMessage } from '../../Public/generalTools' import { BookService } from '../../../define/db/service/Book/bookService' import { BookTaskService } from '../../../define/db/service/Book/bookTaskService' import { BookTaskDetailService } from '../../../define/db/service/Book/bookTaskDetailService' import { CopyImageType } from '../../../define/enum/bookEnum' const { v4: uuidv4 } = require('uuid') import { define } from '../../../define/define' import path from 'path' import { CheckFileOrDirExist, CheckFolderExistsOrCreate, CopyFileOrFolder } from '../../../define/Tools/file' import { Book } from '../../../model/book' import { GeneralResponse } from '../../../model/generalResponse' import { cloneDeep, isEmpty } from 'lodash' export class BookBasic { constructor() { } bookTaskService: BookTaskService bookTaskDetailService: BookTaskDetailService async InitService() { if (!this.bookTaskService) { this.bookTaskService = await BookTaskService.getInstance() } if (!this.bookTaskDetailService) { this.bookTaskDetailService = await BookTaskDetailService.getInstance() } } //#region 小说相关操作 /** * 新增或者是修小说数据 * @param {*} book 小说信息 * @returns */ async AddOrModifyBook(book) { try { if (book == null) { return errorMessage('小说数据为空,无法修改') } // 处理一下数据,处理文件地址(删除前缀,转换为默认地址) // 当前的小说的名字是不是在数据库中以存在 let _bookService = await BookService.getInstance() let res = await _bookService.AddOrModifyBook(book) return res } catch (error) { return errorMessage( '修改数据错误,错误信息如下:' + error.message, 'BookBasic_AddOrModifyBook' ) } } // 小说类型返回 GetBookType() { return successMessage( [ { label: 'SD反推', value: BookType.SD_REVERSE }, { label: 'MJ反推', value: BookType.MJ_REVERSE }, { label: '原创', value: BookType.ORIGINAL } ], '获取小说类型成功' ) } //#endregion //#region 小说批次任务相关操作 async OneToFourBookTask(bookTaskId: string) { try { console.log(bookTaskId) await this.InitService(); let copyCount = 100 let bookTask = this.bookTaskService.GetBookTaskDataById(bookTaskId) if (bookTask == null) { throw new Error("没有找到对应的数小说任务,请检查数据") } // 获取所有的出图中最少的 let bookTaskDetail = this.bookTaskDetailService.GetBookTaskData({ bookTaskId: bookTaskId }).data as Book.SelectBookTaskDetail[] if (bookTaskDetail == null || bookTaskDetail.length <= 0) { throw new Error("没有对应的小说分镜任务,请先添加分镜任务") } for (let i = 0; i < bookTaskDetail.length; i++) { const element = bookTaskDetail[i]; if (isEmpty(element.subImagePath)) { throw new Error("检测到图片没有出完,请先检查出图") } if (element.subImagePath == null || element.subImagePath.length <= 0) { throw new Error("检测到图片没有出完,请先检查出图") } if (element.subImagePath.length < copyCount) { copyCount = element.subImagePath.length } } if (copyCount <= 0) { throw new Error("批次设置错误,无法进行一拆四") } // 开始复制 let res = await this.CopyNewBookTask(bookTask, bookTaskDetail, copyCount - 1, CopyImageType.ONE) if (res.code == 0) { throw new Error(res.message) } return successMessage(res.data, "一拆四成功", "BookBasic_OneToFourBookTask") } catch (error) { return errorMessage("一拆四失败,失败信息如下:" + error.message, "BookBasic_OneToFourBookTask") } } /** * 复制一个小说批次任务,创建新的小说批次任务 * @param oldBookTaskId * @param copyCount 复制的数量 * @param isCopyImage 是否复制图片 */ async CopyNewBookTask(sourceBookTask: Book.SelectBookTask, sourceBookTaskDetail: Book.SelectBookTaskDetail[], copyCount: number, copyImageType: CopyImageType) { try { await this.InitService(); let addBookTask = [] as Book.SelectBookTask[] let addBookTaskDetail = [] as Book.SelectBookTaskDetail[] // 先处理文件夹的创建,包括小说任务的和小说任务分镜的 for (let i = 0; i < copyCount; i++) { let maxNo = this.bookTaskService.realm .objects('BookTask') .filtered('bookId = $0', sourceBookTask.bookId) .max('no') let no = maxNo == null ? 1 : Number(maxNo) + 1 + i let name = 'output_0000' + no let imageFolder = path.join(define.project_path, `${sourceBookTask.bookId}/tmp/${name}`) await CheckFolderExistsOrCreate(imageFolder) // 创建对应的文件夹 let addOneBookTask = { id: uuidv4(), bookId: sourceBookTask.bookId, no: no, name: name, generateVideoPath: sourceBookTask.generateVideoPath, srtPath: sourceBookTask.srtPath, audioPath: sourceBookTask.audioPath, draftSrtStyle: sourceBookTask.draftSrtStyle, backgroundMusic: sourceBookTask.backgroundMusic, friendlyReminder: sourceBookTask.friendlyReminder, imageFolder: path.relative(define.project_path, imageFolder), status: sourceBookTask.status, errorMsg: sourceBookTask.errorMsg, updateTime: new Date(), createTime: new Date(), isAuto: sourceBookTask.isAuto, imageStyle: sourceBookTask.imageStyle, autoAnalyzeCharacter: sourceBookTask.autoAnalyzeCharacter, customizeImageStyle: sourceBookTask.customizeImageStyle, videoConfig: sourceBookTask.videoConfig, prefixPrompt: sourceBookTask.prefixPrompt, suffixPrompt: sourceBookTask.suffixPrompt, version: sourceBookTask.version, imageCategory: sourceBookTask.imageCategory, } as Book.SelectBookTask addBookTask.push(addOneBookTask) for (let j = 0; j < sourceBookTaskDetail.length; j++) { const element = sourceBookTaskDetail[j]; let outImagePath = undefined as string let subImagePath = [] as string[] if (copyImageType == CopyImageType.ALL) { // 直接全部复制 outImagePath = element.outImagePath subImagePath = element.subImagePath } else if (copyImageType == CopyImageType.ONE) { // 只复制对应的 let oldImage = element.subImagePath[i + 1] outImagePath = path.join(imageFolder, path.basename(element.outImagePath)) await CopyFileOrFolder(oldImage, outImagePath) subImagePath = [] } else if (copyImageType == CopyImageType.NONE) { outImagePath = undefined subImagePath = [] } else { throw new Error("无效的图片复制类型") } if (outImagePath) { // 单独处理一下显示的图片 let imageBaseName = path.basename(element.outImagePath); let newImageBaseName = path.join(define.project_path, `${sourceBookTask.bookId}/tmp/${name}/${imageBaseName}`) await CopyFileOrFolder(outImagePath, newImageBaseName) } // 处理SD设置 let sdConifg = undefined if (element.sdConifg) { let sdConifg = cloneDeep(element.sdConifg) if (sdConifg.webuiConfig) { let tempSdConfig = cloneDeep(sdConifg.webuiConfig); tempSdConfig.id = uuidv4() sdConifg.webuiConfig = tempSdConfig } } let reverseId = uuidv4() // 处理反推数据 let reverseMessage = [] as Book.ReversePrompt[] if (element.reversePrompt && element.reversePrompt.length > 0) { reverseMessage = cloneDeep(element.reversePrompt) for (let k = 0; k < reverseMessage.length; k++) { reverseMessage[k].id = uuidv4() reverseMessage[k].bookTaskDetailId = reverseId } } let addOneBookTaskDetail = { id: reverseId, no: element.no, name: element.name, bookId: sourceBookTask.bookId, bookTaskId: addOneBookTask.id, videoPath: path.relative(define.project_path, element.videoPath), word: element.word, oldImage: path.relative(define.project_path, element.oldImage), afterGpt: element.afterGpt, startTime: element.startTime, endTime: element.endTime, timeLimit: element.timeLimit, subValue: element.subValue, characterTags: element.characterTags && element.characterTags.length > 0 ? cloneDeep(element.characterTags) : [], gptPrompt: element.gptPrompt, outImagePath: path.relative(define.project_path, outImagePath), subImagePath: subImagePath || [], prompt: element.prompt, adetailer: element.adetailer, sdConifg: sdConifg, createTime: new Date(), updateTime: new Date(), audioPath: element.audioPath, subtitlePosition: element.subtitlePosition, status: element.status, reversePrompt: reverseMessage, imageLock: element.imageLock } as Book.SelectBookTaskDetail addBookTaskDetail.push(addOneBookTaskDetail) } } // 数据处理完毕,开始新增数据 // 将所有的复制才做,全部放在一个事务中 this.bookTaskService.transaction(() => { for (let i = 0; i < addBookTask.length; i++) { const element = addBookTask[i]; this.bookTaskService.realm.create('BookTask', element) } for (let i = 0; i < addBookTaskDetail.length; i++) { const element = addBookTaskDetail[i]; this.bookTaskDetailService.realm.create('BookTaskDetail', element) } }) // 全部创建完成 // 查找到数据,然后全部返回 let returnBookTask = this.bookTaskService.GetBookTaskData({ bookId: sourceBookTask.bookId }).data as Book.SelectBookTask[] return successMessage(returnBookTask, "复制小说任务成功", "BookBasic_CopyNewBookTask") } catch (error) { console.log(error) throw error } } //#endregion }