V3.2.0
修复聚合推文剪映抽帧时,导入srt没有输入 (聚合推文) SD 反推,MJ反推添加单句洗稿功能 (聚合推文)小说任务列表,添加进入出图文件夹的菜单 (聚合推文)新增一键出图 (聚合推文)新增默认出图方式设置, 5.1只对原创生效,SD反推默认是SD,MJ反推默认是MJ 5.2添加批次的默认出图方式同 a点说明,但是选择了 选择旧批次,新批次的默认出图方式会继承 后台任务,完成后台任务的可视化界面 (聚合推文)小说详情界面,添加小说和批次名称显示
This commit is contained in:
parent
22cfe65dde
commit
51deef0c09
@ -17,7 +17,8 @@ export default defineConfig({
|
||||
renderer: {
|
||||
resolve: {
|
||||
alias: {
|
||||
'@renderer': resolve('src/renderer/src')
|
||||
'@renderer': resolve('src/renderer/src'),
|
||||
"@" : resolve('src/'),
|
||||
}
|
||||
},
|
||||
plugins: [vue(), Jsx()]
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "laitool",
|
||||
"version": "3.1.9",
|
||||
"version": "3.2.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "laitool",
|
||||
"version": "3.1.9",
|
||||
"version": "3.2.0",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@alicloud/alimt20181012": "^1.2.0",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "laitool",
|
||||
"version": "3.1.9",
|
||||
"version": "3.2.0",
|
||||
"description": "An AI tool for image processing, video processing, and other functions.",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "laitool.cn",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -205,7 +205,7 @@ export class BookService extends BaseRealmService {
|
||||
} else if (book.type == BookType.MJ_REVERSE) {
|
||||
imageCategory = BookImageCategory.MJ
|
||||
} else if (book.type == BookType.ORIGINAL) {
|
||||
imageCategory = BookImageCategory.MJ
|
||||
imageCategory = global.config.defaultImageMode
|
||||
} else {
|
||||
throw new Error('未知的小说类型')
|
||||
}
|
||||
|
||||
@ -104,6 +104,9 @@ const BOOK = {
|
||||
*/
|
||||
GET_IMAGE_URL_AND_DOWNLOAD: "GET_IMAGE_URL_AND_DOWNLOAD",
|
||||
|
||||
/** 添加一键生图后台任务 */
|
||||
GENERATE_ALL_TASK_IMAGE: "GENERATE_ALL_TASK_IMAGE",
|
||||
|
||||
//#endregion
|
||||
|
||||
COMPUTE_STORYBOARD: 'COMPUTE_STORYBOARD',
|
||||
|
||||
@ -3,6 +3,7 @@ import TASK from "./taskDefineString"
|
||||
import TTS from "./ttsDefineString"
|
||||
import SETTING from "./settingDefineString"
|
||||
import BOOK from "./bookDefineString"
|
||||
import WRITE from "./writeDefineString"
|
||||
|
||||
export const DEFINE_STRING = {
|
||||
SYSTEM: SYSTEM,
|
||||
@ -10,6 +11,7 @@ export const DEFINE_STRING = {
|
||||
TTS: TTS,
|
||||
BOOK: BOOK,
|
||||
SETTING: SETTING,
|
||||
WRITE: WRITE,
|
||||
SHOW_GLOBAL_MESSAGE: "SHOW_GLOBAL_MESSAGE",
|
||||
SHOW_GLOBAL_MAIN_NOTIFICATION: 'SHOW_GLOBAL_MAIN_NOTIFICATION',
|
||||
OPEN_DEV_TOOLS_PASSWORD: 'OPEN_DEV_TOOLS_PASSWORD',
|
||||
@ -246,14 +248,6 @@ export const DEFINE_STRING = {
|
||||
*/
|
||||
GET_SCENE_PRESET: "GET_SCENE_PRESET"
|
||||
},
|
||||
WRITE: {
|
||||
GET_WRITE_CONFIG: 'GET_WRITE_CONFIG',
|
||||
SAVE_WRITE_CONFIG: 'SAVE_WRITE_CONFIG',
|
||||
ACTION_START: 'ACTION_START',
|
||||
GET_SUBTITLE_SETTING: "GET_SUBTITLE_SETTING",
|
||||
RESET_SUBTITLE_SETTING: "RESET_SUBTITLE_SETTING",
|
||||
SAVE_SUBTITLE_SETTING: "SAVE_SUBTITLE_SETTING",
|
||||
},
|
||||
DB: {
|
||||
UPDATE_BOOK_TASK_DATA: "UPDATE_BOOK_TASK_DATA",
|
||||
UPDATE_BOOK_TASK_DETAIL_DATA: "UPDATE_BOOK_TASK_DETAIL_DATA",
|
||||
|
||||
@ -9,6 +9,9 @@ const TASK = {
|
||||
/** 获取等待中的任务 */
|
||||
GET_ALL_STATUS_TASK_COUNT: "GET_ALL_STATUS_TASK_COUNT",
|
||||
|
||||
/** 获取后台任务的集合,分页 */
|
||||
GET_BACK_TASK_COLLECTION: "GET_BACK_TASK_COLLECTION",
|
||||
|
||||
};
|
||||
|
||||
export default TASK;
|
||||
|
||||
15
src/define/define_string/writeDefineString.ts
Normal file
15
src/define/define_string/writeDefineString.ts
Normal file
@ -0,0 +1,15 @@
|
||||
const WRITE = {
|
||||
GET_WRITE_CONFIG: 'GET_WRITE_CONFIG',
|
||||
SAVE_WRITE_CONFIG: 'SAVE_WRITE_CONFIG',
|
||||
ACTION_START: 'ACTION_START',
|
||||
GET_SUBTITLE_SETTING: "GET_SUBTITLE_SETTING",
|
||||
RESET_SUBTITLE_SETTING: "RESET_SUBTITLE_SETTING",
|
||||
SAVE_SUBTITLE_SETTING: "SAVE_SUBTITLE_SETTING",
|
||||
|
||||
/** 生成洗稿后文案 */
|
||||
GENERATE_AFTER_GPT_WORD: "GENERATE_AFTER_GPT_WORD",
|
||||
/** 生成洗稿后文案返回数据,前端接收 */
|
||||
GENERATE_AFTER_GPT_WORD_RESPONSE: "GENERATE_AFTER_GPT_WORD_RESPONSE"
|
||||
}
|
||||
|
||||
export default WRITE
|
||||
@ -282,3 +282,144 @@ export enum BookTagSelectType {
|
||||
// 标签
|
||||
TAG = 'tag'
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据Key返回指定的后台任务类型的label
|
||||
* @param key
|
||||
* @returns
|
||||
*/
|
||||
export function GetBookBackTaskTypeLabel(key: string) {
|
||||
switch (key) {
|
||||
case BookBackTaskType.STORYBOARD:
|
||||
return '分镜计算';
|
||||
case BookBackTaskType.SPLIT:
|
||||
return '分割视频';
|
||||
case BookBackTaskType.AUDIO:
|
||||
return '提取音频';
|
||||
case BookBackTaskType.RECOGNIZE:
|
||||
return '识别字幕';
|
||||
case BookBackTaskType.FRAME:
|
||||
return '抽帧';
|
||||
case BookBackTaskType.MJ_REVERSE:
|
||||
return 'MJ反推';
|
||||
case BookBackTaskType.SD_REVERSE:
|
||||
return 'SD反推';
|
||||
case BookBackTaskType.MJ_IMAGE:
|
||||
return 'MJ生成图片';
|
||||
case BookBackTaskType.SD_IMAGE:
|
||||
return 'SD生成图片';
|
||||
case BookBackTaskType.FLUX_FORGE_IMAGE:
|
||||
return 'flux forge生成图片';
|
||||
case BookBackTaskType.FLUX_API_IMAGE:
|
||||
return 'flux api生成图片';
|
||||
case BookBackTaskType.D3_IMAGE:
|
||||
return 'D3生成图片';
|
||||
case BookBackTaskType.HD:
|
||||
return '高清';
|
||||
case BookBackTaskType.COMPOSING:
|
||||
return '合成视频';
|
||||
case BookBackTaskType.INFERENCE:
|
||||
return '推理';
|
||||
case BookBackTaskType.TRANSLATE:
|
||||
return '翻译';
|
||||
default:
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据Key返回指定的后台任务状态的label
|
||||
* @param key
|
||||
* @returns
|
||||
*/
|
||||
export function GetBookTaskDetailStatusLabel(key: string) {
|
||||
switch (key) {
|
||||
case BookTaskStatus.WAIT:
|
||||
return '等待';
|
||||
case BookTaskStatus.STORYBOARD:
|
||||
return '分镜计算中';
|
||||
case BookTaskStatus.STORYBOARD_FAIL:
|
||||
return '分镜计算失败';
|
||||
case BookTaskStatus.STORYBOARD_DONE:
|
||||
return '分镜计算完成';
|
||||
case BookTaskStatus.SPLIT:
|
||||
return '分割视频中';
|
||||
case BookTaskStatus.SPLIT_FAIL:
|
||||
return '分割视频失败';
|
||||
case BookTaskStatus.SPLIT_DONE:
|
||||
return '分割视频完成';
|
||||
case BookTaskStatus.AUDIO:
|
||||
return '提取音频中';
|
||||
case BookTaskStatus.AUDIO_FAIL:
|
||||
return '提取音频失败';
|
||||
case BookTaskStatus.AUDIO_DONE:
|
||||
return '提取音频完成';
|
||||
case BookTaskStatus.RECOGNIZE:
|
||||
return '识别字幕中';
|
||||
case BookTaskStatus.RECOGNIZE_FAIL:
|
||||
return '识别字幕失败';
|
||||
case BookTaskStatus.RECOGNIZE_DONE:
|
||||
return '识别字幕完成';
|
||||
case BookTaskStatus.FRAME:
|
||||
return '抽帧中';
|
||||
case BookTaskStatus.FRAME_FAIL:
|
||||
return '抽帧失败';
|
||||
case BookTaskStatus.FRAME_DONE:
|
||||
return '抽帧完成';
|
||||
case BookTaskStatus.REVERSE:
|
||||
return '反推中';
|
||||
case BookTaskStatus.REVERSE_FAIL:
|
||||
return '反推失败';
|
||||
case BookTaskStatus.REVERSE_DONE:
|
||||
return '反推完成';
|
||||
case BookTaskStatus.IMAGE:
|
||||
return '生成图片中';
|
||||
case BookTaskStatus.IMAGE_FAIL:
|
||||
return '生成图片失败';
|
||||
case BookTaskStatus.IMAGE_DONE:
|
||||
return '生成图片完成';
|
||||
case BookTaskStatus.HD:
|
||||
return '高清中';
|
||||
case BookTaskStatus.HD_FAIL:
|
||||
return '高清失败';
|
||||
case BookTaskStatus.HD_DONE:
|
||||
return '高清完成';
|
||||
case BookTaskStatus.COMPOSING:
|
||||
return '合成视频中';
|
||||
case BookTaskStatus.COMPOSING_FAIL:
|
||||
return '合成视频失败';
|
||||
case BookTaskStatus.COMPOSING_DONE:
|
||||
return '合成视频完成';
|
||||
case BookTaskStatus.DRAFT_DONE:
|
||||
return '添加草稿完成';
|
||||
case BookTaskStatus.DRAFT_FAIL:
|
||||
return '添加草稿失败';
|
||||
default:
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据Key返回指定的后台任务状态的label
|
||||
* @param key
|
||||
* @returns
|
||||
*/
|
||||
export function GetBookBackTaskStatusLabel(key: string) {
|
||||
switch (key) {
|
||||
case BookBackTaskStatus.WAIT:
|
||||
return '等待';
|
||||
case BookBackTaskStatus.RUNNING:
|
||||
return '运行中';
|
||||
case BookBackTaskStatus.PAUSE:
|
||||
return '暂停';
|
||||
case BookBackTaskStatus.DONE:
|
||||
return '完成';
|
||||
case BookBackTaskStatus.FAIL:
|
||||
return '失败';
|
||||
case BookBackTaskStatus.RECONNECT:
|
||||
return '重连';
|
||||
default:
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,21 +267,22 @@ export function BookIpc() {
|
||||
async (event, id, operateBookType) => await bookImage.ResetGenerateImage(id, operateBookType)
|
||||
)
|
||||
|
||||
// 获取图片的URL并且下载
|
||||
ipcMain.handle(
|
||||
DEFINE_STRING.BOOK.GET_IMAGE_URL_AND_DOWNLOAD,
|
||||
async (event, id: string, operateBookType: OperateBookType, coverData: boolean) =>
|
||||
await bookImage.GetImageUrlAndDownload(id, operateBookType, coverData)
|
||||
)
|
||||
|
||||
/** 添加一键生图后台任务 */
|
||||
ipcMain.handle(
|
||||
DEFINE_STRING.BOOK.GENERATE_ALL_TASK_IMAGE,
|
||||
async (event, ids: string[], operateBookType: OperateBookType) => await bookImage.GenerateAllTaskImage(ids, operateBookType)
|
||||
)
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
// 一拆四,将一个任务拆分成四个任务,并且复制对应的图片
|
||||
ipcMain.handle(
|
||||
DEFINE_STRING.BOOK.ONE_TO_FOUR_BOOK_TASK,
|
||||
async (event, bookTaskDetailId) => await bookTask.OneToFourBookTask(bookTaskDetailId)
|
||||
)
|
||||
|
||||
//#region 小说相关
|
||||
|
||||
// 重置小说数据
|
||||
@ -294,6 +295,12 @@ export function BookIpc() {
|
||||
|
||||
//#region 小说批次任务相关
|
||||
|
||||
// 一拆四,将一个任务拆分成四个任务,并且复制对应的图片
|
||||
ipcMain.handle(
|
||||
DEFINE_STRING.BOOK.ONE_TO_FOUR_BOOK_TASK,
|
||||
async (event, bookTaskDetailId) => await bookTask.OneToFourBookTask(bookTaskDetailId)
|
||||
)
|
||||
|
||||
// 新建小说批次任务
|
||||
ipcMain.handle(DEFINE_STRING.BOOK.ADD_NEW_BOOK_TASK, async (event, addBookTaskData) => await bookTask.AddNewBookTask(addBookTaskData))
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ import { BookBackTaskStatus, BookBackTaskType, TaskExecuteType } from "../../def
|
||||
|
||||
let bookServiceBasic = new BookServiceBasic();
|
||||
import BackTaskService from '../Service/task/backTaskService'
|
||||
import { TaskModal } from "@/model/task";
|
||||
const backTaskService = new BackTaskService()
|
||||
|
||||
function TaskIpc() {
|
||||
@ -38,8 +39,12 @@ function TaskIpc() {
|
||||
return errorMessage(`添加多个任务失败,错误信息如下:${error.toString()} `, 'TaskIpc_AddMultiBookBackTask')
|
||||
}
|
||||
})
|
||||
|
||||
/** 获取指定状态的任务数量 */
|
||||
ipcMain.handle(DEFINE_STRING.TASK.GET_ALL_STATUS_TASK_COUNT, async (event, value: BookBackTaskStatus[]) => await backTaskService.GetAllStatusTaskCount(value))
|
||||
|
||||
/** 获取后台任务的集合,分页 */
|
||||
ipcMain.handle(DEFINE_STRING.TASK.GET_BACK_TASK_COLLECTION, async (event, queryTaskCondition: TaskModal.QueryTaskCondition) => await backTaskService.GetBackTaskCollection(queryTaskCondition))
|
||||
}
|
||||
|
||||
export { TaskIpc }
|
||||
@ -5,7 +5,9 @@ let writing = new Writing(global)
|
||||
import { WritingSetting } from '../setting/writeSetting'
|
||||
let writingSetting = new WritingSetting()
|
||||
import { SubtitleService } from '../Service/Subtitle/subtitleService'
|
||||
import { BookPrompt } from '../Service/Book/bookPrompt'
|
||||
let subtitleService = new SubtitleService()
|
||||
const bookPrompt = new BookPrompt();
|
||||
|
||||
function WritingIpc() {
|
||||
// 监听分镜时间的保存
|
||||
@ -71,5 +73,14 @@ function WritingIpc() {
|
||||
DEFINE_STRING.WRITE.ACTION_START,
|
||||
async (event, aiSetting, word) => await writing.ActionStart(aiSetting, word)
|
||||
)
|
||||
|
||||
//#region 文案洗稿相关
|
||||
|
||||
/** 生成洗稿后文案 */
|
||||
ipcMain.handle(
|
||||
DEFINE_STRING.WRITE.GENERATE_AFTER_GPT_WORD,
|
||||
async (event, ids: string[], isEmpty: boolean) => await bookPrompt.GenerateAfterGptWord(ids, isEmpty)
|
||||
)
|
||||
//#endregion
|
||||
}
|
||||
export { WritingIpc }
|
||||
@ -84,7 +84,7 @@ export class BookFrame {
|
||||
startTime: Math.ceil(element.startTime / 1000),
|
||||
endTime: Math.ceil(element.endTime / 1000),
|
||||
status: BookTaskStatus.WAIT,
|
||||
word: element.word,
|
||||
word: element.text,
|
||||
videoPath: element.videoPath,
|
||||
oldImage: path.relative(define.project_path, element.framePath),
|
||||
afterGpt: element.text,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { BookImageCategory, BookType, MJAction, OperateBookType } from "../../../define/enum/bookEnum";
|
||||
import { BookBackTaskType, BookImageCategory, BookType, MJAction, OperateBookType, TaskExecuteType } from "../../../define/enum/bookEnum";
|
||||
import { GeneralResponse } from "../../../model/generalResponse";
|
||||
import { errorMessage, successMessage } from "../../Public/generalTools";
|
||||
import { Book } from "../../../model/book";
|
||||
@ -19,6 +19,13 @@ import { MJImageType } from "../../../define/enum/mjEnum";
|
||||
import MJApi from '../MJ/mjApi'
|
||||
const execAsync = util.promisify(exec);
|
||||
|
||||
type TaskTemp = {
|
||||
bookTaskId: string;
|
||||
bookId: string;
|
||||
imageCategory: BookImageCategory;
|
||||
bookTaskDetail: Book.SelectBookTaskDetail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 小说图片执行的相关操作
|
||||
*/
|
||||
@ -87,8 +94,9 @@ export class BookImage {
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region 开始高清图片任务
|
||||
/**
|
||||
* 开始高清图片,当前默认是四倍,后续可以调整
|
||||
* 开始高清图片
|
||||
* @param id 要高清操作的ID
|
||||
* @param scale 高清的倍率
|
||||
* @param operateBookType 操作的类型(支持BOOK,BOOKTASK两种)
|
||||
@ -188,7 +196,9 @@ export class BookImage {
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 检查图片的大小
|
||||
/**
|
||||
* 检查图片的大小(只要有一个图片的大小超过了 fileSize 的大小,就返回false)
|
||||
* @param id 需要操作的的ID,可以是整个小说的ID,也可以单个批次的ID
|
||||
@ -251,6 +261,88 @@ export class BookImage {
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
/**
|
||||
* 将指定的批次任务,添加里面的所有的分镜到出图任务中
|
||||
* @param ids 批次任务ID
|
||||
* @param operateBookType 操作类型
|
||||
*/
|
||||
async GenerateAllTaskImage(ids: string[], operateBookType: OperateBookType) {
|
||||
try {
|
||||
let bookTasks = [] as Book.SelectBookTask[];
|
||||
if (operateBookType == OperateBookType.ASSIGNBOOKTASK) {
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
const element = ids[i];
|
||||
let tempBookTask = await this.bookServiceBasic.GetBookTaskDataById(element);
|
||||
bookTasks.push(tempBookTask)
|
||||
}
|
||||
} else {
|
||||
throw new Error('不支持的操作类型,请检查')
|
||||
}
|
||||
if (bookTasks.length <= 0) {
|
||||
throw new Error('没有找到需要操作的数据,请检查')
|
||||
}
|
||||
let taskTemp = [] as TaskTemp[]
|
||||
for (let i = 0; i < bookTasks.length; i++) {
|
||||
const element = bookTasks[i];
|
||||
let bookTaskDetails = await this.bookServiceBasic.GetBookTaskDetailData({
|
||||
bookTaskId: element.id
|
||||
}, true)
|
||||
if (bookTaskDetails.length <= 0) {
|
||||
throw new Error(`批次任务 ${element.name} 没有找到分镜数据,请检查`)
|
||||
}
|
||||
let emptyPrompt = bookTaskDetails.filter(item => isEmpty(item.prompt));
|
||||
if (emptyPrompt.length > 0) {
|
||||
throw new Error(`批次任务 ${element.name} 的分镜 ${emptyPrompt[0].name} 没有找到出图提示词,请检查`)
|
||||
}
|
||||
|
||||
taskTemp.push(...bookTaskDetails.map((item) => {
|
||||
return {
|
||||
bookTaskId: element.id,
|
||||
bookId: element.bookId,
|
||||
imageCategory: element.imageCategory,
|
||||
bookTaskDetail: item
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
// 检查当前小说批次任务是不是又出图方式
|
||||
// 判断是不是所有的小说批次都有小说分镜
|
||||
// 判断每个分镜是不是都有出图提示词
|
||||
// 添加出图任务
|
||||
for (let i = 0; i < taskTemp.length; i++) {
|
||||
const element = taskTemp[i];
|
||||
// 添加任务
|
||||
let taskType = BookBackTaskType.MJ_IMAGE
|
||||
let responseMessageName = DEFINE_STRING.BOOK.MJ_IMAGE_GENERATE_RETURN;
|
||||
|
||||
if (element.imageCategory == BookImageCategory.MJ) {
|
||||
taskType = BookBackTaskType.MJ_IMAGE;
|
||||
responseMessageName = DEFINE_STRING.BOOK.MJ_IMAGE_GENERATE_RETURN;
|
||||
} else if (element.imageCategory == BookImageCategory.SD) {
|
||||
taskType = BookBackTaskType.SD_IMAGE;
|
||||
responseMessageName = DEFINE_STRING.BOOK.SD_IMAGE_GENERATE_RETURN;
|
||||
} else if (element.imageCategory == BookImageCategory.D3) {
|
||||
taskType = BookBackTaskType.D3_IMAGE;
|
||||
responseMessageName = DEFINE_STRING.BOOK.D3_IMAGE_GENERATE_RETURN;
|
||||
} else if (element.imageCategory == BookImageCategory.FLUX_FORGE) {
|
||||
taskType = BookBackTaskType.FLUX_FORGE_IMAGE;
|
||||
responseMessageName = DEFINE_STRING.BOOK.FLUX_FORGE_IMAGE_GENERATE_RETURN
|
||||
} else if (element.imageCategory == BookImageCategory.FLUX_API) {
|
||||
taskType = BookBackTaskType.FLUX_API_IMAGE;
|
||||
responseMessageName = DEFINE_STRING.BOOK.FLUX_API_IMAGE_GENERATE_RETURN;
|
||||
} else {
|
||||
throw new Error('未知的出图类型')
|
||||
}
|
||||
await this.bookServiceBasic.AddBookBackTask(element.bookId, taskType, TaskExecuteType.AUTO, element.bookTaskId, element.bookTaskDetail.id, responseMessageName)
|
||||
}
|
||||
return successMessage(null, "添加所选的的生图任务成功", "BookImage_GenerateAllTaskImage")
|
||||
} catch (error) {
|
||||
return errorMessage("添加所有的生图任务失败,失败信息如下:" + error.toString(), "BookImage_GenerateAllTaskImage");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成所有的图片,这个方法主要是分流,根据批次生成的方式,添加对应的数据
|
||||
@ -277,6 +369,7 @@ export class BookImage {
|
||||
}
|
||||
}
|
||||
|
||||
//#region 对图片进行锁定或者是解锁操作
|
||||
/**
|
||||
* 对图片进行锁定或者是解锁操作
|
||||
* @param id 要执行的id
|
||||
@ -327,7 +420,9 @@ export class BookImage {
|
||||
return errorMessage("图片执行锁定或解锁失败,失败信息如下:" + error.toString(), "BookImage_ImageLockOperation")
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region 下载指定的图片地址并且分割
|
||||
/**
|
||||
* 下载指定的图片地址并且分割
|
||||
* @param bookTaskDetailId 对应的分镜ID
|
||||
@ -416,8 +511,9 @@ export class BookImage {
|
||||
}
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region 获取指定的图片链接 ,然后下载图片
|
||||
/**
|
||||
* 获取指定的图片链接 ,然后下载图片
|
||||
* @param id
|
||||
@ -486,4 +582,5 @@ export class BookImage {
|
||||
return errorMessage('获取图片链接并且下载失败,错误信息如下:' + error.message, 'BookImage_GetImageUrlAndDownload')
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import path from 'path'
|
||||
import readline from 'readline';
|
||||
import { define } from "../../../define/define";
|
||||
import { ValidateJson } from "../../../define/Tools/validate";
|
||||
import { SendMessageToRenderer } from "../globalService";
|
||||
|
||||
|
||||
export class BookPrompt {
|
||||
@ -290,6 +291,67 @@ export class BookPrompt {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成洗稿后文案
|
||||
* @param ids 要洗稿的分镜的ID
|
||||
* @param isEmpty 是不是只洗空行
|
||||
* 先删除,在洗稿
|
||||
*/
|
||||
async GenerateAfterGptWord(ids: string[], empty: boolean) {
|
||||
try {
|
||||
if (ids.length <= 0) {
|
||||
throw new Error('没有传入要洗稿的数据ID')
|
||||
}
|
||||
let bookTaskDetails = [] as Book.SelectBookTaskDetail[]
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
const element = ids[i];
|
||||
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(element)
|
||||
bookTaskDetails.push(bookTaskDetail);
|
||||
}
|
||||
if (empty) {
|
||||
bookTaskDetails = bookTaskDetails.filter(item => isEmpty(item.gptPrompt))
|
||||
}
|
||||
if (bookTaskDetails.length <= 0) {
|
||||
throw new Error('没有找到要洗稿的数据')
|
||||
}
|
||||
|
||||
// 开始删除数据
|
||||
for (let i = 0; i < bookTaskDetails.length; i++) {
|
||||
const element = bookTaskDetails[i];
|
||||
await this.bookServiceBasic.UpdateBookTaskDetail(element.id, {
|
||||
afterGpt: undefined
|
||||
})
|
||||
|
||||
SendMessageToRenderer({
|
||||
code: 1,
|
||||
message: "删除洗稿后文案成功",
|
||||
id: element.id,
|
||||
data: ""
|
||||
}, DEFINE_STRING.WRITE.GENERATE_AFTER_GPT_WORD_RESPONSE)
|
||||
}
|
||||
|
||||
for (let i = 0; i < bookTaskDetails.length; i++) {
|
||||
const element = bookTaskDetails[i];
|
||||
|
||||
// 开始洗稿
|
||||
let content = await this.gptService.GenerateAfterGptWordByGPT(element.word);
|
||||
// 修改数据
|
||||
await this.bookServiceBasic.UpdateBookTaskDetail(element.id, {
|
||||
afterGpt: content
|
||||
})
|
||||
SendMessageToRenderer({
|
||||
code: 1,
|
||||
message: "文案洗稿成功",
|
||||
id: element.id,
|
||||
data: content
|
||||
}, DEFINE_STRING.WRITE.GENERATE_AFTER_GPT_WORD_RESPONSE)
|
||||
}
|
||||
return successMessage(null, "洗稿完成", "ReverseBook_GenerateAfterGptWord")
|
||||
} catch (error) {
|
||||
return errorMessage("生成洗稿后文案失败,错误信息如下:" + error.message, "ReverseBook_GenerateAfterGptWord")
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 原创的提示词相关
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { CheckFileOrDirExist, CheckFolderExistsOrCreate, CopyFileOrFolder, DeleteFolderAllFile } from "../../../define/Tools/file";
|
||||
import { AddBookTaskCopyData, BookImageCategory, BookTaskStatus, CopyImageType, OperateBookType } from "../../../define/enum/bookEnum";
|
||||
import { AddBookTaskCopyData, BookImageCategory, BookTaskStatus, BookType, CopyImageType, OperateBookType } from "../../../define/enum/bookEnum";
|
||||
import { errorMessage, successMessage } from "../../Public/generalTools";
|
||||
import { Book } from "../../../model/book";
|
||||
import path from 'path'
|
||||
@ -119,9 +119,23 @@ export class BookTask {
|
||||
* @param no 当前的编号
|
||||
* @returns
|
||||
*/
|
||||
CopyBookTaskBaseData(bookTask: Book.SelectBookTask, addNewBookTask: Book.AddBookTask, no: number): Book.SelectBookTask {
|
||||
async CopyBookTaskBaseData(bookTask: Book.SelectBookTask, addNewBookTask: Book.AddBookTask, no: number): Promise<Book.SelectBookTask> {
|
||||
let name = 'output_' + no.toString().padStart(5, '0');
|
||||
let imageFolder = path.join(define.project_path, `${bookTask.bookId}/tmp/${name}`);
|
||||
let imageCategory = global.config.defaultImageMode;
|
||||
let book = await this.bookServiceBasic.GetBookDataById(bookTask.bookId)
|
||||
if (!isEmpty(bookTask.imageCategory)) {
|
||||
imageCategory = bookTask.imageCategory;
|
||||
} else {
|
||||
if (book.type == BookType.MJ_REVERSE) {
|
||||
imageCategory = BookImageCategory.MJ
|
||||
} else if (book.type == BookType.SD_REVERSE) {
|
||||
imageCategory = BookImageCategory.SD
|
||||
} else if (book.type == BookType.ORIGINAL) {
|
||||
imageCategory = global.config.defaultImageMode
|
||||
}
|
||||
}
|
||||
|
||||
let newBookTask = {
|
||||
id: uuidv4(),
|
||||
bookId: bookTask.bookId,
|
||||
@ -142,7 +156,7 @@ export class BookTask {
|
||||
videoConfig: bookTask.videoConfig ??= undefined,
|
||||
prefixPrompt: addNewBookTask.prefixPrompt ??= undefined,
|
||||
suffixPrompt: addNewBookTask.suffixPrompt ?? undefined,
|
||||
imageCategory: bookTask.imageCategory ??= BookImageCategory.MJ,
|
||||
imageCategory: imageCategory,
|
||||
subImageFolder: [],
|
||||
draftSrtStyle: undefined,
|
||||
backgroundMusic: bookTask.backgroundMusic ??= undefined,
|
||||
@ -164,7 +178,7 @@ export class BookTask {
|
||||
* @returns
|
||||
*/
|
||||
async AddOneBookTask(bookTask: Book.SelectBookTask, bookTaskDetails: Book.SelectBookTaskDetail[], addNewBookTask: Book.AddBookTask, no: number): Promise<{ newBookTask: Book.SelectBookTask, newBookTaskDetails: Book.SelectBookTaskDetail[] }> {
|
||||
let newBookTask = this.CopyBookTaskBaseData(bookTask, addNewBookTask, no)
|
||||
let newBookTask = await this.CopyBookTaskBaseData(bookTask, addNewBookTask, no)
|
||||
let newBookTaskDetails = await this.CopyBookTaskDetailBaseData(bookTask, newBookTask, bookTaskDetails, addNewBookTask)
|
||||
return {
|
||||
newBookTask: newBookTask,
|
||||
@ -199,7 +213,7 @@ export class BookTask {
|
||||
bookTasks.push(newBookTask)
|
||||
bookTaskDetail.push(...newBookTaskDetails)
|
||||
} else {
|
||||
let newBookTask = this.CopyBookTaskBaseData({ bookId: addNewBookTask.selectBookId }, addNewBookTask, maxNo + i)
|
||||
let newBookTask = await this.CopyBookTaskBaseData({ bookId: addNewBookTask.selectBookId }, addNewBookTask, maxNo + i)
|
||||
bookTasks.push(newBookTask);
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,6 +160,7 @@ export class FluxOpt {
|
||||
})
|
||||
} catch (error) {
|
||||
let errorMsg = "FLUX FORGE 生成图片失败,错误信息如下:" + error.toString()
|
||||
|
||||
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
|
||||
mjApiUrl: sdSetting ? sdSetting.setting.webui_api_url : "",
|
||||
progress: 0,
|
||||
@ -171,6 +172,11 @@ export class FluxOpt {
|
||||
status: "error",
|
||||
message: errorMsg
|
||||
})
|
||||
await this.bookServiceBasic.UpdateTaskStatus({
|
||||
id: task.id,
|
||||
status: BookBackTaskStatus.FAIL,
|
||||
errorMessage: errorMsg
|
||||
});
|
||||
|
||||
global.newWindow[0].win.webContents.send(task.messageName, {
|
||||
code: 0,
|
||||
|
||||
@ -318,4 +318,65 @@ export class GptService {
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region 聚合推文 文案洗稿
|
||||
|
||||
/**
|
||||
* 聚合推文的文案洗稿
|
||||
* @param word 之前的提示词
|
||||
* @returns
|
||||
*/
|
||||
async GenerateAfterGptWordByGPT(word: string,) {
|
||||
try {
|
||||
let prompt = `## - Role: 文案去重
|
||||
<Background>: 用户需要将小说的文本进行细致的分析,并将原文文本内容进行同义转换,换一种描述,不要改变文案的结构,不改变原来的意思,要求参考原文案的写作风格,不要书面词,要尽可能的口语化输出,但不要太过于运用东北话的一些词语,比如“瞅“,“爱咋咋地“,“咋地“,等类似的词语。
|
||||
|
||||
## 要求
|
||||
严格执行以下要求进行小说内容的段落分行:
|
||||
1.严格要求根据原文进行同义输出:不允许将原文一行内容所表达的内容分成多行来输出。
|
||||
2.仅对原文中的话换一种描述,但不能完全脱离这句话的意思。
|
||||
3.输出的内容每一句话与原文的字数尽量保持一致,严格遵守不能远少于原文每个句子的字数,再次强调不能少于原文每句话的字数。
|
||||
4.输出的文案的相似度必须低于百分之五十
|
||||
|
||||
## 示例
|
||||
输入1:这个世界的女人每结一次婚,就会在手上戴一枚戒指,手上的戒指越多,那么就代表着她的老公越多。
|
||||
输出1: 雌性每洞房一次,就会带上一枚戒指,手上的戒指越多,就代表被她宠幸的雄性越多。
|
||||
|
||||
输入2:我重生到末日前的第一件事,就是从学校后山徒手抓了一条黑曼巴蛇,并丧心病狂的将之活生生吞下。
|
||||
输出2: 我重生后的第一件事就是生吞羊辣子,然后挖出自己双眼,再割掉自己头颅,众人以为我是疯子得了精神病,但只有我知道我是重生者。
|
||||
|
||||
输入3:我明明觉醒了SSS级异能紫霄神器,却被全校所有人嘲笑,原因我觉醒的异能在别人眼里只是一个人形电击棒。
|
||||
输出3: 我明明觉醒了sss级暗黑系异能,却被超神学院五大院长同时除名,就连唯一的妹妹夜哭着劝我放弃修炼。
|
||||
|
||||
输入3:我的奶奶觉醒级凶兽烈焰巨龙,我的爷爷觉醒级凶兽暴虐滔天,而我却在这个觉醒凶兽的世界觉醒了个破烂石板
|
||||
输出3: 我爷爷觉醒了s级凶兽黄金朱厌,奶奶觉醒了ss级神兽泰坦巨猿,可我却在这个人人觉醒泰坦战士的世界
|
||||
|
||||
输入5: 一个先天满属性的天才却被称为废物,只因我在转职时觉醒了史上最垃圾的道士职业,就连重金挖我来的学校也将我当成了耻辱
|
||||
输出5: 一个先天满属性的天才却被称为废物,只因我在转职时觉醒了史上最垃圾的道士职业,就连重金挖我来的学校也将我当成了耻辱
|
||||
|
||||
##
|
||||
最后再强调,你作为一位优秀的小说改写者,每一次输出都要严格遵守<要求>,一步一步慢慢思考,参考<示例>的格式,一步一步思考,按顺序执行<要求>,不需要做解释说明,只呈现最后的结果,严格要求理解全文之后再进行分组,无需要在输出用户,直接输出Ai部分。
|
||||
`;
|
||||
|
||||
let message = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": prompt,
|
||||
}, {
|
||||
"role": "user",
|
||||
"content": word
|
||||
}
|
||||
]
|
||||
|
||||
// 开始请求,这个默认是使用的是LAI API的gpt-4o-mini
|
||||
let content = await RetryWithBackoff<string>(async () => {
|
||||
return await this.FetchGpt(message, null, null, null);
|
||||
}, 5, 2000)
|
||||
return content;
|
||||
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@ -660,7 +660,7 @@ export class MJOpt {
|
||||
data: task_res
|
||||
}, task.messageName);
|
||||
// 当获取的图片的进度小于100的时候,等待5秒继续监听
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
await new Promise(resolve => setTimeout(resolve, 9000));
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
@ -369,7 +369,6 @@ export class SDOpt {
|
||||
action: MJAction.IMAGINE,
|
||||
status: "error",
|
||||
message: errorMsg,
|
||||
id: task.bookTaskDetailId
|
||||
})
|
||||
|
||||
await this.bookServiceBasic.UpdateBookTaskDetail(task.bookTaskDetailId, {
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { BookBackTaskStatus, BookBackTaskType, TaskExecuteType } from "../../../define/enum/bookEnum";
|
||||
import { BookBackTaskListService } from "../../../define/db/service/Book/bookBackTaskListService";
|
||||
import { Book } from "../../../model/book";
|
||||
import { TaskModal } from "@/model/task";
|
||||
import { cloneDeep, isEmpty } from "lodash";
|
||||
|
||||
export default class BookBackTaskServiceBasic {
|
||||
bookBackTaskListService: BookBackTaskListService
|
||||
@ -57,6 +59,29 @@ export default class BookBackTaskServiceBasic {
|
||||
this.bookBackTaskListService.UpdateTaskStatus(bookBackTask)
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置指定消息名称的任务为失败,并设置错误消息
|
||||
* @param messageName
|
||||
* @param errorMessage
|
||||
*/
|
||||
async SetMessageNameTaskToFail(messageName: string, errorMessage: string) {
|
||||
console.log(messageName, errorMessage)
|
||||
await this.InitService();
|
||||
let tasks = this.bookBackTaskListService.realm.objects('BookBackTaskList').filtered('messageName == $0 ', messageName)
|
||||
tasks = tasks.filtered('status != $0', BookBackTaskStatus.DONE);
|
||||
tasks = tasks.filtered('status != $0', BookBackTaskStatus.FAIL);
|
||||
let ids = tasks.map((item) => {
|
||||
return item.id
|
||||
})
|
||||
this.bookBackTaskListService.transaction(() => {
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
let task = this.bookBackTaskListService.realm.objectForPrimaryKey('BookBackTaskList', ids[i]);
|
||||
task.status = BookBackTaskStatus.FAIL
|
||||
task.errorMessage = errorMessage
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 丢弃等待中和重新连接的任务
|
||||
*/
|
||||
@ -75,4 +100,86 @@ export default class BookBackTaskServiceBasic {
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 查询指定的条件的后台任务集合
|
||||
* @param queryTaskCondition
|
||||
*/
|
||||
GetBackTaskCollection(queryTaskCondition: TaskModal.QueryTaskCondition): TaskModal.TaskCollection {
|
||||
let tasks = this.bookBackTaskListService.realm.objects('BookBackTaskList');
|
||||
if (!isEmpty(queryTaskCondition.bookName)) {
|
||||
let book = this.bookBackTaskListService.realm.objects('Book').filtered('name CONTAINS[c] $0', queryTaskCondition.bookName);
|
||||
let ids = [] as string[]
|
||||
if (book.length > 0) {
|
||||
ids = book.map((item) => {
|
||||
return item.id as string
|
||||
})
|
||||
}
|
||||
tasks = tasks.filtered('bookId in $0', ids);
|
||||
}
|
||||
if (!isEmpty(queryTaskCondition.bookTaskName)) {
|
||||
let bookTask = this.bookBackTaskListService.realm.objects('BookTask').filtered('name CONTAINS[c] $0', queryTaskCondition.bookTaskName);
|
||||
let ids = [] as string[]
|
||||
if (bookTask.length > 0) {
|
||||
ids = bookTask.map((item) => {
|
||||
return item.id as string
|
||||
})
|
||||
}
|
||||
tasks = tasks.filtered('bookTaskId in $0', ids);
|
||||
}
|
||||
if (!isEmpty(queryTaskCondition.bookTaskDetailName)) {
|
||||
let bookTaskDetail = this.bookBackTaskListService.realm.objects('BookTaskDetail').filtered('name CONTAINS[c] $0', queryTaskCondition.bookTaskDetailName);
|
||||
let ids = [] as string[]
|
||||
if (bookTaskDetail.length > 0) {
|
||||
ids = bookTaskDetail.map((item) => {
|
||||
return item.id as string
|
||||
})
|
||||
}
|
||||
tasks = tasks.filtered('bookTaskDetailId in $0', ids);
|
||||
}
|
||||
if (!isEmpty(queryTaskCondition.taskName)) {
|
||||
tasks = tasks.filtered('name CONTAINS[c] $0', queryTaskCondition.taskName);
|
||||
}
|
||||
if (!isEmpty(queryTaskCondition.taskType)) {
|
||||
tasks = tasks.filtered('type == $0', queryTaskCondition.taskType);
|
||||
}
|
||||
if (!isEmpty(queryTaskCondition.taskStatus)) {
|
||||
tasks = tasks.filtered('status == $0', queryTaskCondition.taskStatus);
|
||||
}
|
||||
if (!isEmpty(queryTaskCondition.taskErrorMessage)) {
|
||||
tasks = tasks.filtered('errorMessage CONTAINS[c] $0', queryTaskCondition.taskErrorMessage);
|
||||
}
|
||||
let count = tasks.length
|
||||
tasks = tasks.sorted('createTime', true)
|
||||
let task = tasks.slice((queryTaskCondition.page - 1) * queryTaskCondition.pageSize, queryTaskCondition.page * queryTaskCondition.pageSize) as TaskModal.BackTaskCollection[];
|
||||
|
||||
let taskList = Array.from(task).map((item) => {
|
||||
let resObj = {
|
||||
...item,
|
||||
} as TaskModal.BackTaskCollection
|
||||
return cloneDeep(resObj)
|
||||
})
|
||||
|
||||
for (let i = 0; i < taskList.length; i++) {
|
||||
const element = taskList[i];
|
||||
let book = this.bookBackTaskListService.realm.objectForPrimaryKey('Book', element.bookId)
|
||||
if (book) {
|
||||
element.bookName = book.name as string;
|
||||
}
|
||||
let bookTask = this.bookBackTaskListService.realm.objectForPrimaryKey('BookTask', element.bookTaskId);
|
||||
if (bookTask) {
|
||||
element.bookTaskName = bookTask.name as string;
|
||||
}
|
||||
let bookTaskDetail = this.bookBackTaskListService.realm.objectForPrimaryKey('BookTaskDetail', element.bookTaskDetailId);
|
||||
if (bookTaskDetail) {
|
||||
element.bookTaskDetailName = bookTaskDetail.name as string;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
page: queryTaskCondition.page,
|
||||
pageSize: queryTaskCondition.pageSize,
|
||||
count: count,
|
||||
data: taskList
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ import BookBackTaskServiceBasic from "./bookBackTaskServiceBasic";
|
||||
import { BookBasic } from "./bookBasic";
|
||||
import BookTaskServiceBasic from "./bookTaskServiceBasic";
|
||||
import BookTaskDetailServiceBasic from "./bookTaskDetailServiceBasic";
|
||||
import { TaskModal } from "@/model/task";
|
||||
|
||||
/**
|
||||
* 该类中封装了小说的基础服务,主要是检查每次引入对应的服务类
|
||||
@ -90,6 +91,10 @@ class BookServiceBasic {
|
||||
UpdateTaskStatus = async (bookBackTask: Book.UpdateBookTaskListStatus) => await this.bookBackTaskServiceBasic.UpdateTaskStatus(bookBackTask);
|
||||
GiveUpNotStartBackTask = async () => await this.bookBackTaskServiceBasic.GiveUpNotStartBackTask();
|
||||
|
||||
/** 设置指定的消息名称的任务状态为错误及错误信息 */
|
||||
SetMessageNameTaskToFail = async (massageName: string, errorMessage: string) => await this.bookBackTaskServiceBasic.SetMessageNameTaskToFail(massageName, errorMessage);
|
||||
/** 查询指定的条件的后台任务 */
|
||||
GetBackTaskCollection = async (queryTaskCondition: TaskModal.QueryTaskCondition) => await this.bookBackTaskServiceBasic.GetBackTaskCollection(queryTaskCondition);
|
||||
//#endregion
|
||||
}
|
||||
export { BookServiceBasic };
|
||||
|
||||
@ -179,6 +179,9 @@ export class SubtitleService {
|
||||
default:
|
||||
throw new Error("未知的识别字幕模式")
|
||||
}
|
||||
if (res.code == 0) {
|
||||
throw new Error(res.message)
|
||||
}
|
||||
if (operateBookType == OperateBookType.BOOKTASKDETAIL) {
|
||||
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(bookTaskId)
|
||||
return successMessage(bookTaskDetail.afterGpt, "获取文案成功", "ReverseBook_GetCopywriting")
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { TaskModal } from "@/model/task";
|
||||
import { BookBackTaskStatus } from "../../../define/enum/bookEnum";
|
||||
import { GeneralResponse } from "../../../model/generalResponse";
|
||||
import { errorMessage, successMessage } from "../../Public/generalTools";
|
||||
@ -10,6 +11,7 @@ export default class BackTaskService {
|
||||
this.bookServiceBasic = new BookServiceBasic()
|
||||
}
|
||||
|
||||
//#region 获取指定状态的后台任务数量
|
||||
/**
|
||||
* 获取指定状态的后台任务数量
|
||||
*/
|
||||
@ -23,6 +25,9 @@ export default class BackTaskService {
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 启动后台任务
|
||||
/**
|
||||
* 启动后台任务,判断是不是丢弃,要是丢弃的话,先将等待任务全部丢弃
|
||||
* @param isGiveUp
|
||||
@ -44,4 +49,14 @@ export default class BackTaskService {
|
||||
return errorMessage('启动后台任务失败', 'BackTaskService_StartBackTask')
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
public async GetBackTaskCollection(queryTaskCondition: TaskModal.QueryTaskCondition) {
|
||||
try {
|
||||
let res = await this.bookServiceBasic.GetBackTaskCollection(queryTaskCondition);
|
||||
return successMessage(res, '获取后台任务集合成功', 'BackTaskService_GetBackTaskCollection');
|
||||
} catch (error) {
|
||||
return errorMessage('获取后台任务集合失败,失败信息如下:' + error.toString(), 'BackTaskService_GetBackTaskCollection')
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,8 @@ import { AsyncQueue } from '../../quene'
|
||||
import { SoftWareServiceBasic } from '../ServiceBasic/softwareServiceBasic'
|
||||
import { MJSetting } from '../../../model/Setting/mjSetting'
|
||||
import { BookVideo } from '../Book/bookVideo'
|
||||
import { BookServiceBasic } from '../ServiceBasic/bookServiceBasic'
|
||||
import { TaskModal } from '@/model/task'
|
||||
|
||||
export class TaskManager {
|
||||
isExecuting: boolean = false;
|
||||
@ -26,6 +28,7 @@ export class TaskManager {
|
||||
eventListeners: Record<string | number, Function[]> = {};
|
||||
softWareServiceBasic: SoftWareServiceBasic
|
||||
bookVideo: BookVideo
|
||||
bookServiceBasic: BookServiceBasic
|
||||
|
||||
mjSetting: MJSetting.MjSetting
|
||||
spaceTime: number = 5000;
|
||||
@ -48,6 +51,7 @@ export class TaskManager {
|
||||
this.d3Opt = new D3Opt()
|
||||
this.softWareServiceBasic = new SoftWareServiceBasic();
|
||||
this.fluxOpt = new FluxOpt()
|
||||
this.bookServiceBasic = new BookServiceBasic();
|
||||
}
|
||||
|
||||
async InitService(getMJsetting = false) {
|
||||
@ -63,6 +67,16 @@ export class TaskManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行后台任务的时候,当批次任务出错的时候,会删除子任务,
|
||||
* 这边将子任务设置为失败状态,用于管理
|
||||
* @param messageName
|
||||
*/
|
||||
async ErrorTaskHandle(messageName: string, ems: string, bsb: BookServiceBasic) {
|
||||
debugger
|
||||
bsb.SetMessageNameTaskToFail(messageName, ems);
|
||||
}
|
||||
|
||||
// 初始化事件监听方法
|
||||
InitListeners() {
|
||||
if (this.isListening) return; // 如果已经在监听,直接返回
|
||||
@ -201,7 +215,6 @@ export class TaskManager {
|
||||
global.requestQuene.enqueue(async () => {
|
||||
await this.basicReverse.ExtractSubtitlesData(task);
|
||||
}, `${batch}_${task.id}`, batch)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -209,10 +222,10 @@ export class TaskManager {
|
||||
* @param task
|
||||
*/
|
||||
AddSingleReversePrompt(task: TaskModal.Task): void {
|
||||
let batch = DEFINE_STRING.BOOK.ADD_REVERSE_PROMPT;
|
||||
let batch = task.messageName;
|
||||
global.requestQuene.enqueue(async () => {
|
||||
await this.reverseBook.SingleReversePrompt(task);
|
||||
}, `${batch}_${task.id}`, batch)
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`, this.bookServiceBasic.SetMessageNameTaskToFail);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -221,10 +234,10 @@ export class TaskManager {
|
||||
*/
|
||||
async AddImageMJImage(task: TaskModal.Task) {
|
||||
// 判断是不是MJ的任务
|
||||
let batch = DEFINE_STRING.MJ.MJ_IMAGE;
|
||||
let batch = task.messageName;
|
||||
global.mjQueue.enqueue(async () => {
|
||||
await this.mjOpt.MJImagine(task);
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`);
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`, this.bookServiceBasic.SetMessageNameTaskToFail);
|
||||
}
|
||||
|
||||
|
||||
@ -233,10 +246,10 @@ export class TaskManager {
|
||||
* @param task
|
||||
*/
|
||||
async AddSDImage(task: TaskModal.Task) {
|
||||
let batch = DEFINE_STRING.SD.TXT2IMG
|
||||
let batch = task.messageName;
|
||||
global.requestQuene.enqueue(async () => {
|
||||
await this.sdOpt.SDImageGenerate(task);
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`)
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`, this.bookServiceBasic.SetMessageNameTaskToFail)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -251,7 +264,7 @@ export class TaskManager {
|
||||
let batch = task.messageName;
|
||||
global.requestQuene.enqueue(async () => {
|
||||
await this.d3Opt.D3ImageGenerate(task);
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`)
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`, this.bookServiceBasic.SetMessageNameTaskToFail);
|
||||
}
|
||||
|
||||
/** 添加生成视频的后台任务 */
|
||||
@ -260,7 +273,7 @@ export class TaskManager {
|
||||
global.requestQuene.enqueue(async () => {
|
||||
this.bookVideo = new BookVideo();
|
||||
await this.bookVideo.GenerateVideo(task);
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`)
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`, this.bookServiceBasic.SetMessageNameTaskToFail)
|
||||
}
|
||||
|
||||
|
||||
@ -269,10 +282,10 @@ export class TaskManager {
|
||||
* @param task
|
||||
*/
|
||||
async AddFluxForgeImage(task: TaskModal.Task) {
|
||||
let batch = task.messageName
|
||||
let batch = task.messageName;
|
||||
global.requestQuene.enqueue(async () => {
|
||||
await this.fluxOpt.FluxForgeImage(task);
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`)
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`, this.bookServiceBasic.SetMessageNameTaskToFail)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -283,7 +296,7 @@ export class TaskManager {
|
||||
let batch = task.messageName;
|
||||
global.requestQuene.enqueue(async () => {
|
||||
await this.fluxOpt.FluxAPIImage(task);
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`)
|
||||
}, `${batch}_${task.id}`, batch, `${batch}_${task.id}_${new Date().getTime()}`, this.bookServiceBasic.SetMessageNameTaskToFail)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -683,6 +683,8 @@ async function SaveSDConfig(value) {
|
||||
sd_config.webui.width = value.width ? value.width : sd_config.webui.width
|
||||
sd_config.webui.height = value.height ? value.height : sd_config.webui.height
|
||||
sd_config.webui.cfg_scale = value.cfg_scale ? value.cfg_scale : sd_config.webui.cfg_scale
|
||||
sd_config.webui.batch_size = value.batch_size ? value.batch_size : sd_config.webui.batch_size
|
||||
sd_config.setting.seed = value.seed ? value.seed : sd_config.setting.seed
|
||||
sd_config.webui.adetailer = value.hasOwnProperty('adetailer')
|
||||
? value.adetailer
|
||||
: sd_config.webui.adetailer
|
||||
@ -695,6 +697,7 @@ async function SaveSDConfig(value) {
|
||||
} else {
|
||||
sd_config.flux.model = value.flux_model ? value.flux_model : FLxuAPIImageType.FLUX
|
||||
}
|
||||
|
||||
await fspromises.writeFile(define.sd_setting, JSON.stringify(sd_config))
|
||||
return {
|
||||
code: 1,
|
||||
|
||||
@ -19,7 +19,7 @@ export class AsyncQueue {
|
||||
this.taskProgress = []
|
||||
}
|
||||
|
||||
async enqueue(task, taskId, batchId, subBatchId = 'default') {
|
||||
async enqueue(task, taskId, batchId, subBatchId = 'default', errorFunc = null) {
|
||||
if (batchId && batchId != DEFINE_STRING.QUEUE_BATCH.IMAGE_SAVE_TO_OTHER_FOLDER) {
|
||||
// 判断当前的任务是否已经存在,存在则不添加
|
||||
let index = this.tasks.findIndex(
|
||||
@ -44,7 +44,7 @@ export class AsyncQueue {
|
||||
|
||||
this.batchCompletion[batchId].remaining++
|
||||
this.batchCompletion[batchId].subBatches[subBatchId].remaining++
|
||||
this.tasks.push({ task, taskId, batchId, subBatchId })
|
||||
this.tasks.push({ task, taskId, batchId, subBatchId, errorFunc })
|
||||
if (!this.manualMode) {
|
||||
await this.process()
|
||||
}
|
||||
@ -95,7 +95,7 @@ export class AsyncQueue {
|
||||
? this.taskProgress.length < task_count
|
||||
: this.currentConcurrency < this.concurrencyLimit)
|
||||
) {
|
||||
const { task, taskId, batchId, subBatchId } = this.tasks.shift()
|
||||
const { task, taskId, batchId, subBatchId, errorFunc } = this.tasks.shift()
|
||||
this.currentConcurrency++
|
||||
Promise.resolve(task())
|
||||
.then(() => {
|
||||
@ -132,6 +132,13 @@ export class AsyncQueue {
|
||||
// console.error(`Task ${taskId} failed after ${maxRetryCount} retries`);
|
||||
this.currentConcurrency--
|
||||
this.handleTaskCompletion(batchId, subBatchId, { taskId, error })
|
||||
// 执行传入的错误后执行方法,一般用于修改后台任务或者是批量提示
|
||||
if (errorFunc) {
|
||||
errorFunc(
|
||||
batchId,
|
||||
`任务 ${taskId} 执行失败,错误信息:${error.toString()},开始清理整个批次,批次ID:${batchId}`
|
||||
)
|
||||
}
|
||||
if (!this.manualMode) {
|
||||
this.process()
|
||||
}
|
||||
@ -151,6 +158,13 @@ export class AsyncQueue {
|
||||
// 出现报错。直接停掉当前对应的的子批次
|
||||
this.currentConcurrency--
|
||||
this.handleTaskCompletion(batchId, subBatchId, { taskId, error })
|
||||
// 执行传入的错误后执行方法,一般用于修改后台任务或者是批量提示
|
||||
if (errorFunc) {
|
||||
errorFunc(
|
||||
batchId,
|
||||
`任务 ${taskId} 执行失败,错误信息:${error.toString()},开始清理整个批次,批次ID:${batchId}`
|
||||
)
|
||||
}
|
||||
if (!this.manualMode) {
|
||||
this.process()
|
||||
} else {
|
||||
|
||||
1
src/model/Setting/softwareSetting.d.ts
vendored
1
src/model/Setting/softwareSetting.d.ts
vendored
@ -40,5 +40,6 @@ declare namespace SoftwareSettingModel {
|
||||
gpt_key: string = undefined // GPT KEY,
|
||||
laiApiSelect: string = undefined // LaiAPI选择
|
||||
hdScale: number = 2 // HD缩放
|
||||
defaultImageMode: BookImageCategory = 'mj' // 默认图片模式
|
||||
}
|
||||
}
|
||||
31
src/model/task.d.ts
vendored
31
src/model/task.d.ts
vendored
@ -1,6 +1,7 @@
|
||||
import { BookBackTaskStatus, BookBackTaskType, TaskExecuteType } from "@/define/enum/bookEnum"
|
||||
|
||||
declare namespace TaskModal {
|
||||
type Task = {
|
||||
interface Task {
|
||||
id?: string
|
||||
bookId?: string
|
||||
bookTaskId?: string
|
||||
@ -16,4 +17,32 @@ declare namespace TaskModal {
|
||||
endTime?: number,
|
||||
messageName?: string
|
||||
}
|
||||
|
||||
interface TaskCondition {
|
||||
bookName?: string,
|
||||
bookTaskName?: string,
|
||||
bookTaskDetailName?: string,
|
||||
taskName?: string,
|
||||
taskType?: BookBackTaskType,
|
||||
taskStatus?: BookBackTaskStatus,
|
||||
taskErrorMessage?: string
|
||||
}
|
||||
|
||||
interface QueryTaskCondition extends TaskCondition {
|
||||
page: number,
|
||||
pageSize: number
|
||||
}
|
||||
|
||||
interface BackTaskCollection extends Task {
|
||||
bookName?: string
|
||||
bookTaskName?: string
|
||||
bookTaskDetailName?: string
|
||||
}
|
||||
|
||||
type TaskCollection = {
|
||||
page: number,
|
||||
pageSize: number,
|
||||
count: number,
|
||||
data: BackTaskCollection[]
|
||||
}
|
||||
}
|
||||
@ -179,6 +179,9 @@ const book = {
|
||||
GetImageUrlAndDownload: async (id: string, operateBookType: OperateBookType, coverData: boolean) =>
|
||||
await ipcRenderer.invoke(DEFINE_STRING.BOOK.GET_IMAGE_URL_AND_DOWNLOAD, id, operateBookType, coverData),
|
||||
|
||||
/** 添加一键生图后台任务 */
|
||||
GenerateAllTaskImage: async (ids: string[], operateBookType: OperateBookType) => await ipcRenderer.invoke(DEFINE_STRING.BOOK.GENERATE_ALL_TASK_IMAGE, ids, operateBookType),
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 一键反推的单个任务
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { ipcRenderer } from 'electron'
|
||||
import { DEFINE_STRING } from '../define/define_string'
|
||||
import { BookBackTaskStatus, BookBackTaskType, TaskExecuteType } from '../define/enum/bookEnum'
|
||||
import { TaskModal } from '@/model/task'
|
||||
|
||||
const task = {
|
||||
|
||||
@ -10,16 +11,8 @@ const task = {
|
||||
* @returns
|
||||
*/
|
||||
StartBackTask: async (isGiveUp: boolean) => await ipcRenderer.invoke(DEFINE_STRING.TASK.START_BACK_TASK, isGiveUp),
|
||||
/**
|
||||
* 添加单个任务
|
||||
* @param bookId 小说ID
|
||||
* @param taskType 任务类型
|
||||
* @param executeType 任务执行类型
|
||||
* @param bookTaskId 小说任务ID
|
||||
* @param bookTaskDetailId 小说分镜ID
|
||||
* @param responseMessageName 响应消息名称
|
||||
* @returns
|
||||
*/
|
||||
|
||||
/** 添加单个任务 */
|
||||
AddBookBackTask: async (bookId: string, taskType: BookBackTaskType,
|
||||
executeType = TaskExecuteType.AUTO,
|
||||
bookTaskId = null,
|
||||
@ -27,14 +20,14 @@ const task = {
|
||||
responseMessageName: string = null) =>
|
||||
await ipcRenderer.invoke(DEFINE_STRING.TASK.ADD_BOOK_BACK_TASK, bookId, taskType, executeType, bookTaskId, bookTaskDetailId, responseMessageName),
|
||||
|
||||
/**
|
||||
* 同时添加多个任务
|
||||
* @param task
|
||||
*/
|
||||
/** 同时添加多个任务 */
|
||||
AddMultiBookBackTask: async (task: TaskModal.Task[]) =>
|
||||
await ipcRenderer.invoke(DEFINE_STRING.TASK.ADD_MULTI_BOOK_BACK_TASK, task),
|
||||
|
||||
/** 获取等待中的任务 */
|
||||
GetAllStatusTaskCount: async (value: BookBackTaskStatus[]) => await ipcRenderer.invoke(DEFINE_STRING.TASK.GET_ALL_STATUS_TASK_COUNT, value),
|
||||
|
||||
/** 获取后台任务的集合,分页 */
|
||||
GetBackTaskCollection: async (queryTaskCondition: TaskModal.QueryTaskCondition) => await ipcRenderer.invoke(DEFINE_STRING.TASK.GET_BACK_TASK_COLLECTION, queryTaskCondition),
|
||||
}
|
||||
export { task }
|
||||
|
||||
@ -30,7 +30,13 @@ const write = {
|
||||
// 开始执行API相关的一系列任务
|
||||
ActionStart(aiSetting, word) {
|
||||
return ipcRenderer.invoke(DEFINE_STRING.WRITE.ACTION_START, aiSetting, word)
|
||||
}
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//#region 文案洗稿相关
|
||||
|
||||
/** 生成洗稿后文案 */
|
||||
GenerateAfterGptWord: async (ids: string[], isEmpty: boolean) => await ipcRenderer.invoke(DEFINE_STRING.WRITE.GENERATE_AFTER_GPT_WORD, ids, isEmpty),
|
||||
|
||||
//#endregion
|
||||
}
|
||||
19
src/renderer/src/components/BackTask/BackTask.vue
Normal file
19
src/renderer/src/components/BackTask/BackTask.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import TaskDataTable from './TaskDataTable.vue'
|
||||
|
||||
let props = defineProps({
|
||||
height: undefined
|
||||
})
|
||||
let height = ref(props.height - 220)
|
||||
|
||||
onMounted(() => {
|
||||
// 加载任务数据
|
||||
// height.value = props.height - 200
|
||||
console.log(height.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TaskDataTable :height="height" />
|
||||
</template>
|
||||
247
src/renderer/src/components/BackTask/TaskDataTable.vue
Normal file
247
src/renderer/src/components/BackTask/TaskDataTable.vue
Normal file
@ -0,0 +1,247 @@
|
||||
<template>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
inline
|
||||
:label-width="80"
|
||||
:model="softwareStore.backTask.queryData"
|
||||
size="small"
|
||||
style="min-width: 600px"
|
||||
>
|
||||
<n-grid x-gap="12" y-gap="0" cols="5">
|
||||
<n-grid-item>
|
||||
<n-form-item label="任务名称" path="taskName">
|
||||
<n-input
|
||||
v-model:value="softwareStore.backTask.queryData.taskName"
|
||||
placeholder="请输入任务名称"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<n-form-item label="小说名" path="bookId">
|
||||
<n-input
|
||||
v-model:value="softwareStore.backTask.queryData.bookName"
|
||||
placeholder="请输入小说名称"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<n-form-item label="小说批次任务" path="bookTaskId">
|
||||
<n-input
|
||||
v-model:value="softwareStore.backTask.queryData.bookTaskName"
|
||||
placeholder="请输入小说批次任务名称"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<n-form-item label="小说分镜名称" path="bookTaskId">
|
||||
<n-input
|
||||
v-model:value="softwareStore.backTask.queryData.bookTaskDetailName"
|
||||
placeholder="请输入小说分镜名称"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<n-form-item label="任务类型" path="taskType">
|
||||
<n-select
|
||||
v-model:value="softwareStore.backTask.queryData.taskType"
|
||||
placeholder="请选择小说任务类型"
|
||||
:options="taskTypeOptions"
|
||||
clearable="true"
|
||||
>
|
||||
</n-select>
|
||||
</n-form-item>
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<n-form-item label="任务状态" path="taskStatus">
|
||||
<n-select
|
||||
v-model:value="softwareStore.backTask.queryData.taskStatus"
|
||||
placeholder="请选择小说任务类型"
|
||||
:options="taskStatusOptions"
|
||||
clearable="true"
|
||||
></n-select>
|
||||
</n-form-item>
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<n-form-item label="任务失败原因" path="taskErrorMessage">
|
||||
<n-input
|
||||
v-model:value="softwareStore.backTask.queryData.taskErrorMessage"
|
||||
placeholder="请输入小说失败原因"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<n-form-item path="taskErrorMessage">
|
||||
<n-button type="info" @click="ResetQuery">重置</n-button>
|
||||
<n-button style="margin-left: 10px" type="info" @click="QueryByByCondition"
|
||||
>查询</n-button
|
||||
>
|
||||
</n-form-item>
|
||||
</n-grid-item>
|
||||
</n-grid>
|
||||
</n-form>
|
||||
<n-data-table
|
||||
remote
|
||||
ref="table"
|
||||
:columns="columns"
|
||||
:data="softwareStore.backTask.taskData"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:row-key="rowKey"
|
||||
@update:page="handlePageChange"
|
||||
:style="{ height: `${height}px` }"
|
||||
flex-height
|
||||
:scroll-x="1000"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { h, onMounted, reactive, ref, render } from 'vue'
|
||||
import {
|
||||
NDataTable,
|
||||
useMessage,
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInput,
|
||||
NButton,
|
||||
NGrid,
|
||||
NGridItem,
|
||||
NSelect
|
||||
} from 'naive-ui'
|
||||
import { useSoftwareStore } from '@/stores/software'
|
||||
import {
|
||||
BookBackTaskStatus,
|
||||
BookBackTaskType,
|
||||
GetBookBackTaskStatusLabel,
|
||||
GetBookBackTaskTypeLabel
|
||||
} from '@/define/enum/bookEnum'
|
||||
let softwareStore = useSoftwareStore()
|
||||
let message = useMessage()
|
||||
let loading = ref(true)
|
||||
|
||||
let props = defineProps({
|
||||
height: undefined
|
||||
})
|
||||
let height = ref(props.height)
|
||||
let columns = [
|
||||
{
|
||||
title: '任务名(小说名+批次任务名+分镜名+任务类型)',
|
||||
key: 'name',
|
||||
width: '350px'
|
||||
},
|
||||
{
|
||||
title: '消息名称',
|
||||
key: 'messageName',
|
||||
minWidth: 200,
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '任务类型',
|
||||
key: 'type',
|
||||
minWidth: 100
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
minWidth: 100
|
||||
},
|
||||
{
|
||||
title: '失败原因',
|
||||
key: 'errorMessage',
|
||||
minWidth: 300,
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
async function ResetQuery() {
|
||||
softwareStore.ResetBackTaskQueryData()
|
||||
await query(1, pagination.value.pageSize)
|
||||
}
|
||||
|
||||
async function QueryByByCondition() {
|
||||
await query(1, pagination.value.pageSize)
|
||||
}
|
||||
|
||||
async function query(page, pageSize = 10) {
|
||||
try {
|
||||
loading.value = true
|
||||
let res = await window.task.GetBackTaskCollection({
|
||||
page,
|
||||
pageSize,
|
||||
...softwareStore.backTask.queryData
|
||||
})
|
||||
console.log(res)
|
||||
if (res.code == 0) {
|
||||
message.error(res.message)
|
||||
} else {
|
||||
softwareStore.backTask.taskData = res.data.data
|
||||
pagination.value.page = page
|
||||
pagination.value.pageCount = Math.ceil(res.data.count / pageSize)
|
||||
pagination.value.itemCount = res.data.count
|
||||
}
|
||||
} catch (error) {
|
||||
message.error(error.message)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
const pagination = ref({
|
||||
page: 1,
|
||||
pageCount: 1,
|
||||
pageSize: 10,
|
||||
showSizePicker: true,
|
||||
pageSizes: [10, 20, 50, 100, 200, 500],
|
||||
prefix({ itemCount }) {
|
||||
return `Total is ${itemCount}.`
|
||||
},
|
||||
onUpdatePageSize: async (pageSize) => {
|
||||
pagination.value.pageSize = pageSize
|
||||
await handlePageChange(pagination.value.page)
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
debugger
|
||||
height.value = props.height
|
||||
console.log(height.value)
|
||||
await query(pagination.value.page, pagination.value.pageSize)
|
||||
})
|
||||
|
||||
let rowKey = (rowData) => rowData.column1
|
||||
|
||||
async function handlePageChange(currentPage) {
|
||||
if (!loading.value) {
|
||||
loading.value = true
|
||||
await query(currentPage, pagination.value.pageSize)
|
||||
pagination.value.page = currentPage
|
||||
pagination.value.pageSize = pagination.value.pageSize
|
||||
}
|
||||
}
|
||||
|
||||
let GetBookBackTaskType = () => {
|
||||
let options = []
|
||||
for (const key in BookBackTaskType) {
|
||||
options.push({
|
||||
label: GetBookBackTaskTypeLabel(BookBackTaskType[key]),
|
||||
value: BookBackTaskType[key]
|
||||
})
|
||||
}
|
||||
return options
|
||||
}
|
||||
let taskTypeOptions = GetBookBackTaskType()
|
||||
|
||||
let GeBookBackTaskStatus = () => {
|
||||
let options = []
|
||||
for (const key in BookBackTaskStatus) {
|
||||
options.push({
|
||||
label: GetBookBackTaskStatusLabel(BookBackTaskStatus[key]),
|
||||
value: BookBackTaskStatus[key]
|
||||
})
|
||||
}
|
||||
return options
|
||||
}
|
||||
let taskStatusOptions = GeBookBackTaskStatus()
|
||||
</script>
|
||||
@ -99,7 +99,6 @@ export default defineComponent({
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.7
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
|
||||
@ -397,7 +397,6 @@ export default defineComponent({
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.8
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
@ -479,7 +478,6 @@ export default defineComponent({
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = 800
|
||||
let dialogHeight = 600
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
|
||||
@ -652,7 +652,6 @@ export default defineComponent({
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.7
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
|
||||
@ -51,7 +51,6 @@ async function EditBook(e) {
|
||||
reverseManageStore.SetSelectBook(toRaw(book.value))
|
||||
// 一个弹窗添加数据
|
||||
let dialogWidth = 600
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
|
||||
@ -83,11 +83,10 @@ export default defineComponent({
|
||||
reverseManageStore.SetSelectBook({
|
||||
name: null,
|
||||
id: null,
|
||||
type: BookType.MJ_REVERSE
|
||||
type: BookType.ORIGINAL,
|
||||
})
|
||||
// 一个弹窗添加数据
|
||||
let dialogWidth = 600
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
@ -115,7 +114,6 @@ export default defineComponent({
|
||||
|
||||
// 选择下拉菜单
|
||||
async function SelectDropdown(key) {
|
||||
|
||||
console.log(key)
|
||||
softwareStore.softWare.reverse_data_table_size = key
|
||||
// 直接提交修改
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<template #2>
|
||||
<div style="margin-left: 20px">
|
||||
<div style="margin-left: 20px; min-width: 500px; overflow: auto">
|
||||
<AddCharacterTag
|
||||
v-if="currentType.startsWith('character')"
|
||||
:currentCharacter="currentCharacter"
|
||||
|
||||
@ -243,8 +243,6 @@ async function SelectReversePrompt() {
|
||||
message.error('当前没有反推提示词')
|
||||
return
|
||||
}
|
||||
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
title: `重选MJ反推提示词 ${data.value.name}`,
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
size="tiny"
|
||||
:options="image_options"
|
||||
@update:value="UpdateImageGenerateCategory"
|
||||
v-model:value="reverseManageStore.selectBookTask.imageCategory"
|
||||
v-model:value="select"
|
||||
placeholder="选择生图模式"
|
||||
></n-select>
|
||||
<div v-if="reverseManageStore.selectBookTask.imageCategory == 'mj'">
|
||||
@ -38,7 +38,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { NSelect, NButton, useMessage, useDialog, NPopover, NIcon } from 'naive-ui'
|
||||
import { useSoftwareStore } from '../../../../../stores/software'
|
||||
import { useReverseManageStore } from '../../../../../stores/reverseManage'
|
||||
@ -50,6 +50,12 @@ let dialog = useDialog()
|
||||
let reverseManageStore = useReverseManageStore()
|
||||
let image_options = ref([])
|
||||
|
||||
let select = computed(() =>
|
||||
reverseManageStore.selectBookTask.imageCategory
|
||||
? reverseManageStore.selectBookTask.imageCategory
|
||||
: softwareStore.globalSetting.defaultImageMode
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
// 获取生图下拉列表的方式
|
||||
await window.api.GetImageGenerateCategory((value) => {
|
||||
@ -68,6 +74,7 @@ async function UpdateImageGenerateCategory(value, options) {
|
||||
imageCategory: value
|
||||
})
|
||||
window.api.showGlobalMessage(res)
|
||||
reverseManageStore.selectBookTask.imageCategory = value
|
||||
}
|
||||
|
||||
async function DownloadAllImage() {
|
||||
|
||||
@ -172,6 +172,7 @@ async function SelectPromptIndex() {
|
||||
title: '选择反推提示词',
|
||||
content: () => h(SelectMJReversePrompt),
|
||||
style: 'width : 500px',
|
||||
maskClosable: false,
|
||||
showIcon: false
|
||||
})
|
||||
}
|
||||
@ -183,7 +184,6 @@ async function SelectStyle() {
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.8
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
|
||||
@ -45,11 +45,12 @@ export default defineComponent({
|
||||
let select = computed(() =>
|
||||
reverseManageStore.selectBookTask.imageCategory
|
||||
? reverseManageStore.selectBookTask.imageCategory
|
||||
: BookImageCategory.MJ
|
||||
: softwareStore.globalSetting.defaultImageMode
|
||||
)
|
||||
let options = ref([])
|
||||
|
||||
onMounted(async () => {
|
||||
debugger
|
||||
// 获取生图下拉列表的方式
|
||||
await window.api.GetImageGenerateCategory((value) => {
|
||||
if (value.code == 0) {
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
<template>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<div style="display: flex; align-items: center">
|
||||
<n-button strong secondary @click="RetuenMain" size="small"> 返回 </n-button>
|
||||
<n-button strong secondary @click="RetuenMain" size="small">
|
||||
{{
|
||||
'返回 | ' +
|
||||
reverseManageStore.selectBook?.name +
|
||||
'_' +
|
||||
reverseManageStore.selectBookTask?.name
|
||||
}}
|
||||
</n-button>
|
||||
<!-- <n-dropdown trigger="hover" :options="AutoOptions" @select="SelectAutoAction">
|
||||
<n-button :color="softwareStore.SoftColor.ORANGE" @click="Start" style="margin-left: 5px">
|
||||
自动开始
|
||||
@ -206,6 +213,7 @@ async function ComputeStoryboard() {
|
||||
async function JianyingFrame() {
|
||||
let da = dialog.info({
|
||||
title: '剪映分镜参数',
|
||||
maskClosable: false,
|
||||
content: () => h(JianyingFrameOption)
|
||||
})
|
||||
}
|
||||
@ -403,7 +411,6 @@ async function GetWatermarkPosition() {
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.7
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
@ -806,6 +813,7 @@ async function ImportWordAndSrtFunc() {
|
||||
|
||||
let tempData = []
|
||||
for (let i = 0; i < reverseManageStore.selectBookTaskDetail.length; i++) {
|
||||
debugger
|
||||
const element = reverseManageStore.selectBookTaskDetail[i]
|
||||
tempData.push({
|
||||
no: element.no,
|
||||
@ -820,7 +828,6 @@ async function ImportWordAndSrtFunc() {
|
||||
})
|
||||
}
|
||||
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
|
||||
@ -54,6 +54,7 @@ async function OpenGetVideoFrame() {
|
||||
dialog.create({
|
||||
title: '获取视频的帧',
|
||||
style: 'width : 800px;',
|
||||
maskClosable: false,
|
||||
content: () =>
|
||||
h(GetVideoFrame, {
|
||||
videoPath: data.value.videoPath,
|
||||
|
||||
@ -3,6 +3,9 @@
|
||||
<n-button :render-icon="renderIcon" size="small" type="info" @click="AddBookDialog()"
|
||||
>新增</n-button
|
||||
>
|
||||
<n-button style="margin-left: 5px" size="small" type="info" @click="GenerateAllTaskImage()"
|
||||
>一键生图</n-button
|
||||
>
|
||||
<n-button style="margin-left: 5px" size="small" type="info" @click="HDImageAll()"
|
||||
>一键高清</n-button
|
||||
>
|
||||
@ -55,7 +58,7 @@ import {
|
||||
} from 'naive-ui'
|
||||
import { useReverseManageStore } from '../../../../stores/reverseManage'
|
||||
import { useSoftwareStore } from '../../../../stores/software'
|
||||
import { AddSharp } from '@vicons/ionicons5'
|
||||
import { AddSharp, Open } from '@vicons/ionicons5'
|
||||
import BookTaskListAction from './Components/ManageBook/BookTaskListAction.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { OperateBookType } from '../../../../define/enum/bookEnum'
|
||||
@ -63,6 +66,7 @@ import { DEFINE_STRING } from '../../../../define/define_string'
|
||||
import { ResponseMessageType } from '../../../../define/enum/softwareEnum'
|
||||
import AddBookTask from './Components/ManageBook/AddBookTask.vue'
|
||||
import ManageBookTaskGenerateInformation from './Components/ManageBook/ManageBookTaskGenerateInformation.vue'
|
||||
import { isEmpty } from 'lodash'
|
||||
|
||||
let reverseManageStore = useReverseManageStore()
|
||||
let softwareStore = useSoftwareStore()
|
||||
@ -125,6 +129,11 @@ function createColumns() {
|
||||
key: 'prefix',
|
||||
width: 130
|
||||
},
|
||||
{
|
||||
title: '出图方式',
|
||||
key: 'imageCategory',
|
||||
width: 90
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
@ -161,6 +170,10 @@ function createOptions(row) {
|
||||
label: `合成视频 ${row.name}`,
|
||||
key: 'generateVideo'
|
||||
},
|
||||
{
|
||||
label: `打开生图文件夹`,
|
||||
key: 'openImageFolder'
|
||||
},
|
||||
{
|
||||
label: () => h('span', { style: { color: '#f4a534' } }, `重置 ${row.name}`),
|
||||
key: 'reset'
|
||||
@ -263,6 +276,23 @@ async function GenerateVideo(value) {
|
||||
})
|
||||
}
|
||||
|
||||
async function OpenImageFolder(value) {
|
||||
debugger
|
||||
if (isEmpty(value.imageFolder)) {
|
||||
message.error('没有找到对应的文件夹')
|
||||
return
|
||||
}
|
||||
let res = await window.system.OpenFolder({
|
||||
folderPath: value.imageFolder,
|
||||
baseProject: false
|
||||
})
|
||||
if (res.code == 0) {
|
||||
message.error(res.message)
|
||||
return
|
||||
}
|
||||
message.success('打开文件夹成功')
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置小说数据
|
||||
* @param e
|
||||
@ -328,6 +358,9 @@ async function handleSelect(key) {
|
||||
case 'generateVideo':
|
||||
await GenerateVideo(selectRow.value)
|
||||
break
|
||||
case 'openImageFolder':
|
||||
await OpenImageFolder(selectRow.value)
|
||||
break
|
||||
case 'reset':
|
||||
await ReSetBookTaskDetail(selectRow.value)
|
||||
break
|
||||
@ -344,20 +377,31 @@ function onClickoutside() {
|
||||
showDropdown.value = false
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 高清数据
|
||||
// */
|
||||
// async function hdImageFunc2(id, operateBookType) {
|
||||
// softwareStore.spin.spinning = true
|
||||
// softwareStore.spin.tip = '正在高清中。。。'
|
||||
// let res = await window.book.HDImage(id, 4, operateBookType)
|
||||
// softwareStore.spin.spinning = false
|
||||
// if (res.code == 1) {
|
||||
// message.success('高清成功')
|
||||
// } else {
|
||||
// message.error(res.message)
|
||||
// }
|
||||
// }
|
||||
// 一键生图
|
||||
async function GenerateAllTaskImage() {
|
||||
if (checkedRowKeysRef.value.length == 0) {
|
||||
message.error('请选择要生图的数据')
|
||||
return
|
||||
}
|
||||
let da = dialog.warning({
|
||||
title: '一键生图提示',
|
||||
content:
|
||||
'即将开始添加生图任务,会按照每个批次的出图方式添加后台任务,添加之后不可修改,请检查每个批次的出图方式,是否继续?',
|
||||
positiveText: '继续',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
da?.destroy()
|
||||
softwareStore.spin.spinning = true
|
||||
softwareStore.spin.tip = '正在校验/添加生图任务。。。'
|
||||
let res = await window.book.GenerateAllTaskImage(
|
||||
[...checkedRowKeysRef.value],
|
||||
OperateBookType.ASSIGNBOOKTASK
|
||||
)
|
||||
window.api.showGlobalMessageDialog(res);
|
||||
softwareStore.spin.spinning = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键高清全部
|
||||
@ -406,6 +450,7 @@ async function AddBookDialog() {
|
||||
dialog.create({
|
||||
title: '新增小说批次任务',
|
||||
showIcon: false,
|
||||
maskClosable: false,
|
||||
content: () => h(AddBookTask),
|
||||
style: { width: '600px' }
|
||||
})
|
||||
@ -486,6 +531,7 @@ async function ResetAll() {
|
||||
return
|
||||
}
|
||||
message.success('重置小说任务成功')
|
||||
checkedRowKeysRef.value = []
|
||||
} else {
|
||||
message.error(res.message)
|
||||
}
|
||||
@ -525,6 +571,7 @@ async function DeleteAll() {
|
||||
}
|
||||
// 删除成功
|
||||
message.success('删除小说任务并刷新数据成功')
|
||||
checkedRowKeysRef.value = []
|
||||
} else {
|
||||
message.error(res.message)
|
||||
}
|
||||
|
||||
@ -274,7 +274,6 @@ async function SelectStyle() {
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.8
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
|
||||
@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<div style="display: flex; align-items: center">
|
||||
<div style="display: flex">
|
||||
<n-button strong secondary @click="ReturnMain" size="small">返回</n-button>
|
||||
<n-button strong secondary @click="ReturnMain" size="small">{{
|
||||
'返回 | ' +
|
||||
reverseManageStore.selectBook?.name +
|
||||
'_' +
|
||||
reverseManageStore.selectBookTask?.name
|
||||
}}</n-button>
|
||||
<n-divider vertical style="height: 30px" />
|
||||
<!-- <n-button strong secondary @click="ReturnMain" size="small">一键全自动</n-button>
|
||||
<n-divider vertical style="height: 30px" /> -->
|
||||
@ -133,7 +138,6 @@ async function ImportWord() {
|
||||
})
|
||||
}
|
||||
|
||||
// ImportWordAndSrt
|
||||
let da = dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
@ -162,7 +166,7 @@ async function ImportWord() {
|
||||
async function CharacterLibrary() {
|
||||
// 判断当前数据是不是存在
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.6
|
||||
let dialogWidth = 1000
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
let word = '' // 这边要拼接一下word
|
||||
|
||||
@ -373,7 +377,6 @@ async function GetPromptAll() {
|
||||
* @param {Boolean} cover - 是否覆盖现有图像
|
||||
*/
|
||||
async function AddFluxImageAll(type, cover) {
|
||||
|
||||
let messageName = DEFINE_STRING.BOOK.FLUX_API_IMAGE_GENERATE_RETURN
|
||||
let taskType = BookBackTaskType.FLUX_API_IMAGE
|
||||
if (type == BookImageCategory.FLUX_FORGE) {
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useMessage, NButton, NFloatButton, NBadge, NIcon } from 'naive-ui'
|
||||
import { Layers } from '@vicons/ionicons5'
|
||||
import { useSoftwareStore } from '../../../../../stores/software'
|
||||
import QueryButton from './QueryButton.vue'
|
||||
import TaskDataTable from './TaskDataTable.vue'
|
||||
|
||||
let softwareStore = useSoftwareStore()
|
||||
|
||||
onMounted(() => {
|
||||
// 加载任务数据
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QueryButton />
|
||||
<TaskDataTable />
|
||||
</template>
|
||||
@ -1,57 +0,0 @@
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useMessage, NForm, NFormItem, NInput, NButton } from 'naive-ui'
|
||||
import { useSoftwareStore } from '../../../../../stores/software'
|
||||
let softwareStore = useSoftwareStore()
|
||||
|
||||
function handleSubmit() {
|
||||
alert(123)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-form
|
||||
ref="formRef"
|
||||
inline
|
||||
:label-width="80"
|
||||
:model="softwareStore.backTask.queryData"
|
||||
size="small"
|
||||
>
|
||||
<n-form-item label="小说" path="bookId">
|
||||
<n-input v-model:value="softwareStore.backTask.queryData.bookId" placeholder="选择小说任务" />
|
||||
</n-form-item>
|
||||
<n-form-item label="小说批次任务" path="bookTaskId">
|
||||
<n-input
|
||||
v-model:value="softwareStore.backTask.queryData.bookTaskId"
|
||||
placeholder="选择小说批次任务"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="任务名字" path="taskName">
|
||||
<n-input
|
||||
v-model:value="softwareStore.backTask.queryData.taskName"
|
||||
placeholder="选择小说批次任务"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="任务类型" path="taskType">
|
||||
<n-input
|
||||
v-model:value="softwareStore.backTask.queryData.taskType"
|
||||
placeholder="选择小说批次任务"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="任务状态" path="taskStatus">
|
||||
<n-input
|
||||
v-model:value="softwareStore.backTask.queryData.taskStatus"
|
||||
placeholder="选择小说批次任务"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="任务失败原因" path="taskErrorMessage">
|
||||
<n-input
|
||||
v-model:value="softwareStore.backTask.queryData.taskErrorMessage"
|
||||
placeholder="选择小说批次任务"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="taskErrorMessage">
|
||||
<n-button type="info" @click="handleSubmit">查询</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</template>
|
||||
@ -1,7 +0,0 @@
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>TaskDataTable</div>
|
||||
</template>
|
||||
@ -64,7 +64,7 @@ import { MD5 } from 'crypto-js'
|
||||
import InputDialogContent from '../Original/Components/InputDialogContent.vue'
|
||||
import APIIcon from '../Icon/APIIcon.vue'
|
||||
import BackTaskIcon from '../Icon/BackTaskIcon.vue'
|
||||
import BackTask from '../Components/BackTask/BackTask.vue'
|
||||
import BackTask from '@/renderer/src/components/BackTask/BackTask.vue'
|
||||
import { useSystemStore } from '../../../../stores/system'
|
||||
import { TimeDelay } from '../../../../define/Tools/time'
|
||||
import { BookBackTaskStatus } from '../../../../define/enum/bookEnum'
|
||||
@ -603,7 +603,8 @@ function renderIcon(icon) {
|
||||
}
|
||||
|
||||
function OpneBackTask() {
|
||||
let dialogWidth = window.innerWidth * 0.8
|
||||
let dialogWidth = window.innerWidth * 0.9
|
||||
if (dialogWidth < 800) dialogWidth = 800
|
||||
let dialogHeight = window.innerHeight * 0.95
|
||||
dialog.create({
|
||||
title: '后台任务',
|
||||
|
||||
@ -1,6 +1,22 @@
|
||||
<template>
|
||||
<div id="import_word_and_srt">
|
||||
<div style="height: 30px; margin-bottom: 5px">
|
||||
<n-button
|
||||
v-if="type != 'original'"
|
||||
color="#1e90ff"
|
||||
size="small"
|
||||
style="margin-left: 20px"
|
||||
@click="ExecuteAfterGptWord(false)"
|
||||
>一键洗稿</n-button
|
||||
>
|
||||
<n-button
|
||||
v-if="type != 'original'"
|
||||
color="#1e90ff"
|
||||
size="small"
|
||||
style="margin-left: 20px"
|
||||
@click="ExecuteAfterGptWord(true)"
|
||||
>继续洗稿(勾选未出)</n-button
|
||||
>
|
||||
<n-button
|
||||
v-if="type == 'original'"
|
||||
color="#1e90ff"
|
||||
@ -32,8 +48,8 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { h, defineComponent, onMounted, ref, toRaw, watch, onUnmounted } from 'vue'
|
||||
<script setup>
|
||||
import { h, onMounted, ref, toRaw, onUnmounted } from 'vue'
|
||||
import { NButton, NDataTable, useMessage, NInput, NImage, useDialog } from 'naive-ui'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import EditWord from './EditWord.vue'
|
||||
@ -47,16 +63,15 @@ const buttonArr = [
|
||||
}
|
||||
]
|
||||
import InputDialogContent from './InputDialogContent.vue'
|
||||
import { DEFINE_STRING } from '@/define/define_string'
|
||||
|
||||
let props = defineProps({
|
||||
initData: undefined,
|
||||
menuType: undefined,
|
||||
height: undefined,
|
||||
type: undefined
|
||||
})
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NButton,
|
||||
NDataTable,
|
||||
NInput,
|
||||
NImage
|
||||
},
|
||||
props: ['initData', 'menuType', 'height', 'type'],
|
||||
setup(props) {
|
||||
let hh = props.height
|
||||
let maxHeight = props.height - 80
|
||||
let data = ref(JSON.parse(JSON.stringify(props.initData)))
|
||||
@ -68,8 +83,36 @@ export default defineComponent({
|
||||
let type = ref(props.type ? props.type : 'original')
|
||||
let reverseManageStore = useReverseManageStore()
|
||||
|
||||
async function ExecuteAfterGptWord(isEmpty) {
|
||||
if (selectKey.value.length <= 0) {
|
||||
message.error('请选择需要洗稿的数据')
|
||||
return
|
||||
}
|
||||
await AfterGptWordFunc([...selectKey.value], isEmpty)
|
||||
}
|
||||
async function AfterGptWordFunc(ids, isEmpty) {
|
||||
let da = dialog.warning({
|
||||
title: '洗稿提示',
|
||||
content: isEmpty
|
||||
? '是否继续洗稿(勾选未出)'
|
||||
: '将对所有的数据进行洗稿' +
|
||||
',在洗稿钱会删除洗稿后文案,该操作不可逆,即使出现报错删掉的还是删掉了,是否继续?',
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
da.destroy()
|
||||
let res = await window.write.GenerateAfterGptWord(ids, isEmpty)
|
||||
if (res.code == 1) {
|
||||
message.success('洗稿成功')
|
||||
} else {
|
||||
message.error(res.message)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const createColumns = ({ AlignNextWord }) => {
|
||||
return [
|
||||
let col = [
|
||||
{
|
||||
type: 'selection',
|
||||
disabled(row) {
|
||||
@ -82,16 +125,30 @@ export default defineComponent({
|
||||
width: 70
|
||||
},
|
||||
{
|
||||
title: '分镜文案',
|
||||
key: 'after_gpt',
|
||||
title: '文案',
|
||||
key: 'word',
|
||||
width: 300,
|
||||
render(row, index) {
|
||||
return h(NInput, {
|
||||
value: row.word,
|
||||
disabled: true,
|
||||
type: 'textarea',
|
||||
autosize: true
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '洗稿后文案',
|
||||
key: 'after_gpt',
|
||||
width: 300,
|
||||
render(row, index) {
|
||||
return h(NInput, {
|
||||
value: row.after_gpt,
|
||||
type: 'textarea',
|
||||
autosize: true,
|
||||
onUpdateValue(v) {
|
||||
data.value[index].word = v
|
||||
data.value[index].after_gpt = v
|
||||
reverseManageStore.selectBookTaskDetail[index].afterGpt = v
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -165,6 +222,12 @@ export default defineComponent({
|
||||
width: 120
|
||||
}
|
||||
]
|
||||
|
||||
if (props.type == 'original') {
|
||||
return col.filter((item) => item.key != 'after_gpt')
|
||||
} else {
|
||||
return col
|
||||
}
|
||||
}
|
||||
|
||||
// 设置窗体的高度
|
||||
@ -178,10 +241,27 @@ export default defineComponent({
|
||||
|
||||
// 监听 ctrl + alt + w 键盘的按键事件
|
||||
window.addEventListener('keydown', ImportWenKeSrt)
|
||||
|
||||
// 监听FLUX API 出图返回的数据
|
||||
window.api.setEventListen([DEFINE_STRING.WRITE.GENERATE_AFTER_GPT_WORD_RESPONSE], (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
let findIndex = reverseManageStore.selectBookTaskDetail.findIndex((item) => item.id == value.id)
|
||||
if (findIndex != -1) {
|
||||
reverseManageStore.selectBookTaskDetail[findIndex].afterGpt = value.data
|
||||
}
|
||||
let dataIndex = data.value.findIndex((item) => item.id == value.id)
|
||||
if (dataIndex != -1) {
|
||||
data.value[dataIndex].after_gpt = value.data
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('keydown', ImportWenKeSrt)
|
||||
window.api.removeEventListen(DEFINE_STRING.WRITE.GENERATE_AFTER_GPT_WORD_RESPONSE)
|
||||
})
|
||||
|
||||
/**
|
||||
@ -207,7 +287,6 @@ export default defineComponent({
|
||||
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px`,
|
||||
maskClosable: false,
|
||||
onClose: async () => {
|
||||
|
||||
console.log(wenkeRef.value.word)
|
||||
let word = wenkeRef.value.data
|
||||
if (word == null || word == '') {
|
||||
@ -522,6 +601,7 @@ export default defineComponent({
|
||||
* 保存字幕文案信息,用于自动生成视频
|
||||
*/
|
||||
async function SaveCopywritingInformation() {
|
||||
try {
|
||||
if (type.value == 'original') {
|
||||
if (props.menuType == 'mj') {
|
||||
await window.mj.SvaeMJWordSrt([toRaw(data.value), 'srt_time_information'], (value) => {
|
||||
@ -559,7 +639,6 @@ export default defineComponent({
|
||||
})
|
||||
}
|
||||
} else if (type.value == 'mj_reverse' || type.value == 'sd_reverse') {
|
||||
debugger
|
||||
if (data.value.length != reverseManageStore.selectBookTaskDetail.length) {
|
||||
message.error('检测到导入的字幕数据和分镜对不上,请先对齐')
|
||||
return
|
||||
@ -571,9 +650,14 @@ export default defineComponent({
|
||||
startTime: element.start_time,
|
||||
endTime: element.end_time,
|
||||
timeLimit: element.timeLimit,
|
||||
afterGpt: element.after_gpt,
|
||||
subValue: JSON.stringify(element.subValue)
|
||||
})
|
||||
}
|
||||
message.success('保存成功')
|
||||
}
|
||||
} catch (error) {
|
||||
message.error('保存失败')
|
||||
}
|
||||
}
|
||||
|
||||
@ -621,7 +705,6 @@ export default defineComponent({
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.7
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
@ -664,24 +747,11 @@ export default defineComponent({
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
data,
|
||||
columns: createColumns({
|
||||
let columns = createColumns({
|
||||
AlignNextWord
|
||||
}),
|
||||
rowKey: (row) => row.id,
|
||||
handleCheck(rowKeys) {
|
||||
selectKey.value = rowKeys
|
||||
},
|
||||
ImportSrtAndGetTime,
|
||||
SaveCopywritingInformation,
|
||||
OpenOneDialog,
|
||||
maxHeight,
|
||||
hh,
|
||||
wenkeRef,
|
||||
type,
|
||||
reverseManageStore
|
||||
}
|
||||
}
|
||||
})
|
||||
let rowKey = (row) => row.id
|
||||
let handleCheck = (rowKeys) => {
|
||||
selectKey.value = rowKeys
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -315,7 +315,8 @@ export default defineComponent({
|
||||
let sdObj = {
|
||||
batch_size: toRaw(sd_batch_size.value),
|
||||
width: toRaw(sd_image_width.value),
|
||||
height: toRaw(sd_image_height.value)
|
||||
height: toRaw(sd_image_height.value),
|
||||
seed: toRaw(sd_seed.value)
|
||||
}
|
||||
await window.api.SaveSDConfig(sdObj, (value) => {
|
||||
if (value.code == 0) {
|
||||
|
||||
@ -615,7 +615,6 @@ export default defineComponent({
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.8
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
|
||||
@ -114,7 +114,6 @@ export default defineComponent({
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.95
|
||||
let dialogHeight = window.innerHeight * 0.95
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
@ -133,9 +132,8 @@ export default defineComponent({
|
||||
async function GetCharacter() {
|
||||
// 判断当前数据是不是存在
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.6
|
||||
let dialogWidth = 1000
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
@ -217,7 +215,6 @@ export default defineComponent({
|
||||
* 生成所有的图片
|
||||
*/
|
||||
async function GenerateImageAll() {
|
||||
|
||||
let tmpData = cloneDeep(toRaw(data.value))
|
||||
tmpData = tmpData.filter((item) => {
|
||||
return item.imageLock == null || item.imageLock == false
|
||||
@ -367,7 +364,6 @@ export default defineComponent({
|
||||
console.log(value.value)
|
||||
// 拿到提示词文件地址,然后还是获取
|
||||
await window.pmpt.OpenPromptFileTxt(value.value, (res) => {
|
||||
|
||||
console.log(res)
|
||||
if (res.code == 0) {
|
||||
message.error(res.message)
|
||||
@ -382,7 +378,6 @@ export default defineComponent({
|
||||
positiveText: '继续',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
|
||||
// 开始导入
|
||||
for (let i = 0; i < data.value.length && i < res.data.length; i++) {
|
||||
const element = res.data[i]
|
||||
|
||||
@ -36,6 +36,25 @@
|
||||
placeholder="输入重绘幅度"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="SD批次出图张数" style="margin-right: 30px">
|
||||
<n-input-number
|
||||
:min="0"
|
||||
:max="30"
|
||||
:step="1"
|
||||
:default-value="1"
|
||||
v-model:value="formValue.batch_size"
|
||||
placeholder="SD批次出图张数"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="种子值" style="margin-right: 30px">
|
||||
<n-input-number
|
||||
:min="-1"
|
||||
:step="1"
|
||||
:default-value="-1"
|
||||
v-model:value="formValue.seed"
|
||||
placeholder="SD批次出图张数"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="重绘幅度" path="denoising_strength">
|
||||
<n-input-number
|
||||
:precision="2"
|
||||
|
||||
@ -71,6 +71,16 @@
|
||||
>
|
||||
</n-form-item>
|
||||
</n-form-item>
|
||||
<n-form-item path="image_setting" label="生图设置">
|
||||
<n-form-item path="defaultImageMode" label="默认生图模式">
|
||||
<n-select
|
||||
v-model:value="formValue.defaultImageMode"
|
||||
:options="defaultImageModeOptions"
|
||||
placeholder="选择默认的生图模式"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form-item>
|
||||
<n-form-item path="gpt_setting" label="GPT设置">
|
||||
<n-form-item path="gpt_business" label="GPT接口服务商">
|
||||
<n-select
|
||||
@ -161,7 +171,7 @@
|
||||
</NSpace>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref, toRaw, onMounted, defineComponent, h } from 'vue'
|
||||
import {
|
||||
NForm,
|
||||
@ -183,26 +193,9 @@ import { FolderOpenSharp as FolderOpen } from '@vicons/ionicons5'
|
||||
import AddGptPrompts from './Components/AddGptPrompts.vue'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { useSoftwareStore } from '../../../../stores/software'
|
||||
import { TranslateAPIType } from '../../../../define/enum/translate'
|
||||
import TranslateSetting from './TranslateSetting.vue'
|
||||
import { LaiAPIType } from '../../../../define/enum/softwareEnum'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInput,
|
||||
NInputNumber,
|
||||
NButton,
|
||||
NSpace,
|
||||
NSpin,
|
||||
NSelect,
|
||||
NCheckbox,
|
||||
NSwitch,
|
||||
FolderOpen,
|
||||
NIcon
|
||||
},
|
||||
setup() {
|
||||
let formRef = ref(null)
|
||||
let softwareStore = useSoftwareStore()
|
||||
let message = useMessage()
|
||||
@ -223,7 +216,8 @@ export default defineComponent({
|
||||
character_select_model: window.config.character_select_model,
|
||||
window_wh_bm_remember: window.config.window_wh_bm_remember,
|
||||
laiApiSelect: window.config.laiApiSelect ? window.config.laiApiSelect : LaiAPIType.MAIN,
|
||||
hdScale: window.config.hdScale ?? 2
|
||||
hdScale: window.config.hdScale ?? 2,
|
||||
defaultImageMode: window.config.defaultImageMode ?? 'mj'
|
||||
})
|
||||
let show = ref(false)
|
||||
let gpt_options = ref([])
|
||||
@ -245,6 +239,7 @@ export default defineComponent({
|
||||
])
|
||||
let dialog = useDialog()
|
||||
let loading = ref(false)
|
||||
let defaultImageModeOptions = ref([])
|
||||
/**
|
||||
* 加载GPT的配置信息
|
||||
*/
|
||||
@ -272,6 +267,15 @@ export default defineComponent({
|
||||
|
||||
onMounted(async () => {
|
||||
await InitGptOptions()
|
||||
|
||||
// 获取生图下拉列表的方式
|
||||
await window.api.GetImageGenerateCategory((value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
defaultImageModeOptions.value = value.data
|
||||
})
|
||||
})
|
||||
|
||||
// 切换翻译服务商事件
|
||||
@ -392,7 +396,6 @@ export default defineComponent({
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = 600
|
||||
let dialogHeight = 450
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
@ -430,14 +433,11 @@ export default defineComponent({
|
||||
* 选择项目文件夹
|
||||
*/
|
||||
async function SelectProjectFolder() {
|
||||
await window.api.selectFolder(
|
||||
{ default_paht: toRaw(formValue.value).project_path },
|
||||
(value) => {
|
||||
await window.api.selectFolder({ default_paht: toRaw(formValue.value).project_path }, (value) => {
|
||||
if (value.length > 0) {
|
||||
formValue.value.project_path = value[0]
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@ -448,7 +448,6 @@ export default defineComponent({
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = 600
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
@ -468,7 +467,6 @@ export default defineComponent({
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.8
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
title: '翻译设置',
|
||||
@ -477,29 +475,7 @@ export default defineComponent({
|
||||
maskClosable: false
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
formRef,
|
||||
ChangeMode,
|
||||
openGptBuyUrl,
|
||||
railStyle,
|
||||
handleValidateButtonClick,
|
||||
rules,
|
||||
SwitchTranslate,
|
||||
gpt_model_options,
|
||||
gpt_options,
|
||||
show,
|
||||
formValue,
|
||||
addGptOption,
|
||||
TestGPTConnection,
|
||||
loading,
|
||||
SelectProjectFolder,
|
||||
AddGptPrompt,
|
||||
character_select_model_options,
|
||||
softwareStore,
|
||||
hdSelectOptions,
|
||||
ModifyTranslateSetting,
|
||||
laiApiOptions: [
|
||||
let laiApiOptions = [
|
||||
{
|
||||
label: '主站点',
|
||||
value: LaiAPIType.MAIN
|
||||
@ -513,7 +489,4 @@ export default defineComponent({
|
||||
value: LaiAPIType.BAK_MAIN
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -39,6 +39,7 @@ export const useReverseManageStore = defineStore('reverseManage', {
|
||||
imageFolder: null,
|
||||
styleList: null,
|
||||
prefix: null,
|
||||
imageCategory: null,
|
||||
status: BookTaskStatus.WAIT,
|
||||
errorMsg: null
|
||||
} as Book.SelectBookTask// 当前选中的小说任务
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { TaskModal } from '@/model/task'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
// 系统相关设置
|
||||
@ -15,8 +16,8 @@ export const useSoftwareStore = defineStore('software', {
|
||||
taskType: undefined,
|
||||
taskStatus: undefined,
|
||||
taskErrorMessage: undefined,
|
||||
}, // 查询传递的数据
|
||||
taskData: [], // 后台任务数据
|
||||
} as TaskModal.TaskCondition, // 查询传递的数据
|
||||
taskData: [] as TaskModal.Task[], // 后台任务数据
|
||||
},
|
||||
softWare: {
|
||||
theme: 'light', // 系统主题,亮或是暗
|
||||
@ -43,15 +44,6 @@ export const useSoftwareStore = defineStore('software', {
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
// 设置一键反推界面显示数据
|
||||
SetReverseDispalayShow(value) {
|
||||
this.softWare.reverse_display_show = value
|
||||
},
|
||||
|
||||
// 设置反推界面时候小说信息显示斑马纹
|
||||
SetReverseBookStripedShow(value) {
|
||||
this.softWare.reverse_show_book_striped = value
|
||||
},
|
||||
|
||||
// 修改软件主题
|
||||
SetSoftware(value) {
|
||||
@ -75,8 +67,22 @@ export const useSoftwareStore = defineStore('software', {
|
||||
// 保存数据
|
||||
// @ts-ignore
|
||||
return await window.setting.SaveSoftWareSetting(JSON.parse(JSON.stringify(this.softWare)))
|
||||
}
|
||||
},
|
||||
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* 重置后台任务查询数据
|
||||
*/
|
||||
ResetBackTaskQueryData() {
|
||||
this.backTask.queryData = {
|
||||
taskName: undefined,
|
||||
bookId: undefined,
|
||||
bookTaskId: undefined,
|
||||
taskType: undefined,
|
||||
taskStatus: undefined,
|
||||
taskErrorMessage: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user