1. 添加英文配音

2. 修复聚合推文 任务没有文件不能删掉
3. 修复聚合推文删除所有的批次任务之后,不能再添加的问题
4. 添加版本更新通知,版本更新内容提醒
5. 添加MJ代理MJ账号设置,可以删除本地的账号和同步云端的账号(主要是状态和禁用原因)
This commit is contained in:
lq1405 2024-10-18 12:39:40 +08:00
parent 224ee47984
commit efa8d3b2a2
41 changed files with 1875 additions and 2963 deletions

1626
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "laitool", "name": "laitool",
"version": "3.1.5", "version": "3.1.6",
"description": "An AI tool for image processing, video processing, and other functions.", "description": "An AI tool for image processing, video processing, and other functions.",
"main": "./out/main/index.js", "main": "./out/main/index.js",
"author": "laitool.cn", "author": "laitool.cn",
@ -18,34 +18,29 @@
}, },
"dependencies": { "dependencies": {
"@alicloud/alimt20181012": "^1.2.0", "@alicloud/alimt20181012": "^1.2.0",
"@alicloud/openapi-client": "^0.4.12",
"@alicloud/tea-util": "^1.4.9",
"@electron-toolkit/preload": "^3.0.0", "@electron-toolkit/preload": "^3.0.0",
"@electron-toolkit/utils": "^3.0.0", "@electron-toolkit/utils": "^3.0.0",
"@vicons/ionicons5": "^0.12.0", "@vicons/ionicons5": "^0.12.0",
"@vitejs/plugin-vue-jsx": "^3.1.0", "@vitejs/plugin-vue-jsx": "^3.1.0",
"@volcengine/openapi": "^1.16.0", "@volcengine/openapi": "^1.16.0",
"7zip-min": "^1.4.4",
"artplayer": "^5.1.6", "artplayer": "^5.1.6",
"awesome-js": "^2.0.0", "awesome-js": "^2.0.0",
"axios": "^1.6.5", "axios": "^1.6.5",
"blob-to-buffer": "^1.2.9",
"compressing": "^1.10.0", "compressing": "^1.10.0",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"electron-store": "^9.0.0",
"electron-updater": "^6.1.7",
"fluent-ffmpeg": "^2.1.3", "fluent-ffmpeg": "^2.1.3",
"form-data": "^4.0.1",
"highlight.js": "^11.9.0", "highlight.js": "^11.9.0",
"install": "^0.13.0", "https-proxy-agent": "^7.0.5",
"jieba-js": "^1.0.2",
"jsdom": "^24.0.0", "jsdom": "^24.0.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"moment-timezone": "^0.5.45", "moment-timezone": "^0.5.45",
"music-metadata": "^7.14.0", "music-metadata": "^7.14.0",
"node-edge-tts": "^1.2.3", "node-edge-tts": "^1.2.3",
"node-gyp": "^10.2.0",
"node-machine-id": "^1.1.12", "node-machine-id": "^1.1.12",
"node-pre-gyp": "^0.17.0",
"npm": "^10.7.0", "npm": "^10.7.0",
"paddle": "^1.0.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"realm": "^12.9.0", "realm": "^12.9.0",
"sharp": "^0.33.2", "sharp": "^0.33.2",

Binary file not shown.

Binary file not shown.

View File

@ -2,10 +2,12 @@ import * as image from './image';
import * as common from './common'; import * as common from './common';
import * as file from './file' import * as file from './file'
import * as validate from './validate'; import * as validate from './validate';
import * as write from './write';
export { export {
image, image,
common, common,
file, file,
validate validate,
write
}; };

36
src/define/Tools/write.ts Normal file
View File

@ -0,0 +1,36 @@
import { isEmpty } from "lodash";
/**
*
*
* @param text -
* @param simpleSplitChar - 使
* @param specialSplitChat - 使
* @returns
*/
export function FormatWord(text: string, simpleSplitChar?: string, specialSplitChat?: string[],): string[] {
const defaultSimpleSplitChar = '。,“”‘’!?【】《》()…—:;.,\'\'""!?[]<>()...-:;';
const defaultSpecialSplitChat = ['.', '*', '?', '+', '^', '$', '[', ']', '(', ')', '{', '}', '|', '\\'];
if (isEmpty(simpleSplitChar)) {
simpleSplitChar = defaultSimpleSplitChar;
}
if (specialSplitChat == null || specialSplitChat.length === 0) {
specialSplitChat = defaultSpecialSplitChat;
}
Array.from(simpleSplitChar).forEach((item) => {
let regex: RegExp;
if (defaultSpecialSplitChat.includes(item)) {
regex = new RegExp('\\' + item, 'g')
} else {
regex = new RegExp(item, 'g')
}
text = text.replace(regex, '\n')
})
let wordArr = text.split('\n')
wordArr = wordArr.filter((item) => item != '' && item != null)
return wordArr
}

View File

@ -52,6 +52,7 @@ export class RemoteMJModel extends Realm.Object<RemoteMJModel> {
createTime: Date createTime: Date
updateTime: Date updateTime: Date
version: string version: string
blockMessage?: string
static schema: ObjectSchema = { static schema: ObjectSchema = {
name: 'RemoteMJ', name: 'RemoteMJ',
properties: { properties: {
@ -71,7 +72,8 @@ export class RemoteMJModel extends Realm.Object<RemoteMJModel> {
userToken: 'string', userToken: 'string',
createTime: 'date', createTime: 'date',
updateTime: 'date', updateTime: 'date',
version: 'string' version: 'string',
blockMessage: 'string?'
}, },
// 主键为_id // 主键为_id
primaryKey: 'id' primaryKey: 'id'

View File

@ -300,6 +300,9 @@ export class MJSettingService extends BaseSoftWareService {
if (remoteMjQuery?.id) { if (remoteMjQuery?.id) {
remoteMjSettings = this.realm.objects('RemoteMJ').filtered('id = $0', remoteMjQuery.id) remoteMjSettings = this.realm.objects('RemoteMJ').filtered('id = $0', remoteMjQuery.id)
} }
if (remoteMjQuery?.accountId) {
remoteMjSettings = this.realm.objects('RemoteMJ').filtered('accountId = $0', remoteMjQuery.accountId)
}
let resRemoteMj = Array.from(remoteMjSettings).map((remoteMj) => { let resRemoteMj = Array.from(remoteMjSettings).map((remoteMj) => {
return { return {
...remoteMj ...remoteMj
@ -348,9 +351,12 @@ export class MJSettingService extends BaseSoftWareService {
remoteMjSetting.createTime = new Date() remoteMjSetting.createTime = new Date()
remoteMjSetting.updateTime = new Date() remoteMjSetting.updateTime = new Date()
remoteMjSetting.version = version remoteMjSetting.version = version
remoteMjSetting.enable = true
remoteMjSetting.remark = global.machineId remoteMjSetting.remark = global.machineId
if (remoteMjSetting.hasOwnProperty('enable') == false) {
remoteMjSetting.enable = true
}
// 判断当前this.relam 是不是已经处于一个事务中 // 判断当前this.relam 是不是已经处于一个事务中
if (this.realm.isInTransaction) { if (this.realm.isInTransaction) {
this.realm.create('RemoteMJ', remoteMjSetting) this.realm.create('RemoteMJ', remoteMjSetting)

View File

@ -159,6 +159,14 @@ const migration = (oldRealm: Realm, newRealm: Realm) => {
if (oldRealm.schemaVersion < 22) { if (oldRealm.schemaVersion < 22) {
} }
if (oldRealm.schemaVersion < 23) {
newRealm.write(() => {
const newSoftwares = newRealm.objects('RemoteMJ')
for (let software of newSoftwares) {
software.blockMessage = ''
}
})
}
} }
export class BaseSoftWareService extends BaseService { export class BaseSoftWareService extends BaseService {
@ -198,7 +206,7 @@ export class BaseSoftWareService extends BaseService {
PresetModel PresetModel
], ],
path: dbPath, path: dbPath,
schemaVersion: 23, // 当前版本号 schemaVersion: 24, // 当前版本号
migration: migration migration: migration
} }
// 判断当前全局是不是又当前这个 // 判断当前全局是不是又当前这个

View File

@ -149,4 +149,8 @@ define['serverUrl'] = 'http://lapi.laitool.cn'
define['hkServerUrl'] = 'https://laitool.net/' define['hkServerUrl'] = 'https://laitool.net/'
define['bakServerUrl'] = 'https://laitool.net/' define['bakServerUrl'] = 'https://laitool.net/'
define['API'] = 'f85d39ed5a40fd09966f13f12b6cf0f0' define['API'] = 'f85d39ed5a40fd09966f13f12b6cf0f0'
define['lms'] =
process.env.NODE_ENV == 'development' ? 'https://localhost:44362' : 'https://lms.laitool.cn'
export { define } export { define }

View File

@ -1,9 +1,13 @@
import { SYSTEM } from "./systemDefineString" import { SYSTEM } from "./systemDefineString"
import TASK from "./taskDefineString" import TASK from "./taskDefineString"
import TTS from "./ttsDefineString"
import SETTING from "./settingDefineString"
export const DEFINE_STRING = { export const DEFINE_STRING = {
SYSTEM: SYSTEM, SYSTEM: SYSTEM,
TASK: TASK, TASK: TASK,
TTS: TTS,
SETTING: SETTING,
SHOW_GLOBAL_MESSAGE: "SHOW_GLOBAL_MESSAGE", SHOW_GLOBAL_MESSAGE: "SHOW_GLOBAL_MESSAGE",
SHOW_GLOBAL_MAIN_NOTIFICATION: 'SHOW_GLOBAL_MAIN_NOTIFICATION', SHOW_GLOBAL_MAIN_NOTIFICATION: 'SHOW_GLOBAL_MAIN_NOTIFICATION',
OPEN_DEV_TOOLS_PASSWORD: 'OPEN_DEV_TOOLS_PASSWORD', OPEN_DEV_TOOLS_PASSWORD: 'OPEN_DEV_TOOLS_PASSWORD',
@ -361,25 +365,6 @@ export const DEFINE_STRING = {
//#endregion //#endregion
}, },
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',
GET_WATER_MARK_SETTING: 'GET_WATER_MARK_SETTING',
SAVE_WATER_MARK_SETTING: 'SAVE_WATER_MARK_SETTING'
},
PROMPT: { PROMPT: {
GET_SORT_OPTIONS: 'GET_SORT_OPTIONS', GET_SORT_OPTIONS: 'GET_SORT_OPTIONS',
SAVE_PROMPT_SORT_DATA: 'SAVE_PROMPT_SORT_DATA', SAVE_PROMPT_SORT_DATA: 'SAVE_PROMPT_SORT_DATA',
@ -399,14 +384,6 @@ export const DEFINE_STRING = {
*/ */
GET_SCENE_PRESET: "GET_SCENE_PRESET" GET_SCENE_PRESET: "GET_SCENE_PRESET"
}, },
TTS: {
GET_TTS_CONFIG: 'GET_TTS_CONFIG',
GENERATE_AUDIO: 'GENERATE_AUDIO',
SAVE_TTS_CONFIG: 'SAVE_TTS_CONFIG',
GENERATE_SRT: "GENERATE_SRT",
GET_TTS_HISTORY_DATA: 'GET_TTS_HISTORY_DATA',
DELETE_TTS_HISTORY: 'DELETE_TTS_HISTORY',
},
WRITE: { WRITE: {
GET_WRITE_CONFIG: 'GET_WRITE_CONFIG', GET_WRITE_CONFIG: 'GET_WRITE_CONFIG',
SAVE_WRITE_CONFIG: 'SAVE_WRITE_CONFIG', SAVE_WRITE_CONFIG: 'SAVE_WRITE_CONFIG',

View File

@ -0,0 +1,23 @@
const 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',
GET_WATER_MARK_SETTING: 'GET_WATER_MARK_SETTING',
SAVE_WATER_MARK_SETTING: 'SAVE_WATER_MARK_SETTING',
/** 获取远程代理服务器的账号信息 */
GET_REMOTE_MJ_SETTINGS_FROM_SERVICE: "GET_REMOTE_MJ_SETTINGS_FROM_SERVICE"
}
export default SETTING

View File

@ -8,5 +8,7 @@ export const SYSTEM = {
/** 获取机器码 */ /** 获取机器码 */
GET_MACHINE_ID: "GET_MACHINE_ID", GET_MACHINE_ID: "GET_MACHINE_ID",
/** 检查机器码状态 */ /** 检查机器码状态 */
CHECK_MACHINE_STATUS : "CHECK_MACHINE_STATUS" CHECK_MACHINE_STATUS: "CHECK_MACHINE_STATUS",
/** 获取软件版本信息,更新信息,首页内容,公告等 */
GET_REMOTE_SYSTEM_INFORMATION: 'GET_REMOTE_SYSTEM_INFORMATION'
} }

View File

@ -0,0 +1,19 @@
/** TTS 相关的消息任务 */
const TTS = {
/** 获取TTS配置 */
GET_TTS_CONFIG: 'GET_TTS_CONFIG',
/** 生成配音 */
GENERATE_AUDIO: 'GENERATE_AUDIO',
/** 保存TTS配置 */
SAVE_TTS_CONFIG: 'SAVE_TTS_CONFIG',
/** 生成SRT文件 */
GENERATE_SRT: "GENERATE_SRT",
/** 获取TTS历史数据 */
GET_TTS_HISTORY_DATA: 'GET_TTS_HISTORY_DATA',
/** 删除TTS配音历史记录 */
DELETE_TTS_HISTORY: 'DELETE_TTS_HISTORY',
/** 获取TTS的Options */
GET_TTS_OPTIONS: 'GET_TTS_OPTIONS',
}
export default TTS;

View File

@ -11,6 +11,9 @@ export function GetTTSSelect() {
* edge-tts * edge-tts
*/ */
export function GetEdgeTTSRole() { export function GetEdgeTTSRole() {
//
return [ return [
{ {
value: 'zh-CN-XiaoxiaoNeural', value: 'zh-CN-XiaoxiaoNeural',

View File

@ -1,19 +1,19 @@
import { PromptIpc } from './promptIpc' import { PromptIpc } from './promptIpc'
import { SettingIpc } from './settingIpc.js' import { SettingIpc } from './settingIpc'
import { ImageGenerateIpc } from './imageGenerateIpc.js' import { ImageGenerateIpc } from './imageGenerateIpc'
import { WritingIpc } from './writingIpc.js' import { WritingIpc } from './writingIpc'
import { VideoGenerateIpc } from './videoGenerateIpc' import { VideoGenerateIpc } from './videoGenerateIpc'
import { TranslateIpc } from './translateIpc.js' import { TranslateIpc } from './translateIpc'
import { GptIpc } from './gptIpc.js' import { GptIpc } from './gptIpc'
import { MjIpc } from './mjIpc.js' import { MjIpc } from './mjIpc'
import { OriginalImageGenerateIpc } from './originalImageGenerateIpc' import { OriginalImageGenerateIpc } from './originalImageGenerateIpc'
import { SdIpc } from './sdIpc.js' import { SdIpc } from './sdIpc'
import { MainIpc } from './mainIpc.js' import { MainIpc } from './mainIpc'
import { GlobalIpc } from './globalIpc.js' import { GlobalIpc } from './globalIpc'
import { ImageIpc } from './imageIpc.js' import { ImageIpc } from './imageIpc'
import { SystemIpc } from './systemIpc' import { SystemIpc } from './systemIpc'
import { BookIpc } from './bookIpc' import { BookIpc } from './bookIpc'
import { TTSIpc } from './ttsIpc.js' import { TTSIpc } from './ttsIpc'
import { DBIpc } from './dbIpc' import { DBIpc } from './dbIpc'
import { PresetIpc } from './presetIpc' import { PresetIpc } from './presetIpc'
import { TaskIpc } from './taskIpc' import { TaskIpc } from './taskIpc'

View File

@ -206,7 +206,7 @@ async function SettingIpc() {
// 创建新的代理MJ信息 // 创建新的代理MJ信息
ipcMain.handle( ipcMain.handle(
DEFINE_STRING.SETTING.ADD_REMOTE_MJ_SETTING, DEFINE_STRING.SETTING.ADD_REMOTE_MJ_SETTING,
async (event, value) => await mjSetting.AddRemoteMJSetting(value) async (event, value, isRemote) => await mjSetting.AddRemoteMJSetting(value, isRemote)
) )
// 修改MJ账号并重连 // 修改MJ账号并重连
@ -218,7 +218,13 @@ async function SettingIpc() {
// 删除指定的MJ账号 // 删除指定的MJ账号
ipcMain.handle( ipcMain.handle(
DEFINE_STRING.SETTING.DELETE_REMOTE_MJ_SETTING, DEFINE_STRING.SETTING.DELETE_REMOTE_MJ_SETTING,
async (event, value) => await mjSetting.DeleteRemoteMJSetting(value) async (event, value, isRemote) => await mjSetting.DeleteRemoteMJSetting(value, isRemote)
)
/** 同步MJ远程代理服务器账户信息 */
ipcMain.handle(
DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS_FROM_SERVICE,
async (event) => await mjSetting.GetRemoteMJSettingsFromService()
) )
//#endregion //#endregion

View File

@ -26,5 +26,7 @@ function SystemIpc() {
ipcMain.handle(DEFINE_STRING.SYSTEM.GET_MACHINE_ID, async (event) => await systemInfo.GetMachineId()) ipcMain.handle(DEFINE_STRING.SYSTEM.GET_MACHINE_ID, async (event) => await systemInfo.GetMachineId())
/** 检查机器码状态 */ /** 检查机器码状态 */
ipcMain.handle(DEFINE_STRING.SYSTEM.CHECK_MACHINE_STATUS, async (event, value: string) => await systemInfo.CheckMachineStatus(value)) ipcMain.handle(DEFINE_STRING.SYSTEM.CHECK_MACHINE_STATUS, async (event, value: string) => await systemInfo.CheckMachineStatus(value))
/** 获取软件版本信息,更新信息,首页内容,公告等 */
ipcMain.handle(DEFINE_STRING.SYSTEM.GET_REMOTE_SYSTEM_INFORMATION, async (event) => await systemInfo.GetRemoteSystemInformation())
} }
export { SystemIpc } export { SystemIpc }

View File

@ -37,4 +37,7 @@ export function TTSIpc() {
DEFINE_STRING.TTS.GET_TTS_HISTORY_DATA, DEFINE_STRING.TTS.GET_TTS_HISTORY_DATA,
async (event, queryCondition) => await tts.GetTTSHistoryData(queryCondition) async (event, queryCondition) => await tts.GetTTSHistoryData(queryCondition)
) )
ipcMain.handle(
DEFINE_STRING.TTS.GET_TTS_OPTIONS, async (event, key) => await tts.GetTTSOptions(key))
} }

View File

@ -181,21 +181,25 @@ export class BookTask {
async AddNewBookTask(addNewBookTask: Book.AddBookTask): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> { async AddNewBookTask(addNewBookTask: Book.AddBookTask): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
try { try {
console.log(addNewBookTask) console.log(addNewBookTask)
if (isEmpty(addNewBookTask.selectBookId)) {
throw new Error("请选择对应的小说")
}
let bookTasks = [] as Book.SelectBookTask[]
let bookTaskDetail = [] as Book.SelectBookTaskDetail[]
let maxNo = await this.bookServiceBasic.GetMaxBookTaskNo(addNewBookTask.selectBookId)
for (let i = 0; i < addNewBookTask.count; i++) {
if (addNewBookTask.copyBookTask && !isEmpty(addNewBookTask.selectBookTask)) {
let bookTask = await this.bookServiceBasic.GetBookTaskDataById(addNewBookTask.selectBookTask) let bookTask = await this.bookServiceBasic.GetBookTaskDataById(addNewBookTask.selectBookTask)
let oldBookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({ let oldBookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailData({
bookTaskId: addNewBookTask.selectBookTask bookTaskId: addNewBookTask.selectBookTask
}) })
let bookTasks = [] as Book.SelectBookTask[]
let bookTaskDetail = [] as Book.SelectBookTaskDetail[]
let maxNo = await this.bookServiceBasic.GetMaxBookTaskNo(bookTask.bookId)
for (let i = 0; i < addNewBookTask.count; i++) {
if (addNewBookTask.copyBookTask) {
let { newBookTask, newBookTaskDetails } = await this.AddOneBookTask(bookTask, oldBookTaskDetail, addNewBookTask, maxNo + i) let { newBookTask, newBookTaskDetails } = await this.AddOneBookTask(bookTask, oldBookTaskDetail, addNewBookTask, maxNo + i)
bookTasks.push(newBookTask) bookTasks.push(newBookTask)
bookTaskDetail.push(...newBookTaskDetails) bookTaskDetail.push(...newBookTaskDetails)
} else { } else {
let newBookTask = this.CopyBookTaskBaseData({ bookId: bookTask.bookId }, addNewBookTask, maxNo + i) let newBookTask = this.CopyBookTaskBaseData({ bookId: addNewBookTask.selectBookId }, addNewBookTask, maxNo + i)
bookTasks.push(newBookTask); bookTasks.push(newBookTask);
} }
} }
@ -236,7 +240,9 @@ export class BookTask {
// 数据库删除完毕,看是删除对应的文件(主要是图片) // 数据库删除完毕,看是删除对应的文件(主要是图片)
let imageFolder = bookTask.imageFolder; let imageFolder = bookTask.imageFolder;
// 整个删掉在重建 // 整个删掉在重建
if (await CheckFileOrDirExist(imageFolder)) {
await DeleteFolderAllFile(imageFolder) await DeleteFolderAllFile(imageFolder)
}
await CheckFolderExistsOrCreate(imageFolder) await CheckFolderExistsOrCreate(imageFolder)
return successMessage(null, "重置小说数据成功", "BookTask_ReSetBookTask") return successMessage(null, "重置小说数据成功", "BookTask_ReSetBookTask")
} catch (error) { } catch (error) {
@ -255,7 +261,9 @@ export class BookTask {
// 先删除每个批次对应的数据,然后删除批次 // 先删除每个批次对应的数据,然后删除批次
await this.bookServiceBasic.DeleteBookTaskData(bookTaskId); await this.bookServiceBasic.DeleteBookTaskData(bookTaskId);
// 删除成功,直接把对应的出图文件夹删掉 // 删除成功,直接把对应的出图文件夹删掉
if (await CheckFileOrDirExist(imageFolder)) {
await DeleteFolderAllFile(imageFolder, true) await DeleteFolderAllFile(imageFolder, true)
}
return successMessage(null, "删除小说批次数据成功", "BookTask_DeleteBookTask") return successMessage(null, "删除小说批次数据成功", "BookTask_DeleteBookTask")
} catch (error) { } catch (error) {
return errorMessage('删除小说批次数据失败,错误信息如下' + error.toString(), "BookTask_DeleteBookTask"); return errorMessage('删除小说批次数据失败,错误信息如下' + error.toString(), "BookTask_DeleteBookTask");

View File

@ -6,10 +6,49 @@ import { version } from '../../../../package.json';
import { graphics } from 'systeminformation'; import { graphics } from 'systeminformation';
import { machineId } from 'node-machine-id'; import { machineId } from 'node-machine-id';
import axios from 'axios'; import axios from 'axios';
import { TaskManager } from '../task/taskManage';
export default class SystemInfo { export default class SystemInfo {
constructor() { } constructor() { }
/**
*
* @returns
*/
public async GetRemoteSystemInformation() {
try {
let remoteSysteminformationRes = await axios.get(define.lms + "/lms/LaitoolOptions/GetSimpleOptions/laitoolinfo");
if (remoteSysteminformationRes.data.code != 1) {
throw new Error(remoteSysteminformationRes.data.message)
}
let data = remoteSysteminformationRes.data.data;
let remoteVersionData = data.filter((item: any) => item.key == "LaitoolVersion");
let remoteVersion = remoteVersionData && remoteVersionData.length > 0 && remoteVersionData[0].value ? remoteVersionData[0].value : version;
let remoteHomePageData = data.filter((item: any) => item.key == "LaitoolHomePage");
let remoteHomePage = remoteHomePageData && remoteHomePageData.length > 0 && remoteHomePageData[0].value ? remoteHomePageData[0].value : '';
let remoteNoticeData = data.filter((item: any) => item.key == "LaitoolNotice");
let remoteNotice = remoteNoticeData && remoteNoticeData.length > 0 && remoteNoticeData[0].value ? remoteNoticeData[0].value : '';
let remoteUpdateContentData = data.filter((item: any) => item.key == "LaitoolUpdateContent");
let remoteUpdateContent = remoteUpdateContentData && remoteUpdateContentData.length > 0 && remoteUpdateContentData[0].value ? remoteUpdateContentData[0].value : '';
// 开始返回数据
return successMessage({
remoteVersion,
remoteHomePage,
remoteNotice,
remoteUpdateContent
}, '获取软件信息成功', 'SystemIpc_GET_SYSTEM_INFORMATION')
} catch (error) {
return errorMessage('获取软件信息错误,错误信息如下:' + error.message, 'SystemIpc_GET_SYSTEM_INFORMATION')
}
}
/** /**
* *
* @returns * @returns

View File

@ -7,11 +7,13 @@ import { isEmpty } from 'lodash'
import { ValidateJson } from '../../define/Tools/validate' import { ValidateJson } from '../../define/Tools/validate'
import { CheckFileOrDirExist, CheckFolderExistsOrCreate, DeleteFolderAllFile } from '../../define/Tools/file' import { CheckFileOrDirExist, CheckFolderExistsOrCreate, DeleteFolderAllFile } from '../../define/Tools/file'
import { TTSSelectModel } from '../../define/enum/tts' import { TTSSelectModel } from '../../define/enum/tts'
const { EdgeTTS } = require('node-edge-tts') import { EdgeTTS } from 'node-edge-tts'
const { v4: uuidv4 } = require('uuid') const { v4: uuidv4 } = require('uuid')
import { TTSService } from '../../define/db/tts/ttsService' import { TTSService } from '../../define/db/tts/ttsService'
import { tts } from '../../model/tts' import { tts } from '../../model/tts'
import { GeneralResponse } from '../../model/generalResponse' import { GeneralResponse } from '../../model/generalResponse'
import axios from 'axios'
import { GetEdgeTTSRole } from '../../define/tts/ttsDefine'
export class TTS { export class TTS {
softService: SoftwareService softService: SoftwareService
@ -34,6 +36,41 @@ export class TTS {
//#region 设置相关 //#region 设置相关
/**
* TTS配置选项
*
* @param {string} key - TTS配置的键值
* @returns {Promise<any>} TTS配置选项的Promise对象
*
* @throws {Error}
*
* @example
* ```typescript
* const options = await GetTTSOptions('someKey');
* console.log(options);
* ```
*/
async GetTTSOptions(key: string): Promise<GeneralResponse.SuccessItem | GeneralResponse.ErrorItem> {
try {
// 开始请求数据
let res = await axios.get(define.lms + '/lms/LaitoolOptions/GetSimpleOptions/ttsrole');
if (res.data.code != 1) {
throw new Error(res.data.message)
}
let data = res.data.data.filter(item => item.key == "EdgeTTsRoles")
if (data.length != 1) {
throw new Error("获取TTS角色配置失败")
}
if (isEmpty(data[0].value) || !ValidateJson(data[0].value)) {
return successMessage(GetEdgeTTSRole(), "获取远程配置失败,获取默认配音角色", "TTS_GetTTSCOnfig"); // 使用默认值
}
// 返回远程值
return successMessage(JSON.parse(data[0].value), '获取TTS配置成功', 'TTS_GetTTSCOnfig')
} catch (error) {
return errorMessage('获取TTS配置失败错误信息如下' + error.toString(), 'TTS_GetTTSCOnfig')
}
}
/** /**
* TTS设置 * TTS设置
*/ */
@ -166,7 +203,7 @@ export class TTS {
saveSubtitles: true, saveSubtitles: true,
pitch: `${edgeTTS.pitch}%`, pitch: `${edgeTTS.pitch}%`,
rate: `${edgeTTS.rate}%`, rate: `${edgeTTS.rate}%`,
volumn: `${edgeTTS.volumn}%` volume: `${edgeTTS.volumn}%`
}) })
let ttsRes = await tts.ttsPromise(text, mp3Path) let ttsRes = await tts.ttsPromise(text, mp3Path)
console.log(ttsRes) console.log(ttsRes)

View File

@ -11,7 +11,7 @@ import { AsyncQueue } from './quene'
import { DEFINE_STRING } from '../define/define_string' import { DEFINE_STRING } from '../define/define_string'
import { Tools } from './tools.js' import { Tools } from './tools.js'
import { ImageGenerate } from './ReverseManage/imageGenerate.js' import { ImageGenerate } from './ReverseManage/imageGenerate.js'
import { Setting } from './setting/setting.js' import { Setting } from './setting/setting'
import { has, isEmpty } from 'lodash' import { has, isEmpty } from 'lodash'
import { AutoSync } from './setting/autoSync.js' import { AutoSync } from './setting/autoSync.js'
import { TaskManager } from './Service/task/taskManage' import { TaskManager } from './Service/task/taskManage'
@ -95,6 +95,7 @@ async function createWindow(hash = 'ShowMessage', data, url = null) {
if (is.dev && process.env['ELECTRON_RENDERER_URL']) { if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] + '/#/' + hash) mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] + '/#/' + hash)
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
} else { } else {
if (hash != '') { if (hash != '') {
mainWindow.loadURL(`file://${path.join(__dirname, '../renderer/index.html')}#/${hash}`) mainWindow.loadURL(`file://${path.join(__dirname, '../renderer/index.html')}#/${hash}`)

View File

@ -8,6 +8,85 @@ const { v4: uuidv4 } = require('uuid')
export class MJSetting { export class MJSetting {
constructor() {} constructor() {}
/**
* 同步远程代理服务器中的MJ账号信息
*/
async GetRemoteMJSettingsFromService() {
try {
let url = define.remotemj_api + 'mj/account/query'
let res = await axios.post(
url,
{ remark: global.machineId, current: 1, pageNumber: 0, pageSize: 30 },
{ headers: { 'mj-api-secret': define.API } }
)
console.log('GetRemoteMJSettingsFromService', res)
if (res.status != 200) {
throw new Error(res.statusText)
}
if (!res.data || !res.data.content) {
throw new Error('远程服务器返回数据格式错误')
}
let content = res.data.content
let remoteMjSetting = await this.GetRemoteMJSettings()
if (remoteMjSetting.code == 0) {
throw new Error(remoteMjSetting.message)
}
let remoteIds = remoteMjSetting.data.map((item) => item.id)
for (let i = 0; i < remoteIds.length; i++) {
const element = remoteIds[i]
let deleteRes = await this.DeleteRemoteMJSetting(element, false)
if (deleteRes.code == 0) {
throw new Error(deleteRes.message)
}
}
if (content.length <= 0) {
// 没有数据,删除当前的所有的配置
} else {
// 先将所有的数据删除,再添加
for (let i = 0; i < content.length; i++) {
const element = content[i]
let addRes = await this.AddRemoteMJSetting(
{
channelId: element.channelId,
guildId: element.guildId,
userToken: element.userToken,
coreSize: element.coreSize,
queueSize: element.queueSize,
timeoutMinutes: element.timeoutMinutes,
userAgent: element.userAgent,
remark: element.remark,
enable: element.enable,
remixAutoSubmit: element.remixAutoSubmit,
mjBotChannelId: element.mjBotChannelId,
nijiBotChannelId: element.nijiBotChannelId,
accountId: element.id,
blockMessage: element.properties.disabledReason
},
false
)
if (addRes.code == 0) {
throw new Error(addRes.message)
}
}
}
return successMessage(
null,
'同步远程代理服务器中的MJ账号信息成功',
'MJSetting_GetRemoteMJSettingsFromService'
)
} catch (error) {
return errorMessage(
'同步远程代理服务器中的MJ账号信息错误详细错误信息如下' + error.toString(),
'MJSetting_GetRemoteMJSettingsFromService'
)
}
}
/** /**
* 获取MJ的基础设置数据 * 获取MJ的基础设置数据
*/ */
@ -94,7 +173,7 @@ export class MJSetting {
* 创建新的代理MJ信息 * 创建新的代理MJ信息
* @param {*} value * @param {*} value
*/ */
async AddRemoteMJSetting(value) { async AddRemoteMJSetting(value, isRemote) {
try { try {
// 先检查必填字段 // 先检查必填字段
console.log(value) console.log(value)
@ -134,7 +213,17 @@ export class MJSetting {
if (value.nijiBotChannelId) { if (value.nijiBotChannelId) {
remoteData.nijiBotChannelId = value.nijiBotChannelId remoteData.nijiBotChannelId = value.nijiBotChannelId
} }
if (value.accountId) {
remoteData.accountId = value.accountId
}
if (!isEmpty(value.blockMessage)) {
remoteData.blockMessage = value.blockMessage
}
if (value.hasOwnProperty('enable')) {
remoteData.enable = value.enable
}
if (isRemote) {
// 添加账号 // 添加账号
let accountRes = await axios.post(createUrl, remoteData, { let accountRes = await axios.post(createUrl, remoteData, {
headers: { headers: {
@ -150,6 +239,8 @@ export class MJSetting {
// 添加成功,修改数据,将数据返回 (服务器添加成功,开始在本地数据库添加)s // 添加成功,修改数据,将数据返回 (服务器添加成功,开始在本地数据库添加)s
let accountId = accountRes.data.result let accountId = accountRes.data.result
remoteData.accountId = accountId remoteData.accountId = accountId
}
remoteData.remixAutoSubmit = false remoteData.remixAutoSubmit = false
let _mjSettingService = await MJSettingService.getInstance() let _mjSettingService = await MJSettingService.getInstance()
@ -248,7 +339,7 @@ export class MJSetting {
* 删除指定的MJ账号 * 删除指定的MJ账号
* @param {*} id 数据库中存放的ID * @param {*} id 数据库中存放的ID
*/ */
async DeleteRemoteMJSetting(id) { async DeleteRemoteMJSetting(id, isRemote) {
try { try {
// 先检查必填字段 // 先检查必填字段
if (isEmpty(id)) { if (isEmpty(id)) {
@ -261,6 +352,7 @@ export class MJSetting {
throw new Error('没有要删除的数据') throw new Error('没有要删除的数据')
} }
if (isRemote) {
// 开始删除 // 开始删除
let deleteData = deleteConfig.data[0] let deleteData = deleteConfig.data[0]
let deleteUrl = define.remotemj_api + `mj/account/${deleteData.accountId}/delete` let deleteUrl = define.remotemj_api + `mj/account/${deleteData.accountId}/delete`
@ -272,13 +364,15 @@ export class MJSetting {
if (accountRes.data.code != 1) { if (accountRes.data.code != 1) {
throw new Error(accountRes.data.description) throw new Error(accountRes.data.description)
} }
}
// 删除本地数据
// 删除成功,修改数据 // 删除成功,修改数据
let save_res = _mjSetting.DeleteRemoteMJSetting(id) let save_res = _mjSetting.DeleteRemoteMJSetting(id)
if (save_res.code == 0) { if (save_res.code == 0) {
throw new Error(save_res.message) throw new Error(save_res.message)
} }
return successMessage(deleteData, 'MJ账号删除成功', 'MJSetting_DeleteRemoteMJSetting') return successMessage(null, 'MJ账号删除成功', 'MJSetting_DeleteRemoteMJSetting')
} catch (error) { } catch (error) {
return errorMessage( return errorMessage(
'删除指定的MJ账号错误详细错误信息如下' + error.toString(), '删除指定的MJ账号错误详细错误信息如下' + error.toString(),

1
src/model/book.d.ts vendored
View File

@ -84,6 +84,7 @@ declare namespace Book {
suffixPrompt?: string // 后缀提示词 suffixPrompt?: string // 后缀提示词
selectBookTask?: string // 选择的旧的小说任务 selectBookTask?: string // 选择的旧的小说任务
selectTaskDataCategory?: string[] // 选择复制的数据类型 selectTaskDataCategory?: string[] // 选择复制的数据类型
selectBookId: string // 选择的小说ID
} }
// 字幕相关 // 字幕相关

8
src/model/tts.d.ts vendored
View File

@ -27,4 +27,12 @@ declare namespace tts {
ttsCount: number ttsCount: number
} }
/** TTS 配音角色列表 */
type TTSRoleName = {
gender: string | "Male" | 'Female'
label: string
lang: string
value: string
}
} }

View File

@ -1,19 +1,19 @@
import { contextBridge, ipcRenderer } from 'electron' import { contextBridge, ipcRenderer } from 'electron'
import { electronAPI } from '@electron-toolkit/preload' import { electronAPI } from '@electron-toolkit/preload'
import { DEFINE_STRING } from '../define/define_string' import { DEFINE_STRING } from '../define/define_string'
import { discord } from './discord.js' import { discord } from './discord'
import { mj } from './mj.js' import { mj } from './mj'
import { sd } from './sd' import { sd } from './sd'
import { img } from './img.js' import { img } from './img'
import { system } from './system' import { system } from './system'
import { setting } from './setting.js' import { setting } from './setting'
import { prompt } from './prompt.js' import { prompt } from './prompt'
import { book } from './book' import { book } from './book'
import { tts } from './tts.js' import { tts } from './tts'
import { write } from './write.js' import { write } from './write'
import { gpt } from './gpt.js' import { gpt } from './gpt'
import { db } from './db' import { db } from './db'
import { translate } from './translate.js' import { translate } from './translate'
import { preset } from './preset' import { preset } from './preset'
import { task } from './task' import { task } from './task'
// Custom APIs for renderer // Custom APIs for renderer

View File

@ -50,16 +50,19 @@ const setting = {
await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS), await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS),
// 添加代理模式的MJ账号 // 添加代理模式的MJ账号
AddRemoteMJSetting: async (value) => AddRemoteMJSetting: async (value, isRemote) =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.ADD_REMOTE_MJ_SETTING, value), await ipcRenderer.invoke(DEFINE_STRING.SETTING.ADD_REMOTE_MJ_SETTING, value, isRemote),
// 修改并重连MJ的账号 // 修改并重连MJ的账号
UpdateRemoteMJSetting: async (value) => UpdateRemoteMJSetting: async (value) =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.UPDATE_REMOTE_MJ_SETTING, value), await ipcRenderer.invoke(DEFINE_STRING.SETTING.UPDATE_REMOTE_MJ_SETTING, value),
// 删除指定的MJ账号 // 删除指定的MJ账号
DeleteRemoteMJSetting: async (value) => DeleteRemoteMJSetting: async (value: string, isRemote: boolean) =>
await ipcRenderer.invoke(DEFINE_STRING.SETTING.DELETE_REMOTE_MJ_SETTING, value), await ipcRenderer.invoke(DEFINE_STRING.SETTING.DELETE_REMOTE_MJ_SETTING, value, isRemote),
/** 同步代理服务器的账号信息 */
GetRemoteMJSettingsFromService: async () => await ipcRenderer.invoke(DEFINE_STRING.SETTING.GET_REMOTE_MJ_SETTINGS_FROM_SERVICE),
//#endregion //#endregion

View File

@ -12,8 +12,9 @@ const system = {
/** 获取系统的机器码 */ /** 获取系统的机器码 */
GetMachineId: () => ipcRenderer.invoke(DEFINE_STRING.SYSTEM.GET_MACHINE_ID), GetMachineId: () => ipcRenderer.invoke(DEFINE_STRING.SYSTEM.GET_MACHINE_ID),
/** 检查机器码状态 */ /** 检查机器码状态 */
CheckMachineStatus: (value: string) => ipcRenderer.invoke(DEFINE_STRING.SYSTEM.CHECK_MACHINE_STATUS, value) CheckMachineStatus: (value: string) => ipcRenderer.invoke(DEFINE_STRING.SYSTEM.CHECK_MACHINE_STATUS, value),
/** 获取软件版本信息,更新信息,首页内容,公告等 */
GetRemoteSystemInformation : () => ipcRenderer.invoke(DEFINE_STRING.SYSTEM.GET_REMOTE_SYSTEM_INFORMATION)
} }
export { system } export { system }

View File

@ -20,6 +20,9 @@ const tts = {
// 获取生成音频的历史记录 // 获取生成音频的历史记录
GetTTSHistoryData: async (queryCondition) => GetTTSHistoryData: async (queryCondition) =>
await ipcRenderer.invoke(DEFINE_STRING.TTS.GET_TTS_HISTORY_DATA, queryCondition) await ipcRenderer.invoke(DEFINE_STRING.TTS.GET_TTS_HISTORY_DATA, queryCondition),
GetTTSOptions: async (key: string) => await ipcRenderer.invoke(DEFINE_STRING.TTS.GET_TTS_OPTIONS, key)
} }
export { tts } export { tts }

View File

@ -90,7 +90,8 @@ let creatObj = ref({
selectBookTask: undefined, selectBookTask: undefined,
selectTaskDataCategory: [], selectTaskDataCategory: [],
prefixPrompt: '', prefixPrompt: '',
suffixPrompt: '' suffixPrompt: '',
selectBookId: reverseManageStore.selectBook.id
}) })
let bookTaskOptions = ref([]) let bookTaskOptions = ref([])
let groupData = ref([ let groupData = ref([

View File

@ -33,10 +33,9 @@
</n-spin> </n-spin>
</template> </template>
<script> <script setup>
import { ref, h, onMounted, defineComponent, toRaw } from 'vue' import { ref, h, onMounted, defineComponent, toRaw } from 'vue'
import { RouterLink } from 'vue-router' import { RouterLink } from 'vue-router'
import { Layers } from '@vicons/ionicons5'
import { import {
useDialog, useDialog,
NMenu, NMenu,
@ -47,10 +46,6 @@ import {
NIcon, NIcon,
useNotification, useNotification,
useMessage, useMessage,
NSwitch,
NButton,
NFloatButton,
NBadge,
NSpin NSpin
} from 'naive-ui' } from 'naive-ui'
@ -65,7 +60,6 @@ import {
} from '@vicons/ionicons5' } from '@vicons/ionicons5'
import CheckMachineId from '../Components/CheckMachineId.vue' import CheckMachineId from '../Components/CheckMachineId.vue'
import { DEFINE_STRING } from '../../../../define/define_string' import { DEFINE_STRING } from '../../../../define/define_string'
import ShowMessage from './ShowMessage.vue'
import { MD5 } from 'crypto-js' import { MD5 } from 'crypto-js'
import InputDialogContent from '../Original/Components/InputDialogContent.vue' import InputDialogContent from '../Original/Components/InputDialogContent.vue'
import APIIcon from '../Icon/APIIcon.vue' import APIIcon from '../Icon/APIIcon.vue'
@ -75,36 +69,18 @@ import { useSystemStore } from '../../../../stores/system'
import { TimeDelay } from '../../../../define/Tools/time' import { TimeDelay } from '../../../../define/Tools/time'
import { BookBackTaskStatus } from '../../../../define/enum/bookEnum' import { BookBackTaskStatus } from '../../../../define/enum/bookEnum'
export default defineComponent({ let collapsed = ref(false)
components: { let dialog = useDialog()
NMenu, let machineRef = ref()
NSpace, let message = useMessage()
NLayout, let notification = useNotification()
NLayoutSider, let show = ref(true)
NLayoutContent, const systemStore = useSystemStore()
NIcon,
ShowMessage,
NSwitch,
NButton,
APIIcon,
NFloatButton,
NBadge,
Layers,
NSpin
},
setup() {
let collapsed = ref(false)
let dialog = useDialog()
let machineRef = ref()
let message = useMessage()
let notification = useNotification()
let show = ref(true)
const systemStore = useSystemStore()
let key_down_ref = ref(null) let key_down_ref = ref(null)
// //
function renderMenuIcon(option) { function renderMenuIcon(option) {
if (option.key === 'sheep-man') return true if (option.key === 'sheep-man') return true
if (option.key === 'food') return null if (option.key === 'food') return null
if (option.key == 'sdoriginal') return h(NIcon, null, { default: () => h(PaperPlaneOutline) }) if (option.key == 'sdoriginal') return h(NIcon, null, { default: () => h(PaperPlaneOutline) })
@ -112,8 +88,7 @@ export default defineComponent({
if (option.key == 'gptCopywriting') return h(NIcon, null, { default: () => h(BookOutline) }) if (option.key == 'gptCopywriting') return h(NIcon, null, { default: () => h(BookOutline) })
if (option.key == 'book_management') return h(NIcon, null, { default: () => h(GridOutline) }) if (option.key == 'book_management') return h(NIcon, null, { default: () => h(GridOutline) })
if (option.key == 'lai_api') return h(NIcon, null, { default: () => h(APIIcon) }) if (option.key == 'lai_api') return h(NIcon, null, { default: () => h(APIIcon) })
if (option.key == 'backward_matrix') if (option.key == 'backward_matrix') return h(NIcon, null, { default: () => h(DuplicateOutline) })
return h(NIcon, null, { default: () => h(DuplicateOutline) })
if (option.key == 'back_task') if (option.key == 'back_task')
return h( return h(
NIcon, NIcon,
@ -125,19 +100,20 @@ export default defineComponent({
{ default: () => h(BackTaskIcon) } { default: () => h(BackTaskIcon) }
) )
if (option.key == 'TTS_Services') return h(NIcon, null, { default: () => h(RadioOutline) }) if (option.key == 'TTS_Services') return h(NIcon, null, { default: () => h(RadioOutline) })
} }
//
async function StartBackTask(isGiveUp) { //
async function StartBackTask(isGiveUp) {
let startRes = await window.task.StartBackTask(isGiveUp) let startRes = await window.task.StartBackTask(isGiveUp)
if (startRes.code == 0) { if (startRes.code == 0) {
message.error(startRes.message) message.error(startRes.message)
} else { } else {
message.success(startRes.message) message.success(startRes.message)
} }
} }
/** 判断是不是还是后台任务,用户确认是不是丢弃 */ /** 判断是不是还是后台任务,用户确认是不是丢弃 */
async function CheckWaitTask() { async function CheckWaitTask() {
await TimeDelay(1000) await TimeDelay(1000)
let getWaitTaskCountRes = await window.task.GetAllStatusTaskCount([ let getWaitTaskCountRes = await window.task.GetAllStatusTaskCount([
BookBackTaskStatus.WAIT, BookBackTaskStatus.WAIT,
@ -169,10 +145,10 @@ export default defineComponent({
// //
await StartBackTask(true) await StartBackTask(true)
} }
} }
/** 校验机器码的逻辑 */ /** 校验机器码的逻辑 */
async function GetMachineStatus() { async function GetMachineStatus() {
try { try {
// //
const machineRes = await window.system.GetMachineId() const machineRes = await window.system.GetMachineId()
@ -230,9 +206,10 @@ export default defineComponent({
} finally { } finally {
show.value = false show.value = false
} }
} }
onMounted(async () => { /** 加载版本和GPU信息 */
async function GetViosionAndGpuMessage() {
// //
let res = await window.system.GetViosionAndGpuMessage() let res = await window.system.GetViosionAndGpuMessage()
console.log(res) console.log(res)
@ -241,6 +218,11 @@ export default defineComponent({
} else { } else {
message.success(res.message) message.success(res.message)
} }
}
onMounted(async () => {
//
await GetViosionAndGpuMessage()
// ctrl + alt + l // ctrl + alt + l
window.addEventListener('keydown', (e) => { window.addEventListener('keydown', (e) => {
@ -335,18 +317,19 @@ export default defineComponent({
} }
}) })
//
await GetMachineStatus() await GetMachineStatus()
window.api.getSettingDafultData(async (value) => { window.api.getSettingDafultData(async (value) => {
window.config = value window.config = value
}) })
}) })
function expandIcon(value) { function expandIcon(value) {
return h(NIcon, null, { default: () => h(CaretDownOutline) }) return h(NIcon, null, { default: () => h(CaretDownOutline) })
} }
const menuOptions = [ const menuOptions = [
{ {
label: () => label: () =>
h( h(
@ -613,13 +596,13 @@ export default defineComponent({
), ),
key: 'back_task' key: 'back_task'
} }
] ]
function renderIcon(icon) { function renderIcon(icon) {
return () => h(NIcon, null, { default: () => h(icon) }) return () => h(NIcon, null, { default: () => h(icon) })
} }
function OpneBackTask() { function OpneBackTask() {
let dialogWidth = window.innerWidth * 0.8 let dialogWidth = window.innerWidth * 0.8
let dialogHeight = window.innerHeight * 0.95 let dialogHeight = window.innerHeight * 0.95
dialog.create({ dialog.create({
@ -630,17 +613,5 @@ export default defineComponent({
style: `width : ${dialogWidth}px; height : ${dialogHeight}px`, style: `width : ${dialogWidth}px; height : ${dialogHeight}px`,
maskClosable: false maskClosable: false
}) })
} }
return {
renderMenuIcon,
menuOptions,
expandIcon,
OpneBackTask,
collapsed,
show,
systemStore
}
}
})
</script> </script>

View File

@ -1,44 +1,77 @@
<template> <template>
<div style="width: 100%; height: auto;"> <div style="width: 100%; height: 100%">
<!-- <div style="display: flex; justify-content: center;"> <div
<n-image width="200" height="250" src="http://qiniuyun.upsurging.xyz/LAI/1280X1280.PNG" preview-disabled /> id="showmessage"
<n-image width="250" style="margin-left: 100px;" style="font-size: 15px; display: flex; justify-content: center; width: 100%; height: 100%"
src="http://qiniuyun.upsurging.xyz/LAI/%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20240427225845.png" ></div>
preview-disabled />
</div> -->
<div style="font-size: 15px ;display: flex; justify-content: center;">
<div id="showmessage"></div>
</div>
</div> </div>
</template> </template>
<script> <script setup>
import { ref, h, onMounted, defineComponent, onUnmounted, toRaw } from "vue" import { onMounted } from 'vue'
import { NImage, useMessage } from "naive-ui"; import { useMessage, useNotification } from 'naive-ui'
import { DEFINE_STRING } from "../../../../define/define_string"; import { version } from '../../../../../package.json'
import { isEmpty } from 'lodash'
export default defineComponent({ let message = useMessage()
components: { const notification = useNotification()
NImage
}, async function GetRemoteSystemInformation() {
setup() { let res = await window.system.GetRemoteSystemInformation()
onMounted(async () => { if (res.code == 0) {
await window.api.GetShowMessage((value) => { message.error(res.message)
if (value.code == 0) { return
return;
} }
let parser = new DOMParser();
let html = parser.parseFromString(value.data, 'text/html');
let div = document.getElementById("showmessage");
div.innerHTML = value.data.shareInfo.note_list[0].html_content if (!isEmpty(res.data.remoteHomePage)) {
const showMessageDiv = document.getElementById('showmessage')
const remoteHomePage = res.data.remoteHomePage
if (remoteHomePage.startsWith('http://') || remoteHomePage.startsWith('https://')) {
const iframe = document.createElement('iframe')
iframe.src = remoteHomePage
iframe.style.width = '100%'
iframe.style.border = 'none'
iframe.style.padding = '0'
iframe.style.height = '98vh' // Adjust the height as needed
showMessageDiv.innerHTML = ''
showMessageDiv.appendChild(iframe)
} else {
showMessageDiv.innerHTML = remoteHomePage
}
}
//
if (res.data.remoteVersion > version) {
notification.warning({
title: '更新提醒!',
content: `当前版本为 ${version} ,最新版本为 ${res.data.remoteVersion} ,请及时更新!`,
keepAliveOnHover: true
}) })
}
//
if (res.data.remoteVersion > version && !isEmpty(res.data.remoteUpdateContent)) {
notification.info({
title: '更新内容!',
content: res.data.remoteUpdateContent,
keepAliveOnHover: true
}) })
return {
}
} }
}
onMounted(async () => {
//
await GetRemoteSystemInformation()
// await window.api.GetShowMessage((value) => {
// if (value.code == 0) {
// return
// }
// let parser = new DOMParser()
// let html = parser.parseFromString(value.data, 'text/html')
// let div = document.getElementById('showmessage')
// div.innerHTML = value.data.shareInfo.note_list[0].html_content
// })
}) })
</script> </script>

View File

@ -1,129 +1,67 @@
<template> <template>
<n-spin :show="spinning">
<div id="AddMultiRemoteMj" style="overflow-y: auto"> <div id="AddMultiRemoteMj" style="overflow-y: auto">
<div style="margin-bottom: 5px"> <div style="margin-bottom: 5px">
<n-button type="info" @click="ManageAccount(null)">新增账号</n-button> <n-button type="info" @click="ManageAccount(null)">新增账号</n-button>
<n-button type="info" style="margin-left: 10px" @click="GetRemoteMJSettingsFromService()"
>同步服务器帐号信息</n-button
>
</div> </div>
<n-data-table :data="remoteMjSetting" :columns="columns" :max-height="maxHeight"> <n-data-table :data="remoteMjSetting" :columns="columns" :max-height="maxHeight">
</n-data-table> </n-data-table>
</div> </div>
<template #description> 同步数据中 </template>
</n-spin>
</template> </template>
<script> <script setup>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch, h } from 'vue' import { ref, onMounted, h } from 'vue'
import { import { useMessage, NDataTable, NButton, useDialog, NTag, NSpin } from 'naive-ui'
useMessage,
NDataTable,
NButton,
NInput,
NInputNumber,
NForm,
NFormItem,
useDialog,
NTag
} from 'naive-ui'
import { useSettingStore } from '../../../../../stores/setting' import { useSettingStore } from '../../../../../stores/setting'
import ManageRemoteMjAccount from './ManageRemoteMjAccount.vue' import ManageRemoteMjAccount from './ManageRemoteMjAccount.vue'
import { isEmpty } from 'lodash' import { isEmpty } from 'lodash'
export default defineComponent({ let props = defineProps({
components: { height: {
NDataTable, type: Number,
NButton, default: 500
NInput, }
NInputNumber, })
NForm, let message = useMessage()
NFormItem, let dialog = useDialog()
NTag let maxHeight = ref(props.height - 150)
}, let remoteMjSetting = ref([])
props: ['height'], let settingStore = useSettingStore()
setup(props) { let spinning = ref(false)
let message = useMessage()
let dialog = useDialog()
let maxHeight = ref(props.height - 150)
let remoteMjSetting = ref([])
let settingStore = useSettingStore()
onMounted(async () => { async function GetRemoteMJSettingsFromService() {
document.getElementById('AddMultiRemoteMj').style.height = props.height - 60 + 'px' spinning.value = true
let remoteMjSettingRes = await window.setting.GetRemoteMJSettings() try {
let remoteMjSettingRes = await window.setting.GetRemoteMJSettingsFromService()
if (remoteMjSettingRes.code == 0) { if (remoteMjSettingRes.code == 0) {
message.error('获取代理MJ配置失败') message.error('获取代理MJ配置失败')
} else { return
remoteMjSetting.value = remoteMjSettingRes.data
} }
}) message.success('同步服务器帐号信息成功')
/**
* 添加和编辑账号
*/
async function ManageAccount(remote = null) {
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() let res = await window.setting.GetRemoteMJSettings()
if (remoteMjSettingRes.code == 0) { if (res.code == 0) {
message.error('获取代理MJ配置失败') message.error('获取代理MJ配置失败')
} else { } else {
remoteMjSetting.value = remoteMjSettingRes.data remoteMjSetting.value = res.data
}
settingStore.ResetActionRemoteMJ()
}
})
} }
/** remoteMjSetting.value = res.data
* 删除指定的账号
* @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 { spinning.value = false
remoteMjSetting, } catch (error) {
maxHeight, } finally {
ManageAccount, spinning.value = false
settingStore, }
columns: [ }
let columns = [
{ {
title: '服务器ID', title: '服务器ID',
key: 'guildId' key: 'guildId'
@ -159,6 +97,10 @@ export default defineComponent({
title: 'NIJI私信ID', title: 'NIJI私信ID',
key: 'nijiBotChannelId' key: 'nijiBotChannelId'
}, },
{
title: '禁用原因',
key: 'blockMessage'
},
{ {
title: '操作', title: '操作',
key: 'action', key: 'action',
@ -167,9 +109,9 @@ export default defineComponent({
h( h(
NButton, NButton,
{ {
size: 'small', size: 'tiny',
type: 'info', type: 'info',
style: 'margin-left: 5px', style: 'margin-left: 5px;margin-bottom: 5px',
onClick: () => ManageAccount(row) onClick: () => ManageAccount(row)
}, },
{ default: () => '编辑并同步' } { default: () => '编辑并同步' }
@ -177,18 +119,111 @@ export default defineComponent({
h( h(
NButton, NButton,
{ {
size: 'small', size: 'tiny',
type: 'error', type: 'error',
style: 'margin-left: 5px', style: 'margin-left: 5px;margin-bottom: 5px',
onClick: () => DeleteAccount(row) onClick: () => DeleteAccount(row, false)
}, },
{ default: () => '删除账号' } { default: () => '删除账号(本地)' }
),
h(
NButton,
{
size: 'tiny',
type: 'error',
style: 'margin-left: 5px;margin-bottom: 5px',
onClick: () => DeleteAccount(row, true)
},
{ default: () => '删除账号(服务器)' }
) )
]) ])
} }
} }
] ]
onMounted(async () => {
document.getElementById('AddMultiRemoteMj').style.height = props.height - 60 + 'px'
spinning.value = true
try {
let res = await window.setting.GetRemoteMJSettings()
console.log(res)
if (res.code == 0) {
message.error('获取代理MJ配置失败')
} else {
remoteMjSetting.value = res.data
} }
} catch (error) {
message.error('获取代理MJ配置失败: ' + error.toString())
} finally {
spinning.value = false
} }
}) })
/**
* 添加和编辑账号
*/
async function ManageAccount(remote = null) {
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, isRemote) {
dialog.warning({
title: '删除账号',
content: isRemote
? '确定删除该账号吗?会将代理模式的服务器的数据一起删除,请确认操作!'
: '确定删除账号信息?该操作只会删除本地的,并不会对代理服务器数据产生影响!',
positiveText: '确认',
negativeText: '取消',
onPositiveClick: async () => {
if (isEmpty(row.accountId)) {
message.error('删除账号失败,错误消息如下:' + '账号ID为空')
return
}
let deleteRes = await window.setting.DeleteRemoteMJSetting(row.id, isRemote)
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
}
}
})
}
</script> </script>

View File

@ -158,7 +158,7 @@ export default defineComponent({
message.success('更新账号成功') message.success('更新账号成功')
} else { } else {
// //
let res = await window.setting.AddRemoteMJSetting(toRaw(settingStore.actionRemoteMJ)) let res = await window.setting.AddRemoteMJSetting(toRaw(settingStore.actionRemoteMJ),true)
loading.value = false loading.value = false
if (res.code == 0) { if (res.code == 0) {
message.error('创建账号失败,错误消息如下:' + res.message) message.error('创建账号失败,错误消息如下:' + res.message)

View File

@ -100,7 +100,7 @@
</n-card> </n-card>
<n-card title="代理模式设置" hoverable style="margin-top: 10px; min-width: 850px"> <n-card title="代理模式设置" hoverable style="margin-top: 10px; min-width: 850px">
<n-button type="info" @click="AddMultiMjAccount">账号管理</n-button> <n-button type="info" @click="AddMultiMjAccount()">账号管理</n-button>
</n-card> </n-card>
<n-card title="浏览器模式设置" hoverable style="margin-top: 10px; min-width: 850px"> <n-card title="浏览器模式设置" hoverable style="margin-top: 10px; min-width: 850px">
@ -154,7 +154,7 @@
</div> </div>
</template> </template>
<script> <script setup>
import { defineComponent, ref, onMounted, computed, toRaw, h } from 'vue' import { defineComponent, ref, onMounted, computed, toRaw, h } from 'vue'
import { import {
NButton, NButton,
@ -178,28 +178,11 @@ import { Reload } from '@vicons/ionicons5'
import { isEmpty, max, min } from 'lodash' import { isEmpty, max, min } from 'lodash'
import { MJImageType } from '../../../../define/enum/mjEnum' import { MJImageType } from '../../../../define/enum/mjEnum'
import AddMultiRemoteMj from './Components/AddMultiRemoteMj.vue' import AddMultiRemoteMj from './Components/AddMultiRemoteMj.vue'
export default defineComponent({
components: { let message = useMessage()
NButton, let dialog = useDialog()
NDataTable, let sampleRef = ref(null)
NForm, let select_robot_options = ref([
NFormItem,
NInput,
NDivider,
NCheckbox,
NSelect,
NTooltip,
NIcon,
Reload,
NInputNumber,
NCard,
NSpin
},
setup() {
let message = useMessage()
let dialog = useDialog()
let sampleRef = ref(null)
let select_robot_options = ref([
{ {
label: 'MJ', label: 'MJ',
value: 'mj' value: 'mj'
@ -208,9 +191,9 @@ export default defineComponent({
label: 'NIJI', label: 'NIJI',
value: 'niji' value: 'niji'
} }
]) ])
let mj_speed_options = ref([ let mj_speed_options = ref([
{ {
label: 'RELAXED', label: 'RELAXED',
value: 'relaxed' value: 'relaxed'
@ -219,9 +202,9 @@ export default defineComponent({
label: 'FAST', label: 'FAST',
value: 'fast' value: 'fast'
} }
]) ])
let mjSetting = ref({ let mjSetting = ref({
id: null, id: null,
imageModel: null, imageModel: null,
imageScale: null, imageScale: null,
@ -264,15 +247,15 @@ export default defineComponent({
userAgent: null, userAgent: null,
userAgentCustom: false userAgentCustom: false
} }
}) })
let image_scale_options = ref([]) let image_scale_options = ref([])
let image_model_options = ref([]) let image_model_options = ref([])
let tmp_image_model_options = [] let tmp_image_model_options = []
let request_model_options = ref([]) let request_model_options = ref([])
let mj_api_options = ref([]) let mj_api_options = ref([])
let computedSuffix = () => { let computedSuffix = () => {
let text = image_model_options.value.findIndex((item) => { let text = image_model_options.value.findIndex((item) => {
return item.value == mjSetting.value.imageModel return item.value == mjSetting.value.imageModel
}) })
@ -285,11 +268,10 @@ export default defineComponent({
let dd = ` --${image_model_options.value[text].text} --ar ${image_scale_options.value[sc].text}` let dd = ` --${image_model_options.value[text].text} --ar ${image_scale_options.value[sc].text}`
mjSetting.value.imageSuffix = dd mjSetting.value.imageSuffix = dd
return dd return dd
} }
//
async function InitData() {
//
async function InitData() {
// //
let res = await window.setting.GetMJSettingTreeData() let res = await window.setting.GetMJSettingTreeData()
if (res.code == 0) { if (res.code == 0) {
@ -355,12 +337,11 @@ export default defineComponent({
mjSetting.value.apiSetting.mjApiUrl = mj_api_options.value[0].value mjSetting.value.apiSetting.mjApiUrl = mj_api_options.value[0].value
} }
}) })
} }
onMounted(async () => { onMounted(async () => {
// //
window.api.setEventListen([DEFINE_STRING.DISCORD.OPERATE_REFRASH_DISCORD_URL], (value) => { window.api.setEventListen([DEFINE_STRING.DISCORD.OPERATE_REFRASH_DISCORD_URL], (value) => {
if (value.code == 0) { if (value.code == 0) {
message.error(value.message) message.error(value.message)
return return
@ -385,32 +366,32 @@ export default defineComponent({
if (mjSetting.value.apiSetting.mjSpeed == null) { if (mjSetting.value.apiSetting.mjSpeed == null) {
mjSetting.value.apiSetting.mjSpeed = mj_speed_options.value[0].value mjSetting.value.apiSetting.mjSpeed = mj_speed_options.value[0].value
} }
}) })
/** /**
* 打开discord窗口 * 打开discord窗口
*/ */
async function OpenDiscordWindow() { async function OpenDiscordWindow() {
await window.api.OpenDiscordWindow((value) => { await window.api.OpenDiscordWindow((value) => {
if (value.code == 0) { if (value.code == 0) {
message.error(value.message) message.error(value.message)
return return
} }
}) })
} }
// //
let sampleRules = { let sampleRules = {
imageModel: [{ required: true, message: '请选择机器人模型', trigger: 'blur' }], imageModel: [{ required: true, message: '请选择机器人模型', trigger: 'blur' }],
imageScale: [{ required: true, message: '请选择生图尺寸', trigger: 'blur' }], imageScale: [{ required: true, message: '请选择生图尺寸', trigger: 'blur' }],
requestModel: [{ required: true, message: '请选择出图模式', trigger: 'blur' }], requestModel: [{ required: true, message: '请选择出图模式', trigger: 'blur' }],
selectRobot: [{ required: true, message: '请选择生图机器人', trigger: 'blur' }] selectRobot: [{ required: true, message: '请选择生图机器人', trigger: 'blur' }]
} }
/** /**
* 保存MJ配置 * 保存MJ配置
*/ */
async function SaveMjSetting(e) { async function SaveMjSetting(e) {
// //
e.preventDefault() e.preventDefault()
@ -480,12 +461,12 @@ export default defineComponent({
window.api.showGlobalMessageDialog({ code: 1, message: '添加成功' }) window.api.showGlobalMessageDialog({ code: 1, message: '添加成功' })
} }
}) })
} }
/** /**
* 更新选择的机器人时触发的方法 * 更新选择的机器人时触发的方法
*/ */
async function UpdateSelectRobot(value) { async function UpdateSelectRobot(value) {
// //
image_model_options.value = tmp_image_model_options.filter((item) => { image_model_options.value = tmp_image_model_options.filter((item) => {
return item.type == value return item.type == value
@ -503,12 +484,12 @@ export default defineComponent({
// //
mjSetting.value.imageSuffix = computedSuffix() mjSetting.value.imageSuffix = computedSuffix()
} }
/** /**
* 打开购买GPT的地址 * 打开购买GPT的地址
*/ */
async function openGptBuyUrl() { async function openGptBuyUrl() {
let tmp_gb = mj_api_options.value.filter( let tmp_gb = mj_api_options.value.filter(
(item) => item.value == mjSetting.value.apiSetting.mjApiUrl (item) => item.value == mjSetting.value.apiSetting.mjApiUrl
) )
@ -522,12 +503,12 @@ export default defineComponent({
} else { } else {
window.api.openGptBuyUrl(buy_url) window.api.openGptBuyUrl(buy_url)
} }
} }
/** /**
* 添加多个账号这样可以同时跑多个账号 * 添加多个账号这样可以同时跑多个账号
*/ */
async function AddMultiMjAccount() { async function AddMultiMjAccount() {
// //
let dW = window.innerWidth * 0.9 let dW = window.innerWidth * 0.9
let dH = window.innerHeight * 0.9 let dH = window.innerHeight * 0.9
@ -538,24 +519,5 @@ export default defineComponent({
style: `min-width : 600px; width : ${dW}px; height : ${dH}px; padding-right : 5px;`, style: `min-width : 600px; width : ${dW}px; height : ${dH}px; padding-right : 5px;`,
maskClosable: false maskClosable: false
}) })
} }
return {
OpenDiscordWindow,
mjSetting,
select_robot_options,
SaveMjSetting,
sampleRef,
image_scale_options,
image_model_options,
UpdateSelectRobot,
request_model_options,
mj_api_options,
mj_speed_options,
openGptBuyUrl,
sampleRules,
AddMultiMjAccount
}
}
})
</script> </script>

View File

@ -30,7 +30,7 @@
</div> </div>
</template> </template>
<script> <script setup>
import { ref, onMounted, defineComponent, watch, inject } from 'vue' import { ref, onMounted, defineComponent, watch, inject } from 'vue'
import { import {
useMessage, useMessage,
@ -47,42 +47,35 @@ import { GetEdgeTTSRole } from '../../../../define/tts/ttsDefine'
import { ReaderOutline } from '@vicons/ionicons5' import { ReaderOutline } from '@vicons/ionicons5'
import { useSettingStore } from '../../../../stores/setting' import { useSettingStore } from '../../../../stores/setting'
export default defineComponent({ let message = useMessage()
components: { let settingStore = useSettingStore()
NForm,
NCheckbox,
NFormItem,
NInputNumber,
NSelect,
NButton,
NIcon,
ReaderOutline,
NPopover
},
setup(props) {
let message = useMessage()
let settingStore = useSettingStore()
let roleOptions = ref([]) async function SwitchTTSOptions(key) {
onMounted(async () => { console.log('SwitchTTSOptions', key)
let ttsOptionsRes = await window.tts.GetTTSOptions(key)
console.log('SwitchTTSOptions', ttsOptionsRes)
if (ttsOptionsRes.code == 0) {
message.error(ttsOptionsRes.message)
} else {
roleOptions.value = ttsOptionsRes.data
}
console.log('SwitchTTSOptions', roleOptions.value)
}
let roleOptions = ref([])
onMounted(async () => {
// //
roleOptions.value = GetEdgeTTSRole() await SwitchTTSOptions('edge-tts')
}) })
/** /**
* 切换角色的时候修改角色的配置 * 切换角色的时候修改角色的配置
*/ */
function ChangeCharacter(value) { function ChangeCharacter(value) {
let role = roleOptions.value.find((item) => item.value === value)
let role = roleOptions.value.find(
(item) => item.value === value
)
settingStore.ttsSetting.edgeTTS.value = role.value settingStore.ttsSetting.edgeTTS.value = role.value
settingStore.ttsSetting.edgeTTS.label = role.label settingStore.ttsSetting.edgeTTS.label = role.label
settingStore.ttsSetting.edgeTTS.lang = role.lang settingStore.ttsSetting.edgeTTS.lang = role.lang
settingStore.ttsSetting.edgeTTS.gender = role.gender settingStore.ttsSetting.edgeTTS.gender = role.gender
} }
return { roleOptions, settingStore, ChangeCharacter }
}
})
</script> </script>

View File

@ -12,7 +12,11 @@
show-count show-count
></n-input> ></n-input>
<div class="tts-options"> <div class="tts-options">
<n-button :color="softwareStore.SoftColor.BROWN_YELLOW" size="small" @click="FormatWord"> <n-button
:color="softwareStore.SoftColor.BROWN_YELLOW"
size="small"
@click="FormatWordString"
>
格式化文档 格式化文档
</n-button> </n-button>
<n-popover trigger="hover"> <n-popover trigger="hover">
@ -46,10 +50,9 @@
></n-select> ></n-select>
</n-form-item> </n-form-item>
</n-form> </n-form>
<EdgeTTS :ref="edgettsRef" v-if="settingStore.ttsSetting.selectModel == 'edge-tts'" /> <EdgeTTS v-if="settingStore.ttsSetting.selectModel == 'edge-tts'" />
<AzureTTS <AzureTTS
:azureTTS="settingStore.ttsSetting.azureTTS" :azureTTS="settingStore.ttsSetting.azureTTS"
:ref="azurettsRef"
v-else-if="settingStore.ttsSetting.selectModel == 'azure-tts'" v-else-if="settingStore.ttsSetting.selectModel == 'azure-tts'"
/> />
</div> </div>
@ -83,7 +86,7 @@
</div> </div>
</template> </template>
<script> <script setup>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, reactive, h } from 'vue' import { ref, onMounted, defineComponent, onUnmounted, toRaw, reactive, h } from 'vue'
import { import {
useMessage, useMessage,
@ -104,45 +107,32 @@ import { AddCircleOutline } from '@vicons/ionicons5'
import InputDialogContent from '../Original/Components/InputDialogContent.vue' import InputDialogContent from '../Original/Components/InputDialogContent.vue'
import { useSettingStore } from '../../../../stores/setting' import { useSettingStore } from '../../../../stores/setting'
import TTSHistory from './TTSHistory.vue' import TTSHistory from './TTSHistory.vue'
import { FormatWord } from '../../../../define/Tools/write'
export default defineComponent({ let message = useMessage()
components: { let dialog = useDialog()
NInput, let softwareStore = useSoftwareStore()
NSelect, let text = ref('你好,我是你的智能语音助手')
NFormItem, let ttsOptions = ref([
NForm, {
EdgeTTS, label: 'EdgeTTS免费',
AzureTTS, value: 'edge-tts'
NButton, }
NPopover, ])
AddCircleOutline, let splitRef = ref(null)
NIcon, let settingStore = useSettingStore()
InputDialogContent, let writeSetting = ref({
TTSHistory
},
setup() {
let message = useMessage()
let dialog = useDialog()
let softwareStore = useSoftwareStore()
let text = ref('你好,我是你的智能语音助手')
let ttsOptions = ref([])
let edgettsRef = ref(null)
let azurettsRef = ref(null)
let splitRef = ref(null)
let settingStore = useSettingStore()
let writeSetting = ref({
split_char: '。,“”‘’!?【】《》()…—:;.,\'\'""!?[]<>()...-:;', split_char: '。,“”‘’!?【】《》()…—:;.,\'\'""!?[]<>()...-:;',
merge_count: 3, merge_count: 3,
merge_char: '', merge_char: '',
end_char: '。' end_char: '。'
}) })
let audioUrl = ref(null) let audioUrl = ref(null)
onMounted(async () => {
ttsOptions.value = GetTTSSelect()
onMounted(async () => {
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在加载,请稍等...'
try {
// TTSTTS // TTSTTS
let res = await window.tts.GetTTSCOnfig() let res = await window.tts.GetTTSCOnfig()
if (res.code == 0) { if (res.code == 0) {
@ -158,12 +148,17 @@ export default defineComponent({
} else { } else {
writeSetting.value = writeSettingRes.data writeSetting.value = writeSettingRes.data
} }
}) } catch (error) {
message.error('加载失败,失败原因:' + error.toString())
} finally {
softwareStore.spin.spinning = false
}
})
/** /**
* 修改分割符 * 修改分割符
*/ */
async function ModifySplitChar() { async function ModifySplitChar() {
// //
// //
let dialogWidth = 400 let dialogWidth = 400
@ -191,68 +186,44 @@ export default defineComponent({
message.success('分隔符保存成功') message.success('分隔符保存成功')
} }
}) })
} }
/** /**
* 解析/格式化文档 * 解析/格式化文档
*/ */
async function FormatWord() { async function FormatWordString() {
let split_arr = Array.from(writeSetting.value.split_char) try {
split_arr.forEach((item) => { let wordSrr = FormatWord(text.value)
let specialCharacters = [ text.value = wordSrr.join('\n')
'.', message.success('文本格式化成功')
'*', } catch (error) {
'?', message.error('文本格式化失败,失败原因:' + error.toString())
'+',
'^',
'$',
'[',
']',
'(',
')',
'{',
'}',
'|',
'\\'
]
let regex
if (specialCharacters.includes(item)) {
regex = new RegExp('\\' + item, 'g')
} else {
regex = new RegExp(item, 'g')
}
text.value = text.value.replace(regex, '\n')
})
//
let word_arr = text.value.split('\n')
word_arr = word_arr.filter((item) => item != '' && item != null)
text.value = word_arr.join('\n')
} }
}
/** /**
* 删除文本内容 * 删除文本内容
*/ */
async function ClearText() { async function ClearText() {
text.value = '' text.value = ''
} }
/** /**
* 保存TTS配置信息 * 保存TTS配置信息
*/ */
async function SaveTTSConfig() { async function SaveTTSConfig() {
let saveRes = await window.tts.SaveTTSConfig(toRaw(settingStore.ttsSetting)) let saveRes = await window.tts.SaveTTSConfig(toRaw(settingStore.ttsSetting))
if (saveRes.code == 0) { if (saveRes.code == 0) {
message.error(saveRes.message) message.error(saveRes.message)
return return
} }
message.success('TTS配置保存成功') message.success('TTS配置保存成功')
} }
/** /**
* 开始合成音频 * 开始合成音频
*/ */
async function GenerateAudio() { async function GenerateAudio() {
if (text.value == '') { if (text.value == '') {
message.error('文本内容不能为空') message.error('文本内容不能为空')
return return
@ -279,10 +250,10 @@ export default defineComponent({
audioUrl.value = generateRes.mp3Path audioUrl.value = generateRes.mp3Path
softwareStore.spin.spinning = false softwareStore.spin.spinning = false
} }
// //
function ShowHistory() { function ShowHistory() {
let dialogWidth = window.innerWidth * 0.8 let dialogWidth = window.innerWidth * 0.8
let dialogHeight = window.innerHeight * 0.9 let dialogHeight = window.innerHeight * 0.9
dialog.create({ dialog.create({
@ -293,27 +264,7 @@ export default defineComponent({
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px;matgin-right: 0px`, style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px;matgin-right: 0px`,
maskClosable: false maskClosable: false
}) })
} }
return {
text,
azurettsRef,
edgettsRef,
settingStore,
writeSetting,
softwareStore,
ModifySplitChar,
ShowHistory,
SaveTTSConfig,
FormatWord,
ClearText,
splitRef,
audioUrl,
GenerateAudio,
ttsOptions: [{ label: 'Edge TTS免费', value: 'edge-tts' }]
}
}
})
</script> </script>
<style scoped> <style scoped>

View File

@ -1,7 +1,6 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import { createRouter, createWebHashHistory } from 'vue-router' import { createRouter, createWebHashHistory } from 'vue-router'
import App from './App.vue' import App from './App.vue'
import { Home } from '@vicons/ionicons5'
const app = createApp(App) const app = createApp(App)
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
const pinia = createPinia() const pinia = createPinia()

View File

@ -34,8 +34,10 @@ export const useSettingStore = defineStore('setting', {
pitch: 0, // 语调 pitch: 0, // 语调
rate: 10, // 倍速 rate: 10, // 倍速
volumn: 0 // 音量 volumn: 0 // 音量
} },
} as TTSSettingModel.TTSSetting } as TTSSettingModel.TTSSetting
,
ttsRoles: []
}), }),
getters: {}, getters: {},
actions: { actions: {