2025-08-19 14:33:59 +08:00
|
|
|
|
import { OperateBookType, PromptMergeType } from '@/define/enum/bookEnum'
|
|
|
|
|
|
import { Book } from '@/define/model/book/book'
|
|
|
|
|
|
import { errorMessage, SendReturnMessage, successMessage } from '@/public/generalTools'
|
|
|
|
|
|
|
|
|
|
|
|
import { isEmpty } from 'lodash'
|
|
|
|
|
|
import { AiReasonCommon } from '../../aiReason/aiReasonCommon'
|
|
|
|
|
|
import { DEFINE_STRING } from '@/define/ipcDefineString'
|
|
|
|
|
|
import { GeneralResponse } from '@/define/model/generalResponse'
|
|
|
|
|
|
import { ExecuteConcurrently } from '@/define/Tools/common'
|
|
|
|
|
|
import { OptionKeyName } from '@/define/enum/option'
|
|
|
|
|
|
import { optionSerialization } from '../../option/optionSerialization'
|
|
|
|
|
|
import { SettingModal } from '@/define/model/setting'
|
|
|
|
|
|
import { MJServiceHandle } from '@/main/service/mj/mjServiceHandle'
|
|
|
|
|
|
import { BookBasicHandle } from './bookBasicHandle'
|
|
|
|
|
|
import { PresetCategory } from '@/define/data/presetData'
|
|
|
|
|
|
import { ValidateJsonAndParse } from '@/define/Tools/validate'
|
|
|
|
|
|
import { BookTask } from '@/define/model/book/bookTask'
|
|
|
|
|
|
import { SDServiceHandle } from '../../sd/sdServiceHandle'
|
|
|
|
|
|
import { aiHandle } from '../../ai'
|
2025-09-04 16:58:42 +08:00
|
|
|
|
import { AICharacterAnalyseRequestData } from '@/define/data/aiData/aiPrompt/CharacterAndScene/aiCharacterAnalyseRequestData'
|
|
|
|
|
|
import { AISceneAnalyseRequestData } from '@/define/data/aiData/aiPrompt/CharacterAndScene/aiSceneAnalyseRequestData'
|
2025-08-19 14:33:59 +08:00
|
|
|
|
|
|
|
|
|
|
export class BookPromptHandle extends BookBasicHandle {
|
|
|
|
|
|
aiReasonCommon: AiReasonCommon
|
|
|
|
|
|
mjServiceHandle: MJServiceHandle
|
|
|
|
|
|
sdServiceHandle: SDServiceHandle
|
|
|
|
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
|
|
super()
|
|
|
|
|
|
this.aiReasonCommon = new AiReasonCommon()
|
|
|
|
|
|
this.mjServiceHandle = new MJServiceHandle()
|
|
|
|
|
|
this.sdServiceHandle = new SDServiceHandle()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 为小说分镜生成AI提示词
|
|
|
|
|
|
*
|
|
|
|
|
|
* 该方法根据操作类型获取相应的分镜数据,然后使用AI推理为每个分镜生成提示词。
|
|
|
|
|
|
* 支持三种操作模式:
|
|
|
|
|
|
* 1. 对整个小说任务的所有分镜进行处理(BOOKTASK)
|
|
|
|
|
|
* 2. 对单个指定分镜进行处理(BOOKTASKDETAIL)
|
|
|
|
|
|
* 3. 对指定分镜及其后续所有分镜进行处理(UNDERBOOKTASK)
|
|
|
|
|
|
*
|
|
|
|
|
|
* 生成过程中会实时向前端发送进度通知,并根据系统设置控制并发处理数量。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} id - 根据operateBookType不同,可能是小说任务ID或分镜ID
|
|
|
|
|
|
* @param {OperateBookType} operateBookType - 操作类型,决定处理范围
|
|
|
|
|
|
* @param {boolean} coverData - 是否覆盖已有提示词数据:
|
|
|
|
|
|
* true-处理所有分镜, false-只处理空白提示词的分镜
|
|
|
|
|
|
* @returns {Promise<SuccessItem | ErrorItem>} 操作结果,成功或失败的标准化响应
|
|
|
|
|
|
*
|
|
|
|
|
|
* @throws 如果找不到指定分镜数据或操作类型未知,将抛出异常
|
|
|
|
|
|
*
|
|
|
|
|
|
* @example
|
|
|
|
|
|
* // 为整个小说任务生成提示词,不覆盖已有数据
|
|
|
|
|
|
* const result = await bookPromptHandle.OriginalGetAiPrompt(
|
|
|
|
|
|
* "task-123",
|
|
|
|
|
|
* OperateBookType.BOOKTASK,
|
|
|
|
|
|
* false
|
|
|
|
|
|
* );
|
|
|
|
|
|
*/
|
|
|
|
|
|
OriginalGetAiPrompt = async (
|
|
|
|
|
|
id: string,
|
|
|
|
|
|
operateBookType: OperateBookType,
|
|
|
|
|
|
coverData: boolean
|
|
|
|
|
|
): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let bookTask: Book.SelectBookTask = {} as Book.SelectBookTask
|
|
|
|
|
|
let bookTaskDetails: Book.SelectBookTaskDetail[] = []
|
|
|
|
|
|
let allBookTaskDetails: Book.SelectBookTaskDetail[] = []
|
|
|
|
|
|
|
|
|
|
|
|
await this.InitBookBasicHandle()
|
|
|
|
|
|
if (operateBookType == OperateBookType.BOOKTASK) {
|
|
|
|
|
|
bookTask = await this.bookTaskService.GetBookTaskDataById(id)
|
|
|
|
|
|
allBookTaskDetails = await this.bookTaskDetailService.GetBookTaskDetailDataByCondition({
|
|
|
|
|
|
bookTaskId: id
|
|
|
|
|
|
})
|
|
|
|
|
|
if (!coverData) {
|
|
|
|
|
|
// 不覆盖数据,只推理空白提示词
|
|
|
|
|
|
bookTaskDetails = allBookTaskDetails.filter((item) => isEmpty(item.gptPrompt))
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 不覆盖,就是全部
|
|
|
|
|
|
bookTaskDetails = allBookTaskDetails
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (operateBookType == OperateBookType.BOOKTASKDETAIL) {
|
|
|
|
|
|
let singleBookTaskDetail = await this.bookTaskDetailService.GetBookTaskDetailDataById(id)
|
|
|
|
|
|
if (singleBookTaskDetail == null) {
|
|
|
|
|
|
throw new Error('没有找到要推理的分镜数据,请检查ID是否正确')
|
|
|
|
|
|
}
|
|
|
|
|
|
bookTask = await this.bookTaskService.GetBookTaskDataById(
|
|
|
|
|
|
singleBookTaskDetail.bookTaskId as string
|
|
|
|
|
|
)
|
|
|
|
|
|
bookTaskDetails = [singleBookTaskDetail]
|
|
|
|
|
|
} else if (operateBookType == OperateBookType.UNDERBOOKTASK) {
|
|
|
|
|
|
let singleBookTaskDetail = await this.bookTaskDetailService.GetBookTaskDetailDataById(id)
|
|
|
|
|
|
if (singleBookTaskDetail == null) {
|
|
|
|
|
|
throw new Error('没有找到要推理的分镜数据,请检查ID是否正确')
|
|
|
|
|
|
}
|
|
|
|
|
|
bookTask = await this.bookTaskService.GetBookTaskDataById(
|
|
|
|
|
|
singleBookTaskDetail.bookTaskId as string
|
|
|
|
|
|
)
|
|
|
|
|
|
// 获取全部的分镜数据
|
|
|
|
|
|
allBookTaskDetails = await this.bookTaskDetailService.GetBookTaskDetailDataByCondition({
|
|
|
|
|
|
bookTaskId: bookTask.id
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 只要当前行往下的数据
|
|
|
|
|
|
for (let i = 0; i < allBookTaskDetails.length; i++) {
|
|
|
|
|
|
const element = allBookTaskDetails[i]
|
|
|
|
|
|
if (bookTaskDetails == undefined) {
|
|
|
|
|
|
bookTaskDetails = []
|
|
|
|
|
|
}
|
|
|
|
|
|
if (i + 1 >= (singleBookTaskDetail.no as number)) {
|
|
|
|
|
|
bookTaskDetails.push(element)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error('未知的操作类型')
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!allBookTaskDetails || allBookTaskDetails.length <= 0) {
|
|
|
|
|
|
allBookTaskDetails = await this.bookTaskDetailService.GetBookTaskDetailDataByCondition({
|
|
|
|
|
|
bookTaskId: bookTask.id
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (bookTaskDetails.length <= 0) {
|
|
|
|
|
|
throw new Error('没有找到要推理的分镜数据')
|
|
|
|
|
|
}
|
|
|
|
|
|
let generalSettingOption = this.optionRealmService.GetOptionByKey(
|
|
|
|
|
|
OptionKeyName.Software.GeneralSetting
|
|
|
|
|
|
)
|
|
|
|
|
|
let generalSetting = optionSerialization<SettingModal.GeneralSettings>(
|
|
|
|
|
|
generalSettingOption,
|
|
|
|
|
|
'‘设置 -> 通用设置’'
|
|
|
|
|
|
)
|
|
|
|
|
|
let tasks = [] as Array<() => Promise<any>>
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前task的角色和场景数据
|
|
|
|
|
|
let autoAnalyzeCharacter = bookTask.autoAnalyzeCharacter ?? '{}'
|
|
|
|
|
|
let autoAnalyzeCharacterData =
|
|
|
|
|
|
ValidateJsonAndParse<BookTask.BookTaskCharacterAndScene>(autoAnalyzeCharacter)
|
|
|
|
|
|
let characterData = autoAnalyzeCharacterData[PresetCategory.Character] ?? []
|
|
|
|
|
|
let sceneData = autoAnalyzeCharacterData[PresetCategory.Scene] ?? []
|
|
|
|
|
|
let characterString = ''
|
|
|
|
|
|
let sceneString = ''
|
2025-09-04 16:58:42 +08:00
|
|
|
|
|
2025-08-19 14:33:59 +08:00
|
|
|
|
if (characterData.length > 0) {
|
|
|
|
|
|
characterString = characterData.map((item) => item.name + ':' + item.prompt).join('\n')
|
2025-09-04 16:58:42 +08:00
|
|
|
|
characterString = '角色设定:' + '\n' + characterString
|
2025-08-19 14:33:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (sceneData.length > 0) {
|
|
|
|
|
|
sceneString = sceneData.map((item) => item.name + ':' + item.prompt).join('\n')
|
2025-09-04 16:58:42 +08:00
|
|
|
|
sceneString = '场景设定:' + '\n' + sceneString
|
2025-08-19 14:33:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 添加异步任务
|
|
|
|
|
|
for (let i = 0; i < bookTaskDetails.length; i++) {
|
|
|
|
|
|
const element = bookTaskDetails[i]
|
|
|
|
|
|
tasks.push(async () => {
|
|
|
|
|
|
let content = await this.aiReasonCommon.OriginalInferencePrompt(
|
|
|
|
|
|
element,
|
|
|
|
|
|
allBookTaskDetails,
|
|
|
|
|
|
15, // 上下文关联行数
|
2025-09-04 16:58:42 +08:00
|
|
|
|
characterString,
|
|
|
|
|
|
sceneString
|
2025-08-19 14:33:59 +08:00
|
|
|
|
)
|
2025-09-04 16:58:42 +08:00
|
|
|
|
console.log(element.afterGpt, content)
|
2025-08-19 14:33:59 +08:00
|
|
|
|
// 修改推理出来的数据
|
|
|
|
|
|
await this.bookTaskDetailService.ModifyBookTaskDetailById(element.id as string, {
|
|
|
|
|
|
gptPrompt: content
|
|
|
|
|
|
})
|
|
|
|
|
|
// 每次完成,都要向前端返回信息
|
|
|
|
|
|
SendReturnMessage(
|
|
|
|
|
|
{
|
|
|
|
|
|
code: 1,
|
|
|
|
|
|
id: element.id as string,
|
|
|
|
|
|
data: {
|
|
|
|
|
|
content: content,
|
|
|
|
|
|
progress: {
|
|
|
|
|
|
current: i,
|
|
|
|
|
|
total: bookTaskDetails.length
|
|
|
|
|
|
} as GeneralResponse.ProgressResponse
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
DEFINE_STRING.BOOK.ORIGINAL_GET_AI_PROMPT_RETURN
|
|
|
|
|
|
)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
// 分批次执行异步任务
|
|
|
|
|
|
await ExecuteConcurrently(tasks, global.am.isPro ? (generalSetting.concurrency ?? 1) : 1)
|
|
|
|
|
|
// 执行完毕
|
|
|
|
|
|
return successMessage(null, '推理所有数据完成', 'BookPrompt_OriginalGetPrompt')
|
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
|
// 处理错误,返回错误信息
|
|
|
|
|
|
return errorMessage(
|
|
|
|
|
|
`获取小说子任务详细数据失败,失败原因如下:${error.message}`,
|
|
|
|
|
|
'BookPromptHandle_OriginalGetAiPrompt'
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AIStoryboardMerge = async (bookTaskId: string, type: BookTask.StoryboardMergeType) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
let res = await aiHandle.AIStoryboardMerge(bookTaskId, type)
|
|
|
|
|
|
return successMessage(res, 'AI分镜头合并成功', 'BookPromptHandle_AIStoryboardMerge')
|
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
|
return errorMessage(
|
|
|
|
|
|
`AI分镜头合并失败,失败原因如下:${error.message}`,
|
|
|
|
|
|
'BookPromptHandle_AIStoryboardMerge'
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 合并提示词
|
|
|
|
|
|
*
|
|
|
|
|
|
* 该方法根据提供的合并类型(MJ或SD),将分镜中的提示词按照规则进行合并处理。
|
|
|
|
|
|
* 支持两种合并类型:
|
|
|
|
|
|
* - MJ_MERGE: 使用MidJourney规则合并提示词
|
|
|
|
|
|
* - SD_MERGE: 使用Stable Diffusion规则合并提示词
|
|
|
|
|
|
*
|
|
|
|
|
|
* 合并操作支持不同的处理范围,由operateBookType参数决定:
|
|
|
|
|
|
* - BOOKTASK: 处理整个小说任务中的所有分镜
|
|
|
|
|
|
* - BOOKTASKDETAIL: 仅处理单个指定分镜
|
|
|
|
|
|
* - UNDERBOOKTASK: 处理指定分镜及其后续所有分镜
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} id - 根据operateBookType不同,可能是小说任务ID或分镜ID
|
|
|
|
|
|
* @param {PromptMergeType} type - 合并类型,决定使用哪种规则合并提示词
|
|
|
|
|
|
* @param {OperateBookType} operateBookType - 操作类型,决定处理范围
|
|
|
|
|
|
* @returns {Promise<SuccessItem | ErrorItem>} 操作结果,成功或失败的标准化响应
|
|
|
|
|
|
*
|
|
|
|
|
|
* @throws {Error} 如果合并类型未知,将抛出异常
|
|
|
|
|
|
*
|
|
|
|
|
|
* @example
|
|
|
|
|
|
* // 使用MidJourney规则合并单个分镜的提示词
|
|
|
|
|
|
* const result = await bookPromptHandle.MergePrompt(
|
|
|
|
|
|
* "detail-123",
|
|
|
|
|
|
* PromptMergeType.MJ_MERGE,
|
|
|
|
|
|
* OperateBookType.BOOKTASKDETAIL
|
|
|
|
|
|
* );
|
|
|
|
|
|
*/
|
|
|
|
|
|
MergePrompt = async (
|
|
|
|
|
|
id: string,
|
|
|
|
|
|
type: PromptMergeType,
|
|
|
|
|
|
operateBookType: OperateBookType
|
|
|
|
|
|
): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (type == PromptMergeType.MJ_MERGE) {
|
|
|
|
|
|
return await this.mjServiceHandle.MergeMJPrompt(id, operateBookType)
|
|
|
|
|
|
} else if (type == PromptMergeType.SD_MERGE) {
|
|
|
|
|
|
return await this.sdServiceHandle.MergeSDPrompt(id, operateBookType)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error('未知的合并模式,请检查')
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
|
return errorMessage(
|
|
|
|
|
|
'合并提示词失败,错误信息如下:' + error.message,
|
|
|
|
|
|
'ReverseBook_MergePrompt'
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 自动分析书籍任务中的角色或场景
|
|
|
|
|
|
*
|
|
|
|
|
|
* 该方法使用AI技术分析书籍任务中的所有分镜文本,自动识别并提取角色或场景信息。
|
|
|
|
|
|
* 处理过程包括合并所有分镜文本、调用AI分析、解析返回结果并格式化为结构化数据。
|
|
|
|
|
|
* 分析结果会更新到书籍任务的autoAnalyzeCharacter字段中,以JSON格式存储。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} bookTaskId - 要分析的书籍任务ID
|
|
|
|
|
|
* @param {PresetCategory} type - 分析类型,必须是PresetCategory.Character(角色)或PresetCategory.Scene(场景)
|
|
|
|
|
|
*
|
|
|
|
|
|
* @returns {Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem>}
|
|
|
|
|
|
* 成功时返回分析得到的角色或场景数据对象数组,失败时返回错误信息
|
|
|
|
|
|
*
|
|
|
|
|
|
* @throws {Error} 当分析类型无效、找不到书籍任务数据或分镜数据为空时抛出错误
|
|
|
|
|
|
*
|
|
|
|
|
|
* @example
|
|
|
|
|
|
* // 分析书籍任务中的角色
|
|
|
|
|
|
* const characterResult = await bookPromptHandle.AutoAnalyzeCharacterOrScene(
|
|
|
|
|
|
* "task-123",
|
|
|
|
|
|
* PresetCategory.Character
|
|
|
|
|
|
* );
|
|
|
|
|
|
*
|
|
|
|
|
|
* // 分析书籍任务中的场景
|
|
|
|
|
|
* const sceneResult = await bookPromptHandle.AutoAnalyzeCharacterOrScene(
|
|
|
|
|
|
* "task-123",
|
|
|
|
|
|
* PresetCategory.Scene
|
|
|
|
|
|
* );
|
|
|
|
|
|
*/
|
|
|
|
|
|
AutoAnalyzeCharacterOrScene = async (bookTaskId: string, type: PresetCategory) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (type != PresetCategory.Character && type != PresetCategory.Scene) {
|
|
|
|
|
|
throw new Error('分析的类型只能是角色或场景,请检查')
|
|
|
|
|
|
}
|
|
|
|
|
|
await this.InitBookBasicHandle()
|
|
|
|
|
|
|
|
|
|
|
|
let bookTask = await this.bookTaskService.GetBookTaskDataById(bookTaskId)
|
|
|
|
|
|
let bookTaskDetails = await this.bookTaskDetailService.GetBookTaskDetailDataByCondition({
|
|
|
|
|
|
bookTaskId: bookTaskId
|
|
|
|
|
|
})
|
|
|
|
|
|
if (bookTaskDetails.length <= 0) {
|
|
|
|
|
|
throw new Error('没有找到要分析的分镜数据,请先导入文案或者时srt!')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let words = bookTaskDetails
|
|
|
|
|
|
.map((item) => {
|
|
|
|
|
|
return item.afterGpt
|
|
|
|
|
|
})
|
|
|
|
|
|
.join('\r\n')
|
|
|
|
|
|
|
2025-09-04 16:58:42 +08:00
|
|
|
|
let requestData: OpenAIRequest.Request
|
2025-08-19 14:33:59 +08:00
|
|
|
|
if (type == PresetCategory.Character) {
|
2025-09-04 16:58:42 +08:00
|
|
|
|
requestData = AICharacterAnalyseRequestData
|
2025-08-19 14:33:59 +08:00
|
|
|
|
} else if (type == PresetCategory.Scene) {
|
2025-09-04 16:58:42 +08:00
|
|
|
|
requestData = AISceneAnalyseRequestData
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error('未知的分析类型,请检查')
|
2025-08-19 14:33:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-04 16:58:42 +08:00
|
|
|
|
requestData.messages = this.aiReasonCommon.replaceMessageObject(requestData.messages, {
|
|
|
|
|
|
textContent: words
|
|
|
|
|
|
})
|
2025-08-19 14:33:59 +08:00
|
|
|
|
await this.aiReasonCommon.GetAISetting()
|
2025-09-04 16:58:42 +08:00
|
|
|
|
delete requestData.model
|
|
|
|
|
|
|
|
|
|
|
|
let content = await this.aiReasonCommon.FetchGpt(requestData.messages, requestData)
|
2025-08-19 14:33:59 +08:00
|
|
|
|
|
|
|
|
|
|
let autoAnalyzeCharacter = bookTask.autoAnalyzeCharacter ?? '{}'
|
|
|
|
|
|
let autoAnalyzeCharacterData =
|
|
|
|
|
|
ValidateJsonAndParse<BookTask.BookTaskCharacterAndScene>(autoAnalyzeCharacter)
|
|
|
|
|
|
let returnData = content.split('\n').filter((item) => !isEmpty(item))
|
|
|
|
|
|
let newData: BookTask.BookTaskCharacterAndSceneObject[] = []
|
|
|
|
|
|
for (let i = 0; i < returnData.length; i++) {
|
|
|
|
|
|
const element = returnData[i]
|
|
|
|
|
|
let splitData = element.split('.')
|
|
|
|
|
|
if (splitData.length < 3) {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
let tempData = {
|
|
|
|
|
|
no: Number(splitData[0]),
|
|
|
|
|
|
id: crypto.randomUUID(),
|
|
|
|
|
|
name: splitData[1],
|
|
|
|
|
|
prompt: splitData[2]
|
|
|
|
|
|
} as BookTask.BookTaskCharacterAndSceneObject
|
|
|
|
|
|
newData.push(tempData)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (type == PresetCategory.Character) {
|
|
|
|
|
|
autoAnalyzeCharacterData[PresetCategory.Character] = newData
|
|
|
|
|
|
} else if (type == PresetCategory.Scene) {
|
|
|
|
|
|
// 场景数据
|
|
|
|
|
|
autoAnalyzeCharacterData[PresetCategory.Scene] = newData
|
|
|
|
|
|
}
|
|
|
|
|
|
// 重新写入
|
|
|
|
|
|
await this.bookTaskService.ModifyBookTaskDataById(bookTaskId, {
|
|
|
|
|
|
autoAnalyzeCharacter: JSON.stringify(autoAnalyzeCharacterData)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
return successMessage(
|
|
|
|
|
|
autoAnalyzeCharacterData,
|
|
|
|
|
|
'自动分析角色或场景成功',
|
|
|
|
|
|
'ReverseBook_AutoAnalyzeCharacterOrScene'
|
|
|
|
|
|
)
|
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
|
return errorMessage(
|
|
|
|
|
|
'自动分析角色或场景失败,错误信息如下:' + error.message,
|
|
|
|
|
|
'ReverseBook_AutoAnalyzeCharacterOrScene'
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|