V 2.2.10 新增MJ的代理模式
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
|
||||
import fs from "fs"
|
||||
import { isEmpty } from "lodash";
|
||||
import path from "path";
|
||||
const fspromises = fs.promises;
|
||||
|
||||
@@ -17,6 +18,87 @@ export async function CheckFileOrDirExist(path) {
|
||||
}
|
||||
}
|
||||
|
||||
// 检查文件夹是不是存在,不存在的话,创建
|
||||
export async function CheckFolderExistsOrCreate(folderPath) {
|
||||
try {
|
||||
if (!(await CheckFileOrDirExist(folderPath))) {
|
||||
await fspromises.mkdir(folderPath, { recursive: true });
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 拼接两个地址,返回拼接后的地址
|
||||
* @param {*} rootPath 根目录的消息
|
||||
* @param {*} subPath 子目录的消息
|
||||
* @returns
|
||||
*/
|
||||
export function JoinPath(rootPath, subPath) {
|
||||
// 判断第二个地址是不是存在,不存在返回null,存在返回拼接后的地址
|
||||
if (subPath && !isEmpty(subPath)) {
|
||||
return path.resolve(rootPath, subPath)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拷贝一个文件或者是文件夹到指定的目标地址
|
||||
* @param {*} source 源文件或文件夹地址
|
||||
* @param {*} target 目标文件或文件夹地址
|
||||
* @param {*} checkParent 是否检查父文件夹是否存在,不存在的话创建,默认false,不检查,不存在直接创建
|
||||
*/
|
||||
export async function CopyFileOrFolder(source, target, checkParent = false) {
|
||||
try {
|
||||
// 判断源文件或文件夹是不是存在
|
||||
if (!(await CheckFileOrDirExist(source))) {
|
||||
throw new Error(`源文件或文件夹不存在: ${source}`);
|
||||
}
|
||||
// 判断父文件夹是否存在,不存在创建
|
||||
const parent_path = path.dirname(target);
|
||||
let parentIsExist = await CheckFileOrDirExist(parent_path);
|
||||
if (!parentIsExist) {
|
||||
if (checkParent) {
|
||||
throw new Error(`目的文件或文件夹的父文件夹不存在: ${parent_path}`);
|
||||
} else {
|
||||
await fspromises.mkdir(parent_path, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是不是文件夹
|
||||
const isDirectory = await IsDirectory(source);
|
||||
// 复制文件夹的逻辑
|
||||
async function copyDirectory(source, target) {
|
||||
// 创建目标文件夹
|
||||
await fspromises.mkdir(target, { recursive: true });
|
||||
let entries = await fspromises.readdir(source, { withFileTypes: true });
|
||||
for (let entry of entries) {
|
||||
let srcPath = path.join(source, entry.name);
|
||||
let tgtPath = path.join(target, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
await copyDirectory(srcPath, tgtPath);
|
||||
} else {
|
||||
await fspromises.copyFile(srcPath, tgtPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDirectory) {
|
||||
// 创建目标文件夹
|
||||
await copyDirectory(source, target);
|
||||
} else {
|
||||
// 复制文件
|
||||
await fspromises.copyFile(source, target);
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** * 判断一个文件地址是不是文件夹
|
||||
* @param {*} path 输入的文件地址
|
||||
* @returns true 是 false 不是
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import Realm, { ObjectSchema } from 'realm'
|
||||
import { BookBackTaskStatus, BookBackTaskType } from '../../../enum/bookEnum'
|
||||
|
||||
export class BookBackTaskList extends Realm.Object<BookBackTaskList> {
|
||||
id: string
|
||||
bookId: string
|
||||
bookTaskId: string
|
||||
name: string
|
||||
type: BookBackTaskType
|
||||
status: BookBackTaskStatus
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'BookBackTaskList',
|
||||
properties: {
|
||||
id: 'string',
|
||||
bookId: { type: 'string', indexed: true },
|
||||
bookTaskId: { type: 'string', indexed: true },
|
||||
name: 'string',
|
||||
type: 'string',
|
||||
status: 'string',
|
||||
createTime: 'date',
|
||||
updateTime: 'date'
|
||||
},
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import Realm, { ObjectSchema } from 'realm'
|
||||
import { BookType } from '../../../enum/bookEnum'
|
||||
|
||||
export class BookModel extends Realm.Object<BookModel> {
|
||||
id: string
|
||||
no: number
|
||||
name: string
|
||||
bookFolderPath: string
|
||||
imageFolder: string | null
|
||||
type: BookType
|
||||
oldVideoPath: string | null
|
||||
srtPath: string | null
|
||||
audioPath: string | null
|
||||
updateTime: Date
|
||||
createTime: Date
|
||||
test: string | null
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'Book',
|
||||
properties: {
|
||||
id: 'string',
|
||||
no: 'int',
|
||||
name: 'string',
|
||||
bookFolderPath: 'string',
|
||||
type: 'string',
|
||||
oldVideoPath: 'string?',
|
||||
srtPath: 'string?',
|
||||
audioPath: 'string?',
|
||||
imageFolder: 'string?',
|
||||
updateTime: 'date',
|
||||
createTime: 'date',
|
||||
test: 'string?'
|
||||
},
|
||||
// 主键为_id
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import Realm, { ObjectSchema } from 'realm'
|
||||
import { BookTaskStatus, BookType } from '../../../enum/bookEnum'
|
||||
|
||||
export class BookTaskModel extends Realm.Object<BookTaskModel> {
|
||||
id: string
|
||||
no: number
|
||||
bookId: string
|
||||
name: string
|
||||
generateVideoPath: string | null
|
||||
srtPath: string | null
|
||||
audioPath: string | null
|
||||
imageFolder: string | null
|
||||
styleList: Realm.List<string> | null
|
||||
prefix: string | null
|
||||
status: BookTaskStatus
|
||||
errorMsg: string | null
|
||||
isAuto: boolean // 是否自动
|
||||
updateTime: Date
|
||||
createTime: Date
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'BookTask',
|
||||
properties: {
|
||||
id: 'string',
|
||||
bookId: { type: 'string', indexed: true },
|
||||
no: 'int',
|
||||
name: 'string',
|
||||
generateVideoPath: 'string?',
|
||||
srtPath: 'string?',
|
||||
audioPath: 'string?',
|
||||
imageFolder: 'string?',
|
||||
styleList: 'string[]',
|
||||
prefix: 'string?',
|
||||
status: 'string',
|
||||
errorMsg: 'string?',
|
||||
isAuto: 'bool',
|
||||
updateTime: 'date',
|
||||
createTime: 'date'
|
||||
},
|
||||
// 主键为_id
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
import Realm, { ObjectSchema } from 'realm'
|
||||
import {
|
||||
BookBackTaskStatus,
|
||||
BookBackTaskType,
|
||||
BookTaskStatus,
|
||||
BookType,
|
||||
MJAction,
|
||||
MJCategroy
|
||||
} from '../../../enum/bookEnum'
|
||||
|
||||
export class Subtitle extends Realm.Object<Subtitle> {
|
||||
startTime: number
|
||||
endTime: number
|
||||
srtValue: string
|
||||
id: string
|
||||
static schema = {
|
||||
name: 'Subtitle',
|
||||
properties: {
|
||||
startTime: 'int',
|
||||
endTime: 'int',
|
||||
srtValue: 'string',
|
||||
id: 'string'
|
||||
},
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
|
||||
export class MJMessage extends Realm.Object<MJMessage> {
|
||||
id: string
|
||||
mjApiUrl: string | null
|
||||
progress: number
|
||||
category: MJCategroy
|
||||
imageClick: string | null // 图片点击(显示的小的)
|
||||
imageShow: string | null // 图片实际的地址
|
||||
messageId: string // 消息ID(可以是MJ中的,也可以是API中的)
|
||||
action: MJAction // 动作(生图,反推之类)
|
||||
status: string // 状态
|
||||
message: string | null // 消息
|
||||
static schema: ObjectSchema = {
|
||||
name: 'MJMessage',
|
||||
properties: {
|
||||
id: 'string',
|
||||
mjApiUrl: 'string?',
|
||||
progress: 'int',
|
||||
category: 'string',
|
||||
imageClick: 'string?',
|
||||
imageShow: 'string?',
|
||||
messageId: 'string',
|
||||
action: 'string',
|
||||
status: 'string',
|
||||
message: 'string?'
|
||||
},
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
|
||||
export class WebuiConfig extends Realm.Object<WebuiConfig> {
|
||||
sampler_name: string // 采样器名称
|
||||
negative_prompt: string // 负面提示
|
||||
batch_size: number // 批次大小
|
||||
steps: number // 步数
|
||||
cfg_scale: number // 提示词相关性
|
||||
denoising_strength: number // 降噪强度
|
||||
width: number // 宽度
|
||||
height: number // 高度
|
||||
seed: number // 种子
|
||||
init_images: string // 初始图片(垫图的图片地址)
|
||||
id: string
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'WebuiConfig',
|
||||
properties: {
|
||||
sampler_name: 'string',
|
||||
negative_prompt: 'string',
|
||||
batch_size: 'int',
|
||||
steps: 'int',
|
||||
cfg_scale: 'int',
|
||||
denoising_strength: 'int',
|
||||
width: 'int',
|
||||
height: 'int',
|
||||
seed: 'int',
|
||||
init_images: 'string',
|
||||
id: 'string'
|
||||
},
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
|
||||
export class SDConfig extends Realm.Object<SDConfig> {
|
||||
checkpoints: string // 大模型
|
||||
api: string // api地址
|
||||
model: string // 生图方式
|
||||
webuiConfig: WebuiConfig
|
||||
id: string
|
||||
static schema: ObjectSchema = {
|
||||
name: 'SDConfig',
|
||||
properties: {
|
||||
checkpoints: 'string',
|
||||
api: 'string',
|
||||
model: 'string',
|
||||
webuiConfig: 'WebuiConfig',
|
||||
id: 'string'
|
||||
},
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
|
||||
export class BookTaskDetailModel extends Realm.Object<BookTaskDetailModel> {
|
||||
id: string
|
||||
no: number
|
||||
name: string
|
||||
bookId: string
|
||||
bookTaskId: string
|
||||
videoPath: string | null // 视频地址
|
||||
word: string | null // 文案
|
||||
oldImage: string | null // 旧图片(用于SD的图生图)
|
||||
afterGpt: string | null // GPT生成的文案
|
||||
startTime: number | null // 开始时间
|
||||
endTime: number | null // 结束时间
|
||||
timeLimit: string | null // 事件实现(0 -- 3000)
|
||||
subValue: Realm.List<Subtitle> | null // 包含的字幕数据
|
||||
characterTags: string[] | null // 角色标签
|
||||
gptPrompt: string | null // GPT提示词
|
||||
mjMessage: MJMessage | null // MJ消息
|
||||
outImagePath: string | null // 输出图片地址
|
||||
subImagePath: string[] | null // 字幕图片地址
|
||||
prompt: string | null // 提示
|
||||
adetailer: boolean // 是否开启修脸
|
||||
sdConifg: SDConfig | null // SD配置
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'BookTaskDetail',
|
||||
properties: {
|
||||
id: 'string',
|
||||
no: 'int',
|
||||
name: 'string',
|
||||
bookId: { type: 'string', indexed: true },
|
||||
bookTaskId: { type: 'string', indexed: true },
|
||||
videoPath: 'string?',
|
||||
word: 'string?',
|
||||
oldImage: 'string?',
|
||||
afterGpt: 'string?',
|
||||
startTime: 'int?',
|
||||
endTime: 'int?',
|
||||
timeLimit: 'string?',
|
||||
subValue: { type: 'list', objectType: 'Subtitle' },
|
||||
characterTags: { type: 'list', objectType: 'string' },
|
||||
gptPrompt: 'string?',
|
||||
mjMessage: 'MJMessage?',
|
||||
outImagePath: 'string?',
|
||||
subImagePath: 'string[]',
|
||||
prompt: 'string?',
|
||||
adetailer: 'bool',
|
||||
sdConifg: 'SDConfig?',
|
||||
createTime: 'date',
|
||||
updateTime: 'date'
|
||||
},
|
||||
// 主键为_id
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import Realm, { ObjectSchema } from 'realm'
|
||||
import { LoggerStatus, LoggerType } from '../../../enum/softwareEnum'
|
||||
|
||||
export class LoggerModel extends Realm.Object<LoggerModel> {
|
||||
id: string
|
||||
bookId: string // 小说ID
|
||||
bookTaskId: string // 小说任务ID
|
||||
type: LoggerType
|
||||
status: LoggerStatus
|
||||
date: Date
|
||||
content: string
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'Logger',
|
||||
properties: {
|
||||
id: 'string',
|
||||
bookId: 'string',
|
||||
bookTaskId: 'string',
|
||||
type: 'string',
|
||||
status: 'string',
|
||||
date: 'date',
|
||||
content: 'string'
|
||||
},
|
||||
// 主键为_id
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import Realm, { ObjectSchema } from 'realm'
|
||||
import { LoggerStatus, LoggerType } from '../../../enum/softwareEnum'
|
||||
import { MJImageType, MJRobotType } from '../../../enum/mjEnum'
|
||||
|
||||
export class BrowserMJModel extends Realm.Object<BrowserMJModel> {
|
||||
id: string
|
||||
serviceId: string
|
||||
channelId: string
|
||||
mjBotId: string
|
||||
nijBotId: string
|
||||
token: string
|
||||
userAgent: string
|
||||
userAgentCustom: boolean
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
version: string
|
||||
static schema: ObjectSchema = {
|
||||
name: 'BrowserMJ',
|
||||
properties: {
|
||||
id: 'string',
|
||||
serviceId: 'string',
|
||||
channelId: 'string',
|
||||
mjBotId: 'string?',
|
||||
nijBotId: 'string?',
|
||||
token: 'string',
|
||||
userAgent: 'string',
|
||||
userAgentCustom: 'bool',
|
||||
createTime: 'date',
|
||||
updateTime: 'date',
|
||||
version: 'string'
|
||||
},
|
||||
// 主键为_id
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
|
||||
export class RemoteMJModel extends Realm.Object<RemoteMJModel> {
|
||||
id: string
|
||||
accountId: string | null
|
||||
channelId: string
|
||||
coreSize: number
|
||||
guildId: string
|
||||
mjBotChannelId: string
|
||||
nijiBotChannelId: string
|
||||
queueSize: number
|
||||
remark: string
|
||||
remixAutoSubmit: boolean
|
||||
timeoutMinutes: number
|
||||
userAgent: string
|
||||
userToken: string
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
version: string
|
||||
static schema: ObjectSchema = {
|
||||
name: 'RemoteMJ',
|
||||
properties: {
|
||||
id: 'string',
|
||||
accountId: 'string?',
|
||||
channelId: 'string',
|
||||
coreSize: 'int',
|
||||
guildId: 'string',
|
||||
mjBotChannelId: 'string',
|
||||
nijiBotChannelId: 'string',
|
||||
queueSize: 'int',
|
||||
remark: 'string',
|
||||
remixAutoSubmit: 'bool',
|
||||
timeoutMinutes: 'int',
|
||||
userAgent: 'string',
|
||||
userToken: 'string',
|
||||
createTime: 'date',
|
||||
updateTime: 'date',
|
||||
version: 'string'
|
||||
},
|
||||
// 主键为_id
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
|
||||
export class APIMjModel extends Realm.Object<APIMjModel> {
|
||||
id: string
|
||||
mjApiUrl: string
|
||||
mjSpeed: string // MJ出图的速度模式
|
||||
apiKey: string
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
version: string
|
||||
static schema: ObjectSchema = {
|
||||
name: 'APIMj',
|
||||
properties: {
|
||||
id: 'string',
|
||||
mjApiUrl: 'string',
|
||||
mjSpeed: 'string',
|
||||
apiKey: 'string',
|
||||
createTime: 'date',
|
||||
updateTime: 'date',
|
||||
version: 'string'
|
||||
},
|
||||
// 主键为_id
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
|
||||
export class MjSettingModel extends Realm.Object<MjSettingModel> {
|
||||
id: string
|
||||
type: MJImageType
|
||||
requestModel: MJImageType
|
||||
selectRobot: MJRobotType
|
||||
imageScale: string
|
||||
imageModel: string
|
||||
imageSuffix: string
|
||||
taskCount: number
|
||||
spaceTime: number
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
version: string
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'MjSetting',
|
||||
properties: {
|
||||
id: 'string',
|
||||
type: 'string',
|
||||
requestModel: 'string',
|
||||
selectRobot: 'string',
|
||||
imageScale: 'string',
|
||||
imageModel: 'string',
|
||||
imageSuffix: 'string',
|
||||
taskCount: 'int',
|
||||
spaceTime: 'int',
|
||||
createTime: 'date',
|
||||
updateTime: 'date',
|
||||
version: 'string'
|
||||
},
|
||||
// 主键为_id
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import Realm, { ObjectSchema } from 'realm'
|
||||
import { ComponentSize, SoftwareThemeType } from '../../../enum/softwareEnum'
|
||||
|
||||
export class SoftwareModel extends Realm.Object<SoftwareModel> {
|
||||
id: string
|
||||
theme: SoftwareThemeType
|
||||
reverse_display_show: boolean
|
||||
reverse_show_book_striped: boolean
|
||||
reverse_data_table_size: ComponentSize
|
||||
|
||||
static schema: ObjectSchema = {
|
||||
name: 'Software',
|
||||
properties: {
|
||||
id: 'string',
|
||||
theme: 'string',
|
||||
reverse_display_show: 'bool',
|
||||
reverse_show_book_striped: 'bool',
|
||||
reverse_data_table_size: 'string'
|
||||
},
|
||||
// 主键为_id
|
||||
primaryKey: 'id'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
import Realm from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { BookTaskModel } from '../../model/Book/bookTask.js'
|
||||
import { BookTaskStatus } from '../../../enum/bookEnum.js'
|
||||
import { errorMessage, successMessage } from '../../../../main/generalTools.js'
|
||||
import { BaseRealmService } from './bookBasic'
|
||||
import { isEmpty } from 'lodash'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
export class BookBackTaskListService extends BaseRealmService {
|
||||
static instance: BookBackTaskListService | null = null
|
||||
realm: Realm
|
||||
|
||||
private constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前实例对象,为空则创建一个新的
|
||||
* @returns
|
||||
*/
|
||||
public static async getInstance() {
|
||||
if (BookBackTaskListService.instance === null) {
|
||||
BookBackTaskListService.instance = new BookBackTaskListService()
|
||||
await super.getInstance()
|
||||
}
|
||||
return BookBackTaskListService.instance
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增一个小说相关的后台任务队列
|
||||
* @param bookBackTask 要添加的小说数据
|
||||
*/
|
||||
async AddBookBackTaskList(bookBackTask) {
|
||||
try {
|
||||
// 判断数据是不是存在
|
||||
if (
|
||||
isEmpty(bookBackTask.bookId) ||
|
||||
isEmpty(bookBackTask.bookTaskId) ||
|
||||
isEmpty(bookBackTask.name) ||
|
||||
isEmpty(bookBackTask.type)
|
||||
) {
|
||||
throw new Error('新增后台队列任务到数据库失败,数据不完整,缺少必要字段')
|
||||
}
|
||||
// 开始新建
|
||||
bookBackTask.id = uuidv4()
|
||||
bookBackTask.createTime = new Date()
|
||||
bookBackTask.updateTime = new Date()
|
||||
bookBackTask.status = BookTaskStatus.WAIT
|
||||
this.realm.write(() => {
|
||||
this.realm.create('BookBackTaskList', bookBackTask)
|
||||
})
|
||||
return successMessage(
|
||||
bookBackTask,
|
||||
'新增后台队列任务到数据库成功',
|
||||
'BookBackTaskList_AddBookBackTaskList'
|
||||
)
|
||||
} catch (error) {
|
||||
return errorMessage(
|
||||
'新增后台队列任务到数据库失败,错误信息入校' + error.toString(),
|
||||
'BookBackTaskList_AddBookBackTaskList'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改一个小说相关的后台任务队列中的详细信息(对于后台的队列任务只能修改状态)
|
||||
* @param bookBackTask 修改的数据
|
||||
*/
|
||||
async ModifyBookBackTaskList(bookBackTask) {
|
||||
try {
|
||||
// 判断数据是不是存在
|
||||
if (isEmpty(bookBackTask.id) || isEmpty(bookBackTask.status)) {
|
||||
throw new Error('修改后台队列任务失败,数据不完整,缺少必要字段')
|
||||
}
|
||||
// 开始修改
|
||||
this.realm.write(() => {
|
||||
// 获取指定ID的队列任务
|
||||
let _bookBackTask = this.realm.objectForPrimaryKey('BookBackTaskList', bookBackTask.id)
|
||||
// 判断数据是不是存在
|
||||
if (_bookBackTask == null) {
|
||||
throw new Error('修改后台队列任务失败,数据不存在')
|
||||
}
|
||||
// 修改数据
|
||||
_bookBackTask.status = bookBackTask.status
|
||||
})
|
||||
return successMessage(
|
||||
bookBackTask,
|
||||
'修改后台队列任务成功',
|
||||
'BookBackTaskList_ModifyBookBackTaskList'
|
||||
)
|
||||
} catch (error) {
|
||||
return errorMessage(
|
||||
'修改后台队列任务失败,错误信息如下:' + error.toString(),
|
||||
'BookBackTaskList_ModifyBookBackTaskList'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除满足条件的数据,包含 id、bookId、bookTaskId
|
||||
* @param bookBackTask 删除的数据
|
||||
*/
|
||||
async DeleteBookBackTaskListBy(bookBackTask) {
|
||||
try {
|
||||
this.realm.write(() => {
|
||||
// 构建查询条件
|
||||
let query = [] as string[]
|
||||
if (bookBackTask.id) {
|
||||
query.push(`id = ${bookBackTask.id}`)
|
||||
}
|
||||
if (bookBackTask.bookId) {
|
||||
query.push(`bookId = ${bookBackTask.bookId}`)
|
||||
}
|
||||
if (bookBackTask.bookTaskId) {
|
||||
query.push(`bookTaskId = ${bookBackTask.bookTaskId}`)
|
||||
}
|
||||
const queryString = query.join(' && ')
|
||||
// 获取指定的数据
|
||||
if (queryString) {
|
||||
const tasksToDelete = this.realm.objects('BookBackTaskList').filtered(queryString)
|
||||
this.realm.delete(tasksToDelete)
|
||||
} else {
|
||||
throw new Error('删除后台队列任务失败,没有筛选条件')
|
||||
}
|
||||
return successMessage(
|
||||
bookBackTask,
|
||||
'删除后台队列任务成功',
|
||||
'BookBackTaskList_DeleteBookBackTaskListBy'
|
||||
)
|
||||
})
|
||||
} catch (error) {
|
||||
return errorMessage(
|
||||
'删除后台队列任务失败,错误信息如下:' + error.toString(),
|
||||
'BookBackTaskList_DeleteBookBackTaskListBy'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import Realm from 'realm'
|
||||
import { BookModel } from '../../model/Book/book'
|
||||
import { BookTaskModel } from '../../model/Book/bookTask'
|
||||
import { BaseService } from '../baseService'
|
||||
import { define } from '../../../define'
|
||||
import path from 'path'
|
||||
import {
|
||||
BookTaskDetailModel,
|
||||
MJMessage,
|
||||
SDConfig,
|
||||
Subtitle,
|
||||
WebuiConfig
|
||||
} from '../../model/Book/bookTaskDetail'
|
||||
import { BookBackTaskList } from '../../model/Book/BookBackTaskListModel'
|
||||
|
||||
let dbPath = path.resolve(define.db_path, 'book.realm')
|
||||
|
||||
// 版本迁移
|
||||
const migration = (oldRealm: Realm, newRealm: Realm) => {
|
||||
if (oldRealm.schemaVersion < 1) {
|
||||
const oldBooks = oldRealm.objects('Book')
|
||||
const newBooks = newRealm.objects('Book')
|
||||
|
||||
for (let i = 0; i < oldBooks.length; i++) {
|
||||
newBooks[i].test = 'defaultValue' // 为新属性设置默认值
|
||||
}
|
||||
}
|
||||
if (oldRealm.schemaVersion < 2) {
|
||||
const oldBookTask = oldRealm.objects('BookTask')
|
||||
const newBookTask = newRealm.objects('BookTask')
|
||||
for (let i = 0; i < oldBookTask.length; i++) {
|
||||
newBookTask[i].isAuto = false // 为新属性设置默认值
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class BaseRealmService extends BaseService {
|
||||
static instance: BaseRealmService | null = null
|
||||
protected realm: Realm | null = null
|
||||
dbpath: string
|
||||
|
||||
protected constructor() {
|
||||
super()
|
||||
this.dbpath = dbPath
|
||||
}
|
||||
|
||||
public static async getInstance() {
|
||||
if (BaseRealmService.instance === null) {
|
||||
BaseRealmService.instance = new BaseRealmService()
|
||||
await BaseRealmService.instance.open()
|
||||
}
|
||||
return BaseRealmService.instance
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建数据库连接,如果已经存在则直接返回
|
||||
* @returns
|
||||
*/
|
||||
async open() {
|
||||
try {
|
||||
if (this.realm != null) return
|
||||
// 判断当前全局是不是又当前这个
|
||||
const config = {
|
||||
schema: [
|
||||
BookModel,
|
||||
Subtitle,
|
||||
MJMessage,
|
||||
BookBackTaskList,
|
||||
SDConfig,
|
||||
WebuiConfig,
|
||||
BookTaskModel,
|
||||
BookTaskDetailModel
|
||||
],
|
||||
path: this.dbpath,
|
||||
schemaVersion: 2,
|
||||
migration: migration
|
||||
}
|
||||
this.realm = await Realm.open(config)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
import Realm, { UpdateMode } from 'realm'
|
||||
import { BookModel } from '../../model/Book/book.js'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { BookTaskStatus, BookType } from '../../../enum/bookEnum.js'
|
||||
import { successMessage } from '../../../../main/generalTools.js'
|
||||
import { CheckFolderExistsOrCreate, CopyFileOrFolder } from '../../../Tools/file.js'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
import { BookTaskService } from './bookTaskService'
|
||||
import { BaseRealmService } from './bookBasic.js'
|
||||
import { isEmpty } from 'lodash'
|
||||
|
||||
class BooKService extends BaseRealmService {
|
||||
static instance: BooKService | null = null
|
||||
realm: Realm
|
||||
|
||||
private constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前实例对象,为空则创建一个新的
|
||||
* @returns
|
||||
*/
|
||||
public static async getInstance() {
|
||||
if (BooKService.instance === null) {
|
||||
BooKService.instance = new BooKService()
|
||||
await super.getInstance()
|
||||
}
|
||||
return BooKService.instance
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取小说信息,通过参数查询
|
||||
* @returns
|
||||
*/
|
||||
async GetBookData(bookQuery) {
|
||||
try {
|
||||
await this.open()
|
||||
// 获取所有的小说数据,并进行时间降序排序
|
||||
let books = this.realm.objects<BookModel>('Book')
|
||||
let book_length = books.length
|
||||
|
||||
// 开始开始筛选
|
||||
if (bookQuery.bookId) {
|
||||
// 查询对应的小说ID的数据
|
||||
books = books.filtered('id = $0', bookQuery.bookId)
|
||||
}
|
||||
|
||||
books = books.sorted('updateTime', true)
|
||||
// 判断是不是有page和pageSize,有的话对查询返回的信息做分页
|
||||
if (bookQuery.page && bookQuery.pageSize) {
|
||||
books = books.slice(
|
||||
(bookQuery.page - 1) * bookQuery.pageSize,
|
||||
bookQuery.page * bookQuery.pageSize
|
||||
) as unknown as Realm.Results<BookModel>
|
||||
}
|
||||
if (books.length <= 0) {
|
||||
return successMessage(
|
||||
{
|
||||
res_book: [],
|
||||
book_length: 0
|
||||
},
|
||||
'没有数据',
|
||||
'ReverseBook_GetBookData'
|
||||
)
|
||||
}
|
||||
|
||||
// 将realm对象数组转换为普通对象数组
|
||||
let res_book = 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(
|
||||
{
|
||||
res_book,
|
||||
book_length
|
||||
},
|
||||
'获取成功',
|
||||
'ReverseBook_GetBookData'
|
||||
)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增或者是修小说数据
|
||||
* @param {*} book 小说信息
|
||||
* @returns
|
||||
*/
|
||||
async AddOrModifyBook(book) {
|
||||
try {
|
||||
await this.open()
|
||||
if (book == null) {
|
||||
throw new Error('小说数据为空,无法修改')
|
||||
}
|
||||
|
||||
// 当小说的类型是反推的时候,必须传入视频
|
||||
if (book.type == BookType.MJ_REVERSE || book.type == BookType.SD_REVERSE) {
|
||||
// 判断视频是否存在
|
||||
if (book.oldVideoPath == null || book.oldVideoPath == '') {
|
||||
throw new Error('反推必须传入视频')
|
||||
}
|
||||
}
|
||||
|
||||
if (book.id == null) {
|
||||
// 新增
|
||||
// 判断指定的名字在数据库中是否存在
|
||||
let books = this.realm.objects('Book').filtered('name = $0', book.name)
|
||||
if (books.length > 0) {
|
||||
throw new Error(`小说名字 ${book.name} 已经存在,请更换小说名字`)
|
||||
}
|
||||
console.log(this)
|
||||
// 新增数据
|
||||
book.id = uuidv4()
|
||||
book.createTime = new Date()
|
||||
book.updateTime = new Date()
|
||||
// 检查传入的视频文件是不是存在
|
||||
// 获取当前最大的no
|
||||
let maxNo = this.realm.objects('Book').max('no')
|
||||
book.no = maxNo == null ? 1 : Number(maxNo) + 1
|
||||
// 拼接项目文件夹
|
||||
book.bookFolderPath = book.id
|
||||
book.imageFolder = `${book.id}/tmp`
|
||||
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`)
|
||||
|
||||
// 将视频拷贝一个到项目文件下面
|
||||
if (book.oldVideoPath) {
|
||||
await CopyFileOrFolder(book.oldVideoPath, oldVideoPath)
|
||||
}
|
||||
|
||||
// 创建对应的文件夹
|
||||
await CheckFolderExistsOrCreate(bookFolderPath)
|
||||
await CheckFolderExistsOrCreate(imageFolder)
|
||||
// 修改数据
|
||||
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(),
|
||||
bookId: book.id,
|
||||
no: 1,
|
||||
name: 'output_00001',
|
||||
generateVideoPath: null,
|
||||
srtPath: null,
|
||||
audioPath: null,
|
||||
imageFolder: path.relative(define.project_path, bookTaskImageFolder), // 获取文件输出对于项目的相对路径
|
||||
styleList: [],
|
||||
prefix: null,
|
||||
status: BookTaskStatus.WAIT,
|
||||
errorMsg: null,
|
||||
isAuto: false,
|
||||
updateTime: new Date(),
|
||||
createTime: new Date()
|
||||
}
|
||||
|
||||
// 添加任务
|
||||
this.realm.create('BookTask', bookTask)
|
||||
})
|
||||
|
||||
// 保存成功,返回数据,但是要做处理
|
||||
book.bookFolderPath = bookFolderPath
|
||||
book.imageFolder = imageFolder
|
||||
book.oldVideoPath = oldVideoPath
|
||||
|
||||
return successMessage(book, '新增成功', 'BookBasic_AddOrModifyBook')
|
||||
} else {
|
||||
// 修改
|
||||
// 判断指定的名字在数据库中是否存在(不算自己)
|
||||
let books = this.realm
|
||||
.objects('Book')
|
||||
.filtered('name = $0 AND id != $1', book.name, book.id)
|
||||
if (books.length > 0) {
|
||||
throw new Error(`小说名字 ${book.name} 已经存在,请更换小说名字`)
|
||||
}
|
||||
// 两个文件夹地址不能改,删除两个属性
|
||||
delete book.bookFolderPath
|
||||
delete book.imageFolder
|
||||
// 修改数据
|
||||
book.updateTime = new Date()
|
||||
this.realm.write(() => {
|
||||
this.realm.create('Book', book, UpdateMode.Modified)
|
||||
})
|
||||
|
||||
// 保存成功,返回数据,但是要做处理
|
||||
return successMessage(null, '修改成功', 'BookBasic_AddOrModifyBook')
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default BooKService
|
||||
@@ -0,0 +1,47 @@
|
||||
import Realm from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { BookTaskModel } from '../../model/Book/bookTask.js'
|
||||
import { BookTaskStatus } from '../../../enum/bookEnum.js'
|
||||
import { successMessage } from '../../../../main/generalTools.js'
|
||||
import { BaseRealmService } from './bookBasic'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
let dbPath = path.resolve(define.db_path, 'book.realm')
|
||||
|
||||
// 版本迁移
|
||||
const migration = (oldRealm: Realm, newRealm: Realm) => {}
|
||||
|
||||
export class BookTaskDetailService extends BaseRealmService {
|
||||
static instance: BookTaskDetailService | null = null
|
||||
realm: Realm
|
||||
|
||||
private constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前实例对象,为空则创建一个新的
|
||||
* @returns
|
||||
*/
|
||||
public static async getInstance() {
|
||||
if (BookTaskDetailService.instance === null) {
|
||||
BookTaskDetailService.instance = new BookTaskDetailService()
|
||||
await super.getInstance()
|
||||
}
|
||||
return BookTaskDetailService.instance
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条小说人物对应的详细数据
|
||||
* @param BookTaskDetail
|
||||
*/
|
||||
public async AddBookTaskDetail(BookTaskDetail) {
|
||||
try {
|
||||
// 判断是不是又小说的ID
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
import Realm from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { BookTaskModel } from '../../model/Book/bookTask.js'
|
||||
import { BookTaskStatus } from '../../../enum/bookEnum.js'
|
||||
import { successMessage } from '../../../../main/generalTools.js'
|
||||
import { BaseRealmService } from './bookBasic'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { JoinPath } from '../../../Tools/file.js'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
let dbPath = path.resolve(define.db_path, 'book.realm')
|
||||
|
||||
export class BookTaskService extends BaseRealmService {
|
||||
static instance: BookTaskService | null = null
|
||||
realm: Realm
|
||||
|
||||
private constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前实例对象,为空则创建一个新的
|
||||
* @returns
|
||||
*/
|
||||
public static async getInstance() {
|
||||
if (BookTaskService.instance === null) {
|
||||
BookTaskService.instance = new BookTaskService()
|
||||
await super.getInstance()
|
||||
}
|
||||
return BookTaskService.instance
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询满足条件的小说子任务信息
|
||||
* @param bookTaskCondition 查询条件 id,bookId,name,no,page, pageSize
|
||||
*/
|
||||
async GetBookTaskData(bookTaskCondition) {
|
||||
try {
|
||||
await this.open()
|
||||
// 获取所有的小说数据,并进行时间降序排序
|
||||
let bookTasks = this.realm.objects<BookTaskModel>('BookTask')
|
||||
|
||||
// 开始开始筛选
|
||||
if (bookTaskCondition.id) {
|
||||
// 查询对应的小说ID的数据
|
||||
bookTasks = bookTasks.filtered('id = $0', bookTaskCondition.id)
|
||||
}
|
||||
if (bookTaskCondition.bookId) {
|
||||
// 查询对应的小说ID的数据
|
||||
bookTasks = bookTasks.filtered('bookId = $0', bookTaskCondition.bookId)
|
||||
}
|
||||
if (bookTaskCondition.name) {
|
||||
// 查询对应的小说ID的数据
|
||||
bookTasks = bookTasks.filtered('name = $0', bookTaskCondition.name)
|
||||
}
|
||||
if (bookTaskCondition.no) {
|
||||
// 查询对应的小说ID的数据
|
||||
bookTasks = bookTasks.filtered('no = $0', bookTaskCondition.no)
|
||||
}
|
||||
let bookTask_length = bookTasks.length
|
||||
|
||||
bookTasks = bookTasks.sorted('updateTime', true)
|
||||
// 判断是不是有page和pageSize,有的话对查询返回的信息做分页
|
||||
if (bookTaskCondition.page && bookTaskCondition.pageSize) {
|
||||
bookTasks = bookTasks.slice(
|
||||
(bookTaskCondition.page - 1) * bookTaskCondition.pageSize,
|
||||
bookTaskCondition.page * bookTaskCondition.pageSize
|
||||
) as unknown as Realm.Results<BookTaskModel>
|
||||
}
|
||||
|
||||
// 做一下数据转换
|
||||
// 将realm对象数组转换为普通对象数组
|
||||
let res_bookTasks = Array.from(bookTasks).map((bookTask) => {
|
||||
// 这里可以直接操作普通对象
|
||||
let bookObj = {
|
||||
...bookTask,
|
||||
styleList: bookTask.styleList ? Array.from(bookTask.styleList) : [],
|
||||
generateVideoPath: JoinPath(define.project_path, bookTask.generateVideoPath),
|
||||
srtPath: JoinPath(define.project_path, bookTask.srtPath),
|
||||
audioPath: JoinPath(define.project_path, bookTask.audioPath),
|
||||
imageFolder: JoinPath(define.project_path, bookTask.imageFolder)
|
||||
}
|
||||
return bookObj
|
||||
})
|
||||
|
||||
return successMessage(
|
||||
{
|
||||
bookTasks: res_bookTasks,
|
||||
total: bookTask_length
|
||||
},
|
||||
'查询小说任务成功',
|
||||
'BookTaskService_GetBookTaskData'
|
||||
)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 添加一条数据
|
||||
async AddOrModifyBookTask(bookTask) {
|
||||
try {
|
||||
await this.open()
|
||||
if (bookTask == null) {
|
||||
throw new Error('添加的小说任务不能为空')
|
||||
}
|
||||
if (bookTask.id == null) {
|
||||
// 新增
|
||||
if (bookTask.bookId == '' || bookTask.bookId == null) {
|
||||
throw new Error('小说ID不能为空')
|
||||
}
|
||||
|
||||
bookTask.id = uuidv4()
|
||||
|
||||
// 获取当前bookID对应的最大的no
|
||||
let maxNo = this.realm
|
||||
.objects('BookTask')
|
||||
.filtered('bookId = $0', bookTask.bookId)
|
||||
.max('no')
|
||||
bookTask.no = maxNo == null ? 1 : Number(maxNo) + 1
|
||||
bookTask.name = 'output_0000' + bookTask.no
|
||||
bookTask.status = BookTaskStatus.WAIT
|
||||
|
||||
bookTask.updateTime = new Date()
|
||||
bookTask.createTime = new Date()
|
||||
|
||||
this.realm.write(() => {
|
||||
this.realm.create('BookTask', bookTask)
|
||||
})
|
||||
return successMessage(bookTask, '新增小说任务成功', 'BookTaskService_AddOrModifyBookTask')
|
||||
} else {
|
||||
// 修改
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import Realm, { UpdateMode } from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { SoftwareModel } from '../../model/SoftWare/software.js'
|
||||
import { ComponentSize, SoftwareThemeType } from '../../../enum/softwareEnum.js'
|
||||
import { errorMessage, successMessage } from '../../../../main/generalTools.js'
|
||||
import { BaseSoftWareService } from './softwareBasic.js'
|
||||
import { isEmpty } from 'lodash'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
export class LoggerService extends BaseSoftWareService {
|
||||
static instance: LoggerService | null = null
|
||||
realm: Realm
|
||||
private constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前实例对象,为空则创建一个新的
|
||||
* @returns
|
||||
*/
|
||||
public static async getInstance() {
|
||||
if (LoggerService.instance === null) {
|
||||
LoggerService.instance = new LoggerService()
|
||||
await super.getInstance()
|
||||
}
|
||||
return LoggerService.instance
|
||||
}
|
||||
|
||||
// 添加一条日志信息
|
||||
async AddLogger(logger) {
|
||||
try {
|
||||
await this.open()
|
||||
// 判断数据是不是存在 bookId,bookTaskId,type,status,content
|
||||
if (
|
||||
isEmpty(logger.bookId) ||
|
||||
isEmpty(logger.bookTaskId) ||
|
||||
isEmpty(logger.type) ||
|
||||
isEmpty(logger.status) ||
|
||||
isEmpty(logger.content)
|
||||
) {
|
||||
throw new Error('新增日志信息到数据库失败,数据不完整,缺少必要字段')
|
||||
}
|
||||
|
||||
logger.id = uuidv4()
|
||||
logger.date = new Date()
|
||||
this.realm.write(() => {
|
||||
this.realm.create('Logger', logger)
|
||||
})
|
||||
return successMessage(logger, '新增日志信息成功', 'LoggerService_AddLogger')
|
||||
} catch (error) {
|
||||
return errorMessage(
|
||||
'新增日志信息失败,错误信息如下:' + error.toString(),
|
||||
'LoggerService_AddLogger'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 删除日志信息 (删除指定日期之前的)
|
||||
async DeleteLogger(date) {
|
||||
try {
|
||||
await this.open()
|
||||
this.realm.write(() => {
|
||||
// 删除十五天之前的日志数据
|
||||
const currentDate = new Date()
|
||||
currentDate.setDate(currentDate.getDate() - 5)
|
||||
|
||||
let logger = this.realm.objects('Logger').filtered('date < $0', currentDate)
|
||||
this.realm.delete(logger)
|
||||
})
|
||||
return successMessage(null, '删除日志信息成功', 'LoggerService_DeleteLogger')
|
||||
} catch (error) {
|
||||
return errorMessage(
|
||||
'删除日志信息失败,错误信息如下:' + error.toString(),
|
||||
'LoggerService_DeleteLogger'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,611 @@
|
||||
import Realm, { UpdateMode } from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService'
|
||||
import { define } from '../../../define.js'
|
||||
import { SoftwareModel } from '../../model/SoftWare/software.js'
|
||||
import { ComponentSize, SoftwareThemeType } from '../../../enum/softwareEnum.js'
|
||||
import { errorMessage, successMessage } from '../../../../main/generalTools.js'
|
||||
import { BaseSoftWareService } from './softwareBasic.js'
|
||||
import { isEmpty, isNumber } from 'lodash'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
import { version } from '../../../../../package.json'
|
||||
|
||||
export class MJSettingService extends BaseSoftWareService {
|
||||
static instance: MJSettingService | null = null
|
||||
realm: Realm
|
||||
private constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前实例对象,为空则创建一个新的
|
||||
* @returns
|
||||
*/
|
||||
public static async getInstance() {
|
||||
if (MJSettingService.instance === null) {
|
||||
MJSettingService.instance = new MJSettingService()
|
||||
await super.getInstance()
|
||||
}
|
||||
await MJSettingService.instance.open()
|
||||
return MJSettingService.instance
|
||||
}
|
||||
|
||||
//#region 览器模式的MJ设置
|
||||
|
||||
/**
|
||||
* 查询对应的浏览器的MJ设置
|
||||
* @param browserQuery 查询条件 Id ,null 返回全部
|
||||
*/
|
||||
GetBrowserMJSetting(browserQuery) {
|
||||
try {
|
||||
let browserMjSettings = this.realm.objects('BrowserMJ')
|
||||
|
||||
if (browserQuery?.id) {
|
||||
browserMjSettings = this.realm.objects('BrowserMJ').filtered('id = $0', browserQuery.id)
|
||||
}
|
||||
|
||||
let resBrowserMj = Array.from(browserMjSettings).map((browserMj) => {
|
||||
return {
|
||||
...browserMj
|
||||
}
|
||||
})
|
||||
|
||||
return successMessage(
|
||||
resBrowserMj,
|
||||
'获取浏览器配置成功',
|
||||
'MJSettingService_GetBrowserMJSetting'
|
||||
)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加浏览器相关的MJ设置
|
||||
* @param browserMj 浏览器的MJ设置对象
|
||||
* @returns
|
||||
*/
|
||||
AddBrowserMJSetting(browserMj) {
|
||||
try {
|
||||
if (isEmpty(browserMj.serviceId) || isEmpty(browserMj.channelId)) {
|
||||
throw new Error('服务器ID和频道ID必填')
|
||||
}
|
||||
if (isEmpty(browserMj.token) || isEmpty(browserMj.userAgent)) {
|
||||
throw new Error('用户Agent和token必填')
|
||||
}
|
||||
browserMj.id = uuidv4()
|
||||
browserMj.createTime = new Date()
|
||||
browserMj.updateTime = new Date()
|
||||
browserMj.version = version
|
||||
browserMj.userAgentCustom = false
|
||||
if (this.realm.isInTransaction) {
|
||||
this.realm.create('BrowserMJ', browserMj)
|
||||
} else {
|
||||
this.realm.write(() => {
|
||||
this.realm.create('BrowserMJ', browserMj)
|
||||
})
|
||||
}
|
||||
return successMessage(
|
||||
browserMj,
|
||||
'新增MJ浏览器模式配置成功',
|
||||
'MJSettingService_AddBrowserMJSetting'
|
||||
)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新浏览器的MJ设置
|
||||
* @param browserMj
|
||||
*/
|
||||
UpdateBrowserMJSetting(browserMj) {
|
||||
try {
|
||||
if (isEmpty(browserMj.id)) {
|
||||
throw new Error('更改浏览器模式配置,ID不能为空')
|
||||
}
|
||||
|
||||
if (
|
||||
isEmpty(browserMj.serviceId) ||
|
||||
isEmpty(browserMj.channelId) ||
|
||||
isEmpty(browserMj.token)
|
||||
) {
|
||||
throw new Error('更改浏览器配置,服务器ID,频道ID,Token不能为空')
|
||||
}
|
||||
|
||||
// 判断是不是有数据
|
||||
let browserMjRes = this.realm.objects('BrowserMJ').filtered('id = $0', browserMj.id)
|
||||
if (browserMjRes.length <= 0) {
|
||||
throw new Error('没有找到对应的浏览器配置信息')
|
||||
}
|
||||
|
||||
browserMj.updateTime = new Date()
|
||||
browserMj.version = version
|
||||
if (this.realm.isInTransaction) {
|
||||
this.realm.create('BrowserMJ', browserMj, UpdateMode.Modified)
|
||||
} else {
|
||||
this.realm.write(() => {
|
||||
this.realm.create('BrowserMJ', browserMj, UpdateMode.Modified)
|
||||
})
|
||||
}
|
||||
|
||||
return successMessage(
|
||||
browserMj,
|
||||
'修改浏览器模式配置成功',
|
||||
'MJSettingService_UpdateBrowserMJSetting'
|
||||
)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region API 模式的相关配置
|
||||
|
||||
/**
|
||||
* 获取API配置信息
|
||||
* @param apiQuery 查询条件 Id ,null 返回全部
|
||||
* @returns
|
||||
*/
|
||||
GetAPIMjSetting(apiQuery) {
|
||||
try {
|
||||
let apiMjSettings = this.realm.objects('APIMj')
|
||||
|
||||
if (apiQuery?.id) {
|
||||
apiMjSettings = this.realm.objects('APIMj').filtered('id = $0', apiQuery.id)
|
||||
}
|
||||
|
||||
let resApiMj = Array.from(apiMjSettings).map((apiMj) => {
|
||||
return {
|
||||
...apiMj
|
||||
}
|
||||
})
|
||||
|
||||
return successMessage(resApiMj, '获取API配置成功', 'MJSettingService_GetAPIMjSetting')
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加API模式的配置
|
||||
* @param apiMj API的配置信息
|
||||
*/
|
||||
AddAPIMjSetting(apiMj) {
|
||||
try {
|
||||
if (isEmpty(apiMj.mjApiUrl) || isEmpty(apiMj.mjSpeed) || isEmpty(apiMj.apiKey)) {
|
||||
throw new Error('请求的API URL,对应的API Key,请求模式这些必填')
|
||||
}
|
||||
|
||||
apiMj.id = uuidv4()
|
||||
apiMj.createTime = new Date()
|
||||
apiMj.updateTime = new Date()
|
||||
apiMj.version = version
|
||||
if (this.realm.isInTransaction) {
|
||||
this.realm.create('APIMj', apiMj)
|
||||
} else {
|
||||
this.realm.write(() => {
|
||||
this.realm.create('APIMj', apiMj)
|
||||
})
|
||||
}
|
||||
return successMessage(apiMj, '添加API设置成功', 'MJSettingService_AddAPIMjSetting')
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改APIMJ的配置信息
|
||||
* @param apiSetting
|
||||
*/
|
||||
UpdateAPIMJSetting(apiSetting) {
|
||||
try {
|
||||
if (apiSetting.id == null) {
|
||||
throw new Error('修改API配置数据,ID必填')
|
||||
}
|
||||
|
||||
// 判断必填的数据是不是为空
|
||||
if (
|
||||
isEmpty(apiSetting.mjApiUrl) ||
|
||||
isEmpty(apiSetting.mjSpeed) ||
|
||||
isEmpty(apiSetting.apiKey)
|
||||
) {
|
||||
throw new Error('请求的API URL,对应的API Key,请求模式这些必填')
|
||||
}
|
||||
|
||||
// 判断对应的ID是不是存在
|
||||
let apiSettingRes = this.realm.objects('APIMj').filtered('id = $0', apiSetting.id)
|
||||
if (apiSettingRes.length <= 0) {
|
||||
throw new Error('没有找到对应的API配置信息')
|
||||
}
|
||||
apiSetting.updateTime = new Date()
|
||||
apiSetting.version = version
|
||||
if (this.realm.isInTransaction) {
|
||||
this.realm.create('APIMj', apiSetting, UpdateMode.Modified)
|
||||
} else {
|
||||
this.realm.write(() => {
|
||||
this.realm.create('APIMj', apiSetting, UpdateMode.Modified)
|
||||
})
|
||||
}
|
||||
return successMessage(apiSetting, '修改API设置成功', 'MJSettingService_UpdateAPIMJSetting')
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 代理模式的相关配置
|
||||
|
||||
/**
|
||||
* 查询代理模式的配置信息
|
||||
* @param remoteMjQuery 查询条件,id,null-返回全部
|
||||
*/
|
||||
GetRemoteMJSettings(remoteMjQuery) {
|
||||
try {
|
||||
let remoteMjSettings = this.realm.objects('RemoteMJ')
|
||||
|
||||
if (remoteMjQuery?.id) {
|
||||
remoteMjSettings = this.realm.objects('RemoteMJ').filtered('id = $0', remoteMjQuery.id)
|
||||
}
|
||||
|
||||
let resRemoteMj = Array.from(remoteMjSettings).map((remoteMj) => {
|
||||
return {
|
||||
...remoteMj
|
||||
}
|
||||
})
|
||||
|
||||
return successMessage(
|
||||
resRemoteMj,
|
||||
'获取代理模式配置成功',
|
||||
'MJSettingService_GetRemoteMjSettings'
|
||||
)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加代理API配置
|
||||
* @param remoteMjSetting 代理API的设置对象
|
||||
* @returns
|
||||
*/
|
||||
AddRemoteMjSetting(remoteMjSetting) {
|
||||
try {
|
||||
if (
|
||||
isEmpty(remoteMjSetting.channelId) ||
|
||||
isEmpty(remoteMjSetting.guildId) ||
|
||||
isEmpty(remoteMjSetting.userToken)
|
||||
) {
|
||||
throw new Error('代理模式的频道ID,服务器ID,用户Token必填')
|
||||
}
|
||||
|
||||
let defaultSetting = {
|
||||
coreSize: 3,
|
||||
mjBotChannelId: null,
|
||||
nijiBotChannelId: null,
|
||||
queueSize: 5,
|
||||
remark: global.machineId,
|
||||
remixAutoSubmit: false,
|
||||
timeoutMinutes: 6,
|
||||
userAgent:
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
|
||||
}
|
||||
// 覆盖
|
||||
remoteMjSetting = Object.assign(defaultSetting, remoteMjSetting)
|
||||
remoteMjSetting.id = uuidv4()
|
||||
remoteMjSetting.createTime = new Date()
|
||||
remoteMjSetting.updateTime = new Date()
|
||||
remoteMjSetting.version = version
|
||||
remoteMjSetting.remark = global.machineId
|
||||
|
||||
// 判断当前this.relam 是不是已经处于一个事务中
|
||||
if (this.realm.isInTransaction) {
|
||||
this.realm.create('RemoteMJ', remoteMjSetting)
|
||||
} else {
|
||||
this.realm.write(() => {
|
||||
this.realm.create('RemoteMJ', remoteMjSetting)
|
||||
})
|
||||
}
|
||||
|
||||
return successMessage(
|
||||
remoteMjSetting,
|
||||
'新增代理API配置成功',
|
||||
'MJSettingService_AddRemoteMjSetting'
|
||||
)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新代理模式的配置信息
|
||||
* @param remoteMjSetting
|
||||
*/
|
||||
UpdateRemoteMjSetting(remoteMjSetting) {
|
||||
try {
|
||||
if (isEmpty(remoteMjSetting.id)) {
|
||||
throw new Error('更改代理模式配置,ID不能为空')
|
||||
}
|
||||
if (
|
||||
isEmpty(remoteMjSetting.channelId) ||
|
||||
isEmpty(remoteMjSetting.guildId) ||
|
||||
isEmpty(remoteMjSetting.userToken)
|
||||
) {
|
||||
throw new Error('代理模式的账号ID,服务ID,频道ID,用户Token不能为空')
|
||||
}
|
||||
|
||||
if (
|
||||
remoteMjSetting.coreSize == null ||
|
||||
remoteMjSetting.queueSize == null ||
|
||||
remoteMjSetting.timeoutMinutes == null
|
||||
) {
|
||||
throw new Error('核心数量,队列数量,超时时间不能为空')
|
||||
}
|
||||
|
||||
let remoteMjSettingRes = this.realm
|
||||
.objects('RemoteMJ')
|
||||
.filtered('id = $0', remoteMjSetting.id)
|
||||
if (remoteMjSettingRes.length <= 0) {
|
||||
throw new Error('没有找到对应的代理模式配置信息')
|
||||
}
|
||||
|
||||
remoteMjSetting.updateTime = new Date()
|
||||
remoteMjSetting.version = version
|
||||
remoteMjSetting.remark = global.machineId
|
||||
|
||||
// 判断relam是不是在事务中
|
||||
if (this.realm.isInTransaction) {
|
||||
this.realm.create('RemoteMJ', remoteMjSetting, UpdateMode.Modified)
|
||||
} else {
|
||||
this.realm.write(() => {
|
||||
this.realm.create('RemoteMJ', remoteMjSetting, UpdateMode.Modified)
|
||||
})
|
||||
}
|
||||
|
||||
return successMessage(
|
||||
remoteMjSetting,
|
||||
'修改代理API配置成功',
|
||||
'MJSettingService_UpdateRemoteMjSetting'
|
||||
)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region MJ设置的基础设置
|
||||
|
||||
/**
|
||||
* 获取MJ的基础配置信息
|
||||
* @param mjSettingQuery 查询的条件 Id ,null 返回全部
|
||||
* @returns
|
||||
*/
|
||||
GetMjSetting(mjSettingQuery) {
|
||||
try {
|
||||
let mjSettings = this.realm.objects('MjSetting')
|
||||
|
||||
if (mjSettingQuery?.id) {
|
||||
mjSettings = this.realm.objects('MjSetting').filtered('id = $0', mjSettingQuery.id)
|
||||
}
|
||||
|
||||
let resMjSetting = Array.from(mjSettings).map((mjSetting) => {
|
||||
return {
|
||||
...mjSetting
|
||||
}
|
||||
})
|
||||
|
||||
return successMessage(resMjSetting, '获取MJ基础设置成功', 'MJSettingService_getMjSetting')
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加MJ的基础配置到数据库
|
||||
* @param mjSetting 添加的mj基础配置的对象
|
||||
* @returns
|
||||
*/
|
||||
AddMJSetting(mjSetting) {
|
||||
try {
|
||||
mjSetting.type = mjSetting.requestModel
|
||||
// 判断传入的必填数据是不是为空
|
||||
if (isEmpty(mjSetting.type) || isEmpty(mjSetting.requestModel)) {
|
||||
throw new Error('MJ设置的类型和请求模型不能为空')
|
||||
}
|
||||
|
||||
if (
|
||||
isEmpty(mjSetting.imageScale) ||
|
||||
isEmpty(mjSetting.imageModel) ||
|
||||
isEmpty(mjSetting.imageSuffix) ||
|
||||
isEmpty(mjSetting.selectRobot)
|
||||
) {
|
||||
throw new Error('MJ设置的图片比例、图片模型、生图后缀、选择机器人不能为空')
|
||||
}
|
||||
|
||||
mjSetting.id = uuidv4()
|
||||
mjSetting.createTime = new Date()
|
||||
mjSetting.updateTime = new Date()
|
||||
mjSetting.version = version
|
||||
|
||||
//TODO 还有一些判断条件,后面需要添加,比如选择生图模式,要保存对应的配置数据
|
||||
if (this.realm.isInTransaction) {
|
||||
this.realm.create('MjSetting', mjSetting)
|
||||
} else {
|
||||
this.realm.write(() => {
|
||||
this.realm.create('MjSetting', mjSetting)
|
||||
})
|
||||
}
|
||||
// 返回成功信息
|
||||
return successMessage(mjSetting, '添加MJ设置成功', 'MJSettingService_AddMJSetting')
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新MJ的基础配置信息
|
||||
* @param mjSetting
|
||||
*/
|
||||
UpdateMJSetting(mjSetting) {
|
||||
try {
|
||||
// 判断传入的数据中的必填数据是不是为空
|
||||
if (isEmpty(mjSetting.id)) {
|
||||
throw new Error('更改MJ基础设置,ID不能为空')
|
||||
}
|
||||
if (isEmpty(mjSetting.requestModel)) {
|
||||
throw new Error('MJ设置的请求模型不能为空')
|
||||
}
|
||||
mjSetting.type = mjSetting.requestModel
|
||||
if (
|
||||
isEmpty(mjSetting.selectRobot) ||
|
||||
isEmpty(mjSetting.imageScale) ||
|
||||
isEmpty(mjSetting.imageModel) ||
|
||||
isEmpty(mjSetting.imageSuffix)
|
||||
) {
|
||||
throw new Error('MJ设置的图片比例、图片模型、生图后缀、选择机器人不能为空')
|
||||
}
|
||||
|
||||
if (mjSetting.taskCount == null || mjSetting.spaceTime == null) {
|
||||
throw new Error('任务数量和间隔时间不能为空')
|
||||
}
|
||||
|
||||
// 判断指定ID的数据是不是存在
|
||||
let mjSettingRes = this.realm.objects('MjSetting').filtered('id = $0', mjSetting.id)
|
||||
if (mjSettingRes.length <= 0) {
|
||||
throw new Error('没有找到对应的MJ配置信息')
|
||||
}
|
||||
mjSetting.updateTime = new Date()
|
||||
mjSetting.version = version
|
||||
|
||||
if (this.realm.isInTransaction) {
|
||||
this.realm.create('MjSetting', mjSetting, UpdateMode.Modified)
|
||||
} else {
|
||||
this.realm.write(() => {
|
||||
this.realm.create('MjSetting', mjSetting, UpdateMode.Modified)
|
||||
})
|
||||
}
|
||||
// 返回成功信息
|
||||
return successMessage(mjSetting, '修改MJ配置信息成功', 'MJSettingService_UpdateMJSetting')
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region 组合操作,组合返回前端的数据信息
|
||||
|
||||
/**
|
||||
* 获取MJ的所有配置信息,包含所有的子项
|
||||
*/
|
||||
GetMJSettingTreeData() {
|
||||
try {
|
||||
// 获取MJ的基础配置信息
|
||||
let mjSettings = this.GetMjSetting(null)
|
||||
if (mjSettings.data.length <= 0) {
|
||||
throw new Error('没有找到MJ的配置信息,请先添加')
|
||||
}
|
||||
// 获取API的配置信息
|
||||
let apiSettings = this.GetAPIMjSetting(null)
|
||||
// 获取代理模式的配置信息
|
||||
let remoteSettings = this.GetRemoteMJSettings(null)
|
||||
|
||||
// 获取浏览器模式的配置信息
|
||||
let browserSettings = this.GetBrowserMJSetting(null)
|
||||
let mjSetting = mjSettings.data[0]
|
||||
mjSetting.apiSetting = apiSettings.data.length > 0 ? apiSettings.data[0] : null
|
||||
mjSetting.remoteSetting = remoteSettings.data.length > 0 ? remoteSettings.data[0] : null
|
||||
mjSetting.browserSetting = browserSettings.data.length > 0 ? browserSettings.data[0] : null
|
||||
|
||||
return successMessage(
|
||||
mjSetting,
|
||||
'获取MJ的所有配置信息成功',
|
||||
'MJSettingService_GetMJSettingTreeData'
|
||||
)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 组合操作,保存数据
|
||||
* @param mjSetting
|
||||
*/
|
||||
SaveMJSettingTreeData(mjSetting) {
|
||||
try {
|
||||
if (mjSetting == null) {
|
||||
throw new Error('保存的数据不能为空')
|
||||
}
|
||||
// 组合添加数据
|
||||
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) {
|
||||
let apiSettingRes: { code: number; data: any; message: any }
|
||||
if (isEmpty(apiSetting.id)) {
|
||||
// 新增
|
||||
apiSettingRes = this.AddAPIMjSetting(apiSetting)
|
||||
} else {
|
||||
// 修改
|
||||
apiSettingRes = this.UpdateAPIMJSetting(apiSetting)
|
||||
}
|
||||
if (apiSettingRes && apiSettingRes.code == 1) {
|
||||
mjSetting.apiSetting = apiSettingRes.data
|
||||
}
|
||||
}
|
||||
|
||||
// 判断浏览器模式的数据是不是存在
|
||||
let browserSetting = mjSetting.browserSetting ? mjSetting.browserSetting : null
|
||||
if (browserSetting != null) {
|
||||
let browserSettingRes: { code: number; data: any; message: any }
|
||||
if (isEmpty(browserSetting.id)) {
|
||||
// 新增
|
||||
browserSettingRes = this.AddBrowserMJSetting(browserSetting)
|
||||
} else {
|
||||
// 修改
|
||||
browserSettingRes = this.UpdateBrowserMJSetting(browserSetting)
|
||||
}
|
||||
if (browserSettingRes && browserSettingRes.code == 1) {
|
||||
mjSetting.browserSetting = browserSettingRes.data
|
||||
}
|
||||
}
|
||||
|
||||
// 添加MJ的基础配置信息
|
||||
let mjSettingRes: { code: number; data: any; message: any }
|
||||
if (isEmpty(mjSetting.id)) {
|
||||
// 新增
|
||||
mjSettingRes = this.AddMJSetting(mjSetting)
|
||||
} else {
|
||||
// 修改
|
||||
mjSettingRes = this.UpdateMJSetting(mjSetting)
|
||||
}
|
||||
if (mjSettingRes && mjSettingRes.code == 1) {
|
||||
mjSetting = mjSettingRes.data
|
||||
}
|
||||
})
|
||||
return successMessage(mjSetting, '添加信息成功', 'MJSettingService_SaveMJSettingTreeData')
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
import Realm from 'realm'
|
||||
import { BaseService } from '../baseService'
|
||||
import { define } from '../../../define'
|
||||
import path from 'path'
|
||||
import { ComponentSize, SoftwareThemeType } from '../../../enum/softwareEnum'
|
||||
import { SoftwareModel } from '../../model/SoftWare/software'
|
||||
import { LoggerModel } from '../../model/SoftWare/logger'
|
||||
import {
|
||||
APIMjModel,
|
||||
BrowserMJModel,
|
||||
MjSettingModel,
|
||||
RemoteMJModel
|
||||
} from '../../model/SoftWare/mjSetting'
|
||||
import { MJImageType, MJRobotType } from '../../../enum/mjEnum'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
let dbPath = path.resolve(define.db_path, 'software.realm')
|
||||
|
||||
// 版本迁移
|
||||
const migration = (oldRealm: Realm, newRealm: Realm) => {
|
||||
const oldBooks = oldRealm.objects('Software')
|
||||
const newBooks = newRealm.objects('Software')
|
||||
if (oldRealm.schemaVersion < 1) {
|
||||
}
|
||||
// 第二个版本
|
||||
if (oldRealm.schemaVersion < 2) {
|
||||
newRealm.write(() => {
|
||||
const newSoftwares = newRealm.objects('Software')
|
||||
for (let software of newSoftwares) {
|
||||
software.theme = SoftwareThemeType.LIGHT // 为新属性设置默认值
|
||||
}
|
||||
})
|
||||
}
|
||||
// 第三个版本
|
||||
if (oldRealm.schemaVersion < 3) {
|
||||
newRealm.write(() => {
|
||||
const newSoftwares = newRealm.objects('Software')
|
||||
for (let software of newSoftwares) {
|
||||
software.reverse_display_show = false
|
||||
software.reverse_show_book_striped = false
|
||||
software.reverse_data_table_size = ComponentSize.SMALL
|
||||
}
|
||||
})
|
||||
}
|
||||
if (oldRealm.schemaVersion < 6) {
|
||||
newRealm.write(() => {
|
||||
const newSoftwares = newRealm.objects('MjSetting')
|
||||
for (let software of newSoftwares) {
|
||||
software.requestModel = MJImageType.API_MJ
|
||||
}
|
||||
})
|
||||
}
|
||||
if (oldRealm.schemaVersion < 8) {
|
||||
newRealm.write(() => {
|
||||
const newSoftwares = newRealm.objects('MjSetting')
|
||||
for (let software of newSoftwares) {
|
||||
software.imageModel = MJRobotType.MJ
|
||||
}
|
||||
})
|
||||
}
|
||||
if (oldRealm.schemaVersion < 9) {
|
||||
newRealm.write(() => {
|
||||
const newSoftwares = newRealm.objects('MjSetting')
|
||||
for (let software of newSoftwares) {
|
||||
software.accountId = null
|
||||
}
|
||||
})
|
||||
}
|
||||
if (oldRealm.schemaVersion < 10) {
|
||||
newRealm.write(() => {
|
||||
const newSoftwares = newRealm.objects('MjSetting')
|
||||
for (let software of newSoftwares) {
|
||||
software.accountId = null
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class BaseSoftWareService extends BaseService {
|
||||
static instance: BaseSoftWareService | null = null
|
||||
protected realm: Realm
|
||||
dbpath: string
|
||||
|
||||
protected constructor() {
|
||||
super()
|
||||
this.dbpath = dbPath
|
||||
}
|
||||
|
||||
public static async getInstance() {
|
||||
if (BaseSoftWareService.instance === null) {
|
||||
BaseSoftWareService.instance = new BaseSoftWareService()
|
||||
await BaseSoftWareService.instance.open()
|
||||
}
|
||||
return BaseSoftWareService.instance
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建数据库连接,如果已经存在则直接返回
|
||||
* @param dbPath 数据库文件地址
|
||||
* @returns
|
||||
*/
|
||||
async open() {
|
||||
try {
|
||||
if (this.realm != null) return
|
||||
let config = {
|
||||
schema: [
|
||||
SoftwareModel,
|
||||
LoggerModel,
|
||||
BrowserMJModel,
|
||||
RemoteMJModel,
|
||||
APIMjModel,
|
||||
MjSettingModel
|
||||
],
|
||||
path: dbPath,
|
||||
schemaVersion: 10, // 当前版本号
|
||||
migration: migration
|
||||
}
|
||||
// 判断当前全局是不是又当前这个
|
||||
this.realm = await Realm.open(config)
|
||||
// 判断当前是不是有数据,一条都没有的话添加一条空白数据
|
||||
if (this.realm.objects('Software').length == 0) {
|
||||
this.realm.write(() => {
|
||||
this.realm.create('Software', {
|
||||
id: uuidv4(),
|
||||
theme: SoftwareThemeType.LIGHT // 默认是亮色主题
|
||||
})
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import Realm, { UpdateMode } from 'realm'
|
||||
import path from 'path'
|
||||
import { BaseService } from '../baseService.js'
|
||||
import { define } from '../../../define.js'
|
||||
import { SoftwareModel } from '../../model/SoftWare/software.js'
|
||||
import { ComponentSize, SoftwareThemeType } from '../../../enum/softwareEnum.js'
|
||||
import { successMessage } from '../../../../main/generalTools.js'
|
||||
import { BaseSoftWareService } from './softwareBasic.js'
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
|
||||
export class SoftwareService extends BaseSoftWareService {
|
||||
static instance: SoftwareService | null = null
|
||||
realm: Realm
|
||||
private constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前实例对象,为空则创建一个新的
|
||||
* @returns
|
||||
*/
|
||||
public static async getInstance() {
|
||||
if (SoftwareService.instance === null) {
|
||||
SoftwareService.instance = new SoftwareService()
|
||||
await super.getInstance()
|
||||
}
|
||||
return SoftwareService.instance
|
||||
}
|
||||
|
||||
// 修改数据库中行中的某个属性数据
|
||||
async UpdateSoftware(software) {
|
||||
try {
|
||||
await this.open()
|
||||
this.realm.write(() => {
|
||||
this.realm.create('Software', software, UpdateMode.Modified)
|
||||
})
|
||||
// 返回成功信息
|
||||
return successMessage(null, '修改软件配置信息成功', 'SoftwareService_UpdateSoftware')
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async AddSfotware(software) {
|
||||
try {
|
||||
await this.open()
|
||||
software.id = uuidv4()
|
||||
this.realm.write(() => {
|
||||
this.realm.create('Software', software)
|
||||
})
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 或软件基础配置信息
|
||||
*/
|
||||
async GetSoftwareData() {
|
||||
try {
|
||||
await this.open()
|
||||
let software = this.realm.objects('Software')
|
||||
return successMessage(
|
||||
software.toJSON(),
|
||||
'获取软件配置信息成功',
|
||||
'SoftwareService_GetSoftwareData'
|
||||
)
|
||||
} catch (error) {
|
||||
global.logger.error(
|
||||
'SoftwareService_GetSoftwareData',
|
||||
'获取软件的基础设置失败 ,错误信息如下:' + error.toString()
|
||||
)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default SoftwareService
|
||||
@@ -0,0 +1,36 @@
|
||||
// 定义抽象基类
|
||||
import Realm from 'realm'
|
||||
|
||||
export abstract class BaseService {
|
||||
protected realm: Realm | null = null
|
||||
// 抽象类的构造函数应该是protected,以防止外部直接实例化
|
||||
protected constructor() {
|
||||
// 构造函数逻辑,使用someValue进行初始化
|
||||
}
|
||||
|
||||
// 定义抽象方法,子类必须实现,打开数据库连接
|
||||
abstract open(dbPath: string): void
|
||||
|
||||
// 关闭数据库连接
|
||||
close(): void {
|
||||
// 关闭数据库的连接,防止内存溢出
|
||||
// 实现关闭数据库连接的逻辑
|
||||
if (this.realm != null) {
|
||||
console.log('Closing database connection')
|
||||
this.realm.close()
|
||||
this.realm = null // 清理引用,确保垃圾回收
|
||||
}
|
||||
}
|
||||
transaction(func: () => unknown): void {
|
||||
if (this.realm != null) {
|
||||
// 判断当前的relam是不是在一个事务中
|
||||
if (this.realm.isInTransaction) {
|
||||
func()
|
||||
} else {
|
||||
this.realm.write(() => {
|
||||
func()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,8 @@ if (!app.isPackaged) {
|
||||
img_base: path.join(__dirname, "../../resources/config/img_base.json"),
|
||||
video_config: path.join(__dirname, "../../resources/config/video_config.json"),
|
||||
scripts_path: path.join(__dirname, "../../resources/scripts"),
|
||||
db_path: path.join(__dirname, "../../resources/scripts/db"),
|
||||
project_path: path.join(__dirname, "../../project"),
|
||||
logger_path: path.join(__dirname, "../../resources/logger"),
|
||||
package_path: path.join(__dirname, "../../resources/package"),
|
||||
image_path: path.join(__dirname, "../../resources/image"),
|
||||
@@ -44,6 +46,8 @@ if (!app.isPackaged) {
|
||||
video_config: path.join(__dirname, "../../../resources/config/video_config.json"),
|
||||
img_base: path.join(__dirname, "../../../resources/config/img_base.json"),
|
||||
scripts_path: path.join(__dirname, "../../../resources/scripts"),
|
||||
db_path: path.join(__dirname, "../../../resources/scripts/db"),
|
||||
project_path: path.join(__dirname, "../../../project"),
|
||||
logger_path: path.join(__dirname, "../../../resources/logger"),
|
||||
package_path: path.join(__dirname, "../../../resources/package"),
|
||||
discordScript: path.join(__dirname, "../../../resources/scripts/discordScript.js"),
|
||||
@@ -67,6 +71,8 @@ if (!app.isPackaged) {
|
||||
}
|
||||
}
|
||||
|
||||
define["remotemj_api"] = "https://api.laitool.net/"
|
||||
define["API"] = "f85d39ed5a40fd09966f13f12b6cf0f0"
|
||||
export {
|
||||
define
|
||||
};
|
||||
@@ -189,17 +189,34 @@ export const DEFINE_STRING = {
|
||||
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"
|
||||
},
|
||||
SYSTEM: {
|
||||
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"
|
||||
},
|
||||
PROMPT: {
|
||||
GET_SORT_OPTIONS: "GET_SORT_OPTIONS",
|
||||
SAVE_PROMPT_SORT_DATA: "SAVE_PROMPT_SORT_DATA",
|
||||
GET_PROMPT_SORT_DATA: "GET_PROMPT_SORT_DATA"
|
||||
GET_PROMPT_SORT_DATA: "GET_PROMPT_SORT_DATA",
|
||||
OPEN_PROMPT_FILE_TXT: "OPEN_PROMPT_FILE_TXT"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
export enum BookType {
|
||||
// 原创
|
||||
ORIGINAL = 'original',
|
||||
// 反推
|
||||
SD_REVERSE = 'sd_reverse',
|
||||
// MJ 反推
|
||||
MJ_REVERSE = 'mj_reverse'
|
||||
}
|
||||
|
||||
export enum MJCategroy {
|
||||
// 本地MJ
|
||||
LOCAL_MJ = 'local_mj',
|
||||
// 代理MJ
|
||||
REMOTE_MJ = 'remote_mj',
|
||||
// 浏览器模式
|
||||
BROWSER_MJ = 'browser_mj',
|
||||
// API模式
|
||||
API_MJ = 'api_mj'
|
||||
}
|
||||
|
||||
export enum MJAction {
|
||||
// 生图
|
||||
IMAGINE = 'IMAGINE',
|
||||
|
||||
// 反推describe
|
||||
DESCRIBE = 'DESCRIBE'
|
||||
}
|
||||
|
||||
export enum BookBackTaskType {
|
||||
// 分镜计算
|
||||
STORYBOARD = 'storyboard',
|
||||
// 分割视频
|
||||
SPLIT = 'split',
|
||||
// 提取音频
|
||||
AUDIO = 'audio',
|
||||
// 识别字幕
|
||||
RECOGNIZE = 'recognize',
|
||||
// 抽帧
|
||||
FRAME = 'frame',
|
||||
// 反推
|
||||
REVERSE = 'reverse',
|
||||
// 生成图片
|
||||
IMAGE = 'image',
|
||||
// 高清
|
||||
HD = 'hd',
|
||||
// 合成视频
|
||||
COMPOSING = 'composing',
|
||||
// 推理
|
||||
INFERENCE = 'inference',
|
||||
// 翻译
|
||||
TRANSLATE = 'translate'
|
||||
}
|
||||
|
||||
export enum BookBackTaskStatus {
|
||||
// 等待
|
||||
WAIT = 'wait',
|
||||
// 运行中
|
||||
RUNNING = 'running',
|
||||
// 暂停
|
||||
PAUSE = 'pause',
|
||||
// 完成
|
||||
DONE = 'done',
|
||||
// 失败
|
||||
FAIL = 'fail'
|
||||
}
|
||||
|
||||
/**
|
||||
* 小说任务状态
|
||||
*/
|
||||
export enum BookTaskStatus {
|
||||
// 等待
|
||||
WAIT = 'wait',
|
||||
|
||||
// 分镜中
|
||||
STORYBOARD = 'storyboard',
|
||||
|
||||
// 分镜失败
|
||||
STORYBOARD_FAIL = 'storyboard_fail',
|
||||
|
||||
// 分镜完成,等待分割视频
|
||||
STORYBOARD_DONE = 'storyboard_done',
|
||||
|
||||
// 分割视频中
|
||||
SPLIT = 'split',
|
||||
|
||||
// 分割视频失败
|
||||
SPLIT_FAIL = 'split_fail',
|
||||
|
||||
// 分割视频完成,等待提取音频
|
||||
SPLIT_DONE = 'split_done',
|
||||
|
||||
// 提取音频中
|
||||
AUDIO = 'audio',
|
||||
|
||||
// 提取音频失败
|
||||
AUDIO_FAIL = 'audio_fail',
|
||||
|
||||
// 提取音频完成,等待识别字幕
|
||||
AUDIO_DONE = 'audio_done',
|
||||
|
||||
// 识别字幕中
|
||||
RECOGNIZE = 'recognize',
|
||||
|
||||
// 识别字幕失败
|
||||
RECOGNIZE_FAIL = 'recognize_fail',
|
||||
|
||||
// 识别字幕完成,等待抽帧
|
||||
RECOGNIZE_DONE = 'recognize_done',
|
||||
|
||||
// 抽帧中
|
||||
FRAME = 'frame',
|
||||
|
||||
// 抽帧完成,等待反推
|
||||
FRAME_DONE = 'frame_done',
|
||||
|
||||
// 抽帧失败
|
||||
FRAME_FAIL = 'frame_fail',
|
||||
|
||||
// 反推中
|
||||
REVERSE = 'reverse',
|
||||
|
||||
// 反推失败
|
||||
REVERSE_FAIL = 'reverse_fail',
|
||||
|
||||
// 反推完成,等待生成图片
|
||||
REVERSE_DONE = 'reverse_done',
|
||||
|
||||
// 生成图片中
|
||||
IMAGE = 'image',
|
||||
|
||||
// 图片生成完成,等待高清
|
||||
IMAGE_DONE = 'image_done',
|
||||
|
||||
// 图片生成失败
|
||||
IMAGE_FAIL = 'image_fail',
|
||||
|
||||
// 高清中
|
||||
HD = 'hd',
|
||||
|
||||
// 高清失败
|
||||
HD_FAIL = 'hd_fail',
|
||||
|
||||
// 高清完成,等待合成视频
|
||||
HD_DONE = 'hd_done',
|
||||
|
||||
// 合成视频中
|
||||
COMPOSING = 'composing',
|
||||
|
||||
// 合成视频完成
|
||||
COMPOSING_DONE = 'composing_done',
|
||||
|
||||
// 合成视频失败
|
||||
COMPOSING_FAIL = 'composing_fail'
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
export enum MJImageType {
|
||||
//本地MJ
|
||||
LOCAL_MJ = 'local_mj',
|
||||
|
||||
// 代理MJ
|
||||
REMOTE_MJ = 'remote_mj',
|
||||
|
||||
// 浏览器模式
|
||||
BROWSER_MJ = 'browser_mj',
|
||||
|
||||
// API模式
|
||||
API_MJ = 'api_mj'
|
||||
}
|
||||
|
||||
export enum MJRobotType {
|
||||
// MJ
|
||||
MJ = 'mj',
|
||||
|
||||
// niji
|
||||
NIJI = 'niji'
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
export enum SoftwareThemeType {
|
||||
// 暗
|
||||
DARK = 'dark',
|
||||
// 亮
|
||||
LIGHT = 'light'
|
||||
}
|
||||
|
||||
export enum ComponentSize {
|
||||
// 极小
|
||||
TINY = 'tiny',
|
||||
// 小
|
||||
SMALL = 'small',
|
||||
// 中
|
||||
MEDIUM = 'medium',
|
||||
// 大
|
||||
LARGE = 'large'
|
||||
}
|
||||
|
||||
export enum LoggerType {
|
||||
// SD反推
|
||||
SD_REVERSE = 'sd_reverse',
|
||||
// 原创
|
||||
ORIGINAL = 'original',
|
||||
// MJ反推
|
||||
MJ_REVERSE = 'mj_reverse'
|
||||
}
|
||||
|
||||
export enum LoggerStatus {
|
||||
// 成功
|
||||
SUCCESS = 'success',
|
||||
// 失败
|
||||
FAIL = 'fail',
|
||||
// 进行中
|
||||
DOING = 'doing'
|
||||
}
|
||||
|
||||
export enum OtherData {
|
||||
// 未知
|
||||
UNKNOWN = 'unknown',
|
||||
//默认
|
||||
DEFAULT = 'default'
|
||||
}
|
||||
@@ -6,7 +6,8 @@ export const LOGGER_DEFINE = {
|
||||
PROMPT: {
|
||||
GET_PROMPT_SORT_OPTIONS: "获取所有的排序选项",
|
||||
SAVE_PROMPT_SORT_DATA: "保存提示词排序的数据",
|
||||
GET_PROMPT_SORT_DATA: "获取提示词排序的数据"
|
||||
GET_PROMPT_SORT_DATA: "获取提示词排序的数据",
|
||||
OPEN_PROMPT_FILE_TXT: "获取提示词文件数据"
|
||||
},
|
||||
|
||||
GLOBAL: {
|
||||
|
||||
@@ -96,9 +96,9 @@ export class MjSetting {
|
||||
disable: true
|
||||
},
|
||||
{
|
||||
label: "代理MJ(待开发)",
|
||||
label: "代理MJ(token)",
|
||||
value: "remote_mj",
|
||||
disable: true
|
||||
disable: false
|
||||
},
|
||||
{
|
||||
label: "浏览器模式",
|
||||
|
||||
Reference in New Issue
Block a user