import Realm from 'realm' import { RealmBaseService } from '../base/realmBase' import { Book } from '@/define/model/book/book' import { BookTaskModel } from '../../model/bookTask' import { getProjectPath } from '@/main/service/option/optionCommonService' import { ImageCategory } from '@/define/data/imageData' import { JoinPath } from '@/define/Tools/file' import { BookTaskStatus } from '@/define/enum/bookEnum' export class BookTaskService extends RealmBaseService { static instance: BookTaskService | null = null declare realm: Realm private constructor() { super() } /** * 获取当前实例对象,为空则创建一个新的 * @returns */ public static async getInstance() { if (BookTaskService.instance === null) { BookTaskService.instance = new BookTaskService() await super.getInstance() } await BookTaskService.instance.open() return BookTaskService.instance } /** * 查询满足条件的小说子任务信息 * @param bookTaskCondition 查询条件 id,bookId,name,no,page, pageSize */ async GetBookTaskDataByCondition( bookTaskCondition: Book.QueryBookTaskCondition ): Promise { try { // 获取所有的小说数据,并进行时间降序排序 let bookTasks = this.realm.objects('BookTask') // 开始开始筛选 if (bookTaskCondition.id) { // 查询对应的小说ID的数据 bookTasks = bookTasks.filtered('id = $0', bookTaskCondition.id) } if (bookTaskCondition.bookId) { // 查询对应的小说ID的数据 bookTasks = bookTasks.filtered('bookId = $0', bookTaskCondition.bookId) } if (bookTaskCondition.name) { // 查询对应的小说ID的数据 bookTasks = bookTasks.filtered('name = $0', bookTaskCondition.name) } if (bookTaskCondition.no) { // 查询对应的小说ID的数据 bookTasks = bookTasks.filtered('no = $0', bookTaskCondition.no) } let bookTask_length = bookTasks.length // bookTasks = bookTasks.sorted('updateTime', true) // 判断是不是有page和pageSize,有的话对查询返回的信息做分页 if (bookTaskCondition.page && bookTaskCondition.pageSize) { bookTasks = bookTasks.slice( (bookTaskCondition.page - 1) * bookTaskCondition.pageSize, bookTaskCondition.page * bookTaskCondition.pageSize ) as unknown as Realm.Results } let projectPath: string = await getProjectPath() // 做一下数据转换 // 将realm对象数组转换为普通对象数组 // 将realm对象数组转换为普通对象数组,并处理异步操作 let res_bookTasks = Array.from(bookTasks).map((bookTask) => { // 直接操作普通对象 return { ...bookTask, imageStyle: bookTask.imageStyle ? Array.from(bookTask.imageStyle) : [], customizeImageStyle: bookTask.customizeImageStyle ? Array.from(bookTask.customizeImageStyle) : [], generateVideoPath: JoinPath(projectPath, bookTask.generateVideoPath), srtPath: JoinPath(projectPath, bookTask.srtPath), audioPath: JoinPath(projectPath, bookTask.audioPath), imageFolder: JoinPath(projectPath, bookTask.imageFolder), cacheImageList: bookTask.cacheImageList ? Array.from(bookTask.cacheImageList).map((item) => JoinPath(projectPath, item)) : [], imageCategory: bookTask.imageCategory ? bookTask.imageCategory : ImageCategory.Midjourney // 默认使用MJ出图 } as Book.SelectBookTask }) return { bookTasks: JSON.parse(JSON.stringify(res_bookTasks)), bookTaskLength: bookTask_length } as Book.QueryBookTaskConditionResponse } catch (error) { throw error } } /** * 通过ID获取小说批次任务的数据 * @param bookTaskId */ async GetBookTaskDataById(bookTaskId: string): Promise { try { if (bookTaskId == null) { throw new Error('小说任务ID不能为空') } let bookTasks = await this.GetBookTaskDataByCondition({ id: bookTaskId }) if (bookTasks.bookTasks.length <= 0) { throw new Error('未找到对应的小说任务') } else { return bookTasks.bookTasks[0] } } catch (error) { throw error } } /** * 修改小说批次任务的状态 * @param bookTaskId 小说批次任务Id * @param status 目标状态 */ ModifyBookTaskStatus(bookTaskId: string, status: BookTaskStatus, errorMsg?: string): void { try { this.transaction(() => { // 修改对应小说批次任务的状态 let bookTask = this.realm.objectForPrimaryKey('BookTask', bookTaskId) if (bookTask == null) { throw new Error('未找到对应的小说任务') } bookTask.status = status bookTask.updateTime = new Date() if (errorMsg != null) { bookTask.errorMsg = errorMsg } }) } catch (error) { throw error } } /** * 修改小说批次任务数据 * @param bookTaskId 小说批次任务ID * @param data 要修改的数据 */ async ModifyBookTaskDataById( bookTaskId: string, data: Book.SelectBookTask ): Promise { try { this.transaction(() => { let updateData = this.realm.objectForPrimaryKey('BookTask', bookTaskId) if (updateData == null) { throw new Error('未找到对应的小说任务详细信息') } // 开始修改 for (let key in data) { updateData[key] = data[key] } }) let res = await this.GetBookTaskDataById(bookTaskId) return res } catch (error) { throw error } } // 添加一条数据 async AddBookTask(bookTask: Book.SelectBookTask): Promise { try { // 新增 if (bookTask.bookId == '' || bookTask.bookId == null) { throw new Error('小说ID不能为空') } bookTask.id = crypto.randomUUID() // 获取当前bookID对应的最大的no let maxNo = this.realm.objects('BookTask').filtered('bookId = $0', bookTask.bookId).max('no') bookTask.no = maxNo == null ? 1 : Number(maxNo) + 1 bookTask.name = 'output_0000' + bookTask.no bookTask.status = BookTaskStatus.WAIT bookTask.updateTime = new Date() bookTask.createTime = new Date() this.realm.write(() => { this.realm.create('BookTask', bookTask) }) // 处理完毕,返回结果 let res = await this.GetBookTaskDataById(bookTask.id) return res } catch (error) { throw error } } /** * 获取最大的小说批次任务的编号 * @param bookId 小说ID */ async GetMaxBookTaskNo(bookId: string): Promise { let maxNo = this.realm.objects('BookTask').filtered('bookId = $0', bookId).max('no') let no = maxNo == null ? 1 : Number(maxNo) + 1 return no } /** * 重置小说批次数据,清除小说的详细信息 * @param bookTaskId 小说批次ID */ async ResetBookTaskDataById( bookTaskId: string, resetBase: boolean = true ): Promise { try { // 开始重置数据,先重置小说批次数据,在重置其他 this.transaction(() => { this.ResetBookTaskDataInfo(bookTaskId, resetBase) }) let res = await this.GetBookTaskDataById(bookTaskId) return res } catch (error) { throw error } } /** * 删除对应的小说批次数据 * @param bookTaskId 要删除的批次的ID */ DeleteBookTaskDataById(bookTaskId: string): void { try { this.transaction(() => { // 先调用清除数据的方法 this.ResetBookTaskDataInfo(bookTaskId) // 删除批次数据 let bookTask = this.realm.objectForPrimaryKey('BookTask', bookTaskId) if (bookTask == null) { throw new Error('未找到对应的小说任务,无法执行删除操作') } this.realm.delete(bookTask) }) } catch (error) { throw error } } /** 重置小说批次任务数据 */ private ResetBookTaskDataInfo(bookTaskId: string, resetBase: boolean = true) { try { let modifyBookTask = this.realm.objectForPrimaryKey('BookTask', bookTaskId) if (modifyBookTask == null) { throw new Error('未找到对应的小说批次任务,无法执行重置操作') } let book = this.realm.objectForPrimaryKey('Book', modifyBookTask.bookId) if (book == null) { throw new Error('未找到对应的小说,无法执行重置操作') } if (resetBase) { // 基础数据的重置 modifyBookTask.errorMsg = '' modifyBookTask.updateTime = new Date() modifyBookTask.imageStyle = [] modifyBookTask.autoAnalyzeCharacter = undefined modifyBookTask.customizeImageStyle = [] modifyBookTask.videoConfig = undefined modifyBookTask.prefixPrompt = undefined modifyBookTask.suffixPrompt = undefined modifyBookTask.subImageFolder = [] modifyBookTask.srtPath = book.srtPath ?? undefined modifyBookTask.audioPath = book.audioPath ?? undefined } // 继承小说的srt和配音文件 modifyBookTask.imageCategory = ImageCategory.Midjourney // 默认使用MJ出图 modifyBookTask.status = BookTaskStatus.WAIT // 开始删除 分镜信息 let bookTaskDetails = this.realm .objects('BookTaskDetail') .filtered('bookTaskId = $0', bookTaskId) // 开始删除数据 for (const bookTaskDetail of bookTaskDetails) { // 删除MJMessage if (bookTaskDetail.mjMessage) { this.realm.delete(bookTaskDetail.mjMessage) } if (bookTaskDetail.reversePrompt) { ;(bookTaskDetail.reversePrompt as any[]).forEach((item) => { this.realm.delete(item) }) } if (bookTaskDetail.sdConifg) { this.realm.delete(bookTaskDetail.sdConifg) } this.realm.delete(bookTaskDetail) } } catch (error) { throw error } } }