2025-08-19 14:33:59 +08:00
|
|
|
|
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'
|
2025-09-04 16:58:42 +08:00
|
|
|
|
import { CheckFolderExistsOrCreate, CopyFileOrFolder, JoinPath } from '@/define/Tools/file'
|
|
|
|
|
|
import { BookTaskStatus, CopyImageType } from '@/define/enum/bookEnum'
|
|
|
|
|
|
import path from 'path'
|
|
|
|
|
|
import { ImageToVideoModels } from '@/define/enum/video'
|
|
|
|
|
|
import { cloneDeep, isEmpty } from 'lodash'
|
2025-08-19 14:33:59 +08:00
|
|
|
|
|
|
|
|
|
|
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<Book.QueryBookTaskConditionResponse> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 获取所有的小说数据,并进行时间降序排序
|
|
|
|
|
|
let bookTasks = this.realm.objects<BookTaskModel>('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<BookTaskModel>
|
|
|
|
|
|
}
|
|
|
|
|
|
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<Book.SelectBookTask> {
|
|
|
|
|
|
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<Book.SelectBookTask> {
|
|
|
|
|
|
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<Book.SelectBookTask> {
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-04 16:58:42 +08:00
|
|
|
|
|
|
|
|
|
|
async CopyNewBookTask(
|
|
|
|
|
|
sourceBookTask: Book.SelectBookTask,
|
|
|
|
|
|
sourceBookTaskDetail: Book.SelectBookTaskDetail[],
|
|
|
|
|
|
copyCount: number,
|
|
|
|
|
|
copyImageType: CopyImageType
|
|
|
|
|
|
) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let addBookTask = [] as Book.SelectBookTask[]
|
|
|
|
|
|
let addBookTaskDetail = [] as Book.SelectBookTaskDetail[]
|
|
|
|
|
|
let book = this.realm.objectForPrimaryKey('Book', sourceBookTask.bookId as string)
|
|
|
|
|
|
if (book == null) {
|
|
|
|
|
|
throw new Error('未找到对应的小说')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let projectPath = await getProjectPath()
|
|
|
|
|
|
// 先处理文件夹的创建,包括小说任务的和小说任务分镜的
|
|
|
|
|
|
for (let i = 0; i < copyCount; i++) {
|
|
|
|
|
|
let no = this.GetMaxBookTaskNo(sourceBookTask.bookId as string) + i
|
|
|
|
|
|
let name = book.name + '_0000' + no
|
|
|
|
|
|
let imageFolder = path.join(projectPath, `${sourceBookTask.bookId}/tmp/${name}`)
|
|
|
|
|
|
await CheckFolderExistsOrCreate(imageFolder)
|
|
|
|
|
|
// 创建对应的文件夹
|
|
|
|
|
|
let addOneBookTask = {
|
|
|
|
|
|
id: crypto.randomUUID(),
|
|
|
|
|
|
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(projectPath, 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,
|
|
|
|
|
|
videoCategory: sourceBookTask.videoCategory ?? ImageToVideoModels.MJ_VIDEO,
|
|
|
|
|
|
openVideoGenerate:
|
|
|
|
|
|
sourceBookTask.openVideoGenerate == null ? false : sourceBookTask.openVideoGenerate
|
|
|
|
|
|
} as Book.SelectBookTask
|
|
|
|
|
|
|
|
|
|
|
|
addBookTask.push(addOneBookTask)
|
|
|
|
|
|
|
|
|
|
|
|
for (let j = 0; j < sourceBookTaskDetail.length; j++) {
|
|
|
|
|
|
const element = sourceBookTaskDetail[j]
|
|
|
|
|
|
|
|
|
|
|
|
let outImagePath: string | undefined
|
|
|
|
|
|
let subImagePath: string[] | undefined
|
|
|
|
|
|
|
|
|
|
|
|
if (element.outImagePath == null || isEmpty(element.outImagePath)) {
|
|
|
|
|
|
throw new Error('部分分镜的输出图片路径为空')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (copyImageType == CopyImageType.ALL) {
|
|
|
|
|
|
// 直接全部复制
|
|
|
|
|
|
outImagePath = element.outImagePath
|
|
|
|
|
|
subImagePath = element.subImagePath
|
|
|
|
|
|
} else if (copyImageType == CopyImageType.ONE) {
|
|
|
|
|
|
if (!element.subImagePath || element.subImagePath.length <= 1) {
|
|
|
|
|
|
throw new Error('部分分镜的子图片路径数量不足或为空')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 只复制对应的
|
|
|
|
|
|
let oldImage = element.subImagePath[i + 1]
|
|
|
|
|
|
outImagePath = path.join(imageFolder, path.basename(element.outImagePath as string))
|
|
|
|
|
|
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(
|
|
|
|
|
|
projectPath,
|
|
|
|
|
|
`${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 = crypto.randomUUID()
|
|
|
|
|
|
sdConifg.webuiConfig = tempSdConfig
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let reverseId = crypto.randomUUID()
|
|
|
|
|
|
// 处理反推数据
|
|
|
|
|
|
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 = crypto.randomUUID()
|
|
|
|
|
|
reverseMessage[k].bookTaskDetailId = reverseId
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let addOneBookTaskDetail = {} as Book.SelectBookTaskDetail
|
|
|
|
|
|
addOneBookTaskDetail.id = reverseId
|
|
|
|
|
|
addOneBookTaskDetail.no = element.no
|
|
|
|
|
|
addOneBookTaskDetail.name = element.name
|
|
|
|
|
|
addOneBookTaskDetail.bookId = sourceBookTask.bookId
|
|
|
|
|
|
addOneBookTaskDetail.bookTaskId = addOneBookTask.id
|
|
|
|
|
|
addOneBookTaskDetail.videoPath = element.videoPath
|
|
|
|
|
|
? path.relative(projectPath, element.videoPath)
|
|
|
|
|
|
: undefined
|
|
|
|
|
|
addOneBookTaskDetail.word = element.word
|
|
|
|
|
|
addOneBookTaskDetail.oldImage = element.oldImage
|
|
|
|
|
|
? path.relative(projectPath, element.oldImage)
|
|
|
|
|
|
: undefined
|
|
|
|
|
|
addOneBookTaskDetail.afterGpt = element.afterGpt
|
|
|
|
|
|
addOneBookTaskDetail.startTime = element.startTime
|
|
|
|
|
|
addOneBookTaskDetail.endTime = element.endTime
|
|
|
|
|
|
addOneBookTaskDetail.timeLimit = element.timeLimit
|
|
|
|
|
|
addOneBookTaskDetail.subValue = (
|
|
|
|
|
|
element.subValue && element.subValue.length > 0
|
|
|
|
|
|
? JSON.stringify(element.subValue)
|
|
|
|
|
|
: undefined
|
|
|
|
|
|
) as string
|
|
|
|
|
|
addOneBookTaskDetail.characterTags =
|
|
|
|
|
|
element.characterTags && element.characterTags.length > 0
|
|
|
|
|
|
? cloneDeep(element.characterTags)
|
|
|
|
|
|
: []
|
|
|
|
|
|
addOneBookTaskDetail.gptPrompt = element.gptPrompt
|
|
|
|
|
|
addOneBookTaskDetail.outImagePath = outImagePath
|
|
|
|
|
|
? path.relative(projectPath, outImagePath)
|
|
|
|
|
|
: undefined
|
|
|
|
|
|
addOneBookTaskDetail.subImagePath = subImagePath || []
|
|
|
|
|
|
addOneBookTaskDetail.prompt = element.prompt
|
|
|
|
|
|
addOneBookTaskDetail.adetailer = element.adetailer
|
|
|
|
|
|
addOneBookTaskDetail.sdConifg = sdConifg
|
|
|
|
|
|
addOneBookTaskDetail.createTime = new Date()
|
|
|
|
|
|
addOneBookTaskDetail.updateTime = new Date()
|
|
|
|
|
|
addOneBookTaskDetail.audioPath = element.audioPath
|
|
|
|
|
|
addOneBookTaskDetail.subtitlePosition = element.subtitlePosition
|
|
|
|
|
|
addOneBookTaskDetail.status = element.status
|
|
|
|
|
|
addOneBookTaskDetail.reversePrompt = reverseMessage
|
|
|
|
|
|
addOneBookTaskDetail.imageLock = false // 默认不锁定
|
|
|
|
|
|
addBookTaskDetail.push(addOneBookTaskDetail)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
throw error
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-19 14:33:59 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取最大的小说批次任务的编号
|
|
|
|
|
|
* @param bookId 小说ID
|
|
|
|
|
|
*/
|
2025-09-04 16:58:42 +08:00
|
|
|
|
GetMaxBookTaskNo(bookId: string): number {
|
2025-08-19 14:33:59 +08:00
|
|
|
|
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<Book.SelectBookTask> {
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|