1. 添加英文配音

2. 修复聚合推文 任务没有文件不能删掉
3. 修复聚合推文删除所有的批次任务之后,不能再添加的问题
4. 添加版本更新通知,版本更新内容提醒
5. 添加MJ代理MJ账号设置,可以删除本地的账号和同步云端的账号(主要是状态和禁用原因)
This commit is contained in:
2024-10-18 12:39:40 +08:00
parent 224ee47984
commit efa8d3b2a2
41 changed files with 1871 additions and 2959 deletions
@@ -90,7 +90,8 @@ let creatObj = ref({
selectBookTask: undefined,
selectTaskDataCategory: [],
prefixPrompt: '',
suffixPrompt: ''
suffixPrompt: '',
selectBookId: reverseManageStore.selectBook.id
})
let bookTaskOptions = ref([])
let groupData = ref([
File diff suppressed because it is too large Load Diff
@@ -1,44 +1,77 @@
<template>
<div style="width: 100%; height: auto;">
<!-- <div style="display: flex; justify-content: center;">
<n-image width="200" height="250" src="http://qiniuyun.upsurging.xyz/LAI/1280X1280.PNG" preview-disabled />
<n-image width="250" style="margin-left: 100px;"
src="http://qiniuyun.upsurging.xyz/LAI/%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20240427225845.png"
preview-disabled />
</div> -->
<div style="font-size: 15px ;display: flex; justify-content: center;">
<div id="showmessage"></div>
</div>
</div>
<div style="width: 100%; height: 100%">
<div
id="showmessage"
style="font-size: 15px; display: flex; justify-content: center; width: 100%; height: 100%"
></div>
</div>
</template>
<script>
import { ref, h, onMounted, defineComponent, onUnmounted, toRaw } from "vue"
import { NImage, useMessage } from "naive-ui";
import { DEFINE_STRING } from "../../../../define/define_string";
<script setup>
import { onMounted } from 'vue'
import { useMessage, useNotification } from 'naive-ui'
import { version } from '../../../../../package.json'
import { isEmpty } from 'lodash'
export default defineComponent({
components: {
NImage
},
setup() {
onMounted(async () => {
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");
let message = useMessage()
const notification = useNotification()
div.innerHTML = value.data.shareInfo.note_list[0].html_content
})
})
async function GetRemoteSystemInformation() {
let res = await window.system.GetRemoteSystemInformation()
if (res.code == 0) {
message.error(res.message)
return
}
return {
}
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
})
}
}
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>
@@ -1,194 +1,229 @@
<template>
<div id="AddMultiRemoteMj" style="overflow-y: auto">
<div style="margin-bottom: 5px">
<n-button type="info" @click="ManageAccount(null)">新增账号</n-button>
<n-spin :show="spinning">
<div id="AddMultiRemoteMj" style="overflow-y: auto">
<div style="margin-bottom: 5px">
<n-button type="info" @click="ManageAccount(null)">新增账号</n-button>
<n-button type="info" style="margin-left: 10px" @click="GetRemoteMJSettingsFromService()"
>同步服务器帐号信息</n-button
>
</div>
<n-data-table :data="remoteMjSetting" :columns="columns" :max-height="maxHeight">
</n-data-table>
</div>
<n-data-table :data="remoteMjSetting" :columns="columns" :max-height="maxHeight">
</n-data-table>
</div>
<template #description> 同步数据中 </template>
</n-spin>
</template>
<script>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch, h } from 'vue'
import {
useMessage,
NDataTable,
NButton,
NInput,
NInputNumber,
NForm,
NFormItem,
useDialog,
NTag
} from 'naive-ui'
<script setup>
import { ref, onMounted, h } from 'vue'
import { useMessage, NDataTable, NButton, useDialog, NTag, NSpin } from 'naive-ui'
import { useSettingStore } from '../../../../../stores/setting'
import ManageRemoteMjAccount from './ManageRemoteMjAccount.vue'
import { isEmpty } from 'lodash'
export default defineComponent({
components: {
NDataTable,
NButton,
NInput,
NInputNumber,
NForm,
NFormItem,
NTag
},
props: ['height'],
setup(props) {
let message = useMessage()
let dialog = useDialog()
let maxHeight = ref(props.height - 150)
let remoteMjSetting = ref([])
let settingStore = useSettingStore()
let props = defineProps({
height: {
type: Number,
default: 500
}
})
let message = useMessage()
let dialog = useDialog()
let maxHeight = ref(props.height - 150)
let remoteMjSetting = ref([])
let settingStore = useSettingStore()
let spinning = ref(false)
onMounted(async () => {
document.getElementById('AddMultiRemoteMj').style.height = props.height - 60 + 'px'
async function GetRemoteMJSettingsFromService() {
spinning.value = true
try {
let remoteMjSettingRes = await window.setting.GetRemoteMJSettingsFromService()
if (remoteMjSettingRes.code == 0) {
message.error('获取代理MJ配置失败')
return
}
message.success('同步服务器帐号信息成功')
// 关闭的时候,刷新数据
let res = await window.setting.GetRemoteMJSettings()
if (res.code == 0) {
message.error('获取代理MJ配置失败')
} else {
remoteMjSetting.value = res.data
}
remoteMjSetting.value = res.data
spinning.value = false
} catch (error) {
} finally {
spinning.value = false
}
}
let columns = [
{
title: '服务器ID',
key: 'guildId'
},
{
title: '频道ID',
key: 'channelId'
},
{
title: '状态',
key: 'enable',
render(row) {
return h(
NTag,
{
style: {
marginRight: '6px'
},
type: (() => (row.enable ? 'success' : 'error'))(),
bordered: false
},
{
default: () => (row.enable ? '启用' : '禁用')
}
)
}
},
{
title: 'MJ私信ID',
key: 'mjBotChannelId'
},
{
title: 'NIJI私信ID',
key: 'nijiBotChannelId'
},
{
title: '禁用原因',
key: 'blockMessage'
},
{
title: '操作',
key: 'action',
render(row) {
return h('div', {}, [
h(
NButton,
{
size: 'tiny',
type: 'info',
style: 'margin-left: 5px;margin-bottom: 5px',
onClick: () => ManageAccount(row)
},
{ default: () => '编辑并同步' }
),
h(
NButton,
{
size: 'tiny',
type: 'error',
style: 'margin-left: 5px;margin-bottom: 5px',
onClick: () => DeleteAccount(row, false)
},
{ 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()
}
})
}
/**
* 添加和编辑账号
*/
async function ManageAccount(remote = null) {
if (remote == null) {
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 {
// 有数据的话
settingStore.actionRemoteMJ = remote
remoteMjSetting.value = remoteMjSettingRes.data
}
// 弹窗,管理不想要的值
let dW = 800
let dH = 600
dialog.create({
showIcon: false,
title: '添加MJ账号',
content: () => h(ManageRemoteMjAccount, {}),
style: `min-width : 600px; width : ${dW}px; height : ${dH}px; padding-right : 5px;`,
maskClosable: false,
onClose: async () => {
// 关闭的时候,刷新数据
let remoteMjSettingRes = await window.setting.GetRemoteMJSettings()
if (remoteMjSettingRes.code == 0) {
message.error('获取代理MJ配置失败')
} else {
remoteMjSetting.value = remoteMjSettingRes.data
}
settingStore.ResetActionRemoteMJ()
}
})
}
/**
* 删除指定的账号
* @param row 数据
*/
async function DeleteAccount(row) {
dialog.warning({
title: '删除账号',
content: '确定删除该账号吗?',
positiveText: '确认',
negativeText: '取消',
onPositiveClick: async () => {
if (isEmpty(row.accountId)) {
message.error('删除账号失败,错误消息如下:' + '账号ID为空')
return
}
let deleteRes = await window.setting.DeleteRemoteMJSetting(row.id)
if (deleteRes.code == 0) {
message.error('删除账号失败,错误消息如下:' + deleteRes.message)
return
}
message.success('删除账号成功')
// 这边刷新一下数据
let remoteMjSettingRes = await window.setting.GetRemoteMJSettings()
if (remoteMjSettingRes.code == 0) {
message.error('获取代理MJ配置失败')
} else {
remoteMjSetting.value = remoteMjSettingRes.data
}
}
})
}
return {
remoteMjSetting,
maxHeight,
ManageAccount,
settingStore,
columns: [
{
title: '服务器ID',
key: 'guildId'
},
{
title: '频道ID',
key: 'channelId'
},
{
title: '状态',
key: 'enable',
render(row) {
return h(
NTag,
{
style: {
marginRight: '6px'
},
type: (() => (row.enable ? 'success' : 'error'))(),
bordered: false
},
{
default: () => (row.enable ? '启用' : '禁用')
}
)
}
},
{
title: 'MJ私信ID',
key: 'mjBotChannelId'
},
{
title: 'NIJI私信ID',
key: 'nijiBotChannelId'
},
{
title: '操作',
key: 'action',
render(row) {
return h('div', {}, [
h(
NButton,
{
size: 'small',
type: 'info',
style: 'margin-left: 5px',
onClick: () => ManageAccount(row)
},
{ default: () => '编辑并同步' }
),
h(
NButton,
{
size: 'small',
type: 'error',
style: 'margin-left: 5px',
onClick: () => DeleteAccount(row)
},
{ default: () => '删除账号' }
)
])
}
}
]
}
}
})
})
}
</script>
@@ -158,7 +158,7 @@ export default defineComponent({
message.success('更新账号成功')
} else {
// 新建,开始保存
let res = await window.setting.AddRemoteMJSetting(toRaw(settingStore.actionRemoteMJ))
let res = await window.setting.AddRemoteMJSetting(toRaw(settingStore.actionRemoteMJ),true)
loading.value = false
if (res.code == 0) {
message.error('创建账号失败,错误消息如下:' + res.message)
+339 -377
View File
@@ -100,7 +100,7 @@
</n-card>
<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 title="浏览器模式设置" hoverable style="margin-top: 10px; min-width: 850px">
@@ -154,7 +154,7 @@
</div>
</template>
<script>
<script setup>
import { defineComponent, ref, onMounted, computed, toRaw, h } from 'vue'
import {
NButton,
@@ -178,384 +178,346 @@ import { Reload } from '@vicons/ionicons5'
import { isEmpty, max, min } from 'lodash'
import { MJImageType } from '../../../../define/enum/mjEnum'
import AddMultiRemoteMj from './Components/AddMultiRemoteMj.vue'
export default defineComponent({
components: {
NButton,
NDataTable,
NForm,
NFormItem,
NInput,
NDivider,
NCheckbox,
NSelect,
NTooltip,
NIcon,
Reload,
NInputNumber,
NCard,
NSpin
let message = useMessage()
let dialog = useDialog()
let sampleRef = ref(null)
let select_robot_options = ref([
{
label: 'MJ',
value: 'mj'
},
setup() {
let message = useMessage()
let dialog = useDialog()
let sampleRef = ref(null)
let select_robot_options = ref([
{
label: 'MJ',
value: 'mj'
},
{
label: 'NIJI',
value: 'niji'
}
])
{
label: 'NIJI',
value: 'niji'
}
])
let mj_speed_options = ref([
{
label: 'RELAXED',
value: 'relaxed'
},
{
label: 'FAST',
value: 'fast'
}
])
let mj_speed_options = ref([
{
label: 'RELAXED',
value: 'relaxed'
},
{
label: 'FAST',
value: 'fast'
}
])
let mjSetting = ref({
id: null,
imageModel: null,
imageScale: null,
imageSuffix: null,
requestModel: null,
type: null,
selectRobot: null,
spaceTime: 6,
taskCount: 3,
createTime: null,
updateTime: null,
version: null,
remoteSetting: {
accountId: null,
channelId: null,
coreSize: 3,
guildId: null,
mjBotChannelId: null,
nijiBotChannelId: null,
queueSize: 6,
remark: null, // 机器码
remixAutoSubmit: false,
timeoutMinutes: 6,
userAgent: null,
userToken: null
},
apiSetting: {
id: null,
mjApiUrl: null,
mjSpeed: null,
apiKey: null
},
browserSetting: {
id: null,
serviceId: null,
channelId: null,
mjBotId: null,
nijBotId: null,
token: null,
userAgent: null,
userAgentCustom: false
}
})
let image_scale_options = ref([])
let image_model_options = ref([])
let tmp_image_model_options = []
let request_model_options = ref([])
let mj_api_options = ref([])
let computedSuffix = () => {
let text = image_model_options.value.findIndex((item) => {
return item.value == mjSetting.value.imageModel
})
if (text == -1) {
return
}
let sc = image_scale_options.value.findIndex((item) => {
return item.value == mjSetting.value.imageScale
})
let dd = ` --${image_model_options.value[text].text} --ar ${image_scale_options.value[sc].text}`
mjSetting.value.imageSuffix = dd
return dd
}
// 初始化现在设置的数据
async function InitData() {
// 获取到的是当前的配置信息
let res = await window.setting.GetMJSettingTreeData()
if (res.code == 0) {
message.error(res.message)
return
}
if (!res.data.apiSetting) {
delete res.data.apiSetting
}
if (!res.data.remoteSetting) {
delete res.data.remoteSetting
}
if (!res.data.browserSetting) {
delete res.data.browserSetting
}
mjSetting.value = Object.assign(mjSetting.value, res.data)
console.log(res)
await window.mj.GetMJImageScale((value) => {
if (value.code == 0) {
message.error(value.message)
return
}
image_scale_options.value = value.data
if (image_scale_options.value.length > 0 && mjSetting.value.imageScale == null) {
mjSetting.value.imageScale = image_scale_options.value[0].value
}
})
await window.mj.GetMJImageRobotModel((value) => {
if (value.code == 0) {
message.error(value.message)
return
}
image_model_options.value = value.data
tmp_image_model_options = value.data
if (image_model_options.value.length > 0 && mjSetting.value.imageModel == null) {
mjSetting.value.imageModel = image_model_options.value[0].value
}
})
await window.mj.GetMJGenerateCategory((value) => {
if (value.code == 0) {
message.error(value.message)
return
}
request_model_options.value = value.data.filter((item) => !item.disable)
if (request_model_options.value.length > 0 && mjSetting.value.requestModel == null) {
mjSetting.value.requestModel = request_model_options.value[0].value
}
})
await window.api.getGptBusinessOption('all', (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
mj_api_options.value = value.data.filter((item) => item.mj_url)
if (mj_api_options.value.length > 0 && mjSetting.value.apiSetting.mjApiUrl == null) {
mjSetting.value.apiSetting.mjApiUrl = mj_api_options.value[0].value
}
})
}
onMounted(async () => {
// 监听浏览器设置的中信息
window.api.setEventListen([DEFINE_STRING.DISCORD.OPERATE_REFRASH_DISCORD_URL], (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
// 保存数据
console.log(value)
if (value.type == DEFINE_STRING.DISCORD_SIMPLE_DATA_TYPE.URL) {
mjSetting.value.browserSetting.serviceId = value.data.serviceID
mjSetting.value.browserSetting.channelId = value.data.channelID
} else if (value.type == DEFINE_STRING.DISCORD_SIMPLE_DATA_TYPE.TOKEN) {
mjSetting.value.browserSetting.token = value.data.authorization
if (!mjSetting.value.browserSetting.userAgentCustom) {
mjSetting.value.browserSetting.userAgent = value.data.userAgent
}
} else {
message.error('未知的数据类型')
}
})
await InitData()
if (mjSetting.value.apiSetting.mjSpeed == null) {
mjSetting.value.apiSetting.mjSpeed = mj_speed_options.value[0].value
}
})
/**
* 打开discord窗口
*/
async function OpenDiscordWindow() {
await window.api.OpenDiscordWindow((value) => {
if (value.code == 0) {
message.error(value.message)
return
}
})
}
// 基础配置的必填检测
let sampleRules = {
imageModel: [{ required: true, message: '请选择机器人模型', trigger: 'blur' }],
imageScale: [{ required: true, message: '请选择生图尺寸', trigger: 'blur' }],
requestModel: [{ required: true, message: '请选择出图模式', trigger: 'blur' }],
selectRobot: [{ required: true, message: '请选择生图机器人', trigger: 'blur' }]
}
/**
* 保存MJ配置
*/
async function SaveMjSetting(e) {
// 在保存的时候要进行数据保存
e.preventDefault()
sampleRef.value?.validate(async (errors) => {
if (errors) {
message.error('请检查必填字段')
return
}
// mjSetting.value.imageSuffix = image_suffix.value
// 通过选择的请求模式判断哪些是要校验的
let request_model = mjSetting.value.requestModel
if (request_model == MJImageType.API_MJ) {
// API模式,检查必填数据
if (
mjSetting.value.apiSetting == null ||
mjSetting.value.apiSetting.mjApiUrl == null ||
mjSetting.value.apiSetting.mjSpeed == null ||
mjSetting.value.apiSetting.apiKey == null
) {
message.error('请检查API模式设置的必填字段')
return
}
}
if (request_model == MJImageType.REMOTE_MJ) {
// 检查是不是有代理账号
let remoteMjRes = await window.setting.GetRemoteMJSettings()
if (remoteMjRes.code == 0) {
message.error('获取代理MJ配置失败')
return
}
if (remoteMjRes.data.length <= 0) {
message.error('请先添加代理模式的配置')
return
}
}
if (request_model == MJImageType.BROWSER_MJ) {
// 浏览器模式,检查必填数据
if (
mjSetting.value.browserSetting == null ||
mjSetting.value.browserSetting.serviceId == null ||
mjSetting.value.browserSetting.channelId == null ||
mjSetting.value.browserSetting.token == null ||
mjSetting.value.browserSetting.userAgent == null
) {
message.error('请检查浏览器模式设置的必填字段')
return
}
}
// 开始保存数据
let res = await window.setting.SaveMJSettingTreeData(toRaw(mjSetting.value))
if (res.code == 0) {
window.api.showGlobalMessageDialog({ code: 0, message: res.message })
return
}
mjSetting.value = res.data
// 判断当前的模式
if (mjSetting.value.requestModel == MJImageType.REMOTE_MJ) {
window.api.showGlobalMessageDialog({
code: 1,
message: `数据保存成功,当前模式为代理模式`
})
} else {
window.api.showGlobalMessageDialog({ code: 1, message: '添加成功' })
}
})
}
/**
* 更新选择的机器人时触发的方法
*/
async function UpdateSelectRobot(value) {
// 刷新数据
image_model_options.value = tmp_image_model_options.filter((item) => {
return item.type == value
})
// 判断当前选中的机器人是不是在当前的数据中
if (
image_model_options.value.findIndex((item) => {
return item.value == mjSetting.value.imageModel
}) == -1
) {
mjSetting.value.imageModel =
image_model_options.value.length > 0 ? image_model_options.value[0].value : null
}
// 刷新命令后缀
mjSetting.value.imageSuffix = computedSuffix()
}
/**
* 打开购买GPT的地址
*/
async function openGptBuyUrl() {
let tmp_gb = mj_api_options.value.filter(
(item) => item.value == mjSetting.value.apiSetting.mjApiUrl
)
if (tmp_gb.length == 0) {
message.error('当前选择的服务商没有购买地址!')
return
}
let buy_url = tmp_gb[0].buy_url
if (isEmpty(buy_url)) {
message.error('当前选择的服务商没有购买地址!')
} else {
window.api.openGptBuyUrl(buy_url)
}
}
/**
* 添加多个账号,这样可以同时跑多个账号
*/
async function AddMultiMjAccount() {
// 弹窗,管理不想要的值
let dW = window.innerWidth * 0.9
let dH = window.innerHeight * 0.9
dialog.create({
showIcon: false,
title: '管理代理模式MJ账号',
content: () => h(AddMultiRemoteMj, { height: dH }),
style: `min-width : 600px; width : ${dW}px; height : ${dH}px; padding-right : 5px;`,
maskClosable: false
})
}
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
}
let mjSetting = ref({
id: null,
imageModel: null,
imageScale: null,
imageSuffix: null,
requestModel: null,
type: null,
selectRobot: null,
spaceTime: 6,
taskCount: 3,
createTime: null,
updateTime: null,
version: null,
remoteSetting: {
accountId: null,
channelId: null,
coreSize: 3,
guildId: null,
mjBotChannelId: null,
nijiBotChannelId: null,
queueSize: 6,
remark: null, // 机器码
remixAutoSubmit: false,
timeoutMinutes: 6,
userAgent: null,
userToken: null
},
apiSetting: {
id: null,
mjApiUrl: null,
mjSpeed: null,
apiKey: null
},
browserSetting: {
id: null,
serviceId: null,
channelId: null,
mjBotId: null,
nijBotId: null,
token: null,
userAgent: null,
userAgentCustom: false
}
})
let image_scale_options = ref([])
let image_model_options = ref([])
let tmp_image_model_options = []
let request_model_options = ref([])
let mj_api_options = ref([])
let computedSuffix = () => {
let text = image_model_options.value.findIndex((item) => {
return item.value == mjSetting.value.imageModel
})
if (text == -1) {
return
}
let sc = image_scale_options.value.findIndex((item) => {
return item.value == mjSetting.value.imageScale
})
let dd = ` --${image_model_options.value[text].text} --ar ${image_scale_options.value[sc].text}`
mjSetting.value.imageSuffix = dd
return dd
}
// 初始化现在设置的数据
async function InitData() {
// 获取到的是当前的配置信息
let res = await window.setting.GetMJSettingTreeData()
if (res.code == 0) {
message.error(res.message)
return
}
if (!res.data.apiSetting) {
delete res.data.apiSetting
}
if (!res.data.remoteSetting) {
delete res.data.remoteSetting
}
if (!res.data.browserSetting) {
delete res.data.browserSetting
}
mjSetting.value = Object.assign(mjSetting.value, res.data)
console.log(res)
await window.mj.GetMJImageScale((value) => {
if (value.code == 0) {
message.error(value.message)
return
}
image_scale_options.value = value.data
if (image_scale_options.value.length > 0 && mjSetting.value.imageScale == null) {
mjSetting.value.imageScale = image_scale_options.value[0].value
}
})
await window.mj.GetMJImageRobotModel((value) => {
if (value.code == 0) {
message.error(value.message)
return
}
image_model_options.value = value.data
tmp_image_model_options = value.data
if (image_model_options.value.length > 0 && mjSetting.value.imageModel == null) {
mjSetting.value.imageModel = image_model_options.value[0].value
}
})
await window.mj.GetMJGenerateCategory((value) => {
if (value.code == 0) {
message.error(value.message)
return
}
request_model_options.value = value.data.filter((item) => !item.disable)
if (request_model_options.value.length > 0 && mjSetting.value.requestModel == null) {
mjSetting.value.requestModel = request_model_options.value[0].value
}
})
await window.api.getGptBusinessOption('all', (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
mj_api_options.value = value.data.filter((item) => item.mj_url)
if (mj_api_options.value.length > 0 && mjSetting.value.apiSetting.mjApiUrl == null) {
mjSetting.value.apiSetting.mjApiUrl = mj_api_options.value[0].value
}
})
}
onMounted(async () => {
// 监听浏览器设置的中信息
window.api.setEventListen([DEFINE_STRING.DISCORD.OPERATE_REFRASH_DISCORD_URL], (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
// 保存数据
console.log(value)
if (value.type == DEFINE_STRING.DISCORD_SIMPLE_DATA_TYPE.URL) {
mjSetting.value.browserSetting.serviceId = value.data.serviceID
mjSetting.value.browserSetting.channelId = value.data.channelID
} else if (value.type == DEFINE_STRING.DISCORD_SIMPLE_DATA_TYPE.TOKEN) {
mjSetting.value.browserSetting.token = value.data.authorization
if (!mjSetting.value.browserSetting.userAgentCustom) {
mjSetting.value.browserSetting.userAgent = value.data.userAgent
}
} else {
message.error('未知的数据类型')
}
})
await InitData()
if (mjSetting.value.apiSetting.mjSpeed == null) {
mjSetting.value.apiSetting.mjSpeed = mj_speed_options.value[0].value
}
})
/**
* 打开discord窗口
*/
async function OpenDiscordWindow() {
await window.api.OpenDiscordWindow((value) => {
if (value.code == 0) {
message.error(value.message)
return
}
})
}
// 基础配置的必填检测
let sampleRules = {
imageModel: [{ required: true, message: '请选择机器人模型', trigger: 'blur' }],
imageScale: [{ required: true, message: '请选择生图尺寸', trigger: 'blur' }],
requestModel: [{ required: true, message: '请选择出图模式', trigger: 'blur' }],
selectRobot: [{ required: true, message: '请选择生图机器人', trigger: 'blur' }]
}
/**
* 保存MJ配置
*/
async function SaveMjSetting(e) {
// 在保存的时候要进行数据保存
e.preventDefault()
sampleRef.value?.validate(async (errors) => {
if (errors) {
message.error('请检查必填字段')
return
}
// mjSetting.value.imageSuffix = image_suffix.value
// 通过选择的请求模式判断哪些是要校验的
let request_model = mjSetting.value.requestModel
if (request_model == MJImageType.API_MJ) {
// API模式,检查必填数据
if (
mjSetting.value.apiSetting == null ||
mjSetting.value.apiSetting.mjApiUrl == null ||
mjSetting.value.apiSetting.mjSpeed == null ||
mjSetting.value.apiSetting.apiKey == null
) {
message.error('请检查API模式设置的必填字段')
return
}
}
if (request_model == MJImageType.REMOTE_MJ) {
// 检查是不是有代理账号
let remoteMjRes = await window.setting.GetRemoteMJSettings()
if (remoteMjRes.code == 0) {
message.error('获取代理MJ配置失败')
return
}
if (remoteMjRes.data.length <= 0) {
message.error('请先添加代理模式的配置')
return
}
}
if (request_model == MJImageType.BROWSER_MJ) {
// 浏览器模式,检查必填数据
if (
mjSetting.value.browserSetting == null ||
mjSetting.value.browserSetting.serviceId == null ||
mjSetting.value.browserSetting.channelId == null ||
mjSetting.value.browserSetting.token == null ||
mjSetting.value.browserSetting.userAgent == null
) {
message.error('请检查浏览器模式设置的必填字段')
return
}
}
// 开始保存数据
let res = await window.setting.SaveMJSettingTreeData(toRaw(mjSetting.value))
if (res.code == 0) {
window.api.showGlobalMessageDialog({ code: 0, message: res.message })
return
}
mjSetting.value = res.data
// 判断当前的模式
if (mjSetting.value.requestModel == MJImageType.REMOTE_MJ) {
window.api.showGlobalMessageDialog({
code: 1,
message: `数据保存成功,当前模式为代理模式`
})
} else {
window.api.showGlobalMessageDialog({ code: 1, message: '添加成功' })
}
})
}
/**
* 更新选择的机器人时触发的方法
*/
async function UpdateSelectRobot(value) {
// 刷新数据
image_model_options.value = tmp_image_model_options.filter((item) => {
return item.type == value
})
// 判断当前选中的机器人是不是在当前的数据中
if (
image_model_options.value.findIndex((item) => {
return item.value == mjSetting.value.imageModel
}) == -1
) {
mjSetting.value.imageModel =
image_model_options.value.length > 0 ? image_model_options.value[0].value : null
}
// 刷新命令后缀
mjSetting.value.imageSuffix = computedSuffix()
}
/**
* 打开购买GPT的地址
*/
async function openGptBuyUrl() {
let tmp_gb = mj_api_options.value.filter(
(item) => item.value == mjSetting.value.apiSetting.mjApiUrl
)
if (tmp_gb.length == 0) {
message.error('当前选择的服务商没有购买地址!')
return
}
let buy_url = tmp_gb[0].buy_url
if (isEmpty(buy_url)) {
message.error('当前选择的服务商没有购买地址!')
} else {
window.api.openGptBuyUrl(buy_url)
}
}
/**
* 添加多个账号,这样可以同时跑多个账号
*/
async function AddMultiMjAccount() {
// 弹窗,管理不想要的值
let dW = window.innerWidth * 0.9
let dH = window.innerHeight * 0.9
dialog.create({
showIcon: false,
title: '管理代理模式MJ账号',
content: () => h(AddMultiRemoteMj, { height: dH }),
style: `min-width : 600px; width : ${dW}px; height : ${dH}px; padding-right : 5px;`,
maskClosable: false
})
}
</script>
+29 -36
View File
@@ -30,7 +30,7 @@
</div>
</template>
<script>
<script setup>
import { ref, onMounted, defineComponent, watch, inject } from 'vue'
import {
useMessage,
@@ -47,42 +47,35 @@ import { GetEdgeTTSRole } from '../../../../define/tts/ttsDefine'
import { ReaderOutline } from '@vicons/ionicons5'
import { useSettingStore } from '../../../../stores/setting'
export default defineComponent({
components: {
NForm,
NCheckbox,
NFormItem,
NInputNumber,
NSelect,
NButton,
NIcon,
ReaderOutline,
NPopover
},
setup(props) {
let message = useMessage()
let settingStore = useSettingStore()
let message = useMessage()
let settingStore = useSettingStore()
let roleOptions = ref([])
onMounted(async () => {
// 获取配音角色列表
roleOptions.value = GetEdgeTTSRole()
})
/**
* 切换角色的时候,修改角色的配置
*/
function ChangeCharacter(value) {
let role = roleOptions.value.find(
(item) => item.value === value
)
settingStore.ttsSetting.edgeTTS.value = role.value
settingStore.ttsSetting.edgeTTS.label = role.label
settingStore.ttsSetting.edgeTTS.lang = role.lang
settingStore.ttsSetting.edgeTTS.gender = role.gender
}
return { roleOptions, settingStore, ChangeCharacter }
async function SwitchTTSOptions(key) {
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 () => {
// 获取配音角色列表
await SwitchTTSOptions('edge-tts')
})
/**
* 切换角色的时候,修改角色的配置
*/
function ChangeCharacter(value) {
let role = roleOptions.value.find((item) => item.value === value)
settingStore.ttsSetting.edgeTTS.value = role.value
settingStore.ttsSetting.edgeTTS.label = role.label
settingStore.ttsSetting.edgeTTS.lang = role.lang
settingStore.ttsSetting.edgeTTS.gender = role.gender
}
</script>
+158 -207
View File
@@ -12,7 +12,11 @@
show-count
></n-input>
<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-popover trigger="hover">
@@ -46,10 +50,9 @@
></n-select>
</n-form-item>
</n-form>
<EdgeTTS :ref="edgettsRef" v-if="settingStore.ttsSetting.selectModel == 'edge-tts'" />
<EdgeTTS v-if="settingStore.ttsSetting.selectModel == 'edge-tts'" />
<AzureTTS
:azureTTS="settingStore.ttsSetting.azureTTS"
:ref="azurettsRef"
v-else-if="settingStore.ttsSetting.selectModel == 'azure-tts'"
/>
</div>
@@ -83,7 +86,7 @@
</div>
</template>
<script>
<script setup>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, reactive, h } from 'vue'
import {
useMessage,
@@ -104,216 +107,164 @@ import { AddCircleOutline } from '@vicons/ionicons5'
import InputDialogContent from '../Original/Components/InputDialogContent.vue'
import { useSettingStore } from '../../../../stores/setting'
import TTSHistory from './TTSHistory.vue'
import { FormatWord } from '../../../../define/Tools/write'
export default defineComponent({
components: {
NInput,
NSelect,
NFormItem,
NForm,
EdgeTTS,
AzureTTS,
NButton,
NPopover,
AddCircleOutline,
NIcon,
InputDialogContent,
TTSHistory
},
let message = useMessage()
let dialog = useDialog()
let softwareStore = useSoftwareStore()
let text = ref('你好,我是你的智能语音助手')
let ttsOptions = ref([
{
label: 'EdgeTTS(免费)',
value: 'edge-tts'
}
])
let splitRef = ref(null)
let settingStore = useSettingStore()
let writeSetting = ref({
split_char: '。,“”‘’!?【】《》()…—:;.,\'\'""!?[]<>()...-:;',
merge_count: 3,
merge_char: '',
end_char: '。'
})
let audioUrl = ref(null)
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: '。,“”‘’!?【】《》()…—:;.,\'\'""!?[]<>()...-:;',
merge_count: 3,
merge_char: '',
end_char: '。'
})
let audioUrl = ref(null)
onMounted(async () => {
ttsOptions.value = GetTTSSelect()
// 加载服务端的TTS配置(目前的TTS配置是全局的)
let res = await window.tts.GetTTSCOnfig()
if (res.code == 0) {
message.error(res.message)
} else {
settingStore.ttsSetting = res.data
}
// 加载文字设置
let writeSettingRes = await window.write.GetWriteCOnfig()
if (writeSettingRes.code == 0) {
message.error(writeSettingRes.message)
} else {
writeSetting.value = writeSettingRes.data
}
})
/**
* 修改分割符
*/
async function ModifySplitChar() {
// 判断当前数据是不是存在
// 处理数据。获取当前的所有的数据
let dialogWidth = 400
let dialogHeight = 150
dialog.create({
title: '添加分割符',
showIcon: false,
closeOnEsc: false,
content: () =>
h(InputDialogContent, {
ref: splitRef,
initData: writeSetting.value.split_char,
placeholder: '请输入分割符'
}),
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px`,
maskClosable: false,
onClose: async () => {
writeSetting.value.split_char = splitRef.value.data
// 保存数据
let saveRes = await window.write.SaveWriteConfig(toRaw(writeSetting.value))
if (saveRes.code == 0) {
message.error(saveRes.message)
return
}
message.success('分隔符保存成功')
}
})
onMounted(async () => {
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在加载,请稍等...'
try {
// 加载服务端的TTS配置(目前的TTS配置是全局的)
let res = await window.tts.GetTTSCOnfig()
if (res.code == 0) {
message.error(res.message)
} else {
settingStore.ttsSetting = res.data
}
/**
* 解析/格式化文档
*/
async function FormatWord() {
let split_arr = Array.from(writeSetting.value.split_char)
split_arr.forEach((item) => {
let specialCharacters = [
'.',
'*',
'?',
'+',
'^',
'$',
'[',
']',
'(',
')',
'{',
'}',
'|',
'\\'
]
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() {
text.value = ''
}
/**
* 保存TTS配置信息
*/
async function SaveTTSConfig() {
let saveRes = await window.tts.SaveTTSConfig(toRaw(settingStore.ttsSetting))
if (saveRes.code == 0) {
message.error(saveRes.message)
return
}
message.success('TTS配置保存成功')
}
/**
* 开始合成音频
*/
async function GenerateAudio() {
if (text.value == '') {
message.error('文本内容不能为空')
return
}
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在合成音频,请稍等...'
// 保存配置信息
let saveRes = await window.tts.SaveTTSConfig(toRaw(settingStore.ttsSetting))
if (saveRes.code == 0) {
softwareStore.spin.spinning = false
message.error(saveRes.message)
return
}
// 开始真正的合成音频
let generateRes = await window.tts.GenerateAudio(text.value)
if (generateRes.code == 0) {
softwareStore.spin.spinning = false
message.error(generateRes.message)
return
}
audioUrl.value = generateRes.mp3Path
softwareStore.spin.spinning = false
}
// 显示配音的历史记录
function ShowHistory() {
let dialogWidth = window.innerWidth * 0.8
let dialogHeight = window.innerHeight * 0.9
dialog.create({
title: '配音历史记录',
showIcon: false,
closeOnEsc: false,
content: () => h(TTSHistory, { height: dialogHeight }),
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px;matgin-right: 0px`,
maskClosable: false
})
}
return {
text,
azurettsRef,
edgettsRef,
settingStore,
writeSetting,
softwareStore,
ModifySplitChar,
ShowHistory,
SaveTTSConfig,
FormatWord,
ClearText,
splitRef,
audioUrl,
GenerateAudio,
ttsOptions: [{ label: 'Edge TTS(免费)', value: 'edge-tts' }]
// 加载文字设置
let writeSettingRes = await window.write.GetWriteCOnfig()
if (writeSettingRes.code == 0) {
message.error(writeSettingRes.message)
} else {
writeSetting.value = writeSettingRes.data
}
} catch (error) {
message.error('加载失败,失败原因:' + error.toString())
} finally {
softwareStore.spin.spinning = false
}
})
/**
* 修改分割符
*/
async function ModifySplitChar() {
// 判断当前数据是不是存在
// 处理数据。获取当前的所有的数据
let dialogWidth = 400
let dialogHeight = 150
dialog.create({
title: '添加分割符',
showIcon: false,
closeOnEsc: false,
content: () =>
h(InputDialogContent, {
ref: splitRef,
initData: writeSetting.value.split_char,
placeholder: '请输入分割符'
}),
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px`,
maskClosable: false,
onClose: async () => {
writeSetting.value.split_char = splitRef.value.data
// 保存数据
let saveRes = await window.write.SaveWriteConfig(toRaw(writeSetting.value))
if (saveRes.code == 0) {
message.error(saveRes.message)
return
}
message.success('分隔符保存成功')
}
})
}
/**
* 解析/格式化文档
*/
async function FormatWordString() {
try {
let wordSrr = FormatWord(text.value)
text.value = wordSrr.join('\n')
message.success('文本格式化成功')
} catch (error) {
message.error('文本格式化失败,失败原因:' + error.toString())
}
}
/**
* 删除文本内容
*/
async function ClearText() {
text.value = ''
}
/**
* 保存TTS配置信息
*/
async function SaveTTSConfig() {
let saveRes = await window.tts.SaveTTSConfig(toRaw(settingStore.ttsSetting))
if (saveRes.code == 0) {
message.error(saveRes.message)
return
}
message.success('TTS配置保存成功')
}
/**
* 开始合成音频
*/
async function GenerateAudio() {
if (text.value == '') {
message.error('文本内容不能为空')
return
}
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在合成音频,请稍等...'
// 保存配置信息
let saveRes = await window.tts.SaveTTSConfig(toRaw(settingStore.ttsSetting))
if (saveRes.code == 0) {
softwareStore.spin.spinning = false
message.error(saveRes.message)
return
}
// 开始真正的合成音频
let generateRes = await window.tts.GenerateAudio(text.value)
if (generateRes.code == 0) {
softwareStore.spin.spinning = false
message.error(generateRes.message)
return
}
audioUrl.value = generateRes.mp3Path
softwareStore.spin.spinning = false
}
// 显示配音的历史记录
function ShowHistory() {
let dialogWidth = window.innerWidth * 0.8
let dialogHeight = window.innerHeight * 0.9
dialog.create({
title: '配音历史记录',
showIcon: false,
closeOnEsc: false,
content: () => h(TTSHistory, { height: dialogHeight }),
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px;matgin-right: 0px`,
maskClosable: false
})
}
</script>
<style scoped>
-1
View File
@@ -1,7 +1,6 @@
import { createApp } from 'vue'
import { createRouter, createWebHashHistory } from 'vue-router'
import App from './App.vue'
import { Home } from '@vicons/ionicons5'
const app = createApp(App)
import { createPinia } from 'pinia'
const pinia = createPinia()