V 3.2.4(2025.02.24)
1. 新增MJ(API,代理模式)国内转发接口(不包括反推),解决部分用户不能访问外部网络 2. 新增 FLUX-API 国内转发接口,解决部分用户不能访问外部网络(可能出现超时报错) 3. 动态设置FLUX模型,统一后台管理 4. 新增图转视频国内(Kling,Luma,Runway)转发接口,解决部分用户不能访问外部网络 5. 新增支持 Luma 慢速模型 6. 优化MJ设置及MJ请求,减少出错 7. MJ代理模式取消账号生图速度校验 注意:本次更新需要重新设置MJ设置(代理账号不用)
This commit is contained in:
parent
6cf1e7df5b
commit
03d3ff7e9d
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "laitool",
|
||||
"version": "3.2.3",
|
||||
"version": "3.2.4",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "laitool",
|
||||
"version": "3.2.3",
|
||||
"version": "3.2.4",
|
||||
"description": "An AI tool for image processing, video processing, and other functions.",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "laitool.cn",
|
||||
@ -92,8 +92,13 @@
|
||||
"resources/tmp/**",
|
||||
"resources/icon.ico"
|
||||
],
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"win": {
|
||||
"target": "nsis",
|
||||
"icon": "./resources/icon.ico"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -12,7 +12,22 @@ let apiUrl = [
|
||||
d3_url: {
|
||||
image: 'https://api.laitool.cc/v1/images/generations'
|
||||
},
|
||||
buy_url: 'https://api.laitool.cc/register?aff=Zmdu'
|
||||
buy_url: 'https://api.laitool.cc/login'
|
||||
},
|
||||
{
|
||||
label: 'LAI API - 美国',
|
||||
value: '2b443f53-ba12-42b3-a57c-e4df92685c73',
|
||||
gpt_url: 'https://laitool.net/v1/chat/completions',
|
||||
mj_url: {
|
||||
imagine: 'https://laitool.net/mj/submit/imagine',
|
||||
describe: 'https://laitool.net/mj/submit/describe',
|
||||
update_file: 'https://laitool.net/mj/submit/upload-discord-images',
|
||||
once_get_task: 'https://laitool.net/mj/task/${id}/fetch'
|
||||
},
|
||||
d3_url: {
|
||||
image: 'https://laitool.net/v1/images/generations'
|
||||
},
|
||||
buy_url: 'https://laitool.net/login'
|
||||
},
|
||||
{
|
||||
label: 'openai-hk',
|
||||
@ -1,145 +1,149 @@
|
||||
const path = require('path')
|
||||
const { app } = require('electron')
|
||||
let define = {}
|
||||
if (!app.isPackaged) {
|
||||
define = {
|
||||
discordScript: path.join(__dirname, '../../src/main/discord/discordScript.js'),
|
||||
zhanwei_image: path.join(__dirname, '../../resources/image/zhanwei.png'),
|
||||
config_path: path.join(__dirname, '../../resources/config/global_setting.json'),
|
||||
clip_setting: path.join(__dirname, '../../resources/config/clip_setting.json'),
|
||||
sd_setting: path.join(__dirname, '../../resources/config/sd_config.json'),
|
||||
dynamic_setting: path.join(__dirname, '../../resources/config/dynamic_setting.json'),
|
||||
tag_setting: path.join(__dirname, '../../resources/config/tag_setting.json'),
|
||||
img_base: path.join(__dirname, '../../resources/config/img_base.json'),
|
||||
video_config: path.join(__dirname, '../../resources/config/video_config.json'),
|
||||
system_config: path.join(__dirname, '../../resources/config/system_config.json'),
|
||||
scripts_path: path.join(__dirname, '../../resources/scripts'),
|
||||
db_path: path.join(__dirname, '../../resources/scripts/db'),
|
||||
project_path: path.join(__dirname, '../../project'),
|
||||
tts_path: path.join(__dirname, '../../tts'),
|
||||
logger_path: path.join(__dirname, '../../resources/logger'),
|
||||
package_path: path.join(__dirname, '../../resources/package'),
|
||||
image_path: path.join(__dirname, '../../resources/image'),
|
||||
temp_sd_image: path.join(__dirname, '../../resources/image/TempSDImage'),
|
||||
draft_temp_path: path.join(__dirname, '../../resources/tmp/temp.zip'),
|
||||
init_config_path: path.join(__dirname, '../../resources/tmp/config'),
|
||||
clip_speed_temp_path: path.join(__dirname, '../../resources/tmp/Clip/speeds_tmp.json'),
|
||||
add_canvases_temp_path: path.join(__dirname, '../../resources/tmp/Clip/canvases_tmp.json'),
|
||||
add_sound_channel_mappings_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/sound_channel_mappings_tmp.json'
|
||||
),
|
||||
add_vocal_separations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/vocal_separations_tmp.json'
|
||||
),
|
||||
add_material_video_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/videoMaterialTemp.json'
|
||||
),
|
||||
add_tracks_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/tracks_segments_tmp.json'
|
||||
),
|
||||
add_tracks_type_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/tracks_type_tmp.json'
|
||||
),
|
||||
add_material_animations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/material_animations_tmp.json'
|
||||
),
|
||||
add_material_text_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/material_text_temp.json'
|
||||
),
|
||||
add_track_text_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/track_text_segments_temp.json'
|
||||
),
|
||||
add_materials_beats_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/materials_beats_tmp.json'
|
||||
),
|
||||
add_materials_audios_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/materials_audios_tmp.json'
|
||||
),
|
||||
add_tracks_audio_segments_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/tracks_audio_segments_tmp.json'
|
||||
),
|
||||
add_keyframe_tmp_path: path.join(__dirname, '../../resources/tmp/Clip/keyframe_tmp.json')
|
||||
}
|
||||
} else {
|
||||
define = {
|
||||
zhanwei_image: path.join(__dirname, '../../../resources/image/zhanwei.png'),
|
||||
config_path: path.join(__dirname, '../../../resources/config/global_setting.json'),
|
||||
clip_setting: path.join(__dirname, '../../../resources/config/clip_setting.json'),
|
||||
sd_setting: path.join(__dirname, '../../../resources/config/sd_config.json'),
|
||||
dynamic_setting: path.join(__dirname, '../../../resources/config/dynamic_setting.json'),
|
||||
tag_setting: path.join(__dirname, '../../../resources/config/tag_setting.json'),
|
||||
video_config: path.join(__dirname, '../../../resources/config/video_config.json'),
|
||||
system_config: path.join(__dirname, '../../../resources/config/system_config.json'),
|
||||
img_base: path.join(__dirname, '../../../resources/config/img_base.json'),
|
||||
scripts_path: path.join(__dirname, '../../../resources/scripts'),
|
||||
db_path: path.join(__dirname, '../../../resources/scripts/db'),
|
||||
project_path: path.join(__dirname, '../../../project'),
|
||||
tts_path: path.join(__dirname, '../../../tts'),
|
||||
logger_path: path.join(__dirname, '../../../resources/logger'),
|
||||
package_path: path.join(__dirname, '../../../resources/package'),
|
||||
discordScript: path.join(__dirname, '../../../resources/scripts/discordScript.js'),
|
||||
image_path: path.join(__dirname, '../../../resources/image'),
|
||||
temp_sd_image: path.join(__dirname, '../../../resources/image/TempSDImage'),
|
||||
draft_temp_path: path.join(__dirname, '../../../resources/tmp/temp.zip'),
|
||||
init_config_path: path.join(__dirname, '../../../resources/tmp/config'),
|
||||
clip_speed_temp_path: path.join(__dirname, '../../../resources/tmp/Clip/speeds_tmp.json'),
|
||||
add_canvases_temp_path: path.join(__dirname, '../../../resources/tmp/Clip/canvases_tmp.json'),
|
||||
add_sound_channel_mappings_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/sound_channel_mappings_tmp.json'
|
||||
),
|
||||
add_vocal_separations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/vocal_separations_tmp.json'
|
||||
),
|
||||
add_material_video_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/videoMaterialTemp.json'
|
||||
),
|
||||
add_tracks_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/tracks_segments_tmp.json'
|
||||
),
|
||||
add_tracks_type_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/tracks_type_tmp.json'
|
||||
),
|
||||
add_material_animations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/material_animations_tmp.json'
|
||||
),
|
||||
add_material_text_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/material_text_temp.json'
|
||||
),
|
||||
add_track_text_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/track_text_segments_temp.json'
|
||||
),
|
||||
add_materials_beats_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/materials_beats_tmp.json'
|
||||
),
|
||||
add_materials_audios_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/materials_audios_tmp.json'
|
||||
),
|
||||
add_tracks_audio_segments_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/tracks_audio_segments_tmp.json'
|
||||
),
|
||||
add_keyframe_tmp_path: path.join(__dirname, '../../../resources/tmp/Clip/keyframe_tmp.json')
|
||||
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined'
|
||||
|
||||
if (!isBrowser) {
|
||||
const path = require('path')
|
||||
const { app } = require('electron')
|
||||
if (!app.isPackaged) {
|
||||
define = {
|
||||
discordScript: path.join(__dirname, '../../src/main/discord/discordScript.js'),
|
||||
zhanwei_image: path.join(__dirname, '../../resources/image/zhanwei.png'),
|
||||
config_path: path.join(__dirname, '../../resources/config/global_setting.json'),
|
||||
clip_setting: path.join(__dirname, '../../resources/config/clip_setting.json'),
|
||||
sd_setting: path.join(__dirname, '../../resources/config/sd_config.json'),
|
||||
dynamic_setting: path.join(__dirname, '../../resources/config/dynamic_setting.json'),
|
||||
tag_setting: path.join(__dirname, '../../resources/config/tag_setting.json'),
|
||||
img_base: path.join(__dirname, '../../resources/config/img_base.json'),
|
||||
video_config: path.join(__dirname, '../../resources/config/video_config.json'),
|
||||
system_config: path.join(__dirname, '../../resources/config/system_config.json'),
|
||||
scripts_path: path.join(__dirname, '../../resources/scripts'),
|
||||
db_path: path.join(__dirname, '../../resources/scripts/db'),
|
||||
project_path: path.join(__dirname, '../../project'),
|
||||
tts_path: path.join(__dirname, '../../tts'),
|
||||
logger_path: path.join(__dirname, '../../resources/logger'),
|
||||
package_path: path.join(__dirname, '../../resources/package'),
|
||||
image_path: path.join(__dirname, '../../resources/image'),
|
||||
temp_sd_image: path.join(__dirname, '../../resources/image/TempSDImage'),
|
||||
draft_temp_path: path.join(__dirname, '../../resources/tmp/temp.zip'),
|
||||
init_config_path: path.join(__dirname, '../../resources/tmp/config'),
|
||||
clip_speed_temp_path: path.join(__dirname, '../../resources/tmp/Clip/speeds_tmp.json'),
|
||||
add_canvases_temp_path: path.join(__dirname, '../../resources/tmp/Clip/canvases_tmp.json'),
|
||||
add_sound_channel_mappings_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/sound_channel_mappings_tmp.json'
|
||||
),
|
||||
add_vocal_separations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/vocal_separations_tmp.json'
|
||||
),
|
||||
add_material_video_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/videoMaterialTemp.json'
|
||||
),
|
||||
add_tracks_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/tracks_segments_tmp.json'
|
||||
),
|
||||
add_tracks_type_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/tracks_type_tmp.json'
|
||||
),
|
||||
add_material_animations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/material_animations_tmp.json'
|
||||
),
|
||||
add_material_text_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/material_text_temp.json'
|
||||
),
|
||||
add_track_text_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/track_text_segments_temp.json'
|
||||
),
|
||||
add_materials_beats_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/materials_beats_tmp.json'
|
||||
),
|
||||
add_materials_audios_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/materials_audios_tmp.json'
|
||||
),
|
||||
add_tracks_audio_segments_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../resources/tmp/Clip/tracks_audio_segments_tmp.json'
|
||||
),
|
||||
add_keyframe_tmp_path: path.join(__dirname, '../../resources/tmp/Clip/keyframe_tmp.json')
|
||||
}
|
||||
} else {
|
||||
define = {
|
||||
zhanwei_image: path.join(__dirname, '../../../resources/image/zhanwei.png'),
|
||||
config_path: path.join(__dirname, '../../../resources/config/global_setting.json'),
|
||||
clip_setting: path.join(__dirname, '../../../resources/config/clip_setting.json'),
|
||||
sd_setting: path.join(__dirname, '../../../resources/config/sd_config.json'),
|
||||
dynamic_setting: path.join(__dirname, '../../../resources/config/dynamic_setting.json'),
|
||||
tag_setting: path.join(__dirname, '../../../resources/config/tag_setting.json'),
|
||||
video_config: path.join(__dirname, '../../../resources/config/video_config.json'),
|
||||
system_config: path.join(__dirname, '../../../resources/config/system_config.json'),
|
||||
img_base: path.join(__dirname, '../../../resources/config/img_base.json'),
|
||||
scripts_path: path.join(__dirname, '../../../resources/scripts'),
|
||||
db_path: path.join(__dirname, '../../../resources/scripts/db'),
|
||||
project_path: path.join(__dirname, '../../../project'),
|
||||
tts_path: path.join(__dirname, '../../../tts'),
|
||||
logger_path: path.join(__dirname, '../../../resources/logger'),
|
||||
package_path: path.join(__dirname, '../../../resources/package'),
|
||||
discordScript: path.join(__dirname, '../../../resources/scripts/discordScript.js'),
|
||||
image_path: path.join(__dirname, '../../../resources/image'),
|
||||
temp_sd_image: path.join(__dirname, '../../../resources/image/TempSDImage'),
|
||||
draft_temp_path: path.join(__dirname, '../../../resources/tmp/temp.zip'),
|
||||
init_config_path: path.join(__dirname, '../../../resources/tmp/config'),
|
||||
clip_speed_temp_path: path.join(__dirname, '../../../resources/tmp/Clip/speeds_tmp.json'),
|
||||
add_canvases_temp_path: path.join(__dirname, '../../../resources/tmp/Clip/canvases_tmp.json'),
|
||||
add_sound_channel_mappings_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/sound_channel_mappings_tmp.json'
|
||||
),
|
||||
add_vocal_separations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/vocal_separations_tmp.json'
|
||||
),
|
||||
add_material_video_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/videoMaterialTemp.json'
|
||||
),
|
||||
add_tracks_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/tracks_segments_tmp.json'
|
||||
),
|
||||
add_tracks_type_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/tracks_type_tmp.json'
|
||||
),
|
||||
add_material_animations_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/material_animations_tmp.json'
|
||||
),
|
||||
add_material_text_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/material_text_temp.json'
|
||||
),
|
||||
add_track_text_segments_temp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/track_text_segments_temp.json'
|
||||
),
|
||||
add_materials_beats_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/materials_beats_tmp.json'
|
||||
),
|
||||
add_materials_audios_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/materials_audios_tmp.json'
|
||||
),
|
||||
add_tracks_audio_segments_tmp_path: path.join(
|
||||
__dirname,
|
||||
'../../../resources/tmp/Clip/tracks_audio_segments_tmp.json'
|
||||
),
|
||||
add_keyframe_tmp_path: path.join(__dirname, '../../../resources/tmp/Clip/keyframe_tmp.json')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,4 +159,5 @@ define['API'] = 'f85d39ed5a40fd09966f13f12b6cf0f0'
|
||||
|
||||
define['lms'] = 'https://lms.laitool.cn'
|
||||
|
||||
|
||||
export { define }
|
||||
|
||||
@ -1,15 +1,4 @@
|
||||
|
||||
/**
|
||||
* Flux 调用API时候的 生图模型
|
||||
*/
|
||||
export enum FLxuAPIImageType {
|
||||
FLUX = "flux",
|
||||
FLUX_PRO = "flux-pro",
|
||||
FLUX_DEV = "flux-dev",
|
||||
FLUX_SCHNELL = "flux-schnell",
|
||||
FLUX_PRO_MAX = "flux-pro-max"
|
||||
}
|
||||
|
||||
|
||||
export enum PresetType {
|
||||
// 角色
|
||||
|
||||
@ -35,10 +35,10 @@ export enum MJRobotType {
|
||||
|
||||
export enum MJSpeed {
|
||||
// 快速
|
||||
FAST = 'fast',
|
||||
FAST = 'FAST',
|
||||
|
||||
// 休闲
|
||||
RELAX = 'relaxed'
|
||||
RELAX = 'RELAXED'
|
||||
}
|
||||
|
||||
export enum MJRespoonseType {
|
||||
|
||||
@ -36,5 +36,25 @@ export enum OptionKeyName {
|
||||
*/
|
||||
TTS_GlobalSetting = 'TTS_GlobalSetting',
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region MJ
|
||||
|
||||
/**
|
||||
* MJ 基础设置
|
||||
*/
|
||||
MJ_GlobalSetting = 'MJ_GlobalSetting',
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region FLUX
|
||||
|
||||
/**
|
||||
* FLUX API 模型列表
|
||||
*/
|
||||
FLUX_APIModelList = 'FLUX_APIModelList',
|
||||
|
||||
|
||||
//#endregion
|
||||
}
|
||||
25
src/define/response/ForwardResponse.ts
Normal file
25
src/define/response/ForwardResponse.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { ValidateJson } from "../Tools/validate";
|
||||
|
||||
/**
|
||||
* 获取转发请求的数据,序列化后返回
|
||||
* @param response
|
||||
* @returns
|
||||
*/
|
||||
function GetForwardResponseData(response: any) {
|
||||
if (response.status != 200) {
|
||||
throw new Error("转发请求失败")
|
||||
}
|
||||
if (response.data.code != 1) {
|
||||
throw new Error(response.data.message)
|
||||
}
|
||||
if (!ValidateJson(response.data.data)) {
|
||||
throw new Error(response.data.data)
|
||||
}
|
||||
return JSON.parse(response.data.data);
|
||||
}
|
||||
|
||||
let ForwardResponse = {
|
||||
GetForwardResponseData,
|
||||
}
|
||||
|
||||
export default ForwardResponse;
|
||||
@ -60,7 +60,6 @@ function MjIpc() {
|
||||
)
|
||||
|
||||
// 获取MJ生图的方式
|
||||
// GetMJGenerateCategory: async (callback) => callback(await ipcRenderer.invoke(DEFINE_STRING.MJ.GET_MJ_GENERATE_CATEGORY)),
|
||||
ipcMain.handle(
|
||||
DEFINE_STRING.MJ.GET_MJ_GENERATE_CATEGORY,
|
||||
async (event) => await mjSimple.GetMJGenerateCategory()
|
||||
|
||||
@ -10,7 +10,7 @@ function OptionsIpc() {
|
||||
*/
|
||||
ipcMain.handle(
|
||||
DEFINE_STRING.OPTIONS.GET_OPTION_BY_KEY,
|
||||
async (_, key: string) => await OptionHandle.GetOptionByKey(key)
|
||||
async (_, key: string | string[]) => await OptionHandle.GetOptionByKey(key)
|
||||
)
|
||||
|
||||
/**
|
||||
|
||||
@ -4,7 +4,6 @@ import { DEFINE_STRING } from '../../define/define_string'
|
||||
import { define } from '../../define/define'
|
||||
let fspromises = require('fs').promises
|
||||
import { gptDefine } from '../../define/gptDefine'
|
||||
import { apiUrl } from '../../define/api/apiUrlDefine'
|
||||
import { successMessage } from '../Public/generalTools'
|
||||
import { RetryWithBackoff } from '../../define/Tools/common'
|
||||
|
||||
|
||||
@ -11,6 +11,8 @@ import { Base64ToFile, GetImageBase64 } from '../../../define/Tools/image';
|
||||
import { BookBackTaskStatus } from '../../../define/enum/bookEnum';
|
||||
import { MJAction, MJImageType } from '../../../define/enum/mjEnum';
|
||||
import { GptService } from '../GPT/gpt';
|
||||
import { TaskModal } from '@/model/task';
|
||||
import { ValidateJson } from '@/define/Tools/validate';
|
||||
|
||||
export class FluxOpt {
|
||||
gptService: GptService
|
||||
@ -203,18 +205,55 @@ export class FluxOpt {
|
||||
* @param body 请求的请求体
|
||||
* @returns
|
||||
*/
|
||||
async FluxAPIImageRequest(url: string, key: string, body: { model: string; prompt: string; size: string; }): Promise<string> {
|
||||
let response = await axios.post(url, { ...body, n: 1 }, {
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + key
|
||||
}
|
||||
})
|
||||
async FluxAPIImageRequest(url: string, key: string, body: { model: string; prompt: string; size: string; }, useTransfer: boolean): Promise<string> {
|
||||
|
||||
if (response.data && response.data.data && response.data.data.length > 0) {
|
||||
return response.data.data[0].url
|
||||
} else {
|
||||
return undefined
|
||||
let data = {
|
||||
...body,
|
||||
n: 1
|
||||
}
|
||||
|
||||
let resData: any = [];
|
||||
|
||||
if (useTransfer) {
|
||||
let transferUrl = define.lms + "/lms/Forward/SimpleTransfer";
|
||||
let transferConfig = {
|
||||
method: 'post',
|
||||
url: transferUrl,
|
||||
maxBodyLength: Infinity,
|
||||
timeout: 600000, // 600 seconds timeout
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify({
|
||||
url: url,
|
||||
apiKey: key,
|
||||
dataString: JSON.stringify(data)
|
||||
})
|
||||
}
|
||||
let response = await axios(transferConfig)
|
||||
if (response.status != 200) {
|
||||
throw new Error("转发请求失败")
|
||||
}
|
||||
if (response.data.code != 1) {
|
||||
throw new Error(response.data.message)
|
||||
}
|
||||
if (!ValidateJson(response.data.data)) {
|
||||
throw new Error(response.data.data)
|
||||
}
|
||||
let re = JSON.parse(response.data.data);
|
||||
resData = re.data
|
||||
} else {
|
||||
let response = await axios.post(url, data, {
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + key
|
||||
}
|
||||
})
|
||||
resData = response.data.data
|
||||
}
|
||||
if (!Array.isArray(resData) || resData.length == 0) {
|
||||
throw new Error("FLUX API 返回数据异常")
|
||||
}
|
||||
return resData[0].url
|
||||
}
|
||||
|
||||
/**
|
||||
@ -239,7 +278,11 @@ export class FluxOpt {
|
||||
prompt = sdSetting.webui.prompt + ', ' + prompt
|
||||
}
|
||||
let size = `${sdSetting.webui.width}x${sdSetting.webui.height}`
|
||||
if (!sdSetting.flux.model) {
|
||||
throw new Error('FLUX API 模型为空,请先设置!')
|
||||
}
|
||||
let model = sdSetting.flux.model
|
||||
let useTransfer = sdSetting.flux.useTransfer
|
||||
// 一次请求生成一张 多个请求
|
||||
|
||||
let SdOriginalImage = path.join(book.bookFolderPath, 'data/SdOriginalImage');
|
||||
@ -259,7 +302,7 @@ export class FluxOpt {
|
||||
model: model,
|
||||
prompt: prompt,
|
||||
size: size
|
||||
})
|
||||
}, useTransfer)
|
||||
// 这边开始处理返回的数据
|
||||
if (isEmpty(imageUrl)) {
|
||||
throw new Error('FLUX 生图返回的图片地址为空')
|
||||
|
||||
@ -9,7 +9,7 @@ import { BookBackTaskStatus, BookBackTaskType, BookTaskStatus, BookType, DialogT
|
||||
import { DEFINE_STRING } from "../../../define/define_string";
|
||||
import { MJ } from "../../../model/mj";
|
||||
import { MJRespoonseType } from "../../../define/enum/mjEnum";
|
||||
import { MJSetting } from "../../../model/Setting/mjSetting";
|
||||
import { MJSettingModel } from "../../../model/Setting/mjSetting";
|
||||
import { GeneralResponse } from "../../../model/generalResponse"
|
||||
import { LoggerStatus, ResponseMessageType } from "../../../define/enum/softwareEnum";
|
||||
import { ImageStyle } from "../Book/imageStyle";
|
||||
@ -27,7 +27,7 @@ const fspromise = fs.promises
|
||||
|
||||
export class MJOpt {
|
||||
mjApi: MJApi;
|
||||
mjSetting: MJSetting.MjSetting
|
||||
mjSimpleSetting: MJSettingModel.MjSimpleSettingModel;
|
||||
imageStyle: ImageStyle;
|
||||
logScheduler: LogScheduler;
|
||||
tools: Tools;
|
||||
@ -48,8 +48,8 @@ export class MJOpt {
|
||||
* 获取MJ设置
|
||||
*/
|
||||
async GetMJSetting() {
|
||||
if (!this.mjSetting) {
|
||||
this.mjSetting = await this.softWareServiceBasic.GetMjSetting()
|
||||
if (!this.mjSimpleSetting) {
|
||||
this.mjSimpleSetting = await this.softWareServiceBasic.GetMjSetting()
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,7 +231,7 @@ export class MJOpt {
|
||||
code: 1,
|
||||
type: MJRespoonseType.UPDATED,
|
||||
mjType: MJAction.DESCRIBE,
|
||||
category: this.mjSetting.type,
|
||||
category: this.mjSimpleSetting.type,
|
||||
messageId: reqRes,
|
||||
id: task.bookTaskDetailId,
|
||||
progress: 0,
|
||||
@ -258,7 +258,7 @@ export class MJOpt {
|
||||
code: 0,
|
||||
type: MJRespoonseType.UPDATED,
|
||||
mjType: MJAction.DESCRIBE,
|
||||
category: this.mjSetting.type,
|
||||
category: this.mjSimpleSetting.type,
|
||||
messageId: undefined,
|
||||
id: task.bookTaskDetailId,
|
||||
progress: 0,
|
||||
@ -560,7 +560,7 @@ export class MJOpt {
|
||||
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
|
||||
mjApiUrl: this.mjApi.imagineUrl,
|
||||
progress: 100,
|
||||
category: this.mjApi.mjSetting.type,
|
||||
category: this.mjApi.mjSimpleSetting.type,
|
||||
imageClick: task_res.imageClick,
|
||||
imageShow: task_res.imageShow,
|
||||
messageId: task_res.messageId,
|
||||
@ -622,7 +622,7 @@ export class MJOpt {
|
||||
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
|
||||
mjApiUrl: this.mjApi.imagineUrl,
|
||||
progress: 100,
|
||||
category: this.mjApi.mjSetting.type,
|
||||
category: this.mjApi.mjSimpleSetting.type,
|
||||
imageClick: task_res.imageClick,
|
||||
imageShow: task_res.imageShow,
|
||||
messageId: task_res.messageId,
|
||||
@ -644,7 +644,7 @@ export class MJOpt {
|
||||
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
|
||||
mjApiUrl: this.mjApi.imagineUrl,
|
||||
progress: task_res.progress,
|
||||
category: this.mjApi.mjSetting.type,
|
||||
category: this.mjApi.mjSimpleSetting.type,
|
||||
imageClick: task_res.imageClick,
|
||||
imageShow: task_res.imageShow,
|
||||
messageId: task_res.messageId,
|
||||
@ -697,7 +697,6 @@ export class MJOpt {
|
||||
// 这个就是任务ID
|
||||
let reqRes = await this.mjApi.SubmitMJImagine(task.id, prompt)
|
||||
if (reqRes == '23') {
|
||||
console.log(task.id, "33333")
|
||||
// 任务队列过多,重新提交排队
|
||||
await this.bookServiceBasic.UpdateTaskStatus({
|
||||
id: task.id,
|
||||
@ -711,7 +710,7 @@ export class MJOpt {
|
||||
code: 1,
|
||||
type: MJRespoonseType.UPDATED,
|
||||
mjType: MJAction.IMAGINE,
|
||||
category: this.mjSetting.type,
|
||||
category: this.mjSimpleSetting.type,
|
||||
message_id: '',
|
||||
id: task.bookTaskDetailId,
|
||||
progress: 0,
|
||||
@ -721,7 +720,7 @@ export class MJOpt {
|
||||
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
|
||||
mjApiUrl: this.mjApi.imagineUrl,
|
||||
progress: 0,
|
||||
category: this.mjApi.mjSetting.type,
|
||||
category: this.mjApi.mjSimpleSetting.type,
|
||||
imageClick: "",
|
||||
imageShow: "",
|
||||
messageId: "",
|
||||
@ -747,7 +746,7 @@ export class MJOpt {
|
||||
code: 1,
|
||||
type: MJRespoonseType.UPDATED,
|
||||
mjType: MJAction.IMAGINE,
|
||||
category: this.mjSetting.type,
|
||||
category: this.mjSimpleSetting.type,
|
||||
message_id: reqRes,
|
||||
id: task.bookTaskDetailId,
|
||||
progress: 0,
|
||||
@ -773,7 +772,7 @@ export class MJOpt {
|
||||
code: 0,
|
||||
type: MJRespoonseType.UPDATED,
|
||||
mjType: MJAction.IMAGINE,
|
||||
category: this.mjSetting.type,
|
||||
category: this.mjSimpleSetting.type,
|
||||
messageId: undefined,
|
||||
id: task.bookTaskDetailId,
|
||||
progress: 0,
|
||||
@ -784,7 +783,7 @@ export class MJOpt {
|
||||
await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, {
|
||||
mjApiUrl: this.mjApi.imagineUrl,
|
||||
progress: 0,
|
||||
category: this.mjApi.mjSetting.type,
|
||||
category: this.mjApi.mjSimpleSetting.type,
|
||||
imageClick: "",
|
||||
imageShow: "",
|
||||
messageId: "",
|
||||
|
||||
@ -1,65 +1,83 @@
|
||||
import axios from "axios"
|
||||
import { define } from "../../../define/define"
|
||||
import { GetImageBase64 } from "../../../define/Tools/image"
|
||||
import { MJImageType, MJRespoonseType, MJSpeed } from "../../../define/enum/mjEnum"
|
||||
import { MJImageType, MJRespoonseType, MJRobotType, MJSpeed } from "../../../define/enum/mjEnum"
|
||||
import { MJSettingService } from "../../../define/db/service/SoftWare/mjSettingService"
|
||||
import { BookBackTaskListService } from "../../../define/db/service/Book/bookBackTaskListService"
|
||||
import { BookBackTaskStatus } from "../../../define/enum/bookEnum"
|
||||
import { MJSetting } from "../../../model/Setting/mjSetting"
|
||||
import { GPT } from "../../Public/GPT"
|
||||
import { MJSettingModel } from "../../../model/Setting/mjSetting"
|
||||
import { MJ } from "../../../model/mj"
|
||||
import { LaiAPIType } from "../../../define/enum/softwareEnum"
|
||||
import { isEmpty } from "lodash"
|
||||
import { OptionServices } from "../Options/optionServices"
|
||||
import { OptionKeyName } from "@/define/enum/option"
|
||||
import { ValidateJson } from "@/define/Tools/validate"
|
||||
import { apiUrl } from "@/define/api/apiUrlDefine"
|
||||
|
||||
/**
|
||||
* 调用MJ的API类
|
||||
*/
|
||||
class MJApi {
|
||||
mjSetting: MJSetting.MjSetting
|
||||
mjSimpleSetting: MJSettingModel.MjSimpleSettingModel
|
||||
bootType: string
|
||||
imagineUrl: string
|
||||
fetchTaskUrl: string
|
||||
describeUrl: string
|
||||
|
||||
optionServices: OptionServices
|
||||
|
||||
mj_globalSetting: MJSettingModel.MJ_GlobalSettingModel
|
||||
|
||||
constructor() {
|
||||
this.bootType = "MID_JOURNEY"
|
||||
this.optionServices = new OptionServices()
|
||||
}
|
||||
|
||||
async InitMJSetting(): Promise<MJSetting.MjSetting> {
|
||||
/**
|
||||
* 初始化MJ设置
|
||||
*/
|
||||
async InitMJSetting(): Promise<void> {
|
||||
// 获取MJ配置,从数据库中
|
||||
let _mjSettingService = await MJSettingService.getInstance()
|
||||
let mjSettings = _mjSettingService.GetMJSettingTreeData()
|
||||
if (mjSettings.code == 0) {
|
||||
throw new Error(mjSettings.message)
|
||||
}
|
||||
this.mjSetting = mjSettings.data
|
||||
this.bootType = this.mjSetting.selectRobot == "niji" ? "NIJI_JOURNEY" : "MID_JOURNEY"
|
||||
if (this.mjSetting.type == MJImageType.REMOTE_MJ) {
|
||||
|
||||
|
||||
let mjSettingData = await this.optionServices.GetOptionByKey(OptionKeyName.MJ_GlobalSetting);
|
||||
if (mjSettingData.code == 0) {
|
||||
throw new Error("加载MJ设置失败,失败原因如下:" + mjSettingData.message)
|
||||
}
|
||||
if (mjSettingData.data == null) {
|
||||
throw new Error("加载MJ设置失败,失败原因如下:没有找到对应的MJ设置,请先去MJ设置中设置")
|
||||
}
|
||||
if (!ValidateJson(mjSettingData.data.value)) {
|
||||
throw new Error("MJ设置的数据格式不正确,请检查数据格式")
|
||||
}
|
||||
|
||||
this.mj_globalSetting = JSON.parse(mjSettingData.data.value) as MJSettingModel.MJ_GlobalSettingModel
|
||||
this.mjSimpleSetting = this.mj_globalSetting.mj_simpleSetting
|
||||
|
||||
this.bootType = this.mjSimpleSetting.selectRobot == MJRobotType.NIJI ? "NIJI_JOURNEY" : "MID_JOURNEY"
|
||||
if (this.mjSimpleSetting.type == MJImageType.REMOTE_MJ) {
|
||||
this.imagineUrl = define.remotemj_api + 'mj/submit/imagine'
|
||||
this.describeUrl = define.remotemj_api + 'mj/submit/describe'
|
||||
this.fetchTaskUrl = define.remotemj_api + 'mj/task/${id}/fetch'
|
||||
} else {
|
||||
if (global.config.laiApiSelect == LaiAPIType.HK_PROXY) {
|
||||
this.imagineUrl = define.hkServerUrl + 'mj/submit/imagine'
|
||||
this.describeUrl = define.hkServerUrl + 'mj/submit/describe'
|
||||
this.fetchTaskUrl = define.hkServerUrl + 'mj/task/${id}/fetch'
|
||||
} else if (global.config.laiApiSelect == LaiAPIType.BAK_MAIN) {
|
||||
this.imagineUrl = define.bakServerUrl + 'mj/submit/imagine'
|
||||
this.describeUrl = define.bakServerUrl + 'mj/submit/describe'
|
||||
this.fetchTaskUrl = define.bakServerUrl + 'mj/task/${id}/fetch'
|
||||
} else {
|
||||
let gpt = new GPT()
|
||||
let mj_api = (await gpt.GetGPTBusinessOption('all', (value) => value.mj_url)).data
|
||||
let mj_api_url_index = mj_api.findIndex((item) => item.value == this.mjSetting.apiSetting.mjApiUrl)
|
||||
if (mj_api_url_index == -1) {
|
||||
throw new Error('没有找到对应的MJ API的配置,请先检查配置')
|
||||
}
|
||||
this.imagineUrl = mj_api[mj_api_url_index].mj_url.imagine;
|
||||
this.fetchTaskUrl = mj_api[mj_api_url_index].mj_url.once_get_task;
|
||||
this.describeUrl = mj_api[mj_api_url_index].mj_url.imagine.replace("imagine", "describe");
|
||||
|
||||
let apiUrlIndex = apiUrl.findIndex(item => item.value == this.mj_globalSetting.mj_apiSetting.mjApiUrl);
|
||||
if (apiUrlIndex == -1) {
|
||||
throw new Error('没有找到MJ API对应的请求URL,请检查配置');
|
||||
}
|
||||
|
||||
let apiUrlItem = apiUrl[apiUrlIndex];
|
||||
if (apiUrlItem.mj_url == null) {
|
||||
throw new Error('没有找到MJ API对应的请求URL,请检查配置');
|
||||
}
|
||||
|
||||
this.imagineUrl = apiUrlItem.mj_url.imagine
|
||||
this.describeUrl = apiUrlItem.mj_url.describe
|
||||
this.fetchTaskUrl = apiUrlItem.mj_url.once_get_task
|
||||
}
|
||||
return mjSettings.data
|
||||
}
|
||||
|
||||
//#region 获取对应的任务,通过ID
|
||||
@ -71,27 +89,66 @@ class MJApi {
|
||||
async GetMJAPITaskById(taskId: string, backTaskId: string) {
|
||||
try {
|
||||
await this.InitMJSetting();
|
||||
let url = this.fetchTaskUrl.replace("${id}", taskId)
|
||||
let APIDescribeUrl = this.fetchTaskUrl.replace("${id}", taskId)
|
||||
let headers = undefined
|
||||
if (this.mjSetting.type == MJImageType.REMOTE_MJ) {
|
||||
let useTransfer = false
|
||||
|
||||
if (this.mjSimpleSetting.type == MJImageType.REMOTE_MJ) {
|
||||
headers = {
|
||||
'mj-api-secret': define.API
|
||||
}
|
||||
useTransfer = this.mj_globalSetting.mj_remoteSimpleSetting.useTransfer
|
||||
} else {
|
||||
headers = {
|
||||
Authorization: this.mjSetting.apiSetting.apiKey
|
||||
Authorization: this.mj_globalSetting.mj_apiSetting.apiKey
|
||||
}
|
||||
useTransfer = this.mj_globalSetting.mj_apiSetting.useTransfer
|
||||
}
|
||||
|
||||
let res = await axios.get(url, {
|
||||
headers: headers
|
||||
})
|
||||
let resData = undefined
|
||||
if (useTransfer) {
|
||||
|
||||
let progress = res.data.progress && res.data.progress.length > 0
|
||||
? parseInt(res.data.progress.slice(0, -1))
|
||||
let url = define.lms + "/lms/Forward/GetTransfer";
|
||||
let config = {
|
||||
method: 'post',
|
||||
url: url,
|
||||
maxBodyLength: Infinity,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify({
|
||||
url: APIDescribeUrl,
|
||||
apiKey: this.mjSimpleSetting.type == MJImageType.REMOTE_MJ ?
|
||||
define.API :
|
||||
headers.Authorization,
|
||||
})
|
||||
}
|
||||
|
||||
let res = await axios.request(config);
|
||||
if (res.status != 200) {
|
||||
throw new Error("转发请求失败")
|
||||
}
|
||||
if (res.data.code != 1) {
|
||||
throw new Error(res.data.message)
|
||||
}
|
||||
if (!ValidateJson(res.data.data)) {
|
||||
throw new Error(res.data.data)
|
||||
}
|
||||
resData = JSON.parse(res.data.data);
|
||||
|
||||
} else {
|
||||
let res = await axios.get(APIDescribeUrl, {
|
||||
headers: headers
|
||||
})
|
||||
resData = res.data
|
||||
}
|
||||
|
||||
|
||||
let progress = resData.progress && resData.progress.length > 0
|
||||
? parseInt(resData.progress.slice(0, -1))
|
||||
: 0
|
||||
|
||||
let status = res.data.status.toLowerCase()
|
||||
let status = resData.status.toLowerCase()
|
||||
let code = status == 'failure' || status == 'cancel' ? 0 : 1
|
||||
|
||||
let _bookBackTaskListService = await BookBackTaskListService.getInstance()
|
||||
@ -101,22 +158,22 @@ class MJApi {
|
||||
_bookBackTaskListService.UpdateTaskStatus({
|
||||
id: backTaskId,
|
||||
status: BookBackTaskStatus.FAIL,
|
||||
errorMessage: res.data.message
|
||||
errorMessage: resData.message
|
||||
})
|
||||
}
|
||||
}
|
||||
let resObj = {
|
||||
type: MJRespoonseType.UPDATED,
|
||||
progress: isNaN(progress) ? 0 : progress,
|
||||
category: this.mjSetting.type,
|
||||
imageClick: res.data.imageUrl,
|
||||
imageShow: res.data.imageUrl,
|
||||
imagePath: res.data.imageUrl,
|
||||
category: this.mjSimpleSetting.type,
|
||||
imageClick: resData.imageUrl,
|
||||
imageShow: resData.imageUrl,
|
||||
imagePath: resData.imageUrl,
|
||||
messageId: taskId,
|
||||
status: status,
|
||||
code: code,
|
||||
prompt: res.data.prompt == "" ? res.data.promptEn : res.data.prompt,
|
||||
message: res.data.failReason,
|
||||
prompt: resData.prompt == "" ? resData.promptEn : resData.prompt,
|
||||
message: resData.failReason,
|
||||
mjApiUrl: this.fetchTaskUrl,
|
||||
} as MJ.MJResponseToFront
|
||||
return resObj
|
||||
@ -135,7 +192,7 @@ class MJApi {
|
||||
async SubmitMJDescribe(param: MJ.APIDescribeParams): Promise<string> {
|
||||
await this.InitMJSetting()
|
||||
let res = undefined
|
||||
switch (this.mjSetting.type) {
|
||||
switch (this.mjSimpleSetting.type) {
|
||||
case MJImageType.REMOTE_MJ:
|
||||
case MJImageType.API_MJ:
|
||||
res = await this.SubmitMJDescribeAPI(param)
|
||||
@ -157,7 +214,7 @@ class MJApi {
|
||||
botType: this.bootType,
|
||||
base64: param.image,
|
||||
accountFilter: {
|
||||
modes: [this.mjSetting.apiSetting.mjSpeed == MJSpeed.FAST ? "FAST" : "RELAX"],
|
||||
modes: [this.mj_globalSetting.mj_apiSetting.mjSpeed == MJSpeed.FAST ? "FAST" : "RELAX"],
|
||||
remark: global.machineId
|
||||
},
|
||||
|
||||
@ -168,11 +225,12 @@ class MJApi {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mjSetting.type == MJImageType.REMOTE_MJ) {
|
||||
if (this.mjSimpleSetting.type == MJImageType.REMOTE_MJ) {
|
||||
config.headers["mj-api-secret"] = define.API;
|
||||
delete data.accountFilter.modes;
|
||||
} else {
|
||||
delete data.accountFilter.remark
|
||||
config.headers["Authorization"] = this.mjSetting.apiSetting.apiKey;
|
||||
config.headers["Authorization"] = this.mj_globalSetting.mj_apiSetting.apiKey;
|
||||
}
|
||||
|
||||
// 开始请求
|
||||
@ -215,7 +273,7 @@ class MJApi {
|
||||
async SubmitMJImagine(taskId: string, prompt: string): Promise<string> {
|
||||
await this.InitMJSetting()
|
||||
let res = undefined
|
||||
switch (this.mjSetting.type) {
|
||||
switch (this.mjSimpleSetting.type) {
|
||||
case MJImageType.REMOTE_MJ:
|
||||
case MJImageType.API_MJ:
|
||||
res = await this.SubmitMJImagineAPI(taskId, prompt)
|
||||
@ -233,12 +291,13 @@ class MJApi {
|
||||
async SubmitMJImagineAPI(taskId: string, prompt: string): Promise<string> {
|
||||
|
||||
let _bookBackTaskListService = await BookBackTaskListService.getInstance()
|
||||
|
||||
// 提交API的出图任务
|
||||
let data = {
|
||||
botType: this.bootType,
|
||||
prompt: prompt,
|
||||
accountFilter: {
|
||||
modes: [this.mjSetting.apiSetting.mjSpeed == MJSpeed.FAST ? "FAST" : "RELAX"],
|
||||
modes: [this.mj_globalSetting.mj_apiSetting.mjSpeed == MJSpeed.FAST ? "FAST" : "RELAX"],
|
||||
remark: global.machineId
|
||||
},
|
||||
|
||||
@ -249,18 +308,59 @@ class MJApi {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.mjSetting.type == MJImageType.REMOTE_MJ) {
|
||||
let useTransfer = false;
|
||||
|
||||
if (this.mjSimpleSetting.type == MJImageType.REMOTE_MJ) {
|
||||
config.headers["mj-api-secret"] = define.API;
|
||||
delete data.accountFilter.modes;
|
||||
useTransfer = this.mj_globalSetting.mj_remoteSimpleSetting.useTransfer
|
||||
} else {
|
||||
delete data.accountFilter.remark
|
||||
config.headers["Authorization"] = this.mjSetting.apiSetting.apiKey;
|
||||
config.headers["Authorization"] = this.mj_globalSetting.mj_apiSetting.apiKey;
|
||||
useTransfer = this.mj_globalSetting.mj_apiSetting.useTransfer
|
||||
}
|
||||
|
||||
// 开始请求
|
||||
let res = await axios.post(this.imagineUrl, data, config)
|
||||
let resData: any = undefined;
|
||||
if (useTransfer) {
|
||||
|
||||
let url = define.lms + "/lms/Forward/SimpleTransfer"
|
||||
let transferConfig = {
|
||||
method: 'post',
|
||||
url: url,
|
||||
maxBodyLength: Infinity,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify({
|
||||
url: this.imagineUrl,
|
||||
apiKey: this.mjSimpleSetting.type == MJImageType.REMOTE_MJ ? define.API : this.mj_globalSetting.mj_apiSetting.apiKey,
|
||||
dataString: JSON.stringify(data)
|
||||
})
|
||||
}
|
||||
let res = await axios.request(transferConfig);
|
||||
if (res.status != 200) {
|
||||
throw new Error("转发请求失败")
|
||||
}
|
||||
if (res.data.code != 1) {
|
||||
throw new Error(res.data.message)
|
||||
}
|
||||
if (!ValidateJson(res.data.data)) {
|
||||
throw new Error(res.data.data)
|
||||
}
|
||||
let re = JSON.parse(res.data.data);
|
||||
resData = re
|
||||
} else {
|
||||
|
||||
// 开始请求
|
||||
let res = await axios.post(this.imagineUrl, data, config)
|
||||
resData = res.data
|
||||
}
|
||||
|
||||
if (resData == null) {
|
||||
throw new Error("返回的数据为空")
|
||||
}
|
||||
// 某些API的返回的code为23,表示队列已满,需要重新请求
|
||||
if (res.data.code == 23) {
|
||||
if (resData.code == 23) {
|
||||
_bookBackTaskListService.UpdateTaskStatus({
|
||||
id: taskId,
|
||||
status: BookBackTaskStatus.RECONNECT
|
||||
@ -268,13 +368,13 @@ class MJApi {
|
||||
return '23'
|
||||
}
|
||||
|
||||
if (res.data.code != 1 && res.data.code != 22) {
|
||||
if (resData.code != 1 && resData.code != 22) {
|
||||
_bookBackTaskListService.UpdateTaskStatus({
|
||||
id: taskId,
|
||||
status: BookBackTaskStatus.FAIL,
|
||||
errorMessage: res.data.description
|
||||
errorMessage: resData.description
|
||||
})
|
||||
throw new Error(res.data.description)
|
||||
throw new Error(resData.description)
|
||||
}
|
||||
|
||||
_bookBackTaskListService.UpdateTaskStatus({
|
||||
@ -282,7 +382,7 @@ class MJApi {
|
||||
status: BookBackTaskStatus.RUNNING
|
||||
})
|
||||
|
||||
return res.data.result as string
|
||||
return resData.result as string
|
||||
}
|
||||
|
||||
|
||||
|
||||
169
src/main/Service/MJ/mjDefine.ts
Normal file
169
src/main/Service/MJ/mjDefine.ts
Normal file
@ -0,0 +1,169 @@
|
||||
import { apiUrl } from "@/define/api/apiUrlDefine"
|
||||
import { MJRobotType, MJSpeed } from "@/define/enum/mjEnum"
|
||||
|
||||
/**
|
||||
* 获取MJ的请求模式列表
|
||||
* @returns
|
||||
*/
|
||||
function GetMJRequestModelOptions() {
|
||||
let mjRequstModel = [{
|
||||
label: "本地MJ(待开发)",
|
||||
value: "local_mj",
|
||||
disable: true
|
||||
},
|
||||
{
|
||||
label: "代理MJ(token)",
|
||||
value: "remote_mj",
|
||||
disable: false
|
||||
},
|
||||
{
|
||||
label: "浏览器模式",
|
||||
value: "browser_mj",
|
||||
disable: false
|
||||
},
|
||||
{
|
||||
label: "API模式",
|
||||
value: "api_mj",
|
||||
disable: false
|
||||
}]
|
||||
return mjRequstModel.filter(item => !item.disable)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取MJ的机器人列表
|
||||
* @returns
|
||||
*/
|
||||
function GetMJRobotOptions() {
|
||||
return [{
|
||||
label: 'MJ',
|
||||
value: MJRobotType.MJ
|
||||
},
|
||||
{
|
||||
label: 'NIJI',
|
||||
value: MJRobotType.NIJI
|
||||
}]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取机器人对应的出图模型
|
||||
*/
|
||||
function GetMJRobotModelOptions(mjRobot?: MJRobotType) {
|
||||
let allRobotModel = [
|
||||
{
|
||||
label: "MJ V6.0",
|
||||
text: "v 6",
|
||||
type: MJRobotType.MJ,
|
||||
value: "3e6473ab-9a64-4574-9a38-f5c75af552b6"
|
||||
},
|
||||
{
|
||||
label: "MJ V5.2",
|
||||
text: "v 5.2",
|
||||
type: MJRobotType.MJ,
|
||||
value: "27a0d30e-f46c-4684-96c8-d91334deb94f"
|
||||
},
|
||||
{
|
||||
label: "MJ V5.1",
|
||||
text: "v 5.1",
|
||||
type: MJRobotType.MJ,
|
||||
value: "e1226715-e969-44c4-b18b-f2ad5dae5d2f"
|
||||
}, {
|
||||
label: "MJ V5.0",
|
||||
text: "v 5",
|
||||
type: MJRobotType.MJ,
|
||||
value: "afb7bea1-4eda-46ea-8165-34701b4566bf"
|
||||
}, {
|
||||
label: "MJ V4.0",
|
||||
text: "v 4",
|
||||
type: MJRobotType.MJ,
|
||||
value: "d05b8497-7f4a-4890-8fac-89f1803984d2"
|
||||
}, {
|
||||
label: "NIJI V6",
|
||||
text: "niji 6",
|
||||
type: MJRobotType.NIJI,
|
||||
value: "99377cad-c103-4cee-a958-86a104879328"
|
||||
}, {
|
||||
label: "NIJI V5",
|
||||
text: "niji 5",
|
||||
type: MJRobotType.NIJI,
|
||||
value: "53cec077-9885-4635-ab18-e021066b2c4c"
|
||||
}, {
|
||||
label: "NIJI V4",
|
||||
text: "niji 4",
|
||||
type: MJRobotType.NIJI,
|
||||
value: "6a7199fe-6e0d-40a9-9772-b5eb3d2e2e66"
|
||||
},
|
||||
]
|
||||
|
||||
switch (mjRobot) {
|
||||
case MJRobotType.MJ:
|
||||
return allRobotModel.filter(item => item.type == MJRobotType.MJ)
|
||||
case MJRobotType.NIJI:
|
||||
return allRobotModel.filter(item => item.type == MJRobotType.NIJI)
|
||||
default:
|
||||
return allRobotModel
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取MJ出图的比例Options
|
||||
* @returns
|
||||
*/
|
||||
function GetMJImageScaleOptions() {
|
||||
return [{
|
||||
label: "1:1",
|
||||
text: "1:1",
|
||||
value: "3e2772f2-041c-49c6-ba13-d0ed120310b8"
|
||||
}, {
|
||||
label: "4:3",
|
||||
text: "4:3",
|
||||
value: "fcef555c-1958-4082-88fe-434782aa8151"
|
||||
}, {
|
||||
label: "3:4",
|
||||
text: "3:4",
|
||||
value: "13f71d53-73a3-4c9b-9c1e-6e7e939aee73"
|
||||
}, {
|
||||
label: "16:9",
|
||||
text: "16:9",
|
||||
value: "bf33ce1a-15cd-4901-b38e-89543cf14a1f"
|
||||
}, {
|
||||
label: "9:16",
|
||||
text: "9:16",
|
||||
value: "fd4641e2-97f4-4a86-8616-4965e05f3348"
|
||||
}]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取MJ API 可用的URL Options
|
||||
* @returns
|
||||
*/
|
||||
function GetMJAPIUrlOptions() {
|
||||
return apiUrl.filter((item) => item.mj_url)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取MJ的速度Options
|
||||
* @returns
|
||||
*/
|
||||
function GetMJSpeedOptions() {
|
||||
return [{
|
||||
label: "FAST",
|
||||
value: MJSpeed.FAST
|
||||
}, {
|
||||
label: "RELAXED",
|
||||
value: MJSpeed.RELAX
|
||||
}]
|
||||
}
|
||||
|
||||
/**
|
||||
* MJ的一些数据的定义
|
||||
*/
|
||||
let MJDefine = {
|
||||
GetMJRequestModelOptions,
|
||||
GetMJRobotOptions,
|
||||
GetMJRobotModelOptions,
|
||||
GetMJImageScaleOptions,
|
||||
GetMJAPIUrlOptions,
|
||||
GetMJSpeedOptions
|
||||
}
|
||||
|
||||
export default MJDefine
|
||||
@ -13,7 +13,7 @@ class OptionHandle {
|
||||
* @param key 指定的Key的值
|
||||
* @returns
|
||||
*/
|
||||
GetOptionByKey = async (key: string) => await this.optionServices.GetOptionByKey(key)
|
||||
GetOptionByKey = async (key: string | string[]) => await this.optionServices.GetOptionByKey(key)
|
||||
|
||||
/**
|
||||
* 修改指定的Option,通过key,不存在则创建
|
||||
|
||||
@ -3,6 +3,7 @@ import { OptionKeyName, OptionType } from '@/define/enum/option'
|
||||
import { ValidateJson } from '@/define/Tools/validate'
|
||||
import { errorMessage, successMessage } from '@/main/Public/generalTools'
|
||||
import { ErrorItem, GeneralResponse, SuccessItem } from '@/model/generalResponse'
|
||||
import { OptionModel } from '@/model/option/option'
|
||||
export class OptionServices {
|
||||
optionRealmService!: OptionRealmService
|
||||
constructor() { }
|
||||
@ -19,10 +20,26 @@ export class OptionServices {
|
||||
* @param key
|
||||
* @returns
|
||||
*/
|
||||
public async GetOptionByKey(key: string): Promise<GeneralResponse.ErrorItem | SuccessItem> {
|
||||
public async GetOptionByKey(key: string | string[]): Promise<GeneralResponse.ErrorItem | SuccessItem> {
|
||||
try {
|
||||
await this.InitService()
|
||||
let res = this.optionRealmService.GetOptionByKey(key)
|
||||
let res: Array<OptionModel.OptionItem> | OptionModel.OptionItem;
|
||||
if (Array.isArray(key)) {
|
||||
if (key.length <= 0) {
|
||||
throw new Error('Key不能为空')
|
||||
}
|
||||
let temp = []
|
||||
for (let i = 0; i < key.length; i++) {
|
||||
const element = key[i];
|
||||
let resItem = this.optionRealmService.GetOptionByKey(element)
|
||||
if (resItem != null) {
|
||||
temp.push(resItem)
|
||||
}
|
||||
}
|
||||
res = temp;
|
||||
} else {
|
||||
res = this.optionRealmService.GetOptionByKey(key)
|
||||
}
|
||||
return successMessage(res, '获取成功 OptionKey: ' + key, 'OptionOptions.GetOptionByKey')
|
||||
} catch (error: any) {
|
||||
return errorMessage(
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { SoftwareService } from '../../../define/db/service/SoftWare/softwareService';
|
||||
import { MJSettingService } from '../../../define/db/service/SoftWare/mjSettingService';
|
||||
import { MJSetting } from '../../../model/Setting/mjSetting';
|
||||
import { MJSettingModel } from '../../../model/Setting/mjSetting';
|
||||
|
||||
|
||||
export class SoftWareServiceBasic {
|
||||
@ -85,7 +85,7 @@ export class SoftWareServiceBasic {
|
||||
* 获取MJ的设置信息
|
||||
* @returns
|
||||
*/
|
||||
async GetMjSetting(): Promise<MJSetting.MjSetting> {
|
||||
async GetMjSetting(): Promise<MJSettingModel.MjSimpleSettingModel> {
|
||||
await this.InitService();
|
||||
let mjSetting = this.mjSettingService.GetMjSetting({})
|
||||
if (mjSetting.code == 1) {
|
||||
|
||||
@ -12,7 +12,7 @@ import { D3Opt } from '../d3'
|
||||
import { FluxOpt } from '../Flux/flux'
|
||||
import { AsyncQueue } from '../../quene'
|
||||
import { SoftWareServiceBasic } from '../ServiceBasic/softwareServiceBasic'
|
||||
import { MJSetting } from '../../../model/Setting/mjSetting'
|
||||
import { MJSettingModel } from '../../../model/Setting/mjSetting'
|
||||
import { BookVideo } from '../Book/bookVideo'
|
||||
import { BookServiceBasic } from '../ServiceBasic/bookServiceBasic'
|
||||
import { TaskModal } from '@/model/task'
|
||||
@ -32,7 +32,7 @@ export class TaskManager {
|
||||
bookServiceBasic: BookServiceBasic
|
||||
videoGlobal: VideoGlobal
|
||||
|
||||
mjSetting: MJSetting.MjSetting
|
||||
mjSimpleSetting: MJSettingModel.MjSimpleSettingModel
|
||||
spaceTime: number = 5000;
|
||||
count = 0;
|
||||
isListening = false;
|
||||
@ -65,7 +65,7 @@ export class TaskManager {
|
||||
}
|
||||
if (getMJsetting) {
|
||||
// 初始化MJ设置
|
||||
this.mjSetting = await this.softWareServiceBasic.GetMjSetting()
|
||||
this.mjSimpleSetting = await this.softWareServiceBasic.GetMjSetting()
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,8 +141,8 @@ export class TaskManager {
|
||||
if (element.type == BookBackTaskType.MJ_IMAGE || element.type == BookBackTaskType.MJ_REVERSE) {
|
||||
// 判断任务数量是不是又修改
|
||||
let taskNumber = global.mjQueue.getConcurrencyLimit();
|
||||
if (taskNumber != this.mjSetting.taskCount) {
|
||||
global.mjQueue.concurrencyLimit = this.mjSetting.taskCount // 重置并发执行的数量
|
||||
if (taskNumber != this.mjSimpleSetting.taskCount) {
|
||||
global.mjQueue.concurrencyLimit = this.mjSimpleSetting.taskCount // 重置并发执行的数量
|
||||
}
|
||||
|
||||
if (global.mjQueue.getWaitingQueue() > 10) {
|
||||
|
||||
@ -7,11 +7,12 @@ import { cloneDeep, isEmpty } from "lodash";
|
||||
import { GetBaseUrl } from "@/define/Tools/common";
|
||||
import axios from "axios";
|
||||
import { Book } from "@/model/book/book";
|
||||
import { c } from "naive-ui";
|
||||
import { VideoStatus } from "@/define/enum/video";
|
||||
import { SendMessageToRenderer } from "../globalService";
|
||||
import { ResponseMessageType } from "@/define/enum/softwareEnum";
|
||||
import { BookBackTaskStatus, BookTaskStatus } from "@/define/enum/bookEnum";
|
||||
import { define } from "@/define/define"
|
||||
import ForwardResponse from "@/define/response/ForwardResponse";
|
||||
|
||||
export class KlingService {
|
||||
bookServiceBasic: BookServiceBasic
|
||||
@ -25,7 +26,7 @@ export class KlingService {
|
||||
* @param gptUrl GPT地址
|
||||
* @param gptApiKey GPTAPIKey
|
||||
*/
|
||||
async KlingImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string): Promise<void> {
|
||||
async KlingImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string, useTransfer: boolean = false): Promise<void> {
|
||||
try {
|
||||
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId);
|
||||
let klingOptionsString = bookTaskDetail.videoMessage.klingOptions;
|
||||
@ -76,18 +77,41 @@ export class KlingService {
|
||||
if (klingOptions.hasOwnProperty("callback_url")) {
|
||||
data.callback_url = klingOptions.callback_url;
|
||||
}
|
||||
|
||||
// 开始请求
|
||||
let baseUrl = GetBaseUrl(gptUrl);
|
||||
let url = baseUrl + "/kling/v1/videos/image2video";
|
||||
let res = await axios.post(url, data, {
|
||||
headers: {
|
||||
"Authorization": gptApiKey
|
||||
}
|
||||
});
|
||||
|
||||
// console.log("kling合成视频结果", res);
|
||||
let resData = res.data;
|
||||
let resData: any = undefined;
|
||||
if (useTransfer) {
|
||||
let transferUrl = define.lms + "/lms/Forward/SimpleTransfer";
|
||||
let transferConfig = {
|
||||
method: 'post',
|
||||
url: transferUrl,
|
||||
maxBodyLength: Infinity,
|
||||
timeout: 600000, // 600 seconds timeout
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify({
|
||||
url: url,
|
||||
apiKey: gptApiKey,
|
||||
dataString: JSON.stringify(data)
|
||||
})
|
||||
}
|
||||
let response = await axios(transferConfig)
|
||||
resData = ForwardResponse.GetForwardResponseData(response)
|
||||
|
||||
} else {
|
||||
let res = await axios.post(url, data, {
|
||||
headers: {
|
||||
"Authorization": gptApiKey
|
||||
}
|
||||
});
|
||||
|
||||
// console.log("kling合成视频结果", res);
|
||||
resData = res.data;
|
||||
}
|
||||
|
||||
let id = resData.data.task_id;
|
||||
|
||||
// 修改数据
|
||||
@ -107,38 +131,60 @@ export class KlingService {
|
||||
data: JSON.stringify(resData)
|
||||
}, task.messageName);
|
||||
|
||||
await this.FetchKlingVideoResult(bookTaskDetail, task, resData.data.task_id, baseUrl, gptApiKey);
|
||||
await this.FetchKlingVideoResult(bookTaskDetail, task, resData.data.task_id, baseUrl, gptApiKey, useTransfer);
|
||||
} catch (error) {
|
||||
throw new Error("可灵合成视频失败,失败信息如下:" + error.toString());
|
||||
}
|
||||
|
||||
}
|
||||
async FetchKlingVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string) {
|
||||
async FetchKlingVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string, useTransfer: boolean = false) {
|
||||
while (true) {
|
||||
try {
|
||||
let url = baseUrl + "/kling/v1/videos/image2video/" + taskId;
|
||||
let res = await axios.get(url, {
|
||||
headers: {
|
||||
Authorization: gptApiKey
|
||||
let resData: any = undefined;
|
||||
if (useTransfer) {
|
||||
let transferUrl = define.lms + "/lms/Forward/GetTransfer";
|
||||
let transferConfig = {
|
||||
method: 'post',
|
||||
url: transferUrl,
|
||||
maxBodyLength: Infinity,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify({
|
||||
url: url,
|
||||
apiKey: gptApiKey,
|
||||
})
|
||||
}
|
||||
});
|
||||
// console.log("kling合成视频结果", res.data);
|
||||
let data = res.data.data;
|
||||
if (data.task_status == "submitted") {
|
||||
let res = await axios.request(transferConfig);
|
||||
resData = ForwardResponse.GetForwardResponseData(res)
|
||||
} else {
|
||||
let res = await axios.get(url, {
|
||||
headers: {
|
||||
Authorization: gptApiKey
|
||||
}
|
||||
});
|
||||
resData = res.data;
|
||||
}
|
||||
if (!resData) {
|
||||
throw new Error("获取可灵合成视频结果失败")
|
||||
}
|
||||
|
||||
if (resData.data.task_status == "submitted") {
|
||||
SendMessageToRenderer({
|
||||
code: 1,
|
||||
id: bookTaskDetail.id,
|
||||
message: "可灵合成任务提交成功,正在合成中",
|
||||
type: ResponseMessageType.KLING_VIDEO,
|
||||
data: JSON.stringify(data)
|
||||
data: JSON.stringify(resData.data)
|
||||
}, task.messageName);
|
||||
} else if (data.task_status == "processing") {
|
||||
} else if (resData.data.task_status == "processing") {
|
||||
|
||||
let videoMessage = cloneDeep(bookTaskDetail.videoMessage);
|
||||
delete videoMessage.id;
|
||||
videoMessage.status = VideoStatus.PROCESSING;
|
||||
videoMessage.taskId = taskId;
|
||||
videoMessage.messageData = JSON.stringify(data);
|
||||
videoMessage.messageData = JSON.stringify(resData.data);
|
||||
await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(task.bookTaskDetailId, videoMessage);
|
||||
|
||||
SendMessageToRenderer({
|
||||
@ -146,16 +192,16 @@ export class KlingService {
|
||||
id: bookTaskDetail.id,
|
||||
message: "可灵合成任务正在合成中",
|
||||
type: ResponseMessageType.KLING_VIDEO,
|
||||
data: JSON.stringify(data)
|
||||
data: JSON.stringify(resData.data)
|
||||
}, task.messageName);
|
||||
} else if (data.task_status == "succeed") {
|
||||
} else if (resData.data.task_status == "succeed") {
|
||||
// 完成
|
||||
let videoMessage = cloneDeep(bookTaskDetail.videoMessage);
|
||||
delete videoMessage.id;
|
||||
videoMessage.status = VideoStatus.SUCCESS;
|
||||
videoMessage.taskId = taskId;
|
||||
videoMessage.videoUrl = data.task_result.videos[0].url;
|
||||
videoMessage.messageData = JSON.stringify(data);
|
||||
videoMessage.videoUrl = resData.data.task_result.videos[0].url;
|
||||
videoMessage.messageData = JSON.stringify(resData.data);
|
||||
await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(task.bookTaskDetailId, videoMessage);
|
||||
await this.bookServiceBasic.UpdetedBookTaskData(task.bookTaskId, {
|
||||
status: BookTaskStatus.IMAGE_TO_VIDEO_SUCCESS,
|
||||
@ -169,7 +215,7 @@ export class KlingService {
|
||||
id: bookTaskDetail.id,
|
||||
message: "可灵合成视频完成",
|
||||
type: ResponseMessageType.KLING_VIDEO,
|
||||
data: JSON.stringify(data.data)
|
||||
data: JSON.stringify(resData.data.data)
|
||||
}, task.messageName);
|
||||
break;
|
||||
} else {
|
||||
@ -177,18 +223,18 @@ export class KlingService {
|
||||
let videoMessage = cloneDeep(bookTaskDetail.videoMessage);
|
||||
delete videoMessage.id;
|
||||
videoMessage.status = VideoStatus.FAIL;
|
||||
videoMessage.msg = res.data.message;
|
||||
videoMessage.msg = resData.message;
|
||||
videoMessage.taskId = taskId;
|
||||
videoMessage.messageData = JSON.stringify(data);
|
||||
videoMessage.messageData = JSON.stringify(resData.data);
|
||||
await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(bookTaskDetail.id, videoMessage);
|
||||
SendMessageToRenderer({
|
||||
code: 0,
|
||||
id: bookTaskDetail.id,
|
||||
message: "runway合成视频失败,错误信息如下:" + res.data.message,
|
||||
message: "runway合成视频失败,错误信息如下:" + resData.data.message,
|
||||
type: ResponseMessageType.KLING_VIDEO,
|
||||
data: JSON.stringify(data)
|
||||
data: JSON.stringify(resData.data)
|
||||
}, task.messageName);
|
||||
throw new Error("可灵合成视频失败,失败信息如下:" + res.data.message);
|
||||
throw new Error("可灵合成视频失败,失败信息如下:" + resData.message);
|
||||
}
|
||||
// 等待20秒后再次请求
|
||||
await new Promise(resolve => setTimeout(resolve, 20000));
|
||||
|
||||
@ -11,14 +11,25 @@ import { SendMessageToRenderer } from "../globalService";
|
||||
import { ResponseMessageType } from "@/define/enum/softwareEnum";
|
||||
import { Book } from "@/model/book/book";
|
||||
import { BookBackTaskStatus, BookTaskStatus } from "@/define/enum/bookEnum";
|
||||
import { define } from "@/define/define"
|
||||
import ForwardResponse from "@/define/response/ForwardResponse";
|
||||
|
||||
export class LumaService {
|
||||
bookServiceBasic: BookServiceBasic
|
||||
requestModel: string
|
||||
constructor() {
|
||||
this.bookServiceBasic = new BookServiceBasic();
|
||||
this.requestModel = "fast"
|
||||
}
|
||||
|
||||
async LumaImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string): Promise<void> {
|
||||
/**
|
||||
* LUMA 合成视频
|
||||
* @param task
|
||||
* @param gptUrl
|
||||
* @param gptApiKey
|
||||
* @param useTransfer
|
||||
*/
|
||||
async LumaImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string, useTransfer: boolean = false): Promise<void> {
|
||||
try {
|
||||
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId);
|
||||
let lumaOptionsString = bookTaskDetail.videoMessage.lumaOptions;
|
||||
@ -27,6 +38,7 @@ export class LumaService {
|
||||
}
|
||||
let lumaOptions: BookTaskDetail.lumaOptions = JSON.parse(lumaOptionsString);
|
||||
// console.log("lumaOptions", lumaOptions, "gptUrl", gptUrl, "gptApiKey", gptApiKey);
|
||||
this.requestModel = lumaOptions.request_model == null ? "fast" : lumaOptions.request_model;
|
||||
|
||||
let data: BookTaskDetail.lumaOptions = {
|
||||
user_prompt: lumaOptions.user_prompt,
|
||||
@ -59,16 +71,39 @@ export class LumaService {
|
||||
// 开始请求
|
||||
let baseUrl = GetBaseUrl(gptUrl);
|
||||
let url = baseUrl + "/luma/generations";
|
||||
let res = await axios.post(url, data, {
|
||||
headers: {
|
||||
"Authorization": gptApiKey
|
||||
if (this.requestModel == 'relax') {
|
||||
url = baseUrl + "/luma-relax/luma/generations";
|
||||
}
|
||||
|
||||
let returnData: any = undefined
|
||||
// 是否国内转发
|
||||
if (useTransfer) {
|
||||
|
||||
let transferUrl = define.lms + "/lms/Forward/SimpleTransfer";
|
||||
let transferConfig = {
|
||||
method: 'post',
|
||||
url: transferUrl,
|
||||
maxBodyLength: Infinity,
|
||||
timeout: 600000, // 600 seconds timeout
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify({
|
||||
url: url,
|
||||
apiKey: gptApiKey,
|
||||
dataString: JSON.stringify(data)
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
// console.log("luma合成视频结果", res);
|
||||
|
||||
let returnData = res.data;
|
||||
// console.log("luma合成视频结果", returnData);
|
||||
let response = await axios(transferConfig)
|
||||
returnData = ForwardResponse.GetForwardResponseData(response)
|
||||
} else {
|
||||
let res = await axios.post(url, data, {
|
||||
headers: {
|
||||
"Authorization": gptApiKey
|
||||
}
|
||||
});
|
||||
returnData = res.data;
|
||||
}
|
||||
let id = returnData.id;
|
||||
|
||||
// 修改数据
|
||||
@ -88,7 +123,7 @@ export class LumaService {
|
||||
data: JSON.stringify(returnData)
|
||||
}, task.messageName);
|
||||
|
||||
await this.FetchLumaVideoResult(bookTaskDetail, task, id, baseUrl, gptApiKey);
|
||||
await this.FetchLumaVideoResult(bookTaskDetail, task, id, baseUrl, gptApiKey, useTransfer);
|
||||
} catch (error) {
|
||||
throw new Error("Luma合成视频失败,错误信息如下:" + error.toString());
|
||||
}
|
||||
@ -101,14 +136,38 @@ export class LumaService {
|
||||
* @param gptApiKey Key
|
||||
* @returns
|
||||
*/
|
||||
async GetVideoUri(taskId: string, baseUrl: string, gptApiKey: string): Promise<string> {
|
||||
async GetVideoUri(taskId: string, baseUrl: string, gptApiKey: string, useTransfer: boolean = false): Promise<string> {
|
||||
let url = baseUrl + "/luma/generations/" + taskId + "/download_video_url";
|
||||
let res = await axios.get(url, {
|
||||
headers: {
|
||||
Authorization: gptApiKey
|
||||
|
||||
if (this.requestModel == "relax") {
|
||||
url = baseUrl + "/luma-relax/luma/generations/" + taskId + "/download_video_url";
|
||||
}
|
||||
|
||||
let resData: any = undefined;
|
||||
if (useTransfer) {
|
||||
let transferUrl = define.lms + "/lms/Forward/GetTransfer";
|
||||
let transferConfig = {
|
||||
method: 'post',
|
||||
url: transferUrl,
|
||||
maxBodyLength: Infinity,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify({
|
||||
url: url,
|
||||
apiKey: gptApiKey,
|
||||
})
|
||||
}
|
||||
});
|
||||
let resData = res.data;
|
||||
let res = await axios.request(transferConfig);
|
||||
resData = ForwardResponse.GetForwardResponseData(res)
|
||||
} else {
|
||||
let res = await axios.get(url, {
|
||||
headers: {
|
||||
Authorization: gptApiKey
|
||||
}
|
||||
});
|
||||
resData = res.data;
|
||||
}
|
||||
// console.log("luma获取视频地址", resData);
|
||||
return resData.url;
|
||||
}
|
||||
@ -121,24 +180,45 @@ export class LumaService {
|
||||
* @param baseUrl 请求的网址
|
||||
* @param gptApiKey APIKey
|
||||
*/
|
||||
async FetchLumaVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string) {
|
||||
async FetchLumaVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string, useTransfer: boolean = false): Promise<void> {
|
||||
while (true) {
|
||||
try {
|
||||
let url = baseUrl + "/luma/generations/" + taskId;
|
||||
let res = await axios.get(url, {
|
||||
headers: {
|
||||
Authorization: gptApiKey
|
||||
if (this.requestModel == 'relax') {
|
||||
url = baseUrl + "/luma-relax/luma/generations/" + taskId;
|
||||
}
|
||||
|
||||
let resData: any = undefined
|
||||
if (useTransfer) {
|
||||
let transferUrl = define.lms + "/lms/Forward/GetTransfer";
|
||||
let transferConfig = {
|
||||
method: 'post',
|
||||
url: transferUrl,
|
||||
maxBodyLength: Infinity,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify({
|
||||
url: url,
|
||||
apiKey: gptApiKey,
|
||||
})
|
||||
}
|
||||
});
|
||||
// console.log("luma合成视频结果", res.data);
|
||||
let resData = res.data;
|
||||
let res = await axios.request(transferConfig);
|
||||
resData = ForwardResponse.GetForwardResponseData(res)
|
||||
} else {
|
||||
let res = await axios.get(url, {
|
||||
headers: {
|
||||
Authorization: gptApiKey
|
||||
}
|
||||
});
|
||||
resData = res.data;
|
||||
}
|
||||
if (resData.state == "completed") {
|
||||
|
||||
let video_url = resData.video.download_url;
|
||||
if (isEmpty(video_url)) {
|
||||
// 完成
|
||||
let vr = await this.GetVideoUri(taskId, baseUrl, gptApiKey);
|
||||
// console.log("luma合成视频结果", vr);
|
||||
let vr = await this.GetVideoUri(taskId, baseUrl, gptApiKey, useTransfer);
|
||||
video_url = vr;
|
||||
}
|
||||
// 保存数据
|
||||
|
||||
@ -11,6 +11,8 @@ import { SendMessageToRenderer } from "../globalService";
|
||||
import { ResponseMessageType } from "@/define/enum/softwareEnum";
|
||||
import { Book } from "@/model/book/book";
|
||||
import { BookBackTaskStatus, BookTaskStatus } from "@/define/enum/bookEnum";
|
||||
import { define } from "@/define/define"
|
||||
import ForwardResponse from "@/define/response/ForwardResponse";
|
||||
|
||||
export class RunwayService {
|
||||
bookServiceBasic: BookServiceBasic
|
||||
@ -24,7 +26,7 @@ export class RunwayService {
|
||||
* @param gptUrl 调用地址
|
||||
* @param gptApiKey Key
|
||||
*/
|
||||
async ImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string) {
|
||||
async ImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string, useTransfer: boolean = false) {
|
||||
try {
|
||||
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId);
|
||||
|
||||
@ -77,16 +79,42 @@ export class RunwayService {
|
||||
}
|
||||
// 开始请求
|
||||
let baseUrl = GetBaseUrl(gptUrl);
|
||||
let res = await axios.post(baseUrl + "/runway/pro/generate", data, {
|
||||
headers: {
|
||||
Authorization: gptApiKey
|
||||
let url = baseUrl + "/runway/pro/generate"
|
||||
|
||||
let resData: any = undefined
|
||||
|
||||
if (useTransfer) {
|
||||
|
||||
let transferUrl = define.lms + "/lms/Forward/SimpleTransfer";
|
||||
let transferConfig = {
|
||||
method: 'post',
|
||||
url: transferUrl,
|
||||
maxBodyLength: Infinity,
|
||||
timeout: 600000, // 600 seconds timeout
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify({
|
||||
url: url,
|
||||
apiKey: gptApiKey,
|
||||
dataString: JSON.stringify(data)
|
||||
})
|
||||
}
|
||||
});
|
||||
// console.log("runway合成视频结果", res.data);
|
||||
let resData = res.data;
|
||||
if (resData.code != 200) {
|
||||
throw new Error(res.data.msg);
|
||||
let response = await axios(transferConfig)
|
||||
resData = ForwardResponse.GetForwardResponseData(response)
|
||||
} else {
|
||||
let res = await axios.post(url, data, {
|
||||
headers: {
|
||||
Authorization: gptApiKey
|
||||
}
|
||||
});
|
||||
// console.log("runway合成视频结果", res.data);
|
||||
resData = res.data;
|
||||
}
|
||||
if (resData.code != 200) {
|
||||
throw new Error(resData.msg);
|
||||
}
|
||||
|
||||
// 修改数据
|
||||
let videoMessage = cloneDeep(bookTaskDetail.videoMessage);
|
||||
videoMessage.taskId = resData.data.task_id;
|
||||
@ -104,37 +132,62 @@ export class RunwayService {
|
||||
type: ResponseMessageType.RUNWAY_VIDEO,
|
||||
data: JSON.stringify(resData.data)
|
||||
}, task.messageName);
|
||||
await this.FetchRunwayVideoResult(bookTaskDetail, task, resData.data.task_id, baseUrl, gptApiKey);
|
||||
await this.FetchRunwayVideoResult(bookTaskDetail, task, resData.data.task_id, baseUrl, gptApiKey, useTransfer);
|
||||
} catch (error) {
|
||||
throw new Error("runway合成视频失败,错误信息如下:" + error.toString());
|
||||
}
|
||||
}
|
||||
|
||||
async FetchRunwayVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string) {
|
||||
async FetchRunwayVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string, useTransfer: boolean = false) {
|
||||
while (true) {
|
||||
try {
|
||||
let url = baseUrl + "/runway/feed";
|
||||
let res = await axios.post(url, {
|
||||
"task_id": taskId
|
||||
}, {
|
||||
headers: {
|
||||
Authorization: gptApiKey
|
||||
}
|
||||
});
|
||||
|
||||
let data = res.data;
|
||||
if (data.code != 200) {
|
||||
throw new Error(data.msg);
|
||||
let resData: any = undefined
|
||||
|
||||
if (useTransfer) {
|
||||
let transferUrl = define.lms + "/lms/Forward/SimpleTransfer";
|
||||
let transferConfig = {
|
||||
method: 'post',
|
||||
url: transferUrl,
|
||||
maxBodyLength: Infinity,
|
||||
timeout: 600000, // 600 seconds timeout
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify({
|
||||
url: url,
|
||||
apiKey: gptApiKey,
|
||||
dataString: JSON.stringify({
|
||||
"task_id": taskId
|
||||
})
|
||||
})
|
||||
}
|
||||
let response = await axios(transferConfig)
|
||||
resData = ForwardResponse.GetForwardResponseData(response)
|
||||
} else {
|
||||
let res = await axios.post(url, {
|
||||
"task_id": taskId
|
||||
}, {
|
||||
headers: {
|
||||
Authorization: gptApiKey
|
||||
}
|
||||
});
|
||||
|
||||
resData = res.data;
|
||||
}
|
||||
if (resData.code != 200) {
|
||||
throw new Error(resData.msg);
|
||||
}
|
||||
|
||||
if (data.data.status == '3') {
|
||||
if (resData.data.status == '3') {
|
||||
// 完成
|
||||
let videoMessage = cloneDeep(bookTaskDetail.videoMessage);
|
||||
delete videoMessage.id;
|
||||
videoMessage.status = VideoStatus.SUCCESS;
|
||||
videoMessage.taskId = taskId;
|
||||
videoMessage.videoUrl = data.data.video_url;
|
||||
videoMessage.messageData = JSON.stringify(data.data);
|
||||
videoMessage.videoUrl = resData.data.video_url;
|
||||
videoMessage.messageData = JSON.stringify(resData.data);
|
||||
await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(task.bookTaskDetailId, videoMessage);
|
||||
await this.bookServiceBasic.UpdetedBookTaskData(task.bookTaskId, {
|
||||
status: BookTaskStatus.IMAGE_TO_VIDEO_SUCCESS,
|
||||
@ -149,37 +202,37 @@ export class RunwayService {
|
||||
id: bookTaskDetail.id,
|
||||
message: "runway合成视频完成",
|
||||
type: ResponseMessageType.RUNWAY_VIDEO,
|
||||
data: JSON.stringify(data.data)
|
||||
data: JSON.stringify(resData.data)
|
||||
}, task.messageName);
|
||||
break;
|
||||
} else if (data.data.status == '1') {
|
||||
} else if (resData.data.status == '1') {
|
||||
// 处理中
|
||||
SendMessageToRenderer({
|
||||
code: 1,
|
||||
id: bookTaskDetail.id,
|
||||
message: "runway合成视频处理中",
|
||||
type: ResponseMessageType.RUNWAY_VIDEO,
|
||||
data: JSON.stringify(data.data)
|
||||
data: JSON.stringify(resData.data)
|
||||
}, task.messageName);
|
||||
} else {
|
||||
// 没有完成
|
||||
if (data.data.status == '2') {
|
||||
if (resData.data.status == '2') {
|
||||
// 有报错信息直接返回错误
|
||||
let videoMessage = cloneDeep(bookTaskDetail.videoMessage);
|
||||
delete videoMessage.id;
|
||||
videoMessage.status = VideoStatus.FAIL;
|
||||
videoMessage.msg = data.data.msg;
|
||||
videoMessage.msg = resData.data.msg;
|
||||
videoMessage.taskId = taskId;
|
||||
videoMessage.messageData = JSON.stringify(data.data);
|
||||
videoMessage.messageData = JSON.stringify(resData.data);
|
||||
await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(bookTaskDetail.id, videoMessage);
|
||||
SendMessageToRenderer({
|
||||
code: 0,
|
||||
id: bookTaskDetail.id,
|
||||
message: "runway合成视频失败,错误信息如下:" + data.data.msg,
|
||||
message: "runway合成视频失败,错误信息如下:" + resData.data.msg,
|
||||
type: ResponseMessageType.RUNWAY_VIDEO,
|
||||
data: JSON.stringify(data.data)
|
||||
data: JSON.stringify(resData.data)
|
||||
}, task.messageName);
|
||||
throw new Error(data.data.msg);
|
||||
throw new Error(resData.data.msg);
|
||||
}
|
||||
}
|
||||
// 等待20秒后再次请求
|
||||
|
||||
@ -128,24 +128,24 @@ export class VideoGlobal {
|
||||
|
||||
async ImageToVideo(task: TaskModal.Task): Promise<GeneralResponse.ErrorItem | GeneralResponse.SuccessItem> {
|
||||
try {
|
||||
let { gptUrl, gptApiKey } = await this.gptService.RefreshGptSetting();
|
||||
let { gptUrl, gptApiKey, useTransfer } = await this.gptService.RefreshGptSetting();
|
||||
switch (task.type) {
|
||||
case BookBackTaskType.RUNWAY_VIDEO:
|
||||
await this.runwayService.ImageToVideo(task, gptUrl, gptApiKey);
|
||||
await this.runwayService.ImageToVideo(task, gptUrl, gptApiKey, useTransfer);
|
||||
break;
|
||||
case BookBackTaskType.LUMA_VIDEO:
|
||||
await this.lumaService.LumaImageToVideo(task, gptUrl, gptApiKey);
|
||||
await this.lumaService.LumaImageToVideo(task, gptUrl, gptApiKey, useTransfer);
|
||||
break;
|
||||
|
||||
case BookBackTaskType.KLING_VIDEO:
|
||||
await this.klingService.KlingImageToVideo(task, gptUrl, gptApiKey);
|
||||
await this.klingService.KlingImageToVideo(task, gptUrl, gptApiKey, useTransfer);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error("暂不支持的视频类型");
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 执行完毕,开始下载视频
|
||||
let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId);
|
||||
let book = await this.bookServiceBasic.GetBookDataById(task.bookId);
|
||||
|
||||
@ -16,7 +16,6 @@ import { PublicMethod } from './Public/publicMethod'
|
||||
import { ImageStyleDefine } from '../define/iamgeStyleDefine'
|
||||
let tools = new Tools()
|
||||
let pm = new PublicMethod(global)
|
||||
import { FLxuAPIImageType } from '../define/enum/image'
|
||||
import JianyingService from './Service/jianying/jianyingService'
|
||||
import VideoHandle from './Service/videoService/videoHandle'
|
||||
import { successMessage } from './Public/generalTools'
|
||||
@ -691,11 +690,13 @@ async function SaveSDConfig(value) {
|
||||
|
||||
if (!sd_config.flux) {
|
||||
let model = {
|
||||
model: value.flux_model ? value.flux_model : FLxuAPIImageType.FLUX
|
||||
model: value.flux_model ? value.flux_model : 'flux',
|
||||
useTransfer: value.useTransfer == null ? false : value.useTransfer
|
||||
}
|
||||
sd_config.flux = model
|
||||
} else {
|
||||
sd_config.flux.model = value.flux_model ? value.flux_model : FLxuAPIImageType.FLUX
|
||||
sd_config.flux.model = value.flux_model ? value.flux_model : sd_config.flux.model
|
||||
sd_config.flux.useTransfer = value.useTransfer == null ? false : value.useTransfer
|
||||
}
|
||||
|
||||
await fspromises.writeFile(define.sd_setting, JSON.stringify(sd_config))
|
||||
|
||||
@ -11,7 +11,6 @@ import { TagDefine } from '../../define/tagDefine'
|
||||
import { errorMessage } from '../Public/generalTools'
|
||||
import { TaskManager } from '../Service/task/taskManage'
|
||||
import { SoftWareServiceBasic } from '../Service/ServiceBasic/softwareServiceBasic'
|
||||
import { FLxuAPIImageType } from '../../define/enum/image'
|
||||
|
||||
let tagDefine = new TagDefine(global)
|
||||
export class Setting {
|
||||
@ -176,7 +175,9 @@ export class Setting {
|
||||
sd_model: sd_config.sd_model,
|
||||
lora: sd_config.lora,
|
||||
sampler: sd_config.sampler,
|
||||
flux_model: sd_config.flux?.model ? sd_config.flux.model : FLxuAPIImageType.FLUX
|
||||
flux_model: sd_config.flux?.model,
|
||||
useTransfer:
|
||||
sd_config.flux.useTransfer == undefined ? false : sd_config.flux.useTransfer
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
96
src/model/Setting/mjSetting.d.ts
vendored
96
src/model/Setting/mjSetting.d.ts
vendored
@ -1,7 +1,10 @@
|
||||
import { MJImageType, MJRobotType } from "../../define/enum/mjEnum"
|
||||
import { MJImageType, MJRobotType, MJSpeed } from "../../define/enum/mjEnum"
|
||||
|
||||
declare namespace MJSetting {
|
||||
type ActionRemoteMJSetting = {
|
||||
declare namespace MJSettingModel {
|
||||
/**
|
||||
* 代理模式配置数据模型
|
||||
*/
|
||||
type ActionRemoteMJSettingModel = {
|
||||
id?: string
|
||||
accountId?: string
|
||||
channelId?: string
|
||||
@ -19,22 +22,10 @@ declare namespace MJSetting {
|
||||
updateTime?: Date
|
||||
}
|
||||
|
||||
|
||||
type BrowserMJ = {
|
||||
id: string
|
||||
serviceId: string
|
||||
channelId: string
|
||||
mjBotId: string
|
||||
nijBotId: string
|
||||
token: string
|
||||
userAgent: string
|
||||
userAgentCustom: boolean
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
version: string
|
||||
}
|
||||
|
||||
type RemoteMJ = {
|
||||
/**
|
||||
* 代理模式配置数据模型
|
||||
*/
|
||||
type RemoteMJSettingModel = {
|
||||
id: string
|
||||
accountId: string | null
|
||||
channelId: string
|
||||
@ -49,23 +40,47 @@ declare namespace MJSetting {
|
||||
timeoutMinutes: number
|
||||
userAgent: string
|
||||
userToken: string
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
version: string
|
||||
createTime?: Date
|
||||
updateTime?: Date
|
||||
version?: string
|
||||
}
|
||||
|
||||
type APIMj = {
|
||||
/**
|
||||
* 浏览器模式配置数据模型
|
||||
*/
|
||||
type BrowserMJSettingModel = {
|
||||
id: string
|
||||
serviceId: string
|
||||
channelId: string
|
||||
mjBotId: string
|
||||
nijBotId: string
|
||||
token: string
|
||||
userAgent: string
|
||||
userAgentCustom: boolean
|
||||
createTime?: Date
|
||||
updateTime?: Date
|
||||
version?: string
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* MJ API 设置
|
||||
*/
|
||||
type MJAPISettingModel = {
|
||||
id: string
|
||||
mjApiUrl: string
|
||||
mjSpeed: string // MJ出图的速度模式
|
||||
mjSpeed: MJSpeed // MJ出图的速度模式
|
||||
apiKey: string
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
version: string
|
||||
useTransfer: boolean // 是否国内转发
|
||||
createTime?: Date
|
||||
updateTime?: Date
|
||||
version?: string
|
||||
}
|
||||
|
||||
type MjSetting = {
|
||||
id: string
|
||||
/**
|
||||
* MJ 基础设置
|
||||
*/
|
||||
type MjSimpleSettingModel = {
|
||||
type: MJImageType
|
||||
requestModel: MJImageType
|
||||
selectRobot: MJRobotType
|
||||
@ -74,11 +89,22 @@ declare namespace MJSetting {
|
||||
imageSuffix: string
|
||||
taskCount: number
|
||||
spaceTime: number
|
||||
createTime: Date
|
||||
updateTime: Date
|
||||
version: string
|
||||
apiSetting: APIMj
|
||||
remoteSetting: RemoteMJ
|
||||
browserSetting: BrowserMJ
|
||||
}
|
||||
|
||||
/**
|
||||
* MJ 代理设置模型
|
||||
*/
|
||||
type MJRemoteSimpleSettingModel = {
|
||||
useTransfer: boolean // 是否国内转发
|
||||
}
|
||||
|
||||
/**
|
||||
* MJ 全局设置
|
||||
*/
|
||||
type MJ_GlobalSettingModel = {
|
||||
mj_simpleSetting: MjSimpleSettingModel
|
||||
mj_apiSetting: MJAPISettingModel
|
||||
mj_browserSetting: BrowserMJSettingModel
|
||||
mj_remoteSimpleSetting: MJRemoteSimpleSettingModel
|
||||
}
|
||||
}
|
||||
|
||||
1
src/model/book/bookTaskDetail.d.ts
vendored
1
src/model/book/bookTaskDetail.d.ts
vendored
@ -56,6 +56,7 @@ declare namespace BookTaskDetail {
|
||||
image_url?: string; // 图片地址(参考图,支持第三方图片地址、Base64)
|
||||
image_end_url?: string; // 尾帧图片地址(支持第三方图片地址、Base64)
|
||||
notify_hook?: string; // 回调地址
|
||||
request_model?: string; // 请求的模型,快速还是慢速
|
||||
}
|
||||
|
||||
type klingOptions = {
|
||||
|
||||
1
src/model/option/option.d.ts
vendored
1
src/model/option/option.d.ts
vendored
@ -1,3 +1,4 @@
|
||||
import { MJImageType, MJRobotType } from "@/define/enum/mjEnum"
|
||||
import { OptionType } from "@/define/enum/option"
|
||||
|
||||
declare namespace OptionModel {
|
||||
|
||||
@ -4,7 +4,7 @@ import { OptionType } from '@/define/enum/option'
|
||||
|
||||
const options = {
|
||||
/** 通过Key获取指定的option */
|
||||
GetOptionByKey: async (key: string) =>
|
||||
GetOptionByKey: async (key: string | string[]) =>
|
||||
await ipcRenderer.invoke(DEFINE_STRING.OPTIONS.GET_OPTION_BY_KEY, key),
|
||||
|
||||
/**
|
||||
|
||||
30
src/renderer/src/common/SDFluxCommon.ts
Normal file
30
src/renderer/src/common/SDFluxCommon.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { define } from "@/define/define"
|
||||
import { OptionKeyName } from "@/define/enum/option";
|
||||
import { ValidateJson } from "@/define/Tools/validate";
|
||||
import axios from "axios";
|
||||
import { isEmpty } from "lodash";
|
||||
/**
|
||||
* 远程的FLUX模型列表
|
||||
* @returns
|
||||
*/
|
||||
async function GetRemoteFluxModelList() {
|
||||
debugger
|
||||
let res = await axios.get(define.lms + `/lms/LaitoolOptions/GetSimpleOptions/LaitoolFluxApiModelList`);
|
||||
if (res.data.code != 1) {
|
||||
throw new Error(res.data.message)
|
||||
}
|
||||
let data = res.data.data.filter(item => item.key == "LaitoolFluxApiModelList")
|
||||
if (data.length != 1) {
|
||||
throw new Error("获取远程FLUX API模型列表失败")
|
||||
}
|
||||
if (isEmpty(data[0].value) || !ValidateJson(data[0].value)) {
|
||||
throw new Error("FLUX API模型列表数据异常,请联系管理员!")
|
||||
}
|
||||
return JSON.parse(data[0].value)
|
||||
}
|
||||
|
||||
let SDFluxCommon = {
|
||||
GetRemoteFluxModelList
|
||||
}
|
||||
|
||||
export default SDFluxCommon
|
||||
@ -1,6 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import { OptionKeyName, OptionType } from '@/define/enum/option'
|
||||
import { useOptionStore } from '@/stores/option'
|
||||
import SDFluxCommon from './SDFluxCommon'
|
||||
|
||||
/**
|
||||
* 初始化特殊字符数据,用于文案的相关处理
|
||||
@ -90,8 +91,54 @@ async function InitTTSGlobalSetting() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化模型列表
|
||||
* @returns
|
||||
*/
|
||||
async function InitFluxModelList(isMust: boolean = false): Promise<Array<{ label: string, value: string }>> {
|
||||
debugger
|
||||
let initData = []
|
||||
if (!isMust) {
|
||||
let FLUX_APIModelListData = await window.options.GetOptionByKey(OptionKeyName.FLUX_APIModelList);
|
||||
if (FLUX_APIModelListData.code == 0) {
|
||||
window.api.showGlobalMessageDialog(FLUX_APIModelListData);
|
||||
return initData;
|
||||
}
|
||||
if (FLUX_APIModelListData.data == null) {
|
||||
initData = await SDFluxCommon.GetRemoteFluxModelList()
|
||||
let saveRes = await window.options.ModifyOptionByKey(
|
||||
OptionKeyName.FLUX_APIModelList,
|
||||
JSON.stringify(initData),
|
||||
OptionType.JOSN
|
||||
)
|
||||
if (saveRes.code == 0) {
|
||||
window.api.showGlobalMessageDialog(saveRes)
|
||||
return initData
|
||||
} else {
|
||||
return initData
|
||||
}
|
||||
} else {
|
||||
return JSON.parse(FLUX_APIModelListData.data.value)
|
||||
}
|
||||
} else {
|
||||
initData = await SDFluxCommon.GetRemoteFluxModelList()
|
||||
let saveRes = await window.options.ModifyOptionByKey(
|
||||
OptionKeyName.FLUX_APIModelList,
|
||||
JSON.stringify(initData),
|
||||
OptionType.JOSN
|
||||
)
|
||||
if (saveRes.code == 0) {
|
||||
window.api.showGlobalMessageDialog(saveRes)
|
||||
return initData
|
||||
} else {
|
||||
return initData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let InitCommon = {
|
||||
InitSpecialCharacters,
|
||||
InitTTSGlobalSetting
|
||||
InitTTSGlobalSetting,
|
||||
InitFluxModelList
|
||||
}
|
||||
export default InitCommon
|
||||
|
||||
@ -95,6 +95,8 @@ async function GetBookTaskDetailOption() {
|
||||
}
|
||||
if (ValidateJson(videoMessage.value.lumaOptions)) {
|
||||
lumaOptions.value = JSON.parse(videoMessage.value.lumaOptions)
|
||||
lumaOptions.value.request_model =
|
||||
lumaOptions.value.request_model == null ? 'fast' : lumaOptions.value.request_model
|
||||
lumaOptions.value.image_url = videoMessage.value.imageUrl
|
||||
}
|
||||
if (ValidateJson(videoMessage.value.klingOptions)) {
|
||||
|
||||
@ -30,6 +30,16 @@
|
||||
<n-form-item-gi :span="12">
|
||||
<n-image width="100" :src="lumaOptions.image_end_url"></n-image>
|
||||
</n-form-item-gi>
|
||||
<n-form-item-gi :span="4" label="速度模式">
|
||||
<n-select
|
||||
v-model:value="lumaOptions.request_model"
|
||||
:options="[
|
||||
{ label: 'FAST', value: 'fast' },
|
||||
{ label: 'RELAX', value: 'relax' }
|
||||
]"
|
||||
placeholder="请选择速度"
|
||||
></n-select>
|
||||
</n-form-item-gi>
|
||||
</n-grid>
|
||||
</n-form>
|
||||
</div>
|
||||
@ -37,7 +47,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { NForm, NImage, NGrid, NFormItemGi, NInput, NCheckbox } from 'naive-ui'
|
||||
import { NForm, NImage, NSelect, NGrid, NFormItemGi, NInput, NCheckbox } from 'naive-ui'
|
||||
|
||||
let props = defineProps({
|
||||
lumaOptions: undefined
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
pane-wrapper-style="margin: 0 -4px"
|
||||
pane-style="padding-left: 4px; padding-right: 4px; box-sizing: border-box;"
|
||||
>
|
||||
<n-tab-pane name="mj_setting" tab="MJ设置"> <MJSetting /> </n-tab-pane>
|
||||
<n-tab-pane name="mj_setting" tab="MJ设置"> <MJSettingHome /> </n-tab-pane>
|
||||
<n-tab-pane name="sd_setting" tab="SD设置"> <SDSetting /> </n-tab-pane>
|
||||
<n-tab-pane name="export_video_setting" tab="导出视频设置">
|
||||
<VideoGenerateSetting />
|
||||
@ -28,7 +28,7 @@
|
||||
<script>
|
||||
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch } from 'vue'
|
||||
import { useMessage, NTabPane, NTabs, NCard } from 'naive-ui'
|
||||
import MJSetting from '../../Setting/MJSetting.vue'
|
||||
import MJSettingHome from '../../Setting/MJSetting/MJSettingHome.vue'
|
||||
import SDSetting from '../../Setting/SDSetting.vue'
|
||||
import VideoGenerateSetting from '../../Setting/VideoGenerateSetting.vue'
|
||||
import WatermarkSetting from '../../Setting/WatermarkSetting.vue'
|
||||
@ -39,7 +39,7 @@ export default defineComponent({
|
||||
NTabPane,
|
||||
NTabs,
|
||||
NCard,
|
||||
MJSetting,
|
||||
MJSettingHome,
|
||||
SDSetting,
|
||||
VideoGenerateSetting,
|
||||
WatermarkSetting,
|
||||
|
||||
@ -1,522 +0,0 @@
|
||||
<template>
|
||||
<div style="overflow: auto; height: 100%">
|
||||
<n-card title="基础设置" size="medium" hoverable style="min-width: 850px">
|
||||
<n-form :model="mjSetting" ref="sampleRef" :rules="sampleRules">
|
||||
<div style="display: flex; align-items: center">
|
||||
<n-form-item label="出图模式" style="width: 150px" path="requestModel">
|
||||
<n-select
|
||||
:options="request_model_options"
|
||||
v-model:value="mjSetting.requestModel"
|
||||
placeholder="请选择出图模式"
|
||||
></n-select>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="选择生图机器人"
|
||||
path="selectRobot"
|
||||
style="width: 120px; margin-left: 10px"
|
||||
>
|
||||
<n-select
|
||||
:options="select_robot_options"
|
||||
v-model:value="mjSetting.selectRobot"
|
||||
@update:value="UpdateSelectRobot"
|
||||
></n-select>
|
||||
</n-form-item>
|
||||
<n-form-item label="机器人模型" style="width: 120px; margin-left: 10px" path="imageModel">
|
||||
<n-select
|
||||
placeholder="请选择机器人模型"
|
||||
:options="image_model_options"
|
||||
v-model:value="mjSetting.imageModel"
|
||||
></n-select>
|
||||
</n-form-item>
|
||||
<n-form-item label="生图尺寸" style="width: 120px; margin-left: 10px" path="imageScale">
|
||||
<n-select
|
||||
placeholder="请选择生图尺寸"
|
||||
:options="image_scale_options"
|
||||
v-model:value="mjSetting.imageScale"
|
||||
></n-select>
|
||||
</n-form-item>
|
||||
<n-form-item label="命令后缀" style="width: 160px; margin-left: 10px" path="imageSuffix">
|
||||
<n-input v-model:value="mjSetting.imageSuffix" placeholder="请输入后缀命令"></n-input>
|
||||
</n-form-item>
|
||||
<n-form-item label="生图任务量" style="width: 100px; margin-left: 10px" path="taskCount">
|
||||
<n-input-number
|
||||
v-model:value="mjSetting.taskCount"
|
||||
:show-button="false"
|
||||
placeholder="MJ并发出图数量"
|
||||
:min="1"
|
||||
:max="20"
|
||||
></n-input-number>
|
||||
</n-form-item>
|
||||
<n-form-item label="间隔时间(s)" style="width: 100px; margin-left: 10px" path="spaceTime">
|
||||
<n-input-number
|
||||
v-model:value="mjSetting.spaceTime"
|
||||
:show-button="false"
|
||||
placeholder="请输入间隔时间(s)"
|
||||
:min="1"
|
||||
:max="30"
|
||||
></n-input-number>
|
||||
</n-form-item>
|
||||
</div>
|
||||
</n-form>
|
||||
</n-card>
|
||||
<n-card title="API模式设置" hoverable style="margin-top: 10px; min-width: 850px" size="medium">
|
||||
<n-form :model="mjSetting.apiSetting">
|
||||
<div style="display: flex">
|
||||
<n-form-item
|
||||
label="选择出图的API"
|
||||
style="width: 160px; margin-left: 10px"
|
||||
path="mjApiUrl"
|
||||
>
|
||||
<n-select
|
||||
:options="mj_api_options"
|
||||
v-model:value="mjSetting.apiSetting.mjApiUrl"
|
||||
placeholder="选择出图的中转API"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item style="margin-left: 10px" path="mj_api_url">
|
||||
<n-button type="success" @click="openGptBuyUrl">购买</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="选择出图速度模式"
|
||||
style="width: 160px; margin-left: 10px"
|
||||
path="mjSpeed"
|
||||
>
|
||||
<n-select
|
||||
:options="mj_speed_options"
|
||||
v-model:value="mjSetting.apiSetting.mjSpeed"
|
||||
placeholder="选择出图速度模式"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="输入API密钥" style="width: 160px; margin-left: 10px" path="apiKey">
|
||||
<n-input
|
||||
type="password"
|
||||
placeholder="请输入密钥"
|
||||
show-password-on="mousedown"
|
||||
v-model:value="mjSetting.apiSetting.apiKey"
|
||||
></n-input>
|
||||
</n-form-item>
|
||||
</div>
|
||||
</n-form>
|
||||
</n-card>
|
||||
|
||||
<n-card title="代理模式设置" hoverable style="margin-top: 10px; min-width: 850px">
|
||||
<n-button type="info" @click="AddMultiMjAccount()">账号管理</n-button>
|
||||
</n-card>
|
||||
|
||||
<n-card title="浏览器模式设置" hoverable style="margin-top: 10px; min-width: 850px">
|
||||
<n-form :model="mjSetting.browserSetting">
|
||||
<div style="display: flex; margin-top: 10px">
|
||||
<n-form-item>
|
||||
<n-button type="info" @click="OpenDiscordWindow">打开登录MJ</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item label="服务器ID" style="width: 200px; margin-left: 5px" path="serviceId">
|
||||
<n-input
|
||||
v-model:value="mjSetting.browserSetting.serviceId"
|
||||
placeholder="登录MJ后切换服务器自动获取"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="频道ID" style="width: 200px; margin-left: 10px" path="channelId">
|
||||
<n-input
|
||||
v-model:value="mjSetting.browserSetting.channelId"
|
||||
placeholder="登录MJ后切换频道自动获取"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="用户token" style="width: 300px; margin-left: 10px" path="token">
|
||||
<n-input
|
||||
v-model:value="mjSetting.browserSetting.token"
|
||||
placeholder="登录MJ后切换服务器自动获取"
|
||||
/>
|
||||
</n-form-item>
|
||||
</div>
|
||||
<n-form-item label="用户Agent" style="width: 810px" path="userAgent">
|
||||
<n-input
|
||||
v-model:value="mjSetting.browserSetting.userAgent"
|
||||
placeholder="登录MJ后切换服务器自动获取(可自定义)"
|
||||
style="margin-right: 10px"
|
||||
/>
|
||||
<n-tooltip trigger="hover" style="background-color: aliceblue; color: black">
|
||||
<template #trigger>
|
||||
<n-checkbox
|
||||
v-model:checked="mjSetting.browserSetting.userAgentCustom"
|
||||
style="width: 100px"
|
||||
>
|
||||
自定义
|
||||
</n-checkbox>
|
||||
</template>
|
||||
开启自定义需要手动填写userAgent。可以填入浏览器的userAgent
|
||||
</n-tooltip>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-card>
|
||||
<n-button type="info" round @click="SaveMjSetting" style="margin-top: 10px"
|
||||
>保存MJ配置</n-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineComponent, ref, onMounted, computed, toRaw, h } from 'vue'
|
||||
import {
|
||||
NButton,
|
||||
useMessage,
|
||||
useDialog,
|
||||
NDataTable,
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInput,
|
||||
NDivider,
|
||||
NCheckbox,
|
||||
NSelect,
|
||||
NTooltip,
|
||||
NIcon,
|
||||
NInputNumber,
|
||||
NCard,
|
||||
NSpin
|
||||
} from 'naive-ui'
|
||||
import { DEFINE_STRING } from '../../../../define/define_string'
|
||||
import { Reload } from '@vicons/ionicons5'
|
||||
import { isEmpty, max, min } from 'lodash'
|
||||
import { MJImageType } from '../../../../define/enum/mjEnum'
|
||||
import AddMultiRemoteMj from './Components/AddMultiRemoteMj.vue'
|
||||
|
||||
let message = useMessage()
|
||||
let dialog = useDialog()
|
||||
let sampleRef = ref(null)
|
||||
let select_robot_options = ref([
|
||||
{
|
||||
label: 'MJ',
|
||||
value: 'mj'
|
||||
},
|
||||
{
|
||||
label: 'NIJI',
|
||||
value: 'niji'
|
||||
}
|
||||
])
|
||||
|
||||
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
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<div class="mj-api-setting">
|
||||
<n-card title="API模式设置" hoverable style="margin-top: 10px; min-width: 850px" size="medium">
|
||||
<n-form :model="optionStore.MJ_GlobalSetting.mj_apiSetting">
|
||||
<div style="display: flex">
|
||||
<n-form-item
|
||||
label="选择出图的API"
|
||||
style="width: 160px; margin-left: 10px"
|
||||
path="mjApiUrl"
|
||||
>
|
||||
<n-select
|
||||
:options="mjAPIURLOptions"
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_apiSetting.mjApiUrl"
|
||||
placeholder="选择出图的中转API"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item style="margin-left: 10px" path="mj_api_url">
|
||||
<n-button type="success" @click="openGptBuyUrl">购买</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="选择出图速度模式"
|
||||
style="width: 160px; margin-left: 10px"
|
||||
path="mjSpeed"
|
||||
>
|
||||
<n-select
|
||||
:options="mjImageSpeedOptions"
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_apiSetting.mjSpeed"
|
||||
placeholder="选择出图速度模式"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="输入API密钥" style="width: 160px; margin-left: 10px" path="apiKey">
|
||||
<n-input
|
||||
type="password"
|
||||
placeholder="请输入密钥"
|
||||
show-password-on="mousedown"
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_apiSetting.apiKey"
|
||||
></n-input>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
style="width: 120px; margin-left: 30px"
|
||||
path="useTransfer"
|
||||
label="是否国内转发"
|
||||
>
|
||||
<n-select
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_apiSetting.useTransfer"
|
||||
:options="[
|
||||
{ label: '是', value: true },
|
||||
{ label: '否', value: false }
|
||||
]"
|
||||
style="width: 100px"
|
||||
/>
|
||||
</n-form-item>
|
||||
</div>
|
||||
</n-form>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { NCard, NForm, NFormItem, NInput, NSelect, NButton, useMessage } from 'naive-ui'
|
||||
import { useOptionStore } from '@/stores/option'
|
||||
import MJDefine from '@/main/Service/MJ/mjDefine'
|
||||
import { isEmpty } from 'lodash'
|
||||
|
||||
let optionStore = useOptionStore()
|
||||
let message = useMessage()
|
||||
|
||||
let mjAPIURLOptions = ref([])
|
||||
let mjImageSpeedOptions = ref([])
|
||||
|
||||
onMounted(() => {
|
||||
mjAPIURLOptions.value = MJDefine.GetMJAPIUrlOptions()
|
||||
mjImageSpeedOptions.value = MJDefine.GetMJSpeedOptions()
|
||||
})
|
||||
|
||||
/**
|
||||
* 打开购买GPT的地址
|
||||
*/
|
||||
async function openGptBuyUrl() {
|
||||
let selectAPIUrl = mjAPIURLOptions.value.filter(
|
||||
(item) => item.value == optionStore.MJ_GlobalSetting.mj_apiSetting.mjApiUrl
|
||||
)
|
||||
if (selectAPIUrl.length == 0) {
|
||||
message.error('当前选择的服务商没有购买地址!')
|
||||
return
|
||||
}
|
||||
let buy_url = selectAPIUrl[0].buy_url
|
||||
if (isEmpty(buy_url)) {
|
||||
message.error('当前选择的服务商没有购买地址!')
|
||||
} else {
|
||||
window.api.OpenUrl(buy_url)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<div class="mj-browser-setting">
|
||||
<n-card title="浏览器模式设置" hoverable style="margin-top: 10px; min-width: 850px">
|
||||
<n-form :model="optionStore.MJ_GlobalSetting.mj_browserSetting">
|
||||
<div style="display: flex; margin-top: 10px">
|
||||
<n-form-item>
|
||||
<n-button type="info" @click="OpenDiscordWindow">打开登录MJ</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item label="服务器ID" style="width: 200px; margin-left: 5px" path="serviceId">
|
||||
<n-input
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_browserSetting.serviceId"
|
||||
placeholder="登录MJ后切换服务器自动获取"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="频道ID" style="width: 200px; margin-left: 10px" path="channelId">
|
||||
<n-input
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_browserSetting.channelId"
|
||||
placeholder="登录MJ后切换频道自动获取"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="用户token" style="width: 300px; margin-left: 10px" path="token">
|
||||
<n-input
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_browserSetting.token"
|
||||
placeholder="登录MJ后切换服务器自动获取"
|
||||
/>
|
||||
</n-form-item>
|
||||
</div>
|
||||
<n-form-item label="用户Agent" style="width: 810px" path="userAgent">
|
||||
<n-input
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_browserSetting.userAgent"
|
||||
placeholder="登录MJ后切换服务器自动获取(可自定义)"
|
||||
style="margin-right: 10px"
|
||||
/>
|
||||
<n-tooltip trigger="hover" style="background-color: aliceblue; color: black">
|
||||
<template #trigger>
|
||||
<n-checkbox
|
||||
v-model:checked="optionStore.MJ_GlobalSetting.mj_browserSetting.customUserAgent"
|
||||
style="width: 100px"
|
||||
>
|
||||
自定义
|
||||
</n-checkbox>
|
||||
</template>
|
||||
开启自定义需要手动填写userAgent。可以填入浏览器的userAgent
|
||||
</n-tooltip>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { NCard, NForm, NFormItem, NTooltip, NCheckbox, NInput, NButton } from 'naive-ui'
|
||||
|
||||
import { useOptionStore } from '@/stores/option'
|
||||
|
||||
let optionStore = useOptionStore()
|
||||
|
||||
/**
|
||||
* 打开discord窗口
|
||||
*/
|
||||
async function OpenDiscordWindow() {
|
||||
await window.api.OpenDiscordWindow((value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="mj-remote-setting">
|
||||
<n-card title="代理模式设置" hoverable style="margin-top: 10px; min-width: 850px">
|
||||
<n-form inline>
|
||||
<n-form-item style="width: 120px" path="useTransfer" label="是否国内转发">
|
||||
<n-select
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_remoteSimpleSetting.useTransfer"
|
||||
:options="[
|
||||
{ label: '是', value: true },
|
||||
{ label: '否', value: false }
|
||||
]"
|
||||
style="width: 100px"
|
||||
/>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item style="width: 120px; margin-left: 30px" path="useTransfer">
|
||||
<n-button type="info" @click="AddMultiMjAccount">账号管理</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, h } from 'vue'
|
||||
import { NCard, NButton, useDialog, NForm, NFormItem, NSelect } from 'naive-ui'
|
||||
import AddMultiRemoteMj from '../Components/AddMultiRemoteMj.vue'
|
||||
import { useOptionStore } from '@/stores/option'
|
||||
|
||||
let optionStore = useOptionStore()
|
||||
|
||||
let dialog = useDialog()
|
||||
|
||||
/**
|
||||
* 添加多个账号,这样可以同时跑多个账号
|
||||
*/
|
||||
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>
|
||||
147
src/renderer/src/components/Setting/MJSetting/MJSettingHome.vue
Normal file
147
src/renderer/src/components/Setting/MJSetting/MJSettingHome.vue
Normal file
@ -0,0 +1,147 @@
|
||||
<template>
|
||||
<div class="mj-setting-home">
|
||||
<MJSimpleSetting />
|
||||
<MJAPISetting />
|
||||
<MJRemoteSetting />
|
||||
<MJBrowserSetting />
|
||||
<n-button type="info" @click="SaveMjSetting" style="margin-top: 10px">保存MJ配置</n-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useMessage, NButton } from 'naive-ui'
|
||||
import { useSoftwareStore } from '@/stores/software'
|
||||
import { useOptionStore } from '@/stores/option'
|
||||
import { TimeDelay } from '@/define/Tools/time'
|
||||
import { OptionKeyName, OptionType } from '@/define/enum/option'
|
||||
import MJSimpleSetting from './MJSimpleSetting.vue'
|
||||
import MJAPISetting from './MJAPISetting.vue'
|
||||
import MJRemoteSetting from './MJRemoteSetting.vue'
|
||||
import MJBrowserSetting from './MJBrowserSetting.vue'
|
||||
import { MJImageType } from '@/define/enum/mjEnum'
|
||||
import { isEmpty } from 'lodash'
|
||||
|
||||
let softwareStore = useSoftwareStore()
|
||||
let optionStore = useOptionStore()
|
||||
let message = useMessage()
|
||||
|
||||
onMounted(async () => {
|
||||
await InitMJSettingData()
|
||||
})
|
||||
|
||||
/**
|
||||
* 初始化MJSetting数据
|
||||
*/
|
||||
async function InitMJSettingData() {
|
||||
try {
|
||||
softwareStore.spin.spinning = true
|
||||
softwareStore.spin.tip = '正在加载数据,请稍等...'
|
||||
|
||||
let mjRes = await window.options.GetOptionByKey(OptionKeyName.MJ_GlobalSetting)
|
||||
if (mjRes.code == 0) {
|
||||
window.api.showGlobalMessageDialog({
|
||||
code: 0,
|
||||
message: '加载或者是初始化MJSetting信息失败,失败原因:' + mjRes.message
|
||||
})
|
||||
return
|
||||
}
|
||||
if (mjRes.data == null) {
|
||||
let saveRes = await window.options.ModifyOptionByKey(
|
||||
OptionKeyName.MJ_GlobalSetting,
|
||||
JSON.stringify(optionStore.MJ_GlobalSetting),
|
||||
OptionType.JSON
|
||||
)
|
||||
if (saveRes.code == 0) {
|
||||
window.api.showGlobalMessageDialog({
|
||||
code: 0,
|
||||
message: '加载或者是初始化MJSetting信息失败,失败原因:' + saveRes.message
|
||||
})
|
||||
return
|
||||
} else {
|
||||
message.success('初始化MJSetting信息成功')
|
||||
return
|
||||
}
|
||||
} else {
|
||||
optionStore.MJ_GlobalSetting = JSON.parse(mjRes.data.value)
|
||||
message.success('加载MJSetting信息成功')
|
||||
}
|
||||
|
||||
await TimeDelay(1000)
|
||||
} catch (error) {
|
||||
window.api.showGlobalMessageDialog({
|
||||
code: 0,
|
||||
message: '加载或者是初始化MJSetting信息失败,失败原因:' + error.toString()
|
||||
})
|
||||
} finally {
|
||||
softwareStore.spin.spinning = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存MJ配置
|
||||
*/
|
||||
async function SaveMjSetting() {
|
||||
// 在保存的时候要进行数据保存
|
||||
debugger
|
||||
// 通过选择的请求模式判断哪些是要校验的
|
||||
let request_model = optionStore.MJ_GlobalSetting.mj_simpleSetting.requestModel
|
||||
if (request_model == MJImageType.API_MJ) {
|
||||
// API模式,检查必填数据
|
||||
if (
|
||||
optionStore.MJ_GlobalSetting.mj_simpleSetting == null ||
|
||||
isEmpty(optionStore.MJ_GlobalSetting.mj_apiSetting.mjApiUrl) ||
|
||||
isEmpty(optionStore.MJ_GlobalSetting.mj_apiSetting.mjSpeed) ||
|
||||
isEmpty(optionStore.MJ_GlobalSetting.mj_apiSetting.apiKey)
|
||||
) {
|
||||
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 (
|
||||
optionStore.MJ_GlobalSetting.mj_browserSetting == null ||
|
||||
isEmpty(optionStore.MJ_GlobalSetting.mj_browserSetting.serviceId) ||
|
||||
isEmpty(optionStore.MJ_GlobalSetting.mj_browserSetting.channelId) ||
|
||||
isEmpty(optionStore.MJ_GlobalSetting.mj_browserSetting.token) ||
|
||||
isEmpty(optionStore.MJ_GlobalSetting.mj_browserSetting.userAgent)
|
||||
) {
|
||||
message.error('请检查浏览器模式设置的必填字段')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
optionStore.MJ_GlobalSetting.mj_simpleSetting.type =
|
||||
optionStore.MJ_GlobalSetting.mj_simpleSetting.requestModel
|
||||
|
||||
let saveRes = await window.options.ModifyOptionByKey(
|
||||
OptionKeyName.MJ_GlobalSetting,
|
||||
JSON.stringify(optionStore.MJ_GlobalSetting),
|
||||
OptionType.JSON
|
||||
)
|
||||
|
||||
if (saveRes.code == 0) {
|
||||
window.api.showGlobalMessageDialog(saveRes)
|
||||
} else {
|
||||
window.api.showGlobalMessageDialog({
|
||||
code: 1,
|
||||
message: '保存数据成功'
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<div class="mj-simple-setting">
|
||||
<n-card title="基础设置" size="medium" hoverable style="min-width: 850px">
|
||||
<n-form
|
||||
:model="optionStore.MJ_GlobalSetting.mj_simpleSetting"
|
||||
ref="sampleRef"
|
||||
:rules="sampleRules"
|
||||
>
|
||||
<div style="display: flex; align-items: center">
|
||||
<n-form-item label="出图模式" style="width: 150px" path="requestModel">
|
||||
<n-select
|
||||
:options="mjRequestModelOptions"
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_simpleSetting.requestModel"
|
||||
placeholder="请选择出图模式"
|
||||
></n-select>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
label="选择生图机器人"
|
||||
path="selectRobot"
|
||||
style="width: 120px; margin-left: 10px"
|
||||
>
|
||||
<n-select
|
||||
:options="mjRobotOptions"
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_simpleSetting.selectRobot"
|
||||
@update:value="UpdateSelectRobot"
|
||||
></n-select>
|
||||
</n-form-item>
|
||||
<n-form-item label="机器人模型" style="width: 120px; margin-left: 10px" path="imageModel">
|
||||
<n-select
|
||||
placeholder="请选择机器人模型"
|
||||
:options="mjRobotModelOptions"
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_simpleSetting.imageModel"
|
||||
@update:value="UpdateRobotModel"
|
||||
></n-select>
|
||||
</n-form-item>
|
||||
<n-form-item label="生图尺寸" style="width: 120px; margin-left: 10px" path="imageScale">
|
||||
<n-select
|
||||
placeholder="请选择生图尺寸"
|
||||
:options="mjImageScaleOptions"
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_simpleSetting.imageScale"
|
||||
@update:value="UpdateImageScale"
|
||||
></n-select>
|
||||
</n-form-item>
|
||||
<n-form-item label="命令后缀" style="width: 160px; margin-left: 10px" path="imageSuffix">
|
||||
<n-input
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_simpleSetting.imageSuffix"
|
||||
placeholder="请输入后缀命令"
|
||||
></n-input>
|
||||
</n-form-item>
|
||||
<n-form-item label="生图任务量" style="width: 100px; margin-left: 10px" path="taskCount">
|
||||
<n-input-number
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_simpleSetting.taskCount"
|
||||
:show-button="false"
|
||||
placeholder="MJ并发出图数量"
|
||||
:min="1"
|
||||
:max="20"
|
||||
></n-input-number>
|
||||
</n-form-item>
|
||||
<n-form-item label="间隔时间(s)" style="width: 100px; margin-left: 10px" path="spaceTime">
|
||||
<n-input-number
|
||||
v-model:value="optionStore.MJ_GlobalSetting.mj_simpleSetting.spaceTime"
|
||||
:show-button="false"
|
||||
placeholder="请输入间隔时间(s)"
|
||||
:min="1"
|
||||
:max="30"
|
||||
></n-input-number>
|
||||
</n-form-item>
|
||||
</div>
|
||||
</n-form>
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { NCard, NForm, NFormItem, NInputNumber, NSelect, NInput } from 'naive-ui'
|
||||
import { useOptionStore } from '@/stores/option'
|
||||
import MJDefine from '@/main/Service/MJ/mjDefine'
|
||||
|
||||
let optionStore = useOptionStore()
|
||||
|
||||
let mjRequestModelOptions = ref([])
|
||||
let mjRobotOptions = ref([])
|
||||
let mjRobotModelOptions = ref([])
|
||||
let mjImageScaleOptions = ref([])
|
||||
|
||||
// 基础配置的必填检测
|
||||
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' }]
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
mjRequestModelOptions.value = MJDefine.GetMJRequestModelOptions()
|
||||
mjRobotOptions.value = MJDefine.GetMJRobotOptions()
|
||||
mjRobotModelOptions.value = MJDefine.GetMJRobotModelOptions(
|
||||
optionStore.MJ_GlobalSetting.mj_simpleSetting.selectRobot
|
||||
)
|
||||
mjImageScaleOptions.value = MJDefine.GetMJImageScaleOptions()
|
||||
})
|
||||
|
||||
let computedSuffix = () => {
|
||||
let text = mjRobotModelOptions.value.findIndex((item) => {
|
||||
return item.value == optionStore.MJ_GlobalSetting.mj_simpleSetting.imageModel
|
||||
})
|
||||
if (text == -1) {
|
||||
return
|
||||
}
|
||||
let sc = mjImageScaleOptions.value.findIndex((item) => {
|
||||
return item.value == optionStore.MJ_GlobalSetting.mj_simpleSetting.imageScale
|
||||
})
|
||||
let dd = ` --${mjRobotModelOptions.value[text].text} --ar ${mjImageScaleOptions.value[sc].text}`
|
||||
optionStore.MJ_GlobalSetting.mj_simpleSetting.imageSuffix = dd
|
||||
return dd
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新选择的机器人时触发的方法
|
||||
*/
|
||||
function UpdateSelectRobot() {
|
||||
mjRobotModelOptions.value = MJDefine.GetMJRobotModelOptions(
|
||||
optionStore.MJ_GlobalSetting.mj_simpleSetting.selectRobot
|
||||
)
|
||||
|
||||
optionStore.MJ_GlobalSetting.mj_simpleSetting.imageModel =
|
||||
mjRobotModelOptions.value.length > 0 ? mjRobotModelOptions.value[0].value : undefined
|
||||
|
||||
// 刷新命令后缀
|
||||
computedSuffix()
|
||||
}
|
||||
|
||||
function UpdateImageScale() {
|
||||
computedSuffix()
|
||||
}
|
||||
|
||||
function UpdateRobotModel() {
|
||||
computedSuffix()
|
||||
}
|
||||
</script>
|
||||
@ -111,18 +111,41 @@
|
||||
placeholder="输入迭代步数"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
style="width: 300px"
|
||||
label="FLXU API模型(和GPT公用一个服务商)"
|
||||
path="flux_model"
|
||||
>
|
||||
<n-select
|
||||
placeholder="请选择FLUX API的生图模型"
|
||||
v-model:value="formValue.flux_model"
|
||||
:options="flux_model_options"
|
||||
<div style="display: flex">
|
||||
<n-form-item
|
||||
style="width: 300px"
|
||||
label="FLXU API模型(和GPT公用一个服务商)"
|
||||
path="flux_model"
|
||||
>
|
||||
</n-select>
|
||||
</n-form-item>
|
||||
<n-select
|
||||
placeholder="请选择FLUX API的生图模型"
|
||||
v-model:value="formValue.flux_model"
|
||||
:options="flux_model_options"
|
||||
>
|
||||
</n-select>
|
||||
<n-button type="primary" style="margin-left: 10px" @click="GetFluxModelList"
|
||||
>加载数据
|
||||
</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
style="width: 150px; margin-left: 30px"
|
||||
label="是否国内转发"
|
||||
path="useTransfer"
|
||||
>
|
||||
<n-select
|
||||
placeholder="请选择是否转换"
|
||||
v-model:value="formValue.useTransfer"
|
||||
:options="[
|
||||
{ label: '是', value: true },
|
||||
{ label: '否', value: false }
|
||||
]"
|
||||
>
|
||||
</n-select>
|
||||
</n-form-item>
|
||||
<n-form-item style="margin-left: 30px">
|
||||
<div style="color: red">注意:使用国内转发可能会出现服务器超时错误,错误码504</div>
|
||||
</n-form-item>
|
||||
</div>
|
||||
<n-form-item>
|
||||
<n-button attr-type="button" type="primary" @click="SaveSDConfig"> 保存设置 </n-button>
|
||||
</n-form-item>
|
||||
@ -134,7 +157,7 @@
|
||||
</n-tabs>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { defineComponent, ref, h, onMounted, toRaw } from 'vue'
|
||||
import {
|
||||
NForm,
|
||||
@ -149,188 +172,164 @@ import {
|
||||
NCheckbox
|
||||
} from 'naive-ui'
|
||||
import SDADetailerSetting from '../Components/SDADetailerSetting.vue'
|
||||
import { FLxuAPIImageType } from '../../../../define/enum/image'
|
||||
import InitCommon from '../../common/initCommon'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInput,
|
||||
NButton,
|
||||
NInputNumber,
|
||||
NSelect,
|
||||
NTabs,
|
||||
NTabPane,
|
||||
SDADetailerSetting,
|
||||
NCheckbox
|
||||
},
|
||||
setup() {
|
||||
let formValue = ref({
|
||||
webui_api_url: window.config.webui_api_url,
|
||||
type: null,
|
||||
prompt: null,
|
||||
negative_prompt: null,
|
||||
denoising_strength: 1,
|
||||
sampler_name: null,
|
||||
steps: 15,
|
||||
width: 0,
|
||||
height: 0,
|
||||
adetailer: false,
|
||||
style_weight: 1,
|
||||
cfg_scale: 1,
|
||||
sd_models: null,
|
||||
lora: null,
|
||||
flux_model: FLxuAPIImageType.FLUX
|
||||
})
|
||||
let flux_model_options = ref([])
|
||||
|
||||
let samplers_options = ref([])
|
||||
let lora_options = ref([])
|
||||
let sd_models_options = ref([])
|
||||
|
||||
let modelOption = ref([
|
||||
{
|
||||
label: '文生图',
|
||||
value: 'txt2img'
|
||||
},
|
||||
{
|
||||
label: '图生图',
|
||||
value: 'img2img'
|
||||
}
|
||||
])
|
||||
|
||||
onMounted(async () => {
|
||||
await window.api.InitSDConfig((value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
formValue.value = value.data
|
||||
|
||||
let samplers = value.data.sampler
|
||||
samplers_options.value = []
|
||||
for (let i = 0; i < samplers.length; i++) {
|
||||
const element = samplers[i]
|
||||
samplers_options.value.push({
|
||||
label: element.name,
|
||||
value: element.name
|
||||
})
|
||||
}
|
||||
let loras = value.data.lora
|
||||
lora_options.value = []
|
||||
for (let i = 0; i < loras.length; i++) {
|
||||
const element = loras[i]
|
||||
lora_options.value.push({
|
||||
label: element.name,
|
||||
value: element.name
|
||||
})
|
||||
}
|
||||
let sd_models = value.data.sd_model
|
||||
sd_models_options.value = []
|
||||
for (let i = 0; i < sd_models.length; i++) {
|
||||
const element = sd_models[i]
|
||||
sd_models_options.value.push({
|
||||
label: element.title,
|
||||
value: element.title
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
let message = useMessage()
|
||||
/**
|
||||
* 保存SD设置
|
||||
*/
|
||||
async function SaveSDConfig() {
|
||||
// 保存SD配置
|
||||
await window.api.SaveSDConfig(toRaw(formValue.value), (value) => {
|
||||
if (value.code == 0) {
|
||||
window.api.showGlobalMessageDialog(value)
|
||||
return
|
||||
} else if (value.code == 1) {
|
||||
window.api.showGlobalMessageDialog(value)
|
||||
window.api.getSettingDafultData((value) => {
|
||||
window.config = value
|
||||
})
|
||||
return
|
||||
} else {
|
||||
window.api.showGlobalMessageDialog({ code: 0, message: value.message })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载SD数据
|
||||
*/
|
||||
async function LoadSDServiceData() {
|
||||
await window.sd.LoadSDServiceData(toRaw(formValue.value).webui_api_url, (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
// formValue.value = value.data
|
||||
// 获取当前的配置信息
|
||||
let samplers = value.data.sampler
|
||||
samplers_options.value = []
|
||||
for (let i = 0; i < samplers.length; i++) {
|
||||
const element = samplers[i]
|
||||
samplers_options.value.push({
|
||||
label: element.name,
|
||||
value: element.name
|
||||
})
|
||||
}
|
||||
let loras = value.data.lora
|
||||
lora_options.value = []
|
||||
for (let i = 0; i < loras.length; i++) {
|
||||
const element = loras[i]
|
||||
lora_options.value.push({
|
||||
label: element.name,
|
||||
value: element.name
|
||||
})
|
||||
}
|
||||
let sd_models = value.data.sd_model
|
||||
sd_models_options.value = []
|
||||
for (let i = 0; i < sd_models.length; i++) {
|
||||
const element = sd_models[i]
|
||||
sd_models_options.value.push({
|
||||
label: element.title,
|
||||
value: element.title
|
||||
})
|
||||
}
|
||||
message.success('加载成功')
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
formValue,
|
||||
SaveSDConfig,
|
||||
modelOption,
|
||||
LoadSDServiceData,
|
||||
samplers_options,
|
||||
lora_options,
|
||||
sd_models_options,
|
||||
flux_model_options: [
|
||||
{
|
||||
label: 'FLUX',
|
||||
value: FLxuAPIImageType.FLUX
|
||||
},
|
||||
{
|
||||
label: 'FLUX DEV',
|
||||
value: FLxuAPIImageType.FLUX_DEV
|
||||
},
|
||||
{
|
||||
label: 'FLUX PRO',
|
||||
value: FLxuAPIImageType.FLUX_PRO
|
||||
},
|
||||
{
|
||||
label: 'FLUX PRO MAX',
|
||||
value: FLxuAPIImageType.FLUX_PRO_MAX
|
||||
},
|
||||
{
|
||||
label: 'FLUX SCHNELL',
|
||||
value: FLxuAPIImageType.FLUX_SCHNELL
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
let formValue = ref({
|
||||
webui_api_url: window.config.webui_api_url,
|
||||
type: null,
|
||||
prompt: null,
|
||||
negative_prompt: null,
|
||||
denoising_strength: 1,
|
||||
sampler_name: null,
|
||||
steps: 15,
|
||||
width: 0,
|
||||
height: 0,
|
||||
adetailer: false,
|
||||
style_weight: 1,
|
||||
cfg_scale: 1,
|
||||
sd_models: null,
|
||||
lora: null,
|
||||
flux_model: null,
|
||||
useTransfer: false
|
||||
})
|
||||
|
||||
let samplers_options = ref([])
|
||||
let lora_options = ref([])
|
||||
let sd_models_options = ref([])
|
||||
|
||||
let modelOption = ref([
|
||||
{
|
||||
label: '文生图',
|
||||
value: 'txt2img'
|
||||
},
|
||||
{
|
||||
label: '图生图',
|
||||
value: 'img2img'
|
||||
}
|
||||
])
|
||||
|
||||
onMounted(async () => {
|
||||
await window.api.InitSDConfig((value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
formValue.value = value.data
|
||||
|
||||
let samplers = value.data.sampler
|
||||
samplers_options.value = []
|
||||
for (let i = 0; i < samplers.length; i++) {
|
||||
const element = samplers[i]
|
||||
samplers_options.value.push({
|
||||
label: element.name,
|
||||
value: element.name
|
||||
})
|
||||
}
|
||||
let loras = value.data.lora
|
||||
lora_options.value = []
|
||||
for (let i = 0; i < loras.length; i++) {
|
||||
const element = loras[i]
|
||||
lora_options.value.push({
|
||||
label: element.name,
|
||||
value: element.name
|
||||
})
|
||||
}
|
||||
let sd_models = value.data.sd_model
|
||||
sd_models_options.value = []
|
||||
for (let i = 0; i < sd_models.length; i++) {
|
||||
const element = sd_models[i]
|
||||
sd_models_options.value.push({
|
||||
label: element.title,
|
||||
value: element.title
|
||||
})
|
||||
}
|
||||
})
|
||||
await InitFluxModelList()
|
||||
})
|
||||
|
||||
/**
|
||||
* 初始化FLUX模型列表
|
||||
*/
|
||||
async function InitFluxModelList(isMust = false) {
|
||||
try {
|
||||
flux_model_options.value = await InitCommon.InitFluxModelList(isMust)
|
||||
if (!formValue.value.flux_model) {
|
||||
formValue.value.flux_model =
|
||||
flux_model_options.value.length > 0 ? flux_model_options.value[0].value : undefined
|
||||
}
|
||||
} catch (error) {
|
||||
message.error('加载FLUX模型列表失败')
|
||||
}
|
||||
}
|
||||
|
||||
async function GetFluxModelList() {
|
||||
await InitFluxModelList(true)
|
||||
message.success('加载远程 FLUX API 模型列表成功')
|
||||
}
|
||||
|
||||
let message = useMessage()
|
||||
/**
|
||||
* 保存SD设置
|
||||
*/
|
||||
async function SaveSDConfig() {
|
||||
// 保存SD配置
|
||||
await window.api.SaveSDConfig(toRaw(formValue.value), (value) => {
|
||||
if (value.code == 0) {
|
||||
window.api.showGlobalMessageDialog(value)
|
||||
return
|
||||
} else if (value.code == 1) {
|
||||
window.api.showGlobalMessageDialog(value)
|
||||
window.api.getSettingDafultData((value) => {
|
||||
window.config = value
|
||||
})
|
||||
return
|
||||
} else {
|
||||
window.api.showGlobalMessageDialog({ code: 0, message: value.message })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载SD数据
|
||||
*/
|
||||
async function LoadSDServiceData() {
|
||||
await window.sd.LoadSDServiceData(toRaw(formValue.value).webui_api_url, (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
// formValue.value = value.data
|
||||
// 获取当前的配置信息
|
||||
let samplers = value.data.sampler
|
||||
samplers_options.value = []
|
||||
for (let i = 0; i < samplers.length; i++) {
|
||||
const element = samplers[i]
|
||||
samplers_options.value.push({
|
||||
label: element.name,
|
||||
value: element.name
|
||||
})
|
||||
}
|
||||
let loras = value.data.lora
|
||||
lora_options.value = []
|
||||
for (let i = 0; i < loras.length; i++) {
|
||||
const element = loras[i]
|
||||
lora_options.value.push({
|
||||
label: element.name,
|
||||
value: element.name
|
||||
})
|
||||
}
|
||||
let sd_models = value.data.sd_model
|
||||
sd_models_options.value = []
|
||||
for (let i = 0; i < sd_models.length; i++) {
|
||||
const element = sd_models[i]
|
||||
sd_models_options.value.push({
|
||||
label: element.title,
|
||||
value: element.title
|
||||
})
|
||||
}
|
||||
message.success('加载成功')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -52,6 +52,7 @@ import { useOptionStore } from '@/stores/option'
|
||||
|
||||
let message = useMessage()
|
||||
let optionStore = useOptionStore()
|
||||
let roleOptions = ref([])
|
||||
|
||||
async function SwitchTTSOptions(key) {
|
||||
console.log('SwitchTTSOptions', key)
|
||||
@ -65,7 +66,6 @@ async function SwitchTTSOptions(key) {
|
||||
console.log('SwitchTTSOptions', roleOptions.value)
|
||||
}
|
||||
|
||||
let roleOptions = ref([])
|
||||
onMounted(async () => {
|
||||
// 获取配音角色列表
|
||||
await SwitchTTSOptions('edge-tts')
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
</n-form>
|
||||
<EdgeTTS v-if="optionStore.TTS_GlobalSetting.selectModel == 'edge-tts'" />
|
||||
<!-- <AzureTTS
|
||||
:azureTTS="settingStore.ttsSetting.azureTTS"
|
||||
:azureTTS=""
|
||||
v-else-if="optionStore.TTS_GlobalSetting.selectModel == 'azure-tts'"
|
||||
/> -->
|
||||
</div>
|
||||
|
||||
@ -86,7 +86,7 @@ const routes = [
|
||||
{
|
||||
path: '/mj_setting',
|
||||
name: 'mj_setting',
|
||||
component: () => import('./components/Setting/MJSetting.vue')
|
||||
component: () => import('./components/Setting/MJSetting/MJSettingHome.vue')
|
||||
},
|
||||
{
|
||||
path: '/video_setting',
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import { MJImageType, MJRobotType, MJSpeed } from "@/define/enum/mjEnum";
|
||||
import { OptionKeyName } from "@/define/enum/option";
|
||||
import { OptionModel } from "@/model/option/option";
|
||||
import { MJSettingModel } from "@/model/Setting/mjSetting";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export type OptionStoreModel = {
|
||||
//#region
|
||||
|
||||
//#region 文案处理
|
||||
|
||||
/** 文案处理 AI设置 */
|
||||
[OptionKeyName.CW_AISetting]: {
|
||||
@ -23,6 +26,11 @@ export type OptionStoreModel = {
|
||||
[OptionKeyName.TTS_GlobalSetting]: OptionModel.TTS_GlobalSettingModel | undefined;
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region MJ
|
||||
/** MJ 基础设置 */
|
||||
[OptionKeyName.MJ_GlobalSetting]: MJSettingModel.MJ_GlobalSettingModel;
|
||||
//#endregion
|
||||
}
|
||||
|
||||
export const useOptionStore = defineStore('option', {
|
||||
@ -64,6 +72,38 @@ export const useOptionStore = defineStore('option', {
|
||||
ttsText: "你好,我是你的智能语音助手!",
|
||||
/** 保存的音频文件路径 */
|
||||
saveAudioPath: undefined,
|
||||
},
|
||||
[OptionKeyName.MJ_GlobalSetting]: {
|
||||
mj_simpleSetting: {
|
||||
type: MJImageType.API_MJ,
|
||||
requestModel: MJImageType.API_MJ,
|
||||
selectRobot: MJRobotType.MJ,
|
||||
imageScale: "3e2772f2-041c-49c6-ba13-d0ed120310b8",
|
||||
imageModel: "3e6473ab-9a64-4574-9a38-f5c75af552b6",
|
||||
imageSuffix: " --niji 6 --ar 1:1",
|
||||
taskCount: 3,
|
||||
spaceTime: 10
|
||||
},
|
||||
mj_apiSetting: {
|
||||
id: "6db0d484-2a41-4545-8b26-ed32812965ad",
|
||||
mjApiUrl: "b44c6f24-59e4-4a71-b2c7-3df0c4e35e65",
|
||||
mjSpeed: MJSpeed.RELAX,
|
||||
apiKey: "LAI API的令牌",
|
||||
useTransfer: false
|
||||
},
|
||||
mj_browserSetting: {
|
||||
id: "4d5d57f2-1d7a-4e0f-b347-a7283e75d64a",
|
||||
serviceId: "自己的服务器ID",
|
||||
channelId: "自己的频道ID",
|
||||
mjBotId: "自己的MJ机器人ID",
|
||||
nijBotId: "自己的NIJI机器人ID",
|
||||
token: "自己的令牌",
|
||||
userAgent: "自己的UserAgent",
|
||||
userAgentCustom: false,
|
||||
},
|
||||
mj_remoteSimpleSetting: {
|
||||
useTransfer: false
|
||||
}
|
||||
}
|
||||
|
||||
} as unknown as OptionStoreModel),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { MJSetting } from '../model/Setting/mjSetting'
|
||||
import { MJSettingModel } from '../model/Setting/mjSetting'
|
||||
|
||||
// 系统相关设置
|
||||
export const useSettingStore = defineStore('setting', {
|
||||
@ -21,7 +21,7 @@ export const useSettingStore = defineStore('setting', {
|
||||
userToken: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined
|
||||
} as MJSetting.ActionRemoteMJSetting,
|
||||
} as MJSettingModel.ActionRemoteMJSettingModel,
|
||||
// tts 配置
|
||||
ttsSetting: {
|
||||
selectModel: 'edge-tts',
|
||||
@ -37,7 +37,7 @@ export const useSettingStore = defineStore('setting', {
|
||||
},
|
||||
} as TTSSettingModel.TTSSetting
|
||||
,
|
||||
ttsRoles: []
|
||||
ttsRoles: []
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
@ -62,7 +62,7 @@ export const useSettingStore = defineStore('setting', {
|
||||
userToken: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined
|
||||
} as MJSetting.ActionRemoteMJSetting
|
||||
} as MJSettingModel.ActionRemoteMJSettingModel
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user