This commit is contained in:
lq1405 2024-05-26 12:12:15 +08:00
parent 17709c1a0b
commit 941a86d07a
23 changed files with 994 additions and 738 deletions

2
.gitignore vendored
View File

@ -6,7 +6,7 @@ resources/scripts/dist
resources/scripts/model
resources/scripts/Temp
resources/image/Temp*
resources/package/ffmpeg*
resources/package/ffmpeg-2023*
resources/config*
*Lai.exe*
.DS_Store

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "laitool",
"version": "2.2.4",
"version": "2.2.5",
"lockfileVersion": 3,
"requires": true,
"packages": {

View File

@ -1,6 +1,6 @@
{
"name": "laitool",
"version": "2.2.4",
"version": "2.2.5",
"description": "An Electron application with Vue",
"main": "./out/main/index.js",
"author": "example.com",

Binary file not shown.

View File

@ -11,7 +11,7 @@ import shotSplit
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
# sys.argv = ["C:\\Users\\27698\\Desktop\\LAITool\\resources\\scripts\\Lai.exe","-c","C:/Users/27698/Desktop/测试/123/scripts/output_crop_00001.json"]
sys.argv = ["C:\\Users\\27698\\Desktop\\LAITool\\resources\\scripts\\Lai.exe","-c","C:/Users/27698/Desktop/测试/mjTest/scripts/output_crop_00001.json"]
print(sys.argv)
if len(sys.argv) < 2:

View File

@ -174,6 +174,7 @@ class ImageToVideo:
# 计算偏移变化率
offset_change_per_frame = float(end_offset - start_offset) / total_frames
current_offset = start_offset
scale = img_resized.shape[0] / video_size[1]
for _ in range(int(duration * fps)):
# 创建一个空白画布
@ -194,13 +195,15 @@ class ImageToVideo:
# 安全检查,确保不会复制超出边界的区域
src_x1 = max(-start_x, 0)
dst_x1 = max(start_x, 0)
copy_height = min(img_resized.shape[0] - src_x1, video_size[1] - dst_x1)
copy_width = min(img_resized.shape[1] - src_x1, video_size[0] - dst_x1)
# copy_width = min(video_size[0], img_resized.shape[1])
# 调整图片复制区域的计算
src_y1 = max(-start_y, 0)
dst_y1 = max(start_y, 0)
copy_width = min(img_resized.shape[1] - src_y1, video_size[0] - dst_y1)
copy_height = min(img_resized.shape[0] - src_y1, video_size[1] - dst_y1)
# copy_width = min(copy_width, img_resized.shape[1])
if copy_height > 0 and copy_width > 0:
canvas[dst_y1 : dst_y1 + copy_height, dst_x1 : dst_x1 + copy_width] = (
@ -238,6 +241,7 @@ class ImageToVideo:
# 计算偏移变化率
offset_change_per_frame = float(end_offset - start_offset) / total_frames
current_offset = start_offset
scale = img_resized.shape[1] / video_size[0]
for _ in range(int(duration * fps)):
# 创建一个空白画布

View File

@ -1,4 +1,6 @@
export const DEFINE_STRING = {
OPEN_DEV_TOOLS_PASSWORD: "OPEN_DEV_TOOLS_PASSWORD",
OPEN_DEV_TOOLS: "OPEN_DEV_TOOLS",
GET_FILE_BASE64: "GET_FILE_BASE64",
SAVE_DEFINE_CONFIG_JSON_BY_PROPERTY: "SAVE_DEFINE_CONFIG_JSON_BY_PROPERTY",
GET_DEFINE_CONFIG_JSON_BY_PROPERTY: "GET_DEFINE_CONFIG_JSON_BY_PROPERTY",

View File

@ -27,6 +27,18 @@ function GlobalIpc() {
return errorMessage("获取文件失败" + error)
}
});
ipcMain.on(DEFINE_STRING.OPEN_DEV_TOOLS, (event) => {
global.newWindow[0].win.webContents.openDevTools();
})
ipcMain.handle(DEFINE_STRING.OPEN_DEV_TOOLS_PASSWORD, (event, value) => {
if (value === "297ab55d41e9f5d3eba95b9df432f991") {
return successMessage("打开成功")
} else {
return errorMessage("管理控制台密码错误")
}
})
}
export {

View File

@ -1,5 +1,5 @@
const {
ipcMain
ipcMain, app
} = require("electron")
import { DEFINE_STRING } from '../../define/define_string'
import {
@ -7,7 +7,7 @@ import {
} from '../setting/setting'
let setting = new Setting(global);
function SettingIpc() {
async function SettingIpc() {
// 获取背景音乐配置列表
ipcMain.handle(DEFINE_STRING.GET_BACKGROUND_MUSIC_CONFIG_LIST, async (event) => await setting.GetBackGroundMusicConfigList());

View File

@ -246,19 +246,23 @@ export class ImageGenerate {
let task_list_json = JSON.parse(await fspromises.readFile(taskPath, 'utf-8'));
let auto_save_image = await this.tools.getJsonFilePropertyValue(define.img_base, "auto_save_image", {}, false);
let png_files = [];
let images = await this.tools.getFilesWithExtensions(path.join(this.global.config.project_path, 'tmp/input_crop'), '.png');
if (images.length <= 0) {
throw new Error("未检测到抽帧图片。请检查");
}
if (auto_save_image.save_match_count && auto_save_image.auto_match && images.length > auto_save_image.save_match_count && auto_save_image.main_save_folder) {
png_files = await this.tools.getFilesWithExtensions(auto_save_image.main_save_folder, '.png');
}
// 读取队列中的任务,然后添加队列
for (let i = 0; i < value.length; i++) {
const element = value[i];
let task_list = task_list_json.task_list.filter(item => item.id == element)[0];
let seed = -1;
let images = await this.tools.getFilesWithExtensions(path.join(this.global.config.project_path, 'tmp/input_crop'), '.png');
await fspromises.mkdir(path.join(this.global.config.project_path, 'tmp/' + task_list.out_folder), { recursive: true });
if (images.length <= 0) {
throw new Error("未检测到抽帧图片。请检查");
}
if (auto_save_image.save_match_count && auto_save_image.auto_match && images.length > auto_save_image.save_match_count) {
png_files = await this.tools.getFilesWithExtensions(auto_save_image.main_save_folder, '.png');
}
this.global.requestQuene.enqueue(async () => {
let res = await this.sd.OneImageGeneration(images[0], task_list, seed);
let tmp_seed = -1;
@ -267,11 +271,13 @@ export class ImageGenerate {
}
for (let j = 1; j < images.length; j++) {
const item = images[j];
// 判断item是不是一个图片的地址
if (!item.endsWith('.png')) {
continue;
}
let has_permission = false;
// 判断权限
let permission = this.global.permission;
if (permission && permission.length >= 0) {
if (permission.indexOf(DEFINE_STRING.PERMISSIONS.AUTO_SAVE_IMAGE_PERMISSION) >= 0) {
has_permission = true;
@ -279,7 +285,6 @@ export class ImageGenerate {
} else {
has_permission = true;
}
if (auto_save_image.save_match_count && j >= auto_save_image.save_match_count && has_permission && auto_save_image.auto_match) {
// 现在随机匹配视频
// 获取指定的文件夹中的图片

View File

@ -67,30 +67,31 @@ export class VideoGenerate {
await this.pm.AddWebuiJson();
let batch = DEFINE_STRING.QUEUE_BATCH.AUTO_VIDEO_GENERATE;
let taskPath = path.join(this.global.config.project_path, "scripts/task_list.json");
// 获取自动保存相关的配置数据
let auto_save_image = await this.tools.getJsonFilePropertyValue(define.img_base, "auto_save_image", {}, false);
// // 修改数据保存srt字幕文件位置。配音文件位置。背景音乐文件
// this.global.fileQueue.enqueue(async () => {
// let config_json = JSON.parse(await fspromises.readFile(path.join(this.global.config.project_path, "scripts/config.json"), 'utf-8'));
// config_json.srt_path = value[1].srt_path;
// config_json.audio_path = value[1].audio_path;
// config_json.background_music = value[1].background_music;
// await fspromises.writeFile(path.join(this.global.config.project_path, "scripts/config.json"), JSON.stringify(config_json));
// })
// 保存基础配置(文案,配音,背景音乐等)
await this.tools.writeJsonFilePropertyValue(path.join(this.global.config.project_path, "scripts/config.json"), "video_config", value[1]);
// 便利所有的队列任务
let images = await this.tools.getFilesWithExtensions(path.join(this.global.config.project_path, 'tmp/input_crop'), '.png');
if (images.length <= 0) {
throw new Error("未检测到抽帧图片。请检查");
}
let png_files = [];
// 获取图片文件夹
if (auto_save_image.save_match_count && auto_save_image.auto_match && images.length > auto_save_image.save_match_count && auto_save_image.main_save_folder) {
png_files = await this.tools.getFilesWithExtensions(auto_save_image.main_save_folder, '.png');
}
// 遍历所有的队列任务
for (let i = 0; i < value[0].length; i++) {
// 将所有的数据天添加到队列(总的大队列,有很多的小队列)
// 将所有生图任务添加到队列中
const task_list = value[0][i];
let seed = -1;
let subBatchId = `${task_list.out_folder}_image`
let images = await this.tools.getFilesWithExtensions(path.join(this.global.config.project_path, 'tmp/input_crop'), '.png');
await fspromises.mkdir(path.join(this.global.config.project_path, 'tmp/' + task_list.out_folder), { recursive: true });
if (images.length <= 0) {
throw new Error("未检测到抽帧图片。请检查");
}
this.global.requestQuene.enqueue(async () => {
let res = await this.sd.OneImageGeneration(images[0], task_list, seed);
let tmp_seed = -1;
@ -99,9 +100,31 @@ export class VideoGenerate {
}
for (let j = 1; j < images.length; j++) {
const element = images[j];
this.global.requestQuene.enqueue(async () => {
await this.sd.OneImageGeneration(element, task_list, tmp_seed);
}, `${task_list.out_folder}_${images[j]}`, batch, subBatchId)
if (!element.endsWith('.png')) {
continue;
}
let has_permission = false;
// 判断权限
let permission = this.global.permission;
if (permission && permission.length >= 0) {
if (permission.indexOf(DEFINE_STRING.PERMISSIONS.AUTO_SAVE_IMAGE_PERMISSION) >= 0) {
has_permission = true;
}
} else {
has_permission = true;
}
if (auto_save_image.save_match_count && auto_save_image.auto_match && j >= auto_save_image.save_match_count && has_permission) {
// 现在随机匹配视频
// 获取指定的文件夹中的图片
let randomData = png_files[Math.floor(Math.random() * png_files.length)];
let base_name = path.basename(element);
let copy_path = path.join(this.global.config.project_path, 'tmp/' + task_list.out_folder, base_name);
await this.tools.copyFileOrDirectory(randomData, copy_path);
} else {
this.global.requestQuene.enqueue(async () => {
await this.sd.OneImageGeneration(element, task_list, tmp_seed);
}, `${task_list.out_folder}_${images[j]}`, batch, subBatchId)
}
}
}, `${task_list.out_folder}_${images[0]}`, batch, subBatchId)

View File

@ -196,11 +196,12 @@ app.whenReady().then(async () => {
tools.checkFolderExistsOrCreate(path.normalize(define.temp_sd_image));
tools.checkFolderExistsOrCreate(path.normalize(path.join(define.image_path, "c_s")));
app.on('activate', function () {
app.on('activate', async function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) mainWindow = createWindow('ShowMessage', null)
if (BrowserWindow.getAllWindows().length === 0) {
mainWindow = createWindow('ShowMessage', null)
}
})
})
@ -213,6 +214,7 @@ app.on('window-all-closed', () => {
}
})
SettingIpc();
ImageGenerateIpc();
WritingIpc();

View File

@ -395,6 +395,10 @@ const api = {
// 知道文件地址获取文件base64编码
GetFileBase64: async (value, callback) => callback(await ipcRenderer.invoke(DEFINE_STRING.GET_FILE_BASE64, value)),
OpenDevTools: () => ipcRenderer.send(DEFINE_STRING.OPEN_DEV_TOOLS),
OpenDevToolsPassword: async (value, callback) => callback(await ipcRenderer.invoke(DEFINE_STRING.OPEN_DEV_TOOLS_PASSWORD, value)),
}
// Use `contextBridge` APIs to expose Electron APIs to

View File

@ -14,18 +14,27 @@
import { defineComponent, ref, onMounted } from 'vue'
import hljs from 'highlight.js/lib/core'
import javascript from 'highlight.js/lib/languages/javascript'
import { NMessageProvider, NDialogProvider, NConfigProvider, darkTheme, NNotificationProvider } from "naive-ui"
import {
NMessageProvider,
NDialogProvider,
NConfigProvider,
darkTheme,
NNotificationProvider
} from 'naive-ui'
hljs.registerLanguage('javascript', javascript)
export default defineComponent({
components: {
NConfigProvider, NDialogProvider, NMessageProvider, NNotificationProvider
NConfigProvider,
NDialogProvider,
NMessageProvider,
NNotificationProvider
},
setup() {
let themeData = ref("");
let themeData = ref('')
onMounted(() => {
window.api.getSettingDafultData(async (value) => {
themeData.value = value.theme;
themeData.value = value.theme
await window.darkMode.toggle(value.theme)
})
})
@ -34,7 +43,7 @@ export default defineComponent({
javascript,
hljs,
darkTheme,
themeData
themeData,
}
}
})

View File

@ -1,387 +1,452 @@
<template>
<div>一键矩阵功能有对应的字幕配置文件直接自动的生图高清合成视频 <span
style="margin-left: 20px ;font-size: 20px; color: red;">注意前三步还是必做</span></div>
<n-form ref="configRef" inline :model="config" :rules="rules">
<n-form-item label="SRT字幕文件" path="srt_path">
<n-input disabled v-model:value="config.srt_path" placeholder="选择SRT文件" />
<n-button color="#e5a84b" @click="SelectSrt">
<n-icon :size="20">
<folder-open />
</n-icon>
</n-button>
</n-form-item>
<n-form-item label="配音文件" path="audio_path">
<n-input disabled="" v-model:value="config.audio_path" placeholder="选择配音文件" />
<n-button color="#e5a84b" @click="SelectAudio">
<n-icon :size="20">
<folder-open />
</n-icon>
</n-button>
</n-form-item>
<n-form-item label="背景音乐文件夹" path="background_music">
<n-select style="width: 300px;" v-model:value="config.background_music" :options="background_music_options"
placeholder="选择背景音乐文件夹" />
</n-form-item>
<n-form-item>
<n-button :type="buttonLabel.type" @click="AutoConditionCheck">
{{ buttonLabel.label }}
</n-button>
</n-form-item>
<n-form-item>
<n-button type="success" @click="ActionTask">
一键全自动
</n-button>
</n-form-item>
</n-form>
<n-divider />
<n-data-table :columns="columns" :data="data" size="small" />
<div>
一键矩阵功能有对应的字幕配置文件直接自动的生图高清合成视频
<span style="margin-left: 20px; font-size: 20px; color: red">注意前三步还是必做</span>
</div>
<n-form ref="configRef" inline :model="config" :rules="rules">
<n-form-item label="SRT字幕文件" path="srt_path">
<n-input disabled v-model:value="config.srt_path" placeholder="选择SRT文件" />
<n-button color="#e5a84b" @click="SelectSrt">
<n-icon :size="20">
<folder-open />
</n-icon>
</n-button>
</n-form-item>
<n-form-item label="配音文件" path="audio_path">
<n-input disabled="" v-model:value="config.audio_path" placeholder="选择配音文件" />
<n-button color="#e5a84b" @click="SelectAudio">
<n-icon :size="20">
<folder-open />
</n-icon>
</n-button>
</n-form-item>
<n-form-item label="背景音乐文件夹" path="background_music">
<n-select
style="width: 300px"
v-model:value="config.background_music"
:options="background_music_options"
placeholder="选择背景音乐文件夹"
/>
</n-form-item>
<n-form-item>
<n-button :type="buttonLabel.type" @click="AutoConditionCheck">
{{ buttonLabel.label }}
</n-button>
</n-form-item>
<n-form-item>
<n-button type="success" @click="ActionTask"> 一键全自动 </n-button>
</n-form-item>
</n-form>
<n-divider />
<n-data-table
:columns="columns"
:data="data"
size="small"
:row-key="rowKey"
@update:checked-row-keys="SelectCheck"
/>
</template>
<script>
import { defineComponent, ref, onMounted, toRaw, h, onUnmounted } from "vue";
import { NSelect, NForm, NFormItem, NButton, NInput, NIcon, NPopover, useMessage, NDivider, NDataTable, NTag } from "naive-ui"
import { defineComponent, ref, onMounted, toRaw, h, onUnmounted } from 'vue'
import {
NSelect,
NForm,
NFormItem,
NButton,
NInput,
NIcon,
NPopover,
useMessage,
NDivider,
NDataTable,
NTag
} from 'naive-ui'
import { FolderOpenSharp as FolderOpen } from '@vicons/ionicons5'
import { DEFINE_STRING } from "../../../../define/define_string";
import { DEFINE_STRING } from '../../../../define/define_string'
import { cloneDeep } from 'lodash'
function statusAndMessage(row) {
if (row.status == 'wait') {
return {
tagLabel: "等待中",
color: '',
type: "warning"
}
} else if (row.status == 'queue') {
return {
tagLabel: "队列中",
color: '',
type: "info"
}
} else if (row.status == 'ok') {
return {
tagLabel: "生图完成(未高清)",
color: { color: "#2ed573", textColor: '#ffffff' },
type: ""
}
if (row.status == 'wait') {
return {
tagLabel: '等待中',
color: '',
type: 'warning'
}
else if (row.status == 'error') {
return {
tagLabel: "生图错误",
color: "",
type: "error"
}
} else if (row.status == 'queue') {
return {
tagLabel: '队列中',
color: '',
type: 'info'
}
else if (row.status == "video_improvied") {
return {
tagLabel: "高清完成",
color: { color: "#70a1ff", textColor: '#ffffff' },
type: ""
}
} else if (row.status == "video_improving") {
return {
tagLabel: "高清中",
color: { color: "#fedc5e", textColor: '#ffffff' },
type: ""
}
} else if (row.status == "video_improvie_error") {
return {
tagLabel: "高清失败",
color: { color: "#d23918", textColor: '#ffffff' },
type: ""
}
} else if (row.status == 'ok') {
return {
tagLabel: '生图完成(未高清)',
color: { color: '#2ed573', textColor: '#ffffff' },
type: ''
}
else if (row.status == "video_queue") {
return {
tagLabel: "合成队列中",
color: { color: "#55efc4", textColor: '#ffffff' },
type: ""
}
} else if (row.status == "video_error") {
return {
tagLabel: "合成失败",
color: { color: "#ff4757", textColor: '#ffffff' },
type: ""
}
} else if (row.status == "video_ok") {
return {
tagLabel: "合成完成",
color: { color: "#1dd1a1", textColor: '#ffffff' },
type: ""
}
} else {
return {
tagLabel: "状态错误",
color: { color: "#d2dae2", textColor: '#ffffff' },
type: ""
}
} else if (row.status == 'error') {
return {
tagLabel: '生图错误',
color: '',
type: 'error'
}
} else if (row.status == 'video_improvied') {
return {
tagLabel: '高清完成',
color: { color: '#70a1ff', textColor: '#ffffff' },
type: ''
}
} else if (row.status == 'video_improving') {
return {
tagLabel: '高清中',
color: { color: '#fedc5e', textColor: '#ffffff' },
type: ''
}
} else if (row.status == 'video_improvie_error') {
return {
tagLabel: '高清失败',
color: { color: '#d23918', textColor: '#ffffff' },
type: ''
}
} else if (row.status == 'video_queue') {
return {
tagLabel: '合成队列中',
color: { color: '#55efc4', textColor: '#ffffff' },
type: ''
}
} else if (row.status == 'video_error') {
return {
tagLabel: '合成失败',
color: { color: '#ff4757', textColor: '#ffffff' },
type: ''
}
} else if (row.status == 'video_ok') {
return {
tagLabel: '合成完成',
color: { color: '#1dd1a1', textColor: '#ffffff' },
type: ''
}
} else {
return {
tagLabel: '状态错误',
color: { color: '#d2dae2', textColor: '#ffffff' },
type: ''
}
}
}
const createColumns = ({
RemoveTask
}) => {
return [
{
title: "批次名称",
key: "out_folder"
},
const createColumns = ({ RemoveTask }) => {
return [
{
type: 'selection'
},
{
title: '批次名称',
key: 'out_folder'
},
{
title: "状态",
key: "status",
render(row) {
return h(
NTag,
{
type: (() => statusAndMessage(row))().type,
color: (() => statusAndMessage(row))().color,
bordered: false
},
{
default: (() => statusAndMessage(row).tagLabel)
}
);
}
},
{
title: "操作",
key: "actions",
render(row) {
return h(
NButton,
{
size: "small",
type: "warning",
onClick: async () => await RemoveTask(row)
},
{ default: () => "停止任务" }
);
}
}
];
};
{
title: '状态',
key: 'status',
render(row) {
return h(
NTag,
{
type: (() => statusAndMessage(row))().type,
color: (() => statusAndMessage(row))().color,
bordered: false
},
{
default: () => statusAndMessage(row).tagLabel
}
)
}
},
{
title: '操作',
key: 'actions',
render(row) {
return h(
NButton,
{
size: 'small',
type: 'warning',
onClick: async () => await RemoveTask(row)
},
{ default: () => '停止任务' }
)
}
}
]
}
export default defineComponent({
components: {
NSelect, NForm, NFormItem, NButton, NInput, NIcon, FolderOpen, NPopover, NDivider, NDataTable, NTag
},
setup() {
let config = ref({
srt_path: null,
audio_path: null,
draft_srt_style: "0",
background_music: null,
friendly_reminder: "0"
components: {
NSelect,
NForm,
NFormItem,
NButton,
NInput,
NIcon,
FolderOpen,
NPopover,
NDivider,
NDataTable,
NTag
},
setup() {
let config = ref({
srt_path: null,
audio_path: null,
draft_srt_style: '0',
background_music: null,
friendly_reminder: '0'
})
let background_music_options = ref([])
let configRef = ref(null)
let message = useMessage()
let buttonLabel = ref({
label: '未进行条件检测',
type: 'warning'
})
let data = ref([])
let selectRowKeysRef = ref([])
onMounted(async () => {
//
//
await window.api.GetBackgroundMusicConfigList((value) => {
if (value.code == 0) {
message.error(value.message)
return
}
for (let i = 0; i < value.value.length; i++) {
const element = value.value[i]
let obj = {
label: element.name,
value: element.id
}
background_music_options.value.push(obj)
}
})
//
await window.api.GetVideoGenerateConfig((value) => {
if (value.code == 0) {
message.error('获取初始化数据失败')
return
}
config.value.srt_path = value.data.srt_path
config.value.audio_path = value.data.audio_path
config.value.background_music = value.data.background_music
})
// -
await window.api.GetGenerateTaskList((value) => {
debugger
console.log(value)
data.value = value.data.task_list
})
//
window.api.setEventListen([DEFINE_STRING.VIDEO_GENERATE_STATUS_REFRESH], (value) => {
debugger
console.log(value)
let index = data.value.findIndex((item) => item.id == value.id)
if (index < 0) {
return
}
//
data.value[index].status = value.status
})
})
onUnmounted(() => {
window.api.removeEventListen(DEFINE_STRING.VIDEO_GENERATE_STATUS_REFRESH)
})
/**
* 全自动条件检测
*/
async function AutoConditionCheck(e) {
e.preventDefault()
configRef.value?.validate(async (errors) => {
debugger
if (errors) {
message.error('请检查必填字段')
return
}
await window.api.AutoConditionCheck(toRaw(config.value), (value) => {
if (value.code == 0) {
message.error(value.message)
buttonLabel.value = {
label: '条件检测失败',
type: 'error'
}
return
}
message.success('条件检测成功')
buttonLabel.value = {
label: '条件检测成功',
type: 'success'
}
})
let background_music_options = ref([]);
let configRef = ref(null);
let message = useMessage();
let buttonLabel = ref({
label: "未进行条件检测",
type: "warning"
})
let data = ref([]);
onMounted(async () => {
//
//
await window.api.GetBackgroundMusicConfigList((value) => {
if (value.code == 0) {
message.error(value.message);
return;
}
for (let i = 0; i < value.value.length; i++) {
const element = value.value[i];
let obj = {
label: element.name,
value: element.id,
}
background_music_options.value.push(obj);
}
})
//
await window.api.GetVideoGenerateConfig((value) => {
if (value.code == 0) {
message.error("获取初始化数据失败");
return;
}
config.value.srt_path = value.data.srt_path;
config.value.audio_path = value.data.audio_path;
config.value.background_music = value.data.background_music;
})
// -
await window.api.GetGenerateTaskList((value) => {
debugger;
console.log(value)
data.value = value.data.task_list;
})
//
window.api.setEventListen([DEFINE_STRING.VIDEO_GENERATE_STATUS_REFRESH], (value) => {
debugger;
console.log(value)
let index = data.value.findIndex(item => item.id == value.id);
if (index < 0) {
return;
}
//
data.value[index].status = value.status;
})
})
onUnmounted(() => {
window.api.removeEventListen(DEFINE_STRING.VIDEO_GENERATE_STATUS_REFRESH);
})
/**
* 全自动条件检测
*/
async function AutoConditionCheck(e) {
e.preventDefault();
configRef.value?.validate(async (errors) => {
debugger
if (errors) {
message.error("请检查必填字段");
return;
}
await window.api.AutoConditionCheck(toRaw(config.value), (value) => {
if (value.code == 0) {
message.error(value.message);
buttonLabel.value = {
label: "条件检测失败",
type: "error"
}
return;
}
message.success("条件检测成功");
buttonLabel.value = {
label: "条件检测成功",
type: "success"
}
})
});
}
/**
* 开始执行全自动任务
*/
async function ActionTask(e) {
e.preventDefault();
configRef.value?.validate(async (errors) => {
debugger
if (errors) {
message.error("请检查必填字段");
return;
}
if (buttonLabel.value.type != "success") {
message.error("请先进行条件检测");
return;
}
//
await window.api.ActionAutoVideoTask([[...toRaw(data.value)], toRaw(config.value)], (value) => {
debugger;
console.log(value);
// let index = data.value.findIndex(item=>item.id == value)
window.api.showGlobalMessageDialog(value)
})
});
}
/**
* 选择对应的字幕文件
*/
async function SelectSrt() {
window.api.SelectFile(['srt'], (value) => {
if (value.code == 0) {
message.error(value.message);
return;
}
config.value.srt_path = value.value;
});
}
/**
* 选择对应的字幕文件
*/
async function SelectAudio() {
window.api.SelectFile(['mp3', 'wav'], (value) => {
if (value.code == 0) {
message.error(value.message);
return;
}
config.value.audio_path = value.value;
});
}
/**
* 移除任务
* @param {*} row
*/
async function RemoveTask(row) {
//
await window.api.DeleteBackTask([DEFINE_STRING.QUEUE_BATCH.AUTO_VIDEO_GENERATE, "all", `${row.out_folder}_image`], async (value) => {
if (value.code == 0) {
message.error(value.message);
return;
}
//
await window.api.DeleteBackTask([DEFINE_STRING.QUEUE_BATCH.AUTO_VIDEO_GENERATE, "all", `${row.out_folder}_improve`], async (value) => {
if (value.code == 0) {
message.error(value.message);
return;
}
//
await window.api.DeleteBackTask([DEFINE_STRING.QUEUE_BATCH.AUTO_VIDEO_GENERATE, "all", `${row.out_folder}_video`], async (value) => {
if (value.code == 0) {
message.error(value.message);
return;
}
await window.api.ModifyGenerateTaskStatus(['out_folder', row.out_folder, 'wait'], (value) => {
if (value.code == 0) {
message.error(value.message);
return;
}
})
})
})
})
}
return {
config,
SelectSrt,
SelectAudio,
background_music_options,
AutoConditionCheck,
ActionTask,
configRef,
buttonLabel,
data,
columns: createColumns({
RemoveTask
}),
rules: {
srt_path: {
required: true,
message: "请输入SRT文件",
trigger: ["input", "blur"]
},
audio_path: {
required: true,
message: "请选择配音文件",
trigger: ["input", "blur"]
},
background_music: {
required: true,
message: "请选择背景音乐",
trigger: ["input", "blur"]
}
},
}
})
}
/**
* 开始执行全自动任务
*/
async function ActionTask(e) {
e.preventDefault()
configRef.value?.validate(async (errors) => {
debugger
console.log(selectRowKeysRef.value)
if (selectRowKeysRef.value.length <= 0) {
message.error('请选择要操作的任务')
return
}
if (errors) {
message.error('请检查必填字段')
return
}
if (buttonLabel.value.type != 'success') {
message.error('请先进行条件检测')
return
}
//
let tmp_data = cloneDeep(toRaw(data.value))
let end_data = []
for (let i = 0; i < selectRowKeysRef.value.length; i++) {
const element = selectRowKeysRef.value[i]
let index = tmp_data.findIndex((item) => item.id == element)
if (index >= 0) {
end_data.push(tmp_data[index])
}
}
//
await window.api.ActionAutoVideoTask([end_data, toRaw(config.value)], (value) => {
// let index = data.value.findIndex(item=>item.id == value)
window.api.showGlobalMessageDialog(value)
})
})
}
/**
* 选择对应的字幕文件
*/
async function SelectSrt() {
window.api.SelectFile(['srt'], (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
config.value.srt_path = value.value
})
}
/**
* 选择对应的字幕文件
*/
async function SelectAudio() {
window.api.SelectFile(['mp3', 'wav'], (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
config.value.audio_path = value.value
})
}
/**
* 移除任务
* @param {*} row
*/
async function RemoveTask(row) {
//
await window.api.DeleteBackTask(
[DEFINE_STRING.QUEUE_BATCH.AUTO_VIDEO_GENERATE, 'all', `${row.out_folder}_image`],
async (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
//
await window.api.DeleteBackTask(
[DEFINE_STRING.QUEUE_BATCH.AUTO_VIDEO_GENERATE, 'all', `${row.out_folder}_improve`],
async (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
//
await window.api.DeleteBackTask(
[DEFINE_STRING.QUEUE_BATCH.AUTO_VIDEO_GENERATE, 'all', `${row.out_folder}_video`],
async (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
await window.api.ModifyGenerateTaskStatus(
['out_folder', row.out_folder, 'wait'],
(value) => {
if (value.code == 0) {
message.error(value.message)
return
}
}
)
}
)
}
)
}
)
}
async function SelectCheck(rowKeys) {
selectRowKeysRef.value = rowKeys
}
return {
config,
SelectSrt,
SelectAudio,
background_music_options,
AutoConditionCheck,
ActionTask,
configRef,
buttonLabel,
SelectCheck,
data,
selectRowKeysRef,
rowKey: (row) => row.id,
columns: createColumns({
RemoveTask
}),
rules: {
srt_path: {
required: true,
message: '请输入SRT文件',
trigger: ['input', 'blur']
},
audio_path: {
required: true,
message: '请选择配音文件',
trigger: ['input', 'blur']
},
background_music: {
required: true,
message: '请选择背景音乐',
trigger: ['input', 'blur']
}
}
}
}
})
</script>
</script>

View File

@ -55,7 +55,7 @@ export default defineComponent({
})
function OpenTeachDoc() {
window.api.OpenUrl("https://pvwu1oahp5m.feishu.cn/docx/CAjGdTDlboJ3nVx0cQccOuNHnvd?from=from_copylink");
window.api.OpenUrl("https://rvgyir5wk1c.feishu.cn/docx/RZYCdG7ZpoKsIzxBEzccNEIFn8f?from=from_copylink");
}
function OpenQueDoc() {

View File

@ -1,327 +1,411 @@
<template>
<n-space vertical>
<n-layout has-sider style="height: 100vh; position: relative;">
<n-layout-sider bordered collapse-mode="width" :collapsed-width="64" :width="220" :collapsed="collapsed"
show-trigger @collapse="collapsed = true" @expand="collapsed = false">
<n-menu :collapsed="collapsed" :collapsed-width="64" :collapsed-icon-size="22" :options="menuOptions"
:render-icon="renderMenuIcon" :expand-icon="expandIcon" />
</n-layout-sider>
<n-layout-content content-style="padding:30px">
<!-- <Setting></Setting> -->
<router-view></router-view>
</n-layout-content>
</n-layout>
</n-space>
<n-space vertical>
<n-layout has-sider style="height: 100vh; position: relative">
<n-layout-sider
bordered
collapse-mode="width"
:collapsed-width="64"
:width="220"
:collapsed="collapsed"
show-trigger
@collapse="collapsed = true"
@expand="collapsed = false"
>
<n-menu
:collapsed="collapsed"
:collapsed-width="64"
:collapsed-icon-size="22"
:options="menuOptions"
:render-icon="renderMenuIcon"
:expand-icon="expandIcon"
/>
</n-layout-sider>
<n-layout-content content-style="padding:30px">
<!-- <Setting></Setting> -->
<router-view></router-view>
</n-layout-content>
</n-layout>
</n-space>
</template>
<script>
import { ref, h, onMounted, defineComponent, toRaw } from "vue"
import { RouterLink } from "vue-router"
import { NMenu, NSpace, NLayout, NLayoutSider, NLayoutContent, NIcon, useDialog, useNotification, useMessage, NSwitch, NButton } from "naive-ui";
import { ref, h, onMounted, defineComponent, toRaw } from 'vue'
import { RouterLink } from 'vue-router'
import {
NMenu,
NSpace,
NLayout,
NLayoutSider,
NLayoutContent,
NIcon,
useDialog,
useNotification,
useMessage,
NSwitch,
NButton
} from 'naive-ui'
import { BookmarkOutline, CaretDownOutline } from "@vicons/ionicons5";
import CheckMachineId from "../Components/CheckMachineId.vue"
import axios from 'axios';
import { DEFINE_STRING } from "../../../../define/define_string.js"
import { BookmarkOutline, CaretDownOutline } from '@vicons/ionicons5'
import CheckMachineId from '../Components/CheckMachineId.vue'
import axios from 'axios'
import { DEFINE_STRING } from '../../../../define/define_string.js'
import ShowMessage from './ShowMessage.vue'
import { MD5 } from 'crypto-js'
import InputDialogContent from '../Original/Components/InputDialogContent.vue'
export default defineComponent({
components: {
NMenu, NSpace, NLayout, NLayoutSider, NLayoutContent, NIcon, ShowMessage, NSwitch, NButton
},
setup() {
let collapsed = ref(false);
let dialog = useDialog();
let machineRef = ref();
let message = useMessage();
let notification = useNotification();
components: {
NMenu,
NSpace,
NLayout,
NLayoutSider,
NLayoutContent,
NIcon,
ShowMessage,
NSwitch,
NButton
},
setup() {
let collapsed = ref(false)
let dialog = useDialog()
let machineRef = ref()
let message = useMessage()
let notification = useNotification()
function renderMenuIcon(option) {
if (option.key === "sheep-man")
return true;
if (option.key === "food")
return null;
return h(NIcon, null, { default: () => h(BookmarkOutline) });
}
let key_down_ref = ref(null)
onMounted(async () => {
//
await window.api.GetVersion((value) => {
document.title = "LAITool " + value;
})
window.api.setEventListen([DEFINE_STRING.SHOW_MESSAGE_DIALOG], (value) => {
let message = value.message;
let type = "success";
let title = "成功"
if (value.code == 0) {
type = "error";
title = "成功但失败"
} else if (value.code == 2) {
type = "warning",
title = "警告"
}
dialog.create({
type: type,
title: title,
showIcon: true,
content: message,
style: `width : 400px;`,
maskClosable: false,
positiveText: "确定",
})
})
window.api.setEventListen([DEFINE_STRING.SHOW_MAIN_NOTIFICATION], (value) => {
let message = value.message;
let type = "success";
let title = "成功"
if (value.code == 0) {
type = "error";
title = "失败"
} else if (value.code == 2) {
type = "warning";
title = "警告"
}
notification.create({
type: type,
title: title,
content: message,
keepAliveOnHover: true,
duration: 2500,
})
})
//
dialog.create({
showIcon: false,
content: () => h(CheckMachineId, { ref: machineRef }),
style: `width : 400px; height: 300px`,
maskClosable: false,
positiveText: "确定",
onClose: () => {
//
window.api.QuitApp();
return false;
},
onEsc: () => {
//
window.api.QuitApp();
return false;
},
onPositiveClick: async () => {
debugger
await new Promise(async (resolve, reject) => {
await window.api.CheckMachineId(toRaw(machineRef.value.machineId), (value) => {
if (value.code == 0) {
message.error(value.message);
reject();
} else {
resolve();
}
});
});
}
})
window.api.getSettingDafultData(async (value) => {
window.config = value;
})
})
function expandIcon(value) {
return h(NIcon, null, { default: () => h(CaretDownOutline) });
}
const menuOptions = [
{
label: () => h(
RouterLink,
{
to: {
name: "sdoriginal",
}
},
{
default: () => "原创生图"
}
),
key: "sdoriginal",
},
{
label: "反推矩阵",
key: "backward_matrix",
children: [
{
label: () => h(
RouterLink,
{
to: {
name: "getframe",
}
},
{ default: () => "抽帧" }
),
key: "backward_frame"
},
{
label: () => h(
RouterLink,
{
to: {
name: "copywriting",
}
},
{ default: () => "文案洗稿" }
),
key: "copywriting"
},
{
label: () => h(
RouterLink,
{
to: {
name: "pushBackPrompt",
}
},
{ default: () => "反推提示词" }
),
key: "push_back"
},
{
label: () => h(
RouterLink,
{
to: {
name: "regenerate",
}
},
{ default: () => "批次生成" }
),
key: "regenerate"
},
{
label: () => h(
RouterLink,
{
to: {
name: "VideoGenerate",
}
},
{ default: () => "重绘/视频合成" }
),
key: "VideoGenerate"
}
]
},
// {
// label: "",
// key: "clip_options",
// children: [
// {
// label: () => h(
// RouterLink,
// {
// to: {
// name: "align_draft",
// }
// },
// { default: () => "稿" }
// ),
// key: "align_draft"
// },
// {
// label: () => h(
// RouterLink,
// {
// to: {
// name: "add_draft",
// }
// },
// { default: () => "稿" }
// ),
// key: "add_draft"
// }
// ]
// },
{
label: "设置",
key: "setting",
children: [
{
label: () => h(
RouterLink,
{
to: {
name: "global_setting",
}
},
{ default: () => "通用设置" }
),
key: "global_setting"
},
{
label: () => h(
RouterLink,
{
to: {
name: "clip_setting",
}
},
{ default: () => "剪映设置" }
),
key: "clip_setting"
},
{
label: () => h(
RouterLink,
{
to: {
name: "videogeneratesetting",
}
},
{ default: () => "生成视频设置" }
),
key: "videogeneratesetting"
},
{
label: () => h(
RouterLink,
{
to: {
name: "sd_setting",
}
},
{ default: () => "SD设置" }
),
key: "sd_setting"
},
{
label: () => h(
RouterLink,
{
to: {
name: "mj_setting",
}
},
{ default: () => "MJ设置" }
),
key: "mj_setting"
}
],
}
];
return {
renderMenuIcon,
menuOptions,
expandIcon,
collapsed,
}
function renderMenuIcon(option) {
if (option.key === 'sheep-man') return true
if (option.key === 'food') return null
return h(NIcon, null, { default: () => h(BookmarkOutline) })
}
onMounted(async () => {
//
await window.api.GetVersion((value) => {
document.title = 'LAITool ' + value
})
// ctrl + alt + l
window.addEventListener('keydown', (e) => {
if (e.ctrlKey && e.altKey && e.key === 'l') {
//
//
//
let dialogWidth = 400
let dialogHeight = 150
dialog.create({
title: '输入管理控制密码',
showIcon: false,
closeOnEsc: false,
content: () =>
h(InputDialogContent, {
ref: key_down_ref,
initData: null,
type: 'password',
placeholder: '请输入管理控制密码'
}),
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px`,
maskClosable: false,
onClose: async () => {
debugger
//
let password = toRaw(key_down_ref.value.data)
console.log(password)
// md5
let md5_password = MD5(password + DEFINE_STRING.OPEN_DEV_TOOLS).toString()
console.log(md5_password)
window.api.OpenDevToolsPassword(md5_password, (value) => {
if (value.code == 0) {
message.error(value.message)
} else {
window.api.OpenDevTools()
}
})
}
})
}
})
window.api.setEventListen([DEFINE_STRING.SHOW_MESSAGE_DIALOG], (value) => {
let message = value.message
let type = 'success'
let title = '成功'
if (value.code == 0) {
type = 'error'
title = '成功但失败'
} else if (value.code == 2) {
;(type = 'warning'), (title = '警告')
}
dialog.create({
type: type,
title: title,
showIcon: true,
content: message,
style: `width : 400px;`,
maskClosable: false,
positiveText: '确定'
})
})
window.api.setEventListen([DEFINE_STRING.SHOW_MAIN_NOTIFICATION], (value) => {
let message = value.message
let type = 'success'
let title = '成功'
if (value.code == 0) {
type = 'error'
title = '失败'
} else if (value.code == 2) {
type = 'warning'
title = '警告'
}
notification.create({
type: type,
title: title,
content: message,
keepAliveOnHover: true,
duration: 2500
})
})
//
dialog.create({
showIcon: false,
content: () => h(CheckMachineId, { ref: machineRef }),
style: `width : 400px; height: 300px`,
maskClosable: false,
positiveText: '确定',
onClose: () => {
//
window.api.QuitApp()
return false
},
onEsc: () => {
//
window.api.QuitApp()
return false
},
onPositiveClick: async () => {
debugger
await new Promise(async (resolve, reject) => {
await window.api.CheckMachineId(toRaw(machineRef.value.machineId), (value) => {
if (value.code == 0) {
message.error(value.message)
reject()
} else {
resolve()
}
})
})
}
})
window.api.getSettingDafultData(async (value) => {
window.config = value
})
})
function expandIcon(value) {
return h(NIcon, null, { default: () => h(CaretDownOutline) })
}
const menuOptions = [
{
label: () =>
h(
RouterLink,
{
to: {
name: 'sdoriginal'
}
},
{
default: () => '原创生图'
}
),
key: 'sdoriginal'
},
{
label: '反推矩阵',
key: 'backward_matrix',
children: [
{
label: () =>
h(
RouterLink,
{
to: {
name: 'getframe'
}
},
{ default: () => '抽帧' }
),
key: 'backward_frame'
},
{
label: () =>
h(
RouterLink,
{
to: {
name: 'copywriting'
}
},
{ default: () => '文案洗稿' }
),
key: 'copywriting'
},
{
label: () =>
h(
RouterLink,
{
to: {
name: 'pushBackPrompt'
}
},
{ default: () => '反推提示词' }
),
key: 'push_back'
},
{
label: () =>
h(
RouterLink,
{
to: {
name: 'regenerate'
}
},
{ default: () => '批次生成' }
),
key: 'regenerate'
},
{
label: () =>
h(
RouterLink,
{
to: {
name: 'VideoGenerate'
}
},
{ default: () => '重绘/视频合成' }
),
key: 'VideoGenerate'
}
]
},
// {
// label: "",
// key: "clip_options",
// children: [
// {
// label: () => h(
// RouterLink,
// {
// to: {
// name: "align_draft",
// }
// },
// { default: () => "稿" }
// ),
// key: "align_draft"
// },
// {
// label: () => h(
// RouterLink,
// {
// to: {
// name: "add_draft",
// }
// },
// { default: () => "稿" }
// ),
// key: "add_draft"
// }
// ]
// },
{
label: '设置',
key: 'setting',
children: [
{
label: () =>
h(
RouterLink,
{
to: {
name: 'global_setting'
}
},
{ default: () => '通用设置' }
),
key: 'global_setting'
},
{
label: () =>
h(
RouterLink,
{
to: {
name: 'clip_setting'
}
},
{ default: () => '剪映设置' }
),
key: 'clip_setting'
},
{
label: () =>
h(
RouterLink,
{
to: {
name: 'videogeneratesetting'
}
},
{ default: () => '生成视频设置' }
),
key: 'videogeneratesetting'
},
{
label: () =>
h(
RouterLink,
{
to: {
name: 'sd_setting'
}
},
{ default: () => 'SD设置' }
),
key: 'sd_setting'
},
{
label: () =>
h(
RouterLink,
{
to: {
name: 'mj_setting'
}
},
{ default: () => 'MJ设置' }
),
key: 'mj_setting'
}
]
}
]
return {
renderMenuIcon,
menuOptions,
expandIcon,
collapsed
}
}
})
</script>
</script>

View File

@ -32,7 +32,8 @@
v-if="outImagePath"
:src="outImagePath"
fit="cover"
style="width: 120px; height: 120px"
width="120"
height="120"
/>
</div>
<div>

View File

@ -1,6 +1,6 @@
<template>
<div style="margin-top: 30px">
<n-input :placeholder="placeholder" v-model:value="data"></n-input>
<n-input :placeholder="placeholder" :type="type" v-model:value="data"></n-input>
</div>
</template>
@ -12,17 +12,19 @@ export default defineComponent({
components: {
NInput
},
props: ['initData', 'placeholder'],
props: ['initData', 'placeholder', 'type'],
setup(props) {
let message = useMessage()
let data = ref(props.initData)
let placeholder = ref(props.placeholder)
let type = ref(props.type ? props.type : 'text')
onMounted(async () => {})
return {
data,
placeholder
placeholder,
type
}
}
})

View File

@ -366,7 +366,7 @@ export default defineComponent({
selectStyle.value = value.data
})
for (let i = 0; i < customize_image_style_list.length; i++) {
for (let i = 0; i < customize_image_style_list && customize_image_style_list.length; i++) {
const element = customize_image_style_list[i]
selectStyle.value.push({
key: element,
@ -395,6 +395,7 @@ export default defineComponent({
window.api.setEventListen(
[DEFINE_STRING.SD_ORIGINAL_GENERATE_IMAGE_RETURN, window.id],
(value) => {
debugger
if (value.code == 0) {
message.error('生成图片错误,错误信息如下:' + value.message)
return
@ -914,7 +915,10 @@ export default defineComponent({
cref_url = checkStringValueAddPrefix(cref_url, ' --cref ')
if (element.character_tags && element.character_tags.length > 0) {
cref_url = checkStringValueAddSuffix(cref_url, ` --cw ${element.character_tags[0].cref_cw} `)
cref_url = checkStringValueAddSuffix(
cref_url,
` --cw ${element.character_tags[0].cref_cw} `
)
}
// character_string
character_string = checkStringValueDeletePrefix(character_string, ',')

View File

@ -14,9 +14,10 @@
</n-form-item>
<n-form-item label="出图方式(文生图、图生图)" path="type">
<n-select
style="width: 250px"
v-model:value="formValue.type"
:options="modelOption"
placeholder="输入采样方法"
placeholder="选择出图方式"
/>
</n-form-item>
<n-form-item label="正向提示词和推导出来的tag进行拼接" path="prompt">
@ -51,7 +52,12 @@
</n-form-item>
</div>
<n-form-item label="采样方式" path="sampler_name">
<n-input v-model:value="formValue.sampler_name" placeholder="输入模型" />
<n-select
style="width: 250px"
v-model:value="formValue.sampler_name"
:options="samplers_options"
placeholder="选择采样方式"
/>
</n-form-item>
<div style="display: flex">
<n-form-item label="迭代步数" path="steps">
@ -161,13 +167,15 @@ export default defineComponent({
onMounted(async () => {
await window.api.InitSDConfig((value) => {
debugger
if (value.code == 0) {
message.error(value.message)
return
}
formValue.value = value.data
let samplers = value.data.samplers
let samplers = value.data.sampler
samplers_options.value = []
for (let i = 0; i < samplers.length; i++) {
const element = samplers[i]
samplers_options.value.push({
@ -175,7 +183,8 @@ export default defineComponent({
value: element.name
})
}
let loras = value.data.loras
let loras = value.data.lora
lora_options.value = []
for (let i = 0; i < loras.length; i++) {
const element = loras[i]
lora_options.value.push({
@ -183,7 +192,8 @@ export default defineComponent({
value: element.name
})
}
let sd_models = value.data.sd_models
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({
@ -221,11 +231,40 @@ export default defineComponent({
*/
async function LoadSDServiceData() {
await window.sd.LoadSDServiceData(toRaw(formValue.value).webui_api_url, (value) => {
debugger
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('加载成功')
})
}