V 2.2.11 优化MJ代理模式

This commit is contained in:
lq1405 2024-06-27 16:24:41 +08:00
parent bac97bc41c
commit 669e57824d
40 changed files with 3364 additions and 1644 deletions

4
.gitignore vendored
View File

@ -15,9 +15,11 @@ resources/scripts/virtual py
resources/scripts/_internal
resources/logger
resources/scripts/Temp
*scripts/db*
resources/image/Temp*
resources/package/ffmpeg-2023*
resources/package/ffmpeg/w*
resources/config*
*ffmpeg.exe*
*Lai.exe*
*Lai_1.exe*
.DS_Store

View File

@ -3,7 +3,7 @@
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"

30
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "laitool",
"version": "2.2.9",
"version": "2.2.10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "laitool",
"version": "2.2.9",
"version": "2.2.10",
"hasInstallScript": true,
"dependencies": {
"@alicloud/alimt20181012": "^1.2.0",
@ -25,7 +25,7 @@
"crypto-js": "^4.2.0",
"electron-store": "^9.0.0",
"electron-updater": "^6.1.7",
"fluent-ffmpeg": "^2.1.2",
"fluent-ffmpeg": "^2.1.3",
"highlight.js": "^11.9.0",
"install": "^0.13.0",
"jimp": "^0.22.10",
@ -51,6 +51,7 @@
"devDependencies": {
"@electron-toolkit/eslint-config": "^1.0.1",
"@rushstack/eslint-patch": "^1.6.1",
"@types/fluent-ffmpeg": "^2.1.24",
"@vitejs/plugin-vue": "^5.0.2",
"@vue/eslint-config-prettier": "^9.0.0",
"electron": "^28.1.1",
@ -2177,6 +2178,15 @@
"version": "1.0.5",
"license": "MIT"
},
"node_modules/@types/fluent-ffmpeg": {
"version": "2.1.24",
"resolved": "https://registry.npmmirror.com/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.24.tgz",
"integrity": "sha512-g5oQO8Jgi2kFS3tTub7wLvfLztr1s8tdXmRd8PiL/hLMLzTIAyMR2sANkTggM/rdEDAg3d63nYRRVepwBiCw5A==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/fs-extra": {
"version": "9.0.13",
"dev": true,
@ -5049,16 +5059,22 @@
"license": "ISC"
},
"node_modules/fluent-ffmpeg": {
"version": "2.1.2",
"license": "MIT",
"version": "2.1.3",
"resolved": "https://registry.npmmirror.com/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz",
"integrity": "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q==",
"dependencies": {
"async": ">=0.2.9",
"async": "^0.2.9",
"which": "^1.1.1"
},
"engines": {
"node": ">=0.8.0"
"node": ">=18"
}
},
"node_modules/fluent-ffmpeg/node_modules/async": {
"version": "0.2.10",
"resolved": "https://registry.npmmirror.com/async/-/async-0.2.10.tgz",
"integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ=="
},
"node_modules/fluent-ffmpeg/node_modules/which": {
"version": "1.3.1",
"license": "ISC",

View File

@ -1,6 +1,6 @@
{
"name": "laitool",
"version": "2.2.10",
"version": "2.2.11",
"description": "An AI tool for image processing, video processing, and other functions.",
"main": "./out/main/index.js",
"author": "laitool.cn",
@ -33,7 +33,7 @@
"crypto-js": "^4.2.0",
"electron-store": "^9.0.0",
"electron-updater": "^6.1.7",
"fluent-ffmpeg": "^2.1.2",
"fluent-ffmpeg": "^2.1.3",
"highlight.js": "^11.9.0",
"install": "^0.13.0",
"jimp": "^0.22.10",
@ -59,6 +59,7 @@
"devDependencies": {
"@electron-toolkit/eslint-config": "^1.0.1",
"@rushstack/eslint-patch": "^1.6.1",
"@types/fluent-ffmpeg": "^2.1.24",
"@vitejs/plugin-vue": "^5.0.2",
"@vue/eslint-config-prettier": "^9.0.0",
"electron": "^28.1.1",
@ -81,7 +82,7 @@
],
"extraResources": [
"resources/package/exittool/**",
"resources/package/ffmpeg-2023-12-07-git-f89cff96d0-full_build/**",
"resources/package/ffmpeg/**",
"resources/package/Improve/**",
"resources/image/style/**",
"resources/image/zhanwei.png",

View File

@ -18,7 +18,7 @@ if len(sys.argv) < 2:
"-ka",
"C:\\Users\\27698\\Desktop\\测试\\123\\测试用 不删.mp4",
"C:\\Users\\27698\\Desktop\\测试\\123\\测试用 不删.json",
30
30,
]
print(sys.argv)
@ -35,9 +35,7 @@ elif __file__:
def set_ffmpeg_env():
# 根据你的ffmpeg路径替换这个
ffmpeg_path = os.path.join(
cript_directory, "../package/ffmpeg-2023-12-07-git-f89cff96d0-full_build/bin"
)
ffmpeg_path = os.path.join(cript_directory, "../package/ffmpeg/win")
if sys.platform == "win32":
ffmpeg_path = ffmpeg_path.replace("/", "\\")

View File

@ -33,10 +33,10 @@ class Clip:
self.config_path = config_path
self.gpu_type = gpu_type
self.ffmpeg_path = (
"../package/ffmpeg-2023-12-07-git-f89cff96d0-full_build/bin/ffmpeg"
"../package/ffmpeg/win/ffmpeg"
)
self.ffprobe_path = (
"../package/ffmpeg-2023-12-07-git-f89cff96d0-full_build/bin/ffprobe"
"../package/ffmpeg/win/ffprobe"
)
self.getInitData()
pass

Binary file not shown.

View File

@ -130,7 +130,7 @@ def init(draft_path, out_dir, package_path):
file.write(line + "\n")
ffmpeg_path = os.path.join(
package_path, "ffmpeg-2023-12-07-git-f89cff96d0-full_build/bin/ffmpeg"
package_path, "ffmpeg/win/ffmpeg"
)
# 抽取关键帧
num = 1

View File

@ -13,12 +13,8 @@ class ImageToVideo:
self.frames = 0
self.gpu_type = gpu_type
self.public_tools = public_tools.PublicTools()
self.ffmpeg_path = (
"../package/ffmpeg-2023-12-07-git-f89cff96d0-full_build/bin/ffmpeg"
)
self.ffprobe_path = (
"../package/ffmpeg-2023-12-07-git-f89cff96d0-full_build/bin/ffprobe"
)
self.ffmpeg_path = "../package/ffmpeg/win/ffmpeg"
self.ffprobe_path = "../package/ffmpeg/win/ffprobe"
pass
def create_video_from_image_with_center_offset(

View File

@ -1,65 +1,70 @@
import { basicApi } from "./apiBasic";
import { Tools } from "../main/tools";
import { define } from "../define/define";
import { basicApi } from './apiBasic'
import { Tools } from '../main/tools'
import { define } from '../define/define'
export class DiscordAPI {
constructor() {
this.tools = new Tools();
this.tools = new Tools()
}
/**
* 通过设置的ID获取MJ API的任务
* @param {*} id
*/
async GetMJAPITaskByID(id, url, key) {
try {
let res;
url = url.replace("${id}", id);
let res
url = url.replace('${id}', id)
let headers = {
"Authorization": key
Authorization: key
}
if (url.includes(define.remotemj_api)) {
headers = {
"mj-api-secret": define.API
'mj-api-secret': define.API
}
}
res = await basicApi.get(url, headers);
res = await basicApi.get(url, headers)
let progress = res.data.progress && res.data.progress.length > 0 ? parseInt(res.data.progress.slice(0, -1)) : 0;
let status = res.data.status.toLowerCase();
let progress =
res.data.progress && res.data.progress.length > 0
? parseInt(res.data.progress.slice(0, -1))
: 0
let status = res.data.status.toLowerCase()
// let code = (status == "success" || status == "in_progress" || status == "not_start") ? 1 : 0;
let code = (status == "failure" || status == "cancel") ? 0 : 1;
let code = status == 'failure' || status == 'cancel' ? 0 : 1
// 返回前端
let res_data = {
type: "updated",
type: 'updated',
progress: progress,
category: "api_mj",
category: 'api_mj',
image_click: res.data.imageUrl,
image_show: res.data.imageUrl,
message_id: res.data.id,
action: res.data.action,
status: status,
code: code,
code: code
}
// 判断当前的API是哪个
if (url.includes("mjapi.deepwl.net")) {
if (url.includes('mjapi.deepwl.net')) {
if (res_data.code == 0) {
res_data["message"] = res.data.failReason
res_data['message'] = res.data.failReason
}
} else if (url.includes("api.ephone.ai")) {
} else if (url.includes('api.ephone.ai')) {
// ePhoneAPI
if (res_data.code == 0) {
res_data["message"] = res.data.failReason
res_data['message'] = res.data.failReason
}
} else if (url.includes('laitool')) {
// laitool
if (res_data.code == 0) {
res_data['message'] = res.data.failReason
}
}
return res_data;
return res_data
} catch (error) {
throw error
}
}
/**
@ -69,34 +74,34 @@ export class DiscordAPI {
try {
// 判断是不是需要垫图将指定的图片转换为base64
for (let i = 0; data.base64Array && i < data.base64Array.length; i++) {
const element = data.base64Array[i];
const element = data.base64Array[i]
// 将指定的图片转换为base64
// 判断图片是本地图片还是网络图片
if (element.indexOf("http") == -1) {
if (element.indexOf('http') == -1) {
// 本地图片
let base64 = await this.tools.readFileBase64(element);
let base64 = await this.tools.readFileBase64(element)
data.base64Array[i] = `data:image/png;base64,${base64}`
} else {
// 网络图片
// 请求对应的图片
let image_buffer = await basicApi.get(element);
let image_buffer = await basicApi.get(element)
// 将返回来的数据转为base64
let base64 = image_buffer.data.toString('base64');
let base64 = image_buffer.data.toString('base64')
data.base64Array[i] = `data:image/png;base64,${base64}`
}
}
let res = await basicApi.post(url, data, headers);
let res = await basicApi.post(url, data, headers)
console.log(res)
let res_data = res.data;
let res_data = res.data
// 判断res_data 是不是json格式的字符串是就序列化为json对象
if (typeof res_data == "string") {
res_data = JSON.parse(res_data);
if (typeof res_data == 'string') {
res_data = JSON.parse(res_data)
}
// 直接返回,错误信息外面判断
return res_data;
return res_data
} catch (error) {
throw error;
throw error
}
}
}

View File

@ -1,4 +1,3 @@
import fs from 'node:fs';
const fspromises = fs.promises;

40
src/define/Tools/time.js Normal file
View File

@ -0,0 +1,40 @@
/**
* 将时间字符串转换为毫秒number
* 00:00:03.867 --3867
* @param {*} timeString 时间字符串
* @returns
*/
export function TimeStringToMilliseconds(timeString) {
// 分割字符串获取小时、分钟、秒和毫秒
const parts = timeString.split(/[:.]/)
const hours = parseInt(parts[0], 10)
const minutes = parseInt(parts[1], 10)
const seconds = parseInt(parts[2], 10)
const milliseconds = parseInt(parts[3], 10)
// 将小时、分钟、秒转换为毫秒并计算总和
return hours * 3600000 + minutes * 60000 + seconds * 1000 + milliseconds
}
/**
* 将毫秒转换为时间字符串
* 85233 -- '00:01:25.233'
* @param {*} milliseconds
* @returns
*/
export function MillisecondsToTimeString(milliseconds) {
let totalSeconds = milliseconds / 1000
const hours = Math.floor(totalSeconds / 3600)
totalSeconds %= 3600
const minutes = Math.floor(totalSeconds / 60)
const seconds = Math.floor(totalSeconds % 60)
const ms = milliseconds % 1000
// 将小时、分钟、秒格式化为两位数,毫秒格式化为三位数
const hoursFormatted = hours.toString().padStart(2, '0')
const minutesFormatted = minutes.toString().padStart(2, '0')
const secondsFormatted = seconds.toString().padStart(2, '0')
const msFormatted = ms.toString().padStart(3, '0')
return `${hoursFormatted}:${minutesFormatted}:${secondsFormatted}.${msFormatted}`
}

View File

@ -5,7 +5,7 @@ export class BookBackTaskList extends Realm.Object<BookBackTaskList> {
id: string
bookId: string
bookTaskId: string
name: string
name: string // 任务名称,小说名+批次名+分镜名
type: BookBackTaskType
status: BookBackTaskStatus
createTime: Date

View File

@ -112,6 +112,7 @@ export class BookTaskDetailModel extends Realm.Object<BookTaskDetailModel> {
bookId: string
bookTaskId: string
videoPath: string | null // 视频地址
audioPath: string | null // 音频地址
word: string | null // 文案
oldImage: string | null // 旧图片用于SD的图生图
afterGpt: string | null // GPT生成的文案
@ -123,7 +124,7 @@ export class BookTaskDetailModel extends Realm.Object<BookTaskDetailModel> {
gptPrompt: string | null // GPT提示词
mjMessage: MJMessage | null // MJ消息
outImagePath: string | null // 输出图片地址
subImagePath: string[] | null // 字幕图片地址
subImagePath: string[] | null // 图片地址
prompt: string | null // 提示
adetailer: boolean // 是否开启修脸
sdConifg: SDConfig | null // SD配置
@ -139,6 +140,7 @@ export class BookTaskDetailModel extends Realm.Object<BookTaskDetailModel> {
bookId: { type: 'string', indexed: true },
bookTaskId: { type: 'string', indexed: true },
videoPath: 'string?',
audioPath: 'string?',
word: 'string?',
oldImage: 'string?',
afterGpt: 'string?',

View File

@ -40,8 +40,9 @@ export class RemoteMJModel extends Realm.Object<RemoteMJModel> {
channelId: string
coreSize: number
guildId: string
mjBotChannelId: string
nijiBotChannelId: string
enable: boolean // 是否启用
mjBotChannelId: string | null
nijiBotChannelId: string | null
queueSize: number
remark: string
remixAutoSubmit: boolean
@ -59,8 +60,9 @@ export class RemoteMJModel extends Realm.Object<RemoteMJModel> {
channelId: 'string',
coreSize: 'int',
guildId: 'string',
mjBotChannelId: 'string',
nijiBotChannelId: 'string',
enable: 'bool',
mjBotChannelId: 'string?',
nijiBotChannelId: 'string?',
queueSize: 'int',
remark: 'string',
remixAutoSubmit: 'bool',

View File

@ -26,14 +26,29 @@ export class BookBackTaskListService extends BaseRealmService {
BookBackTaskListService.instance = new BookBackTaskListService()
await super.getInstance()
}
await BookBackTaskListService.instance.open()
return BookBackTaskListService.instance
}
/**
*
* bookId
* @param query bookIdbookTaskIdnametypestatus
*/
getBookBackTaskList(query) {
try {
// if()
} catch (error) {
throw error
}
}
/**
*
* @param bookBackTask
*/
async AddBookBackTaskList(bookBackTask) {
AddBookBackTaskList(bookBackTask) {
try {
// 判断数据是不是存在
if (

View File

@ -32,6 +32,13 @@ const migration = (oldRealm: Realm, newRealm: Realm) => {
newBookTask[i].isAuto = false // 为新属性设置默认值
}
}
if (oldRealm.schemaVersion < 3) {
const oldBookTask = oldRealm.objects('BookTask')
const newBookTask = newRealm.objects('BookTask')
for (let i = 0; i < oldBookTask.length; i++) {
newBookTask[i].audioPath = null // 为新属性设置默认值
}
}
}
export class BaseRealmService extends BaseService {
@ -72,7 +79,7 @@ export class BaseRealmService extends BaseService {
BookTaskDetailModel
],
path: this.dbpath,
schemaVersion: 2,
schemaVersion: 3,
migration: migration
}
this.realm = await Realm.open(config)

View File

@ -11,8 +11,8 @@ import { BookTaskService } from './bookTaskService'
import { BaseRealmService } from './bookBasic.js'
import { isEmpty } from 'lodash'
class BooKService extends BaseRealmService {
static instance: BooKService | null = null
export class BookService extends BaseRealmService {
static instance: BookService | null = null
realm: Realm
private constructor() {
@ -24,20 +24,59 @@ class BooKService extends BaseRealmService {
* @returns
*/
public static async getInstance() {
if (BooKService.instance === null) {
BooKService.instance = new BooKService()
if (BookService.instance === null) {
BookService.instance = new BookService()
await super.getInstance()
}
return BooKService.instance
await BookService.instance.open()
return BookService.instance
}
/**
* null
* @param bookId
*/
GetBookDataById(bookId) {
try {
if (isEmpty(bookId)) {
throw new Error('获取小说信息失败缺少小说ID')
}
let books = this.realm.objects<BookModel>('Book').filtered('id = $0', bookId)
if (books.length <= 0) {
return successMessage(null, '通过ID获取小说数据成功', 'ReverseBook_GetBookDataById')
} else {
// 对返回的数据进行处理
let resBooks = Array.from(books).map((book) => {
// 这里可以直接操作普通对象
let bookObj = {
...book,
bookFolderPath: path.resolve(
define.project_path,
book.bookFolderPath.replace(/\\/g, '/')
),
oldVideoPath: book.oldVideoPath
? path.resolve(define.project_path, book.oldVideoPath.replace(/\\/g, '/'))
: '',
imageFolder: book.imageFolder
? path.resolve(define.project_path, book.imageFolder.replace(/\\/g, '/'))
: ''
}
return bookObj
})
return successMessage(resBooks[0], '通过ID获取小说数据成功', 'ReverseBook_GetBookDataById')
}
} catch (error) {
throw error
}
}
/**
*
* @returns
*/
async GetBookData(bookQuery) {
GetBookData(bookQuery) {
try {
await this.open()
// 获取所有的小说数据,并进行时间降序排序
let books = this.realm.objects<BookModel>('Book')
let book_length = books.length
@ -106,7 +145,6 @@ class BooKService extends BaseRealmService {
*/
async AddOrModifyBook(book) {
try {
await this.open()
if (book == null) {
throw new Error('小说数据为空,无法修改')
}
@ -141,6 +179,7 @@ class BooKService extends BaseRealmService {
let bookFolderPath = path.resolve(define.project_path, book.id)
let imageFolder = path.resolve(define.project_path, `${book.id}/tmp`)
let oldVideoPath = path.resolve(define.project_path, `${book.id}/data/${book.id}.mp4`)
let bookTaskImageFolder = path.resolve(imageFolder, 'output_00001')
// 将视频拷贝一个到项目文件下面
if (book.oldVideoPath) {
@ -150,11 +189,11 @@ class BooKService extends BaseRealmService {
// 创建对应的文件夹
await CheckFolderExistsOrCreate(bookFolderPath)
await CheckFolderExistsOrCreate(imageFolder)
await CheckFolderExistsOrCreate(bookTaskImageFolder) // 创建默认的任务文件夹
// 修改数据
book.oldVideoPath = path.relative(define.project_path, oldVideoPath)
this.realm.write(() => {
this.realm.create('Book', book)
let bookTaskImageFolder = path.resolve(imageFolder, 'output_00001')
// 添加一个任务
let bookTask = {
id: uuidv4(),
@ -210,5 +249,3 @@ class BooKService extends BaseRealmService {
}
}
}
export default BooKService

View File

@ -6,6 +6,10 @@ import { BookTaskModel } from '../../model/Book/bookTask.js'
import { BookTaskStatus } from '../../../enum/bookEnum.js'
import { successMessage } from '../../../../main/generalTools.js'
import { BaseRealmService } from './bookBasic'
import { endsWith, isEmpty } from 'lodash'
import { book } from '../../../../preload/book.js'
import { DefaultObject } from 'realm/dist/public-types/schema.js'
import { JoinPath } from '../../../Tools/file.js'
const { v4: uuidv4 } = require('uuid')
let dbPath = path.resolve(define.db_path, 'book.realm')
@ -30,16 +34,202 @@ export class BookTaskDetailService extends BaseRealmService {
BookTaskDetailService.instance = new BookTaskDetailService()
await super.getInstance()
}
await BookTaskDetailService.instance.open()
return BookTaskDetailService.instance
}
/**
*
*
* @param condition idnamebookIdbookTaskId
*/
GetBookTaskData(condition) {
try {
if (condition == null) {
throw new Error('查询小说分镜信息,查询条件不能为空')
}
let query = [] as string[]
if (condition.id) {
query.push(`id = ${condition.id}`)
}
if (condition.bookId) {
query.push(`bookId = ${condition.bookId}`)
}
if (condition.bookTaskId) {
query.push(`bookTaskId = ${condition.bookTaskId}`)
}
if (condition.name) {
query.push(`name = ${condition.name}`)
}
const queryString = query.join(' && ')
let tasksToDelete: Realm.Results<Realm.Object<DefaultObject, never> & DefaultObject>
// 获取指定的数据
if (queryString) {
tasksToDelete = this.realm.objects('BookTaskDetail').filtered(queryString)
} else {
// 返回全部
tasksToDelete = this.realm.objects('BookTaskDetail')
}
let resData = Array.from(tasksToDelete).map((item) => {
let resObj = {
...item,
videoPath: JoinPath(define.project_path, item.videoPath),
audioPath: JoinPath(define.project_path, item.audioPath),
oldImage: JoinPath(define.project_path, item.oldImage),
outImagePath: JoinPath(define.project_path, item.outImagePath),
subImagePath: (item.subImagePath as string[])?.map((subImage) => {
return JoinPath(define.project_path, subImage)
})
}
return resObj
})
return successMessage(
resData,
'获取小说的分镜信息成功',
'BookTaskDetailService_GetBookTaskData'
)
} catch (error) {
throw error
}
}
/**
* ID获取指定的小说任务分镜详细数据
* @param bookTaskDetailId
*/
public GetBookTaskDetailDataById(bookTaskDetailId: string) {
try {
if (bookTaskDetailId == null) {
throw new Error('获取小说任务详细信息失败缺少ID')
}
let bookTaskDetails = this.GetBookTaskData({ id: bookTaskDetailId })
if (bookTaskDetails.data.length <= 0) {
return successMessage(
null,
'未找到对应的小说任务详细信息',
'BookTaskDetailService_GetBookTaskDetailDataById'
)
} else {
return successMessage(
bookTaskDetails.data[0],
'获取小说任务详细信息成功',
'BookTaskDetailService_GetBookTaskDetailDataById'
)
}
} catch (error) {
throw error
}
}
/**
*
* @param BookTaskDetail
*/
public async AddBookTaskDetail(BookTaskDetail) {
public AddBookTaskDetail(bookTaskDetail) {
try {
// 判断是不是又小说的ID
// 判断是不是又小说ID
if (isEmpty(bookTaskDetail.bookId) || isEmpty(bookTaskDetail.bookTaskId)) {
throw new Error(
'新增小说任务详细信息到数据库失败数据不完整缺少小说ID或者小说批次任务ID'
)
}
// 开始初始化数据获取指定的bookId和bookTaskId中最大的no
let bookTaskDetails = this.realm
.objects<BookTaskModel>('BookTaskDetail')
.filtered(
'bookId = $0 AND bookTaskId = $1',
bookTaskDetail.bookId,
bookTaskDetail.bookTaskId
)
let maxNo = bookTaskDetails.max('no')
bookTaskDetail.no = maxNo ? Number(maxNo) + 1 : 1
let name = bookTaskDetail.no.tosString().padStart(5, '0')
bookTaskDetail.name = name
bookTaskDetail.id = uuidv4()
bookTaskDetail.createTime = new Date()
bookTaskDetail.updateTime = new Date()
// 开始添加
this.transaction(() => {
this.realm.create('BookTaskDetail', bookTaskDetail)
})
//创建成功,返回
return successMessage(
bookTaskDetail,
'新增小说任务详细信息成功',
'BookTaskDetailService_AddBookTaskDetail'
)
} catch (error) {
throw error
}
}
/**
* ID的指定数据
* @param bookTaskDetailId
* @param updateData
*/
UpdateBookTaskDetail(bookTaskDetailId: string, updateData) {
try {
this.transaction(() => {
let bookTaskDetail = this.realm.objectForPrimaryKey('BookTaskDetail', bookTaskDetailId)
if (bookTaskDetail == null) {
throw new Error('未找到对应的小说任务详细信息')
}
// 开始修改
for (let key in updateData) {
bookTaskDetail[key] = updateData[key]
}
bookTaskDetail.updateTime = new Date()
})
return successMessage(
null,
'修改小说任务详细信息成功',
'BookTaskDetailService_UpdateBookTaskDetail'
)
} catch (error) {
throw error
}
}
/**
* ID和小说任务ID
* @param condition bookIdbookTaskIdnameid
*/
DeleteBookTaskDetail(condition) {
try {
if (isEmpty(condition.id) && isEmpty(condition.bookTaskId) && isEmpty(condition.bookId)) {
throw new Error('删除小说分镜信息失败,没有必要参数')
}
let query = [] as string[]
if (condition.id) {
query.push(`id = ${condition.id}`)
}
if (condition.bookId) {
query.push(`bookId = ${condition.bookId}`)
}
if (condition.bookTaskId) {
query.push(`bookTaskId = ${condition.bookTaskId}`)
}
if (condition.name) {
query.push(`name = ${condition.name}`)
}
if (query.length <= 0) {
throw new Error('删除小说分镜任务失败,没有查询条件')
}
const queryString = query.join(' && ')
let tasksToDelete = this.realm.objects('BookTaskDetail').filtered(queryString)
this.transaction(() => {
this.realm.delete(tasksToDelete)
})
return successMessage(
null,
'删除指定的分镜任务成功',
'BookTaskDetailService_DeleteBookTaskDetail'
)
} catch (error) {
throw error
}

View File

@ -29,6 +29,7 @@ export class BookTaskService extends BaseRealmService {
BookTaskService.instance = new BookTaskService()
await super.getInstance()
}
await BookTaskService.instance.open()
return BookTaskService.instance
}
@ -36,9 +37,8 @@ export class BookTaskService extends BaseRealmService {
*
* @param bookTaskCondition idbookIdnamenopage, pageSize
*/
async GetBookTaskData(bookTaskCondition) {
GetBookTaskData(bookTaskCondition) {
try {
await this.open()
// 获取所有的小说数据,并进行时间降序排序
let bookTasks = this.realm.objects<BookTaskModel>('BookTask')
@ -98,10 +98,64 @@ export class BookTaskService extends BaseRealmService {
}
}
// 添加一条数据
async AddOrModifyBookTask(bookTask) {
/**
* ID获取小说批次任务的数据
* @param bookTaskId
*/
GetBookTaskDataById(bookTaskId: string) {
try {
if (bookTaskId == null) {
throw new Error('小说任务ID不能为空')
}
let bookTasks = this.GetBookTaskData({ id: bookTaskId })
if (bookTasks.data.bookTasks.length <= 0) {
return successMessage(null, '未找到对应的小说任务', 'BookTaskService_GetBookTaskDataById')
} else {
return successMessage(
bookTasks.data.bookTasks[0],
'查询小说任务成功',
'BookTaskService_GetBookTaskDataById'
)
}
} catch (error) {
throw error
}
}
/**
*
* @param bookTaskId Id
* @param status
*/
UpdateBookTaskStatus(bookTaskId: string, status: BookTaskStatus, errorMsg: string | null = null) {
try {
this.transaction(() => {
// 修改对应小说批次任务的状态
let bookTask = this.realm.objectForPrimaryKey('BookTask', bookTaskId)
if (bookTask == null) {
throw new Error('未找到对应的小说任务')
}
bookTask.status = status
bookTask.updateTime = new Date()
if (errorMsg != null) {
bookTask.errorMsg = errorMsg
}
})
return successMessage(
null,
`修改小说任务状态成功,修改后的状态为${status}`,
'BookTaskService_UpdateBookTaskStatus'
)
} catch (error) {
throw error
}
}
// 添加一条数据
AddOrModifyBookTask(bookTask) {
try {
await this.open()
if (bookTask == null) {
throw new Error('添加的小说任务不能为空')
}

View File

@ -249,7 +249,6 @@ export class MJSettingService extends BaseSoftWareService {
if (remoteMjQuery?.id) {
remoteMjSettings = this.realm.objects('RemoteMJ').filtered('id = $0', remoteMjQuery.id)
}
let resRemoteMj = Array.from(remoteMjSettings).map((remoteMj) => {
return {
...remoteMj
@ -298,6 +297,7 @@ export class MJSettingService extends BaseSoftWareService {
remoteMjSetting.createTime = new Date()
remoteMjSetting.updateTime = new Date()
remoteMjSetting.version = version
remoteMjSetting.enable = true
remoteMjSetting.remark = global.machineId
// 判断当前this.relam 是不是已经处于一个事务中
@ -374,6 +374,28 @@ export class MJSettingService extends BaseSoftWareService {
}
}
/**
* ID的数据
* @param id
*/
DeleteRemoteMJSetting(id: string) {
try {
if (isEmpty(id)) {
throw new Error('删除代理模式配置ID不能为空')
}
let remoteMjSettingRes = this.realm.objects('RemoteMJ').filtered('id = $0', id)
if (remoteMjSettingRes.length <= 0) {
throw new Error('没有找到对应的代理模式配置信息')
}
this.transaction(() => {
this.realm.delete(remoteMjSettingRes)
})
return successMessage(null, '删除代理API配置成功', 'MJSettingService_DeleteRemoteMjSetting')
} catch (error) {
throw error
}
}
//#endregion
//#region MJ设置的基础设置
@ -540,22 +562,6 @@ export class MJSettingService extends BaseSoftWareService {
}
// 组合添加数据
this.realm.write(() => {
// 先添加RemoteMJ的数据
let remoteSetting = mjSetting.remoteSetting ? mjSetting.remoteSetting : null
if (remoteSetting != null) {
let remoteSettingRes: { code: number; data: any; message: any }
if (isEmpty(remoteSetting.id)) {
// 新增
remoteSettingRes = this.AddRemoteMjSetting(remoteSetting)
} else {
// 修改
remoteSettingRes = this.UpdateRemoteMjSetting(remoteSetting)
}
if (remoteSettingRes && remoteSettingRes.code == 1) {
mjSetting.remoteSetting = remoteSettingRes.data
}
}
// 判断API设置的数据是不是存在
let apiSetting = mjSetting.apiSetting ? mjSetting.apiSetting : null
if (apiSetting != null) {

View File

@ -60,7 +60,7 @@ const migration = (oldRealm: Realm, newRealm: Realm) => {
}
if (oldRealm.schemaVersion < 9) {
newRealm.write(() => {
const newSoftwares = newRealm.objects('MjSetting')
const newSoftwares = newRealm.objects('RemoteMJ')
for (let software of newSoftwares) {
software.accountId = null
}
@ -74,6 +74,31 @@ const migration = (oldRealm: Realm, newRealm: Realm) => {
}
})
}
if (oldRealm.schemaVersion < 11) {
newRealm.write(() => {
const newSoftwares = newRealm.objects('MjSetting')
for (let software of newSoftwares) {
software.enable = true
}
})
}
if (oldRealm.schemaVersion < 12) {
newRealm.write(() => {
const newSoftwares = newRealm.objects('RemoteMJ')
for (let software of newSoftwares) {
software.nijiBotChannelId = null
software.mjBotChannelId = null
}
})
}
if (oldRealm.schemaVersion < 13) {
newRealm.write(() => {
const newSoftwares = newRealm.objects('RemoteMJ')
for (let software of newSoftwares) {
software.enable = true // 默认都是启用的
}
})
}
}
export class BaseSoftWareService extends BaseService {
@ -112,7 +137,7 @@ export class BaseSoftWareService extends BaseService {
MjSettingModel
],
path: dbPath,
schemaVersion: 10, // 当前版本号
schemaVersion: 13, // 当前版本号
migration: migration
}
// 判断当前全局是不是又当前这个

View File

@ -1,222 +1,227 @@
export const DEFINE_STRING = {
OPEN_DEV_TOOLS_PASSWORD: "OPEN_DEV_TOOLS_PASSWORD",
OPEN_DEV_TOOLS: "OPEN_DEV_TOOLS",
GET_FILE_BASE64: "GET_FILE_BASE64",
SAVE_DEFINE_CONFIG_JSON_BY_PROPERTY: "SAVE_DEFINE_CONFIG_JSON_BY_PROPERTY",
GET_DEFINE_CONFIG_JSON_BY_PROPERTY: "GET_DEFINE_CONFIG_JSON_BY_PROPERTY",
GET_IMAGE_GENERATE_CATEGORY: "GET_IMAGE_GENERATE_CATEGORY",
SHOW_MAIN_NOTIFICATION: "SHOW_MAIN_NOTIFICATION",
SHOW_GLOABAL_MESSAGE: "SHOW_GLOABAL_MESSAGE",
CHECK_MACHINE_ID: "CHECK_MACHINE_ID",
GET_CUSTOMIZE_GPT_PROMPT: "GET_CUSTOMIZE_GPT_PROMPT",
GENERATE_GPT_EXAMPLE_OUT: "GENERATE_GPT_EXAMPLE_OUT",
GET_PERMISSION: "GET_PERMISSION",
SAVE_IMAGE_TO_OTHER_FOLDER: "SAVE_IMAGE_TO_OTHER_FOLDER",
GET_IMAGE_AUTO_SAVE_SETTING: "GET_IMAGE_AUTO_SAVE_SETTING",
SAVE_IMAGE_AUTO_SAVE_SETTING: "SAVE_IMAGE_AUTO_SAVE_SETTING",
GET_AUTO_SAVE_IMAGE_CLASSIFY_OPTIONS: "GET_AUTO_SAVE_IMAGE_CLASSIFY_OPTIONS",
MODIFY_GENERATE_TASK_STATUS: "MODIFY_GENERATE_TASK_STATUS",
DELETE_BACK_TASK: "DELETE_BACK_TASK",
SAVE_VIDEO_SRT_AND_AUDIO_MESSAGE: "SAVE_VIDEO_SRT_AND_AUDIO_MESSAGE",
SAVE_KEY_FRAME_SETTING: "SAVE_KEY_FRAME_SETTING",
MODIFY_SAMPLE_SETTING: "MODIFY_SAMPLE_SETTING",
GET_SETTING_Dafault_DATA: "GET_SETTING_Dafault_DATA",
GET_DRAFT_FILE_LIST: "GET_DRAFT_FILE_LIST",
GET_FRAME: "GET_FRAME",
PYTHON_ERROR: "PYTHON_ERROR",
PYTHON_CLOSE: "PYTHON_CLOSE",
PYTHON_OUTPUT: "PYTHON_OUTPUT",
RESTART_GENERATE: "RESTART_GENERATE",
ALIGN_DRAFT_IMG: "ALIGN_DRAFT_IMG",
ALIGN_DRAFT_IMG_TO_TEXT: "ALIGN_DRAFT_IMG_TO_TEXT",
REGENERATE_IMAGE_RETUN: "REGENERATE_IMAGE_RETUN",
GET_SUBFOLDER_LIST: "GET_SUBFOLDER_LIST",
REFRASH_IMAGWE_DATA: "REFRASH_IMAGWE_DATA",
GET_IMAGE_PROMPTLIST: "GET_IMAGE_PROMPTLIST",
SELECT_FILE: "SELECT_FILE",
IMPROVE_IMAGE_RESOULTION: "IMPROVE_IMAGE_RESOULTION",
GET_BACKGROUND_MUSIC_CONFIG_LIST: "GET_BACKGROUND_MUSIC_CONFIG_LIST",
ADD_BACKGROUND_MUSIC_FOLDER: "ADD_BACKGROUND_MUSIC_FOLDER",
DELETE_CLIP_SETTING: "DELETE_CLIP_SETTING",
DELETE_FRIENDLY_REMINDER: "DELETE_FRIENDLY_REMINDER",
MODIFY_INPUT_CROP_JSON: "MODIFY_INPUT_CROP_JSON",
PUSH_BACK_PROMPT: "PUSH_BACK_PROMPT",
GET_FRIENDLY_REMINDER_DRAFT: "GET_FRIENDLY_REMINDER_DRAFT",
GET_FRIENDLY_REMINDER_LIST: "GET_FRIENDLY_REMINDER_LIST",
AUTO_GENERATION_VIDEO: "AUTO_GENERATION_VIDEO",
GET_PROJECT_WORD: "GET_PROJECT_WORD",
AIMODIFY_ONE_WORD: "AIMODIFY_ONE_WORD",
IMPORT_SRT_AND_GET_TIME: "IMPORT_SRT_AND_GET_TIME",
SAVE_NEW_WORD: "SAVE_NEW_WORD",
SAVE_COPYWRITING_INFOMATION: "SAVE_COPYWRITING_INFOMATION",
SAVE_SD_CONFIG: "SAVE_SD_CONFIG",
SAVE_GENERAL_SETTING: "SAVE_GENERAL_SETTING",
GET_VIDEO_CONFIG_MESSAGE: "GET_VIDEO_CONFIG_MESSAGE",
GET_SYSTEM_INSTALL_FONTNAME: "GET_SYSTEM_INSTALL_FONTNAME",
SAVE_ASS_CONFIG: "SAVE_ASS_CONFIG",
DELETE_VIDEO_CONFIG: "DELETE_VIDEO_CONFIG",
SHOW_NEW_WINDOW: "SHOW_NEW_WINDOW",
GET_DRAFT_FILE_LIST: "GET_DRAFT_FILE_LIST",
SELECT_FOLDER: "SELECT_FOLDER",
GET_DRAFT_TEXT_STYLE: "GET_DRAFT_TEXT_STYLE",
GET_TEXT_STYLE_LIST: "GET_TEXT_STYLE_LIST",
DELETE_DRAFT_TEXT_STYLE: "DELETE_DRAFT_TEXT_STYLE",
ADD_DRAFT: "ADD_DRAFT",
RETURN_IMAGE_PROMPT: "RETURN_IMAGE_PROMPT",
RE_GENERATE_IAMGE_ONE: "RE_GENERATE_IAMGE_ONE",
INIT_SD_CONFIG: "INIT_SD_CONFIG",
ADD_IMAGE_TASK_LIST: "ADD_IMAGE_TASK_LIST",
GET_GENERATE_TASK_LIST: "GET_GENERATE_TASK_LIST",
DELETE_IMAGE_TASK_LIST: "DELETE_IMAGE_TASK_LIST",
GENERATE_IMAGWE_IN_SELECT_TASK: "GENERATE_IMAGWE_IN_SELECT_TASK",
GET_MACHINE_ID: "GET_MACHINE_ID",
QUIT_APP: "QUIT_APP",
GET_BAD_PROMPT: "GET_BAD_PROMPT",
SAVE_BAD_PROMPT: "SAVE_BAD_PROMPT",
DELETE_BAD_PROMPT: "DELETE_BAD_PROMPT",
ADD_WEBUI_JSON: "ADD_WEBUI_JSON",
OPEN_GPT_BUY_URL: "OPEN_GPT_BUY_URL",
GET_IAMGE_PROMPT_LIST: "GET_IAMGE_PROMPT_LIST",
GET_ADETAILER_LIST: "GET_ADETAILER_LIST",
SAVE_DETAILER_CONFIG: "SAVE_DETAILER_CONFIG",
OPEN_URL: "OPEN_URL",
GET_VERSION: "GET_VERSION",
GET_FRAME_RETUN: "GET_FRAME_RETUN",
DOWNLOAD_MODEL: "DOWNLOAD_MODEL",
START_STORY_BOARDING: "START_STORY_BOARDING",
SHOW_MESSAGE_DIALOG: "SHOW_MESSAGE_DIALOG",
SHOW_GLOABAL_MESSAGE_DIALOG: "SHOW_GLOABAL_MESSAGE_DIALOG",
IMAGE_TASK_STATUS_REFRESH: "IMAGE_TASK_STATUS_REFRESH",
SAVE_TRIAL_END_TIME: "SAVE_TRIAL_END_TIME",
DOWNLOAD_IMAGE_FILE: "DOWNLOAD_IMAGE_FILE",
OPEN_FOLDER: "OPEN_FOLDER",
VIDEO_GENERATE_STATUS_REFRESH: "VIDEO_GENERATE_STATUS_REFRESH",
AUTO_CONDITION_CHECK: "AUTO_CONDITION_CHECK",
MODIFY_IMAGE_TASK_LIST: "MODIFY_IMAGE_TASK_LIST",
ACTION_AUTO_VIDEO_TASK: "ACTION_AUTO_VIDEO_TASK",
GET_VIDEO_GENERATE_CONFIG: "GET_VIDEO_GENERATE_CONFIG",
TRANSLATE_PROMPT: "TRANSLATE_PROMPT",
TRANSLATE_RETURN_NOW: "TRANSLATE_RETURN_NOW",
TRANSLATE_RETURN_REFRESH: "TRANSLATE_RETURN_REFRESH",
GET_SHOW_MESSAGE: "GET_SHOW_MESSAGE",
AUTO_ANALYZE_CHARACTER: "AUTO_ANALYZE_CHARACTER",
GET_CONFIG_JSON: "GET_CONFIG_JSON",
ORIGINAL_ADD_WEBUI_JSON: "ORIGINAL_ADD_WEBUI_JSON",
GET_PROMPT_JSON: "GET_PROMPT_JSON",
GPT_PROMPT: "GPT_PROMPT",
GPT_GENERATE_PROMPT_RETURN: "GPT_GENERATE_PROMPT_RETURN",
AUTO_SAVE_DATA_JSON: "AUTO_SAVE_DATA_JSON",
ORIGINAL_SD_SINGLE_IMAGE_GENERATE: "ORIGINAL_SD_SINGLE_IMAGE_GENERATE",
SD_ORIGINAL_GENERATE_IMAGE_RETURN: "SD_ORIGINAL_GENERATE_IMAGE_RETURN",
GET_STYLE_IMAGE_SUB_LIST: "GET_STYLE_IMAGE_SUB_LIST",
GET_IMAGE_STYLE_INFOMATION: "GET_IMAGE_STYLE_INFOMATION",
GET_IMAGE_STYLE_MENU: "GET_IMAGE_STYLE_MENU",
GET_GPT_BUSINESS_OPTION: "GET_GPT_BUSINESS_OPTION",
GET_GPT_MODEL_OPTION: "GET_GPT_MODEL_OPTION",
GET_GPT_AUTO_INFERENCE_OPTIONS: "GET_GPT_AUTO_INFERENCE_OPTIONS",
SAVE_DYNAMIC_GPT_OPTION: "SAVE_DYNAMIC_GPT_OPTION",
DELETE_DYNAMIC_GPT_OPTION: "DELETE_DYNAMIC_GPT_OPTION",
TEST_GPT_CONNECTION: "TEST_GPT_CONNECTION",
SAVE_WORD_TXT: "SAVE_WORD_TXT",
GET_KEY_FRAME_CONFIG_DATA: "GET_KEY_FRAME_CONFIG_DATA",
GET_KEYFRAME_OPTIONS: "GET_KEYFRAME_OPTIONS",
OPEN_DEV_TOOLS_PASSWORD: 'OPEN_DEV_TOOLS_PASSWORD',
OPEN_DEV_TOOLS: 'OPEN_DEV_TOOLS',
GET_FILE_BASE64: 'GET_FILE_BASE64',
SAVE_DEFINE_CONFIG_JSON_BY_PROPERTY: 'SAVE_DEFINE_CONFIG_JSON_BY_PROPERTY',
GET_DEFINE_CONFIG_JSON_BY_PROPERTY: 'GET_DEFINE_CONFIG_JSON_BY_PROPERTY',
GET_IMAGE_GENERATE_CATEGORY: 'GET_IMAGE_GENERATE_CATEGORY',
SHOW_MAIN_NOTIFICATION: 'SHOW_MAIN_NOTIFICATION',
SHOW_GLOABAL_MESSAGE: 'SHOW_GLOABAL_MESSAGE',
CHECK_MACHINE_ID: 'CHECK_MACHINE_ID',
GET_CUSTOMIZE_GPT_PROMPT: 'GET_CUSTOMIZE_GPT_PROMPT',
GENERATE_GPT_EXAMPLE_OUT: 'GENERATE_GPT_EXAMPLE_OUT',
GET_PERMISSION: 'GET_PERMISSION',
SAVE_IMAGE_TO_OTHER_FOLDER: 'SAVE_IMAGE_TO_OTHER_FOLDER',
GET_IMAGE_AUTO_SAVE_SETTING: 'GET_IMAGE_AUTO_SAVE_SETTING',
SAVE_IMAGE_AUTO_SAVE_SETTING: 'SAVE_IMAGE_AUTO_SAVE_SETTING',
GET_AUTO_SAVE_IMAGE_CLASSIFY_OPTIONS: 'GET_AUTO_SAVE_IMAGE_CLASSIFY_OPTIONS',
MODIFY_GENERATE_TASK_STATUS: 'MODIFY_GENERATE_TASK_STATUS',
DELETE_BACK_TASK: 'DELETE_BACK_TASK',
SAVE_VIDEO_SRT_AND_AUDIO_MESSAGE: 'SAVE_VIDEO_SRT_AND_AUDIO_MESSAGE',
SAVE_KEY_FRAME_SETTING: 'SAVE_KEY_FRAME_SETTING',
MODIFY_SAMPLE_SETTING: 'MODIFY_SAMPLE_SETTING',
GET_SETTING_Dafault_DATA: 'GET_SETTING_Dafault_DATA',
GET_DRAFT_FILE_LIST: 'GET_DRAFT_FILE_LIST',
GET_FRAME: 'GET_FRAME',
PYTHON_ERROR: 'PYTHON_ERROR',
PYTHON_CLOSE: 'PYTHON_CLOSE',
PYTHON_OUTPUT: 'PYTHON_OUTPUT',
RESTART_GENERATE: 'RESTART_GENERATE',
ALIGN_DRAFT_IMG: 'ALIGN_DRAFT_IMG',
ALIGN_DRAFT_IMG_TO_TEXT: 'ALIGN_DRAFT_IMG_TO_TEXT',
REGENERATE_IMAGE_RETUN: 'REGENERATE_IMAGE_RETUN',
GET_SUBFOLDER_LIST: 'GET_SUBFOLDER_LIST',
REFRASH_IMAGWE_DATA: 'REFRASH_IMAGWE_DATA',
GET_IMAGE_PROMPTLIST: 'GET_IMAGE_PROMPTLIST',
SELECT_FILE: 'SELECT_FILE',
IMPROVE_IMAGE_RESOULTION: 'IMPROVE_IMAGE_RESOULTION',
GET_BACKGROUND_MUSIC_CONFIG_LIST: 'GET_BACKGROUND_MUSIC_CONFIG_LIST',
ADD_BACKGROUND_MUSIC_FOLDER: 'ADD_BACKGROUND_MUSIC_FOLDER',
DELETE_CLIP_SETTING: 'DELETE_CLIP_SETTING',
DELETE_FRIENDLY_REMINDER: 'DELETE_FRIENDLY_REMINDER',
MODIFY_INPUT_CROP_JSON: 'MODIFY_INPUT_CROP_JSON',
PUSH_BACK_PROMPT: 'PUSH_BACK_PROMPT',
GET_FRIENDLY_REMINDER_DRAFT: 'GET_FRIENDLY_REMINDER_DRAFT',
GET_FRIENDLY_REMINDER_LIST: 'GET_FRIENDLY_REMINDER_LIST',
AUTO_GENERATION_VIDEO: 'AUTO_GENERATION_VIDEO',
GET_PROJECT_WORD: 'GET_PROJECT_WORD',
AIMODIFY_ONE_WORD: 'AIMODIFY_ONE_WORD',
IMPORT_SRT_AND_GET_TIME: 'IMPORT_SRT_AND_GET_TIME',
SAVE_NEW_WORD: 'SAVE_NEW_WORD',
SAVE_COPYWRITING_INFOMATION: 'SAVE_COPYWRITING_INFOMATION',
SAVE_SD_CONFIG: 'SAVE_SD_CONFIG',
SAVE_GENERAL_SETTING: 'SAVE_GENERAL_SETTING',
GET_VIDEO_CONFIG_MESSAGE: 'GET_VIDEO_CONFIG_MESSAGE',
GET_SYSTEM_INSTALL_FONTNAME: 'GET_SYSTEM_INSTALL_FONTNAME',
SAVE_ASS_CONFIG: 'SAVE_ASS_CONFIG',
DELETE_VIDEO_CONFIG: 'DELETE_VIDEO_CONFIG',
SHOW_NEW_WINDOW: 'SHOW_NEW_WINDOW',
GET_DRAFT_FILE_LIST: 'GET_DRAFT_FILE_LIST',
SELECT_FOLDER: 'SELECT_FOLDER',
GET_DRAFT_TEXT_STYLE: 'GET_DRAFT_TEXT_STYLE',
GET_TEXT_STYLE_LIST: 'GET_TEXT_STYLE_LIST',
DELETE_DRAFT_TEXT_STYLE: 'DELETE_DRAFT_TEXT_STYLE',
ADD_DRAFT: 'ADD_DRAFT',
RETURN_IMAGE_PROMPT: 'RETURN_IMAGE_PROMPT',
RE_GENERATE_IAMGE_ONE: 'RE_GENERATE_IAMGE_ONE',
INIT_SD_CONFIG: 'INIT_SD_CONFIG',
ADD_IMAGE_TASK_LIST: 'ADD_IMAGE_TASK_LIST',
GET_GENERATE_TASK_LIST: 'GET_GENERATE_TASK_LIST',
DELETE_IMAGE_TASK_LIST: 'DELETE_IMAGE_TASK_LIST',
GENERATE_IMAGWE_IN_SELECT_TASK: 'GENERATE_IMAGWE_IN_SELECT_TASK',
GET_MACHINE_ID: 'GET_MACHINE_ID',
QUIT_APP: 'QUIT_APP',
GET_BAD_PROMPT: 'GET_BAD_PROMPT',
SAVE_BAD_PROMPT: 'SAVE_BAD_PROMPT',
DELETE_BAD_PROMPT: 'DELETE_BAD_PROMPT',
ADD_WEBUI_JSON: 'ADD_WEBUI_JSON',
OPEN_GPT_BUY_URL: 'OPEN_GPT_BUY_URL',
GET_IAMGE_PROMPT_LIST: 'GET_IAMGE_PROMPT_LIST',
GET_ADETAILER_LIST: 'GET_ADETAILER_LIST',
SAVE_DETAILER_CONFIG: 'SAVE_DETAILER_CONFIG',
OPEN_URL: 'OPEN_URL',
GET_VERSION: 'GET_VERSION',
GET_FRAME_RETUN: 'GET_FRAME_RETUN',
DOWNLOAD_MODEL: 'DOWNLOAD_MODEL',
START_STORY_BOARDING: 'START_STORY_BOARDING',
SHOW_MESSAGE_DIALOG: 'SHOW_MESSAGE_DIALOG',
SHOW_GLOABAL_MESSAGE_DIALOG: 'SHOW_GLOABAL_MESSAGE_DIALOG',
IMAGE_TASK_STATUS_REFRESH: 'IMAGE_TASK_STATUS_REFRESH',
SAVE_TRIAL_END_TIME: 'SAVE_TRIAL_END_TIME',
DOWNLOAD_IMAGE_FILE: 'DOWNLOAD_IMAGE_FILE',
OPEN_FOLDER: 'OPEN_FOLDER',
VIDEO_GENERATE_STATUS_REFRESH: 'VIDEO_GENERATE_STATUS_REFRESH',
AUTO_CONDITION_CHECK: 'AUTO_CONDITION_CHECK',
MODIFY_IMAGE_TASK_LIST: 'MODIFY_IMAGE_TASK_LIST',
ACTION_AUTO_VIDEO_TASK: 'ACTION_AUTO_VIDEO_TASK',
GET_VIDEO_GENERATE_CONFIG: 'GET_VIDEO_GENERATE_CONFIG',
TRANSLATE_PROMPT: 'TRANSLATE_PROMPT',
TRANSLATE_RETURN_NOW: 'TRANSLATE_RETURN_NOW',
TRANSLATE_RETURN_REFRESH: 'TRANSLATE_RETURN_REFRESH',
GET_SHOW_MESSAGE: 'GET_SHOW_MESSAGE',
AUTO_ANALYZE_CHARACTER: 'AUTO_ANALYZE_CHARACTER',
GET_CONFIG_JSON: 'GET_CONFIG_JSON',
ORIGINAL_ADD_WEBUI_JSON: 'ORIGINAL_ADD_WEBUI_JSON',
GET_PROMPT_JSON: 'GET_PROMPT_JSON',
GPT_PROMPT: 'GPT_PROMPT',
GPT_GENERATE_PROMPT_RETURN: 'GPT_GENERATE_PROMPT_RETURN',
AUTO_SAVE_DATA_JSON: 'AUTO_SAVE_DATA_JSON',
ORIGINAL_SD_SINGLE_IMAGE_GENERATE: 'ORIGINAL_SD_SINGLE_IMAGE_GENERATE',
SD_ORIGINAL_GENERATE_IMAGE_RETURN: 'SD_ORIGINAL_GENERATE_IMAGE_RETURN',
GET_STYLE_IMAGE_SUB_LIST: 'GET_STYLE_IMAGE_SUB_LIST',
GET_IMAGE_STYLE_INFOMATION: 'GET_IMAGE_STYLE_INFOMATION',
GET_IMAGE_STYLE_MENU: 'GET_IMAGE_STYLE_MENU',
GET_GPT_BUSINESS_OPTION: 'GET_GPT_BUSINESS_OPTION',
GET_GPT_MODEL_OPTION: 'GET_GPT_MODEL_OPTION',
GET_GPT_AUTO_INFERENCE_OPTIONS: 'GET_GPT_AUTO_INFERENCE_OPTIONS',
SAVE_DYNAMIC_GPT_OPTION: 'SAVE_DYNAMIC_GPT_OPTION',
DELETE_DYNAMIC_GPT_OPTION: 'DELETE_DYNAMIC_GPT_OPTION',
TEST_GPT_CONNECTION: 'TEST_GPT_CONNECTION',
SAVE_WORD_TXT: 'SAVE_WORD_TXT',
GET_KEY_FRAME_CONFIG_DATA: 'GET_KEY_FRAME_CONFIG_DATA',
GET_KEYFRAME_OPTIONS: 'GET_KEYFRAME_OPTIONS',
QUEUE_BATCH: {
SD_ORIGINAL_GENERATE_IMAGE: "SD_ORIGINAL_GENERATE_IMAGE",
SD_ORIGINAL_GPT_PROMPT: "SD_ORIGINAL_GPT_PROMPT",
SD_BACKSTEP_GENERATE_IMAGE: "SD_BACKSTEP_GENERATE_IMAGE",
MJ_ORIGINAL_GENERATE_IMAGE: "MJ_ORIGINAL_GENERATE_IMAGE",
LOCAL_IMAGE_IMPROVE: "LOCAL_IMAGE_IMPROVE",
AUTO_VIDEO_GENERATE: "AUTO_VIDEO_GENERATE",
AUTO_VIDEO_GENERATE_SINGLE: "AUTO_VIDEO_GENERATE_SINGLE",
TRANSLATE_PROMPT: "TRANSLATE_PROMPT",
TRANSLATE_RETURN_NOW_TASK: "TRANSLATE_RETURN_NOW_TASK",
IMAGE_SAVE_TO_OTHER_FOLDER: "IMAGE_SAVE_TO_OTHER_FOLDER",
SAVE_FILE_QUEUE: "SAVE_FILE_QUEUE",
AUTO_SAVE_DATA_JSON: "AUTO_SAVE_DATA_JSON"
SD_ORIGINAL_GENERATE_IMAGE: 'SD_ORIGINAL_GENERATE_IMAGE',
SD_ORIGINAL_GPT_PROMPT: 'SD_ORIGINAL_GPT_PROMPT',
SD_BACKSTEP_GENERATE_IMAGE: 'SD_BACKSTEP_GENERATE_IMAGE',
MJ_ORIGINAL_GENERATE_IMAGE: 'MJ_ORIGINAL_GENERATE_IMAGE',
LOCAL_IMAGE_IMPROVE: 'LOCAL_IMAGE_IMPROVE',
AUTO_VIDEO_GENERATE: 'AUTO_VIDEO_GENERATE',
AUTO_VIDEO_GENERATE_SINGLE: 'AUTO_VIDEO_GENERATE_SINGLE',
TRANSLATE_PROMPT: 'TRANSLATE_PROMPT',
TRANSLATE_RETURN_NOW_TASK: 'TRANSLATE_RETURN_NOW_TASK',
IMAGE_SAVE_TO_OTHER_FOLDER: 'IMAGE_SAVE_TO_OTHER_FOLDER',
SAVE_FILE_QUEUE: 'SAVE_FILE_QUEUE',
AUTO_SAVE_DATA_JSON: 'AUTO_SAVE_DATA_JSON'
},
PERMISSIONS: {
NORMAL_PERMISSION: "NORMAL_PERMISSION",
AUTO_SAVE_IMAGE_PERMISSION: "AUTO_SAVE_IMAGE_PERMISSION",
NORMAL_PERMISSION: 'NORMAL_PERMISSION',
AUTO_SAVE_IMAGE_PERMISSION: 'AUTO_SAVE_IMAGE_PERMISSION'
},
SD: {
LOAD_SD_SERVICE_DATA: "LOAD_SD_SERVICE_DATA",
TXT2IMG: "TXT2IMG",
LOAD_SD_SERVICE_DATA: 'LOAD_SD_SERVICE_DATA',
TXT2IMG: 'TXT2IMG'
},
MJ: {
SAVE_WORD_SRT: "SAVE_WORD_SRT",
GET_MJ_CONFIG_SRT_INFORMATION: "GET_MJ_CONFIG_SRT_INFORMATION",
GET_TAG_DATA_BY_TYPE_AND_PROPERTY: "GET_TAG_DATA_BY_TYPE_AND_PROPERTY",
SAVE_TAG_PROPERTY_DATA: "SAVE_TAG_PROPERTY_DATA",
DELETE_TAG_PROPERTY_DATA: "DELETE_TAG_PROPERTY_DATA",
GET_TAG_SELECT_MODEL: "GET_TAG_SELECT_MODEL",
TRANSLATE_RETURN_NOW_TASK: "TRANSLATE_RETURN_NOW_TASK",
ORIGINAL_MJ_IMAGE_GENERATE: "ORIGINAL_MJ_IMAGE_GENERATE",
GET_CHANNEL_ROBOTS: "GET_CHANNEL_ROBOTS",
GET_MJ_GENERATE_CATEGORY: "GET_MJ_GENERATE_CATEGORY",
IMAGE_SPLIT: "IMAGE_SPLIT",
ADD_MJ_BAD_PROMPT: "ADD_MJ_BAD_PROMPT",
MJ_BAD_PROMPT_CHECK: "MJ_BAD_PROMPT_CHECK",
GET_GENERATED_MJ_IMAGE_AND_SPLIT: "GET_GENERATED_MJ_IMAGE_AND_SPLIT",
DOWNLOAD_IMAGE_URL_AND_SPLIT: "DOWNLOAD_IMAGE_URL_AND_SPLIT",
SAVE_WORD_SRT: 'SAVE_WORD_SRT',
GET_MJ_CONFIG_SRT_INFORMATION: 'GET_MJ_CONFIG_SRT_INFORMATION',
GET_TAG_DATA_BY_TYPE_AND_PROPERTY: 'GET_TAG_DATA_BY_TYPE_AND_PROPERTY',
SAVE_TAG_PROPERTY_DATA: 'SAVE_TAG_PROPERTY_DATA',
DELETE_TAG_PROPERTY_DATA: 'DELETE_TAG_PROPERTY_DATA',
GET_TAG_SELECT_MODEL: 'GET_TAG_SELECT_MODEL',
TRANSLATE_RETURN_NOW_TASK: 'TRANSLATE_RETURN_NOW_TASK',
ORIGINAL_MJ_IMAGE_GENERATE: 'ORIGINAL_MJ_IMAGE_GENERATE',
GET_CHANNEL_ROBOTS: 'GET_CHANNEL_ROBOTS',
GET_MJ_GENERATE_CATEGORY: 'GET_MJ_GENERATE_CATEGORY',
IMAGE_SPLIT: 'IMAGE_SPLIT',
ADD_MJ_BAD_PROMPT: 'ADD_MJ_BAD_PROMPT',
MJ_BAD_PROMPT_CHECK: 'MJ_BAD_PROMPT_CHECK',
GET_GENERATED_MJ_IMAGE_AND_SPLIT: 'GET_GENERATED_MJ_IMAGE_AND_SPLIT',
DOWNLOAD_IMAGE_URL_AND_SPLIT: 'DOWNLOAD_IMAGE_URL_AND_SPLIT',
GET_MJ_IMAGE_SCALE: 'GET_MJ_IMAGE_SCALE',
GET_MJ_IMAGE_ROBOT_MODEL: "GET_MJ_IMAGE_ROBOT_MODEL",
MACTH_USER_RETURN: "MACTH_USER_RETURN",
AUTO_MATCH_USER: "AUTO_MATCH_USER",
GET_MJ_IMAGE_ROBOT_MODEL: 'GET_MJ_IMAGE_ROBOT_MODEL',
MACTH_USER_RETURN: 'MACTH_USER_RETURN',
AUTO_MATCH_USER: 'AUTO_MATCH_USER'
},
DISCORD: {
OPERATE_REFRASH_DISCORD_URL: "OPERATE_REFRASH_DISCORD_URL",
GET_DISCORD_WINDOW_URL: "GET_DISCORD_WINDOW_URL",
CREATE_MESSAGE: "CREATE_MESSAGE",
UPDATE_MESSAGE: "UPDATE_MESSAGE",
DELETE_MESSAGE: "DELETE_MESSAGE",
MAIN_DISCORD_MESSAGE_CHANGE: "MAIN_DISCORD_MESSAGE_CHANGE",
OPERATE_REFRASH_DISCORD_URL: 'OPERATE_REFRASH_DISCORD_URL',
GET_DISCORD_WINDOW_URL: 'GET_DISCORD_WINDOW_URL',
CREATE_MESSAGE: 'CREATE_MESSAGE',
UPDATE_MESSAGE: 'UPDATE_MESSAGE',
DELETE_MESSAGE: 'DELETE_MESSAGE',
MAIN_DISCORD_MESSAGE_CHANGE: 'MAIN_DISCORD_MESSAGE_CHANGE'
},
DISCORD_REQUEST_LISTENER_TYPE: {
INPUT_MODEL_IMAGINE_REQUEST: "INPUT_MODEL_IMAGINE_REQUEST",
INPUT_MODEL_IMAGINE_REQUEST: 'INPUT_MODEL_IMAGINE_REQUEST'
},
DISCORD_SIMPLE_DATA_TYPE: {
URL: "URL",
TOKEN: "TOKEN",
URL: 'URL',
TOKEN: 'TOKEN'
},
MAIN: {
OPEN_DISCORD_WINDOW: "OPEN_DISCORD_WINDOW"
OPEN_DISCORD_WINDOW: 'OPEN_DISCORD_WINDOW'
},
IMG: {
ONE_SPLIT_FOUR: "ONE_SPLIT_FOUR",
BASE64_TO_FILE: "BASE64_TO_FILE",
PROCESS_IMAGE: "PROCESS_IMAGE",
BATCH_PROCESS_IMAGE: "BATCH_PROCESS_IMAGE",
BATCH_PROCESS_IMAGE_RESULT: "BATCH_PROCESS_IMAGE_RESULT"
ONE_SPLIT_FOUR: 'ONE_SPLIT_FOUR',
BASE64_TO_FILE: 'BASE64_TO_FILE',
PROCESS_IMAGE: 'PROCESS_IMAGE',
BATCH_PROCESS_IMAGE: 'BATCH_PROCESS_IMAGE',
BATCH_PROCESS_IMAGE_RESULT: 'BATCH_PROCESS_IMAGE_RESULT'
},
BOOK: {
GET_BOOK_TYPE: "GET_BOOK_TYPE",
ADD_OR_MODIFY_BOOK: "ADD_OR_MODIFY_BOOK",
GET_BOOK_DATA: "GET_BOOK_DATA",
GET_FRAME_DATA: "GET_FRAME_DATA",
GET_BOOK_TASK_DATA: "GET_BOOK_TASK_DATA"
GET_BOOK_TYPE: 'GET_BOOK_TYPE',
ADD_OR_MODIFY_BOOK: 'ADD_OR_MODIFY_BOOK',
GET_BOOK_DATA: 'GET_BOOK_DATA',
GET_FRAME_DATA: 'GET_FRAME_DATA',
GET_BOOK_TASK_DATA: 'GET_BOOK_TASK_DATA',
AUTO_ACTION: 'AUTO_ACTION'
},
SYSTEM: {
OPEN_FILE: "OPEN_FILE",
RETURN_LOGGER: "RETURN_LOGGER",
OPEN_FILE: 'OPEN_FILE',
RETURN_LOGGER: 'RETURN_LOGGER'
},
SETTING: {
GET_DATA_BY_TYPE_AND_PROPERTY: "GET_DATA_BY_TYPE_AND_PROPERTY",
SAVE_DATA_BY_TYPE_AND_PROPERTY: "SAVE_DATA_BY_TYPE_AND_PROPERTY",
DELETE_DATA_BY_TYPE_AND_PROPERTY: "DELETE_DATA_BY_TYPE_AND_PROPERTY",
GET_SOFTWARE_SETTING: "GET_SOFTWARE_SETTING",
SAVE_SOFT_WARE_SETTING: "SAVE_SOFT_WARE_SETTING",
GET_COMPONENT_SIZE: "GET_COMPONENT_SIZE",
GET_MJ_SETTING_TREE_DATA: "GET_MJ_SETTING_TREE_DATA",
SAVE_MJ_SETTING_TREE_DATA: "SAVE_MJ_SETTING_TREE_DATA",
MJ_REMOTE_ACCOUNT_SYNC: "MJ_REMOTE_ACCOUNT_SYNC",
GET_MJ_SETTING: "GET_MJ_SETTING",
UPDATE_MJ_SETTING: "UPDATE_MJ_SETTING"
GET_DATA_BY_TYPE_AND_PROPERTY: 'GET_DATA_BY_TYPE_AND_PROPERTY',
SAVE_DATA_BY_TYPE_AND_PROPERTY: 'SAVE_DATA_BY_TYPE_AND_PROPERTY',
DELETE_DATA_BY_TYPE_AND_PROPERTY: 'DELETE_DATA_BY_TYPE_AND_PROPERTY',
GET_SOFTWARE_SETTING: 'GET_SOFTWARE_SETTING',
SAVE_SOFT_WARE_SETTING: 'SAVE_SOFT_WARE_SETTING',
GET_COMPONENT_SIZE: 'GET_COMPONENT_SIZE',
GET_MJ_SETTING_TREE_DATA: 'GET_MJ_SETTING_TREE_DATA',
SAVE_MJ_SETTING_TREE_DATA: 'SAVE_MJ_SETTING_TREE_DATA',
MJ_REMOTE_ACCOUNT_SYNC: 'MJ_REMOTE_ACCOUNT_SYNC',
GET_MJ_SETTING: 'GET_MJ_SETTING',
UPDATE_MJ_SETTING: 'UPDATE_MJ_SETTING',
GET_REMOTE_MJ_SETTINGS: 'GET_REMOTE_MJ_SETTINGS',
ADD_REMOTE_MJ_SETTING: 'ADD_REMOTE_MJ_SETTING',
UPDATE_REMOTE_MJ_SETTING: 'UPDATE_REMOTE_MJ_SETTING',
DELETE_REMOTE_MJ_SETTING: 'DELETE_REMOTE_MJ_SETTING'
},
PROMPT: {
GET_SORT_OPTIONS: "GET_SORT_OPTIONS",
SAVE_PROMPT_SORT_DATA: "SAVE_PROMPT_SORT_DATA",
GET_PROMPT_SORT_DATA: "GET_PROMPT_SORT_DATA",
OPEN_PROMPT_FILE_TXT: "OPEN_PROMPT_FILE_TXT"
GET_SORT_OPTIONS: 'GET_SORT_OPTIONS',
SAVE_PROMPT_SORT_DATA: 'SAVE_PROMPT_SORT_DATA',
GET_PROMPT_SORT_DATA: 'GET_PROMPT_SORT_DATA',
OPEN_PROMPT_FILE_TXT: 'OPEN_PROMPT_FILE_TXT'
}
}

View File

@ -1,123 +1,217 @@
const {
ipcMain, app
} = require("electron")
const { ipcMain, app } = require('electron')
import { DEFINE_STRING } from '../../define/define_string'
import { GetDataByTypeAndProperty, SaveDataByTypeAndProperty, DeleteDataByTypeAndProperty } from '../../define/setting/dynamicSetting';
import {
Setting
} from '../setting/setting'
let setting = new Setting(global);
import { BasicSetting } from '../setting/basicSetting';
let basicSetting = new BasicSetting();
import { MJSetting } from '../setting/mjSetting';
let mjSetting = new MJSetting();
GetDataByTypeAndProperty,
SaveDataByTypeAndProperty,
DeleteDataByTypeAndProperty
} from '../../define/setting/dynamicSetting'
import { Setting } from '../setting/setting'
let setting = new Setting(global)
import { BasicSetting } from '../setting/basicSetting'
let basicSetting = new BasicSetting()
import { MJSetting } from '../setting/mjSetting'
let mjSetting = new MJSetting()
async function SettingIpc() {
// 获取背景音乐配置列表
ipcMain.handle(DEFINE_STRING.GET_BACKGROUND_MUSIC_CONFIG_LIST, async (event) => await setting.GetBackGroundMusicConfigList());
ipcMain.handle(
DEFINE_STRING.GET_BACKGROUND_MUSIC_CONFIG_LIST,
async (event) => await setting.GetBackGroundMusicConfigList()
)
// 获取剪映关键帧配置列表
ipcMain.handle(DEFINE_STRING.GET_KEYFRAME_OPTIONS, async (event) => await setting.GetKeyFrameOptions());
ipcMain.handle(
DEFINE_STRING.GET_KEYFRAME_OPTIONS,
async (event) => await setting.GetKeyFrameOptions()
)
// 保存剪映关键帧配置
ipcMain.handle(DEFINE_STRING.SAVE_KEY_FRAME_SETTING, async (event, value) => await setting.SaveKeyFrameSetting(value));
ipcMain.handle(
DEFINE_STRING.SAVE_KEY_FRAME_SETTING,
async (event, value) => await setting.SaveKeyFrameSetting(value)
)
// 监听添加背景音乐文件
ipcMain.handle(DEFINE_STRING.ADD_BACKGROUND_MUSIC_FOLDER, async (event, value) => await setting.AddBackgroundMusicFolder(value))
ipcMain.handle(
DEFINE_STRING.ADD_BACKGROUND_MUSIC_FOLDER,
async (event, value) => await setting.AddBackgroundMusicFolder(value)
)
// 删除剪映的样式设置
ipcMain.handle(DEFINE_STRING.DELETE_DRAFT_TEXT_STYLE, async (event, value) => await setting.deleteClipSetting("text_style", value));
ipcMain.handle(
DEFINE_STRING.DELETE_DRAFT_TEXT_STYLE,
async (event, value) => await setting.deleteClipSetting('text_style', value)
)
// 删除剪映的背景音乐设置
ipcMain.handle(DEFINE_STRING.DELETE_CLIP_SETTING, async (event, value) => await setting.deleteClipSetting("background_music_setting", value));
ipcMain.handle(
DEFINE_STRING.DELETE_CLIP_SETTING,
async (event, value) => await setting.deleteClipSetting('background_music_setting', value)
)
// 删除剪映的友情提示设置
ipcMain.handle(DEFINE_STRING.DELETE_FRIENDLY_REMINDER, async (event, value) => await setting.deleteClipSetting("friendly_reminder_setting", value));
ipcMain.handle(
DEFINE_STRING.DELETE_FRIENDLY_REMINDER,
async (event, value) => await setting.deleteClipSetting('friendly_reminder_setting', value)
)
// 监听获取SD配置任务
ipcMain.handle(DEFINE_STRING.INIT_SD_CONFIG, async (event, value) => await setting.InitSDConfig());
ipcMain.handle(DEFINE_STRING.INIT_SD_CONFIG, async (event, value) => await setting.InitSDConfig())
// 获取主页显示信息
ipcMain.handle(DEFINE_STRING.GET_SHOW_MESSAGE, async (event) => await setting.GetShowMessage())
// 获取关键帧的配置数据
ipcMain.handle(DEFINE_STRING.GET_KEY_FRAME_CONFIG_DATA, async (event) => await setting.GetKeyFrameConfigData());
ipcMain.handle(
DEFINE_STRING.GET_KEY_FRAME_CONFIG_DATA,
async (event) => await setting.GetKeyFrameConfigData()
)
// 删除后台队列任务
ipcMain.handle(DEFINE_STRING.DELETE_BACK_TASK, async (event, value) => await setting.RemoveTask(value));
ipcMain.handle(
DEFINE_STRING.DELETE_BACK_TASK,
async (event, value) => await setting.RemoveTask(value)
)
// 获取自动保存图片的分类方式
ipcMain.handle(DEFINE_STRING.GET_AUTO_SAVE_IMAGE_CLASSIFY_OPTIONS, async (event) => await setting.GetAutoSaveImageClassifyOptions());
ipcMain.handle(
DEFINE_STRING.GET_AUTO_SAVE_IMAGE_CLASSIFY_OPTIONS,
async (event) => await setting.GetAutoSaveImageClassifyOptions()
)
// 保存图片自动保存的配置
ipcMain.handle(DEFINE_STRING.SAVE_IMAGE_AUTO_SAVE_SETTING, async (event, value) => await setting.SaveImageAutoSaveSetting(value));
ipcMain.handle(
DEFINE_STRING.SAVE_IMAGE_AUTO_SAVE_SETTING,
async (event, value) => await setting.SaveImageAutoSaveSetting(value)
)
// 获取当前的自动保存图片的设置
ipcMain.handle(DEFINE_STRING.GET_IMAGE_AUTO_SAVE_SETTING, async (event) => await setting.GetImageAutoSaveSetting());
ipcMain.handle(
DEFINE_STRING.GET_IMAGE_AUTO_SAVE_SETTING,
async (event) => await setting.GetImageAutoSaveSetting()
)
// 开始手动保存图片
ipcMain.handle(DEFINE_STRING.SAVE_IMAGE_TO_OTHER_FOLDER, async (event, value) => await setting.SaveImageToOtherFolder(value));
ipcMain.handle(
DEFINE_STRING.SAVE_IMAGE_TO_OTHER_FOLDER,
async (event, value) => await setting.SaveImageToOtherFolder(value)
)
// 检查机器码是否存在
ipcMain.handle(DEFINE_STRING.CHECK_MACHINE_ID, async (event, value) => await setting.CheckMachineId(value));
ipcMain.handle(
DEFINE_STRING.CHECK_MACHINE_ID,
async (event, value) => await setting.CheckMachineId(value)
)
//修改剪映草稿配置
ipcMain.handle(DEFINE_STRING.MODIFY_SAMPLE_SETTING, async (event, value) => await setting.ModifySampleSetting(value));
ipcMain.handle(
DEFINE_STRING.MODIFY_SAMPLE_SETTING,
async (event, value) => await setting.ModifySampleSetting(value)
)
// 获取选择角色场景模式的options
ipcMain.handle(DEFINE_STRING.MJ.GET_TAG_SELECT_MODEL, async (event) => await setting.GetRoleSceneModeOptions());
ipcMain.handle(
DEFINE_STRING.MJ.GET_TAG_SELECT_MODEL,
async (event) => await setting.GetRoleSceneModeOptions()
)
// 获取当前生成图片的生图方式sd,mj,d3
ipcMain.handle(DEFINE_STRING.GET_IMAGE_GENERATE_CATEGORY, async (event) => await setting.GetImageGenerateCategory());
ipcMain.handle(
DEFINE_STRING.GET_IMAGE_GENERATE_CATEGORY,
async (event) => await setting.GetImageGenerateCategory()
)
// // 获取指定的配置文件里面指定的属性的数据
ipcMain.handle(DEFINE_STRING.GET_DEFINE_CONFIG_JSON_BY_PROPERTY, async (event, value) => await setting.GetDefineConfigJsonByProperty(value))
ipcMain.handle(
DEFINE_STRING.GET_DEFINE_CONFIG_JSON_BY_PROPERTY,
async (event, value) => await setting.GetDefineConfigJsonByProperty(value)
)
// // 保存指定的配置文件里面指定的属性的数据
ipcMain.handle(DEFINE_STRING.SAVE_DEFINE_CONFIG_JSON_BY_PROPERTY, async (event, value) => await setting.SaveDefineConfigJsonByProperty(value))
ipcMain.handle(
DEFINE_STRING.SAVE_DEFINE_CONFIG_JSON_BY_PROPERTY,
async (event, value) => await setting.SaveDefineConfigJsonByProperty(value)
)
//#region 动态设置(只是动态设置)
// 获取动态配置的的指定主分类指定的属性的数据只是获取动态的type定死了dynamic
ipcMain.handle(DEFINE_STRING.SETTING.GET_DATA_BY_TYPE_AND_PROPERTY, async (event, value) => await GetDataByTypeAndProperty(value));
ipcMain.handle(
DEFINE_STRING.SETTING.GET_DATA_BY_TYPE_AND_PROPERTY,
async (event, value) => await GetDataByTypeAndProperty(value)
)
// 保存动态配置的的指定主分类,指定的属性的数据
ipcMain.handle(DEFINE_STRING.SETTING.SAVE_DATA_BY_TYPE_AND_PROPERTY, async (event, value) => await SaveDataByTypeAndProperty(value));
ipcMain.handle(
DEFINE_STRING.SETTING.SAVE_DATA_BY_TYPE_AND_PROPERTY,
async (event, value) => await SaveDataByTypeAndProperty(value)
)
// 删除动态配置的的指定主分类,指定的属性的数据
ipcMain.handle(DEFINE_STRING.SETTING.DELETE_DATA_BY_TYPE_AND_PROPERTY, async (event, value) => await DeleteDataByTypeAndProperty(value));
ipcMain.handle(
DEFINE_STRING.SETTING.DELETE_DATA_BY_TYPE_AND_PROPERTY,
async (event, value) => await DeleteDataByTypeAndProperty(value)
)
//#endregion
//#region 基础设置
// 获取软件的基础设置(初始的时候执行一次)
ipcMain.handle(DEFINE_STRING.SETTING.GET_SOFTWARE_SETTING, async (event) => await basicSetting.GetSoftwareSetting());
ipcMain.handle(
DEFINE_STRING.SETTING.GET_SOFTWARE_SETTING,
async (event) => await basicSetting.GetSoftwareSetting()
)
// 保存软件的基础设置
ipcMain.handle(DEFINE_STRING.SETTING.SAVE_SOFT_WARE_SETTING, async (event, value) => await basicSetting.SaveSoftWareSetting(value));
ipcMain.handle(
DEFINE_STRING.SETTING.SAVE_SOFT_WARE_SETTING,
async (event, value) => await basicSetting.SaveSoftWareSetting(value)
)
// 返回组件尺寸的大小的数据(通用)
ipcMain.handle(DEFINE_STRING.SETTING.GET_COMPONENT_SIZE, async (event) => basicSetting.GetComponentSize());
ipcMain.handle(DEFINE_STRING.SETTING.GET_COMPONENT_SIZE, async (event) =>
basicSetting.GetComponentSize()
)
//#endregion
//#region MJ 设置
// 获取MJ基础设置信息
ipcMain.handle(DEFINE_STRING.SETTING.GET_MJ_SETTING, async (event, value) => mjSetting.GetMJSetting(value));
ipcMain.handle(DEFINE_STRING.SETTING.GET_MJ_SETTING, async (event, value) =>
mjSetting.GetMJSetting(value)
)
// 保存MJ的基础设置信息
ipcMain.handle(DEFINE_STRING.SETTING.UPDATE_MJ_SETTING, async (event, value) => mjSetting.UpdateMJSetting(value));
ipcMain.handle(DEFINE_STRING.SETTING.UPDATE_MJ_SETTING, async (event, value) =>
mjSetting.UpdateMJSetting(value)
)
// 获取MJ的所有设置
ipcMain.handle(DEFINE_STRING.SETTING.GET_MJ_SETTING_TREE_DATA, async (event) => mjSetting.GetMJSettingTreeData());
ipcMain.handle(DEFINE_STRING.SETTING.GET_MJ_SETTING_TREE_DATA, async (event) =>
mjSetting.GetMJSettingTreeData()
)
// 保存MJ的所有设置
ipcMain.handle(DEFINE_STRING.SETTING.SAVE_MJ_SETTING_TREE_DATA, async (event, value) => mjSetting.SaveMJSettingTreeData(value));
ipcMain.handle(DEFINE_STRING.SETTING.SAVE_MJ_SETTING_TREE_DATA, async (event, value) =>
mjSetting.SaveMJSettingTreeData(value)
)
// 获取所有的代理MJ信息
ipcMain.handle(DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS, async (event) =>
mjSetting.GetRemoteMJSettings()
)
// 创建新的代理MJ信息
ipcMain.handle(DEFINE_STRING.SETTING.ADD_REMOTE_MJ_SETTING, async (event, value) =>
mjSetting.AddRemoteMJSetting(value)
)
// 修改MJ账号并重连
ipcMain.handle(DEFINE_STRING.SETTING.UPDATE_REMOTE_MJ_SETTING, async (event, value) =>
mjSetting.UpdateRemoteMJSetting(value)
)
// 删除指定的MJ账号
ipcMain.handle(DEFINE_STRING.SETTING.DELETE_REMOTE_MJ_SETTING, async (event, value) =>
mjSetting.DeleteRemoteMJSetting(value)
)
// MJ代理模式账号同步
ipcMain.handle(DEFINE_STRING.SETTING.MJ_REMOTE_ACCOUNT_SYNC, async (event) => mjSetting.MjRemoteAccountSync());
//#endregion
}
export {
SettingIpc
}
export { SettingIpc }

View File

@ -1,44 +1,44 @@
import { DEFINE_STRING } from "../../define/define_string";
import { DEFINE_STRING } from '../../define/define_string'
import { AsyncQueue } from '../quene'
import { PublicMethod } from '../Public/publicMethod'
import { ImageStyleDefine } from '../../define/iamgeStyleDefine'
import { DiscordSimple } from "../discord/discordSimple";
import { DiscordWorker } from "../discord/discordWorker";
import { Tools } from "../tools";
import { DiscordSimple } from '../discord/discordSimple'
import { DiscordWorker } from '../discord/discordWorker'
import { Tools } from '../tools'
import path from 'path'
import sharp from 'sharp'
import { define } from "../../define/define";
import { AwesomeHelp } from "awesome-js";
import { checkStringValueAddSuffix, errorMessage, successMessage } from "../generalTools";
import { ImageSetting } from "../../define/setting/imageSetting";
import { DiscordAPI } from "../../api/discordApi";
import { GPT } from "../Public/GPT";
import { TagDefine } from "../../define/tagDefine";
import { cloneDeep } from "lodash";
import { LOGGER_DEFINE } from "../../define/logger_define";
import { MJImageType } from "../../define/enum/mjEnum";
import { MJSettingService } from "../../define/db/service/SoftWare/mjSettingService";
const { v4: uuidv4 } = require('uuid');
import { define } from '../../define/define'
import { AwesomeHelp } from 'awesome-js'
import { checkStringValueAddSuffix, errorMessage, successMessage } from '../generalTools'
import { ImageSetting } from '../../define/setting/imageSetting'
import { DiscordAPI } from '../../api/discordApi'
import { GPT } from '../Public/GPT'
import { TagDefine } from '../../define/tagDefine'
import { cloneDeep } from 'lodash'
import { LOGGER_DEFINE } from '../../define/logger_define'
import { MJImageType } from '../../define/enum/mjEnum'
import { MJSettingService } from '../../define/db/service/SoftWare/mjSettingService'
const { v4: uuidv4 } = require('uuid')
/**
* MJ原创生图的类
*/
export class MJOriginalImageGenerate {
constructor(global) {
this.global = global;
this.pm = new PublicMethod(global);
this.discordWorker = new DiscordWorker();
this.tools = new Tools();
this.discordAPI = new DiscordAPI();
this.gpt = new GPT(global);
this.tagDefine = new TagDefine(global);
this.global = global
this.pm = new PublicMethod(global)
this.discordWorker = new DiscordWorker()
this.tools = new Tools()
this.discordAPI = new DiscordAPI()
this.gpt = new GPT(global)
this.tagDefine = new TagDefine(global)
}
/**
* 返回指定的人物到前端
* @param {*} data
*/
sendChangeMessage(data, message_name = DEFINE_STRING.DISCORD.MAIN_DISCORD_MESSAGE_CHANGE) {
this.global.newWindow[0].win.webContents.send(message_name, data);
this.global.newWindow[0].win.webContents.send(message_name, data)
}
/**
@ -47,31 +47,37 @@ export class MJOriginalImageGenerate {
*/
async AutoMatchUser(value) {
try {
value = JSON.parse(value);
value = JSON.parse(value)
// 获取所有的角色数据,包括别名
// 获取所有的角色数据
let character_tags = await this.tagDefine.getTagDataByTypeAndProperty("dynamic", "character_tags");
let character_tags = await this.tagDefine.getTagDataByTypeAndProperty(
'dynamic',
'character_tags'
)
if (character_tags.code == 0) {
return errorMessage("获取角色数据错误,错误信息如下:" + character_tags.message, LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
return errorMessage(
'获取角色数据错误,错误信息如下:' + character_tags.message,
LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER
)
}
character_tags = character_tags.data;
character_tags = character_tags.data
if (character_tags.length == 0) {
return errorMessage("请先添加角色数据", LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
return errorMessage('请先添加角色数据', LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
}
let character_tags_data = [];
let character_tags_data = []
for (let i = 0; i < character_tags.length; i++) {
let item = character_tags[i];
let item = character_tags[i]
// 这边还要判断是不是显示只有显示的才hi自动匹配
if (!item.hasOwnProperty("isShow") || !item.isShow) {
continue;
if (!item.hasOwnProperty('isShow') || !item.isShow) {
continue
}
let temp_name = [item.label];
let temp_name = [item.label]
// 判断当前的数是不是存在别名
if (item.children && item.children.length > 0) {
for (let j = 0; j < item.children.length; j++) {
const element = item.children[j];
temp_name.push(element.label);
const element = item.children[j]
temp_name.push(element.label)
}
}
character_tags_data.push({
@ -81,42 +87,44 @@ export class MJOriginalImageGenerate {
})
}
if (character_tags_data.length == 0) {
return errorMessage("当前没有显示的角色数据,请先选择哪些是要显示的角色数据", LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
return errorMessage(
'当前没有显示的角色数据,请先选择哪些是要显示的角色数据',
LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER
)
}
for (let i = 0; i < value.length; i++) {
const element = value[i];
const element = value[i]
let res_data = {
code: 1,
id: element.id, // 当前 data 的ID
match_character: [],
match_character: []
}
// 获取当前的字幕数据
let temp_sub = [];
let temp_sub = []
for (let j = 0; element.suValue && j < element.suValue.length; j++) {
const element = array[j];
temp_sub.push(element.srt_value);
const element = array[j]
temp_sub.push(element.srt_value)
}
let word = "";
let word = ''
if (temp_sub.length == 0) {
word = element.after_gpt;
word = element.after_gpt
} else {
word = temp_sub.join(",");
word = temp_sub.join(',')
}
let match_keys = [];
let match_keys = []
// 开始循环判断,只要又一个满足就跳出新婚换
for (let j = 0; j < character_tags_data.length; j++) {
const item = character_tags_data[j];
let names = AwesomeHelp.makeSensitiveMap(item.names);
const item = character_tags_data[j]
let names = AwesomeHelp.makeSensitiveMap(item.names)
// 开始判断
let name_res = AwesomeHelp.checkSensitiveWord(word, false, names);
let name_res = AwesomeHelp.checkSensitiveWord(word, false, names)
if (name_res.size > 0) {
match_keys.push(item.key);
match_keys.push(item.key)
}
}
@ -124,12 +132,12 @@ export class MJOriginalImageGenerate {
if (match_keys.length > 0) {
// 进行数据的处理通过对应的key获取对应的数据将所有的数进行返回
for (let i = 0; i < match_keys.length; i++) {
const item = match_keys[i];
let index = character_tags.findIndex(x => x.key == item);
const item = match_keys[i]
let index = character_tags.findIndex((x) => x.key == item)
if (index == -1) {
continue;
continue
}
let temp_item_data = cloneDeep(character_tags[index]);
let temp_item_data = cloneDeep(character_tags[index])
if (temp_item_data.children) {
delete temp_item_data.children
}
@ -138,37 +146,41 @@ export class MJOriginalImageGenerate {
}
// 开始往前端传递数据
this.sendChangeMessage(res_data, DEFINE_STRING.MJ.MACTH_USER_RETURN);
this.sendChangeMessage(res_data, DEFINE_STRING.MJ.MACTH_USER_RETURN)
}
return successMessage(null, "人物标签自动匹配完成", LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
return successMessage(null, '人物标签自动匹配完成', LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
} catch (error) {
return errorMessage("通过文本自动匹配数据错误,错误信息如下:" + error.message, LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER)
return errorMessage(
'通过文本自动匹配数据错误,错误信息如下:' + error.message,
LOGGER_DEFINE.ORIGINAL_AUTO_MATCH_USER
)
}
}
/**
* 初始化MJ设置
*/
async InitMjSetting() {
let mjSetting_res = await ImageSetting.GetDefineConfigJsonByProperty(JSON.stringify(['img_base', 'mj_config', false, null]));
let mjSetting_res = await ImageSetting.GetDefineConfigJsonByProperty(
JSON.stringify(['img_base', 'mj_config', false, null])
)
if (mjSetting_res.code == 0 || !mjSetting_res.data) {
throw new Error("请先添加MJ配置")
throw new Error('请先添加MJ配置')
}
let mjSetting = mjSetting_res.data;
return mjSetting;
let mjSetting = mjSetting_res.data
return mjSetting
}
/**
* 初始化MJ API的URL
*/
async InitMJAPIUrl(id) {
let mj_api = (await this.gpt.GetGPTBusinessOption("all", (value) => value.mj_url)).data;
let mj_api_url_index = mj_api.findIndex(item => item.value == id);
let mj_api = (await this.gpt.GetGPTBusinessOption('all', (value) => value.mj_url)).data
let mj_api_url_index = mj_api.findIndex((item) => item.value == id)
if (mj_api_url_index == -1) {
throw new Error("没有找到对应的MJ API的配置请先检查配置")
throw new Error('没有找到对应的MJ API的配置请先检查配置')
}
return mj_api[mj_api_url_index];
return mj_api[mj_api_url_index]
}
/**
@ -178,33 +190,36 @@ export class MJOriginalImageGenerate {
async DownloadImageUrlAndSplit(value) {
try {
console.log(value)
value = JSON.parse(value);
let element = value[0];
let iamge_url = value[1];
let image_path = "";
value = JSON.parse(value)
let element = value[0]
let iamge_url = value[1]
let image_path = ''
if (value.length > 2) {
image_path = value[2];
image_path = value[2]
} else {
image_path = path.join(global.config.project_path, `data\\MJOriginalImage\\${element.id}.png`);
image_path = path.join(
global.config.project_path,
`data\\MJOriginalImage\\${element.id}.png`
)
}
// 判断是不是一个链接
const urlRegex = /^(http|https):\/\/[^ "]+$/;
const urlRegex = /^(http|https):\/\/[^ "]+$/
if (!urlRegex.test(iamge_url)) {
throw new Error("指定的图片地址不是一个链接");
throw new Error('指定的图片地址不是一个链接')
}
// 这边开始下载对应的图片
await this.tools.downloadFileUrl(iamge_url, image_path);
await this.tools.downloadFileUrl(iamge_url, image_path)
// 将下载的图片进行分割
let split_res = await this.ImageSplit(JSON.stringify([image_path, element.name]));
let split_res = await this.ImageSplit(JSON.stringify([image_path, element.name]))
if (split_res.code == 0) {
throw new Error(split_res.message);
throw new Error(split_res.message)
}
element.image_click = iamge_url;
element.subImagePath = split_res.data.subImagePath;
element.outImagePath = split_res.data.outImagePath;
element.image_click = iamge_url
element.subImagePath = split_res.data.subImagePath
element.outImagePath = split_res.data.outImagePath
element['image_path'] = image_path
return {
@ -214,7 +229,7 @@ export class MJOriginalImageGenerate {
} catch (error) {
return {
code: 0,
message: "下载指定的图片地址并且分割错误,错误信息如下:" + error.message
message: '下载指定的图片地址并且分割错误,错误信息如下:' + error.message
}
}
}
@ -226,19 +241,19 @@ export class MJOriginalImageGenerate {
*/
async GetGeneratedMJImageAndSplit(value) {
try {
value = JSON.parse(value);
let mjSetting = await this.InitMjSetting();
let request_model = mjSetting.requestModel;
let result = [];
value = JSON.parse(value)
let mjSetting = await this.InitMjSetting()
let request_model = mjSetting.requestModel
let result = []
// 浏览器生图模式
if (request_model == "browser_mj") {
let param = [];
if (request_model == 'browser_mj') {
let param = []
// 循环数据,直传需要的数据
for (let i = 0; i < value.length; i++) {
const element = value[i];
const element = value[i]
// 一般进度大于 50 会出现图片,
if (!element.mj_message) {
continue;
continue
}
if (element.mj_message.progress && element.mj_message.progress == 100) {
// 判断 image_path 是不是存在。
@ -247,38 +262,44 @@ export class MJOriginalImageGenerate {
param.push({
id: element.id,
image_id: element.mj_message.image_id,
name: element.name,
});
name: element.name
})
}
}
}
// 判断窗口是不是开启
let discordWin = await this.discordWorker.CheckDiscordWindowIsOpenAndLoad();
let discordWin = await this.discordWorker.CheckDiscordWindowIsOpenAndLoad()
// 执行采集图片的脚本
// 开始写入
let discordSimple = new DiscordSimple(discordWin);
let discordSimple = new DiscordSimple(discordWin)
// 开始执行脚本
result = await discordSimple.ExecuteScript(define.discordScript, `GetGeneratedMJImageAndSplit(${JSON.stringify(param)})`);
} else if (request_model == "api_mj") {
let mj_api = await this.InitMJAPIUrl(mjSetting.apiSetting.mjApiUrl);
let once_get_task = mj_api.mj_url.once_get_task;
result = await discordSimple.ExecuteScript(
define.discordScript,
`GetGeneratedMJImageAndSplit(${JSON.stringify(param)})`
)
} else if (request_model == 'api_mj') {
let mj_api = await this.InitMJAPIUrl(mjSetting.apiSetting.mjApiUrl)
let once_get_task = mj_api.mj_url.once_get_task
// 请求
for (let i = 0; i < value.length; i++) {
const element = value[i];
const element = value[i]
if (element.mj_message.progress == 100) {
continue
}
if (element.mj_message.progress.status == "success") {
if (element.mj_message.progress.status == 'success') {
continue
}
let task_res = await this.discordAPI.GetMJAPITaskByID(element.mj_message.message_id, once_get_task, mjSetting.apiSetting.apiKey);
let task_res = await this.discordAPI.GetMJAPITaskByID(
element.mj_message.message_id,
once_get_task,
mjSetting.apiSetting.apiKey
)
if (task_res.code == 0) {
task_res["id"] = element.id;
task_res["mj_api_url"] = mjSetting.apiSetting.mjApiUrl;
task_res['id'] = element.id
task_res['mj_api_url'] = mjSetting.apiSetting.mjApiUrl
this.sendChangeMessage()
}
// 判断进度是不是百分百
@ -295,50 +316,55 @@ export class MJOriginalImageGenerate {
}
}
let res = [];
let res = []
// 判断返回的数据是不是一个字符串
if (typeof result == "string") {
result = JSON.parse(result);
if (typeof result == 'string') {
result = JSON.parse(result)
}
// 将返回的数据进行分割
for (let i = 0; i < result.length; i++) {
const element = result[i];
let image_path = path.join(global.config.project_path, `data\\MJOriginalImage\\${uuidv4()}.png`);
let ds = await this.DownloadImageUrlAndSplit(JSON.stringify([element, element.result, image_path]));
const element = result[i]
let image_path = path.join(
global.config.project_path,
`data\\MJOriginalImage\\${uuidv4()}.png`
)
let ds = await this.DownloadImageUrlAndSplit(
JSON.stringify([element, element.result, image_path])
)
if (ds.code == 0) {
throw new Error(ds.message);
throw new Error(ds.message)
}
// 修改数据。
ds.data["progress"] = 100;
ds.data["status"] = "success";
res.push(ds.data);
ds.data['progress'] = 100
ds.data['status'] = 'success'
res.push(ds.data)
}
// 全部分割完毕,返回
return successMessage(res);
return successMessage(res)
} catch (error) {
return errorMessage("获取已经生图完成的数据,并获取图片错误,错误信息如下" + error.message)
return errorMessage('获取已经生图完成的数据,并获取图片错误,错误信息如下' + error.message)
}
}
// MJ生成的图片分割
async ImageSplit(value) {
try {
value = JSON.parse(value);
let inputPath = value[0];
let r_name = value[1];
let outputDir = path.join(this.global.config.project_path, `data\\MJOriginalImage`);
const metadata = await sharp(inputPath).metadata();
const smallWidth = metadata.width / 2;
const smallHeight = metadata.height / 2;
let times = new Date().getTime();
let imgs = [];
let first_p = path.join(this.global.config.project_path, `tmp\\output_crop_00001\\${r_name}`);
value = JSON.parse(value)
let inputPath = value[0]
let r_name = value[1]
let outputDir = path.join(this.global.config.project_path, `data\\MJOriginalImage`)
const metadata = await sharp(inputPath).metadata()
const smallWidth = metadata.width / 2
const smallHeight = metadata.height / 2
let times = new Date().getTime()
let imgs = []
let first_p = path.join(this.global.config.project_path, `tmp\\output_crop_00001\\${r_name}`)
for (let i = 0; i < 4; i++) {
const xOffset = i % 2 === 0 ? 0 : smallWidth;
const yOffset = Math.floor(i / 2) * smallHeight;
let out_file = path.join(outputDir, `/${r_name}_${times}_${i}.png`);
const xOffset = i % 2 === 0 ? 0 : smallWidth
const yOffset = Math.floor(i / 2) * smallHeight
let out_file = path.join(outputDir, `/${r_name}_${times}_${i}.png`)
await sharp(inputPath)
.extract({
left: xOffset,
@ -347,16 +373,16 @@ export class MJOriginalImageGenerate {
height: smallHeight
})
.resize(smallWidth, smallHeight)
.toFile(out_file);
.toFile(out_file)
imgs.push(out_file);
imgs.push(out_file)
// 将第一个图片复制一个到指定的位置
if (i == 0) {
await this.tools.copyFileOrDirectory(out_file, first_p);
await this.tools.copyFileOrDirectory(out_file, first_p)
// 复制一份到input
let input_p = path.join(this.global.config.project_path, `tmp\\input_crop\\${r_name}`);
await this.tools.copyFileOrDirectory(out_file, input_p);
let input_p = path.join(this.global.config.project_path, `tmp\\input_crop\\${r_name}`)
await this.tools.copyFileOrDirectory(out_file, input_p)
}
}
@ -367,14 +393,12 @@ export class MJOriginalImageGenerate {
outImagePath: first_p
}
}
} catch (err) {
return {
code: 0,
message: "MJ图片切割错误错误信息如下" + err.message
message: 'MJ图片切割错误错误信息如下' + err.message
}
}
}
/**
@ -385,189 +409,190 @@ export class MJOriginalImageGenerate {
async MJImagineRequest(element, mjSetting, prompt, tasK_id = null, batch = null) {
try {
if (mjSetting.apiSetting == null) {
throw new Error("没有API设置请先设置API设置");
throw new Error('没有API设置请先设置API设置')
}
let apiUrl;
let apiUrl
if (mjSetting.requestModel == MJImageType.API_MJ) {
// 获取当前的API url
apiUrl = await this.InitMJAPIUrl(mjSetting.apiSetting.mjApiUrl);
apiUrl = await this.InitMJAPIUrl(mjSetting.apiSetting.mjApiUrl)
} else if (mjSetting.requestModel == MJImageType.REMOTE_MJ) {
apiUrl = {
mj_url: {
imagine: define.remotemj_api + 'mj/submit/imagine',
once_get_task: define.remotemj_api + "mj/task/${id}/fetch"
once_get_task: define.remotemj_api + 'mj/task/${id}/fetch'
}
}
} else {
throw new Error("未知的生图模式,请检查配置")
throw new Error('未知的生图模式,请检查配置')
}
let imagine_url = apiUrl.mj_url.imagine;
let once_get_task = apiUrl.mj_url.once_get_task;
let imagine_url = apiUrl.mj_url.imagine
let once_get_task = apiUrl.mj_url.once_get_task
let task_count = mjSetting.taskCount ? mjSetting.taskCount : 3;
let mj_speed = mjSetting.apiSetting.mjSpeed ? mjSetting.apiSetting.mjSpeed : "relaxed";
let res;
let task_count = mjSetting.taskCount ? mjSetting.taskCount : 3
let mj_speed = mjSetting.apiSetting.mjSpeed ? mjSetting.apiSetting.mjSpeed : 'relaxed'
let res
// 判断当前的API是哪个
if (imagine_url.includes("mjapi.deepwl.net")) {
if (imagine_url.includes('mjapi.deepwl.net')) {
// DrawAPI(MJ)
let data = {
prompt: prompt,
mode: mj_speed == "fast" ? "FAST" : "RELAX",
mode: mj_speed == 'fast' ? 'FAST' : 'RELAX'
}
let headers = {
"Authorization": mjSetting.apiSetting.apiKey
Authorization: mjSetting.apiSetting.apiKey
}
res = await this.discordAPI.mjApiImagine(imagine_url, data, headers);
res = await this.discordAPI.mjApiImagine(imagine_url, data, headers)
if (res.code == 24) {
throw new Error("提示词包含敏感词,请修改后重试");
throw new Error('提示词包含敏感词,请修改后重试')
}
} else if (imagine_url.includes("api.ephone.ai")) {
} else if (imagine_url.includes('api.ephone.ai')) {
// ePhoneAPI
let headers = {
"Authorization": mjSetting.apiSetting.apiKey
Authorization: mjSetting.apiSetting.apiKey
}
let data = {
prompt: prompt,
botType: "MID_JOURNEY",
botType: 'MID_JOURNEY',
accountFilter: {
modes: [
mj_speed == "fast" ? "FAST" : "RELAX"
]
modes: [mj_speed == 'fast' ? 'FAST' : 'RELAX']
}
}
res = await this.discordAPI.mjApiImagine(imagine_url, data, headers);
res = await this.discordAPI.mjApiImagine(imagine_url, data, headers)
} else if (imagine_url.includes(define.remotemj_api)) {
// 代理模式
let headers = {
"mj-api-secret": define.API
'mj-api-secret': define.API
}
// 判断数据是不是存在
if (!mjSetting.remoteSetting.channelId) {
throw new Error("请先设置channelId")
throw new Error('请先设置channelId')
}
if (!mjSetting.remoteSetting.accountId) {
throw new Error("请先同步账号")
throw new Error('请先同步账号')
}
let data = {
prompt: prompt,
botType: "MID_JOURNEY",
botType: 'MID_JOURNEY',
accountFilter: {
channelId: mjSetting.remoteSetting.channelId,
instanceId: mjSetting.remoteSetting.accountId,
remark: this.global.machineId,
modes: [
mj_speed == "fast" ? "FAST" : "RELAX"
]
remark: this.global.machineId
}
}
res = await this.discordAPI.mjApiImagine(imagine_url, data, headers);
res = await this.discordAPI.mjApiImagine(imagine_url, data, headers)
}
this.global.mjGenerateQuene.setCurrentCreateItem(null);
this.global.mjGenerateQuene.setCurrentCreateItem(null)
// 错误检查
if (res.code == 23) {
// 任务队列已满,及结束该任务,然后开始下一个任务,并将该任务重新排序
this.global.mjGenerateQuene.removeTaskProgress((taskProgress) => {
return taskProgress.filter(item => item?.id != element.id)
});
return taskProgress.filter((item) => item?.id != element.id)
})
this.sendChangeMessage({
code: 0,
status: "error",
message: "任务队列已满任务结束会重新排序并等待3分钟开始后面的任务",
status: 'error',
message: '任务队列已满任务结束会重新排序并等待3分钟开始后面的任务',
id: element.id
})
await this.tools.delay(40000);
await this.tools.delay(40000)
// 重新将当前任务加入队列
this.global.mjGenerateQuene.enqueue(async () => {
this.global.mjGenerateQuene.enqueue(
async () => {
this.global.mjGenerateQuene.setCurrentCreateItem(element)
await this.MJImagineRequest(element, mjSetting, prompt)
}, tasK_id, batch)
},
tasK_id,
batch
)
this.global.mjGenerateQuene.startNextTask(task_count);
return;
this.global.mjGenerateQuene.startNextTask(task_count)
return
}
if (res.code != 1 && res.code != 22) {
// 未知错误,将当前任务删除,开始下一个任务
this.global.mjGenerateQuene.removeTaskProgress((taskProgress) => {
return taskProgress.filter(item => item?.id != element.id)
});
this.global.mjGenerateQuene.startNextTask(task_count);
return taskProgress.filter((item) => item?.id != element.id)
})
this.global.mjGenerateQuene.startNextTask(task_count)
this.sendChangeMessage({
code: 0,
status: "error",
message: "未知错误,可联系管理员排查," + res.description,
status: 'error',
message: '未知错误,可联系管理员排查,' + res.description,
id: element.id
})
return;
return
}
// 创建成功,开始下一个
this.sendChangeMessage({
code: 1,
type: "created",
category: "api_mj",
type: 'created',
category: 'api_mj',
message_id: res.result,
image_click: null,
image_show: null,
id: element.id,
progress: 0,
mj_api_url: mjSetting.apiSetting.mjApiUrl
});
})
// 开始监听当前ID是不是的生图任务完成
// 这边设置一个循环监听,每隔一段时间去请求一次
let timeoutId;
let timeoutId
let startInterval = () => {
timeoutId = setTimeout(async () => {
// 执行你的操作
let task_res = await this.discordAPI.GetMJAPITaskByID(res.result, once_get_task, mjSetting.apiSetting.apiKey)
let task_res = await this.discordAPI.GetMJAPITaskByID(
res.result,
once_get_task,
mjSetting.apiSetting.apiKey
)
console.log(task_res)
// 判断他的状态是不是成功
if (task_res.code == 0) {
// 将但钱任务删除
this.global.mjGenerateQuene.removeTaskProgress((taskProgress) => {
return taskProgress.filter(item => item?.id != element.id)
});
return taskProgress.filter((item) => item?.id != element.id)
})
// 停止当前循环
clearTimeout(timeoutId);
clearTimeout(timeoutId)
} else {
if (task_res.progress == 100) {
// 将但钱任务删除
this.global.mjGenerateQuene.removeTaskProgress((taskProgress) => {
return taskProgress.filter(item => item?.id != element.id)
});
task_res.type = "finished";
return taskProgress.filter((item) => item?.id != element.id)
})
task_res.type = 'finished'
// 下载对应的图片
let image_path = path.join(this.global.config.project_path, `data\\MJOriginalImage\\${task_res.message_id}.png`);
let image_path = path.join(
this.global.config.project_path,
`data\\MJOriginalImage\\${task_res.message_id}.png`
)
// 这边开始下载对应的图片
await this.tools.downloadFileUrl(task_res.image_click, image_path);
task_res["image_path"] = image_path;
await this.tools.downloadFileUrl(task_res.image_click, image_path)
task_res['image_path'] = image_path
// 开始下一个任务
this.global.mjGenerateQuene.startNextTask(task_count);
this.global.mjGenerateQuene.startNextTask(task_count)
} else {
// 当获取的图片的进度小于100的时候继续监听
startInterval();
startInterval()
}
}
task_res['id'] = element.id;
task_res["mj_api_url"] = mjSetting.apiSetting.mjApiUrl;
this.sendChangeMessage(task_res);
}, 5000);
task_res['id'] = element.id
task_res['mj_api_url'] = mjSetting.apiSetting.mjApiUrl
this.sendChangeMessage(task_res)
}, 5000)
}
startInterval();
this.global.mjGenerateQuene.startNextTask(task_count);
startInterval()
this.global.mjGenerateQuene.startNextTask(task_count)
} catch (error) {
this.sendChangeMessage({
code: 0,
status: "error",
status: 'error',
message: error.message,
id: element.id
})
throw new Error("MJ API 出图错误,错误信息如下:" + error.message)
throw new Error('MJ API 出图错误,错误信息如下:' + error.message)
}
}
@ -577,90 +602,102 @@ export class MJOriginalImageGenerate {
*/
async OriginalMJImageGenerate(value) {
try {
let data = value[0];
let data = value[0]
if (value[1]) {
data = JSON.parse(data);
data = JSON.parse(data)
}
let show_global_message = value[2];
let batch = DEFINE_STRING.QUEUE_BATCH.MJ_ORIGINAL_GENERATE_IMAGE;
let show_global_message = value[2]
let batch = DEFINE_STRING.QUEUE_BATCH.MJ_ORIGINAL_GENERATE_IMAGE
// 判断存放的文件夹是不是存在,不存在的话创建
let outputDir = path.join(this.global.config.project_path, `data\\MJOriginalImage`);
await this.tools.checkFolderExistsOrCreate(outputDir);
let fileExist = await this.tools.checkExists(outputDir);
let outputDir = path.join(this.global.config.project_path, `data\\MJOriginalImage`)
await this.tools.checkFolderExistsOrCreate(outputDir)
let fileExist = await this.tools.checkExists(outputDir)
if (!fileExist) {
await this.tools.createDirectory(outputDir);
await this.tools.createDirectory(outputDir)
}
// 判断该当前tmp\output_crop_00001文件夹是不是存在不存在创建
let output_crop_00001 = path.join(this.global.config.project_path, `tmp\\output_crop_00001`);
await this.tools.checkFolderExistsOrCreate(output_crop_00001);
let output_crop_00001 = path.join(this.global.config.project_path, `tmp\\output_crop_00001`)
await this.tools.checkFolderExistsOrCreate(output_crop_00001)
// 获取MJ配置从数据库中
let _mjSettingService = await MJSettingService.getInstance()
let mjSettings = _mjSettingService.GetMJSettingTreeData();
let mjSettings = _mjSettingService.GetMJSettingTreeData()
if (mjSettings.code == 0) {
throw new Error(mjSettings.message)
}
let mjSetting = mjSettings.data;
let mjSetting = mjSettings.data
// 检查this.global中是不是又mj队列没有的话创建一个
if (!this.global.mjGenerateQuene) {
this.global.mjGenerateQuene = new AsyncQueue(this.global, 1, true);
this.global.mjGenerateQuene = new AsyncQueue(this.global, 1, true)
}
// 替换风格的逻辑
let current_task = null;
let current_task = null
for (let i = 0; i < data.length; i++) {
const element = data[i];
let tasK_id = `${batch}_${element.name}_${element.id}`;
const element = data[i]
let tasK_id = `${batch}_${element.name}_${element.id}`
let old_prompt = element.prompt;
let old_prompt = element.prompt
// 拼接提示词
// 图生图的链接
// 获取风格词 + 命令后缀
let prompt = old_prompt + (mjSetting.imageSuffix ? mjSetting.imageSuffix : "");
let prompt = old_prompt + (mjSetting.imageSuffix ? mjSetting.imageSuffix : '')
// 判断当前生图模式
let request_model = mjSetting.requestModel
switch (request_model) {
case "api_mj":
this.global.mjGenerateQuene.enqueue(async () => {
case 'api_mj':
this.global.mjGenerateQuene.enqueue(
async () => {
this.global.mjGenerateQuene.setCurrentCreateItem(element)
await this.MJImagineRequest(element, mjSetting, prompt, tasK_id, batch)
}, tasK_id, batch)
break;
},
tasK_id,
batch
)
break
case MJImageType.REMOTE_MJ:
this.global.mjGenerateQuene.enqueue(async () => {
this.global.mjGenerateQuene.enqueue(
async () => {
this.global.mjGenerateQuene.setCurrentCreateItem(element)
await this.MJImagineRequest(element, mjSetting, prompt, tasK_id, batch)
}, tasK_id, batch)
break;
},
tasK_id,
batch
)
break
case "browser_mj":
this.global.mjGenerateQuene.enqueue(async () => {
case 'browser_mj':
this.global.mjGenerateQuene.enqueue(
async () => {
try {
this.global.mjGenerateQuene.setCurrentCreateItem(element)
// 开始进行mj生图
current_task = element.name;
current_task = element.name
// 判断窗口是不是开启
let discordW = await this.discordWorker.CheckDiscordWindowIsOpenAndLoad();
let discordW = await this.discordWorker.CheckDiscordWindowIsOpenAndLoad()
// 开始写入
let discordSimple = new DiscordSimple(discordW, mjSetting);
await discordSimple.WritePromptToInput(prompt);
let discordSimple = new DiscordSimple(discordW, mjSetting)
await discordSimple.WritePromptToInput(prompt)
// 发送命令完成(删除当前正在执行。开始下一个任务)
} catch (error) {
throw error;
throw error
}
}, tasK_id, batch);
},
tasK_id,
batch
)
default:
break;
break
}
}
// 判断该当前正在执行的人物队列数(小于设置的数量,开始一个任务)
this.global.mjGenerateQuene.startNextTask(mjSetting.taskCount ? mjSetting.taskCount : 3);
this.global.mjGenerateQuene.startNextTask(mjSetting.taskCount ? mjSetting.taskCount : 3)
this.global.requestQuene.setBatchCompletionCallback(batch, (failedTasks) => {
if (failedTasks.length > 0) {
@ -669,20 +706,25 @@ export class MJOriginalImageGenerate {
但是以下任务执行失败
`
failedTasks.forEach(({ taskId, error }) => {
message += `${taskId}-, \n 错误信息: ${error}` + '\n';
});
message += `${taskId}-, \n 错误信息: ${error}` + '\n'
})
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, errorMessage(message))
this.global.newWindow[0].win.webContents.send(
DEFINE_STRING.SHOW_MESSAGE_DIALOG,
errorMessage(message)
)
} else {
if (show_global_message) {
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, successMessage(null, '所有MJ生图任务完成'))
this.global.newWindow[0].win.webContents.send(
DEFINE_STRING.SHOW_MESSAGE_DIALOG,
successMessage(null, '所有MJ生图任务完成')
)
}
}
});
})
return successMessage(null)
} catch (error) {
return errorMessage("MJ生图错误错误信息如下" + error.message)
return errorMessage('MJ生图错误错误信息如下' + error.message)
}
}
}

View File

@ -1,31 +1,14 @@
import { BookType } from "../../../define/enum/bookEnum";
import { errorMessage, successMessage } from "../../generalTools";
import BooKService from "../../../define/db/service/Book/bookService";
import { BookTaskService } from "../../../define/db/service/Book/bookTaskService";
const { v4: uuidv4 } = require('uuid');
import { BookType } from '../../../define/enum/bookEnum'
import { errorMessage, successMessage } from '../../generalTools'
import { BookService } from '../../../define/db/service/Book/bookService'
import { BookTaskService } from '../../../define/db/service/Book/bookTaskService'
const { v4: uuidv4 } = require('uuid')
import { define } from '../../../define/define'
import path from 'path'
import { CheckFolderExistsOrCreate } from "../../../define/Tools/file";
import { CheckFolderExistsOrCreate } from '../../../define/Tools/file'
export class BookBasic {
constructor() {
}
/**
* 获取路径中的最后一层或两层目录
* @param {string} path 文件或目录的完整路径
* @param {number} level 需要获取的层级数1表示最后一层2表示最后两层
* @returns {string} 最后的一层或两层目录
*/
getLastPathLevels(path, level = 1) {
// 根据操作系统的不同,路径分隔符可能不同
const separator = path.includes('/') ? '/' : '\\';
const parts = path.split(separator);
// 获取最后的一层或两层目录
const lastLevels = parts.slice(-level);
// 重新组合成路径字符串
return lastLevels.join(separator);
}
constructor() {}
/**
* 新增或者是修小说数据
@ -35,29 +18,39 @@ export class BookBasic {
async AddOrModifyBook(book) {
try {
if (book == null) {
return errorMessage('小说数据为空,无法修改');
return errorMessage('小说数据为空,无法修改')
}
// 处理一下数据,处理文件地址(删除前缀,转换为默认地址)
// 当前的小说的名字是不是在数据库中以存在
let _bookService = await BooKService.getInstance();
let res = await _bookService.AddOrModifyBook(book);
return res;
let _bookService = await BookService.getInstance()
let res = await _bookService.AddOrModifyBook(book)
return res
} catch (error) {
return errorMessage('修改数据错误,错误信息如下:' + error.message, 'BookBasic_AddOrModifyBook');
return errorMessage(
'修改数据错误,错误信息如下:' + error.message,
'BookBasic_AddOrModifyBook'
)
}
}
// 小说类型返回
GetBookType() {
return successMessage([{
return successMessage(
[
{
label: 'SD反推',
value: BookType.SD_REVERSE
}, {
},
{
label: 'MJ反推',
value: BookType.MJ_REVERSE
}, {
label: "原创",
},
{
label: '原创',
value: BookType.ORIGINAL
}], '获取小说类型成功');
}
],
'获取小说类型成功'
)
}
}

View File

@ -1,49 +1,104 @@
import { successMessage, errorMessage } from "../../generalTools.js";
import { BookBasic } from "./BooKBasic.js";
import BooKService from "../../../define/db/service/Book/bookService";
import { BookTaskService } from "../../../define/db/service/Book/bookTaskService";
import { successMessage, errorMessage } from '../../generalTools.js'
import { BookBasic } from './BooKBasic.js'
import { BookService } from '../../../define/db/service/Book/bookService'
import { BookTaskService } from '../../../define/db/service/Book/bookTaskService'
import { define } from '../../../define/define.js'
import path from 'path'
import { BasicReverse } from '../../Task/basicReverse.js'
/**
* 一键反推的相关操作
*/
export class ReverseBook extends BookBasic {
constructor() {
super()
this.basicReverse = new BasicReverse()
}
//#region 小说相关操作
/**
* 获取当前的小说数据
* @param {*} bookQuery
*/
async GetBookData(bookQuery) {
try {
let _bookService = await BooKService.getInstance();
let _bookService = await BookService.getInstance()
// 添加小说
let res = await _bookService.GetBookData(bookQuery)
let res = _bookService.GetBookData(bookQuery)
if (res.code == 0) {
throw new Error(res.message)
}
return res
} catch (error) {
return errorMessage(error.message, 'ReverseBook_GetBookData');
return errorMessage(error.message, 'ReverseBook_GetBookData')
}
}
//#endregion
//#region 小说批次任务相关操作
/**
* 获取小说的任务列表
* @param {*} bookTaskCondition 查询任务列表的条件
*/
async GetBookTaskData(bookTaskCondition) {
try {
let _bookTaskService = await BookTaskService.getInstance();
let _bookTaskService = await BookTaskService.getInstance()
let res = await _bookTaskService.GetBookTaskData(bookTaskCondition)
if (res.code == 0) {
throw new Error(res.message)
}
return res;
return res
} catch (error) {
return errorMessage("获取小说对应批次错误,错误信息入校:" + error.message, 'ReverseBook_GetBookTaskData');
return errorMessage(
'获取小说对应批次错误,错误信息入校:' + error.message,
'ReverseBook_GetBookTaskData'
)
}
}
//#endregion
//#region 一键全自动
/**
* 全自动任务这边是任务入口都是在这边调用
* @param {*} value
* @returns
*/
async AutoAction(bookId) {
try {
if (bookId == null || bookId == '') {
throw new Error('bookId不能为空')
}
// 1 分镜,开始调用
let getFramRes = await this.basicReverse.GetFrameData(bookId)
if (getFramRes.code == 0) {
throw new Error(getFramRes.message)
}
// 2 截取视频
let cutVideoRes = await this.basicReverse.CutVideoData(bookId)
if (cutVideoRes.code == 0) {
throw new Error(cutVideoRes.message)
}
// 3 分离音频
let splitAudioRes = await this.basicReverse.SplitAudioData(bookId)
if (splitAudioRes.code == 0) {
throw new Error(splitAudioRes.message)
}
// 4 开始提取字幕
let extractSubtitlesRes = await this.basicReverse.ExtractSubtitlesData(bookId)
//
} catch (error) {
return errorMessage(error.message, 'ReverseBook_AutoAction')
}
}
//#endregion
}

View File

@ -1,24 +1,154 @@
import path from 'path';
import fs from 'fs';
const util = require('util');
const { exec } = require('child_process');
const execAsync = util.promisify(exec);
import { define } from '../../define/define';
import BooKService from '../../define/db/service/Book/bookService';
import { TaskScheduler } from './taskScheduler';
import { LoggerStatus, LoggerType, OtherData } from '../../define/enum/softwareEnum';
import { errorMessage } from '../generalTools';
import { CheckFileOrDirExist } from '../../define/Tools/file';
import { BookTaskDetailService } from '../../define/db/service/Book/bookTaskDetailService';
import path from 'path'
import fs from 'fs'
const util = require('util')
const { exec } = require('child_process')
const execAsync = util.promisify(exec)
import { define } from '../../define/define'
import { BookService } from '../../define/db/service/Book/bookService'
import { TaskScheduler } from './taskScheduler'
import { LoggerStatus, LoggerType, OtherData } from '../../define/enum/softwareEnum'
import { errorMessage, successMessage } from '../generalTools'
import { CheckFileOrDirExist, CheckFolderExistsOrCreate } from '../../define/Tools/file'
import { BookTaskDetailService } from '../../define/db/service/Book/bookTaskDetailService'
import { BookTaskService } from '../../define/db/service/Book/bookTaskService'
import { isEmpty, set } from 'lodash'
import ffmpeg from 'fluent-ffmpeg'
import { SetFfmpegPath } from '../setting/ffmpegSetting'
import { TimeStringToMilliseconds, MillisecondsToTimeString } from '../../define/Tools/time'
import { BookTaskStatus } from '../../define/enum/bookEnum'
SetFfmpegPath()
const fspromises = fs.promises;
const fspromises = fs.promises
// 基础的反推(抽帧,分镜,提取字幕等)
/**
* 后台执行的任务函数直接调用改函数即可抽帧分镜提取字幕等
*/
export class BasicReverse {
constructor() {
this.taskScheduler = new TaskScheduler()
}
//#region ffmpeg的一些操作
/**
* FFmpeg裁剪视频将一个视频将裁剪指定的时间内的片段
* @param {*} book 小说对象类
* @param {*} bookTask 小说批次任务对象类
* @param {*} startTime 开始时间
* @param {*} endTime 结束时间
* @param {*} videoPath 视频地址
* @param {*} outVideoFile 输出地址
* @returns
*/
async FfmpegCutVideo(book, bookTask, startTime, endTime, videoPath, outVideoFile) {
try {
// 判断视频地址是不是存在
let videoIsExist = CheckFileOrDirExist(videoPath)
if (!videoIsExist) {
throw new Error('视频地址对应的文件不存在')
}
// 判断开始时间和结束时间是不是合法
if (isEmpty(startTime) || isEmpty(endTime)) {
throw new Error('开始时间和结束时间不能为空')
}
// 判断输出文件夹是不是存在
let outputFolder = path.dirname(outVideoFile)
await CheckFolderExistsOrCreate(outputFolder)
// 将时间转换为字符串
startTimeString = MillisecondsToTimeString(startTime)
endTimeString = MillisecondsToTimeString(endTime)
// 设置视频编码器
let videoCodec = 'libx264' // 默认编码器
if (global.gpu.type === 'NVIDIA') {
videoCodec = 'h264_nvenc'
} else if (global.gpu.type === 'AMD') {
videoCodec = 'h264_amf'
}
// 判断分镜是不是和数据库中的数据匹配的上
return new Promise((resolve, reject) => {
ffmpeg(videoPath)
.setStartTime(startTimeString)
.setEndTime(endTimeString)
.videoCodec(videoCodec)
.addOption('-preset', 'fast')
.audioCodec('copy')
.output(outVideoFile)
.on('end', async function () {
let res_msg = `视频裁剪完成,输出地址:${outVideoFile}`
// 修改数据库中的输出地址
await this.taskScheduler.AddLogToDB(
book.id,
book.type,
res_msg,
OtherData.DEFAULT,
LoggerStatus.SUCCESS
)
return successMessage(null, res_msg, 'BasicReverse_FfmpegCutVideo')
})
.on('error', async function (err) {
let res_msg = `视频裁剪失败,错误信息如下:${err.toString()}`
await this.taskScheduler.AddLogToDB(
book.id,
book.type,
res_msg,
OtherData.DEFAULT,
LoggerStatus.FAIL
)
return errorMessage(res_msg, 'BasicReverse_FfmpegCutVideo')
})
.run()
})
// 开始裁剪视频
} catch (error) {
return errorMessage(
'裁剪视频失败,错误信息如下: ' + error.message,
'BasicReverse_FfmpegCutVideo'
)
}
}
/**
*
* @param {*} videoPath
* @param {*} audioPath
*/
async FfmpegExtractAudio(videoPath, outAudioPath) {
try {
// 判断视频地址是不是存在
let videoIsExist = CheckFileOrDirExist(videoPath)
if (!videoIsExist) {
throw new Error('视频地址对应的文件不存在')
}
// 开始提取音频
return new Promise((resolve, reject) => {
ffmpeg(videoPath)
.output(outAudioPath)
.audioCodec('libmp3lame')
.audioBitrate('128k')
.on('end', async function () {
let res_msg = `音频提取完成,输出地址:${outAudioPath}`
return successMessage(outAudioPath, res_msg, 'BasicReverse_FfmpegExtractAudio')
})
.on('error', async function (err) {
let res_msg = `音频提取失败,错误信息如下:${err.toString()}`
return errorMessage(res_msg, 'BasicReverse_FfmpegExtractAudio')
})
})
} catch (error) {
return errorMessage(
'提取音频失败,错误信息如下: ' + error.message,
'BasicReverse_FfmpegExtractAudio'
)
}
}
//#endregion
/**
* 分镜通过传入的bookId
* @param {*} bookId 传入的bookId
@ -26,70 +156,412 @@ export class BasicReverse {
*/
async GetFrameData(bookId) {
try {
let _bookService = await BooKService.getInstance();
let _bookTaskDetailService = await BookTaskDetailService.getInstance();
let _bookService = await BookService.getInstance()
let _bookTaskDetailService = await BookTaskDetailService.getInstance()
let _bookTaskService = await BookTaskService.getInstance()
// 获取对应的小说小说数据,找到对应的小说视频地址
let bookQuery = {
bookId: bookId
}
let bookData = await _bookService.GetBookData(bookQuery)
let bookData = _bookService.GetBookData(bookQuery)
if (bookData.code == 0) {
return bookData
}
if (bookData.data.book_length <= 0 || bookData.data.res_book.length <= 0) {
throw new Error("没有找到对应的小说数据请检查bookId是否正确")
throw new Error('没有找到对应的小说数据请检查bookId是否正确')
}
// 获取小说对应的批次任务数据,默认初始化为第一个
let bookTaskRes = await _bookTaskService.GetBookTaskData({
bookId: bookId,
name: 'output_00001'
})
if (bookTaskRes.data.bookTasks.length <= 0 || bookTaskRes.data.total <= 0) {
throw new Error('没有找到对应的小说批次任务数据请检查bookId是否正确')
}
// 获取小说的视频地址
let book = bookData.data.res_book[0]
let bookTask = bookTaskRes.data.bookTasks[0]
_bookTaskService.UpdateBookTaskStatus(bookTask.id, BookTaskStatus.STORYBOARD)
// 分镜之前,删除之前的老数据
let deleteBookTaskRes = _bookTaskDetailService.DeleteBookTaskDetail({
bookId: bookId,
bookTaskId: bookTask.id
})
let oldVideoPath = book.oldVideoPath
let frameJson = oldVideoPath + '.json'
let sensitivity = 30
// 开始之前,推送日志
let log_content = `开始进行分镜操作,视频地址:${oldVideoPath},敏感度:${sensitivity},正在调用程序进行处理`
await this.taskScheduler.AddLogToDB(bookId, book.type, log_content, OtherData.DEFAULT, LoggerStatus.DOING)
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
log_content,
OtherData.DEFAULT,
LoggerStatus.DOING
)
// 小说进行分镜python进行将结果写道一个json里面
// 使用异步的方法调用一个python程序然后写入到指定的json文件中k
let command = `"${path.join(define.scripts_path, "Lai.exe")}" "-ka" "${oldVideoPath}" "${frameJson}" "${sensitivity}"`
const output = await execAsync(command, { maxBuffer: 1024 * 1024 * 10, encoding: 'utf-8' });
let command = `"${path.join(
define.scripts_path,
'Lai.exe'
)}" "-ka" "${oldVideoPath}" "${frameJson}" "${sensitivity}"`
const output = await execAsync(command, {
maxBuffer: 1024 * 1024 * 10,
encoding: 'utf-8'
})
// 有错误输出
if (output.stderr != '') {
await this.taskScheduler.AddLogToDB(bookId, book.type, `分镜失败,错误信息如下:${output.stderr}`, OtherData.DEFAULT, LoggerStatus.FAIL)
throw new Error(output.stderr);
let error_msg = `分镜失败,错误信息如下:${output.stderr}`
_bookTaskService.UpdateBookTaskStatus(
bookTask.id,
BookTaskStatus.STORYBOARD_FAIL,
error_msg
)
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
error_msg,
OtherData.DEFAULT,
LoggerStatus.FAIL
)
throw new Error(output.stderr)
}
// 分镜成功,处理输出
let josnIsExist = CheckFileOrDirExist(frameJson)
if (!josnIsExist) {
let error_message = `分镜失败,没有找到对应的分镜输出文件:${frameJson}`
await this.taskScheduler.AddLogToDB(bookId, book.type, error_message, OtherData.DEFAULT, LoggerStatus.FAIL)
_bookTaskService.UpdateBookTaskStatus(
bookTask.id,
BookTaskStatus.STORYBOARD_FAIL,
error_message
)
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
error_message,
OtherData.DEFAULT,
LoggerStatus.FAIL
)
throw new Error(error_message)
}
let frameJsonData = JSON.parse(await fspromises.readFile(frameJson, 'utf-8'))
if (frameJsonData.length <= 0) {
await this.taskScheduler.AddLogToDB(bookId, book.type, `分镜失败,没有找到对应的分镜数据`, OtherData.DEFAULT, LoggerStatus.FAIL)
throw new Error("分镜失败,没有找到对应的分镜数据")
let error_msg = `分镜失败,没有找到对应的分镜数据`
_bookTaskService.UpdateBookTaskStatus(
bookTask.id,
BookTaskStatus.STORYBOARD_FAIL,
error_msg
)
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
error_msg,
OtherData.DEFAULT,
LoggerStatus.FAIL
)
throw new Error(error_msg)
}
// 循环写入小说人物详细数据
for (let i = 0; i < frameJsonData.length; i++) {
let frameData = frameJsonData[i]
let dataArray = frameJsonData[i]
let bookTaskDetail = {
bookId: bookId,
}
await _bookTaskDetailService.AddBookTaskDetail(frameDataQuery)
bookTaskId: bookTask.id
}
// 将字符串转换为number
bookTaskDetail.startTime = TimeStringToMilliseconds(dataArray[0])
bookTaskDetail.endTime = TimeStringToMilliseconds(dataArray[1])
console.log()
console.log(output.stdout)
let res = _bookTaskDetailService.AddBookTaskDetail(bookTaskDetail)
if (res.code == 0) {
throw new Error(res.message)
}
}
_bookTaskService.UpdateBookTaskStatus(bookTask.id, BookTaskStatus.STORYBOARD_DONE)
// 分镜成功,推送日志
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
`分镜成功,分镜数据如下:${frameJsonData}`,
OtherData.DEFAULT,
LoggerStatus.SUCCESS
)
return successMessage(null, `分镜成功,分镜信息在 ${frameJson}`, 'BasicReverse_GetFrameData')
} catch (error) {
return errorMessage(error.message, 'BasicReverse_GetFrameData');
return errorMessage(error.message, 'BasicReverse_GetFrameData')
}
}
/**
* 裁剪视频
* @param {*} bookId 小说ID
* @param {*} frameJson 存放分镜数据的json文件地址
*/
async CutVideoData(bookId) {
try {
if (isEmpty(bookId)) {
throw new Error('bookId不能为空')
}
// 判断小说是不是存在
let _bookService = await BookService.getInstance()
let _bookTaskService = await BookTaskService.getInstance()
let _bookTaskDetailService = await BookTaskDetailService.getInstance()
let book = _bookService.GetBookDataById(bookId)
if (book == null) {
throw new Error('没有找到对应的小说数据')
}
// 找到对应的小说ID和对应的小说批次任务ID判断是不是有分镜数据
let bookTaskRes = await _bookTaskService.GetBookTaskData({
bookId: bookId,
name: 'output_00001'
})
if (bookTaskRes.data.bookTasks.length <= 0 || bookTaskRes.data.total <= 0) {
throw new Error('没有找到对应的小说批次任务数据请检查bookId是否正确')
}
let bookTask = bookTaskRes.data.bookTasks[0]
let bookTaskDetail = _bookTaskDetailService.GetBookTaskData({
bookId: bookId,
bookTaskId: bookTask.id
})
if (bookTaskDetail.data.length <= 0) {
// 传入的分镜数据为空,需要重新获取
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
`没有传入分镜数据,开始调用分镜方法`,
OtherData.DEFAULT,
LoggerStatus.DOING
)
let frameRes = this.GetFrameData(bookId)
if (frameRes.code == 0) {
throw new Error((await frameRes).message)
}
}
bookTaskDetail = _bookTaskDetailService.GetBookTaskData({
bookId: bookId,
bookTaskId: bookTask.id
})
if (bookTaskDetail.data.length <= 0) {
_bookTaskService.UpdateBookTaskStatus(
bookTask.id,
BookTaskStatus.SPLIT_FAIL,
'重新调用分镜方法还是没有分镜数据,请检查'
)
throw new Error('重新调用分镜方法还是没有分镜数据,请检查')
}
_bookTaskService.UpdateBookTaskStatus(bookTask.id, BookTaskStatus.SPLIT)
// 有分镜数据,开始处理
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
`成功获取分镜数据,开始裁剪视频`,
OtherData.DEFAULT,
LoggerStatus.SUCCESS
)
for (let i = 0; i < bookTaskDetail.length; i++) {
const element = bookTaskDetail[i]
let startTime = element.startTime
let endTime = element.endTime
if (startTime == null || endTime == null) {
_bookTaskService.UpdateBookTaskStatus(
bookTask.id,
BookTaskStatus.SPLIT_FAIL,
'开始时间和结束时间不能为空'
)
throw new Error('开始时间和结束时间不能为空')
}
let outVideoFile = path.join(book.bookFolderPath, `data/frame/${element.name}.mp4`)
let res = await this.FfmpegCutVideo(
book,
startTime,
endTime,
book.oldVideoPath,
outVideoFile
)
if (res.code == 0) {
_bookTaskService.UpdateBookTaskStatus(bookTask.id, BookTaskStatus.SPLIT_FAIL, res.message)
throw new Error(res.message)
}
// 视频裁剪完成,要将裁剪后的视频地址写入到数据库中
_bookTaskDetailService.UpdateBookTaskDetail(element.id, {
videoPath: path.relative(define.project_path, outVideoFile)
})
}
// 小改小说批次的状态
_bookTaskService.UpdateBookTaskStatus(bookTask.id, BookTaskStatus.SPLIT_DONE)
// 结束,分镜完毕,推送日志,返回成功
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
`全部视频裁剪完成`,
OtherData.DEFAULT,
LoggerStatus.SUCCESS
)
return successMessage(null, '全部视频裁剪完成', 'BasicReverse_CutVideoData')
} catch (error) {
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
error.message,
OtherData.DEFAULT,
LoggerStatus.FAIL
)
return errorMessage(
'裁剪视频失败,错误信息如下: ' + error.message,
'BasicReverse_CutVideoData'
)
}
}
/**
* 分离视频片段的音频
* 当没有传入bookTaskId分离默认的第一个
* 有传入的时候分离对应的bookTaskId的数据
* @param {*} bookId
* @param {*} bookTaskId
*/
async SplitAudioData(bookId, bookTaskId = null) {
try {
let _bookService = await BookService.getInstance()
let _bookTaskService = await BookTaskService.getInstance()
let _bookTaskDetailService = await BookTaskDetailService.getInstance()
let book = _bookService.GetBookDataById(bookId)
if (book == null) {
throw new Error('没有找到对应的小说数据')
}
let bookTask
if (bookTaskId != null) {
bookTaskId = _bookTaskService.GetBookTaskData({ id: bookTaskId })
} else {
bookTask = _bookTaskService.GetBookTaskData({
bookId: bookId,
name: 'output_00001'
})
}
if (bookTask.data.bookTasks.length <= 0 || bookTask.data.total <= 0) {
throw new Error('没有找到对应的小说批次任务数据请检查bookId是否正确')
}
bookTask = bookTask.data.bookTasks[0]
// 获取对应小说批次任务的分镜信息
let bookTaskDetails = _bookTaskDetailService.GetBookTaskData({
bookId: bookId,
bookTaskId: bookTask.id
})
if (bookTaskDetails.data.length <= 0) {
throw new Error('没有找到对应的小说批次任务数据请检查bookId是否正确或者手动执行')
}
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
`开始分离音频`,
OtherData.DEFAULT,
LoggerStatus.DOING
)
_bookTaskService.UpdateBookTaskStatus(bookTask.id, BookTaskStatus.AUDIO)
for (let i = 0; i < bookTaskDetails.length; i++) {
const element = bookTaskDetails[i]
let videoPath = element.videoPath
let audioPath = path.join(book.bookFolderPath, `data/audio/${element.name}.mp3`)
await CheckFolderExistsOrCreate(path.dirname(audioPath))
// 开始分离音频
let audioRes = await this.FfmpegExtractAudio(videoPath, audioPath)
if (audioRes.code == 0) {
let errorMessage = `分离音频失败,错误信息如下:${audioRes.message}`
_bookTaskService.UpdateBookTaskStatus(
bookTask.id,
BookTaskStatus.AUDIO_FAIL,
errorMessage
)
throw new Error(audioRes.message)
}
_bookTaskDetailService.UpdateBookTaskDetail(element.id, {
audioPath: path.relative(define.project_path, audioPath)
})
// 推送成功消息
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
`${element.name}分离音频成功,输出地址:${audioPath}`,
OtherData.DEFAULT,
LoggerStatus.SUCCESS
)
}
// 修改状态为分离音频成功
_bookTaskService.UpdateBookTaskStatus(bookTask.id, BookTaskStatus.AUDIO_DONE)
// 所有音频分离成功,推送日志
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
`${element.name}分离音频成功,输出地址:${audioPath}`,
OtherData.DEFAULT,
LoggerStatus.SUCCESS
)
return successMessage(null, '所有音频分离成功', 'BasicReverse_SplitAudioData')
} catch (error) {
let errorMessage = `分离音频失败,错误信息如下:${error.message}`
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
errorMessage,
OtherData.DEFAULT,
LoggerStatus.FAIL
)
return errorMessage(errorMessage, 'BasicReverse_SplitAudioData')
}
}
/**
* 提取字幕
* @param {*} bookId
* @param {*} bookTaskId
* @returns
*/
async ExtractSubtitlesData(bookId, bookTaskId = null) {
try {
} catch (error) {
let errorMessage = `提取字幕失败,错误信息如下:${error.message}`
await this.taskScheduler.AddLogToDB(
bookId,
book.type,
errorMessage,
OtherData.DEFAULT,
LoggerStatus.FAIL
)
return errorMessage(errorMessage, 'BasicReverse_ExtractSubtitlesData')
}
}
}

214
src/main/Task/taskManage.js Normal file
View File

@ -0,0 +1,214 @@
import { BookBackTaskListService } from '../../define/db/service/Book/bookBackTaskListService'
import { BookService } from '../../define/db/service/Book/bookService'
import { BookTaskDetailService } from '../../define/db/service/Book/bookTaskDetailService'
import { BookTaskService } from '../../define/db/service/Book/bookTaskService'
import { OtherData } from '../../define/enum/softwareEnum'
import { BookBackTaskStatus } from '../../define/enum/bookEnum'
class TaskManager {
constructor() {}
/**
* 创建新任务到数据库
* 需要传递 小说ID小说任务ID小说任务分镜ID
* 判断是不是有相同的任务在执行如果有则不创建新任务
* 小说任务ID为null所有相关的数据就是default
* 小说任务分镜ID为null所有相关的数据就是default
* @param {*} bookId 小说ID 必传
* @param {*} taskType 任务类型 必传
* @param {*} bookTaskId 小说任务ID 可为null
* @param {*} bookTaskDetailId 小说任务分镜ID 可为null
* @returns
*/
async AddTask(bookId, taskType, bookTaskId = null, bookTaskDetailId = null) {
try {
// 开始创建任务
let _bookBackTaskListService = await BookBackTaskListService.getInstance()
let _bookService = await BookService.getInstance()
let _bookTaskService = await BookTaskService.getInstance()
let _bookTaskDetailService = await BookTaskDetailService.getInstance()
// 获取小说信息
let book = _bookService.GetBookDataById(bookId)
if (book == null) {
throw new Error('小说信息不存在,添加任务失败')
}
// 有传入小说批次任务ID要检查数据是不是存在
let bookTask = null
if (bookTaskId != null) {
let bookTaskRes = _bookTaskService.GetBookTaskDataById(bookTaskId)
if (bookTaskRes.data == null) {
throw new Error('小说批次任务信息不存在,添加任务失败')
}
bookTask = bookTaskRes.data
}
let bookTaskDetail = null
if (bookTaskDetailId != null) {
let bookTaskDetailRes = _bookTaskDetailService.GetBookTaskDetailDataById(bookTaskDetailId)
if (bookTaskDetailRes.data == null) {
throw new Error('小说任务分镜信息不存在,添加任务失败')
}
bookTaskDetail = bookTaskDetailRes.data
}
// 开始往数据库中添加任务
let name = `${book.name}-${bookTask ? bookTask.name : 'default'}-${
bookTaskDetail ? bookTaskDetail.name : 'default'
}-${taskType}`
let addBookBackTaskListRes = _bookBackTaskListService.AddBookBackTaskList({
bookId: bookId,
bookTaskId: bookTaskId ? bookTaskId : OtherData.DEFAULT,
name: name,
type: taskType,
status: BookBackTaskStatus.WAIT
})
if (addBookBackTaskListRes.code == 1) {
return addBookBackTaskListRes
} else {
throw new Error('添加任务失败')
}
} catch (error) {
throw error
}
}
/**
* 获取指定小说和小说批次任务中等待中的任务
* @param {*} bookId
* @param {*} bookTaskId
*/
async GetWaitTask(bookId, bookTaskId = null) {
try {
if (bookId == null) {
throw new Error('bookId不能为空')
}
let query = {
bookId: bookId,
status: BookBackTaskStatus.WAIT
}
if (bookTaskId != null) {
query.bookTaskId = bookTaskId
}
let _bookBackTaskListService = await BookBackTaskListService.getInstance()
} catch (error) {
throw error
}
}
updateTaskStatus(taskId, batchId, subBatchId, status) {
return new Promise((resolve, reject) => {
this.db.run(
`UPDATE tasks SET status = ?, updatedAt = datetime('now')
WHERE taskId = ? AND batchId = ? AND subBatchId = ?`,
[status, taskId, batchId, subBatchId],
function (err) {
if (err) {
reject(err)
} else {
resolve()
}
}
)
})
}
deleteTask(taskId, batchId, subBatchId) {
return new Promise((resolve, reject) => {
this.db.run(
`DELETE FROM tasks WHERE taskId = ? AND batchId = ? AND subBatchId = ?`,
[taskId, batchId, subBatchId],
function (err) {
if (err) {
reject(err)
} else {
resolve()
}
}
)
})
}
getAllTasks() {
return new Promise((resolve, reject) => {
this.db.all(`SELECT * FROM tasks`, [], (err, rows) => {
if (err) {
reject(err)
} else {
resolve(rows)
}
})
})
}
}
class TaskExecutor {
constructor(taskManager) {
this.taskManager = taskManager
this.isExecuting = false
}
async executePendingTasks() {
if (this.isExecuting) {
console.log('任务正在执行,跳过此次执行')
return
}
this.isExecuting = true
try {
const tasks = await this.taskManager.getAllTasks()
for (const task of tasks) {
if (task.status === 'pending') {
console.log(`Executing task: ${task.taskId}`)
await this.handleTask(task)
await this.taskManager.updateTaskStatus(
task.taskId,
task.batchId,
task.subBatchId,
'completed'
)
}
}
} catch (err) {
console.error('Error executing tasks:', err)
} finally {
this.isExecuting = false
}
}
async handleTask(task) {
if (task.taskId === 'specificTask') {
console.log(`Handling specific task: ${task.taskId}`)
// 执行任务的具体逻辑
} else {
console.log(`Handling general task: ${task.taskId}`)
// 执行任务的具体逻辑
}
}
}
const taskManager = new TaskManager()
const taskExecutor = new TaskExecutor(taskManager)
// 每分钟检查并执行一次任务
setInterval(() => {
taskExecutor.executePendingTasks().catch(console.error)
}, 60 * 1000)
// 示例:创建任务并触发执行
taskManager
.createTask('task1', 'batch1', 'subBatch1')
.then((taskId) => {
if (taskId) {
console.log('Task created with ID:', taskId)
} else {
console.log('没有创建新任务')
}
})
.catch((err) => console.error(err))

View File

@ -0,0 +1,21 @@
import path from 'path'
import os from 'os'
import ffmpeg from 'fluent-ffmpeg'
import { define } from '../../define/define'
export function SetFfmpegPath() {
let ffmpegPath
let ffprobePath
switch (os.platform()) {
case 'win32':
// Windows
ffmpegPath = path.join(define.package_path, 'ffmpeg/win/ffmpeg.exe')
ffprobePath = path.join(define.package_path, 'ffmpeg/win/ffprobe.exe')
break
default:
throw new Error('Unsupported platform: ' + os.platform())
}
ffmpeg.setFfmpegPath(ffmpegPath)
ffmpeg.setFfprobePath(ffprobePath)
}

View File

@ -1,11 +1,12 @@
import axios from 'axios';
import axios from 'axios'
import { MJSettingService } from '../../define/db/service/SoftWare/mjSettingService'
import { define } from '../../define/define';
import { errorMessage, successMessage } from '../generalTools';
import { define } from '../../define/define'
import { errorMessage, successMessage } from '../generalTools'
import { isEmpty } from 'lodash'
const { v4: uuidv4 } = require('uuid')
export class MJSetting {
constructor() {
}
constructor() {}
/**
* 获取MJ的基础设置数据
@ -13,10 +14,13 @@ export class MJSetting {
async GetMJSetting(mjSettingQuery) {
try {
let _mjSetting = await MJSettingService.getInstance()
let res = _mjSetting.GetMjSetting(mjSettingQuery);
let res = _mjSetting.GetMjSetting(mjSettingQuery)
return res
} catch (error) {
return errorMessage("获取MJ的基础配置错误错误信息如下" + error.toString(), "MJSetting_GetMJSetting");
return errorMessage(
'获取MJ的基础配置错误错误信息如下' + error.toString(),
'MJSetting_GetMJSetting'
)
}
}
@ -27,11 +31,13 @@ export class MJSetting {
async UpdateMJSetting(mjSetting) {
try {
let _mjSetting = await MJSettingService.getInstance()
let res = _mjSetting.UpdateMJSetting(mjSetting);
let res = _mjSetting.UpdateMJSetting(mjSetting)
return res
} catch (error) {
return errorMessage("保存MJ的基础配置错误错误信息如下" + error.toString(), "MJSetting_UpdateMJSetting");
return errorMessage(
'保存MJ的基础配置错误错误信息如下' + error.toString(),
'MJSetting_UpdateMJSetting'
)
}
}
@ -41,10 +47,13 @@ export class MJSetting {
async GetMJSettingTreeData() {
try {
let _mjSetting = await MJSettingService.getInstance()
let res = _mjSetting.GetMJSettingTreeData();
let res = _mjSetting.GetMJSettingTreeData()
return res
} catch (error) {
return errorMessage("获取MJ配置错误详细错误信息如下" + error.toString(), 'MJSetting_GetMJSettingTreeData');
return errorMessage(
'获取MJ配置错误详细错误信息如下' + error.toString(),
'MJSetting_GetMJSettingTreeData'
)
}
}
@ -55,101 +64,226 @@ export class MJSetting {
async SaveMJSettingTreeData(mjSetting) {
try {
let _mjSetting = await MJSettingService.getInstance()
let res = _mjSetting.SaveMJSettingTreeData(mjSetting);
let res = _mjSetting.SaveMJSettingTreeData(mjSetting)
return res
} catch (error) {
return errorMessage("保存MJ配置错误详细错误信息如下" + error.toString(), 'MJSetting_SaveMJSettingTreeData');
return errorMessage(
'保存MJ配置错误详细错误信息如下' + error.toString(),
'MJSetting_SaveMJSettingTreeData'
)
}
}
/**
* 同步MJ代理模式账号信息
* @param {*} value
* @returns
*/
async MjRemoteAccountSync() {
try {
// 获取账号数据
let _mjSettingService = await MJSettingService.getInstance()
let remoteMjSettings = _mjSettingService.GetRemoteMJSettings(null);
if (remoteMjSettings.data.length <= 0) {
throw new Error("没有找到保存的数据,请先保存")
}
let remoteMjSetting = remoteMjSettings.data[0]
// 判断是不是同步过就是有没有accountId
// 判断有没有accountId
if (remoteMjSetting.accountId) {
// 查找是不是有
let accountRes = await axios.get(define.remotemj_api + `mj/account/${remoteMjSetting.accountId}/fetch`, {
headers: {
"mj-api-secret": define.API
/**
* 获取所有的MJ代理模式账号信息
*/
async GetRemoteMJSettings() {
try {
let _mjSetting = await MJSettingService.getInstance()
let res = _mjSetting.GetRemoteMJSettings(null)
return res
} catch (error) {
return errorMessage(
'获取MJ代理模式账号信息错误详细错误信息如下' + error.toString(),
'MJSetting_GetRemoteMJSettings'
)
}
});
console.log(accountRes)
// 没有找到账号信息,重新添加
if (accountRes.status == 200 && accountRes.data == "") {
}
/**
* 创建新的代理MJ信息
* @param {*} value
*/
async AddRemoteMJSetting(value) {
try {
// 先检查必填字段
console.log(value)
if (isEmpty(value.channelId) || isEmpty(value.guildId) || isEmpty(value.userToken)) {
throw new Error('必填字段服务器ID频道ID用户token不能为空')
}
if (value.coreSize == null || value.queueSize == null || value.timeoutMinutes == null) {
throw new Error('必填字段核心线程数,队列大小,超时时间不能为空')
}
if (!value.userAgent) {
value.userAgent =
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
}
// 开始调用创建任务
let createUrl = define.remotemj_api + 'mj/account/create'
// 上面是必传的
let remoteData = {
channelId: value.channelId,
guildId: value.guildId,
userToken: value.userToken,
coreSize: value.coreSize,
queueSize: value.queueSize,
timeoutMinutes: value.timeoutMinutes,
userAgent: value.userAgent
? value.userAgent
: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
remark: global.machineId,
remixAutoSubmit: false
}
// 额外添加
if (value.mjBotChannelId) {
remoteData.mjBotChannelId = value.mjBotChannelId
}
if (value.nijiBotChannelId) {
remoteData.nijiBotChannelId = value.nijiBotChannelId
}
// 添加账号
// 找不到的话,直接添加账号
let accountRes = await axios.post(define.remotemj_api + `mj/account/create`, remoteMjSetting, {
let accountRes = await axios.post(createUrl, remoteData, {
headers: {
"mj-api-secret": define.API
'mj-api-secret': define.API
}
});
console.log(accountRes);
})
console.log(accountRes)
if (accountRes.data.code != 1) {
throw new Error(accountRes.data.description);
throw new Error(accountRes.data.description)
}
// 添加成功,修改数据,将数据返回
let accountId = accountRes.data.result;
remoteMjSetting.accountId = accountId;
let save_res = _mjSettingService.UpdateRemoteMjSetting(remoteMjSetting);
// 添加成功,修改数据,将数据返回 (服务器添加成功,开始在本地数据库添加)s
let accountId = accountRes.data.result
remoteData.accountId = accountId
remoteData.remixAutoSubmit = false
let _mjSettingService = await MJSettingService.getInstance()
let save_res = _mjSettingService.AddRemoteMjSetting(remoteData)
if (save_res.code != 1) {
throw new Error(save_res.message)
}
return successMessage(remoteMjSetting, "MJ新增账号同步成功", "MJSetting_MjRemoteAccountSync")
} else {
// 能找到的话,要更新一下账号信息,并重连
remoteMjSetting["weight"] = 1
let accountRes = await axios.put(define.remotemj_api + `mj/account/${remoteMjSetting.accountId}/update-reconnect`, remoteMjSetting, {
headers: {
"mj-api-secret": define.API
return successMessage(remoteData, 'MJ账号同步成功', 'MJSetting_AddRemoteMJSetting')
} catch (error) {
return errorMessage(
'创建新的代理MJ信息错误详细错误信息如下' + error.toString(),
'MJSetting_AddRemoteMJSetting'
)
}
});
console.log(accountRes)
if (accountRes.data.code == 0) {
}
/**
* 修改MJ的账号信息并重连
* @param {*} value
*/
async UpdateRemoteMJSetting(value) {
try {
// 先检查必填字段
console.log(value)
if (isEmpty(value.accountId)) {
throw new Error('修改不能没有账号实例ID')
}
if (isEmpty(value.channelId) || isEmpty(value.guildId) || isEmpty(value.userToken)) {
throw new Error('必填字段服务器ID频道ID用户token不能为空')
}
if (value.coreSize == null || value.queueSize == null || value.timeoutMinutes == null) {
throw new Error('必填字段核心线程数,队列大小,超时时间不能为空')
}
if (!value.userAgent) {
value.userAgent =
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
}
// 开始调用更新重连任务
let updateUrl = define.remotemj_api + `mj/account/${value.accountId}/update-reconnect`
// 开始修改
let remoteData = {
channelId: value.channelId,
coreSize: value.coreSize,
enable: value.enable,
guildId: value.guildId,
id: value.accountId,
mjBotChannelId: value.mjBotChannelId ? value.mjBotChannelId : '',
nijiBotChannelId: value.nijiBotChannelId ? value.nijiBotChannelId : '',
queueSize: value.queueSize,
remark: global.machineId,
remixAutoSubmit: false,
timeoutMinutes: value.timeoutMinutes ? value.timeoutMinutes : 10,
userAgent: value.userAgent,
userToken: value.userToken,
weight: 1
}
let accountRes = await axios.put(updateUrl, remoteData, {
headers: {
'mj-api-secret': define.API
}
})
if (accountRes.data.code != 1) {
throw new Error(accountRes.description)
}
return successMessage(remoteMjSetting, "MJ账号同步成功", "MJSetting_MjRemoteAccountSync")
}
} else {
// 没有accountId直接添加
// 添加账号
let accountRes = await axios.post(define.remotemj_api + `mj/account/create`, remoteMjSetting, {
headers: {
"mj-api-secret": define.API
}
});
console.log(accountRes);
if (accountRes.data.code != 1) {
throw new Error(accountRes.data.description);
}
// 更新成功,修改数据
remoteData.accountId = value.accountId
remoteData.id = value.id
// 添加成功,修改数据,将数据返回
let accountId = accountRes.data.result;
remoteMjSetting.accountId = accountId;
let save_res = _mjSettingService.UpdateRemoteMjSetting(remoteMjSetting);
if (save_res.code != 1) {
// 同步成功,修改数据
let _mjSettingService = await MJSettingService.getInstance()
let save_res = _mjSettingService.UpdateRemoteMjSetting(remoteData)
if (save_res.code == 0) {
throw new Error(save_res.message)
}
return successMessage(remoteMjSetting, "MJ账号同步成功", "MJSetting_MjRemoteAccountSync")
}
return successMessage(remoteData, 'MJ账号修改并同步成功', 'MJSetting_UpdateRemoteMJSetting')
} catch (error) {
return errorMessage("MJ代理模式账号同步错误详细错误信息如下" + error.toString(), 'MJSetting_MjRemoteAccountSync');
return errorMessage(
'修改MJ的账号信息错误详细错误信息如下' + error.toString(),
'MJSetting_UpdateRemoteMJSetting'
)
}
}
/**
* 删除指定的MJ账号
* @param {*} id 数据库中存放的ID
*/
async DeleteRemoteMJSetting(id) {
try {
// 先检查必填字段
if (isEmpty(id)) {
throw new Error('无法删除没有ID的数据')
}
// 先获取数据
let _mjSetting = await MJSettingService.getInstance()
let deleteConfig = _mjSetting.GetRemoteMJSettings({ id: id })
if (deleteConfig.data.length <= 0) {
throw new Error('没有要删除的数据')
}
// 开始删除
let deleteData = deleteConfig.data[0]
let deleteUrl = define.remotemj_api + `mj/account/${deleteData.accountId}/delete`
let accountRes = await axios.delete(deleteUrl, {
headers: {
'mj-api-secret': define.API
}
})
if (accountRes.data.code != 1) {
throw new Error(accountRes.data.description)
}
// 删除成功,修改数据
let save_res = _mjSetting.DeleteRemoteMJSetting(id)
if (save_res.code == 0) {
throw new Error(save_res.message)
}
return successMessage(deleteData, 'MJ账号删除成功', 'MJSetting_DeleteRemoteMJSetting')
} catch (error) {
return errorMessage(
'删除指定的MJ账号错误详细错误信息如下' + error.toString(),
'MJSetting_DeleteRemoteMJSetting'
)
}
}
}

View File

@ -20,6 +20,9 @@ const book = {
// 获取小说的分镜
GetFrameData: async (bookId) => await ipcRenderer.invoke(DEFINE_STRING.BOOK.GET_FRAME_DATA, bookId),
// 一键全自动执行
AutoAction: async (bookId) => await ipcRenderer.invoke(DEFINE_STRING.BOOK.AUTO_ACTION, bookId),
//#endregion
}

View File

@ -1,45 +1,66 @@
import { ipcRenderer } from "electron"
import { DEFINE_STRING } from "../define/define_string"
import { ipcRenderer } from 'electron'
import { DEFINE_STRING } from '../define/define_string'
const setting = {
// 获取动态配置的的指定主分类指定的属性的数据只是获取动态的type定死了dynamic
GetDataByTypeAndProperty: async (value, callback) => callback(await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_DATA_BY_TYPE_AND_PROPERTY, value)),
GetDataByTypeAndProperty: async (value, callback) =>
callback(await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_DATA_BY_TYPE_AND_PROPERTY, value)),
// 保存动态配置的的指定主分类,指定的属性的数据
SaveDataByTypeAndProperty: async (value, callback) => callback(await ipcRenderer.invoke(DEFINE_STRING.SETTING.SAVE_DATA_BY_TYPE_AND_PROPERTY, value)),
SaveDataByTypeAndProperty: async (value, callback) =>
callback(await ipcRenderer.invoke(DEFINE_STRING.SETTING.SAVE_DATA_BY_TYPE_AND_PROPERTY, value)),
// 删除动态配置的的指定主分类,指定的属性的数据
DeleteDataByTypeAndProperty: async (value, callback) => callback(await ipcRenderer.invoke(DEFINE_STRING.SETTING.DELETE_DATA_BY_TYPE_AND_PROPERTY, value)),
DeleteDataByTypeAndProperty: async (value, callback) =>
callback(
await ipcRenderer.invoke(DEFINE_STRING.SETTING.DELETE_DATA_BY_TYPE_AND_PROPERTY, value)
),
// 返回组件尺寸的大小的数据(通用)
GetComponentSize: async () => await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_COMPONENT_SIZE),
// 获取软件的基础设置(初始的时候执行一次)
GetSoftwareSetting: async () => await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_SOFTWARE_SETTING),
GetSoftwareSetting: async () =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_SOFTWARE_SETTING),
// 保存软件的基础设置
SaveSoftWareSetting: async (value) => await ipcRenderer.invoke(DEFINE_STRING.SETTING.SAVE_SOFT_WARE_SETTING, value),
SaveSoftWareSetting: async (value) =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.SAVE_SOFT_WARE_SETTING, value),
//#region MJ的设置
// 获取MJ的基础设置数据
GetMjSetting: async (value = null) => await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_MJ_SETTING, value),
GetMjSetting: async (value = null) =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_MJ_SETTING, value),
// 保存MJ的基础设置
UpdateMJSetting: async (value) => await ipcRenderer.invoke(DEFINE_STRING.SETTING.UPDATE_MJ_SETTING, value),
UpdateMJSetting: async (value) =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.UPDATE_MJ_SETTING, value),
// 获取MJ的所有设置
GetMJSettingTreeData: async () => await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_MJ_SETTING_TREE_DATA),
GetMJSettingTreeData: async () =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_MJ_SETTING_TREE_DATA),
// 保存MJ的所有设置
SaveMJSettingTreeData: async (value) => await ipcRenderer.invoke(DEFINE_STRING.SETTING.SAVE_MJ_SETTING_TREE_DATA, value),
SaveMJSettingTreeData: async (value) =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.SAVE_MJ_SETTING_TREE_DATA, value),
// MJ代理模式账号同步
MjRemoteAccountSync: async () => await ipcRenderer.invoke(DEFINE_STRING.SETTING.MJ_REMOTE_ACCOUNT_SYNC),
// 获取所有的代理MJ的账号
GetRemoteMJSettings: async () =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS),
// 添加代理模式的MJ账号
AddRemoteMJSetting: async (value) =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.ADD_REMOTE_MJ_SETTING, value),
// 修改并重连MJ的账号
UpdateRemoteMJSetting: async (value) =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.UPDATE_REMOTE_MJ_SETTING, value),
// 删除指定的MJ账号
DeleteRemoteMJSetting: async (value) =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.DELETE_REMOTE_MJ_SETTING, value)
//#endregion
}
export {
setting
}
export { setting }

View File

@ -48,7 +48,6 @@ export default defineComponent({
if (software.data == null) {
throw new Error('初始化信息错误: 未获取到数据')
}
debugger
if (software.data.length == 0) {
throw new Error('初始化信息错误: 未获取到数据')
}

View File

@ -316,21 +316,21 @@ export default defineComponent({
}
]
},
// {
// label: () =>
// h(
// RouterLink,
// {
// to: {
// name: 'reverse_management'
// }
// },
// {
// default: () => ''
// }
// ),
// key: 'reverse_management'
// },
{
label: () =>
h(
RouterLink,
{
to: {
name: 'reverse_management'
}
},
{
default: () => '一键反推'
}
),
key: 'reverse_management'
},
// {
// label: "",
// key: "clip_options",

View File

@ -0,0 +1,196 @@
<template>
<div id="AddMultiRemoteMj" style="overflow-y: auto">
<div style="margin-bottom: 5px">
<n-button type="info" @click="ManageAccount(null)">新增账号</n-button>
</div>
<n-data-table :data="remoteMjSetting" :columns="columns" :max-height="maxHeight">
</n-data-table>
</div>
</template>
<script>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch, h } from 'vue'
import {
useMessage,
NDataTable,
NButton,
NInput,
NInputNumber,
NForm,
NFormItem,
useDialog,
NTag
} from 'naive-ui'
import { useSettingStore } from '../../../../../stores/setting'
import ManageRemoteMjAccount from './ManageRemoteMjAccount.vue'
import { isEmpty } from 'lodash'
export default defineComponent({
components: {
NDataTable,
NButton,
NInput,
NInputNumber,
NForm,
NFormItem,
NTag
},
props: ['height'],
setup(props) {
let message = useMessage()
let dialog = useDialog()
let maxHeight = ref(props.height - 150)
let remoteMjSetting = ref([])
let settingStore = useSettingStore()
onMounted(async () => {
document.getElementById('AddMultiRemoteMj').style.height = props.height - 60 + 'px'
debugger
let remoteMjSettingRes = await window.setting.GetRemoteMJSettings()
if (remoteMjSettingRes.code == 0) {
message.error('获取代理MJ配置失败')
} else {
remoteMjSetting.value = remoteMjSettingRes.data
}
})
/**
* 添加和编辑账号
*/
async function ManageAccount(remote = null) {
debugger
if (remote == null) {
settingStore.ResetActionRemoteMJ()
} else {
//
settingStore.actionRemoteMJ = remote
}
//
let dW = 800
let dH = 600
dialog.create({
showIcon: false,
title: '添加MJ账号',
content: () => h(ManageRemoteMjAccount, {}),
style: `min-width : 600px; width : ${dW}px; height : ${dH}px; padding-right : 5px;`,
maskClosable: false,
onClose: async () => {
//
let remoteMjSettingRes = await window.setting.GetRemoteMJSettings()
if (remoteMjSettingRes.code == 0) {
message.error('获取代理MJ配置失败')
} else {
remoteMjSetting.value = remoteMjSettingRes.data
}
settingStore.ResetActionRemoteMJ()
}
})
}
/**
* 删除指定的账号
* @param row 数据
*/
async function DeleteAccount(row) {
dialog.warning({
title: '删除账号',
content: '确定删除该账号吗?',
positiveText: '确认',
negativeText: '取消',
onPositiveClick: async () => {
if (isEmpty(row.accountId)) {
message.error('删除账号失败,错误消息如下:' + '账号ID为空')
return
}
let deleteRes = await window.setting.DeleteRemoteMJSetting(row.id)
if (deleteRes.code == 0) {
message.error('删除账号失败,错误消息如下:' + deleteRes.message)
return
}
message.success('删除账号成功')
//
let remoteMjSettingRes = await window.setting.GetRemoteMJSettings()
if (remoteMjSettingRes.code == 0) {
message.error('获取代理MJ配置失败')
} else {
remoteMjSetting.value = remoteMjSettingRes.data
}
}
})
}
return {
remoteMjSetting,
maxHeight,
ManageAccount,
settingStore,
columns: [
{
title: '服务器ID',
key: 'guildId'
},
{
title: '频道ID',
key: 'channelId'
},
{
title: '状态',
key: 'enable',
render(row) {
return h(
NTag,
{
style: {
marginRight: '6px'
},
type: (() => (row.enable ? 'success' : 'error'))(),
bordered: false
},
{
default: () => (row.enable ? '启用' : '禁用')
}
)
}
},
{
title: 'MJ私信ID',
key: 'mjBotChannelId'
},
{
title: 'NIJI私信ID',
key: 'nijiBotChannelId'
},
{
title: '操作',
key: 'action',
render(row) {
return h('div', {}, [
h(
NButton,
{
size: 'small',
type: 'info',
style: 'margin-left: 5px',
onClick: () => ManageAccount(row)
},
{ default: () => '编辑并同步' }
),
h(
NButton,
{
size: 'small',
type: 'error',
style: 'margin-left: 5px',
onClick: () => DeleteAccount(row)
},
{ default: () => '删除账号' }
)
])
}
}
]
}
}
})
</script>

View File

@ -0,0 +1,175 @@
<template>
<div style="margin-top: 20px; margin-left: 20px">
<n-form ref="addRef" :model="settingStore.actionRemoteMJ" :rules="rules">
<div style="display: flex">
<div style="margin-top: 10px; flex: 1">
<n-form-item label="服务器ID" style="width: 200px; margin-left: 5px" path="guildId">
<n-input
v-model:value="settingStore.actionRemoteMJ.guildId"
placeholder="请填写服务器ID"
/>
</n-form-item>
<n-form-item label="频道ID" style="width: 200px; margin-left: 10px" path="channelId">
<n-input
v-model:value="settingStore.actionRemoteMJ.channelId"
placeholder="请填写频道ID"
/>
</n-form-item>
<n-form-item
label="MJ私信ID"
style="width: 200px; margin-left: 10px"
path="mjBotChannelId"
>
<n-input
v-model:value="settingStore.actionRemoteMJ.mjBotChannelId"
placeholder="请填写MJ私信ID"
/>
</n-form-item>
<n-form-item
label="Niji私信ID"
style="width: 200px; margin-left: 10px"
path="nijiBotChannelId"
>
<n-input
v-model:value="settingStore.actionRemoteMJ.nijiBotChannelId"
placeholder="请填写NIJI私信ID"
/>
</n-form-item>
<n-form-item label="用户token" style="width: 240px; margin-left: 10px" path="userToken">
<n-input
v-model:value="settingStore.actionRemoteMJ.userToken"
placeholder="请填写MJtoken"
/>
</n-form-item>
<n-form-item label="用户Agent" style="width: 250px; margin-left: 10px" path="userAgent">
<n-input
v-model:value="settingStore.actionRemoteMJ.userAgent"
placeholder="请填写用户Agent"
/>
</n-form-item>
</div>
<div style="margin-top: 10px; flex: 1">
<n-form-item label="账号并发数" style="width: 100px; margin-left: 10px" path="coreSize">
<n-input-number
v-model:value="settingStore.actionRemoteMJ.coreSize"
:show-button="false"
placeholder="请填写账号并发数"
:min="1"
:max="20"
></n-input-number>
</n-form-item>
<n-form-item label="等待队列" style="width: 100px; margin-left: 10px" path="queueSize">
<n-input-number
v-model:value="settingStore.actionRemoteMJ.queueSize"
:show-button="false"
placeholder="请填写等待队列数量"
:min="1"
:max="20"
></n-input-number>
</n-form-item>
<n-form-item
label="任务超时时间"
style="width: 100px; margin-left: 10px"
path="timeoutMinutes"
>
<n-input-number
v-model:value="settingStore.actionRemoteMJ.timeoutMinutes"
:show-button="false"
placeholder="请填写任务超时时间"
:min="1"
:max="20"
></n-input-number>
</n-form-item>
<n-form-item
v-if="settingStore.actionRemoteMJ.accountId != null"
label="账号状态"
style="width: 100px; margin-left: 10px"
path="enable"
>
<n-switch v-model:value="settingStore.actionRemoteMJ.enable">
<template #checked> 启用 </template>
<template #unchecked> 禁用 </template>
</n-switch>
</n-form-item>
<n-form-item style="margin-left: 10px">
<n-button type="info" @click="CreateAccount" :loading="loading">{{
settingStore.actionRemoteMJ.accountId ? '修改并重连' : '创建账号'
}}</n-button>
</n-form-item>
</div>
</div>
</n-form>
</div>
</template>
<script>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch } from 'vue'
import { useMessage, NForm, NFormItem, NInput, NInputNumber, NButton, NSwitch } from 'naive-ui'
import { useSettingStore } from '../../../../../stores/setting'
export default defineComponent({
components: {
NForm,
NFormItem,
NInput,
NInputNumber,
NButton,
NSwitch
},
setup() {
let message = useMessage()
debugger
let settingStore = useSettingStore()
let addRef = ref(null)
let loading = ref(false)
onMounted(async () => {
debugger
console.log(settingStore)
})
let rules = {
guildId: [{ required: true, message: '请输入服务器ID', trigger: 'blur' }],
channelId: [{ required: true, message: '请输入频道ID', trigger: 'blur' }],
userToken: [{ required: true, message: '请输入用户token', trigger: 'blur' }]
}
/**
* 创建账号
*/
async function CreateAccount(e) {
debugger
e.preventDefault()
addRef.value?.validate(async (errors) => {
if (errors) {
message.error('请检查必填字段')
return
}
loading.value = true
//
if (settingStore.actionRemoteMJ.accountId) {
//
let res = await window.setting.UpdateRemoteMJSetting(toRaw(settingStore.actionRemoteMJ))
loading.value = false
if (res.code == 0) {
message.error('更新账号失败,错误消息如下:' + res.message)
return
}
message.success('更新账号成功')
} else {
//
let res = await window.setting.AddRemoteMJSetting(toRaw(settingStore.actionRemoteMJ))
loading.value = false
if (res.code == 0) {
message.error('创建账号失败,错误消息如下:' + res.message)
return
}
message.success('创建账号成功')
settingStore.ResetActionRemoteMJ()
}
})
}
return { settingStore, rules, CreateAccount, addRef, loading }
}
})
</script>

View File

@ -1,5 +1,4 @@
<template>
<n-spin :show="show" size="large">
<div style="overflow: auto; height: 100%">
<n-card title="基础设置" size="medium" hoverable style="min-width: 850px">
<n-form :model="mjSetting" ref="sampleRef" :rules="sampleRules">
@ -22,11 +21,7 @@
@update:value="UpdateSelectRobot"
></n-select>
</n-form-item>
<n-form-item
label="机器人模型"
style="width: 120px; margin-left: 10px"
path="imageModel"
>
<n-form-item label="机器人模型" style="width: 120px; margin-left: 10px" path="imageModel">
<n-select
placeholder="请选择机器人模型"
:options="image_model_options"
@ -40,18 +35,10 @@
v-model:value="mjSetting.imageScale"
></n-select>
</n-form-item>
<n-form-item
label="命令后缀"
style="width: 160px; margin-left: 10px"
path="image_suffix"
>
<n-form-item label="命令后缀" style="width: 160px; margin-left: 10px" path="image_suffix">
<n-input v-model:value="image_suffix" placeholder="请输入后缀命令"></n-input>
</n-form-item>
<n-form-item
label="生图任务量"
style="width: 100px; margin-left: 10px"
path="taskCount"
>
<n-form-item label="生图任务量" style="width: 100px; margin-left: 10px" path="taskCount">
<n-input-number
v-model:value="mjSetting.taskCount"
:show-button="false"
@ -60,11 +47,7 @@
:max="20"
></n-input-number>
</n-form-item>
<n-form-item
label="间隔时间(s)"
style="width: 100px; margin-left: 10px"
path="spaceTime"
>
<n-form-item label="间隔时间(s)" style="width: 100px; margin-left: 10px" path="spaceTime">
<n-input-number
v-model:value="mjSetting.spaceTime"
:show-button="false"
@ -76,12 +59,7 @@
</div>
</n-form>
</n-card>
<n-card
title="API模式设置"
hoverable
style="margin-top: 10px; min-width: 850px"
size="medium"
>
<n-card title="API模式设置" hoverable style="margin-top: 10px; min-width: 850px" size="medium">
<n-form :model="mjSetting.apiSetting">
<div style="display: flex">
<n-form-item
@ -121,90 +99,7 @@
</n-card>
<n-card title="代理模式设置" hoverable style="margin-top: 10px; min-width: 850px">
<n-form :model="mjSetting.remoteSetting">
<div style="display: flex; margin-top: 10px">
<n-form-item label="服务器ID" style="width: 200px; margin-left: 5px" path="guildId">
<n-input
v-model:value="mjSetting.remoteSetting.guildId"
placeholder="请填写服务器ID"
/>
</n-form-item>
<n-form-item label="频道ID" style="width: 200px; margin-left: 10px" path="channelId">
<n-input
v-model:value="mjSetting.remoteSetting.channelId"
placeholder="请填写频道ID"
/>
</n-form-item>
<n-form-item
label="MJ私信ID"
style="width: 200px; margin-left: 10px"
path="mjBotChannelId"
>
<n-input
v-model:value="mjSetting.remoteSetting.mjBotChannelId"
placeholder="请填写MJ私信ID"
/>
</n-form-item>
<n-form-item
label="Niji私信ID"
style="width: 200px; margin-left: 10px"
path="nijiBotChannelId"
>
<n-input
v-model:value="mjSetting.remoteSetting.nijiBotChannelId"
placeholder="请填写NIJI私信ID"
/>
</n-form-item>
<n-form-item style="width: 200px; margin-left: 10px">
<n-button type="info" @click="AccountSync">账号同步</n-button>
</n-form-item>
</div>
<div style="display: flex; margin-top: 10px">
<n-form-item label="用户token" style="width: 240px" path="token">
<n-input
v-model:value="mjSetting.remoteSetting.userToken"
placeholder="请填写MJtoken"
/>
</n-form-item>
<n-form-item label="用户Agent" style="width: 250px; margin-left: 10px" path="userAgent">
<n-input
v-model:value="mjSetting.remoteSetting.userAgent"
placeholder="请填写用户Agent"
/>
</n-form-item>
<n-form-item label="账号并发数" style="width: 100px; margin-left: 10px" path="coreSize">
<n-input-number
v-model:value="mjSetting.remoteSetting.coreSize"
:show-button="false"
placeholder="请填写账号并发数"
:min="1"
:max="20"
></n-input-number>
</n-form-item>
<n-form-item label="等待队列" style="width: 100px; margin-left: 10px" path="queueSize">
<n-input-number
v-model:value="mjSetting.remoteSetting.queueSize"
:show-button="false"
placeholder="请填写等待队列数量"
:min="1"
:max="20"
></n-input-number>
</n-form-item>
<n-form-item
label="任务超时时间"
style="width: 100px; margin-left: 10px"
path="timeoutMinutes"
>
<n-input-number
v-model:value="mjSetting.remoteSetting.timeoutMinutes"
:show-button="false"
placeholder="请填写任务超时时间"
:min="1"
:max="20"
></n-input-number>
</n-form-item>
</div>
</n-form>
<n-button type="info" @click="AddMultiMjAccount">账号管理</n-button>
</n-card>
<n-card title="浏览器模式设置" hoverable style="margin-top: 10px; min-width: 850px">
@ -256,8 +151,6 @@
>保存MJ配置</n-button
>
</div>
<template #description> 正在添加或同步MJ账号信息 </template>
</n-spin>
</template>
<script>
@ -283,6 +176,7 @@ import { DEFINE_STRING } from '../../../../define/define_string'
import { Reload } from '@vicons/ionicons5'
import { isEmpty, max, min } from 'lodash'
import { MJImageType } from '../../../../define/enum/mjEnum'
import AddMultiRemoteMj from './Components/AddMultiRemoteMj.vue'
export default defineComponent({
components: {
NButton,
@ -304,7 +198,6 @@ export default defineComponent({
let message = useMessage()
let dialog = useDialog()
let sampleRef = ref(null)
let show = ref(false)
let select_robot_options = ref([
{
label: 'MJ',
@ -543,25 +436,15 @@ export default defineComponent({
}
if (request_model == MJImageType.REMOTE_MJ) {
if (mjSetting.value.remoteSetting == null) {
message.error('请先添加代理模式的配置')
//
let remoteMjRes = await window.setting.GetRemoteMJSettings()
if (remoteMjRes.code == 0) {
message.error('获取代理MJ配置失败')
return
}
// if (mjSetting.value.remoteSetting.accountId == null) {
// message.error('')
// return
// }
//
if (
mjSetting.value.remoteSetting == null ||
mjSetting.value.remoteSetting.guildId == null ||
mjSetting.value.remoteSetting.channelId == null ||
mjSetting.value.remoteSetting.userToken == null ||
mjSetting.value.remoteSetting.userAgent == null
) {
message.error('请检查代理模式设置的必填字段')
if (remoteMjRes.data.length <= 0) {
message.error('请先添加代理模式的配置')
return
}
}
@ -590,8 +473,7 @@ export default defineComponent({
if (mjSetting.value.requestModel == MJImageType.REMOTE_MJ) {
window.api.showGlobalMessageDialog({
code: 1,
message: `数据保存成功,
当前生图模式为代理模式若有修改配置请手动同步账号数据但是不要频繁同步有封号风险 `
message: `数据保存成功,当前模式为代理模式`
})
} else {
window.api.showGlobalMessageDialog({ code: 1, message: '添加成功' })
@ -639,49 +521,18 @@ export default defineComponent({
}
/**
* 账号同步
* 添加多个账号这样可以同时跑多个账号
*/
async function AccountSync() {
dialog.warning({
title: '警告',
content: () =>
h('div', {}, [
h(
'span',
{},
{
default: () => '同步数据的信息是保存后的数据'
}
),
h('br'),
h(
'span',
{ style: 'color : red;font-size : 18px' },
{
default: () => '修改数据后请先保存,请先保存再执行同步操作'
}
),
h('br'),
h(
'span',
{},
{
default: () => '同步操作不要频繁,有封号风险'
}
)
]),
positiveText: '确定',
negativeText: '取消',
onPositiveClick: async () => {
show.value = true
let res = await window.setting.MjRemoteAccountSync()
show.value = false
if (res.code == 0) {
message.error(res.message)
return
}
message.success('MJ账号同步成功可以开始使用')
}
async function AddMultiMjAccount() {
//
let dW = window.innerWidth * 0.9
let dH = window.innerHeight * 0.9
dialog.create({
showIcon: false,
title: '管理代理模式MJ账号',
content: () => h(AddMultiRemoteMj, { height: dH }),
style: `min-width : 600px; width : ${dW}px; height : ${dH}px; padding-right : 5px;`,
maskClosable: false
})
}
@ -700,8 +551,7 @@ export default defineComponent({
mj_speed_options,
openGptBuyUrl,
sampleRules,
AccountSync,
show
AddMultiMjAccount
}
}
})

51
src/stores/setting.js Normal file
View File

@ -0,0 +1,51 @@
import { defineStore } from 'pinia'
// 系统相关设置
export const useSettingStore = defineStore('setting', {
state: () => ({
actionRemoteMJ: {
id: null,
accountId: null,
channelId: null,
coreSize: 3,
guildId: null,
enable: true,
mjBotChannelId: null,
nijiBotChannelId: null,
queueSize: 10,
remark: null,
timeoutMinutes: 10,
userAgent:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
userToken: null,
createTime: null,
updateTime: null
}
}),
getters: {},
actions: {
/**
* 重置MJ代理模式的数据
*/
ResetActionRemoteMJ() {
this.actionRemoteMJ = {
id: null,
accountId: null,
channelId: null,
coreSize: 3,
guildId: null,
enable: true,
mjBotChannelId: null,
nijiBotChannelId: null,
queueSize: 10,
remark: null,
timeoutMinutes: 10,
userAgent:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
userToken: null,
createTime: null,
updateTime: null
}
}
}
})