V2.2.4 版本
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,154 +1,281 @@
|
||||
<template>
|
||||
<n-layout id="layout_height" has-sider style="height: 300px;">
|
||||
<n-layout-sider bordered :width="240" :native-scrollbar="false">
|
||||
<n-menu @update:value="SelectMenu" :options="menuOptions" v-model:value="selectedKeyRef" />
|
||||
</n-layout-sider>
|
||||
<n-layout :native-scrollbar="false" style="margin-top: 30px;">
|
||||
<div style="margin-left: 20px;">
|
||||
<div>选择的风格:</div>
|
||||
<ShowImageTag :selectStyle="selectStyle"></ShowImageTag>
|
||||
<div style="margin-top: 5px;">
|
||||
<div class="image-container" style="display: flex;">
|
||||
<n-image-group show-toolbar-tooltip>
|
||||
<div style="display: flex; flex-wrap: wrap;">
|
||||
<div v-for="(image, index) in style_image_list " style="margin: 0 5px 5px 5px;"
|
||||
:key="image.id">
|
||||
<n-image @contextmenu.prevent="handleContextMenu($event, image)" :width="150"
|
||||
:height="150" :src="image.image" alt="图片描述" lazy style="display: block;" />
|
||||
</div>
|
||||
</div>
|
||||
</n-image-group>
|
||||
<n-layout id="layout_height" has-sider style="height: 300px">
|
||||
<n-layout-sider bordered :width="240" :native-scrollbar="false">
|
||||
<n-menu @update:value="SelectMenu" :options="menuOptions" v-model:value="selectedKeyRef" />
|
||||
</n-layout-sider>
|
||||
<n-layout :native-scrollbar="false" style="margin-top: 10px">
|
||||
<n-tabs
|
||||
class="card-tabs"
|
||||
default-value="select"
|
||||
size="large"
|
||||
style="margin-left: 20px"
|
||||
animated
|
||||
pane-wrapper-style="margin: 0 -4px"
|
||||
pane-style="padding-left: 4px; padding-right: 4px; box-sizing: border-box;"
|
||||
>
|
||||
<n-tab-pane name="select" tab="选择风格">
|
||||
<div>
|
||||
<div>选择的风格:</div>
|
||||
<ShowImageTag :selectStyle="selectStyle"></ShowImageTag>
|
||||
<div style="margin-top: 5px">
|
||||
<div class="image-container" style="display: flex">
|
||||
<n-image-group show-toolbar-tooltip>
|
||||
<div style="display: flex; flex-wrap: wrap">
|
||||
<div
|
||||
v-for="(image, index) in style_image_list"
|
||||
style="margin: 0 5px 5px 5px"
|
||||
:key="image.id"
|
||||
>
|
||||
<n-image
|
||||
@contextmenu.prevent="handleContextMenu($event, image)"
|
||||
:width="150"
|
||||
:height="150"
|
||||
:src="image.image ? image.image : image.show_image"
|
||||
alt="图片描述"
|
||||
lazy
|
||||
style="display: block"
|
||||
/>
|
||||
<n-popover trigger="hover" v-if="image.type == 'style_main'">
|
||||
<template #trigger>
|
||||
<span
|
||||
style="
|
||||
display: block;
|
||||
text-align: center;
|
||||
width: 120px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
"
|
||||
>{{ image.prompt }}</span
|
||||
>
|
||||
</template>
|
||||
<span>{{ image.prompt }}</span>
|
||||
</n-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</n-image-group>
|
||||
</div>
|
||||
</div>
|
||||
</n-layout>
|
||||
</div>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="add" tab="添加风格">
|
||||
<AddStyleTags
|
||||
:currentStyle="null"
|
||||
:initFunc="null"
|
||||
:lora_options="lora_options"
|
||||
></AddStyleTags>
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</n-layout>
|
||||
</n-layout>
|
||||
|
||||
<n-dropdown style="z-index: 100;" trigger="manual" :x="x" :y="y" :options="dropOption" :show="showDropdownRef"
|
||||
:on-clickoutside="onClickoutside" @select="handleSelect" />
|
||||
<n-dropdown
|
||||
style="z-index: 100"
|
||||
trigger="manual"
|
||||
:x="x"
|
||||
:y="y"
|
||||
:options="dropOption"
|
||||
:show="showDropdownRef"
|
||||
:on-clickoutside="onClickoutside"
|
||||
@select="handleSelect"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, onMounted, watch, nextTick } from "vue";
|
||||
import { NDropdown, NImage, NLayout, NLayoutContent, NLayoutSider, NMenu, NSpace, NTag, NTooltip, messageDark, useMessage } from "naive-ui"
|
||||
import ShowImageTag from "./ShowImageTag.vue";
|
||||
import { defineComponent, ref, onMounted, watch, nextTick } from 'vue'
|
||||
import {
|
||||
NDropdown,
|
||||
NImage,
|
||||
NLayout,
|
||||
NLayoutContent,
|
||||
NLayoutSider,
|
||||
NMenu,
|
||||
NSpace,
|
||||
NTabPane,
|
||||
NTabs,
|
||||
NTag,
|
||||
NTooltip,
|
||||
messageDark,
|
||||
useMessage,
|
||||
NPopover
|
||||
} from 'naive-ui'
|
||||
import ShowImageTag from './ShowImageTag.vue'
|
||||
import AddStyleTags from '../Original/Components/AddStyleTags.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NSpace, NLayout, NLayoutSider, NLayoutContent, NMenu, NTag, NTooltip, NImage, NDropdown, ShowImageTag
|
||||
},
|
||||
props: ["selectStyle", "height"],
|
||||
setup(props) {
|
||||
let current_menu = null;
|
||||
let selectedKeyRef = ref(null);
|
||||
components: {
|
||||
NSpace,
|
||||
NLayout,
|
||||
NLayoutSider,
|
||||
NLayoutContent,
|
||||
NMenu,
|
||||
NTag,
|
||||
NTooltip,
|
||||
NImage,
|
||||
NDropdown,
|
||||
ShowImageTag,
|
||||
NTabs,
|
||||
NTabPane,
|
||||
AddStyleTags,
|
||||
NPopover
|
||||
},
|
||||
props: ['selectStyle', 'height', 'tags'],
|
||||
setup(props) {
|
||||
let current_menu = null
|
||||
let selectedKeyRef = ref(null)
|
||||
|
||||
let selectStyle = ref(props.selectStyle ? props.selectStyle : []);
|
||||
let style_image_list = ref([]);
|
||||
let message = useMessage();
|
||||
let showDropdownRef = ref(false);
|
||||
let current_img = ref(null);
|
||||
let menuOptions = ref([]);
|
||||
let selectStyle = ref(props.selectStyle ? props.selectStyle : [])
|
||||
let style_image_list = ref([])
|
||||
let message = useMessage()
|
||||
let showDropdownRef = ref(false)
|
||||
let current_img = ref(null)
|
||||
let menuOptions = ref([])
|
||||
let tags = ref(props.tags)
|
||||
let lora_options = ref([])
|
||||
|
||||
const x = ref(0);
|
||||
const y = ref(0);
|
||||
const x = ref(0)
|
||||
const y = ref(0)
|
||||
|
||||
let dropOption = [{
|
||||
label: "选择风格",
|
||||
key: "selectStyle"
|
||||
}];
|
||||
let dropOption = [
|
||||
{
|
||||
label: '选择风格',
|
||||
key: 'selectStyle'
|
||||
}
|
||||
]
|
||||
|
||||
// 监听props.selectStyle修改
|
||||
watch(() => props.selectStyle, (value) => {
|
||||
selectStyle.value = value;
|
||||
if (!selectStyle.value) {
|
||||
selectStyle.value = [];
|
||||
// 监听props.selectStyle修改
|
||||
watch(
|
||||
() => props.selectStyle,
|
||||
(value) => {
|
||||
selectStyle.value = value
|
||||
if (!selectStyle.value) {
|
||||
selectStyle.value = []
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
await window.api.GetDefineConfigJsonByProperty(
|
||||
JSON.stringify(['sd_setting', 'lora', false, []]),
|
||||
(value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
// 判断是不是有数据
|
||||
if (value.data) {
|
||||
for (let i = 0; i < value.data.length; i++) {
|
||||
const element = value.data[i]
|
||||
lora_options.value.push({
|
||||
label: element.name,
|
||||
value: element.name
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
setLayoutHeight("layout_height");
|
||||
await window.api.GetImageStyleMenu((value) => {
|
||||
debugger
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
menuOptions.value = value.data;
|
||||
current_menu = value.data[0].id;
|
||||
});
|
||||
await getStyleImageSubList();
|
||||
selectedKeyRef.value = current_menu;
|
||||
}
|
||||
}
|
||||
)
|
||||
setLayoutHeight('layout_height')
|
||||
await window.api.GetImageStyleMenu((value) => {
|
||||
debugger
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
menuOptions.value = value.data
|
||||
menuOptions.value.unshift({
|
||||
label: '自定义样式',
|
||||
id: 'tag',
|
||||
key: 'tag'
|
||||
})
|
||||
current_menu = menuOptions.value[0].id
|
||||
})
|
||||
await getStyleImageSubList()
|
||||
selectedKeyRef.value = current_menu
|
||||
})
|
||||
|
||||
/**
|
||||
* 菜单选中事件
|
||||
*/
|
||||
async function SelectMenu(key, item) {
|
||||
current_menu = key;
|
||||
await getStyleImageSubList();
|
||||
}
|
||||
|
||||
async function getStyleImageSubList() {
|
||||
await window.api.getStyleImageSubList(current_menu, (value) => {
|
||||
debugger;
|
||||
console.log(value)
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
style_image_list.value = value.data;
|
||||
});
|
||||
}
|
||||
|
||||
// 将指定ID的元素的的高度设置到和当前组件一样高
|
||||
function setLayoutHeight(id) {
|
||||
let layout_height = document.getElementById(id);
|
||||
layout_height.style.height = props.height - 40 + "px";
|
||||
}
|
||||
|
||||
async function closeTag(image) {
|
||||
debugger;
|
||||
let index = selectStyle.value.findIndex(item => item.id == image.id);
|
||||
if (index != -1) {
|
||||
selectStyle.value.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
selectStyle,
|
||||
menuOptions,
|
||||
SelectMenu,
|
||||
style_image_list,
|
||||
selectedKeyRef,
|
||||
showDropdownRef,
|
||||
dropOption,
|
||||
current_img,
|
||||
x: x,
|
||||
y: y,
|
||||
closeTag,
|
||||
handleContextMenu(e, image) {
|
||||
e.preventDefault();
|
||||
current_img.value = image;
|
||||
nextTick().then(() => {
|
||||
showDropdownRef.value = true;
|
||||
x.value = e.clientX;
|
||||
y.value = e.clientY;
|
||||
});
|
||||
},
|
||||
onClickoutside() {
|
||||
showDropdownRef.value = false;
|
||||
},
|
||||
handleSelect(key) {
|
||||
debugger
|
||||
showDropdownRef.value = false;
|
||||
if (key == "selectStyle") {
|
||||
// 将当前的风格添加到选择的风格中
|
||||
if (current_img.value) {
|
||||
selectStyle.value.push(current_img.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 菜单选中事件
|
||||
*/
|
||||
async function SelectMenu(key, item) {
|
||||
debugger
|
||||
current_menu = key
|
||||
await getStyleImageSubList()
|
||||
}
|
||||
|
||||
async function getStyleImageSubList() {
|
||||
style_image_list.value = []
|
||||
if (current_menu == 'tag') {
|
||||
for (let i = 0; i < tags.value.style_tags.length; i++) {
|
||||
const element = tags.value.style_tags[i]
|
||||
tags.value.style_tags[i].image = tags.value.style_tags[i].show_image
|
||||
tags.value.style_tags[i].id = tags.value.style_tags[i].key
|
||||
}
|
||||
// 获取当前风格风格中图片显示
|
||||
style_image_list.value = tags.value.style_tags
|
||||
} else {
|
||||
await window.api.getStyleImageSubList(current_menu, (value) => {
|
||||
debugger
|
||||
console.log(value)
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
style_image_list.value = value.data
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 将指定ID的元素的的高度设置到和当前组件一样高
|
||||
function setLayoutHeight(id) {
|
||||
let layout_height = document.getElementById(id)
|
||||
layout_height.style.height = props.height - 40 + 'px'
|
||||
}
|
||||
|
||||
async function closeTag(image) {
|
||||
debugger
|
||||
let index = selectStyle.value.findIndex((item) => item.id == image.id)
|
||||
if (index != -1) {
|
||||
selectStyle.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
selectStyle,
|
||||
menuOptions,
|
||||
SelectMenu,
|
||||
style_image_list,
|
||||
selectedKeyRef,
|
||||
showDropdownRef,
|
||||
dropOption,
|
||||
current_img,
|
||||
lora_options,
|
||||
tags,
|
||||
x: x,
|
||||
y: y,
|
||||
closeTag,
|
||||
handleContextMenu(e, image) {
|
||||
e.preventDefault()
|
||||
current_img.value = image
|
||||
nextTick().then(() => {
|
||||
showDropdownRef.value = true
|
||||
x.value = e.clientX
|
||||
y.value = e.clientY
|
||||
})
|
||||
},
|
||||
onClickoutside() {
|
||||
showDropdownRef.value = false
|
||||
},
|
||||
handleSelect(key) {
|
||||
showDropdownRef.value = false
|
||||
if (key == 'selectStyle') {
|
||||
debugger
|
||||
// 将当前的风格添加到选择的风格中
|
||||
if (current_img.value) {
|
||||
selectStyle.value.push(current_img.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -1,57 +1,72 @@
|
||||
<template>
|
||||
<div style="margin-top: 10px; min-height: 40px;">
|
||||
<n-tooltip trigger="hover" v-for="item in selectStyle" placement="bottom-start">
|
||||
<template #trigger>
|
||||
<n-tag @close="closeTag(item)" :key="item.id" type="success"
|
||||
style="margin-right: 10px; margin-bottom: 10px" closable>
|
||||
{{ item.id.split("-")[0] }}
|
||||
</n-tag>
|
||||
</template>
|
||||
<div>
|
||||
<n-image :src="item.image" :width="200" :preview-disabled="true"></n-image>
|
||||
</div>
|
||||
</n-tooltip>
|
||||
</div>
|
||||
<div style="margin-top: 10px; min-height: 40px">
|
||||
<n-tooltip trigger="hover" v-for="item in selectStyle" placement="bottom-start">
|
||||
<template #trigger>
|
||||
<n-tag
|
||||
@close="closeTag(item)"
|
||||
:key="item.id"
|
||||
type="success"
|
||||
style="margin-right: 10px; margin-bottom: 10px"
|
||||
closable
|
||||
>
|
||||
{{
|
||||
item.type && item.type == 'style_main'
|
||||
? '自定义_' + item.key.split('-')[0]
|
||||
: item.id.split('-')[0]
|
||||
}}
|
||||
</n-tag>
|
||||
</template>
|
||||
<div>
|
||||
<n-image
|
||||
:src="item.image ? item.image : item.show_image"
|
||||
:width="200"
|
||||
:preview-disabled="true"
|
||||
></n-image>
|
||||
</div>
|
||||
</n-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, onMounted, watch, nextTick } from "vue";
|
||||
import { NImage, NTag, NTooltip, useMessage } from "naive-ui"
|
||||
import { defineComponent, ref, onMounted, watch, nextTick } from 'vue'
|
||||
import { NImage, NTag, NTooltip, useMessage } from 'naive-ui'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NTag, NTooltip, NImage
|
||||
},
|
||||
props: ["selectStyle"],
|
||||
setup(props) {
|
||||
let selectStyle = ref(props.selectStyle ? props.selectStyle : []);
|
||||
let message = useMessage();
|
||||
components: {
|
||||
NTag,
|
||||
NTooltip,
|
||||
NImage
|
||||
},
|
||||
props: ['selectStyle'],
|
||||
setup(props) {
|
||||
let selectStyle = ref(props.selectStyle ? props.selectStyle : [])
|
||||
let message = useMessage()
|
||||
|
||||
|
||||
// 监听props.selectStyle修改
|
||||
watch(() => props.selectStyle, (value) => {
|
||||
selectStyle.value = value;
|
||||
if (!selectStyle.value) {
|
||||
selectStyle.value = [];
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
})
|
||||
|
||||
async function closeTag(image) {
|
||||
debugger;
|
||||
let index = selectStyle.value.findIndex(item => item.id == image.id);
|
||||
if (index != -1) {
|
||||
selectStyle.value.splice(index, 1);
|
||||
}
|
||||
// 监听props.selectStyle修改
|
||||
watch(
|
||||
() => props.selectStyle,
|
||||
(value) => {
|
||||
selectStyle.value = value
|
||||
if (!selectStyle.value) {
|
||||
selectStyle.value = []
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
selectStyle,
|
||||
closeTag,
|
||||
onMounted(async () => {})
|
||||
|
||||
}
|
||||
async function closeTag(image) {
|
||||
debugger
|
||||
let index = selectStyle.value.findIndex((item) => item.id == image.id)
|
||||
if (index != -1) {
|
||||
selectStyle.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
selectStyle,
|
||||
closeTag
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -1,173 +1,311 @@
|
||||
<template>
|
||||
<div style="width: 500px;">
|
||||
<n-form ref="formRef" label-placement="top" :model="characterData" :rules="rules">
|
||||
<n-form-item label="人物名称" path="label">
|
||||
<n-input v-model:value="characterData.label" placeholder="请输入人物名称" />
|
||||
</n-form-item>
|
||||
<n-form-item label="人物别名(可多个)">
|
||||
<n-dynamic-tags type="success" v-model:value="alias_tags" />
|
||||
</n-form-item>
|
||||
<n-form-item label="人物提示词(中文)">
|
||||
<n-input type="textarea" :rows="2" v-model:value="characterData.chinese_prompt"
|
||||
placeholder="请输入人物提示词" />
|
||||
<n-button type="info" size="small" style="margin-left: 20px;" @click="TranslatePrompt"
|
||||
:loading="loading">翻译提示词</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item label="人物提示词(英文)" path="prompt">
|
||||
<n-input type="textarea" :rows="2" v-model:value="characterData.prompt" placeholder="请输入人物提示词" />
|
||||
</n-form-item>
|
||||
<n-form-item label="MJ:人物图片链接(cref)">
|
||||
<n-input v-model:value="characterData.image_url" placeholder="请输入人物图片链接" style="margin-right: 20px;" />
|
||||
<n-image v-if="characterData.image_url" :src="characterData.image_url"
|
||||
style="width: 80px; height: 80px" />
|
||||
</n-form-item>
|
||||
<n-form-item label="MJ:角色迁移 cw 值(0-100)">
|
||||
<n-input-number :show-button="false" v-model:value="characterData.cref_cw" min="0" max="100"
|
||||
placeholder="请输入人物风格迁移的CW值" />
|
||||
</n-form-item>
|
||||
<n-form-item label="SD:Lora选择">
|
||||
<n-input v-model:value="characterData.lora" placeholder="请输入人物Lora选择" />
|
||||
<!-- <n-button color="#e18a3b" style="margin-left: 20px;">选择</n-button> -->
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<div style="text-align: right;">
|
||||
<n-button type="success" @click="SaveCharacterTag">保存</n-button>
|
||||
</div>
|
||||
<div>
|
||||
<div style="width: 500px; position: relative">
|
||||
<n-form ref="formRef" label-placement="top" :model="characterData" :rules="rules">
|
||||
<n-form-item label="人物名称" path="label">
|
||||
<n-input v-model:value="characterData.label" placeholder="请输入人物名称" />
|
||||
<n-image
|
||||
style="position: absolute; left: 520px; top: 0"
|
||||
width="120"
|
||||
height="120"
|
||||
:src="png_base64 ? png_base64 : characterData.show_image"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="人物别名(可多个)">
|
||||
<n-dynamic-tags type="success" v-model:value="alias_tags" />
|
||||
</n-form-item>
|
||||
<n-form-item label="人物提示词(中文)">
|
||||
<n-input
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
v-model:value="characterData.chinese_prompt"
|
||||
placeholder="请输入人物提示词"
|
||||
/>
|
||||
<!-- 里面的按钮设置上下居中 -->
|
||||
|
||||
<div style="width: 100px; margin-left: 20px">
|
||||
<n-button color="#a76283" size="tiny" @click="TranslatePrompt" :loading="loading"
|
||||
>翻译提示词</n-button
|
||||
>
|
||||
<n-button
|
||||
color="#e18a3b"
|
||||
size="tiny"
|
||||
style="margin-top: 10px"
|
||||
@click="GenerateCharacterImage"
|
||||
:loading="imageLoading"
|
||||
>生成图片</n-button
|
||||
>
|
||||
</div>
|
||||
</n-form-item>
|
||||
<n-form-item label="人物提示词(英文)" path="prompt">
|
||||
<n-input
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
v-model:value="characterData.prompt"
|
||||
placeholder="请输入人物提示词"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="MJ:人物图片链接(cref)">
|
||||
<n-input
|
||||
v-model:value="characterData.image_url"
|
||||
placeholder="请输入人物图片链接"
|
||||
style="margin-right: 20px"
|
||||
/>
|
||||
<n-image
|
||||
v-if="characterData.image_url"
|
||||
:src="characterData.image_url"
|
||||
style="width: 80px; height: 80px"
|
||||
:alt="characterData.image_url"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="MJ:角色迁移 cw 值(0-100)">
|
||||
<n-input-number
|
||||
:show-button="false"
|
||||
v-model:value="characterData.cref_cw"
|
||||
min="0"
|
||||
max="100"
|
||||
placeholder="请输入人物风格迁移的CW值"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="SD:Lora选择">
|
||||
<n-select
|
||||
v-model:value="characterData.lora"
|
||||
style="width: 250px"
|
||||
:options="lora_options"
|
||||
placeholder="选择人物lora"
|
||||
/>
|
||||
<n-input-number
|
||||
style="width: 120px; margin-left: 10px"
|
||||
placeholder="权重"
|
||||
v-model:value="characterData.lora_weight"
|
||||
:show-button="false"
|
||||
:max="2"
|
||||
:step="0.01"
|
||||
:precision="2"
|
||||
S
|
||||
:min="0"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<div style="text-align: right">
|
||||
<n-button type="success" @click="SaveCharacterTag">保存</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, h, onMounted, defineComponent, toRaw, watch } from "vue"
|
||||
import { NImage, useMessage, NButton, useDialog, NInput, NForm, NFormItem, NDynamicTags, NInputNumber } from "naive-ui";
|
||||
import { DEFINE_STRING } from "../../../../../define/define_string";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { ref, h, onMounted, defineComponent, toRaw, watch, nextTick } from 'vue'
|
||||
import {
|
||||
NImage,
|
||||
useMessage,
|
||||
NButton,
|
||||
useDialog,
|
||||
NInput,
|
||||
NForm,
|
||||
NFormItem,
|
||||
NDynamicTags,
|
||||
NInputNumber,
|
||||
NSelect
|
||||
} from 'naive-ui'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { isEmpty } from 'lodash'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NImage, NButton, NInput, NForm, NFormItem, NDynamicTags, NInputNumber
|
||||
},
|
||||
props: ["currentCharacter", "initFunc", "currentTags"],
|
||||
setup(props) {
|
||||
let message = useMessage();
|
||||
let alias_tags = ref(props.currentTags);
|
||||
let characterData = ref(props.currentCharacter);
|
||||
let loading = ref(false);
|
||||
let formRef = ref(null)
|
||||
components: {
|
||||
NImage,
|
||||
NButton,
|
||||
NInput,
|
||||
NForm,
|
||||
NFormItem,
|
||||
NDynamicTags,
|
||||
NInputNumber,
|
||||
NSelect
|
||||
},
|
||||
props: ['currentCharacter', 'initFunc', 'currentTags', 'lora_options'],
|
||||
setup(props) {
|
||||
let message = useMessage()
|
||||
let alias_tags = ref(props.currentTags)
|
||||
let characterData = ref(props.currentCharacter)
|
||||
let lora_options = ref(props.lora_options)
|
||||
let loading = ref(false)
|
||||
let imageLoading = ref(false)
|
||||
let formRef = ref(null)
|
||||
|
||||
// 监听数据变化
|
||||
watch(() => props.currentCharacter, (value) => {
|
||||
characterData.value = value;
|
||||
}, { deep: true })
|
||||
let png_base64 = ref(null)
|
||||
|
||||
watch(() => props.currentTags, (value) => {
|
||||
alias_tags.value = value;
|
||||
}, { deep: true })
|
||||
// 监听数据变化
|
||||
watch(
|
||||
() => props.currentCharacter,
|
||||
(value) => {
|
||||
characterData.value = value
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
watch(
|
||||
() => props.currentTags,
|
||||
(value) => {
|
||||
alias_tags.value = value
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
onMounted(async () => {})
|
||||
|
||||
async function SaveCharacterTag(e) {
|
||||
e.preventDefault()
|
||||
formRef.value?.validate(async (errors) => {
|
||||
if (errors) {
|
||||
message.error('请检查必填字段')
|
||||
return
|
||||
}
|
||||
// 保存之前要处理数据(判断该当前的将别名数组中的数据进行拆分)
|
||||
let children = []
|
||||
alias_tags.value.forEach((item) => {
|
||||
children.push({
|
||||
label: item,
|
||||
key: uuidv4(),
|
||||
type: 'min',
|
||||
chinese_prompt: characterData.value.chinese_prompt,
|
||||
prompt: characterData.value.prompt,
|
||||
image_url: characterData.value.image_url,
|
||||
show_image: characterData.value.show_image,
|
||||
cref_cw: characterData.value.cref_cw,
|
||||
lora: characterData.value.lora,
|
||||
lora_weight: characterData.value.lora_weight
|
||||
})
|
||||
})
|
||||
|
||||
async function SaveCharacterTag(e) {
|
||||
e.preventDefault();
|
||||
formRef.value?.validate(async (errors) => {
|
||||
if (errors) {
|
||||
message.error("请检查必填字段");
|
||||
return
|
||||
}
|
||||
// 保存之前要处理数据(判断该当前的将别名数组中的数据进行拆分)
|
||||
let children = [];
|
||||
alias_tags.value.forEach((item) => {
|
||||
children.push({
|
||||
label: item,
|
||||
key: uuidv4(),
|
||||
type: "min",
|
||||
chinese_prompt: characterData.value.chinese_prompt,
|
||||
prompt: characterData.value.prompt,
|
||||
image_url: characterData.value.image_url,
|
||||
cref_cw: characterData.value.cref_cw,
|
||||
lora: characterData.value.lora,
|
||||
})
|
||||
})
|
||||
characterData.value["children"] = children;
|
||||
|
||||
debugger;
|
||||
console.log(characterData.value);
|
||||
characterData.value['type'] = "character_main";
|
||||
|
||||
// 开始保存
|
||||
await window.mj.SaveTagPropertyData([JSON.stringify(characterData.value), "character_tags"], (value) => {
|
||||
debugger;
|
||||
console.log(value);
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
message.success(value.message);
|
||||
//保存成功在initFunc
|
||||
props.initFunc();
|
||||
// 清楚数据
|
||||
characterData.value = {
|
||||
label: null,
|
||||
key: null,
|
||||
type: "character_main",
|
||||
prompt: null,
|
||||
image_url: null,
|
||||
cref_cw: 20,
|
||||
lora: null,
|
||||
};
|
||||
alias_tags.value = [];
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// 翻译提示词
|
||||
async function TranslatePrompt() {
|
||||
loading.value = true;
|
||||
if (characterData.value.chinese_prompt == "" || characterData.value.chinese_prompt == null) {
|
||||
message.error("请输入中文提示词");
|
||||
loading.value = false;
|
||||
return;
|
||||
characterData.value['children'] = children
|
||||
console.log(characterData.value)
|
||||
characterData.value['type'] = 'character_main'
|
||||
// 开始保存
|
||||
await window.mj.SaveTagPropertyData(
|
||||
[JSON.stringify(characterData.value), 'character_tags'],
|
||||
(value) => {
|
||||
debugger
|
||||
console.log(value)
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
await window.api.TranslateReturnNow([characterData.value.chinese_prompt, 'zh', 'en', false], (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
debugger
|
||||
//
|
||||
console.log(value.data);
|
||||
characterData.value.prompt = value.data[0].src;
|
||||
})
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
|
||||
let ruleObj = (errorMessage) => {
|
||||
return [{
|
||||
required: true,
|
||||
validator(rule, value) {
|
||||
if (value == null || value == "")
|
||||
return new Error(errorMessage);
|
||||
return true;
|
||||
},
|
||||
trigger: ["input", "blur", "change"]
|
||||
}]
|
||||
}
|
||||
let rules = {
|
||||
label: ruleObj("必填人物名称"),
|
||||
prompt: ruleObj("必填英文提示词")
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
characterData,
|
||||
alias_tags,
|
||||
SaveCharacterTag,
|
||||
TranslatePrompt,
|
||||
loading,
|
||||
rules,
|
||||
formRef
|
||||
}
|
||||
message.success(value.message)
|
||||
//保存成功在initFunc
|
||||
props.initFunc()
|
||||
// 清楚数据
|
||||
characterData.value = {
|
||||
label: null,
|
||||
key: null,
|
||||
type: 'character_main',
|
||||
chinese_prompt: null,
|
||||
prompt: null,
|
||||
image_url: null,
|
||||
show_image: window.config.space_image,
|
||||
cref_cw: 20,
|
||||
chinese_prompt: null,
|
||||
lora: '无',
|
||||
lora_weight: 1
|
||||
}
|
||||
png_base64.value = null
|
||||
alias_tags.value = []
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// 翻译提示词
|
||||
async function TranslatePrompt() {
|
||||
loading.value = true
|
||||
if (characterData.value.chinese_prompt == '' || characterData.value.chinese_prompt == null) {
|
||||
message.error('请输入中文提示词')
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
await window.api.TranslateReturnNow(
|
||||
[characterData.value.chinese_prompt, 'zh', 'en', false],
|
||||
(value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
characterData.value.prompt = value.data[0].src
|
||||
}
|
||||
)
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
let ruleObj = (errorMessage) => {
|
||||
return [
|
||||
{
|
||||
required: true,
|
||||
validator(rule, value) {
|
||||
if (value == null || value == '') return new Error(errorMessage)
|
||||
return true
|
||||
},
|
||||
trigger: ['input', 'blur', 'change']
|
||||
}
|
||||
]
|
||||
}
|
||||
let rules = {
|
||||
label: ruleObj('必填人物名称'),
|
||||
prompt: ruleObj('必填英文提示词')
|
||||
}
|
||||
|
||||
/**
|
||||
* 单张生成角色图片,预览
|
||||
*/
|
||||
async function GenerateCharacterImage() {
|
||||
// 判断lora是不是存在
|
||||
let lora = ''
|
||||
if (
|
||||
characterData.value.lora != null &&
|
||||
characterData.value.lora != '' &&
|
||||
characterData.value.lora != '无'
|
||||
) {
|
||||
lora = `<lora:${characterData.value.lora}:${characterData.value.lora_weight}>`
|
||||
}
|
||||
let d = {
|
||||
prompt: `${characterData.value.prompt}, ${lora}`,
|
||||
width: 1024,
|
||||
height: 1024
|
||||
}
|
||||
if (isEmpty(characterData.value.prompt)) {
|
||||
message.error('请填写英文提示词')
|
||||
return
|
||||
}
|
||||
imageLoading.value = true
|
||||
await window.sd.txt2img(JSON.stringify([d]), async (value) => {
|
||||
debugger
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
imageLoading.value = false
|
||||
return
|
||||
}
|
||||
if (value.data && value.data.length > 0) {
|
||||
let d = value.data[0]
|
||||
characterData.value.show_image = d.image_path.replaceAll('\\', '/')
|
||||
png_base64.value = 'data:image/png;base64,' + d.base64
|
||||
console.log(characterData.value.show_image)
|
||||
imageLoading.value = false
|
||||
}
|
||||
// 使用 Vue.nextTick 等待 Vue 更新视图
|
||||
imageLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
characterData,
|
||||
alias_tags,
|
||||
SaveCharacterTag,
|
||||
TranslatePrompt,
|
||||
loading,
|
||||
rules,
|
||||
formRef,
|
||||
lora_options,
|
||||
imageLoading,
|
||||
GenerateCharacterImage,
|
||||
png_base64
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -1,144 +1,281 @@
|
||||
<template>
|
||||
<div style="width: 500px;">
|
||||
<n-form label-placement="top" ref="formRef" :rules="rules" :model="styleData">
|
||||
<n-form-item label="风格名称" path="label">
|
||||
<n-input v-model:value="styleData.label" placeholder="请输入风格名称" />
|
||||
</n-form-item>
|
||||
<n-form-item label="风格提示词描述(中文)">
|
||||
<n-input type="textarea" :rows="3" v-model:value="styleData.chinese_prompt"
|
||||
placeholder="请输入风格提示词描述(中文)" />
|
||||
<n-button type="info" size="small" style="margin-left: 20px;" @click="TranslatePrompt"
|
||||
:loading="loading">翻译提示词</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item label="风格提示词描述(英文)" path ="prompt">
|
||||
<n-input type="textarea" :rows="3" v-model:value="styleData.prompt" placeholder="请输入风格提示词描述(英文)" />
|
||||
</n-form-item>
|
||||
<n-form-item label="MJ:风格垫图链接(sref)">
|
||||
<n-input v-model:value="styleData.image_url" placeholder="请输入风格垫图链接" style="margin-right: 20px;" />
|
||||
<n-image v-if="styleData.image_url" :src="styleData.image_url" style="width: 80px; height: 80px" />
|
||||
</n-form-item>
|
||||
<n-form-item label="MJ:风格迁移 cw 值(0-1000)">
|
||||
<n-input-number :show-button="false" v-model:value="styleData.sref_cw" min="0" max="1000"
|
||||
placeholder="请输入人物风格迁移的CW值" />
|
||||
</n-form-item>
|
||||
<n-form-item label="SD:Lora选择">
|
||||
<n-input v-model:value="styleData.lora" placeholder="请输入风格Lora" />
|
||||
<!-- <n-button color="#e18a3b" style="margin-left: 20px;">选择</n-button> -->
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
|
||||
<div style="text-align: right;">
|
||||
<n-button type="success" @click="SaveStyleTag">保存</n-button>
|
||||
<div style="width: 500px">
|
||||
<n-form label-placement="top" ref="formRef" :rules="rules" :model="styleData">
|
||||
<n-form-item label="风格名称" path="label">
|
||||
<n-input v-model:value="styleData.label" placeholder="请输入风格名称" />
|
||||
<n-image
|
||||
style="position: absolute; left: 520px; top: 0"
|
||||
width="120"
|
||||
height="120"
|
||||
:src="png_base64 ? png_base64 : styleData.show_image"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="风格提示词描述(中文)">
|
||||
<n-input
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
v-model:value="styleData.chinese_prompt"
|
||||
placeholder="请输入风格提示词描述(中文)"
|
||||
/>
|
||||
<div style="width: 100px; margin-left: 20px">
|
||||
<n-button type="info" size="tiny" @click="TranslatePrompt" :loading="loading"
|
||||
>翻译提示词</n-button
|
||||
>
|
||||
<n-tooltip trigger="hover">
|
||||
<template #trigger>
|
||||
<n-button
|
||||
color="#e18a3b"
|
||||
size="tiny"
|
||||
style="margin-top: 10px"
|
||||
@click="GenerateStyleImage"
|
||||
:loading="imageLoading"
|
||||
>生成图片</n-button
|
||||
>
|
||||
</template>
|
||||
使用SD出图模式生成风格图片,提示词为1gril加上风格提示词
|
||||
</n-tooltip>
|
||||
</div>
|
||||
</n-form-item>
|
||||
<n-form-item label="风格提示词描述(英文)" path="prompt">
|
||||
<n-input
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
v-model:value="styleData.prompt"
|
||||
placeholder="请输入风格提示词描述(英文)"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="MJ:风格垫图链接(sref)">
|
||||
<n-input
|
||||
v-model:value="styleData.image_url"
|
||||
placeholder="请输入风格垫图链接"
|
||||
style="margin-right: 20px"
|
||||
/>
|
||||
<n-image
|
||||
v-if="styleData.image_url"
|
||||
:src="styleData.image_url"
|
||||
style="width: 80px; height: 80px"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="MJ:风格迁移 sw 值(0-1000)">
|
||||
<n-input-number
|
||||
:show-button="false"
|
||||
v-model:value="styleData.sref_sw"
|
||||
min="0"
|
||||
max="1000"
|
||||
placeholder="请输入人物风格迁移的SW值"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="SD:Lora选择">
|
||||
<n-select :options="lora_options" v-model:value="styleData.lora"> </n-select>
|
||||
<n-input-number
|
||||
style="width: 120px; margin-left: 10px"
|
||||
placeholder="权重"
|
||||
v-model:value="styleData.lora_weight"
|
||||
:show-button="false"
|
||||
:max="2"
|
||||
:step="0.01"
|
||||
:precision="2"
|
||||
S
|
||||
:min="0"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
|
||||
<div style="text-align: right">
|
||||
<n-button type="success" @click="SaveStyleTag">保存</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, h, onMounted, defineComponent, toRaw, watch } from "vue"
|
||||
import { NImage, useMessage, NButton, useDialog, NInput, NForm, NFormItem, NDynamicTags, NInputNumber } from "naive-ui";
|
||||
import { DEFINE_STRING } from "../../../../../define/define_string";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { ref, h, onMounted, defineComponent, toRaw, watch } from 'vue'
|
||||
import {
|
||||
NImage,
|
||||
useMessage,
|
||||
NButton,
|
||||
useDialog,
|
||||
NInput,
|
||||
NForm,
|
||||
NFormItem,
|
||||
NDynamicTags,
|
||||
NInputNumber,
|
||||
NSelect,
|
||||
NTooltip
|
||||
} from 'naive-ui'
|
||||
import { isEmpty } from 'lodash'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NImage, NButton, NInput, NForm, NFormItem, NDynamicTags, NInputNumber
|
||||
},
|
||||
props: ["currentStyle", "initFunc"],
|
||||
setup(props) {
|
||||
let message = useMessage();
|
||||
let styleData = ref(props.currentStyle);
|
||||
let loading = ref(false);
|
||||
let formRef = ref(null)
|
||||
components: {
|
||||
NImage,
|
||||
NButton,
|
||||
NInput,
|
||||
NForm,
|
||||
NFormItem,
|
||||
NDynamicTags,
|
||||
NInputNumber,
|
||||
NSelect,
|
||||
NTooltip
|
||||
},
|
||||
props: ['currentStyle', 'initFunc', 'lora_options'],
|
||||
setup(props) {
|
||||
let message = useMessage()
|
||||
let styleData = ref(
|
||||
props.currentStyle
|
||||
? props.currentStyle
|
||||
: { show_image: window.config.space_image, lora_weight: 1, sref_sw: 50, lora: '无' }
|
||||
)
|
||||
let loading = ref(false)
|
||||
let imageLoading = ref(false)
|
||||
let formRef = ref(null)
|
||||
let lora_options = ref(props.lora_options)
|
||||
let png_base64 = ref(null)
|
||||
|
||||
// 监听数据变化
|
||||
watch(() => props.currentStyle, (value) => {
|
||||
styleData.value = value;
|
||||
}, { deep: true })
|
||||
// 监听数据变化
|
||||
watch(
|
||||
() => props.currentStyle,
|
||||
(value) => {
|
||||
styleData.value = value
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
onMounted(async () => {})
|
||||
|
||||
})
|
||||
|
||||
async function SaveStyleTag(e) {
|
||||
e.preventDefault();
|
||||
formRef.value?.validate(async (errors) => {
|
||||
if (errors) {
|
||||
message.error("请检查必填字段");
|
||||
return
|
||||
}
|
||||
styleData.value["type"] = "style_main";
|
||||
// 直接保存
|
||||
// 开始保存
|
||||
await window.mj.SaveTagPropertyData([JSON.stringify(styleData.value), "style_tags"], (value) => {
|
||||
debugger;
|
||||
console.log(value);
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
message.success(value.message);
|
||||
//保存成功在initFunc
|
||||
props.initFunc();
|
||||
// 清楚数据
|
||||
styleData.value = {
|
||||
label: null,
|
||||
key: null,
|
||||
type: "style_main",
|
||||
prompt: null,
|
||||
image_url: null,
|
||||
cref_cw: 20,
|
||||
lora: null,
|
||||
};
|
||||
})
|
||||
});
|
||||
async function SaveStyleTag(e) {
|
||||
e.preventDefault()
|
||||
formRef.value?.validate(async (errors) => {
|
||||
if (errors) {
|
||||
message.error('请检查必填字段')
|
||||
return
|
||||
}
|
||||
|
||||
/**
|
||||
* 翻译中文提示词
|
||||
*/
|
||||
async function TranslatePrompt(){
|
||||
loading.value = true;
|
||||
if (styleData.value.chinese_prompt == "" || styleData.value.chinese_prompt == null) {
|
||||
message.error("请输入中文提示词");
|
||||
loading.value = false;
|
||||
return;
|
||||
styleData.value['type'] = 'style_main'
|
||||
// 直接保存
|
||||
// 开始保存
|
||||
await window.mj.SaveTagPropertyData(
|
||||
[JSON.stringify(styleData.value), 'style_tags'],
|
||||
(value) => {
|
||||
debugger
|
||||
console.log(value)
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
await window.api.TranslateReturnNow([styleData.value.chinese_prompt, 'zh', 'en', false], (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
//
|
||||
console.log(value.data);
|
||||
styleData.value.prompt = value.data[0].src;
|
||||
})
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
let ruleObj = (errorMessage) => {
|
||||
return [{
|
||||
required: true,
|
||||
validator(rule, value) {
|
||||
if (value == null || value == "")
|
||||
return new Error(errorMessage);
|
||||
return true;
|
||||
},
|
||||
trigger: ["input", "blur", "change"]
|
||||
}]
|
||||
}
|
||||
let rules = {
|
||||
label: ruleObj("必填人物名称"),
|
||||
prompt: ruleObj("必填英文提示词")
|
||||
};
|
||||
|
||||
return {
|
||||
styleData,
|
||||
SaveStyleTag,
|
||||
loading,
|
||||
rules,
|
||||
formRef,
|
||||
TranslatePrompt
|
||||
}
|
||||
message.success(value.message)
|
||||
//保存成功在initFunc
|
||||
props.initFunc()
|
||||
// 清楚数据
|
||||
styleData.value = {
|
||||
label: null,
|
||||
key: null,
|
||||
type: 'style_main',
|
||||
prompt: null,
|
||||
show_image: window.config.space_image,
|
||||
image_url: null,
|
||||
cref_cw: 20,
|
||||
lora: '无'
|
||||
}
|
||||
png_base64.value = null
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 翻译中文提示词
|
||||
*/
|
||||
async function TranslatePrompt() {
|
||||
loading.value = true
|
||||
if (styleData.value.chinese_prompt == '' || styleData.value.chinese_prompt == null) {
|
||||
message.error('请输入中文提示词')
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
await window.api.TranslateReturnNow(
|
||||
[styleData.value.chinese_prompt, 'zh', 'en', false],
|
||||
(value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
console.log(value.data)
|
||||
styleData.value.prompt = value.data[0].src
|
||||
}
|
||||
)
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
let ruleObj = (errorMessage) => {
|
||||
return [
|
||||
{
|
||||
required: true,
|
||||
validator(rule, value) {
|
||||
if (value == null || value == '') return new Error(errorMessage)
|
||||
return true
|
||||
},
|
||||
trigger: ['input', 'blur', 'change']
|
||||
}
|
||||
]
|
||||
}
|
||||
let rules = {
|
||||
label: ruleObj('必填人物名称'),
|
||||
prompt: ruleObj('必填英文提示词')
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成风格图片
|
||||
*/
|
||||
async function GenerateStyleImage() {
|
||||
if (isEmpty(styleData.value.prompt)) {
|
||||
message.error('请输入提示词')
|
||||
imageLoading.value = false
|
||||
return
|
||||
}
|
||||
// 判断lora是不是存在
|
||||
let lora = ''
|
||||
if (
|
||||
styleData.value.lora != null &&
|
||||
styleData.value.lora != '' &&
|
||||
styleData.value.lora != '无'
|
||||
) {
|
||||
lora = `<lora:${styleData.value.lora}:${styleData.value.lora_weight}>`
|
||||
}
|
||||
let d = {
|
||||
prompt: `1gril, ${styleData.value.prompt}, ${lora}`,
|
||||
width: 1024,
|
||||
height: 1024
|
||||
}
|
||||
imageLoading.value = true
|
||||
await window.sd.txt2img(JSON.stringify([d]), async (value) => {
|
||||
debugger
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
imageLoading.value = false
|
||||
return
|
||||
}
|
||||
if (value.data && value.data.length > 0) {
|
||||
let d = value.data[0]
|
||||
styleData.value.show_image = d.image_path.replaceAll('\\', '/')
|
||||
png_base64.value = 'data:image/png;base64,' + d.base64
|
||||
console.log(styleData.value.show_image)
|
||||
imageLoading.value = false
|
||||
}
|
||||
// 使用 Vue.nextTick 等待 Vue 更新视图
|
||||
imageLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
styleData,
|
||||
SaveStyleTag,
|
||||
loading,
|
||||
imageLoading,
|
||||
rules,
|
||||
formRef,
|
||||
TranslatePrompt,
|
||||
lora_options,
|
||||
png_base64,
|
||||
GenerateStyleImage
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -1,354 +1,468 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
<n-split direction="horizontal" :max="0.3" :min="0.18" :default-size="0.18">
|
||||
<template #1>
|
||||
<div id="tree_define_content" style="display: flex; overflow-y: auto;">
|
||||
<n-tree :node-props="nodeProps" style="width: 200px;" block-line :data="treeData" />
|
||||
</div>
|
||||
<div>
|
||||
<n-split direction="horizontal" :max="0.3" :min="0.18" :default-size="0.18">
|
||||
<template #1>
|
||||
<div id="tree_define_content" style="display: flex; overflow-y: auto">
|
||||
<n-tree :node-props="nodeProps" style="width: 200px" block-line :data="treeData" />
|
||||
</div>
|
||||
</template>
|
||||
<template #2>
|
||||
<div style="margin-left: 20px">
|
||||
<AddCharacterTag
|
||||
v-if="currentType.startsWith('character')"
|
||||
:currentCharacter="currentCharacter"
|
||||
:currentTags="currentTags"
|
||||
:initFunc="InitData"
|
||||
:lora_options="lora_options"
|
||||
/>
|
||||
<AddStyleTags
|
||||
v-else-if="currentType.startsWith('style')"
|
||||
:currentStyle="currentStyle"
|
||||
:initFunc="InitData"
|
||||
:lora_options="lora_options"
|
||||
/>
|
||||
<AddSceneTags
|
||||
v-else-if="currentType.startsWith('scene')"
|
||||
:currentScene="currentScene"
|
||||
:initFunc="InitData"
|
||||
/>
|
||||
<AddPrefixTags
|
||||
v-else-if="currentType.startsWith('prefix')"
|
||||
:currentPrefix="currentPrefix"
|
||||
:initFunc="InitData"
|
||||
/>
|
||||
<AddSuffixTags
|
||||
v-else-if="currentType.startsWith('suffix')"
|
||||
:currentSuffix="currentSuffix"
|
||||
:initFunc="InitData"
|
||||
/>
|
||||
<n-empty v-else description="是一个飞机">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<airplane />
|
||||
</n-icon>
|
||||
</template>
|
||||
<template #2>
|
||||
<div style="margin-left: 20px;">
|
||||
<AddCharacterTag v-if="currentType.startsWith('character')" :currentCharacter="currentCharacter"
|
||||
:currentTags="currentTags" :initFunc="InitData" />
|
||||
<AddStyleTags v-else-if="currentType.startsWith('style')" :currentStyle="currentStyle"
|
||||
:initFunc="InitData" />
|
||||
<AddSceneTags v-else-if="currentType.startsWith('scene')" :currentScene="currentScene"
|
||||
:initFunc="InitData" />
|
||||
<AddPrefixTags v-else-if="currentType.startsWith('prefix')" :currentPrefix="currentPrefix"
|
||||
:initFunc="InitData" />
|
||||
<AddSuffixTags v-else-if="currentType.startsWith('suffix')" :currentSuffix="currentSuffix"
|
||||
:initFunc="InitData" />
|
||||
</div>
|
||||
</template>
|
||||
</n-split>
|
||||
</div>
|
||||
</n-empty>
|
||||
</div>
|
||||
</template>
|
||||
</n-split>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, h, onMounted, defineComponent, toRaw } from "vue"
|
||||
import { NImage, useMessage, NButton, useDialog, NInput, NCard, NTabs, NTabPane, NTree, NSplit, NIcon } from "naive-ui";
|
||||
import { DEFINE_STRING } from "../../../../../define/define_string";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import AddCharacterTag from "./AddCharacterTag.vue";
|
||||
import AddStyleTags from "./AddStyleTags.vue";
|
||||
import AddSceneTags from "./AddSceneTags.vue";
|
||||
import AddPrefixTags from "./AddPrefixTags.vue";
|
||||
import AddSuffixTags from "./AddSuffixTags.vue";
|
||||
import { Trash } from "@vicons/ionicons5"
|
||||
import { ref, h, onMounted, defineComponent, toRaw } from 'vue'
|
||||
import {
|
||||
NImage,
|
||||
useMessage,
|
||||
NButton,
|
||||
useDialog,
|
||||
NInput,
|
||||
NCard,
|
||||
NTabs,
|
||||
NTabPane,
|
||||
NTree,
|
||||
NSplit,
|
||||
NIcon,
|
||||
NEmpty
|
||||
} from 'naive-ui'
|
||||
import { DEFINE_STRING } from '../../../../../define/define_string'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import AddCharacterTag from './AddCharacterTag.vue'
|
||||
import AddStyleTags from './AddStyleTags.vue'
|
||||
import AddSceneTags from './AddSceneTags.vue'
|
||||
import AddPrefixTags from './AddPrefixTags.vue'
|
||||
import AddSuffixTags from './AddSuffixTags.vue'
|
||||
import { Trash, Airplane } from '@vicons/ionicons5'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NImage, NButton, NInput, NCard, NTabs, NTabPane, NTree, NSplit, AddCharacterTag, AddStyleTags, AddSceneTags, AddPrefixTags, AddSuffixTags, NIcon, Trash
|
||||
},
|
||||
props: ["height"],
|
||||
setup(props) {
|
||||
let message = useMessage();
|
||||
let currentCharacter = ref({});
|
||||
let currentStyle = ref({});
|
||||
let currentScene = ref({});
|
||||
let currentPrefix = ref({});
|
||||
let currentSuffix = ref({});
|
||||
let currentTags = ref([]);
|
||||
let currentType = ref("character");
|
||||
let treeData = ref([{
|
||||
label: '人物',
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: "character",
|
||||
suffix: () => h(NButton,
|
||||
components: {
|
||||
NImage,
|
||||
NButton,
|
||||
NInput,
|
||||
NCard,
|
||||
NTabs,
|
||||
NTabPane,
|
||||
NTree,
|
||||
NSplit,
|
||||
AddCharacterTag,
|
||||
AddStyleTags,
|
||||
AddSceneTags,
|
||||
AddPrefixTags,
|
||||
AddSuffixTags,
|
||||
NIcon,
|
||||
Trash,
|
||||
NEmpty,
|
||||
Airplane
|
||||
},
|
||||
props: ['height'],
|
||||
setup(props) {
|
||||
let message = useMessage()
|
||||
let currentCharacter = ref({})
|
||||
let currentStyle = ref({})
|
||||
let currentScene = ref({})
|
||||
let currentPrefix = ref({})
|
||||
let currentSuffix = ref({})
|
||||
let currentTags = ref([])
|
||||
let currentType = ref('default')
|
||||
|
||||
let lora_options = ref([])
|
||||
|
||||
let treeData = ref([
|
||||
{
|
||||
label: '人物',
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: 'character',
|
||||
suffix: () =>
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
color: '#e18a3b',
|
||||
onClick: (e) => {
|
||||
AddCharacterTags(e)
|
||||
}
|
||||
},
|
||||
{ default: () => '新加' }
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '场景',
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: 'scene',
|
||||
suffix: () =>
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
color: '#e18a3b',
|
||||
onClick: (e) => {
|
||||
AddSceneTags(e)
|
||||
}
|
||||
},
|
||||
{ default: () => '新加' }
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '风格预设',
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: 'style',
|
||||
suffix: () =>
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
color: '#e18a3b',
|
||||
onClick: (e) => {
|
||||
AddStyleTags(e)
|
||||
}
|
||||
},
|
||||
{ default: () => '新加' }
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '前缀',
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: 'prefix',
|
||||
suffix: () =>
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
color: '#e18a3b',
|
||||
onClick: (e) => {
|
||||
AddPrefixTags(e)
|
||||
}
|
||||
},
|
||||
{ default: () => '新加' }
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '后缀',
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: 'suffix',
|
||||
suffix: () =>
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
text: true,
|
||||
color: '#e18a3b',
|
||||
onClick: (e) => {
|
||||
AddSuffixTags(e)
|
||||
}
|
||||
},
|
||||
{ default: () => '新加' }
|
||||
)
|
||||
}
|
||||
])
|
||||
|
||||
/**
|
||||
* 初始化标签数据
|
||||
*/
|
||||
async function InitData() {
|
||||
// 获取动态配置里面是不是又标签数(有加载,没有设置默认值)
|
||||
await window.mj.GetTagDataByTypeAndProperty(['dynamic', null], (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
// 判断是不是包含指定的属性
|
||||
if (value.data.hasOwnProperty('character_tags')) {
|
||||
treeData.value[0].children = value.data.character_tags
|
||||
}
|
||||
if (value.data.hasOwnProperty('scene_tags')) {
|
||||
treeData.value[1].children = value.data.scene_tags
|
||||
}
|
||||
if (value.data.hasOwnProperty('style_tags')) {
|
||||
treeData.value[2].children = value.data.style_tags
|
||||
}
|
||||
if (value.data.hasOwnProperty('prefix_tags')) {
|
||||
treeData.value[3].children = value.data.prefix_tags
|
||||
}
|
||||
if (value.data.hasOwnProperty('suffix_tags')) {
|
||||
treeData.value[4].children = value.data.suffix_tags
|
||||
}
|
||||
|
||||
for (let i = 0; i < treeData.value.length; i++) {
|
||||
treeData.value[i].children.map((item) => {
|
||||
item.suffix = () =>
|
||||
h(
|
||||
NButton,
|
||||
{
|
||||
text: true, color: "#e18a3b",
|
||||
onClick: (e) => { AddCharacterTags(e) }
|
||||
text: true,
|
||||
type: 'error',
|
||||
size: 'medium',
|
||||
onClick: (e) => {
|
||||
DeleteTags(e, item)
|
||||
}
|
||||
},
|
||||
{ default: () => "新加" })
|
||||
},
|
||||
{
|
||||
label: '场景',
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: "scene",
|
||||
suffix: () => h(NButton,
|
||||
{
|
||||
text: true, color: "#e18a3b",
|
||||
onClick: (e) => { AddSceneTags(e) }
|
||||
},
|
||||
{ default: () => "新加" })
|
||||
},
|
||||
{
|
||||
label: '风格迁移预设',
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: "style",
|
||||
suffix: () => h(NButton,
|
||||
{
|
||||
text: true, color: "#e18a3b",
|
||||
onClick: (e) => { AddStyleTags(e) }
|
||||
},
|
||||
{ default: () => "新加" })
|
||||
},
|
||||
{
|
||||
label: '前缀',
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: "prefix",
|
||||
suffix: () => h(NButton,
|
||||
{
|
||||
text: true, color: "#e18a3b",
|
||||
onClick: (e) => { AddPrefixTags(e) }
|
||||
},
|
||||
{ default: () => "新加" })
|
||||
},
|
||||
{
|
||||
label: '后缀',
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: "suffix",
|
||||
suffix: () => h(NButton,
|
||||
{
|
||||
text: true, color: "#e18a3b",
|
||||
onClick: (e) => { AddSuffixTags(e) }
|
||||
},
|
||||
{ default: () => "新加" })
|
||||
{ default: () => h(NIcon, null, { default: () => h(Trash) }) }
|
||||
)
|
||||
})
|
||||
}
|
||||
]);
|
||||
|
||||
/**
|
||||
* 初始化标签数据
|
||||
*/
|
||||
async function InitData() {
|
||||
// 获取动态配置里面是不是又标签数(有加载,没有设置默认值)
|
||||
await window.mj.GetTagDataByTypeAndProperty(["dynamic", null], (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
// 判断是不是包含指定的属性
|
||||
if (value.data.hasOwnProperty("character_tags")) {
|
||||
treeData.value[0].children = value.data.character_tags;
|
||||
}
|
||||
if (value.data.hasOwnProperty("scene_tags")) {
|
||||
treeData.value[1].children = value.data.scene_tags;
|
||||
}
|
||||
if (value.data.hasOwnProperty("style_tags")) {
|
||||
treeData.value[2].children = value.data.style_tags;
|
||||
}
|
||||
if (value.data.hasOwnProperty("prefix_tags")) {
|
||||
treeData.value[3].children = value.data.prefix_tags;
|
||||
}
|
||||
if (value.data.hasOwnProperty("suffix_tags")) {
|
||||
treeData.value[4].children = value.data.suffix_tags;
|
||||
}
|
||||
|
||||
for (let i = 0; i < treeData.value.length; i++) {
|
||||
treeData.value[i].children.map(item => {
|
||||
item.suffix = () => h(NButton,
|
||||
{
|
||||
text: true, type: "error", size: "medium",
|
||||
onClick: (e) => { DeleteTags(e, item) }
|
||||
},
|
||||
{ default: () => h(NIcon, null, { default: () => h(Trash) }) });
|
||||
});
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
SetAutoHeight();
|
||||
await InitData();
|
||||
})
|
||||
|
||||
|
||||
// 设置标签集的自动高度,传一个外面的高度进来
|
||||
function SetAutoHeight() {
|
||||
debugger
|
||||
let div = document.getElementById("tree_define_content");
|
||||
div.style.height = props.height - 180 + "px";
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定的数据
|
||||
*/
|
||||
async function DeleteTags(e, value) {
|
||||
if (e) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
let type = value.type.replace("main", "tags");
|
||||
await window.mj.DeleteTagPropertyData([value.key, type], async (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
message.success(value.message);
|
||||
await InitData();
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 新加人物标签
|
||||
*/
|
||||
async function AddCharacterTags(e) {
|
||||
if (e) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
// 初始化值,然后赋值给当前添加人物的组件
|
||||
currentCharacter.value = {
|
||||
label: null,
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: "character_main",
|
||||
prompt: null,
|
||||
image_url: null,
|
||||
cref_cw: 50,
|
||||
lora: null,
|
||||
}
|
||||
currentTags.value = [];
|
||||
currentType.value = "character_main";
|
||||
}
|
||||
|
||||
/**
|
||||
* 新加场景标签
|
||||
*/
|
||||
function AddSceneTags(e) {
|
||||
if (e) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
currentScene.value = {
|
||||
label: null,
|
||||
key: uuidv4(),
|
||||
type: "scene_main",
|
||||
prompt: null,
|
||||
}
|
||||
currentType.value = "scene_main";
|
||||
}
|
||||
|
||||
/**
|
||||
* 新加 风格迁移预设
|
||||
* @param {*} e
|
||||
*/
|
||||
function AddStyleTags(e) {
|
||||
if (e) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
currentStyle.value = {
|
||||
label: null,
|
||||
key: uuidv4(),
|
||||
type: "style_main",
|
||||
prompt: null,
|
||||
image_url: null,
|
||||
sref_cw: 50,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加前缀
|
||||
*/
|
||||
function AddPrefixTags(e) {
|
||||
if (e) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
currentPrefix.value = {
|
||||
label: null,
|
||||
key: uuidv4(),
|
||||
type: "prefix_main",
|
||||
prompt: null,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加后缀
|
||||
* @param {*} e
|
||||
*/
|
||||
function AddSuffixTags(e) {
|
||||
if (e) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
currentSuffix.value = {
|
||||
label: null,
|
||||
key: uuidv4(),
|
||||
type: "suffix_main",
|
||||
prompt: null,
|
||||
}
|
||||
}
|
||||
|
||||
function nodeProps({ option }) {
|
||||
return {
|
||||
onClick() {
|
||||
debugger;
|
||||
// 执行切换组件和数据
|
||||
if (option.type == "style") {
|
||||
currentType.value = "style";
|
||||
AddStyleTags(null);
|
||||
return;
|
||||
} else if (option.type == "scene") {
|
||||
AddSceneTags(null);
|
||||
currentType.value = "scene";
|
||||
// message.error("主节点不允许操作");
|
||||
return;
|
||||
} else if (option.type == "character") {
|
||||
AddCharacterTags(null);
|
||||
currentType.value = "character";
|
||||
return;
|
||||
} else if (option.type == "prefix") {
|
||||
AddPrefixTags(null);
|
||||
currentType.value = "prefix";
|
||||
return;
|
||||
} else if (option.type == "suffix") {
|
||||
AddSuffixTags(null);
|
||||
currentType.value = "suffix";
|
||||
return;
|
||||
}
|
||||
else if (option.type == "min") {
|
||||
message.error("别名节点不允许操作");
|
||||
} else {
|
||||
debugger
|
||||
console.log(option);
|
||||
currentType.value = option.type;
|
||||
// 修改当前属性
|
||||
if (currentType.value.startsWith("character")) {
|
||||
// 修改tags的值
|
||||
currentCharacter.value = option;
|
||||
currentTags.value = option.children.map((item) => {
|
||||
return item.label;
|
||||
})
|
||||
} else if (currentType.value.startsWith("scene")) {
|
||||
currentScene.value = option;
|
||||
}
|
||||
else if (currentType.value.startsWith("style")) {
|
||||
currentStyle.value = option;
|
||||
} else if (currentType.value.startsWith("prefix")) {
|
||||
currentPrefix.value = option;
|
||||
} else if (currentType.value.startsWith("suffix")) {
|
||||
currentSuffix.value = option;
|
||||
}
|
||||
else {
|
||||
message.error("未知的类型");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
treeData,
|
||||
AddCharacterTags,
|
||||
AddSceneTags,
|
||||
AddStyleTags,
|
||||
nodeProps,
|
||||
currentCharacter,
|
||||
currentTags,
|
||||
InitData,
|
||||
currentType,
|
||||
currentStyle,
|
||||
currentScene,
|
||||
currentPrefix,
|
||||
currentSuffix
|
||||
})
|
||||
// 加载lora数据
|
||||
// 获取当前mj配置信息
|
||||
await window.api.GetDefineConfigJsonByProperty(
|
||||
JSON.stringify(['sd_setting', 'lora', false, []]),
|
||||
(value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
// 判断是不是有数据
|
||||
if (value.data) {
|
||||
for (let i = 0; i < value.data.length; i++) {
|
||||
const element = value.data[i]
|
||||
lora_options.value.push({
|
||||
label: element.name,
|
||||
value: element.name
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
SetAutoHeight()
|
||||
await InitData()
|
||||
})
|
||||
|
||||
// 设置标签集的自动高度,传一个外面的高度进来
|
||||
function SetAutoHeight() {
|
||||
debugger
|
||||
let div = document.getElementById('tree_define_content')
|
||||
div.style.height = props.height - 180 + 'px'
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定的数据
|
||||
*/
|
||||
async function DeleteTags(e, value) {
|
||||
if (e) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
let type = value.type.replace('main', 'tags')
|
||||
await window.mj.DeleteTagPropertyData([value.key, type], async (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
message.success(value.message)
|
||||
await InitData()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 新加人物标签
|
||||
*/
|
||||
async function AddCharacterTags(e) {
|
||||
if (e) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
// 初始化值,然后赋值给当前添加人物的组件
|
||||
currentCharacter.value = {
|
||||
label: null,
|
||||
key: uuidv4(),
|
||||
children: [],
|
||||
type: 'character_main',
|
||||
chinese_prompt: null,
|
||||
prompt: null,
|
||||
image_url: null,
|
||||
show_image: window.config.space_image,
|
||||
cref_cw: 50,
|
||||
lora: '无',
|
||||
lora_weight: 1
|
||||
}
|
||||
currentTags.value = []
|
||||
currentType.value = 'character_main'
|
||||
}
|
||||
|
||||
/**
|
||||
* 新加场景标签
|
||||
*/
|
||||
function AddSceneTags(e) {
|
||||
if (e) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
currentScene.value = {
|
||||
label: null,
|
||||
key: uuidv4(),
|
||||
type: 'scene_main',
|
||||
prompt: null
|
||||
}
|
||||
currentType.value = 'scene_main'
|
||||
}
|
||||
|
||||
/**
|
||||
* 新加 风格迁移预设
|
||||
* @param {*} e
|
||||
*/
|
||||
function AddStyleTags(e) {
|
||||
if (e) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
currentStyle.value = {
|
||||
label: null,
|
||||
key: uuidv4(),
|
||||
type: 'style_main',
|
||||
show_image: window.config.space_image,
|
||||
prompt: null,
|
||||
image_url: null,
|
||||
sref_sw: 50,
|
||||
lora: '无',
|
||||
lora_weight: 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加前缀
|
||||
*/
|
||||
function AddPrefixTags(e) {
|
||||
if (e) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
currentPrefix.value = {
|
||||
label: null,
|
||||
key: uuidv4(),
|
||||
type: 'prefix_main',
|
||||
prompt: null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加后缀
|
||||
* @param {*} e
|
||||
*/
|
||||
function AddSuffixTags(e) {
|
||||
if (e) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
currentSuffix.value = {
|
||||
label: null,
|
||||
key: uuidv4(),
|
||||
type: 'suffix_main',
|
||||
prompt: null
|
||||
}
|
||||
}
|
||||
|
||||
function nodeProps({ option }) {
|
||||
return {
|
||||
onClick() {
|
||||
debugger
|
||||
// 执行切换组件和数据
|
||||
if (option.type == 'style') {
|
||||
currentType.value = 'style'
|
||||
AddStyleTags(null)
|
||||
return
|
||||
} else if (option.type == 'scene') {
|
||||
AddSceneTags(null)
|
||||
currentType.value = 'scene'
|
||||
// message.error("主节点不允许操作");
|
||||
return
|
||||
} else if (option.type == 'character') {
|
||||
AddCharacterTags(null)
|
||||
currentType.value = 'character'
|
||||
return
|
||||
} else if (option.type == 'prefix') {
|
||||
AddPrefixTags(null)
|
||||
currentType.value = 'prefix'
|
||||
return
|
||||
} else if (option.type == 'suffix') {
|
||||
AddSuffixTags(null)
|
||||
currentType.value = 'suffix'
|
||||
return
|
||||
} else if (option.type == 'min') {
|
||||
message.error('别名节点不允许操作')
|
||||
} else {
|
||||
debugger
|
||||
console.log(option)
|
||||
currentType.value = option.type
|
||||
// 修改当前属性
|
||||
if (currentType.value.startsWith('character')) {
|
||||
// 修改tags的值
|
||||
currentCharacter.value = option
|
||||
currentTags.value = option.children.map((item) => {
|
||||
return item.label
|
||||
})
|
||||
} else if (currentType.value.startsWith('scene')) {
|
||||
currentScene.value = option
|
||||
} else if (currentType.value.startsWith('style')) {
|
||||
currentStyle.value = option
|
||||
} else if (currentType.value.startsWith('prefix')) {
|
||||
currentPrefix.value = option
|
||||
} else if (currentType.value.startsWith('suffix')) {
|
||||
currentSuffix.value = option
|
||||
} else {
|
||||
message.error('未知的类型')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
treeData,
|
||||
AddCharacterTags,
|
||||
AddSceneTags,
|
||||
AddStyleTags,
|
||||
nodeProps,
|
||||
currentCharacter,
|
||||
currentTags,
|
||||
InitData,
|
||||
currentType,
|
||||
currentStyle,
|
||||
currentScene,
|
||||
currentPrefix,
|
||||
currentSuffix,
|
||||
lora_options
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-if="type == 'title'" style="display: flex">
|
||||
<span style="margin-right: 5px">参数</span>
|
||||
<span style="margin-right: 5px">人物/场景</span>
|
||||
<n-select
|
||||
style="width: 75px"
|
||||
size="tiny"
|
||||
@@ -56,6 +56,7 @@
|
||||
filterable
|
||||
:options="character_tags"
|
||||
placeholder="选择人物"
|
||||
@update:value="UpdateCharacterSelect"
|
||||
/>
|
||||
</div>
|
||||
<div style="margin-top: 3px">
|
||||
@@ -69,6 +70,7 @@
|
||||
filterable
|
||||
:options="scene_tags"
|
||||
placeholder="选择场景"
|
||||
@update:value="UpdateSceneSelect"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -236,8 +238,12 @@ export default defineComponent({
|
||||
character_tags.value[index].checked = true
|
||||
// 将当前选中的数据生成到select_character_tags中
|
||||
select_character_tags.value.push(character_tags.value[index].key)
|
||||
} else {
|
||||
// 不存在 移除
|
||||
row.value.character_tags.splice(i, 1)
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; row.value.scene_tags && i < row.value.scene_tags.length; i++) {
|
||||
const element = row.value.scene_tags[i]
|
||||
let index = scene_tags.value.findIndex((tag) => tag.key == element.key)
|
||||
@@ -245,6 +251,9 @@ export default defineComponent({
|
||||
scene_tags.value[index].checked = true
|
||||
// 将当前选中的数据生成到select_scene_tags中
|
||||
select_scene_tags.value.push(scene_tags.value[index].key)
|
||||
} else {
|
||||
// 不存在 移除
|
||||
row.value.scene_tags.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,6 +274,36 @@ export default defineComponent({
|
||||
props.func.refreshTagData()
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新人物选择,修改对应的tag
|
||||
*/
|
||||
function UpdateCharacterSelect(value, option) {
|
||||
console.log('人物更新下拉框', value, option)
|
||||
// 先将之前row中的数据全部移除
|
||||
row.value.character_tags = []
|
||||
// 将当前选中的option修改checked为true,并将数据添加到row中
|
||||
for (let i = 0; i < option.length; i++) {
|
||||
const element = option[i]
|
||||
element.checked = true
|
||||
row.value.character_tags.push(element)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新场景时,显示的数据
|
||||
*/
|
||||
function UpdateSceneSelect(value, option) {
|
||||
console.log('场景更新下拉框', value, option)
|
||||
// 先将之前row中的数据全部移除
|
||||
row.value.scene_tags = []
|
||||
// 将当前选中的option修改checked为true,并将数据添加到row中
|
||||
for (let i = 0; i < option.length; i++) {
|
||||
const element = option[i]
|
||||
element.checked = true
|
||||
row.value.scene_tags.push(element)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
characterData,
|
||||
row,
|
||||
@@ -280,7 +319,9 @@ export default defineComponent({
|
||||
InitCharacterAndSceneData,
|
||||
UpdateImageGenerateCategory,
|
||||
title_character_select_model,
|
||||
RefreshTagData
|
||||
RefreshTagData,
|
||||
UpdateCharacterSelect,
|
||||
UpdateSceneSelect
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-button color="#7c461e" style="margin-left: 5px" size="tiny" @click="AddPrefix"
|
||||
>添加前缀</n-button
|
||||
>通用前缀</n-button
|
||||
>
|
||||
</template>
|
||||
<span>添加前缀,只能添加英文,并且通用前缀不为空,推理会自动添加前缀</span>
|
||||
<span>添加通用前缀,只能添加英文,并且通用前缀不为空,推理会自动添加前缀</span>
|
||||
</n-popover>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-button color="#e18a3b" style="margin-left: 5px" size="tiny" @click="AddSuffix"
|
||||
>添加后缀</n-button
|
||||
>通用后缀</n-button
|
||||
>
|
||||
</template>
|
||||
<span>添加后缀,只能添加英文,并且通用后缀不为空,推理会自动添加后缀</span>
|
||||
<span>添加通用后缀,只能添加英文,并且通用后缀不为空,推理会自动添加后缀</span>
|
||||
</n-popover>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
@@ -77,10 +77,6 @@
|
||||
<script>
|
||||
import { ref, h, onMounted, defineComponent, toRaw, watch } from 'vue'
|
||||
import { NButton, NDropdown, NInput, NPopover, useMessage } from 'naive-ui'
|
||||
import { DEFINE_STRING } from '../../../../../define/define_string'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NButton,
|
||||
@@ -192,7 +188,6 @@ export default defineComponent({
|
||||
*/
|
||||
async function SinglePrompt() {
|
||||
await props.func.singlePrompt(row.value)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,37 +1,23 @@
|
||||
<template>
|
||||
<div v-if="type == 'title'">
|
||||
<span style="margin-right: 5px">提示词命令</span>
|
||||
<n-button size="tiny" @click="MergePrompt" color="#7c461e">合并命令</n-button>
|
||||
<n-button
|
||||
color="#e18a3b"
|
||||
size="tiny"
|
||||
style="margin-left: 5px"
|
||||
@click="MJBadPromptCheck"
|
||||
<n-dropdown trigger="hover" :options="MergePromptOptions" @select="MergePromptSelect">
|
||||
<n-button size="tiny" @click="MergePrompt" color="#7c461e">合并命令</n-button>
|
||||
</n-dropdown>
|
||||
<n-button color="#e18a3b" size="tiny" style="margin-left: 5px" @click="MJBadPromptCheck"
|
||||
>敏感词检查</n-button
|
||||
>
|
||||
</div>
|
||||
<div v-else-if="type == 'data'">
|
||||
<n-button
|
||||
size="tiny"
|
||||
color="#dd7694"
|
||||
style="margin-right: 5px"
|
||||
@click="SingleGenerateImage"
|
||||
<n-button size="tiny" color="#dd7694" style="margin-right: 5px" @click="SingleGenerateImage"
|
||||
>单句生图</n-button
|
||||
>
|
||||
<n-button
|
||||
size="tiny"
|
||||
color="#a76283"
|
||||
style="margin-right: 5px"
|
||||
@click="NextGenerateImage"
|
||||
<n-button size="tiny" color="#a76283" style="margin-right: 5px" @click="NextGenerateImage"
|
||||
>下生图</n-button
|
||||
>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-button
|
||||
color="#a46244"
|
||||
style="margin-right: 5px"
|
||||
size="tiny"
|
||||
@click="ImportMJImageUrl"
|
||||
<n-button color="#a46244" style="margin-right: 5px" size="tiny" @click="ImportMJImageUrl"
|
||||
>导入图片</n-button
|
||||
>
|
||||
</template>
|
||||
@@ -40,7 +26,6 @@
|
||||
|
||||
<n-input
|
||||
:status="input_status"
|
||||
readonly
|
||||
size="tiny"
|
||||
placeholder="请生成出图命令或是提示词"
|
||||
type="textarea"
|
||||
@@ -51,25 +36,26 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, h, onMounted, defineComponent, toRaw, watch } from "vue";
|
||||
import { NButton, NInput, NPopover, useMessage, useDialog } from "naive-ui";
|
||||
import { DEFINE_STRING } from "../../../../../define/define_string";
|
||||
import InputDialogContent from "./InputDialogContent.vue";
|
||||
import { ref, h, onMounted, defineComponent, toRaw, watch } from 'vue'
|
||||
import { NButton, NInput, NPopover, useMessage, useDialog, NDropdown } from 'naive-ui'
|
||||
import { DEFINE_STRING } from '../../../../../define/define_string'
|
||||
import InputDialogContent from './InputDialogContent.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NButton,
|
||||
NInput,
|
||||
NPopover,
|
||||
NDropdown
|
||||
},
|
||||
props: ["type", "row", "index", "func"],
|
||||
props: ['type', 'row', 'index', 'func'],
|
||||
setup(props) {
|
||||
let message = useMessage();
|
||||
let dialog = useDialog();
|
||||
let type = ref(props.type);
|
||||
let row = ref(props.row);
|
||||
let input_status = ref("default");
|
||||
let image_url_ref = ref(null);
|
||||
let message = useMessage()
|
||||
let dialog = useDialog()
|
||||
let type = ref(props.type)
|
||||
let row = ref(props.row)
|
||||
let input_status = ref('default')
|
||||
let image_url_ref = ref(null)
|
||||
|
||||
// let input_image_
|
||||
|
||||
@@ -79,63 +65,62 @@ export default defineComponent({
|
||||
watch(
|
||||
() => props.row,
|
||||
(newVal) => {
|
||||
row.value = newVal;
|
||||
row.value = newVal
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.row.mj_message,
|
||||
(newVal) => {
|
||||
if (newVal && newVal["hasBadPrompt"]) {
|
||||
input_status.value = "error";
|
||||
if (newVal && newVal['hasBadPrompt']) {
|
||||
input_status.value = 'error'
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
if (row.value["mj_message"]?.hasBadPrompt) {
|
||||
input_status.value = "error";
|
||||
if (row.value['mj_message']?.hasBadPrompt) {
|
||||
input_status.value = 'error'
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
/**
|
||||
* SD单句生图
|
||||
* @param {*} row 要生图的行数据
|
||||
*/
|
||||
async function SingleGenerateImage() {
|
||||
debugger;
|
||||
let ca = window.config.image_generate_category;
|
||||
let ca = window.config.image_generate_category ? window.config.image_generate_category : 'sd'
|
||||
// 判断当前的生图模式
|
||||
if (ca == "sd") {
|
||||
if (ca == 'sd') {
|
||||
// 生成SD生图
|
||||
await window.api.OriginalSDImageGenerate(
|
||||
[JSON.stringify([toRaw(row.value)]), true, false],
|
||||
(value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
message.success("添加SD生图任务成功");
|
||||
message.success('添加SD生图任务成功')
|
||||
}
|
||||
);
|
||||
} else if (ca == "mj") {
|
||||
)
|
||||
} else if (ca == 'mj') {
|
||||
// MJ生图
|
||||
await window.mj.OriginalMJImageGenerate(
|
||||
[JSON.stringify([toRaw(row.value)]), true, false],
|
||||
(value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
message.success("添加MJ生图任务成功");
|
||||
message.success('添加MJ生图任务成功')
|
||||
}
|
||||
);
|
||||
} else if (ca == "d3") {
|
||||
)
|
||||
} else if (ca == 'd3') {
|
||||
// D3 生图
|
||||
} else {
|
||||
message.error("生图的类别错误");
|
||||
message.error('生图的类别错误')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,21 +128,22 @@ export default defineComponent({
|
||||
* 下生图
|
||||
*/
|
||||
async function NextGenerateImage() {
|
||||
props.func.nextGenerateImage(row.value, window.config.image_generate_category);
|
||||
let ca = window.config.image_generate_category ? window.config.image_generate_category : 'sd'
|
||||
props.func.nextGenerateImage(row.value, ca)
|
||||
}
|
||||
|
||||
/**
|
||||
* MJ敏感词检测
|
||||
*/
|
||||
async function MJBadPromptCheck() {
|
||||
props.func.mJBadPromptCheck();
|
||||
props.func.mJBadPromptCheck()
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并提示词
|
||||
*/
|
||||
async function MergePrompt() {
|
||||
props.func.mergePrompt();
|
||||
props.func.mergePrompt(null)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,43 +152,51 @@ export default defineComponent({
|
||||
async function ImportMJImageUrl() {
|
||||
// 判断当前数据是不是存在
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = 400;
|
||||
let dialogHeight = 150;
|
||||
let dialogWidth = 400
|
||||
let dialogHeight = 150
|
||||
dialog.create({
|
||||
title: "添加图片链接",
|
||||
title: '添加图片链接',
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
content: () =>
|
||||
h(InputDialogContent, {
|
||||
ref: image_url_ref,
|
||||
initData: null,
|
||||
placeholder: "请输入图片链接",
|
||||
placeholder: '请输入图片链接'
|
||||
}),
|
||||
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px`,
|
||||
maskClosable: false,
|
||||
onClose: async () => {
|
||||
debugger;
|
||||
let row_image_url = image_url_ref.value.data;
|
||||
debugger
|
||||
let row_image_url = image_url_ref.value.data
|
||||
|
||||
// 下载指定的图片地址并且分割
|
||||
await window.mj.DownloadImageUrlAndSplit(
|
||||
JSON.stringify([toRaw(row.value), row_image_url]),
|
||||
(value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
// 更新当前的数据
|
||||
row.value.outImagePath = value.data.outImagePath;
|
||||
row.value.subImagePath = value.data.subImagePath;
|
||||
row.value.mj_message = value.data.mj_message ? value.data.mj_message : {};
|
||||
row.value.mj_message.image_click = value.data.image_click;
|
||||
row.value.mj_message.image_path = value.data.image_path;
|
||||
row.value.mj_message.progress = 100;
|
||||
row.value.outImagePath = value.data.outImagePath
|
||||
row.value.subImagePath = value.data.subImagePath
|
||||
row.value.mj_message = value.data.mj_message ? value.data.mj_message : {}
|
||||
row.value.mj_message.image_click = value.data.image_click
|
||||
row.value.mj_message.image_path = value.data.image_path
|
||||
row.value.mj_message.progress = 100
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击合并下拉框实现功能的方式
|
||||
* @param key
|
||||
*/
|
||||
async function MergePromptSelect(key) {
|
||||
props.func.mergePrompt(key)
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -215,7 +209,12 @@ export default defineComponent({
|
||||
MergePrompt,
|
||||
ImportMJImageUrl,
|
||||
image_url_ref,
|
||||
};
|
||||
},
|
||||
});
|
||||
MergePromptSelect,
|
||||
MergePromptOptions: [
|
||||
{ label: 'SD模式合并', key: 'sd_merge' },
|
||||
{ label: 'MJ模式合并', key: 'mj_merge' }
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -32,8 +32,7 @@
|
||||
v-if="outImagePath"
|
||||
:src="outImagePath"
|
||||
fit="cover"
|
||||
width="120px"
|
||||
height="120px"
|
||||
style="width: 120px; height: 120px"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -1,11 +1,71 @@
|
||||
<template>
|
||||
<div style="margin-top: 30px">
|
||||
<div style="display: flex; align-items: center">
|
||||
<n-button color="#b6a014" size="small" @click="formateWrite">一键格式化</n-button>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-button quaternary circle size="tiny" color="#b6a014" @click="AddSplitChar">
|
||||
<template #icon>
|
||||
<n-icon size="25"> <AddCircleOutline /> </n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</template>
|
||||
<span>添加分割标识符</span>
|
||||
</n-popover>
|
||||
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-input-number
|
||||
style="margin-left: 10px; width: 130px"
|
||||
size="small"
|
||||
placeholder="输入合并的行数"
|
||||
:max="10000"
|
||||
:min="1"
|
||||
@update:value="mergeCountChange"
|
||||
:show-button="false"
|
||||
v-model:value="write_setting.merge_count"
|
||||
></n-input-number>
|
||||
</template>
|
||||
<span>设置将多少行进行合并</span>
|
||||
</n-popover>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-input
|
||||
style="margin-left: 10px; width: 80px"
|
||||
size="small"
|
||||
placeholder="输入中间拼接的字符"
|
||||
@update:value="mergeCountChange"
|
||||
:show-button="false"
|
||||
v-model:value="write_setting.merge_char"
|
||||
></n-input>
|
||||
</template>
|
||||
<span>设置中间拼接的字符</span>
|
||||
</n-popover>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-input
|
||||
style="margin-left: 10px; width: 80px"
|
||||
size="small"
|
||||
placeholder="输入结尾拼接的字符"
|
||||
@update:value="mergeCountChange"
|
||||
:show-button="false"
|
||||
v-model:value="write_setting.end_char"
|
||||
></n-input>
|
||||
</template>
|
||||
<span>设置结尾拼接的字符</span>
|
||||
</n-popover>
|
||||
|
||||
<n-button color="#80a492" size="small" style="margin-left: 10px" @click="mergeWord"
|
||||
>合并</n-button
|
||||
>
|
||||
</div>
|
||||
<n-input
|
||||
style="margin-top: 5px"
|
||||
v-model:value="word"
|
||||
:autosize="{ minRows: 30, maxRows: 30 }"
|
||||
type="textarea"
|
||||
placeholder="输入分镜文案"
|
||||
@input="ChangeWordInput"
|
||||
@update:value="ChangeWordInput"
|
||||
/>
|
||||
<div style="margin-top: 5px; display: flex">
|
||||
<div style="flex: 1">共 {{ rowCount }} 行分镜(当前数量不是最后数量,最后会删除空行)</div>
|
||||
@@ -15,26 +75,49 @@
|
||||
|
||||
<script>
|
||||
import { ref, h, onMounted, defineComponent, toRaw } from 'vue'
|
||||
import { NImage, useMessage, NButton, useDialog, NInput } from 'naive-ui'
|
||||
import {
|
||||
NImage,
|
||||
useMessage,
|
||||
NButton,
|
||||
useDialog,
|
||||
NInput,
|
||||
NIcon,
|
||||
NPopover,
|
||||
NInputNumber
|
||||
} from 'naive-ui'
|
||||
import { DEFINE_STRING } from '../../../../../define/define_string'
|
||||
import { AddCircleOutline } from '@vicons/ionicons5'
|
||||
import InputDialogContent from './InputDialogContent.vue'
|
||||
import { max } from 'lodash'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NImage,
|
||||
NButton,
|
||||
NInput
|
||||
NInput,
|
||||
NInputNumber,
|
||||
NIcon,
|
||||
AddCircleOutline,
|
||||
NPopover
|
||||
},
|
||||
props: ['initData'],
|
||||
setup(props) {
|
||||
let message = useMessage()
|
||||
let dialog = useDialog()
|
||||
let rowCount = ref(0)
|
||||
let data = ref(props.initData)
|
||||
let word = ref(null)
|
||||
let word_arr = ref([])
|
||||
let split_ref = ref(null)
|
||||
|
||||
let write_setting = ref({
|
||||
split_char: '。,“”‘’!?【】《》()…—:;.,\'\'""!?[]<>()...-:;',
|
||||
merge_count: 3,
|
||||
merge_char: ',',
|
||||
end_char: '。'
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
debugger
|
||||
console.log(data)
|
||||
// 拼接word
|
||||
let tmp_arr = []
|
||||
for (let i = 0; i < data.value.length; i++) {
|
||||
@@ -43,6 +126,20 @@ export default defineComponent({
|
||||
}
|
||||
word.value = tmp_arr.join('\n')
|
||||
ChangeWordInput()
|
||||
|
||||
// 加载初始配置数据
|
||||
await window.api.GetDefineConfigJsonByProperty(
|
||||
JSON.stringify(['clip_setting', 'write_setting', false, null]),
|
||||
(value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
if (value.data) {
|
||||
write_setting.value = value.data
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -58,12 +155,137 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加分割符号
|
||||
*/
|
||||
async function AddSplitChar() {
|
||||
// 判断当前数据是不是存在
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = 400
|
||||
let dialogHeight = 150
|
||||
dialog.create({
|
||||
title: '添加分割符',
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
content: () =>
|
||||
h(InputDialogContent, {
|
||||
ref: split_ref,
|
||||
initData: write_setting.value.split_char,
|
||||
placeholder: '请输入分割符'
|
||||
}),
|
||||
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px`,
|
||||
maskClosable: false,
|
||||
onClose: async () => {
|
||||
debugger
|
||||
write_setting.value.split_char = split_ref.value.data
|
||||
// 保存数据
|
||||
await window.api.SaveDefineConfigJsonByProperty(
|
||||
JSON.stringify(['clip_setting', 'write_setting', toRaw(write_setting.value), false]),
|
||||
(value) => {
|
||||
debugger
|
||||
console.log(value)
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
message.success(value.message)
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新input-number事件
|
||||
*/
|
||||
let timer = null
|
||||
async function mergeCountChange(value) {
|
||||
// 添加一个防抖函数,防止修改次数太多导致卡顿
|
||||
clearTimeout(timer)
|
||||
timer = setTimeout(async () => {
|
||||
// 执行你的逻辑代码
|
||||
//
|
||||
await window.api.SaveDefineConfigJsonByProperty(
|
||||
JSON.stringify(['clip_setting', 'write_setting', toRaw(write_setting.value), false]),
|
||||
(value) => {
|
||||
debugger
|
||||
console.log(value)
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
message.success(value.message)
|
||||
}
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键格式化
|
||||
*/
|
||||
async function formateWrite() {
|
||||
debugger
|
||||
let split_arr = Array.from(write_setting.value.split_char)
|
||||
split_arr.forEach((item) => {
|
||||
let specialCharacters = [
|
||||
'.',
|
||||
'*',
|
||||
'?',
|
||||
'+',
|
||||
'^',
|
||||
'$',
|
||||
'[',
|
||||
']',
|
||||
'(',
|
||||
')',
|
||||
'{',
|
||||
'}',
|
||||
'|',
|
||||
'\\'
|
||||
]
|
||||
let regex
|
||||
|
||||
if (specialCharacters.includes(item)) {
|
||||
regex = new RegExp('\\' + item, 'g')
|
||||
} else {
|
||||
regex = new RegExp(item, 'g')
|
||||
}
|
||||
word.value = word.value.replace(regex, '\n')
|
||||
})
|
||||
// 删除空行
|
||||
let word_arr = word.value.split('\n')
|
||||
word_arr = word_arr.filter((item) => item != '' && item != null)
|
||||
word.value = word_arr.join('\n')
|
||||
ChangeWordInput()
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并数据
|
||||
*/
|
||||
async function mergeWord() {
|
||||
let step = write_setting.value.merge_count ? write_setting.value.merge_count : 3
|
||||
let tmp_arr = []
|
||||
let word_arr = word.value.split('\n')
|
||||
for (let i = 0; i < word_arr.length; i += step) {
|
||||
let group = word_arr.slice(i, i + step)
|
||||
tmp_arr.push(group.join(write_setting.value.merge_char) + write_setting.value.end_char)
|
||||
}
|
||||
word.value = tmp_arr.join('\n')
|
||||
ChangeWordInput()
|
||||
}
|
||||
|
||||
return {
|
||||
data,
|
||||
rowCount,
|
||||
ChangeWordInput,
|
||||
word,
|
||||
word_arr
|
||||
word_arr,
|
||||
AddSplitChar,
|
||||
split_ref,
|
||||
write_setting,
|
||||
mergeCountChange,
|
||||
formateWrite,
|
||||
mergeWord
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -50,7 +50,7 @@ export default defineComponent({
|
||||
props: ['initData', 'menuType', 'height'],
|
||||
setup(props) {
|
||||
let hh = props.height
|
||||
let maxHeight = props.height - 80
|
||||
let maxHeight = props.height - 80
|
||||
let data = ref(props.initData)
|
||||
const message = useMessage()
|
||||
let selectKey = ref([])
|
||||
@@ -506,11 +506,8 @@ export default defineComponent({
|
||||
positiveText: '保存',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
debugger
|
||||
console.log(editWordRef)
|
||||
debugger
|
||||
data.value = []
|
||||
let word_arr = editWordRef.value.word.split('\n')
|
||||
let new_arr = []
|
||||
let lastId = ''
|
||||
for (let i = 0; i < word_arr.length; i++) {
|
||||
const element = word_arr[i]
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-data-table
|
||||
id="1111"
|
||||
:max-height="maxHeight"
|
||||
:row-key="rowKey"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
:pagination="false"
|
||||
:bordered="false"
|
||||
:scroll-x="0"
|
||||
@update:checked-row-keys="handleCheck"
|
||||
/>
|
||||
</div>
|
||||
@@ -41,13 +43,18 @@ import { DEFINE_STRING } from '../../../../define/define_string'
|
||||
import ModifyPromptChinese from '../Components/ModifyPromptChinese.vue'
|
||||
import InputDialogContent from './Components/InputDialogContent.vue'
|
||||
import DataTableShowGenerateImage from './Components/DataTableShowGenerateImage.vue'
|
||||
import { cloneDeep, debounce, min } from 'lodash'
|
||||
import { cloneDeep, debounce, isEmpty, min } from 'lodash'
|
||||
import SelectImageStyle from '../Components/SelectImageStyle.vue'
|
||||
import DataTableCharacterAndScene from './Components/DataTableCharacterAndScene.vue'
|
||||
import DataTablePromptRow from './Components/DataTablePromptRow.vue'
|
||||
import DataTableGptPromptRow from './Components/DataTableGptPromptRow.vue'
|
||||
import DataTableParameterRow from './Components/DataTableParameterRow.vue'
|
||||
import { Reload } from '@vicons/ionicons5'
|
||||
import {
|
||||
checkStringValueAddPrefix,
|
||||
checkStringValueAddSuffix,
|
||||
checkStringValueDeletePrefix
|
||||
} from '../../../../main/generalTools'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -63,15 +70,15 @@ export default defineComponent({
|
||||
Reload,
|
||||
NIcon
|
||||
},
|
||||
props: ['initData', 'prefix_prompt', 'suffix_prompt'],
|
||||
props: ['initData', 'prefix_prompt', 'suffix_prompt', 'tags', 'InitTags'],
|
||||
setup(props) {
|
||||
console.log('输出文件夹位置', props.initData)
|
||||
let data = ref(props.initData)
|
||||
let tags = ref(props.tags)
|
||||
let message = useMessage()
|
||||
let dialog = useDialog()
|
||||
let selectKey = ref([])
|
||||
let promptChineseRef = ref(null)
|
||||
let zhAutoTranslate = ref(false)
|
||||
let maxHeight = ref(null)
|
||||
let prefix_prompt = ref(props.prefix_prompt)
|
||||
let suffix_prompt = ref(props.suffix_prompt)
|
||||
@@ -86,8 +93,6 @@ export default defineComponent({
|
||||
window.config.character_select_model ? window.config.character_select_model : 'tag'
|
||||
)
|
||||
|
||||
let tags = ref({})
|
||||
|
||||
let AutoSaveDataJsonDebounced = debounce(AutoSaveDataJson, 3000)
|
||||
let SaveDataJsonDebounced = debounce(AutoSaveDataJson, 1000)
|
||||
|
||||
@@ -107,6 +112,23 @@ export default defineComponent({
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.tags,
|
||||
async (newVal) => {
|
||||
debugger
|
||||
tags.value = newVal
|
||||
// 同步修改 selectStyle.value 的值
|
||||
for (let i = 0; i < selectStyle.value.length; i++) {
|
||||
let index = tags.value.style_tags?.findIndex(
|
||||
(item) => item.key == selectStyle.value[i].key
|
||||
)
|
||||
if (selectStyle.value[i].type == 'style_main' && index != null && index != -1) {
|
||||
selectStyle.value[i] = tags.value.style_tags[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.prefix_prompt,
|
||||
(newVal) => {
|
||||
@@ -138,20 +160,16 @@ export default defineComponent({
|
||||
const createColumns = ({}) => {
|
||||
return [
|
||||
{
|
||||
type: 'selection',
|
||||
disabled(row) {
|
||||
return row.name === 'Edward King 3'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
title: 'No.',
|
||||
key: 'no',
|
||||
width: 50
|
||||
width: 50,
|
||||
fixed: 'left'
|
||||
},
|
||||
{
|
||||
title: '字幕',
|
||||
key: 'srt',
|
||||
width: '180',
|
||||
fixed: 'left',
|
||||
render(row) {
|
||||
let tmp
|
||||
if (row.subValue.length > 0) {
|
||||
@@ -187,10 +205,10 @@ export default defineComponent({
|
||||
func: {
|
||||
refreshTagData: async () => {
|
||||
try {
|
||||
await InitTags()
|
||||
await props.InitTags()
|
||||
message.success('人物角色刷新成功')
|
||||
} catch (error) {
|
||||
message.success('人物角色刷新失败,请重试')
|
||||
message.error('人物角色刷新失败,请重试' + error.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,6 +233,7 @@ export default defineComponent({
|
||||
type: 'title',
|
||||
row: row,
|
||||
index: index,
|
||||
tags: tags,
|
||||
func: {
|
||||
translateAll: TranslateAll,
|
||||
addPrefix: AddPrefix,
|
||||
@@ -225,6 +244,9 @@ export default defineComponent({
|
||||
},
|
||||
key: 'gpt_prompt',
|
||||
className: 'prompt_row',
|
||||
resizable: true,
|
||||
minWidth: 300,
|
||||
width: '500',
|
||||
render(row, index) {
|
||||
return h(DataTableGptPromptRow, {
|
||||
type: 'data',
|
||||
@@ -326,32 +348,31 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
async function InitTags() {
|
||||
await window.mj.GetTagDataByTypeAndProperty(['dynamic', null], (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
tags.value = value.data
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
zhAutoTranslate.value = window.config.translation_auto
|
||||
|
||||
await window.api.GetConfigJson(JSON.stringify(['image_style', []]), async (value) => {
|
||||
// 直接或整个cinfig文件
|
||||
await window.api.GetConfigJson(JSON.stringify([null, {}]), async (value) => {
|
||||
debugger
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
await window.api.GetImageStyleInfomation(JSON.stringify(toRaw(value.data)), (value) => {
|
||||
let image_style_list = value.data.image_style
|
||||
let customize_image_style_list = value.data.customize_image_style
|
||||
await window.api.GetImageStyleInfomation(JSON.stringify(image_style_list), (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
selectStyle.value = value.data
|
||||
})
|
||||
|
||||
for (let i = 0; i < customize_image_style_list.length; i++) {
|
||||
const element = customize_image_style_list[i]
|
||||
selectStyle.value.push({
|
||||
key: element,
|
||||
type: 'style_main'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// 判断data中的数据是不是有chinese text
|
||||
@@ -410,7 +431,7 @@ export default defineComponent({
|
||||
}
|
||||
)
|
||||
|
||||
await InitTags()
|
||||
await props.InitTags()
|
||||
})
|
||||
|
||||
onBeforeUnmount(async () => {
|
||||
@@ -438,11 +459,9 @@ export default defineComponent({
|
||||
}
|
||||
delete value.type
|
||||
delete value.code
|
||||
|
||||
data.value[index]['mj_message'] = value
|
||||
} else if (value.type == 'updated') {
|
||||
console.log('接收Discord的更新消息', value)
|
||||
debugger
|
||||
// 修改对应的数据
|
||||
let index = data.value.findIndex((item) => item.mj_message?.message_id == value.message_id)
|
||||
if (index < 0) {
|
||||
@@ -461,8 +480,6 @@ export default defineComponent({
|
||||
console.log('接收Discord的删除消息', value)
|
||||
} else if (value.type == 'finished') {
|
||||
console.log('接收Discord的完成消息', value)
|
||||
debugger
|
||||
|
||||
// 修改对应的数据
|
||||
let index = data.value.findIndex((item) => item.mj_message?.image_id == value.image_id)
|
||||
if (index < 0) {
|
||||
@@ -567,6 +584,7 @@ export default defineComponent({
|
||||
* 选择生成图片的风格
|
||||
*/
|
||||
async function SelectGenerateImagesStyle() {
|
||||
debugger
|
||||
// 判断当前数据是不是存在
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = window.innerWidth * 0.8
|
||||
@@ -578,26 +596,47 @@ export default defineComponent({
|
||||
content: () =>
|
||||
h(SelectImageStyle, {
|
||||
selectStyle: toRaw(selectStyle.value),
|
||||
height: dialogHeight
|
||||
height: dialogHeight,
|
||||
tags: tags
|
||||
}),
|
||||
style: `width : ${dialogWidth}px; height : ${dialogHeight}px`,
|
||||
maskClosable: false,
|
||||
onClose: async () => {
|
||||
// 重新加载数据
|
||||
let tmp_arr = []
|
||||
|
||||
let cus_arr = []
|
||||
|
||||
for (let i = 0; i < selectStyle.value.length; i++) {
|
||||
debugger
|
||||
const element = selectStyle.value[i]
|
||||
tmp_arr.push(element.id)
|
||||
// 判断是不是主风格
|
||||
if (element.type == 'style_main') {
|
||||
cus_arr.push(element.key)
|
||||
} else {
|
||||
tmp_arr.push(element.id)
|
||||
}
|
||||
}
|
||||
|
||||
// 将当前的风格保存
|
||||
await window.api.SaveCopywritingInformation(
|
||||
[JSON.stringify(tmp_arr), 'image_style', true],
|
||||
(value) => {
|
||||
async (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
message.success('保存成功')
|
||||
|
||||
await window.api.SaveCopywritingInformation(
|
||||
[JSON.stringify(cus_arr), 'customize_image_style', true],
|
||||
() => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
message.success('保存成功')
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -808,12 +847,128 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SD 模式合并名并
|
||||
* @param character_string
|
||||
* @param scene_string
|
||||
* @param gpt_prompt
|
||||
*/
|
||||
function SDMergePrompt(element) {
|
||||
let character_string = ''
|
||||
element.character_tags?.forEach((item) => {
|
||||
character_string += ', ' + item.prompt
|
||||
if (item.lora && item.lora != '无' && item.lora_weight) {
|
||||
character_string += `, <lora:${item.lora}:${item.lora_weight}>`
|
||||
}
|
||||
})
|
||||
// 判断 character_string 有数据,有的话删除第一个逗号
|
||||
character_string = checkStringValueDeletePrefix(character_string, ',')
|
||||
|
||||
// 获取当前的场景提示词
|
||||
let scene_string = ''
|
||||
element.scene_tags?.forEach((item) => {
|
||||
scene_string += ', ' + item.prompt
|
||||
})
|
||||
|
||||
let style_string = ''
|
||||
|
||||
selectStyle.value.forEach((item) => {
|
||||
if (item.type && item.type == 'style_main') {
|
||||
style_string += ', ' + item.prompt
|
||||
}
|
||||
})
|
||||
|
||||
// 判断 scene_string 有数据,有的话删除第一个逗号
|
||||
scene_string = checkStringValueDeletePrefix(scene_string, ',')
|
||||
style_string = checkStringValueDeletePrefix(style_string, ',')
|
||||
style_string = checkStringValueAddSuffix(style_string, ',')
|
||||
|
||||
return `${style_string} ${checkStringValueAddSuffix(
|
||||
character_string,
|
||||
', '
|
||||
)}${checkStringValueAddSuffix(scene_string, ', ')}${checkStringValueAddSuffix(
|
||||
element.gpt_prompt,
|
||||
', '
|
||||
)}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 将所有的数据进行拼接
|
||||
* @param prefix 前缀
|
||||
* @param character_string 人物提示词
|
||||
* @param scene_string 场景提示词
|
||||
* @param gpt_prompt GPT提示词
|
||||
* @param suffix 后缀
|
||||
*/
|
||||
function MJMergePrompt(prefix, element, suffix) {
|
||||
debugger
|
||||
let character_string = ''
|
||||
let cref_url = ''
|
||||
element.character_tags?.forEach((item) => {
|
||||
character_string += ', ' + item.prompt
|
||||
if (item.image_url && item.image_url != '' && item.cref_cw) {
|
||||
cref_url += ` ${item.image_url} `
|
||||
}
|
||||
})
|
||||
// 判断cref_url 是不是有数据,有的话添加 --cref
|
||||
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} `)
|
||||
}
|
||||
// 判断 character_string 有数据,有的话删除第一个逗号
|
||||
character_string = checkStringValueDeletePrefix(character_string, ',')
|
||||
|
||||
// 获取当前的场景提示词
|
||||
let scene_string = ''
|
||||
element.scene_tags?.forEach((item) => {
|
||||
scene_string += ', ' + item.prompt
|
||||
})
|
||||
// 判断 scene_string 有数据,有的话删除第一个逗号
|
||||
scene_string = checkStringValueDeletePrefix(scene_string, ',')
|
||||
|
||||
// 获取当前的自定义风格
|
||||
|
||||
let style_string = ''
|
||||
let style_url = ''
|
||||
let sw = 0
|
||||
|
||||
selectStyle.value.forEach((item) => {
|
||||
if (item.type && item.type == 'style_main') {
|
||||
style_string += ', ' + item.prompt
|
||||
if (sw == 0) {
|
||||
sw = item.sref_sw
|
||||
}
|
||||
if (!isEmpty(item.image_url)) {
|
||||
let url = item.image_url ? item.image_url : ''
|
||||
style_url += ' ' + url
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
style_url = checkStringValueAddPrefix(style_url, '--sref ')
|
||||
style_url = checkStringValueAddSuffix(style_url, ` --sw ${sw}`)
|
||||
style_string = checkStringValueDeletePrefix(style_string, ',')
|
||||
style_string = checkStringValueAddSuffix(style_string, ', ')
|
||||
|
||||
return ` ${style_string} ${checkStringValueAddSuffix(
|
||||
prefix,
|
||||
', '
|
||||
)}${checkStringValueAddSuffix(character_string, ', ')}${checkStringValueAddSuffix(
|
||||
scene_string,
|
||||
', '
|
||||
)}${checkStringValueAddSuffix(element.gpt_prompt, ', ')} ${checkStringValueAddSuffix(
|
||||
suffix,
|
||||
' '
|
||||
)} ${cref_url} ${style_url}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成提示词
|
||||
*/
|
||||
async function MergePrompt() {
|
||||
debugger
|
||||
async function MergePrompt(key) {
|
||||
try {
|
||||
debugger
|
||||
// 判断该当前是不是有风格
|
||||
// 获取当前的风格ID
|
||||
let style_str = ''
|
||||
@@ -823,29 +978,34 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
// 获取当前的前缀和后缀
|
||||
let prefix = prefix_prompt.value
|
||||
let suffix = suffix_prompt.value
|
||||
let prefix = prefix_prompt.value ? prefix_prompt.value : ''
|
||||
let suffix = suffix_prompt.value ? suffix_prompt.value : ''
|
||||
|
||||
for (let i = 0; i < data.value.length; i++) {
|
||||
const element = data.value[i]
|
||||
// 匹配提示词
|
||||
// 拼接当前选择的人物
|
||||
let character_string = ''
|
||||
element.character_tags?.forEach((item) => {
|
||||
character_string += item.prompt + ', '
|
||||
})
|
||||
|
||||
// 获取当前的场景提示词
|
||||
let scene_string = ''
|
||||
element.scene_tags?.forEach((item) => {
|
||||
scene_string += item.prompt + ', '
|
||||
})
|
||||
|
||||
// 开始拼接提示词
|
||||
let end_prompt = ''
|
||||
if (key == null) {
|
||||
// 判断当前的分类是什么,通过分类来判断合并提示词
|
||||
if (image_generate_category.value == 'sd') {
|
||||
end_prompt = SDMergePrompt(element)
|
||||
} else if (image_generate_category.value == 'mj') {
|
||||
end_prompt = MJMergePrompt(prefix, element, suffix)
|
||||
} else if (image_generate_category.value == 'd3') {
|
||||
message.error('该分类暂时不可用')
|
||||
return
|
||||
} else {
|
||||
message.error('合并提示词错误:未知的合并提示词类型')
|
||||
return
|
||||
}
|
||||
} else if (key == 'mj_merge') {
|
||||
end_prompt = MJMergePrompt(prefix, element, suffix)
|
||||
} else if (key == 'sd_merge') {
|
||||
end_prompt = SDMergePrompt(element)
|
||||
} else {
|
||||
message.error('合并提示词错误:未知的合并提示词类型')
|
||||
return
|
||||
}
|
||||
// 风格 + 前缀 + 人物 + 场景 + 词 + 后缀
|
||||
let end_prompt = ` ${style_str} ${
|
||||
prefix ? prefix : ''
|
||||
}, ${character_string} ${scene_string} ${element.gpt_prompt}, ${suffix ? suffix : ''}`
|
||||
data.value[i].prompt = end_prompt
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -910,7 +1070,6 @@ export default defineComponent({
|
||||
selectKey.value = rowKeys
|
||||
},
|
||||
promptChineseRef,
|
||||
zhAutoTranslate,
|
||||
TranslatePrompt,
|
||||
TranslateAll,
|
||||
maxHeight,
|
||||
|
||||
@@ -1,99 +1,146 @@
|
||||
<template>
|
||||
<div id="menu">
|
||||
<MenuButton :initData="data" :initDataFunction="InitData" :Character="AnalyzeCharacter" :treeData="TagTreeData">
|
||||
</MenuButton>
|
||||
</div>
|
||||
<div id="data-table" style="margin-top: 10px;">
|
||||
<DataTable :initData="data" :suffix_prompt="suffix_prompt" :prefix_prompt="prefix_prompt"></DataTable>
|
||||
</div>
|
||||
<div id="menu">
|
||||
<MenuButton
|
||||
:initData="data"
|
||||
:initDataFunction="InitData"
|
||||
:Character="AnalyzeCharacter"
|
||||
:treeData="TagTreeData"
|
||||
>
|
||||
</MenuButton>
|
||||
</div>
|
||||
<div id="data-table" style="margin-top: 10px">
|
||||
<DataTable
|
||||
:tags="tags"
|
||||
:initData="data"
|
||||
:suffix_prompt="suffix_prompt"
|
||||
:prefix_prompt="prefix_prompt"
|
||||
:InitTags="InitTags"
|
||||
></DataTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, h, onMounted, defineComponent, onUnmounted, toRaw } from "vue"
|
||||
import { NImage, useMessage } from "naive-ui";
|
||||
import { DEFINE_STRING } from "../../../../define/define_string";
|
||||
import { ref, h, onMounted, defineComponent, onUnmounted, toRaw } from 'vue'
|
||||
import { NImage, useMessage } from 'naive-ui'
|
||||
import { DEFINE_STRING } from '../../../../define/define_string'
|
||||
import MenuButton from './MenuButton.vue'
|
||||
import DataTable from './DataTable.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NImage, DataTable, MenuButton
|
||||
},
|
||||
setup() {
|
||||
let message = useMessage();
|
||||
let data = ref([]);
|
||||
let AnalyzeCharacter = ref("");
|
||||
let TagTreeData = ref([]);
|
||||
let suffix_prompt = ref(null);
|
||||
let prefix_prompt = ref(null);
|
||||
let promptError = true;
|
||||
components: {
|
||||
NImage,
|
||||
DataTable,
|
||||
MenuButton
|
||||
},
|
||||
setup() {
|
||||
let message = useMessage()
|
||||
let data = ref([])
|
||||
let tags = ref({})
|
||||
let AnalyzeCharacter = ref('')
|
||||
let TagTreeData = ref([])
|
||||
let suffix_prompt = ref(null)
|
||||
let prefix_prompt = ref(null)
|
||||
let promptError = true
|
||||
|
||||
async function InitData() {
|
||||
// 加载
|
||||
// 初始化加载项目下面的分镜好的文案
|
||||
// 并判断是不是有洗稿后的文件。一并加载
|
||||
await window.api.GetProjectWord(value => {
|
||||
data.value = value.data;
|
||||
})
|
||||
if (!data.value) {
|
||||
data.value = [];
|
||||
}
|
||||
async function InitData() {
|
||||
// 加载
|
||||
// 初始化加载项目下面的分镜好的文案
|
||||
// 并判断是不是有洗稿后的文件。一并加载
|
||||
await window.api.GetProjectWord((value) => {
|
||||
data.value = value.data
|
||||
})
|
||||
if (!data.value) {
|
||||
data.value = []
|
||||
}
|
||||
|
||||
// 重新加载数据
|
||||
// 判断是不是已经有生成(有有生成显示)
|
||||
await window.api.GetConfigJson(JSON.stringify(['auto_analyze_character', ""]), (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
AnalyzeCharacter.value = value.data;
|
||||
})
|
||||
|
||||
// 判断是不是有前缀
|
||||
await window.api.GetConfigJson(JSON.stringify([null, {}]), async (value) => {
|
||||
debugger
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
suffix_prompt.value = value.data.suffix_prompt;
|
||||
prefix_prompt.value = value.data.prefix_prompt;
|
||||
|
||||
})
|
||||
|
||||
// 读取data数据对应的prompt文件
|
||||
for (let i = 0; i < data.value.length; i++) {
|
||||
const item = data.value[i];
|
||||
await window.api.GetPromptJson(item.name, (value) => {
|
||||
debugger
|
||||
console.log(value);
|
||||
if (value.code == 0 && promptError) {
|
||||
message.error(value.message);
|
||||
promptError = false;
|
||||
}
|
||||
data.value[i].prompt = value.data.webui_config.prompt;
|
||||
data.value[i].chinese_prompt = value.data?.chinese_prompt;
|
||||
// data.value[i].gpt_prompt = value.data?.gpt_prompt;
|
||||
data.value[i].adetailer = value.data?.adetailer;
|
||||
|
||||
})
|
||||
}
|
||||
// 重新加载数据
|
||||
// 判断是不是已经有生成(有有生成显示)
|
||||
await window.api.GetConfigJson(JSON.stringify(['auto_analyze_character', '']), (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
AnalyzeCharacter.value = value.data
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await InitData();
|
||||
// 判断是不是有前缀
|
||||
await window.api.GetConfigJson(JSON.stringify([null, {}]), async (value) => {
|
||||
debugger
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
suffix_prompt.value = value.data.suffix_prompt
|
||||
prefix_prompt.value = value.data.prefix_prompt
|
||||
})
|
||||
|
||||
// 读取data数据对应的prompt文件
|
||||
for (let i = 0; i < data.value.length; i++) {
|
||||
const item = data.value[i]
|
||||
await window.api.GetPromptJson(item.name, (value) => {
|
||||
debugger
|
||||
console.log(value)
|
||||
if (value.code == 0 && promptError) {
|
||||
message.error(value.message)
|
||||
promptError = false
|
||||
}
|
||||
data.value[i].prompt = value.data.webui_config.prompt
|
||||
data.value[i].chinese_prompt = value.data?.chinese_prompt
|
||||
// data.value[i].gpt_prompt = value.data?.gpt_prompt;
|
||||
data.value[i].adetailer = value.data?.adetailer
|
||||
})
|
||||
|
||||
|
||||
return {
|
||||
data,
|
||||
AnalyzeCharacter,
|
||||
TagTreeData,
|
||||
prefix_prompt,
|
||||
suffix_prompt,
|
||||
InitData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function InitTags() {
|
||||
await window.mj.GetTagDataByTypeAndProperty(['dynamic', null], (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
debugger
|
||||
tags.value = value.data
|
||||
// 加载完毕之后,需要刷新当前的data中的tag数据
|
||||
console.log(data, tags)
|
||||
for (let i = 0; i < data.value.length; i++) {
|
||||
const element = data.value[i]
|
||||
if (
|
||||
element.character_tags &&
|
||||
tags.value.character_tags &&
|
||||
tags.value.character_tags.length > 0
|
||||
) {
|
||||
// 循环判断当前的character_tags对应的key在tags.character_tags中是否存在,存在覆盖,不存在删除
|
||||
for (let j = element.character_tags.length - 1; j >= 0; j--) {
|
||||
const item = element.character_tags[j]
|
||||
let index = tags.value.character_tags.findIndex((tag) => tag.key == item.key)
|
||||
if (index != -1) {
|
||||
element.character_tags[j] = tags.value.character_tags[index]
|
||||
} else {
|
||||
element.character_tags.splice(j, 1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
element.character_tags = []
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await InitData()
|
||||
await InitTags()
|
||||
})
|
||||
|
||||
return {
|
||||
data,
|
||||
AnalyzeCharacter,
|
||||
TagTreeData,
|
||||
prefix_prompt,
|
||||
suffix_prompt,
|
||||
InitData,
|
||||
InitTags,
|
||||
tags
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -168,7 +168,6 @@ export default defineComponent({
|
||||
mjSetting.value = value.data;
|
||||
modifyOption(value.data);
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,132 +1,244 @@
|
||||
<template>
|
||||
<n-tabs type="line" animated size="large">
|
||||
<n-tab-pane name="normal setting" tab="基础设置">
|
||||
<n-form ref="formRef" :label-width="80" :model="formValue">
|
||||
<n-form-item label="SD请求地址" path="webui_api_url">
|
||||
<n-input v-model:value="formValue.webui_api_url" placeholder="输入SD地址" />
|
||||
</n-form-item>
|
||||
<n-form-item label="出图方式(文生图、图生图)" path="type">
|
||||
<n-select v-model:value="formValue.type" :options="modelOption" placeholder="输入采样方法" />
|
||||
</n-form-item>
|
||||
<n-form-item label="正向提示词(和推导出来的tag进行拼接)" path="prompt">
|
||||
<n-input v-model:value="formValue.prompt" placeholder="输入正向提示词" />
|
||||
</n-form-item>
|
||||
<n-form-item label="反向提示词" path="negative_prompt">
|
||||
<n-input v-model:value="formValue.negative_prompt" placeholder="输入反向提示词" />
|
||||
</n-form-item>
|
||||
<div style="display: flex">
|
||||
<n-form-item label="CFG Scale" style="margin-right: 30px;">
|
||||
<n-input-number :min="0" :max="30" :step="0.05" v-model:value="formValue.cfg_scale"
|
||||
placeholder="输入重绘幅度" />
|
||||
</n-form-item>
|
||||
<n-form-item label="重绘幅度" path="denoising_strength">
|
||||
<n-input-number :precision="2" :step="0.05" v-model:value="formValue.denoising_strength"
|
||||
placeholder="输入重绘幅度" />
|
||||
<n-checkbox style="margin-left: 30px;" size="large" v-model:checked="formValue.adetailer"
|
||||
label="是否开启修脸/修手" />
|
||||
</n-form-item>
|
||||
</div>
|
||||
<n-form-item label="采样方式" path="sampler_name">
|
||||
<n-input v-model:value="formValue.sampler_name" placeholder="输入模型" />
|
||||
</n-form-item>
|
||||
<div style="display: flex;">
|
||||
<n-form-item label="迭代步数" path="steps">
|
||||
<n-input-number style="width: 150px;" v-model:value="formValue.steps" placeholder="输入迭代步数" />
|
||||
</n-form-item>
|
||||
<n-form-item label="风格词权重" path="style_weight" style="margin-left: 10px;">
|
||||
<n-input-number :min="1" :max="4" :step="0.05" :precision="2" style="width: 150px;"
|
||||
v-model:value="formValue.style_weight" placeholder="输入风格词权重" />
|
||||
</n-form-item>
|
||||
</div>
|
||||
<n-form-item label="图片分辨率" path="resolution">
|
||||
<n-input-number :show-button="false" v-model:value="formValue.width" placeholder="输入迭代步数" />
|
||||
<span style="margin: 0 10px;"> * </span>
|
||||
<n-input-number :show-button="false" v-model:value="formValue.height" placeholder="输入迭代步数" />
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button attr-type="button" type="primary" @click="SaveSDConfig">
|
||||
保存设置
|
||||
</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="ADetailer setting" tab="ADetailer 设置">
|
||||
<SDADetailerSetting />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
<n-tabs type="line" animated size="large">
|
||||
<n-tab-pane name="normal setting" tab="基础设置">
|
||||
<n-form ref="formRef" :label-width="80" :model="formValue">
|
||||
<n-form-item label="SD请求地址" path="webui_api_url">
|
||||
<n-input
|
||||
v-model:value="formValue.webui_api_url"
|
||||
style="width: 250px"
|
||||
placeholder="输入SD地址"
|
||||
/>
|
||||
<n-button style="margin-left: 10px" type="primary" @click="LoadSDServiceData"
|
||||
>加载数据</n-button
|
||||
>
|
||||
</n-form-item>
|
||||
<n-form-item label="出图方式(文生图、图生图)" path="type">
|
||||
<n-select
|
||||
v-model:value="formValue.type"
|
||||
:options="modelOption"
|
||||
placeholder="输入采样方法"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="正向提示词(和推导出来的tag进行拼接)" path="prompt">
|
||||
<n-input v-model:value="formValue.prompt" placeholder="输入正向提示词" />
|
||||
</n-form-item>
|
||||
<n-form-item label="反向提示词" path="negative_prompt">
|
||||
<n-input v-model:value="formValue.negative_prompt" placeholder="输入反向提示词" />
|
||||
</n-form-item>
|
||||
<div style="display: flex">
|
||||
<n-form-item label="CFG Scale" style="margin-right: 30px">
|
||||
<n-input-number
|
||||
:min="0"
|
||||
:max="30"
|
||||
:step="0.05"
|
||||
v-model:value="formValue.cfg_scale"
|
||||
placeholder="输入重绘幅度"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="重绘幅度" path="denoising_strength">
|
||||
<n-input-number
|
||||
:precision="2"
|
||||
:step="0.05"
|
||||
v-model:value="formValue.denoising_strength"
|
||||
placeholder="输入重绘幅度"
|
||||
/>
|
||||
<n-checkbox
|
||||
style="margin-left: 30px"
|
||||
size="large"
|
||||
v-model:checked="formValue.adetailer"
|
||||
label="是否开启修脸/修手"
|
||||
/>
|
||||
</n-form-item>
|
||||
</div>
|
||||
<n-form-item label="采样方式" path="sampler_name">
|
||||
<n-input v-model:value="formValue.sampler_name" placeholder="输入模型" />
|
||||
</n-form-item>
|
||||
<div style="display: flex">
|
||||
<n-form-item label="迭代步数" path="steps">
|
||||
<n-input-number
|
||||
style="width: 150px"
|
||||
v-model:value="formValue.steps"
|
||||
placeholder="输入迭代步数"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="风格词权重" path="style_weight" style="margin-left: 10px">
|
||||
<n-input-number
|
||||
:min="1"
|
||||
:max="4"
|
||||
:step="0.05"
|
||||
:precision="2"
|
||||
style="width: 150px"
|
||||
v-model:value="formValue.style_weight"
|
||||
placeholder="输入风格词权重"
|
||||
/>
|
||||
</n-form-item>
|
||||
</div>
|
||||
<n-form-item label="图片分辨率" path="resolution">
|
||||
<n-input-number
|
||||
:show-button="false"
|
||||
v-model:value="formValue.width"
|
||||
placeholder="输入迭代步数"
|
||||
/>
|
||||
<span style="margin: 0 10px"> * </span>
|
||||
<n-input-number
|
||||
:show-button="false"
|
||||
v-model:value="formValue.height"
|
||||
placeholder="输入迭代步数"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button attr-type="button" type="primary" @click="SaveSDConfig"> 保存设置 </n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="ADetailer setting" tab="ADetailer 设置">
|
||||
<SDADetailerSetting />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, h, onMounted, toRaw } from "vue";
|
||||
import { NForm, NFormItem, NInput, NButton, useMessage, NInputNumber, NSelect, NTabs, NTabPane, NCheckbox } from "naive-ui"
|
||||
import SDADetailerSetting from "../Components/SDADetailerSetting.vue"
|
||||
import { defineComponent, ref, h, onMounted, toRaw } from 'vue'
|
||||
import {
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInput,
|
||||
NButton,
|
||||
useMessage,
|
||||
NInputNumber,
|
||||
NSelect,
|
||||
NTabs,
|
||||
NTabPane,
|
||||
NCheckbox
|
||||
} from 'naive-ui'
|
||||
import SDADetailerSetting from '../Components/SDADetailerSetting.vue'
|
||||
|
||||
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
|
||||
})
|
||||
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
|
||||
})
|
||||
|
||||
let modelOption = ref([{
|
||||
label: "文生图",
|
||||
value: "txt2img"
|
||||
}, {
|
||||
label: "图生图",
|
||||
value: "img2img"
|
||||
}]);
|
||||
let samplers_options = ref([])
|
||||
let lora_options = ref([])
|
||||
let sd_models_options = ref([])
|
||||
|
||||
onMounted(async () => {
|
||||
await window.api.InitSDConfig((value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
formValue.value = value.data;
|
||||
})
|
||||
})
|
||||
let modelOption = ref([
|
||||
{
|
||||
label: '文生图',
|
||||
value: 'txt2img'
|
||||
},
|
||||
{
|
||||
label: '图生图',
|
||||
value: 'img2img'
|
||||
}
|
||||
])
|
||||
|
||||
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: "未知错误" });
|
||||
}
|
||||
})
|
||||
onMounted(async () => {
|
||||
await window.api.InitSDConfig((value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
formValue.value = value.data
|
||||
|
||||
return {
|
||||
formValue,
|
||||
SaveSDConfig,
|
||||
modelOption,
|
||||
let samplers = value.data.samplers
|
||||
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.loras
|
||||
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_models
|
||||
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: '未知错误' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载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
|
||||
message.success('加载成功')
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
formValue,
|
||||
SaveSDConfig,
|
||||
modelOption,
|
||||
LoadSDServiceData,
|
||||
samplers_options,
|
||||
lora_options,
|
||||
sd_models_options
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -1,379 +1,481 @@
|
||||
<template>
|
||||
<NSpace vertical>
|
||||
<n-spin :show="show">
|
||||
<template #description>
|
||||
保存中
|
||||
</template>
|
||||
<n-form ref="formRef" :model="formValue" :rules="rules">
|
||||
<n-form-item path="draft_path" label="剪映草稿地址">
|
||||
<n-input v-model:value="formValue.draft_path" @keydown.enter.prevent />
|
||||
</n-form-item>
|
||||
<n-form-item path="project_path" label="项目地址(帧,图片等输出的地址)">
|
||||
<div>
|
||||
<n-input style="width: 400px;" v-model:value="formValue.project_path" @keydown.enter.prevent />
|
||||
</div>
|
||||
<n-button color="#e5a84b" @click="SelectProjectFolder" style="margin-left: 10px;">
|
||||
<n-icon :size="20">
|
||||
<folder-open />
|
||||
</n-icon>
|
||||
</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item path="project_name" label="项目名称">
|
||||
<n-input v-model:value="formValue.project_name" @keydown.enter.prevent />
|
||||
</n-form-item>
|
||||
<n-form-item path="system_setting" label="系统设置">
|
||||
<n-form-item path="task_number" label="后台并行任务数(量力而行)">
|
||||
<n-input-number v-model:value="formValue.task_number" @keydown.enter.prevent :min="1" :max="10"
|
||||
placeholder="输入后台并行任务数" />
|
||||
</n-form-item>
|
||||
<n-form-item label="系统主题" style="margin-left: 20px;">
|
||||
<n-switch :rail-style="railStyle" v-model:value="formValue.theme" size="medium"
|
||||
checked-value="dark" unchecked-value="light" @update:value="ChangeMode">
|
||||
<template #checked>
|
||||
暗
|
||||
</template>
|
||||
<template #unchecked>
|
||||
亮
|
||||
</template>
|
||||
</n-switch>
|
||||
</n-form-item>
|
||||
<n-form-item label="人物场景选择模式" style="margin-left: 20px;">
|
||||
<n-select size="small" placeholder="请选择" :options="character_select_model_options"
|
||||
v-model:value="formValue.character_select_model" style="width: 120px;" />
|
||||
</n-form-item>
|
||||
</n-form-item>
|
||||
<n-form-item path="gpt_setting" label="GPT设置">
|
||||
<n-form-item path="gpt_business" label="GPT接口服务商">
|
||||
<n-select v-model:value="formValue.gpt_business" :options="gpt_options" placeholder="GPT接口服务商"
|
||||
style="width: 200px;" />
|
||||
</n-form-item>
|
||||
<n-button type="info" @click="openGptBuyUrl">
|
||||
购买
|
||||
</n-button>
|
||||
<n-form-item style="width: 300px; margin-left: 30px;" path="gpt_key" label="GPT Key">
|
||||
<n-input type="password" show-password-on="mousedown" v-model:value="formValue.gpt_key"
|
||||
@keydown.enter.prevent placeholder="GPT Key" />
|
||||
</n-form-item>
|
||||
<n-form-item style="margin-left: 30px;" path="gpt_model" label="GPT模型">
|
||||
<n-select v-model:value="formValue.gpt_model" :options="gpt_model_options" placeholder="GPT模型"
|
||||
style="width: 160px;" />
|
||||
</n-form-item>
|
||||
<NSpace vertical>
|
||||
<n-spin :show="show">
|
||||
<template #description> 保存中 </template>
|
||||
<n-form ref="formRef" :model="formValue" :rules="rules">
|
||||
<n-form-item path="draft_path" label="剪映草稿地址">
|
||||
<n-input v-model:value="formValue.draft_path" @keydown.enter.prevent />
|
||||
</n-form-item>
|
||||
<n-form-item path="project_path" label="项目地址(帧,图片等输出的地址)">
|
||||
<div>
|
||||
<n-input
|
||||
style="width: 400px"
|
||||
v-model:value="formValue.project_path"
|
||||
@keydown.enter.prevent
|
||||
/>
|
||||
</div>
|
||||
<n-button color="#e5a84b" @click="SelectProjectFolder" style="margin-left: 10px">
|
||||
<n-icon :size="20">
|
||||
<folder-open />
|
||||
</n-icon>
|
||||
</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item path="project_name" label="项目名称">
|
||||
<n-input v-model:value="formValue.project_name" @keydown.enter.prevent />
|
||||
</n-form-item>
|
||||
<n-form-item path="system_setting" label="系统设置">
|
||||
<n-form-item path="task_number" label="后台并行任务数(量力而行)">
|
||||
<n-input-number
|
||||
v-model:value="formValue.task_number"
|
||||
@keydown.enter.prevent
|
||||
:min="1"
|
||||
:max="10"
|
||||
placeholder="输入后台并行任务数"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="系统主题" style="margin-left: 20px">
|
||||
<n-switch
|
||||
:rail-style="railStyle"
|
||||
v-model:value="formValue.theme"
|
||||
size="medium"
|
||||
checked-value="dark"
|
||||
unchecked-value="light"
|
||||
@update:value="ChangeMode"
|
||||
>
|
||||
<template #checked> 暗 </template>
|
||||
<template #unchecked> 亮 </template>
|
||||
</n-switch>
|
||||
</n-form-item>
|
||||
<n-form-item label="人物场景选择模式" style="margin-left: 20px">
|
||||
<n-select
|
||||
size="small"
|
||||
placeholder="请选择"
|
||||
:options="character_select_model_options"
|
||||
v-model:value="formValue.character_select_model"
|
||||
style="width: 120px"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item style="margin-left: 20px"
|
||||
><n-checkbox v-model:checked="formValue.window_wh_bm_remember"
|
||||
>开启窗口大小/位置记忆</n-checkbox
|
||||
>
|
||||
</n-form-item>
|
||||
</n-form-item>
|
||||
<n-form-item path="gpt_setting" label="GPT设置">
|
||||
<n-form-item path="gpt_business" label="GPT接口服务商">
|
||||
<n-select
|
||||
v-model:value="formValue.gpt_business"
|
||||
:options="gpt_options"
|
||||
placeholder="GPT接口服务商"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-button type="info" @click="openGptBuyUrl"> 购买 </n-button>
|
||||
<n-form-item style="width: 300px; margin-left: 30px" path="gpt_key" label="GPT Key">
|
||||
<n-input
|
||||
type="password"
|
||||
show-password-on="mousedown"
|
||||
v-model:value="formValue.gpt_key"
|
||||
@keydown.enter.prevent
|
||||
placeholder="GPT Key"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item style="margin-left: 30px" path="gpt_model" label="GPT模型">
|
||||
<n-select
|
||||
v-model:value="formValue.gpt_model"
|
||||
:options="gpt_model_options"
|
||||
placeholder="GPT模型"
|
||||
style="width: 160px"
|
||||
/>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item style="margin-left: 30px;" path="gpt_count" label="推理上下文行数">
|
||||
<n-input-number v-model:value="formValue.gpt_count" placeholder="GPT模型" style="width: 150px;"
|
||||
:show-button="false" :min="1" :max="100" />
|
||||
</n-form-item>
|
||||
<n-button color="#e18a3b" @click="addGptOption" style="margin-left: 10px;">
|
||||
添加GPT
|
||||
</n-button>
|
||||
<n-button color="#779649" @click="TestGPTConnection" :loading="loading" style="margin-left: 10px;">
|
||||
测试链接
|
||||
</n-button>
|
||||
<n-button color="#ba5b49" @click="AddGptPrompt" style="margin-left: 10px;">
|
||||
添加GPT提示词
|
||||
</n-button>
|
||||
|
||||
</n-form-item>
|
||||
<n-form-item path="translation_setting" label="翻译设置">
|
||||
<n-form-item path="translation_business" label="翻译服务商">
|
||||
<n-select v-model:value="formValue.translation_business" :options="translation_options"
|
||||
@update:value="SwitchTranslate" placeholder="翻译服务商" style="width: 200px;" />
|
||||
</n-form-item>
|
||||
<n-form-item path="translation_app_id" label="APP ID" style="width: 300px; margin-left: 30px;">
|
||||
<n-input type="password" show-password-on="mousedown"
|
||||
v-model:value="formValue.translation_app_id" @keydown.enter.prevent placeholder="APP ID" />
|
||||
</n-form-item>
|
||||
<n-form-item path="translation_secret" label="产品密钥" style="width: 300px; margin-left: 30px;">
|
||||
<n-input type="password" show-password-on="mousedown"
|
||||
v-model:value="formValue.translation_secret" placeholder="请输入产品密钥"></n-input>
|
||||
</n-form-item>
|
||||
<n-form-item path="translation_secret" label="自动翻译" style="width: 300px; margin-left: 30px;">
|
||||
<n-checkbox v-model:checked="formValue.translation_auto" placeholder="请输入产品密钥"></n-checkbox>
|
||||
</n-form-item>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button
|
||||
:disabled="formValue.draft_path == null || formValue.draft_path == '' || formValue.project_path == null || formValue.project_path == ''"
|
||||
round type="primary" @click="handleValidateButtonClick">
|
||||
保存
|
||||
</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-spin>
|
||||
</NSpace>
|
||||
<n-form-item style="margin-left: 30px" path="gpt_count" label="推理上下文行数">
|
||||
<n-input-number
|
||||
v-model:value="formValue.gpt_count"
|
||||
placeholder="GPT模型"
|
||||
style="width: 150px"
|
||||
:show-button="false"
|
||||
:min="1"
|
||||
:max="100"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-button color="#e18a3b" @click="addGptOption" style="margin-left: 10px">
|
||||
添加GPT
|
||||
</n-button>
|
||||
<n-button
|
||||
color="#779649"
|
||||
@click="TestGPTConnection"
|
||||
:loading="loading"
|
||||
style="margin-left: 10px"
|
||||
>
|
||||
测试链接
|
||||
</n-button>
|
||||
<n-button color="#ba5b49" @click="AddGptPrompt" style="margin-left: 10px">
|
||||
添加GPT提示词
|
||||
</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item path="translation_setting" label="翻译设置">
|
||||
<n-form-item path="translation_business" label="翻译服务商">
|
||||
<n-select
|
||||
v-model:value="formValue.translation_business"
|
||||
:options="translation_options"
|
||||
@update:value="SwitchTranslate"
|
||||
placeholder="翻译服务商"
|
||||
style="width: 200px"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
path="translation_app_id"
|
||||
label="APP ID"
|
||||
style="width: 300px; margin-left: 30px"
|
||||
>
|
||||
<n-input
|
||||
type="password"
|
||||
show-password-on="mousedown"
|
||||
v-model:value="formValue.translation_app_id"
|
||||
@keydown.enter.prevent
|
||||
placeholder="APP ID"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
path="translation_secret"
|
||||
label="产品密钥"
|
||||
style="width: 300px; margin-left: 30px"
|
||||
>
|
||||
<n-input
|
||||
type="password"
|
||||
show-password-on="mousedown"
|
||||
v-model:value="formValue.translation_secret"
|
||||
placeholder="请输入产品密钥"
|
||||
></n-input>
|
||||
</n-form-item>
|
||||
<n-form-item
|
||||
path="translation_secret"
|
||||
label="自动翻译"
|
||||
style="width: 300px; margin-left: 30px"
|
||||
>
|
||||
<n-checkbox v-model:checked="formValue.translation_auto"></n-checkbox>
|
||||
</n-form-item>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-button
|
||||
:disabled="
|
||||
formValue.draft_path == null ||
|
||||
formValue.draft_path == '' ||
|
||||
formValue.project_path == null ||
|
||||
formValue.project_path == ''
|
||||
"
|
||||
round
|
||||
type="primary"
|
||||
@click="handleValidateButtonClick"
|
||||
>
|
||||
保存
|
||||
</n-button>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-spin>
|
||||
</NSpace>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, toRaw, onMounted, defineComponent, h } from "vue"
|
||||
import { NForm, NFormItem, NInput, NInputNumber, useDialog, NButton, NSpace, NSpin, useMessage, NSelect, NCheckbox, NSwitch, NIcon } from "naive-ui"
|
||||
import AddGptOption from "./Components/AddGptOption.vue";
|
||||
import { ref, toRaw, onMounted, defineComponent, h } from 'vue'
|
||||
import {
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInput,
|
||||
NInputNumber,
|
||||
useDialog,
|
||||
NButton,
|
||||
NSpace,
|
||||
NSpin,
|
||||
useMessage,
|
||||
NSelect,
|
||||
NCheckbox,
|
||||
NSwitch,
|
||||
NIcon
|
||||
} from 'naive-ui'
|
||||
import AddGptOption from './Components/AddGptOption.vue'
|
||||
import { FolderOpenSharp as FolderOpen } from '@vicons/ionicons5'
|
||||
import AddGptPrompts from './Components/AddGptPrompts.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
NForm, NFormItem, NInput, NInputNumber, NButton, NSpace, NSpin, NSelect, NCheckbox, NSwitch, FolderOpen, NIcon
|
||||
},
|
||||
setup() {
|
||||
let formRef = ref(null);
|
||||
let message = useMessage()
|
||||
let formValue = ref({
|
||||
draft_path: window.config.draft_path,
|
||||
project_path: window.config.project_path,
|
||||
project_name: window.config.project_name,
|
||||
gpt_business: window.config.gpt_business,
|
||||
gpt_key: window.config.gpt_key,
|
||||
gpt_model: window.config.gpt_model,
|
||||
gpt_count: window.config.gpt_count,
|
||||
task_number: window.config.task_number,
|
||||
translation_business: window.config.translation_business,
|
||||
translation_app_id: window.config.translation_app_id,
|
||||
translation_secret: window.config.translation_secret,
|
||||
translation_auto: window.config.translation_auto,
|
||||
theme: window.config.theme,
|
||||
character_select_model: window.config.character_select_model
|
||||
});
|
||||
let show = ref(false)
|
||||
let gpt_options = ref([]);
|
||||
let gpt_model_options = ref([]);
|
||||
let character_select_model_options = ref([])
|
||||
let dialog = useDialog();
|
||||
let loading = ref(false);
|
||||
components: {
|
||||
NForm,
|
||||
NFormItem,
|
||||
NInput,
|
||||
NInputNumber,
|
||||
NButton,
|
||||
NSpace,
|
||||
NSpin,
|
||||
NSelect,
|
||||
NCheckbox,
|
||||
NSwitch,
|
||||
FolderOpen,
|
||||
NIcon
|
||||
},
|
||||
setup() {
|
||||
let formRef = ref(null)
|
||||
let message = useMessage()
|
||||
let formValue = ref({
|
||||
draft_path: window.config.draft_path,
|
||||
project_path: window.config.project_path,
|
||||
project_name: window.config.project_name,
|
||||
gpt_business: window.config.gpt_business,
|
||||
gpt_key: window.config.gpt_key,
|
||||
gpt_model: window.config.gpt_model,
|
||||
gpt_count: window.config.gpt_count,
|
||||
task_number: window.config.task_number,
|
||||
translation_business: window.config.translation_business,
|
||||
translation_app_id: window.config.translation_app_id,
|
||||
translation_secret: window.config.translation_secret,
|
||||
translation_auto: window.config.translation_auto,
|
||||
theme: window.config.theme,
|
||||
character_select_model: window.config.character_select_model,
|
||||
window_wh_bm_remember: window.config.window_wh_bm_remember
|
||||
})
|
||||
let show = ref(false)
|
||||
let gpt_options = ref([])
|
||||
let gpt_model_options = ref([])
|
||||
let character_select_model_options = ref([])
|
||||
let dialog = useDialog()
|
||||
let loading = ref(false)
|
||||
|
||||
/**
|
||||
* 加载GPT的配置信息
|
||||
*/
|
||||
async function InitGptOptions() {
|
||||
debugger;
|
||||
await window.api.getGptBusinessOption("all", (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
gpt_options.value = value.data;
|
||||
})
|
||||
|
||||
await window.api.getGptModelOption("all", (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message);
|
||||
return;
|
||||
}
|
||||
gpt_model_options.value = value.data;
|
||||
})
|
||||
|
||||
await window.mj.GetTagSelectModel(value => {
|
||||
character_select_model_options.value = value.data;
|
||||
})
|
||||
/**
|
||||
* 加载GPT的配置信息
|
||||
*/
|
||||
async function InitGptOptions() {
|
||||
debugger
|
||||
await window.api.getGptBusinessOption('all', (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
gpt_options.value = value.data
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await InitGptOptions();
|
||||
})
|
||||
|
||||
|
||||
let translation_options = [{
|
||||
label: "百度翻译",
|
||||
value: "https://fanyi-api.baidu.com/api/trans/vip/translate"
|
||||
}, {
|
||||
label: "火山引擎",
|
||||
value: "https://translate.volcengineapi.com?"
|
||||
},
|
||||
{
|
||||
label: "腾讯翻译",
|
||||
value: "https://tmt.tencentcloudapi.com"
|
||||
},
|
||||
{
|
||||
label: "阿里翻译",
|
||||
value: "https://mt.cn-hangzhou.aliyuncs.com"
|
||||
await window.api.getGptModelOption('all', (value) => {
|
||||
if (value.code == 0) {
|
||||
message.error(value.message)
|
||||
return
|
||||
}
|
||||
];
|
||||
gpt_model_options.value = value.data
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
// 切换翻译服务商事件
|
||||
function SwitchTranslate(value, option) {
|
||||
// 将之前的数据全部删除
|
||||
formValue.value.translation_app_id = null;
|
||||
formValue.value.translation_secret = null;
|
||||
}
|
||||
|
||||
let ruleObj = (errorMessage) => {
|
||||
return [{
|
||||
required: true,
|
||||
validator(rule, value) {
|
||||
if (value == null || value == "")
|
||||
return new Error(errorMessage);
|
||||
return true;
|
||||
},
|
||||
trigger: ["input", "blur", "change"]
|
||||
}]
|
||||
}
|
||||
|
||||
let rules = {
|
||||
draft_path: ruleObj("必填剪映草稿地址"),
|
||||
project_path: ruleObj("必填项目地址"),
|
||||
project_name: ruleObj("必填项目名称"),
|
||||
task_number: ruleObj("必填后台并行任务数"),
|
||||
gpt_business: ruleObj("必填GPT接口服务商"),
|
||||
gpt_key: ruleObj("必填GPT Key"),
|
||||
gpt_model: ruleObj("必填GPT模型"),
|
||||
gpt_count: ruleObj("必填自动推理上下文行数"),
|
||||
translation_secret: ruleObj("必填产品密钥"),
|
||||
translation_app_id: ruleObj("必填APP ID"),
|
||||
translation_business: ruleObj("必填翻译服务商"),
|
||||
};
|
||||
|
||||
/**
|
||||
* 保存配置信息
|
||||
*/
|
||||
function handleValidateButtonClick(e) {
|
||||
e.preventDefault();
|
||||
formRef.value?.validate((errors) => {
|
||||
if (errors) {
|
||||
message.error("请检查必填字段");
|
||||
return
|
||||
}
|
||||
// 保存文件
|
||||
window.api.ModifySampleSetting(JSON.stringify(toRaw(formValue.value)), (value) => {
|
||||
if (value.code == 1) {
|
||||
window.api.getSettingDafultData((value) => {
|
||||
window.config = value;
|
||||
})
|
||||
window.api.showGlobalMessageDialog({ code: 1, message: value.message })
|
||||
} else {
|
||||
window.api.showGlobalMessageDialog({ code: 0, message: value.message })
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
let railStyle = (focused,
|
||||
checked) => {
|
||||
const style = {};
|
||||
if (checked) {
|
||||
style.background = "#f3a694";
|
||||
if (focused) {
|
||||
style.boxShadow = "0 0 0 2px #f3a694";
|
||||
}
|
||||
} else {
|
||||
style.background = "#775039";
|
||||
if (focused) {
|
||||
style.boxShadow = "0 0 0 2px #775039";
|
||||
}
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开购买GPT的地址
|
||||
*/
|
||||
async function openGptBuyUrl() {
|
||||
window.api.openGptBuyUrl(toRaw(formValue.value.gpt_business));
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换主题
|
||||
* @param {*} value 主题名称
|
||||
*/
|
||||
async function ChangeMode(value) {
|
||||
debugger
|
||||
console.log(value)
|
||||
const isDarkMode = await window.darkMode.toggle(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加GPT地址或者模型
|
||||
*/
|
||||
async function addGptOption() {
|
||||
// 判断当前数据是不是存在
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = 600;
|
||||
let dialogHeight = 450;
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
title: "添加GPT地址或者模型",
|
||||
content: () => h(AddGptOption, {}),
|
||||
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px`,
|
||||
maskClosable: false,
|
||||
onClose: async () => {
|
||||
// 刷新界面数据
|
||||
await InitGptOptions();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试当前GPT是不是可以链接成功
|
||||
*/
|
||||
async function TestGPTConnection() {
|
||||
loading.value = true;
|
||||
// 测试链接
|
||||
await window.api.TestGPTConnection(JSON.stringify(formValue.value), (value) => {
|
||||
loading.value = false;
|
||||
if (value.code == 0) {
|
||||
window.api.showGlobalMessageDialog({ code: 0, message: "GPT链接失败,错误信息: " + value.message })
|
||||
return;
|
||||
}
|
||||
window.api.showGlobalMessageDialog({ code: 1, message: "gpt链接测试成功,可以正常使用!" })
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择项目文件夹
|
||||
*/
|
||||
async function SelectProjectFolder() {
|
||||
await window.api.selectFolder({ default_paht: toRaw(formValue.value).project_path }, (value) => {
|
||||
if (value.length > 0) {
|
||||
formValue.value.project_path = value[0]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加GPT提示词预设
|
||||
*/
|
||||
async function AddGptPrompt() {
|
||||
// 判断当前数据是不是存在
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = 600;
|
||||
let dialogHeight = window.innerHeight * 0.9;
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
title: "添加GPT提示词预设",
|
||||
content: () => h(AddGptPrompts, { height: dialogHeight }),
|
||||
style: `width : ${dialogWidth}px; height : ${dialogHeight}px; padding-right : 3px `,
|
||||
maskClosable: false,
|
||||
onClose: () => {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
formRef,
|
||||
ChangeMode,
|
||||
openGptBuyUrl,
|
||||
railStyle,
|
||||
handleValidateButtonClick,
|
||||
rules,
|
||||
SwitchTranslate,
|
||||
translation_options,
|
||||
gpt_model_options,
|
||||
gpt_options,
|
||||
show,
|
||||
formValue,
|
||||
addGptOption,
|
||||
TestGPTConnection,
|
||||
loading,
|
||||
SelectProjectFolder,
|
||||
AddGptPrompt,
|
||||
character_select_model_options,
|
||||
}
|
||||
await window.mj.GetTagSelectModel((value) => {
|
||||
character_select_model_options.value = value.data
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
onMounted(async () => {
|
||||
await InitGptOptions()
|
||||
})
|
||||
|
||||
let translation_options = [
|
||||
{
|
||||
label: '百度翻译',
|
||||
value: 'https://fanyi-api.baidu.com/api/trans/vip/translate'
|
||||
},
|
||||
{
|
||||
label: '火山引擎',
|
||||
value: 'https://translate.volcengineapi.com?'
|
||||
},
|
||||
{
|
||||
label: '腾讯翻译',
|
||||
value: 'https://tmt.tencentcloudapi.com'
|
||||
},
|
||||
{
|
||||
label: '阿里翻译',
|
||||
value: 'https://mt.cn-hangzhou.aliyuncs.com'
|
||||
}
|
||||
]
|
||||
|
||||
// 切换翻译服务商事件
|
||||
function SwitchTranslate(value, option) {
|
||||
// 将之前的数据全部删除
|
||||
formValue.value.translation_app_id = null
|
||||
formValue.value.translation_secret = null
|
||||
}
|
||||
|
||||
let ruleObj = (errorMessage) => {
|
||||
return [
|
||||
{
|
||||
required: true,
|
||||
validator(rule, value) {
|
||||
if (value == null || value == '') return new Error(errorMessage)
|
||||
return true
|
||||
},
|
||||
trigger: ['input', 'blur', 'change']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
let rules = {
|
||||
draft_path: ruleObj('必填剪映草稿地址'),
|
||||
project_path: ruleObj('必填项目地址'),
|
||||
project_name: ruleObj('必填项目名称'),
|
||||
task_number: ruleObj('必填后台并行任务数'),
|
||||
gpt_business: ruleObj('必填GPT接口服务商'),
|
||||
gpt_key: ruleObj('必填GPT Key'),
|
||||
gpt_model: ruleObj('必填GPT模型'),
|
||||
gpt_count: ruleObj('必填自动推理上下文行数'),
|
||||
translation_secret: ruleObj('必填产品密钥'),
|
||||
translation_app_id: ruleObj('必填APP ID'),
|
||||
translation_business: ruleObj('必填翻译服务商')
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存配置信息
|
||||
*/
|
||||
function handleValidateButtonClick(e) {
|
||||
e.preventDefault()
|
||||
formRef.value?.validate((errors) => {
|
||||
if (errors) {
|
||||
message.error('请检查必填字段')
|
||||
return
|
||||
}
|
||||
// 保存文件
|
||||
window.api.ModifySampleSetting(JSON.stringify(toRaw(formValue.value)), (value) => {
|
||||
if (value.code == 1) {
|
||||
window.api.getSettingDafultData((value) => {
|
||||
window.config = value
|
||||
})
|
||||
window.api.showGlobalMessageDialog({ code: 1, message: value.message })
|
||||
} else {
|
||||
window.api.showGlobalMessageDialog({ code: 0, message: value.message })
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
let railStyle = (focused, checked) => {
|
||||
const style = {}
|
||||
if (checked) {
|
||||
style.background = '#f3a694'
|
||||
if (focused) {
|
||||
style.boxShadow = '0 0 0 2px #f3a694'
|
||||
}
|
||||
} else {
|
||||
style.background = '#775039'
|
||||
if (focused) {
|
||||
style.boxShadow = '0 0 0 2px #775039'
|
||||
}
|
||||
}
|
||||
return style
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开购买GPT的地址
|
||||
*/
|
||||
async function openGptBuyUrl() {
|
||||
window.api.openGptBuyUrl(toRaw(formValue.value.gpt_business))
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换主题
|
||||
* @param {*} value 主题名称
|
||||
*/
|
||||
async function ChangeMode(value) {
|
||||
debugger
|
||||
console.log(value)
|
||||
const isDarkMode = await window.darkMode.toggle(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加GPT地址或者模型
|
||||
*/
|
||||
async function addGptOption() {
|
||||
// 判断当前数据是不是存在
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = 600
|
||||
let dialogHeight = 450
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
title: '添加GPT地址或者模型',
|
||||
content: () => h(AddGptOption, {}),
|
||||
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px`,
|
||||
maskClosable: false,
|
||||
onClose: async () => {
|
||||
// 刷新界面数据
|
||||
await InitGptOptions()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试当前GPT是不是可以链接成功
|
||||
*/
|
||||
async function TestGPTConnection() {
|
||||
loading.value = true
|
||||
// 测试链接
|
||||
await window.api.TestGPTConnection(JSON.stringify(formValue.value), (value) => {
|
||||
loading.value = false
|
||||
if (value.code == 0) {
|
||||
window.api.showGlobalMessageDialog({
|
||||
code: 0,
|
||||
message: 'GPT链接失败,错误信息: ' + value.message
|
||||
})
|
||||
return
|
||||
}
|
||||
window.api.showGlobalMessageDialog({ code: 1, message: 'gpt链接测试成功,可以正常使用!' })
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择项目文件夹
|
||||
*/
|
||||
async function SelectProjectFolder() {
|
||||
await window.api.selectFolder(
|
||||
{ default_paht: toRaw(formValue.value).project_path },
|
||||
(value) => {
|
||||
if (value.length > 0) {
|
||||
formValue.value.project_path = value[0]
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加GPT提示词预设
|
||||
*/
|
||||
async function AddGptPrompt() {
|
||||
// 判断当前数据是不是存在
|
||||
// 处理数据。获取当前的所有的数据
|
||||
let dialogWidth = 600
|
||||
let dialogHeight = window.innerHeight * 0.9
|
||||
// ImportWordAndSrt
|
||||
dialog.create({
|
||||
showIcon: false,
|
||||
closeOnEsc: false,
|
||||
title: '添加GPT提示词预设',
|
||||
content: () => h(AddGptPrompts, { height: dialogHeight }),
|
||||
style: `width : ${dialogWidth}px; height : ${dialogHeight}px; padding-right : 3px `,
|
||||
maskClosable: false,
|
||||
onClose: () => {}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
formRef,
|
||||
ChangeMode,
|
||||
openGptBuyUrl,
|
||||
railStyle,
|
||||
handleValidateButtonClick,
|
||||
rules,
|
||||
SwitchTranslate,
|
||||
translation_options,
|
||||
gpt_model_options,
|
||||
gpt_options,
|
||||
show,
|
||||
formValue,
|
||||
addGptOption,
|
||||
TestGPTConnection,
|
||||
loading,
|
||||
SelectProjectFolder,
|
||||
AddGptPrompt,
|
||||
character_select_model_options
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user