3.1.9 2024.10.28

1. (聚合推文)MJ反推、SD反推 添加剪映分镜
2. (聚合推文)完善SD反推分类(界面同MJ反推,些许不一致)
3. (聚合推文)完成一键合成视频(单个和批量)
4. 修改聚合推文进入界面小说批次任务表格样式
5. (聚合推文)完善一键重置
6. (聚合推文)完善一键删除
This commit is contained in:
2024-10-28 18:38:11 +08:00
parent 0c5988ed41
commit 22cfe65dde
78 changed files with 4982 additions and 2440 deletions
@@ -1,300 +0,0 @@
<template>
<div>
<n-dropdown trigger="hover" :options="reverseOptions" @select="ReverseSelect">
<n-button size="tiny" :color="softwareStore.SoftColor.BROWN_YELLOW" @click="AddReversePrompt">
单句反推
</n-button>
</n-dropdown>
<n-dropdown trigger="hover" :options="tranlateOptions" @select="ReverseSelect">
<n-button
style="margin-left: 5px"
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="TranslateOne('translate_chinese')"
>
英文 2 中文
</n-button>
</n-dropdown>
<n-button
style="margin-left: 5px"
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="SelectReversePrompt"
>
重选反推提示词
</n-button>
</div>
</template>
<script>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch, h } from 'vue'
import { useMessage, useDialog, NDropdown, NButton } from 'naive-ui'
import { useSoftwareStore } from '../../../../../stores/software'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import { TranslateType } from '../../../../../define/enum/translate'
import { ContainsChineseOrPunctuation } from '../../../../../define/Tools/common'
import ReSelectReversePrompt from '../MJReverse/ReSelectReversePrompt.vue'
import { OperateBookType } from '../../../../../define/enum/bookEnum'
import { isEmpty } from 'lodash'
import { DEFINE_STRING } from '../../../../../define/define_string'
export default defineComponent({
components: { NDropdown, NButton },
props: ['initData', 'index'],
setup(props) {
let message = useMessage()
let dialog = useDialog()
let data = ref(props.initData)
let index = ref(props.index)
let softwareStore = useSoftwareStore()
let reverseManageStore = useReverseManageStore()
onMounted(async () => {})
/**
* 单句反推提示词
*/
async function AddReversePrompt() {
let res = await window.book.AddReversePrompt(
data.value.id,
OperateBookType.BOOKTASKDETAIL,
null
)
if (res.code == 0) {
message.error(res.message)
} else {
message.success('添加反推任务成功')
}
}
async function AddNextReversePrompt() {
let res = await window.book.AddReversePrompt(
data.value.id,
OperateBookType.UNDERBOOKTASK,
reverseManageStore.selectBook.type
)
if (res.code == 0) {
message.error(res.message)
} else {
message.success('添加反推任务成功')
}
}
/**
* 提示词菜单下拉操作
*/
async function ReverseSelect(key) {
switch (key) {
case 'remove_reverse': // 删除反推提示词
let res = await window.book.ResetGptReverseData(
data.value.id,
OperateBookType.BOOKTASKDETAIL,
reverseManageStore.selectBook.type
)
if (res.code == 0) {
message.error(res.message)
} else {
reverseManageStore.selectBookTaskDetail[props.index].gptPrompt = undefined
reverseManageStore.selectBookTaskDetail[props.index].reversePrompt = undefined
message.success('删除反推数据成功')
}
break
case 'translate_english': // 中文 2 英文
await TranslateOne('translate_english')
break
case 'down_translate_chinese': // 下翻译中文
await TranslateOne('down_translate_chinese')
break
case 'down_translate_english': // 下翻译英文
await TranslateOne('down_translate_english')
break
case 'down_reverse':
await AddNextReversePrompt()
break
default:
message.error('未知的操作类型')
break
}
}
// 处理翻译英文的数据
function TranslateOneParams(from, to) {
let translateData = []
if (!isEmpty(data.value.gptPrompt)) {
translateData.push({
text: data.value.gptPrompt,
from: from,
to: to,
type: TranslateType.GPT_PROMPT_TRANSLATE,
isSplit: false, // 该参数设置为true时,会将文本按照标点符号分割成多个句子进行翻译
bookTaskDetailId: data.value.id,
responseMessgeName: DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN
})
} else {
let reversePrompt = data.value.reversePrompt
if (reversePrompt) {
reversePrompt.forEach((item) => {
let temp_obj = undefined
if (from == 'zh' && to == 'en') {
// 判断是不是有中文
if (!ContainsChineseOrPunctuation(item.promptCN ? item.promptCN : item.prompt)) {
return
}
}
temp_obj = {
text: item.prompt,
from: from,
to: to,
type: TranslateType.REVERSE_PROMPT_TRANSLATE,
isSplit: false, // 该参数设置为true时,会将文本按照标点符号分割成多个句子进行翻译
bookTaskDetailId: data.value.id,
reversePromptId: item.id,
responseMessgeName: DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN
}
translateData.push(temp_obj)
})
}
}
return translateData
}
// 处理批次的翻译
function TranslateBatchParams(from, to) {
let translateData = []
for (let i = index.value; i < reverseManageStore.selectBookTaskDetail.length; i++) {
const element = reverseManageStore.selectBookTaskDetail[i]
// 这边判断GPT提示词是不是存在,存在的话翻译GPT提示词
if (!isEmpty(element.gptPrompt)) {
translateData.push({
text: element.gptPrompt,
from: from,
to: to,
type: TranslateType.GPT_PROMPT_TRANSLATE,
isSplit: false, // 该参数设置为true时,会将文本按照标点符号分割成多个句子进行翻译
bookTaskDetailId: element.id,
responseMessgeName: DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN
})
} else {
let reversePrompt = element.reversePrompt
if (reversePrompt) {
reversePrompt.forEach((item) => {
if (from == 'zh' && to == 'en') {
// 判断是不是有中文
if (!ContainsChineseOrPunctuation(item.promptCN ? item.promptCN : item.prompt)) {
return
}
}
let temp_obj = {
text: item.prompt,
from: from,
to: to,
type: TranslateType.REVERSE_PROMPT_TRANSLATE,
isSplit: false, // 该参数设置为true时,会将文本按照标点符号分割成多个句子进行翻译
bookTaskDetailId: element.id,
reversePromptId: item.id,
responseMessgeName: DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN
}
translateData.push(temp_obj)
})
}
}
}
return translateData
}
// 单句翻译
async function TranslateOne(key) {
let translateData = []
switch (key) {
case 'translate_english':
translateData = TranslateOneParams('zh', 'en')
break
case 'translate_chinese':
translateData = TranslateOneParams('en', 'zh')
break
case 'down_translate_english':
translateData = TranslateBatchParams('zh', 'en')
break
case 'down_translate_chinese':
translateData = TranslateBatchParams('en', 'zh')
break
default:
message.error('未知的操作类型')
break
}
if (translateData.length <= 0) {
message.error('没有需要翻译的数据')
return
}
softwareStore.spin.spinning = true
softwareStore.spin.tip = `翻译中 ... 0 / ${translateData.length}`
// 开始翻译
let res = await window.translate.TranslateNowReturn(translateData)
softwareStore.spin.spinning = false
window.api.showGlobalMessageDialog(res)
}
/**
* 重选反推提示词
*/
async function SelectReversePrompt() {
// 判断当前是不是又反推提示词
if (!data.value.reversePrompt || data.value.reversePrompt.length <= 0) {
message.error('当前没有反推提示词')
return
}
// ImportWordAndSrt
dialog.create({
showIcon: false,
title: `重选MJ反推提示词 ${data.value.name}`,
closeOnEsc: false,
content: () =>
h(ReSelectReversePrompt, {
reversePrompts: data.value.reversePrompt,
index: index.value
}),
style: `width : 750px;`,
maskClosable: false
})
}
return {
index,
data,
softwareStore,
ReverseSelect,
TranslateOne,
reverseManageStore,
SelectReversePrompt,
AddReversePrompt,
reverseOptions: [
{
label: '下推理',
key: 'down_reverse'
},
{
label: '删除反推提示词',
key: 'remove_reverse'
}
],
tranlateOptions: [
{
label: '中文 2 英文',
key: 'translate_english'
},
{
label: '下翻译英文',
key: 'down_translate_english'
},
{
label: '下翻译中文',
key: 'down_translate_chinese'
}
]
}
}
})
</script>
@@ -1,165 +0,0 @@
<template>
<div style="display: flex; justify-content: space-between; white-space: nowrap">
<div style="display: flex">
<div>反推/GPT提示词</div>
<n-button
v-if="reverseManageStore.selectBook.type == bookType.MJ_REVERSE"
type="text"
:color="softwareStore.SoftColor.ZHUYANTUO"
size="tiny"
style="margin-left: 10px"
@click="SelectPromptIndex"
>选择提示词</n-button
><n-button
v-if="reverseManageStore.selectBook.type == bookType.MJ_REVERSE"
type="text"
:color="softwareStore.SoftColor.ZHUYANTUO"
size="tiny"
style="margin-left: 5px"
@click="SelectStyle"
>风格</n-button
>
</div>
<div>
<n-popover trigger="hover">
<template #trigger>
<n-button
color="#7c461e"
@click="SelectReversePromptAndReplace"
text
style="font-size: 24px"
>
<n-icon>
<FindReplaceRound />
</n-icon>
</n-button>
</template>
<span>批量替换反推提示词</span>
</n-popover>
</div>
</div>
</template>
<script>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, h, watch } from 'vue'
import { useMessage, useDialog, NButton, NPopover, NIcon } from 'naive-ui'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import { BookRepalceDataType, BookType } from '../../../../../define/enum/bookEnum'
import { useSoftwareStore } from '../../../../../stores/software'
import SelectMJReversePrompt from '../MJReverse/SelectMJReversePrompt.vue'
import SelectImageStyle from '../../Components/SelectImageStyle.vue'
import FindReplaceRound from '../../Icon/FindReplaceRound.vue'
import DatatableHeaderAfterGptSelectAndReplace from './DatatableHeaderAfterGptSelectAndReplace.vue'
export default defineComponent({
components: { NButton, NPopover, FindReplaceRound, NIcon },
setup() {
let message = useMessage()
let reverseManageStore = useReverseManageStore()
let softwareStore = useSoftwareStore()
let bookType = ref(BookType)
let dialog = useDialog()
let selectStyleRef = ref(null)
let da = undefined
/**
* 选择MJ反推提示词。用于生图
*/
async function SelectPromptIndex() {
// 判断是不是MJ反推,判断是不是所有的都有提示词
if (reverseManageStore.selectBook.type != BookType.MJ_REVERSE) {
message.error('只有MJ反推可以使用该按钮')
return
}
let hasReversePrompt = false
// 判断是不是所有的都有提示词,只要有一个有,就可以
for (let index = 0; index < reverseManageStore.selectBookTaskDetail.length; index++) {
const element = reverseManageStore.selectBookTaskDetail[index]
if (element.reversePrompt && element.reversePrompt.length > 0) {
hasReversePrompt = true
break
}
}
if (!hasReversePrompt) {
message.error('请先进行MJ反推')
return
}
dialog.create({
title: '选择反推提示词',
content: () => h(SelectMJReversePrompt),
style: 'width : 500px',
showIcon: false
})
}
// 选择风格
async function SelectStyle() {
// 先获取风格
// 判断当前数据是不是存在
// 处理数据。获取当前的所有的数据
let dialogWidth = window.innerWidth * 0.8
let dialogHeight = window.innerHeight * 0.9
// ImportWordAndSrt
dialog.create({
showIcon: false,
closeOnEsc: false,
content: () =>
h(SelectImageStyle, {
height: dialogHeight,
ref: selectStyleRef,
imageStyle: reverseManageStore.selectBookTask.imageStyle,
customizeImageStyle: reverseManageStore.selectBookTask.customizeImageStyle
}),
style: `width : ${dialogWidth}px; height : ${dialogHeight}px`,
maskClosable: false,
onClose: async () => {
console.log(selectStyleRef)
// 将数据保存到当前的数据中
// reverseManageStore.selectBookTask.styleList = toRaw(selectStyleRef.value.selectStyle)
// 保存当前的风格到数据库
let res = await window.book.SaveImageStyle(
toRaw(selectStyleRef.value.selectStyle),
reverseManageStore.selectBookTask.id
)
if (res.code == 0) {
message.error(res.message)
return
}
reverseManageStore.selectBookTask.imageStyle = res.data.imageStyle
reverseManageStore.selectBookTask.customizeImageStyle = res.data.customizeImageStyle
message.success('保存成功')
}
})
}
async function SelectReversePromptAndReplace() {
if (da) {
return
}
da = dialog.create({
title: '批量查询替换反推提示词',
showIcon: false,
maskClosable: false,
content: () =>
h(DatatableHeaderAfterGptSelectAndReplace, { type: BookRepalceDataType.GPT_PROMPT }),
onClose: () => {
da = undefined
}
})
}
return {
reverseManageStore,
bookType,
softwareStore,
SelectPromptIndex,
SelectStyle,
selectStyleRef,
SelectReversePromptAndReplace
}
}
})
</script>
@@ -1,215 +0,0 @@
<template>
<div>
<n-dropdown trigger="hover" :options="mergeOptions" @select="MergePrompt">
<n-button
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="MergePrompt(undefined)"
>
单句合并
</n-button>
</n-dropdown>
<n-button
style="margin-left: 5px"
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="SingleGenerateImage"
>
单句生图
</n-button>
<n-button
style="margin-left: 5px"
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="UnderGenerateImage"
>
下生图
</n-button>
<n-button
style="margin-left: 5px"
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="ImportMJImageUrl"
>
导入图片
</n-button>
</div>
<n-input
type="textarea"
size="tiny"
@input="InputDebounced"
v-model:value="data.prompt"
:autosize="{ minRows: 6, maxRows: 6 }"
></n-input>
</template>
<script>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch, h } from 'vue'
import { useMessage, useDialog, NInput, NButton, NDropdown } from 'naive-ui'
import { useSoftwareStore } from '../../../../../stores/software'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import { OperateBookType } from '../../../../../define/enum/bookEnum'
import { BookImageCategory } from '../../../../../define/enum/bookEnum'
import { debounce } from 'lodash'
import InputDialogContent from '../../Original/Components/InputDialogContent.vue'
import { DEFINE_STRING } from '../../../../../define/define_string'
export default defineComponent({
components: { NInput, NButton, NDropdown },
props: ['initData', 'index'],
setup(props) {
let message = useMessage()
let softwareStore = useSoftwareStore()
let reverseManageStore = useReverseManageStore()
let data = ref(props.initData)
let image_url_ref = ref(null)
let dialog = useDialog()
onMounted(async () => {})
// 合并提示词
async function MergePrompt(key) {
let type = key
if (!key) {
if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.MJ) {
type = 'mj_merge'
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.SD) {
type = 'sd_merge'
} else {
type = 'mj_merge'
}
}
// 开始进行合并,调用不同的合并模式
// 合并之前,要确认保存
softwareStore.spin.spinning = true
softwareStore.spin.tip = '合并命令中。。。'
let res = await window.book.MergePrompt(data.value.id, type, OperateBookType.BOOKTASKDETAIL)
softwareStore.spin.spinning = false
// 这边对返回的数据进行处理
if (res.code == 0) {
message.error(res.message)
return
}
for (let i = 0; i < res.data.length; i++) {
const element = res.data[i]
let selectBookDetailIndex = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == element.id
)
reverseManageStore.selectBookTaskDetail[selectBookDetailIndex].prompt = element.prompt
}
message.success(res.message)
}
// 单个出图
async function SingleGenerateImage() {
let res = undefined
if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.MJ) {
res = await window.mj.AddMJGenerateImageTask(
data.value.id,
OperateBookType.BOOKTASKDETAIL,
DEFINE_STRING.BOOK.MJ_IMAGE_GENERATE_RETURN
)
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.SD) {
// res = await window.sd.SingleGenerateImage(data.value.id, OperateBookType.BOOKTASKDETAIL)
message.error('暂不支该出图模式')
} else {
message.error('未知的出图模式')
return
}
if (res.code == 0) {
message.error(res.message)
return
}
message.success(res.message)
}
// 下生图
async function UnderGenerateImage() {
let res = undefined
if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.MJ) {
res = await window.mj.AddMJGenerateImageTask(
data.value.id,
OperateBookType.UNDERBOOKTASK,
DEFINE_STRING.BOOK.MJ_IMAGE_GENERATE_RETURN
)
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.SD) {
// res = await window.sd.SingleGenerateImage(data.value.id, OperateBookType.UNDERBOOKTASK)
message.error('暂不支该出图模式')
} else {
message.error('未知的出图模式')
return
}
if (res.code == 0) {
message.error(res.message)
return
}
message.success(res.message)
}
let InputDebounced = debounce(handleInput, 1000)
async function handleInput() {
let res = await window.db.UpdateBookTaskDetailData(data.value.id, {
prompt: data.value.prompt
})
if (res.code == 0) {
message.error(res.message)
}
}
/**
* 写入图片的链接,将图片链接下载,并且分割
*/
async function ImportMJImageUrl() {
// 判断当前数据是不是存在
// 处理数据。获取当前的所有的数据
let dialogWidth = 400
let dialogHeight = 150
let da = dialog.create({
title: '添加图片链接/本地地址',
showIcon: false,
closeOnEsc: false,
content: () =>
h(InputDialogContent, {
ref: image_url_ref,
initData: null,
placeholder: '请输入图片链接/本地地址'
}),
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px`,
maskClosable: false,
onClose: async () => {
da?.destroy()
let row_image_url = image_url_ref.value.data
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在下载图片/分割图片中。。。'
let res = await window.book.DownloadImageUrlAndSplit(data.value.id, row_image_url)
softwareStore.spin.spinning = false
if (res.code == 0) {
message.error(res.message)
return
}
data.value.outImagePath = res.data.outImagePath
data.value.subImagePath = res.data.subImagePath
message.success(res.message)
}
})
}
return {
softwareStore,
reverseManageStore,
InputDebounced,
SingleGenerateImage,
MergePrompt,
data,
image_url_ref,
ImportMJImageUrl,
UnderGenerateImage,
mergeOptions: [
{ label: 'MJ模式合并', key: 'mj_merge' },
{ label: 'SD模式合并', key: 'sd_merge' }
]
}
}
})
</script>
@@ -33,7 +33,7 @@
</n-button>
</template>
<script>
<script setup>
import { ref, onMounted, defineComponent, h } from 'vue'
import { useMessage, NButton, useDialog } from 'naive-ui'
import { useReverseManageStore } from '../../../../../../stores/reverseManage.ts'
@@ -41,175 +41,173 @@ import { useSoftwareStore } from '../../../../../../stores/software.ts'
import { BookType, OperateBookType } from '../../../../../../define/enum/bookEnum.ts'
import ManageBookTaskGenerateInformation from './ManageBookTaskGenerateInformation.vue'
export default defineComponent({
components: {
NButton
},
let props = defineProps({
bookTask: undefined
})
props: ['bookTask'],
setup(props) {
let message = useMessage()
let dialog = useDialog()
let bookTask = ref(props.bookTask)
console.log('bookTask', bookTask.value)
let reverseManageStore = useReverseManageStore()
let softwareStore = useSoftwareStore()
let message = useMessage()
let dialog = useDialog()
let bookTask = ref(props.bookTask)
console.log('bookTask', bookTask.value)
let reverseManageStore = useReverseManageStore()
let softwareStore = useSoftwareStore()
onMounted(async () => {})
onMounted(async () => {})
/**
* 重置小说数据
* @param e
*/
async function ReSetBookTaskDetail(e) {
e.stopPropagation()
dialog.warning({
title: '重置小说任务',
positiveText: '确定',
negativeText: '取消',
content:
'确定要重置小说任务吗?该操作不可逆,会将对应的批次任务的数据清空,分镜数据全部删除,请谨慎操作!',
onPositiveClick: async () => {
let res = await window.book.ReSetBookTask(bookTask.value.id)
if (res.code == 1) {
message.success('重置小说任务成功')
} else {
message.error(res.message)
}
}
})
/**
* 重置小说数据
* @param e
*/
async function ReSetBookTaskDetail(e) {
e.stopPropagation()
dialog.warning({
title: '重置小说任务',
positiveText: '确定',
negativeText: '取消',
content:
'确定要重置小说任务吗?该操作不可逆,会将对应的批次任务的数据清空,分镜数据全部删除,请谨慎操作!',
onPositiveClick: async () => {
let res = await window.book.ReSetBookTask(bookTask.value.id)
if (res.code == 1) {
message.success('重置小说任务成功')
} else {
message.error(res.message)
}
}
})
}
/**
* 删除小说任务
*/
async function DeleteBookTask(e) {
e.stopPropagation()
dialog.warning({
title: '删除小说任务',
positiveText: '确定',
negativeText: '取消',
content:
'确定要删除小说任务吗?该操作不可逆,会将对应的批次任务数据和分镜数据全部删除,请谨慎操作!',
onPositiveClick: async () => {
let res = await window.book.DeleteBookTask(bookTask.value.id)
if (res.code == 1) {
// 加载任务列表
let bookTaskRes = await reverseManageStore.GetBookTaskDataFromDB({
bookId: reverseManageStore.selectBook.id
})
softwareStore.spin.spinning = false
if (bookTaskRes.code == 0) {
message.error(bookTaskRes.message)
return
}
// 删除成功
message.success('删除小说任务并刷新数据成功')
} else {
message.error(res.message)
}
/**
* 删除小说任务
*/
async function DeleteBookTask(e) {
e.stopPropagation()
dialog.warning({
title: '删除小说任务',
positiveText: '确定',
negativeText: '取消',
content:
'确定要删除小说任务吗?该操作不可逆,会将对应的批次任务数据和分镜数据全部删除,请谨慎操作!',
onPositiveClick: async () => {
let res = await window.book.DeleteBookTask(bookTask.value.id)
if (res.code == 1) {
// 加载任务列表
let bookTaskRes = await reverseManageStore.GetBookTaskDataFromDB({
bookId: reverseManageStore.selectBook.id
})
softwareStore.spin.spinning = false
if (bookTaskRes.code == 0) {
message.error(bookTaskRes.message)
return
}
})
// 删除成功
message.success('删除小说任务并刷新数据成功')
} else {
message.error(res.message)
}
}
})
}
async function hdImageFunc(id, operateBookType) {
let da = dialog.warning({
title: '高清提示',
content: `是否确认高清,当前的高清倍数为 ${softwareStore.globalSetting.hdScale} 倍,是否继续?`,
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
da.destroy()
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在高清中。。。'
let res = await window.book.HDImage(
id,
softwareStore.globalSetting.hdScale ?? 2,
operateBookType
)
softwareStore.spin.spinning = false
if (res.code == 1) {
message.success('高清成功')
} else {
message.error(res.message)
}
}
})
}
/**
* 高清图片
*/
async function HDImage(e) {
e.stopPropagation()
async function hdImageFunc(id, operateBookType) {
let da = dialog.warning({
title: '高清提示',
content: `是否确认高清,当前的高清倍数为 ${softwareStore.globalSetting.hdScale} 倍,是否继续?`,
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
da.destroy()
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在进行高清检查。。。'
let checkImage = await window.book.CheckImageFileSize(
bookTask.value.id,
10240,
OperateBookType.BOOKTASK
softwareStore.spin.tip = '正在高清中。。。'
let res = await window.book.HDImage(
id,
softwareStore.globalSetting.hdScale ?? 2,
operateBookType
)
softwareStore.spin.spinning = false
if (checkImage.code == 0) {
message.error(checkImage.message)
return
}
// 高清检查完成
if (checkImage.data && checkImage.data.length > 0) {
// 出现了图片大的,用户判断是不是需要高清
let msg = checkImage.data.map((item, index) => {
return item.outImagePath + '\n'
})
dialog.warning({
title: '高清警告',
content: '下面的图片大于10MB,是否继续高清?' + '\n' + msg,
positiveText: '确定',
negativeText: '取消',
maskClosable: false,
onPositiveClick: async () => {
alert('确认高清')
await hdImageFunc(bookTask.value.id, OperateBookType.BOOKTASK)
}
})
if (res.code == 1) {
message.success('高清成功')
} else {
// 没有就直接高清
message.error(res.message)
}
}
})
}
/**
* 高清图片
*/
async function HDImage(e) {
e.stopPropagation()
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在进行高清检查。。。'
let checkImage = await window.book.CheckImageFileSize(
bookTask.value.id,
10240,
OperateBookType.BOOKTASK
)
softwareStore.spin.spinning = false
if (checkImage.code == 0) {
message.error(checkImage.message)
return
}
// 高清检查完成
if (checkImage.data && checkImage.data.length > 0) {
// 出现了图片大的,用户判断是不是需要高清
let msg = checkImage.data.map((item, index) => {
return item.outImagePath + '\n'
})
dialog.warning({
title: '高清警告',
content: '下面的图片大于10MB,是否继续高清?' + '\n' + msg,
positiveText: '确定',
negativeText: '取消',
maskClosable: false,
onPositiveClick: async () => {
alert('确认高清')
await hdImageFunc(bookTask.value.id, OperateBookType.BOOKTASK)
}
}
/**
* 生成草稿
*/
async function ClipDraft(e) {
e.stopPropagation()
dialog.info({
closeOnEsc: false,
title: `生成草稿前检查 ${bookTask.value.name}`,
maskClosable: false,
content: () =>
h(ManageBookTaskGenerateInformation, { bookTask: bookTask.value, type: 'bookTask' })
})
}
/**
* 合成视频
*/
async function GenerateVideo(e) {
e.stopPropagation()
message.error('该功能暂不可用')
}
return {
bookTask,
reverseManageStore,
ClipDraft,
GenerateVideo,
softwareStore,
ReSetBookTaskDetail,
DeleteBookTask,
HDImage
}
})
} else {
// 没有就直接高清
await hdImageFunc(bookTask.value.id, OperateBookType.BOOKTASK)
}
})
}
/**
* 生成草稿
*/
async function ClipDraft(e) {
e.stopPropagation()
dialog.info({
closeOnEsc: false,
title: `生成草稿前检查 ${bookTask.value.name}`,
maskClosable: false,
content: () =>
h(ManageBookTaskGenerateInformation, {
bookTask: bookTask.value,
type: 'bookTask',
optionType: 'draft'
})
})
}
/**
* 合成视频
*/
async function GenerateVideo(e) {
e.stopPropagation()
dialog.info({
closeOnEsc: false,
title: `合成视频前检查 ${bookTask.value.name}`,
maskClosable: false,
content: () =>
h(ManageBookTaskGenerateInformation, {
bookTask: bookTask.value,
type: 'bookTask',
optionType: 'video'
})
})
}
</script>
@@ -46,7 +46,7 @@
clearable
/>
</n-form-item>
<n-form-item label="选择剪映草稿" path="backgroundMusic">
<n-form-item label="选择剪映草稿" path="backgroundMusic" v-if="optionType != 'video'">
<div>
<div style="color: red">
注意选择的草稿主轨道的图片数量要和当前的相同会生成新的草稿并且只会替换图片保留其余的数据
@@ -67,12 +67,23 @@
>
<n-button type="info" style="margin-left: 10px" @click="SaveVideoData">保存数据</n-button>
</n-form-item>
<div v-if="type == 'bookTask'" style="color: red">注意在生成草稿前要先保存数据</div>
<div v-if="type == 'bookTask'" style="color: red">
注意 生成草稿/合成视频 前要先保存数据
</div>
<div v-else style="color: red">
注意在生成草稿前要先保存数据当前会生成选择的草稿全部会使用上面的参数
注意 生成草稿/合成视频 前要先保存数据当前会生成选择的 草稿/视频全部会使用上面的参数
</div>
<n-form-item style="display: flex; justify-content: flex-end">
<n-button type="info" style="margin-left: 10px" @click="AddJianyingDraft">生成草稿</n-button>
<n-button
v-if="optionType == 'video'"
type="info"
style="margin-left: 10px"
@click="AddGenerateVideoTask"
>添加合成视频任务</n-button
>
<n-button v-else type="info" style="margin-left: 10px" @click="AddJianyingDraft"
>生成草稿</n-button
>
</n-form-item>
</n-form>
</template>
@@ -81,18 +92,21 @@
import { ref, onMounted } from 'vue'
import { useMessage, NForm, NFormItem, NButton, NIcon, NInput, NSelect } from 'naive-ui'
import { FolderOpen } from '@vicons/ionicons5'
import { OperateBookType } from '../../../../../../define/enum/bookEnum'
import { BookTaskStatus, OperateBookType } from '../../../../../../define/enum/bookEnum'
import { useReverseManageStore } from '../../../../../../stores/reverseManage'
let props = defineProps({
bookTask: undefined,
type: undefined,
selectBookTask: []
selectBookTask: [],
optionType: undefined
})
let bookTask = ref(props.bookTask)
let type = ref(props.type)
let optionType = ref(props.optionType)
let backgroundMusicOptions = ref([])
let message = useMessage()
let draftSelect = ref([])
@@ -217,23 +231,78 @@ async function SaveVideoData() {
}
}
/**
* 添加草稿
*/
async function AddJianyingDraft() {
async function AddGenerateVideoTask() {
let res = undefined
if (props.type == 'book') {
let res = await window.book.AddJianyingDraft(
// 单个
res = await window.book.AddGenerateVideoTask(
props.selectBookTask,
OperateBookType.ASSIGNBOOKTASK
)
window.api.showGlobalMessageDialog(res)
if (res.code == 1) {
reverseManageStore.UpdatedBookTaskData(props.selectBookTask, {
status: BookTaskStatus.COMPOSING
})
} else {
reverseManageStore.UpdatedBookTaskData(props.selectBookTask, {
status: BookTaskStatus.COMPOSING_FAIL,
errorMsg: res.message
})
}
} else if (props.type == 'bookTask') {
let res = await window.book.AddJianyingDraft(bookTask.value.id, OperateBookType.BOOKTASK)
window.api.showGlobalMessageDialog(res)
// 批次
res = await window.book.AddGenerateVideoTask(bookTask.value.id, OperateBookType.BOOKTASK)
if (res.code == 1) {
reverseManageStore.UpdatedBookTaskData(bookTask.value.id, {
status: BookTaskStatus.COMPOSING
})
} else {
reverseManageStore.UpdatedBookTaskData(bookTask.value.id, {
status: BookTaskStatus.COMPOSING_FAIL,
errorMsg: res.message
})
}
} else {
message.error('未知的操作类型,请检查')
return
}
window.api.showGlobalMessageDialog(res)
}
/**
* 添加草稿
*/
async function AddJianyingDraft() {
let res = undefined
if (props.type == 'book') {
res = await window.book.AddJianyingDraft(props.selectBookTask, OperateBookType.ASSIGNBOOKTASK)
if (res.code == 1) {
reverseManageStore.UpdatedBookTaskData(props.selectBookTask, {
status: BookTaskStatus.DRAFT_DONE
})
} else {
reverseManageStore.UpdatedBookTaskData(props.selectBookTask, {
status: BookTaskStatus.DRAFT_FAIL,
errorMsg: res.message
})
}
} else if (props.type == 'bookTask') {
res = await window.book.AddJianyingDraft(bookTask.value.id, OperateBookType.BOOKTASK)
if (res.code == 1) {
reverseManageStore.UpdatedBookTaskData(bookTask.value.id, {
status: BookTaskStatus.DRAFT_DONE
})
} else {
reverseManageStore.UpdatedBookTaskData(bookTask.value.id, {
status: BookTaskStatus.DRAFT_FAIL,
errorMsg: res.message
})
}
} else {
message.error('未知的操作类型,请检查')
return
}
window.api.showGlobalMessageDialog(res)
}
let rules = ref({
srtPath: [{ required: true, message: '请选择背景音乐', trigger: ['input', 'blur', 'change'] }],
@@ -1,960 +0,0 @@
<template>
<div style="display: flex; justify-content: space-between; align-items: center">
<div style="display: flex; align-items: center">
<n-button strong secondary @click="RetuenMain" size="small"> 返回 </n-button>
<!-- <n-dropdown trigger="hover" :options="AutoOptions" @select="SelectAutoAction">
<n-button :color="softwareStore.SoftColor.ORANGE" @click="Start" style="margin-left: 5px">
自动开始
</n-button>
</n-dropdown> -->
<n-divider vertical style="height: 30px" />
<n-dropdown trigger="hover" :options="frameOptions" @select="handleSelect">
<n-button
:color="softwareStore.SoftColor.ORANGE"
class="top-button"
size="small"
@click="ActionFrame"
>
开始分镜
</n-button>
</n-dropdown>
<n-dropdown trigger="hover" :options="copywritingOptions" @select="handleSelect">
<n-button
:color="softwareStore.SoftColor.ORANGE"
style="margin-left: 5px"
size="small"
@click="GetCopywriting('all')"
>
开始提取全部文案
</n-button>
</n-dropdown>
<n-dropdown trigger="hover" :options="watermarkOptions" @select="handleSelect">
<n-button
:color="softwareStore.SoftColor.ORANGE"
style="margin-left: 5px"
size="small"
@click="RemoveWatermark"
>
开始去除水印
</n-button>
</n-dropdown>
<n-dropdown trigger="hover" :options="importWordOptions" @select="handleSelect">
<n-button
:color="softwareStore.SoftColor.ORANGE"
style="margin-left: 5px"
size="small"
@click="ImportWordAndSrtFunc"
>
导入文案/SRT
</n-button>
</n-dropdown>
<n-dropdown trigger="hover" :options="reverseOptions" @select="handleSelect">
<n-button
:color="softwareStore.SoftColor.ORANGE"
style="margin-left: 5px"
size="small"
@click="ImageReversePrompt(undefined)"
>
一键反推
</n-button>
</n-dropdown>
<n-dropdown trigger="hover" :options="translateOptions" @select="handleSelect">
<n-button
:color="softwareStore.SoftColor.ORANGE"
style="margin-left: 5px"
size="small"
@click="Translate(undefined)"
>
一键翻译
</n-button>
</n-dropdown>
<n-dropdown trigger="hover" :options="generateOptions" @select="handleSelect">
<n-button
:color="softwareStore.SoftColor.ORANGE"
style="margin-left: 5px"
size="small"
@click="GenerateImageAll"
>
一键生图
</n-button>
</n-dropdown>
<n-dropdown trigger="hover" :options="resetOptions" @select="handleSelect">
<n-button
:color="softwareStore.SoftColor.ORANGE"
style="margin-left: 5px"
size="small"
@click="ResetAllData"
>
重置
</n-button>
</n-dropdown>
<n-button
:color="softwareStore.SoftColor.ORANGE"
style="margin-left: 5px"
size="small"
@click="OpenSettingDialog"
>
设置
</n-button>
<div style="margin-left: 10px">
<MonitorStatus />
</div>
</div>
<div class="right-button">
<n-button
text
strong
:type="softwareStore.show_logger ? 'default' : 'info'"
@click="switchLogger"
>
{{ softwareStore.show_logger ? '隐藏日志' : '显示日志' }}
</n-button>
</div>
</div>
</template>
<script>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch, h } from 'vue'
import { useMessage, NButton, useDialog, NCheckbox, NDropdown, NDivider, NRate } from 'naive-ui'
import { useRouter } from 'vue-router'
import { useSoftwareStore } from '../../../../../stores/software'
import { useReverseManageStore } from '../../../../../stores/reverseManage.ts'
import { isEmpty } from 'lodash'
import VideoCanvas from '../../VideoSubtitle/VideoCanvas.vue'
import { SubtitleSavePositionType } from '../../../../../define/enum/waterMarkAndSubtitle'
import { DEFINE_STRING } from '../../../../../define/define_string'
import Setting from './Setting.vue'
import { BookType, OperateBookType } from '../../../../../define/enum/bookEnum'
import TranslateSetting from '../../Setting/TranslateSetting.vue'
import { TranslateType } from '../../../../../define/enum/translate'
import { ContainsChineseOrPunctuation } from '../../../../../define/Tools/common'
import ImportWordAndSrt from '../../Original/Components/ImportWordAndSrt.vue'
import GetWaterMaskRectangle from '../../Watermark/GetWaterMaskRectangle.vue'
import MonitorStatus from './MonitorStatus.vue'
export default defineComponent({
components: {
NButton,
NCheckbox,
NDropdown,
NDivider,
GetWaterMaskRectangle,
MonitorStatus
},
setup() {
let router = useRouter()
let message = useMessage()
let dialog = useDialog()
let reverseManageStore = useReverseManageStore()
let softwareStore = useSoftwareStore()
// 获取当前这个界面的数据
onMounted(async () => {})
// 返回主页
function RetuenMain() {
router.push('/book_management')
}
// 自动开始
async function AutoAction() {
// 开始自动执行。先分镜,后面在添加任务中
let res_frame = await window.book.AutoAction(reverseManageStore.selectBook.id)
}
// 选择自动开始的操作(停止或者是继续)
async function SelectAutoAction() {}
// 是不是显示日志
async function switchLogger() {
softwareStore.show_logger = !softwareStore.show_logger
}
/**
* 开始分镜
*/
async function ComputeStoryboard() {
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在计算分镜中'
if (isEmpty(reverseManageStore.selectBookTask.id)) {
window.api.showGlobalMessageDialog({
code: 0,
message: '没有找到要执行的任务'
})
return
}
let res_frame = await window.book.ComputeStoryboard(reverseManageStore.selectBook.id)
if (res_frame.code == 0) {
softwareStore.spin.spinning = false
window.api.showGlobalMessageDialog(res_frame)
return
}
// 分镜完成,重新获取一下数据
let getRes = await reverseManageStore.GetBookTaskDataFromDB({
id: reverseManageStore.selectBookTask.id
})
if (getRes.code == 0) {
softwareStore.spin.spinning = false
message.error(getRes.message)
return
}
softwareStore.spin.spinning = false
message.success('重新获取数据成功')
}
// 执行分镜的方法
async function Framing() {
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在分镜中'
if (isEmpty(reverseManageStore.selectBookTask.id)) {
window.api.showGlobalMessageDialog({
code: 0,
message: '没有找到要执行的任务'
})
return
}
let res_frame = await window.book.Framing(reverseManageStore.selectBook.id)
if (res_frame.code == 0) {
softwareStore.spin.spinning = false
window.api.showGlobalMessageDialog(res_frame)
return
}
// 分镜完成,重新获取一下数据
let getRes = await reverseManageStore.GetBookTaskDataFromDB({
id: reverseManageStore.selectBookTask.id
})
if (getRes.code == 0) {
softwareStore.spin.spinning = false
message.error(getRes.message)
return
}
softwareStore.spin.spinning = false
message.success('重新获取数据成功')
}
// 获取文案信息
async function GetCopywriting(type) {
if (isEmpty(reverseManageStore.selectBookTask.id)) {
window.api.showGlobalMessageDialog({
code: 0,
message: '没有找到要执行的任务'
})
return
}
let subtitleSettingRes = await window.write.GetSubtitleSetting()
if (subtitleSettingRes.code == 0) {
message.error(subtitleSettingRes.message)
return
}
let da = dialog.warning({
title: '开始提取文案提示',
content: `即将进行 ${type == 'blank' ? '空白' : '全部'} 文案提取${
type == 'blank' ? '' : ',会重新提取并覆盖旧的文案数据'
},当前的文案提取模式为 ${subtitleSettingRes.data.selectModel} ,是否继续?`,
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
da?.destroy()
softwareStore.spin.spinning = true
softwareStore.spin.tip = `正在使用 ${subtitleSettingRes.data.selectModel} 提取文案,正在准备中。。。`
let copywriting_res = await window.book.GetCopywriting(
reverseManageStore.selectBook.id,
reverseManageStore.selectBookTask.id,
OperateBookType.BOOKTASK,
type == 'blank' ? false : true
)
softwareStore.spin.spinning = false
if (copywriting_res.code == 0) {
message.error(copywriting_res.message)
return
}
// dialog.success({})
message.success('获取全部文案成功')
}
})
}
// 开始去除水印
async function RemoveWatermark() {
if (isEmpty(reverseManageStore.selectBookTask.id)) {
window.api.showGlobalMessageDialog({
code: 0,
message: '没有找到要执行的任务'
})
return
}
let da = dialog.warning({
title: '去除水印提示',
content: '即将去除全部水印,是否继续?',
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
da?.destroy()
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在去除水印中。。。'
let res_frame = await window.book.RemoveWatermark(
reverseManageStore.selectBookTask.id,
OperateBookType.BOOKTASK
)
softwareStore.spin.spinning = false
window.api.showGlobalMessageDialog(res_frame)
}
})
}
// 获取文案信息设置
async function GetCopywritingSetting() {
let dialogHeight = window.innerHeight * 0.9
dialog.create({
showIcon: false,
closeOnEsc: false,
content: () =>
h(VideoCanvas, {
videoWidth: 800,
videoSrc: reverseManageStore.selectBook.oldVideoPath,
height: dialogHeight - 50,
type: SubtitleSavePositionType.SETTING
}),
style: `width : 850px; height : ${dialogHeight}px`,
maskClosable: false,
onClose: () => {}
})
}
// 导出文案
async function ExportCopywriting() {
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在导出文案中...'
let res = await window.book.ExportCopywriting(reverseManageStore.selectBookTask.id)
if (res.code == 0) {
message.error(res.message)
} else {
dialog.success({
title: '导出文案成功',
content: '导出文案成功,是否打开导出的字幕文件',
positiveText: '打开',
negativeText: '取消',
onPositiveClick: () => {
window.system.OpenFile(res.data)
}
})
}
softwareStore.spin.spinning = false
}
// 导入文案
async function ImportCopywriting() {
window.api.SelectFile(['txt'], async (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
let txtPath = value.value
// 这边开始导入
let res = await window.book.ImportCopywriting(
reverseManageStore.selectBook.id,
reverseManageStore.selectBookTask.id,
txtPath
)
if (res.code == 1) {
for (let i = 0; i < res.data.length; i++) {
const element = res.data[i]
let index = reverseManageStore.selectBookTaskDetail.findIndex(
(x) => x.id == element.bookTaskDetailId
)
if (index != -1) {
reverseManageStore.selectBookTaskDetail[index].afterGpt = element.afterGpt
}
}
} else {
window.api.showGlobalMessageDialog(res)
}
})
}
/**
* 获取水印位置
*/
async function GetWatermarkPosition() {
// 开始获取水印位置
// 判断当前数据是不是存在
// 处理数据。获取当前的所有的数据
let dialogWidth = window.innerWidth * 0.7
let dialogHeight = window.innerHeight * 0.9
// ImportWordAndSrt
dialog.create({
showIcon: false,
closeOnEsc: false,
content: () => h(GetWaterMaskRectangle, { width: dialogWidth, height: dialogHeight }),
style: `width : ${dialogWidth}px; height : ${dialogHeight}px`,
maskClosable: false,
onClose: () => {}
})
}
// 一些选择方式
async function handleSelect(key) {
switch (key) {
case 'compute_frame': // 计算分镜
await ComputeStoryboard()
break
case 'framing': // 开始分镜
await Framing()
break
case 'recognizing_blank': // 提取空白文案
await GetCopywriting('blank')
break
case 'recognizing_setting': // 文案位置设置
await GetCopywritingSetting()
break
case 'export_recognizing': // 导出文案
await ExportCopywriting()
break
case 'import_recognizing': // 导入文案
await ImportCopywriting()
break
case 'watermark_position': // 水印位置设置
await GetWatermarkPosition()
break
case 'clear_import_word': // 清除导入文案
await ClearImportWord()
break
case 'mj_reverse': // MJ反推
await ImageReversePrompt(BookType.MJ_REVERSE)
break
case 'sd_reverse': // SD反推
await ImageReversePrompt(BookType.SD_REVERSE)
break
case 'translate_chinese': // 英文翻译为中文
await Translate('translate_chinese')
break
case 'translate_english': // 中文翻译为英文
await Translate('translate_english')
break
case 'translate_setting': // 翻译设置
await Translate('translate_setting')
break
case 'reset_gpt_reverse_data': // 重置反推/GPT提示词
await ResetGptReverseData()
break
case 'reset_merge_prompt': // 重置合并提示词数据
await ResetMergePromptData()
break
case 'reset_Generate_Image': // 重置生成的图片
await ResetGenerateImage()
break
default:
message.error('未知的选项')
}
}
// 重置出的图片
async function ResetGenerateImage() {
dialog.warning({
title: '重置所有图片提示',
content:
'继续操作会重置所有的生成的图片,包括生成的主图和子图,但是并不会删除本地的图片文件,是否继续?',
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
let res = await window.book.ResetGenerateImage(
reverseManageStore.selectBookTask.id,
OperateBookType.BOOKTASK
)
if (res.code == 0) {
message.error(res.message)
} else {
// 前端重置数据
for (let i = 0; i < reverseManageStore.selectBookTaskDetail.length; i++) {
reverseManageStore.selectBookTaskDetail[i].mjMessage = undefined
reverseManageStore.selectBookTaskDetail[i].outImagePath = undefined
reverseManageStore.selectBookTaskDetail[i].subImagePath = undefined
}
message.success('重置所有生成图片成功')
}
}
})
}
// 重置合并提示词数据
async function ResetMergePromptData() {
dialog.warning({
title: '重置合并提示词数据提示',
content: '继续操作会重置所有的合并提示词数据,请确认是不是继续?',
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
let res = await window.book.ResetMergePromptData(
reverseManageStore.selectBookTask.id,
OperateBookType.BOOKTASK
)
if (res.code == 0) {
message.error(res.message)
} else {
// 前端做响应
for (let i = 0; i < reverseManageStore.selectBookTaskDetail.length; i++) {
reverseManageStore.selectBookTaskDetail[i].prompt = undefined
}
message.success('重置所有合并提示词数据成功')
}
}
})
}
/**
* 重置反推/GPT提示词,更具不同的小说类型进行不同的重置
*/
async function ResetGptReverseData() {
dialog.warning({
title: '删除反推提示词警告提示',
content: '继续操作会移除所有的反推提示词数据,注意,是所有,请确认是不是继续?',
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
let res = await window.book.ResetGptReverseData(
reverseManageStore.selectBookTask.id,
OperateBookType.BOOKTASK,
reverseManageStore.selectBook.type
)
if (res.code == 0) {
message.error(res.message)
} else {
// 这个做个前端删除
for (let i = 0; i < reverseManageStore.selectBookTaskDetail.length; i++) {
reverseManageStore.selectBookTaskDetail[i].reversePrompt = undefined
reverseManageStore.selectBookTaskDetail[i].gptPrompt = undefined
}
message.success('删除所有的反推/GPT提示词成功')
}
}
})
}
/**
* 打开设置对话框
*/
async function OpenSettingDialog() {
let dialogWidth = window.innerWidth * 0.8
let dialogHeight = window.innerHeight * 0.95
dialog.create({
showIcon: false,
title: '设置',
content: () => h(Setting, { height: dialogHeight }),
style: `width : ${dialogWidth}px; height : ${dialogHeight}px`,
maskClosable: false
})
}
/**
* MJ反推数据
* @param type 反推类型
*/
async function ImageReversePrompt(type = undefined) {
if (isEmpty(reverseManageStore.selectBookTask.id)) {
window.api.showGlobalMessageDialog({
code: 0,
message: '没有找到要执行的任务'
})
return
}
dialog.warning({
title: '反推提示',
content: `即将进行反推操作,反推方式为 ${
type ? type : reverseManageStore.selectBook.type
} ,是否继续?`,
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
if (!type) {
let bookType = reverseManageStore.selectBook.type
type = bookType
}
if (type != BookType.MJ_REVERSE && type != BookType.SD_REVERSE) {
message.error(`该类型 ${bookType} 的小说不支持反推`)
return
}
// 开始添加
let res = await window.book.AddReversePrompt(
reverseManageStore.selectBookTask.id,
OperateBookType.BOOKTASK,
type
)
if (res.code == 0) {
message.error(res.message)
} else {
message.success('添加所有反推任务成功')
}
}
})
}
/**
* 翻译提示词
* @param key 操作的值,进行分类
*/
async function Translate(key) {
switch (key) {
case undefined:
case null:
message.error('请选择子菜单中的选项')
break
case 'translate_chinese': // 将英文翻译到中文
await TranslateService('en', 'zh')
break
case 'translate_english': // 将中文翻译到英文
await TranslateService('zh', 'en')
break
case 'translate_setting': // 翻译设置
await OpenTranslateSettingDialog()
break
default:
message.error('不支持的操作类型')
break
}
}
/**
* 打开翻译设置弹窗
*/
async function OpenTranslateSettingDialog() {
// 判断当前数据是不是存在
// 处理数据。获取当前的所有的数据
let dialogWidth = window.innerWidth * 0.8
let dialogHeight = window.innerHeight * 0.9
dialog.create({
showIcon: false,
title: '翻译设置',
content: () => h(TranslateSetting),
style: `width : ${dialogWidth}px; height : ${dialogHeight}px`,
maskClosable: false
})
}
/**
* 调用翻译接口
* @param from 源语言
* @param to 目标语言
*/
async function TranslateService(from, to) {
let translateData = []
for (let i = 0; i < reverseManageStore.selectBookTaskDetail.length; i++) {
const element = reverseManageStore.selectBookTaskDetail[i]
if (!isEmpty(element.gptPrompt)) {
translateData.push({
text: element.gptPrompt,
from: from,
to: to,
type: TranslateType.GPT_PROMPT_TRANSLATE,
isSplit: false, // 该参数设置为true时,会将文本按照标点符号分割成多个句子进行翻译
bookTaskDetailId: element.id,
responseMessgeName: DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN
})
} else {
let reversePrompt = element.reversePrompt
if (reversePrompt) {
reversePrompt.forEach((item) => {
if (from == 'zh' && to == 'en') {
// 判断是不是有中文
if (!ContainsChineseOrPunctuation(item.promptCN ? item.promptCN : item.prompt)) {
return
}
}
let temp_obj = {
text: item.promptCN ? item.promptCN : item.prompt,
from: from,
to: to,
type: TranslateType.REVERSE_PROMPT_TRANSLATE,
isSplit: false, // 该参数设置为true时,会将文本按照标点符号分割成多个句子进行翻译
bookTaskDetailId: element.id,
reversePromptId: item.id,
responseMessgeName: DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN
}
translateData.push(temp_obj)
})
}
}
}
if (translateData.length == 0) {
message.error('没有需要翻译的数据')
return
}
softwareStore.spin.spinning = true
softwareStore.spin.tip = `翻译中 ... 0 / ${translateData.length}`
// 开始翻译
let res = await window.translate.TranslateNowReturn(translateData)
softwareStore.spin.spinning = false
window.api.showGlobalMessageDialog(res)
}
/**
* 生成所有图片
*/
async function GenerateImageAll() {
let res = await window.book.GenerateImageAll(
reverseManageStore.selectBookTask.id,
reverseManageStore.selectBookTask.imageCategory
)
if (res.code == 0) {
message.error(res.message)
return
}
message.success(res.message)
}
/**
* 导入文案和SRT
*/
async function ImportWordAndSrtFunc() {
let dialogWidth = window.innerWidth * 0.95
let dialogHeight = window.innerHeight * 0.95
// 这边要处理下数据
if (
reverseManageStore.selectBook.type == BookType.MJ_REVERSE ||
reverseManageStore.selectBook.type == BookType.MJ_REVERSE
) {
if (reverseManageStore.selectBookTaskDetail.length <= 0) {
message.error('反推小说,没有找到对应的分镜数据')
}
}
let tempData = []
for (let i = 0; i < reverseManageStore.selectBookTaskDetail.length; i++) {
const element = reverseManageStore.selectBookTaskDetail[i]
tempData.push({
no: element.no,
id: element.id,
lastId: i == 0 ? '' : reverseManageStore.selectBookTaskDetail[i - 1].id,
word: element.word,
after_gpt: element.afterGpt,
subValue: element.subValue ? element.subValue : [],
name: element.name + '.png',
prompt: element.prompt,
timeLimit: element.timeLimit
})
}
// ImportWordAndSrt
dialog.create({
showIcon: false,
closeOnEsc: false,
content: () =>
h(ImportWordAndSrt, {
initData: tempData,
height: dialogHeight,
type: BookType.MJ_REVERSE
}),
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px`,
maskClosable: false,
onClose: () => {}
})
}
/**
* 清除导入文案
*/
async function ClearImportWord() {
let da = dialog.warning({
title: '清除导入文案提示',
content:
'继续执行该操作会将导入的对齐文案全部清除(包括文案的时间线),并且操作不可逆,是否继续?',
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
da?.destroy()
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在清除导入数据。。。'
let res = await window.book.ClearImportWord(reverseManageStore.selectBookTask.id)
softwareStore.spin.spinning = false
if (res.code == 0) {
message.error(res.message)
} else {
// 这边重置下数据
for (let i = 0; i < res.data.length; i++) {
const element = res.data[i]
let index = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == element.id
)
if (index != -1) {
reverseManageStore.selectBookTaskDetail[index].subValue = undefined
reverseManageStore.selectBookTaskDetail[index].startTime = element.startTime
reverseManageStore.selectBookTaskDetail[index].endTime = element.endTime
reverseManageStore.selectBookTaskDetail[index].timeLimit = element.timeLimit
}
}
message.success('清除导入文案成功')
}
}
})
}
async function ActionFrame() {
message.info('请使用下面菜单中的按钮进行对应的操作')
}
return {
RetuenMain,
AutoAction,
ImportWordAndSrtFunc,
ClearImportWord,
reverseManageStore,
softwareStore,
ActionFrame,
switchLogger,
ComputeStoryboard,
OpenSettingDialog,
GetCopywriting,
RemoveWatermark,
ImageReversePrompt,
ResetGptReverseData,
Translate,
TranslateService,
GenerateImageAll,
handleSelect,
AutoOptions: [
{
label: '停止任务',
value: 'auto_stop'
},
{
label: '继续任务',
value: 'auto_continue'
}
],
frameOptions: [
{
label: '计算分镜',
key: 'compute_frame'
},
{ label: '分镜', key: 'framing' }
],
copywritingOptions: [
{
label: '提取空白文案',
key: 'recognizing_blank'
},
{
label: '提取文案位置',
key: 'recognizing_setting'
},
{
label: '导出文案',
key: 'export_recognizing'
},
{
label: '导入文案',
key: 'import_recognizing'
},
{
label: '停止提取',
key: 'stop_recognizing'
}
],
watermarkOptions: [
{
label: '选择水印位置',
key: 'watermark_position'
},
{
label: '停止去除',
key: 'stop_watermark'
}
],
reverseOptions: [
{
label: 'MJ反推',
key: 'mj_reverse'
},
{
label: 'SD反推',
key: 'sd_reverse',
disabled: reverseManageStore.selectBook.type != BookType.SD_REVERSE
},
{
label: '停止反推',
key: 'stop_reverse'
}
],
translateOptions: [
{
label: '英文 -> 中文',
key: 'translate_chinese'
},
{
label: '中文 -> 英文',
key: 'translate_english'
},
{
label: '翻译设置',
key: 'translate_setting'
},
{
label: '停止翻译',
key: 'translate_stop'
}
],
generateOptions: [
{
label: '停止生图',
key: 'stop_image_generate'
}
],
importWordOptions: [
{
label: '清除导入文案',
key: 'clear_import_word'
}
],
resetOptions: [
{
label: '重置反推/GPT提示词',
key: 'reset_gpt_reverse_data'
},
{
label: '重置合并提示词',
key: 'reset_merge_prompt'
},
{
label: '重置图片',
key: 'reset_Generate_Image'
}
]
}
}
})
</script>
<style lang="css">
.right-button {
display: flex;
justify-content: flex-end;
}
.top-button {
margin-left: 5px;
}
</style>
@@ -35,7 +35,6 @@ export default defineComponent({
props: ['initData', 'index'],
setup(props) {
let data = ref(props.initData)
console.log('data', props.initData, props.index)
onMounted(async () => {})
let InputDebounced = debounce(handleInput, 1000)
@@ -0,0 +1,284 @@
<template>
<div>
<n-dropdown trigger="hover" :options="reverseOptions" @select="ReverseSelect">
<n-button size="tiny" :color="softwareStore.SoftColor.BROWN_YELLOW" @click="AddReversePrompt">
单句反推
</n-button>
</n-dropdown>
<n-dropdown trigger="hover" :options="tranlateOptions" @select="ReverseSelect">
<n-button
style="margin-left: 5px"
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="TranslateOne('translate_chinese')"
>
英文 2 中文
</n-button>
</n-dropdown>
<n-button
v-if="reverseManageStore.selectBook.type == bookType.MJ_REVERSE"
style="margin-left: 5px"
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="SelectReversePrompt"
>
重选反推提示词
</n-button>
</div>
</template>
<script setup>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch, h } from 'vue'
import { useMessage, useDialog, NDropdown, NButton } from 'naive-ui'
import { useSoftwareStore } from '../../../../../stores/software'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import { TranslateType } from '../../../../../define/enum/translate'
import { ContainsChineseOrPunctuation } from '../../../../../define/Tools/common'
import ReSelectReversePrompt from '../MJReverse/ReSelectReversePrompt.vue'
import { BookType, OperateBookType } from '../../../../../define/enum/bookEnum'
import { isEmpty } from 'lodash'
import { DEFINE_STRING } from '../../../../../define/define_string'
let props = defineProps({
initData: undefined,
index: undefined
})
let message = useMessage()
let dialog = useDialog()
let data = ref(props.initData)
let index = ref(props.index)
let softwareStore = useSoftwareStore()
let reverseManageStore = useReverseManageStore()
let bookType = ref(BookType)
onMounted(async () => {})
/**
* 单句反推提示词
*/
async function AddReversePrompt() {
let res = await window.book.AddReversePrompt(data.value.id, OperateBookType.BOOKTASKDETAIL, null)
if (res.code == 0) {
message.error(res.message)
} else {
message.success('添加反推任务成功')
}
}
async function AddNextReversePrompt() {
let res = await window.book.AddReversePrompt(
data.value.id,
OperateBookType.UNDERBOOKTASK,
reverseManageStore.selectBook.type
)
if (res.code == 0) {
message.error(res.message)
} else {
message.success('添加反推任务成功')
}
}
/**
* 提示词菜单下拉操作
*/
async function ReverseSelect(key) {
switch (key) {
case 'remove_reverse': //
let res = await window.book.ResetGptReverseData(
data.value.id,
OperateBookType.BOOKTASKDETAIL,
reverseManageStore.selectBook.type
)
if (res.code == 0) {
message.error(res.message)
} else {
reverseManageStore.selectBookTaskDetail[props.index].gptPrompt = undefined
reverseManageStore.selectBookTaskDetail[props.index].reversePrompt = undefined
message.success('删除反推数据成功')
}
break
case 'translate_english': // 2
await TranslateOne('translate_english')
break
case 'down_translate_chinese': //
await TranslateOne('down_translate_chinese')
break
case 'down_translate_english': //
await TranslateOne('down_translate_english')
break
case 'down_reverse':
await AddNextReversePrompt()
break
default:
message.error('未知的操作类型')
break
}
}
//
function TranslateOneParams(from, to) {
let translateData = []
if (!isEmpty(data.value.gptPrompt)) {
translateData.push({
text: data.value.gptPrompt,
from: from,
to: to,
type: TranslateType.GPT_PROMPT_TRANSLATE,
isSplit: false, // true
bookTaskDetailId: data.value.id,
responseMessgeName: DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN
})
} else {
let reversePrompt = data.value.reversePrompt
if (reversePrompt) {
reversePrompt.forEach((item) => {
let temp_obj = undefined
if (from == 'zh' && to == 'en') {
//
if (!ContainsChineseOrPunctuation(item.promptCN ? item.promptCN : item.prompt)) {
return
}
}
temp_obj = {
text: item.prompt,
from: from,
to: to,
type: TranslateType.REVERSE_PROMPT_TRANSLATE,
isSplit: false, // true
bookTaskDetailId: data.value.id,
reversePromptId: item.id,
responseMessgeName: DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN
}
translateData.push(temp_obj)
})
}
}
return translateData
}
//
function TranslateBatchParams(from, to) {
let translateData = []
for (let i = index.value; i < reverseManageStore.selectBookTaskDetail.length; i++) {
const element = reverseManageStore.selectBookTaskDetail[i]
// GPTGPT
if (!isEmpty(element.gptPrompt)) {
translateData.push({
text: element.gptPrompt,
from: from,
to: to,
type: TranslateType.GPT_PROMPT_TRANSLATE,
isSplit: false, // true
bookTaskDetailId: element.id,
responseMessgeName: DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN
})
} else {
let reversePrompt = element.reversePrompt
if (reversePrompt) {
reversePrompt.forEach((item) => {
if (from == 'zh' && to == 'en') {
//
if (!ContainsChineseOrPunctuation(item.promptCN ? item.promptCN : item.prompt)) {
return
}
}
let temp_obj = {
text: item.prompt,
from: from,
to: to,
type: TranslateType.REVERSE_PROMPT_TRANSLATE,
isSplit: false, // true
bookTaskDetailId: element.id,
reversePromptId: item.id,
responseMessgeName: DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN
}
translateData.push(temp_obj)
})
}
}
}
return translateData
}
//
async function TranslateOne(key) {
let translateData = []
switch (key) {
case 'translate_english':
translateData = TranslateOneParams('zh', 'en')
break
case 'translate_chinese':
translateData = TranslateOneParams('en', 'zh')
break
case 'down_translate_english':
translateData = TranslateBatchParams('zh', 'en')
break
case 'down_translate_chinese':
translateData = TranslateBatchParams('en', 'zh')
break
default:
message.error('未知的操作类型')
break
}
if (translateData.length <= 0) {
message.error('没有需要翻译的数据')
return
}
softwareStore.spin.spinning = true
softwareStore.spin.tip = `翻译中 ... 0 / ${translateData.length}`
//
let res = await window.translate.TranslateNowReturn(translateData)
softwareStore.spin.spinning = false
window.api.showGlobalMessageDialog(res)
}
/**
* 重选反推提示词
*/
async function SelectReversePrompt() {
//
if (!data.value.reversePrompt || data.value.reversePrompt.length <= 0) {
message.error('当前没有反推提示词')
return
}
// ImportWordAndSrt
dialog.create({
showIcon: false,
title: `重选MJ反推提示词 ${data.value.name}`,
closeOnEsc: false,
content: () =>
h(ReSelectReversePrompt, {
reversePrompts: data.value.reversePrompt,
index: index.value
}),
style: `width : 750px;`,
maskClosable: false
})
}
let reverseOptions = [
{
label: '下推理',
key: 'down_reverse'
},
{
label: '删除反推提示词',
key: 'remove_reverse'
}
]
let tranlateOptions = [
{
label: '中文 2 英文',
key: 'translate_english'
},
{
label: '下翻译英文',
key: 'down_translate_english'
},
{
label: '下翻译中文',
key: 'down_translate_chinese'
}
]</script>
@@ -0,0 +1,235 @@
<template>
<div style="display: flex; justify-content: space-between; white-space: nowrap">
<div style="display: flex">
<div>反推/GPT提示词</div>
<n-button
v-if="reverseManageStore.selectBook.type == bookType.MJ_REVERSE"
type="text"
:color="softwareStore.SoftColor.ZHUYANTUO"
size="tiny"
style="margin-left: 10px"
@click="SelectPromptIndex"
>选择提示词</n-button
><n-button
type="text"
:color="softwareStore.SoftColor.ZHUYANTUO"
size="tiny"
style="margin-left: 5px"
@click="SelectStyle"
>风格</n-button
>
<n-button
type="text"
:color="softwareStore.SoftColor.ZHUYANTUO"
size="tiny"
style="margin-left: 5px"
@click="RemoveBadPrompt"
>去除提示词</n-button
>
<n-button
type="text"
:color="softwareStore.SoftColor.ZHUYANTUO"
size="tiny"
style="margin-left: 5px"
@click="ManagentBadPrompt"
>管理</n-button
>
</div>
<div>
<n-popover trigger="hover">
<template #trigger>
<n-button
color="#7c461e"
@click="SelectReversePromptAndReplace"
text
style="font-size: 24px"
>
<n-icon>
<FindReplaceRound />
</n-icon>
</n-button>
</template>
<span>批量替换反推提示词</span>
</n-popover>
</div>
</div>
</template>
<script setup>
import { ref, toRaw, h } from 'vue'
import { useMessage, useDialog, NButton, NPopover, NIcon } from 'naive-ui'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import { BookRepalceDataType, BookType } from '../../../../../define/enum/bookEnum'
import { useSoftwareStore } from '../../../../../stores/software'
import SelectMJReversePrompt from '../MJReverse/SelectMJReversePrompt.vue'
import SelectImageStyle from '../../Components/SelectImageStyle.vue'
import FindReplaceRound from '../../Icon/FindReplaceRound.vue'
import DatatableHeaderAfterGptSelectAndReplace from './DatatableHeaderAfterGptSelectAndReplace.vue'
import ManageBadPrompt from '../../Components/ManageBadPrompt.vue'
let message = useMessage()
let reverseManageStore = useReverseManageStore()
let softwareStore = useSoftwareStore()
let bookType = ref(BookType)
let dialog = useDialog()
let selectStyleRef = ref(null)
let da = undefined
let promprRef = ref(null)
/**
* 管理不想要的值
*/
async function ManagentBadPrompt() {
//
dialog.create({
showIcon: false,
title: '管理不想要的值',
content: () => h(ManageBadPrompt, { ref: promprRef }),
style: `width : 650px;`,
maskClosable: false,
positiveText: '确定',
negativeText: '取消',
onPositiveClick: async () => {
console.log(toRaw(promprRef.value.tags))
//
await window.api.SaveBadPrompt(toRaw(promprRef.value.tags), (value) => {
console.log(value)
if (value.code == 0) {
message.error(value.message)
return false
}
message.success('添加成功')
})
return true
}
})
}
/** 移除不想要的值 */
async function RemoveBadPrompt() {
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在移除不想要的值...'
let dia = dialog.warning({
title: '移除不想要的值提示',
content: '是否移除反推/GPT提示词里面不想要的值,移除后不可恢复,是否继续?',
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
try {
dia.destroy()
let res = await window.book.RemoveBadPrompt(reverseManageStore.selectBookTask.id)
if (res.code == 0) {
message.error(res.message)
return
}
console.log('RemoveBadPrompt', res)
if (res.data && res.data.length > 0) {
for (let i = 0; i < res.data.length; i++) {
const element = res.data[i]
let findIndex = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == element.id
)
if (findIndex != -1) {
reverseManageStore.selectBookTaskDetail[findIndex].gptPrompt = element.gptPrompt
}
}
} else {
throw new Error('没有移除任何值')
}
message.success(res.message)
} catch (error) {
message.error(error.message)
} finally {
softwareStore.spin.spinning = false
}
}
})
}
/**
* 选择MJ反推提示词用于生图
*/
async function SelectPromptIndex() {
// MJ
if (reverseManageStore.selectBook.type != BookType.MJ_REVERSE) {
message.error('只有MJ反推可以使用该按钮')
return
}
let hasReversePrompt = false
//
for (let index = 0; index < reverseManageStore.selectBookTaskDetail.length; index++) {
const element = reverseManageStore.selectBookTaskDetail[index]
if (element.reversePrompt && element.reversePrompt.length > 0) {
hasReversePrompt = true
break
}
}
if (!hasReversePrompt) {
message.error('请先进行MJ反推')
return
}
dialog.create({
title: '选择反推提示词',
content: () => h(SelectMJReversePrompt),
style: 'width : 500px',
showIcon: false
})
}
//
async function SelectStyle() {
//
//
//
let dialogWidth = window.innerWidth * 0.8
let dialogHeight = window.innerHeight * 0.9
// ImportWordAndSrt
dialog.create({
showIcon: false,
closeOnEsc: false,
content: () =>
h(SelectImageStyle, {
height: dialogHeight,
ref: selectStyleRef,
imageStyle: reverseManageStore.selectBookTask.imageStyle,
customizeImageStyle: reverseManageStore.selectBookTask.customizeImageStyle
}),
style: `width : ${dialogWidth}px; height : ${dialogHeight}px`,
maskClosable: false,
onClose: async () => {
console.log(selectStyleRef)
//
// reverseManageStore.selectBookTask.styleList = toRaw(selectStyleRef.value.selectStyle)
//
let res = await window.book.SaveImageStyle(
toRaw(selectStyleRef.value.selectStyle),
reverseManageStore.selectBookTask.id
)
if (res.code == 0) {
message.error(res.message)
return
}
reverseManageStore.selectBookTask.imageStyle = res.data.imageStyle
reverseManageStore.selectBookTask.customizeImageStyle = res.data.customizeImageStyle
message.success('保存成功')
}
})
}
async function SelectReversePromptAndReplace() {
if (da) {
return
}
da = dialog.create({
title: '批量查询替换反推提示词',
showIcon: false,
maskClosable: false,
content: () =>
h(DatatableHeaderAfterGptSelectAndReplace, { type: BookRepalceDataType.GPT_PROMPT }),
onClose: () => {
da = undefined
}
})
}
</script>
@@ -2,7 +2,7 @@
<div style="display: flex; align-items: center">
<div>出图</div>
<n-select
style="width: 70px; margin-left: 5px"
style="width: 100px; margin-left: 5px"
size="tiny"
v-model:value="select"
@update:value="handleUpdateValue"
@@ -47,13 +47,20 @@ export default defineComponent({
? reverseManageStore.selectBookTask.imageCategory
: BookImageCategory.MJ
)
onMounted(async () => {})
let options = ref([])
onMounted(async () => {
//
await window.api.GetImageGenerateCategory((value) => {
if (value.code == 0) {
message.error(value.message)
return
}
options.value = value.data
})
})
async function handleUpdateValue(value) {
if (value == BookImageCategory.D3) {
message.error('暂不支持该出图模式')
return
}
//
let res = await window.db.UpdateBookTaskData(reverseManageStore.selectBookTask.id, {
imageCategory: value
@@ -124,20 +131,7 @@ export default defineComponent({
key: 'unlock'
}
],
options: [
{
label: 'MJ',
value: BookImageCategory.MJ
},
{
label: 'SD',
value: BookImageCategory.SD
},
{
label: 'D3',
value: BookImageCategory.D3
}
]
options
}
}
})
@@ -0,0 +1,305 @@
<template>
<div>
<n-dropdown trigger="hover" :options="mergeOptions" @select="MergePrompt">
<n-button
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="MergePrompt(undefined)"
>
单句合并
</n-button>
</n-dropdown>
<n-button
style="margin-left: 5px"
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="SingleGenerateImage"
>
单句生图
</n-button>
<n-button
style="margin-left: 5px"
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="UnderGenerateImage"
>
下生图
</n-button>
<n-button
style="margin-left: 5px"
size="tiny"
:color="softwareStore.SoftColor.BROWN_YELLOW"
@click="ImportMJImageUrl"
>
导入图片
</n-button>
</div>
<n-input
type="textarea"
size="tiny"
@input="InputDebounced"
v-model:value="data.prompt"
:autosize="{ minRows: 6, maxRows: 6 }"
></n-input>
</template>
<script setup>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch, h } from 'vue'
import { useMessage, useDialog, NInput, NButton, NDropdown } from 'naive-ui'
import { useSoftwareStore } from '../../../../../stores/software'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import {
BookBackTaskType,
OperateBookType,
TaskExecuteType
} from '../../../../../define/enum/bookEnum'
import { BookImageCategory } from '../../../../../define/enum/bookEnum'
import { debounce } from 'lodash'
import InputDialogContent from '../../Original/Components/InputDialogContent.vue'
import { DEFINE_STRING } from '../../../../../define/define_string'
let props = defineProps({
initData: undefined,
index: undefined
})
let message = useMessage()
let softwareStore = useSoftwareStore()
let reverseManageStore = useReverseManageStore()
let data = ref(props.initData)
let image_url_ref = ref(null)
let dialog = useDialog()
onMounted(async () => {})
//
async function MergePrompt(key) {
let type = key
if (!key) {
if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.MJ) {
type = 'mj_merge'
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.SD) {
type = 'sd_merge'
} else {
type = 'mj_merge'
}
}
//
//
softwareStore.spin.spinning = true
softwareStore.spin.tip = '合并命令中。。。'
let res = await window.book.MergePrompt(data.value.id, type, OperateBookType.BOOKTASKDETAIL)
softwareStore.spin.spinning = false
//
if (res.code == 0) {
message.error(res.message)
return
}
for (let i = 0; i < res.data.length; i++) {
const element = res.data[i]
let selectBookDetailIndex = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == element.id
)
reverseManageStore.selectBookTaskDetail[selectBookDetailIndex].prompt = element.prompt
}
message.success(res.message)
}
//
async function SingleGenerateImage() {
let res = undefined
if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.MJ) {
res = await window.mj.AddMJGenerateImageTask(
data.value.id,
OperateBookType.BOOKTASKDETAIL,
DEFINE_STRING.BOOK.MJ_IMAGE_GENERATE_RETURN
)
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.SD) {
// SD
res = await window.task.AddBookBackTask(
reverseManageStore.selectBook.id,
BookBackTaskType.SD_IMAGE,
TaskExecuteType.AUTO,
reverseManageStore.selectBookTask.id,
data.value.id,
DEFINE_STRING.BOOK.SD_IMAGE_GENERATE_RETURN
)
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.D3) {
res = await window.task.AddBookBackTask(
reverseManageStore.selectBook.id,
BookBackTaskType.D3_IMAGE,
TaskExecuteType.AUTO,
reverseManageStore.selectBookTask.id,
data.value.id,
DEFINE_STRING.BOOK.D3_IMAGE_GENERATE_RETURN
)
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.FLUX_API) {
res = await window.task.AddBookBackTask(
reverseManageStore.selectBook.id,
BookBackTaskType.FLUX_API_IMAGE,
TaskExecuteType.AUTO,
reverseManageStore.selectBookTask.id,
data.value.id,
DEFINE_STRING.BOOK.FLUX_API_IMAGE_GENERATE_RETURN
)
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.FLUX_FORGE) {
res = await window.task.AddBookBackTask(
reverseManageStore.selectBook.id,
BookBackTaskType.FLUX_FORGE_IMAGE,
TaskExecuteType.AUTO,
reverseManageStore.selectBookTask.id,
data.value.id,
DEFINE_STRING.BOOK.FLUX_FORGE_IMAGE_GENERATE_RETURN
)
} else {
message.error('未知的出图模式')
return
}
if (res.code == 0) {
message.error(res.message)
return
}
message.success(res.message)
}
//
async function UnderGenerateImage() {
let res = undefined
let bookTaskDetails = reverseManageStore.selectBookTaskDetail.filter(
(item, index) => index >= props.index && !item.imageLock
)
if (bookTaskDetails.length <= 0) {
message.error('未找到可生成图片的分镜,或者分镜都被锁定')
return
}
if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.MJ) {
res = await window.mj.AddMJGenerateImageTask(
data.value.id,
OperateBookType.UNDERBOOKTASK,
DEFINE_STRING.BOOK.MJ_IMAGE_GENERATE_RETURN
)
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.SD) {
// SD
let tasksList = []
for (let i = 0; i < bookTaskDetails.length; i++) {
const element = bookTaskDetails[i]
tasksList.push({
bookId: reverseManageStore.selectBook.id,
type: BookBackTaskType.SD_IMAGE,
executeType: TaskExecuteType.AUTO,
bookTaskId: reverseManageStore.selectBookTask.id,
bookTaskDetailId: element.id,
messageName: DEFINE_STRING.BOOK.SD_IMAGE_GENERATE_RETURN
})
}
res = await window.task.AddMultiBookBackTask(tasksList)
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.FLUX_FORGE) {
// forge flux
let tasksList = []
for (let i = 0; i < bookTaskDetails.length; i++) {
const element = bookTaskDetails[i]
tasksList.push({
bookId: reverseManageStore.selectBook.id,
type: BookBackTaskType.FLUX_FORGE_IMAGE,
executeType: TaskExecuteType.AUTO,
bookTaskId: reverseManageStore.selectBookTask.id,
bookTaskDetailId: element.id,
messageName: DEFINE_STRING.BOOK.FLUX_FORGE_IMAGE_GENERATE_RETURN
})
}
res = await window.task.AddMultiBookBackTask(tasksList)
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.FLUX_API) {
// forge flux
let tasksList = []
for (let i = 0; i < bookTaskDetails.length; i++) {
const element = bookTaskDetails[i]
tasksList.push({
bookId: reverseManageStore.selectBook.id,
type: BookBackTaskType.FLUX_API_IMAGE,
executeType: TaskExecuteType.AUTO,
bookTaskId: reverseManageStore.selectBookTask.id,
bookTaskDetailId: element.id,
messageName: DEFINE_STRING.BOOK.FLUX_API_IMAGE_GENERATE_RETURN
})
}
res = await window.task.AddMultiBookBackTask(tasksList)
} else if (reverseManageStore.selectBookTask.imageCategory == BookImageCategory.D3) {
let tasksList = []
for (let i = 0; i < bookTaskDetails.length; i++) {
const element = bookTaskDetails[i]
tasksList.push({
bookId: reverseManageStore.selectBook.id,
type: BookBackTaskType.D3_IMAGE,
executeType: TaskExecuteType.AUTO,
bookTaskId: reverseManageStore.selectBookTask.id,
bookTaskDetailId: element.id,
messageName: DEFINE_STRING.BOOK.D3_IMAGE_GENERATE_RETURN
})
}
res = await window.task.AddMultiBookBackTask(tasksList)
} else {
message.error('未知的出图模式')
return
}
if (res.code == 0) {
message.error(res.message)
return
}
message.success(res.message)
}
let InputDebounced = debounce(handleInput, 1000)
async function handleInput() {
let res = await window.db.UpdateBookTaskDetailData(data.value.id, {
prompt: data.value.prompt
})
if (res.code == 0) {
message.error(res.message)
}
}
/**
* 写入图片的链接将图片链接下载并且分割
*/
async function ImportMJImageUrl() {
//
//
let dialogWidth = 400
let dialogHeight = 150
let da = dialog.create({
title: '添加图片链接/本地地址',
showIcon: false,
closeOnEsc: false,
content: () =>
h(InputDialogContent, {
ref: image_url_ref,
initData: null,
placeholder: '请输入图片链接/本地地址'
}),
style: `width : ${dialogWidth}px; min-height : ${dialogHeight}px`,
maskClosable: false,
onClose: async () => {
da?.destroy()
let row_image_url = image_url_ref.value.data
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在下载图片/分割图片中。。。'
let res = await window.book.DownloadImageUrlAndSplit(data.value.id, row_image_url)
softwareStore.spin.spinning = false
if (res.code == 0) {
message.error(res.message)
return
}
data.value.outImagePath = res.data.outImagePath
data.value.subImagePath = res.data.subImagePath
message.success(res.message)
}
})
}
let mergeOptions = [
{ label: 'MJ模式合并', key: 'mj_merge' },
{ label: 'SD模式合并', key: 'sd_merge' }
]
</script>
@@ -0,0 +1,110 @@
<template>
<n-spin :show="show">
<n-form :label-width="80" :model="formValue">
<n-form-item label="选择剪映草稿" path="draftName">
<n-select
v-model:value="formValue.draftName"
filterable
placeholder="选择草稿"
:options="draftSelect"
clearable
/>
</n-form-item>
<n-form-item path="writeTimeLine">
<n-button type="primary" @click="GetJianyingFrame">开始抽帧</n-button>
</n-form-item>
</n-form>
<template #description> 正在剪映抽帧中... </template>
</n-spin>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import {
NForm,
NFormItem,
NInput,
NSpin,
NButton,
NSelect,
NCheckbox,
useMessage,
useDialog
} from 'naive-ui'
import { isEmpty } from 'lodash'
import { useReverseManageStore } from '../../../../../stores/reverseManage.ts'
let draftSelect = ref([])
let formValue = ref({
draftName: undefined
})
let show = ref(false)
let message = useMessage()
let dialog = useDialog()
let reverseManageStore = useReverseManageStore()
onMounted(() => {
// 稿
window.api.getDraftFileList((value) => {
value.forEach((element) => {
let obj = {
label: element,
value: element
}
draftSelect.value.push(obj)
})
})
})
async function GetJianyingFrame() {
if (
reverseManageStore.selectBookTaskDetail &&
reverseManageStore.selectBookTaskDetail.length > 0
) {
let da = dialog.warning({
title: '剪映抽帧提示',
content:
'检测到到当前已经存在分镜数据,继续抽帧将会首先删除当前数据,哪怕是失败也不能恢复,是否继续?',
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
da.destroy()
await JianyingFrame()
}
})
} else {
await JianyingFrame()
}
}
async function JianyingFrame() {
if (isEmpty(formValue.value.draftName)) {
message.error('请选择草稿文件')
return
}
show.value = true
try {
let res = await window.book.JianyingFrame(
reverseManageStore.selectBookTask.id,
formValue.value.draftName
)
if (res.code == 0) {
message.error(res.message)
return
}
message.success('剪映抽帧成功')
//
//
let getRes = await reverseManageStore.GetBookTaskDetail(reverseManageStore.selectBookTask.id)
if (getRes.code == 0) {
message.error(getRes.message)
return
}
} catch (error) {
message.error(error.toString())
} finally {
show.value = false
}
}
</script>
@@ -37,7 +37,7 @@
import { ref, onMounted, defineComponent, onUnmounted, toRaw, computed } from 'vue'
import { useMessage, NButton, NInput, NSpin, NDropdown } from 'naive-ui'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import DatatableGptPromptButton from '../Components/DatatableGptPromptButton.vue'
import DatatableGptPromptButton from './DatatableGptPromptButton.vue'
import { debounce } from 'lodash'
export default defineComponent({
File diff suppressed because it is too large Load Diff
@@ -10,164 +10,162 @@
</div>
</template>
<script>
import { ref, onMounted, defineComponent, watch, h } from 'vue'
<script setup>
import { ref, onMounted, defineComponent, computed, watch, h } from 'vue'
import { useMessage, NDataTable, NImage } from 'naive-ui'
import { useSoftwareStore } from '../../../../../stores/software'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import DataTableShowGenerateImage from '../../Original/Components/DataTableShowGenerateImage.vue'
import ManageBookOldImage from '../Components/ManageBookOldImage.vue'
import ManageBookOldImage from './ManageBookOldImage.vue'
import { BookType } from '../../../../../define/enum/bookEnum'
import MJReversePrompt from './MJReversePrompt.vue'
import DatatableHeaderGptPrompt from '../Components/DatatableHeaderGptPrompt.vue'
import DatatableHeaderAfterGpt from '../Components/DatatableHeaderAfterGpt.vue'
import DatatableHeaderPrompt from '../Components/DatatableHeaderPrompt.vue'
import DatatablePrompt from '../Components/DatatablePrompt.vue'
import DatatableHeaderImage from '../Components/DatatableHeaderImage.vue'
import DatatableAfterGpt from '../Components/DatatableAfterGpt.vue'
import DatatableGenerateImage from '../Components/DatatableGenerateImage.vue'
import DatatableHeaderGptPrompt from './DatatableHeaderGptPrompt.vue'
import DatatableHeaderAfterGpt from './DatatableHeaderAfterGpt.vue'
import DatatableHeaderPrompt from './DatatableHeaderPrompt.vue'
import DatatablePrompt from './DatatablePrompt.vue'
import DatatableHeaderImage from './DatatableHeaderImage.vue'
import DatatableAfterGpt from './DatatableAfterGpt.vue'
import DatatableGenerateImage from './DatatableGenerateImage.vue'
import ODataTableAction from '../Original/ODataTableAction.vue'
import SDReversePrompt from './SDReversePrompt.vue'
export default defineComponent({
components: { NDataTable, NImage },
let softwareStore = useSoftwareStore()
let reverseManageStore = useReverseManageStore()
let message = useMessage()
let maxHeight = ref(0)
let datatable = ref(null)
setup() {
let softwareStore = useSoftwareStore()
let reverseManageStore = useReverseManageStore()
let message = useMessage()
let maxHeight = ref(0)
let datatable = ref(null)
watch(
() => softwareStore.skip,
(newValue) => {
let doc = document.querySelectorAll('.n-data-table-tr')
let sk = doc[newValue.skipRowIndex]
datatable.value.scrollTo({ el: sk })
},
{ deep: true }
)
watch(
() => softwareStore.skip,
(newValue) => {
let doc = document.querySelectorAll('.n-data-table-tr')
let sk = doc[newValue.skipRowIndex]
datatable.value.scrollTo({ el: sk })
},
{ deep: true }
)
const createColumns = () => [
{
title: 'No.',
key: 'name',
width: 50,
fixed: 'left'
},
{
title(row) {
return h(DatatableHeaderAfterGpt)
},
key: 'afterGpt',
width: 200,
fixed: 'left',
render(row, index) {
return h(DatatableAfterGpt, { initData: row, index: index })
}
},
{
title: '图片/视频',
key: 'oldImage',
className: 'space-row',
width: 130,
render(row, index) {
return h(ManageBookOldImage, {
initData: row,
index: index
})
}
},
{
title(row) {
return h(DatatableHeaderGptPrompt)
},
key: 'gptPrompt',
className: 'space-row',
resizable: true,
width: 400,
minWidth: 400,
maxWidth: 600,
render(row, index) {
if (reverseManageStore.selectBook.type == BookType.MJ_REVERSE) {
return h(MJReversePrompt, {
initData: row,
index: index
})
} else if (reverseManageStore.selectBook.type == BookType.SD_REVERSE) {
return h('span', ['SD 反推这边不能用', index])
} else if (reverseManageStore.selectBook.type == BookType.ORIGINAL) {
return h('span', ['原创 这边暂时不能用', index])
}
return h('span', ['不支持的类型', index])
}
},
{
title(row) {
return h(DatatableHeaderPrompt)
},
className: 'space-row',
key: 'row1',
render(row, index) {
return h(DatatablePrompt, {
initData: row,
index: index
})
}
},
{
title() {
return h(DatatableHeaderImage)
},
width: 300,
className: 'space-row',
render(row, index) {
return h(DatatableGenerateImage, {
image_generate_category: 'mj',
initData: row,
index: index,
type: 'data'
})
},
fixed: 'right'
}
]
onMounted(async () => {
calcHeight()
setTimeout(() => {
let div = document.getElementsByClassName('space-row')
for (let i = 0; i < div.length; i++) {
div[i].style.padding = '0px 5px'
}
}, 100)
//
let detailRes = await window.book.GetBookTaskDetail(reverseManageStore.selectBookTask.id)
if (detailRes.code == 0) {
message.error(detailRes.message)
softwareStore.spin.spinning = false
return
}
softwareStore.spin.spinning = false
reverseManageStore.selectBookTaskDetail = detailRes.data
})
function calcHeight() {
//
let height = window.innerHeight
maxHeight.value = height - 120
const columns = [
{
title: 'No.',
key: 'no',
width: 50,
fixed: 'left'
},
{
title(row) {
return h(DatatableHeaderAfterGpt)
},
key: 'afterGpt',
width: 200,
fixed: 'left',
className: 'empty-margin',
render(row, index) {
return h(DatatableAfterGpt, { initData: row, index: index })
}
return {
softwareStore,
reverseManageStore,
maxHeight,
columns: createColumns(),
datatable
},
{
title: '图片/视频',
key: 'oldImage',
className: 'empty-margin',
width: 130,
render(row, index) {
return h(ManageBookOldImage, {
initData: row,
index: index
})
}
},
{
title(row) {
return h(DatatableHeaderGptPrompt)
},
key: 'gptPrompt',
className: 'empty-margin',
resizable: true,
width: 400,
minWidth: 400,
maxWidth: 600,
render(row, index) {
if (reverseManageStore.selectBook.type == BookType.MJ_REVERSE) {
return h(MJReversePrompt, {
initData: row,
index: index
})
} else if (reverseManageStore.selectBook.type == BookType.SD_REVERSE) {
return h(SDReversePrompt, {
initData: row,
index: index
})
} else if (reverseManageStore.selectBook.type == BookType.ORIGINAL) {
return h('span', ['原创 这边暂时不能用', index])
}
return h('span', ['不支持的类型', index])
}
},
{
title(row) {
return h(DatatableHeaderPrompt)
},
className: 'empty-margin',
key: 'row1',
render(row, index) {
return h(DatatablePrompt, {
initData: row,
index: index
})
}
},
{
//
title: '参数',
key: 'parameter',
width: '110',
render(row, index) {
return h(ODataTableAction, { initData: row, index: index })
}
},
{
title() {
return h(DatatableHeaderImage)
},
width: 300,
className: 'empty-margin',
render(row, index) {
return h(DatatableGenerateImage, {
image_generate_category: 'mj',
initData: row,
index: index,
type: 'data'
})
},
fixed: 'right'
}
]
onMounted(async () => {
setTimeout(() => {
let div = document.getElementsByClassName('empty-margin')
for (let i = 0; i < div.length; i++) {
div[i].style.padding = '0px 5px'
}
calcHeight()
// getMaxHeight()
}, 100)
//
let detailRes = await window.book.GetBookTaskDetail(reverseManageStore.selectBookTask.id)
if (detailRes.code == 0) {
message.error(detailRes.message)
softwareStore.spin.spinning = false
return
}
softwareStore.spin.spinning = false
reverseManageStore.selectBookTaskDetail = detailRes.data
})
function calcHeight() {
//
let height = window.innerHeight
maxHeight.value = height - 120
}
</script>
@@ -0,0 +1,44 @@
<template>
<div>
<DatatableGptPromptButton :initData="data" :index="index" />
</div>
<n-input
type="textarea"
size="tiny"
v-model:value="data.gptPrompt"
:autosize="{
minRows: 6,
maxRows: 6
}"
@input="InputDebounced"
>
</n-input>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useMessage, NButton, NInput, NSpin, NDropdown } from 'naive-ui'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import DatatableGptPromptButton from './DatatableGptPromptButton.vue'
import { debounce } from 'lodash'
let props = defineProps({
initData: undefined,
index: undefined
})
let data = ref(props.initData)
let index = ref(props.index)
let message = useMessage()
let reverseManageStore = useReverseManageStore()
onMounted(async () => {})
let InputDebounced = debounce(handleInput, 1000)
async function handleInput(value) {
let res = await window.db.UpdateBookTaskDetailData(data.value.id, {
gptPrompt: value
})
if (res.code == 0) {
message.error(res.message)
}
}
</script>
@@ -1,7 +1,12 @@
<template>
<div style="height: 100%; display: flex; width: 100%; overflow: auto; padding: 0; margin: 0">
<div>
<div v-if="reverseManageStore.selectBook.type == bookType.MJ_REVERSE">
<div
v-if="
reverseManageStore.selectBook.type == bookType.MJ_REVERSE ||
reverseManageStore.selectBook.type == bookType.SD_REVERSE
"
>
<div v-if="true" class="left_container" style="flex: 10; min-width: 500px">
<ManageBookDetailButton />
<ManageBookReverseTable style="margin-top: 5px" />
@@ -20,10 +25,10 @@
</div>
</template>
<script>
<script setup>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch } from 'vue'
import { useMessage, NDivider } from 'naive-ui'
import ManageBookDetailButton from './Components/ManageBookDetailButton.vue'
import ManageBookDetailButton from './MJReverse/ManageBookDetailButton.vue'
import ManageBookReverseTable from './MJReverse/ManageBookReverseTable.vue'
import ManageBookShowLogger from './Components/ManageBook/ManageBookShowLogger.vue'
import { useSoftwareStore } from '../../../../stores/software'
@@ -33,202 +38,250 @@ import { ResponseMessageType } from '../../../../define/enum/softwareEnum'
import { useReverseManageStore } from '../../../../stores/reverseManage'
import OriginalMainPage from './Original/OriginalMainPage.vue'
export default defineComponent({
components: {
ManageBookDetailButton,
ManageBookReverseTable,
ManageBookShowLogger,
NDivider,
OriginalMainPage
},
let message = useMessage()
let softwareStore = useSoftwareStore()
let reverseManageStore = useReverseManageStore()
let bookType = ref(BookType)
setup() {
let message = useMessage()
let softwareStore = useSoftwareStore()
let reverseManageStore = useReverseManageStore()
let bookType = ref(BookType)
onMounted(async () => {
//
window.api.setEventListen([DEFINE_STRING.BOOK.GET_COPYWRITING_RETURN], (value) => {
if (value.code == 0) {
message.error(value.message)
code.value = code.value + '\n' + value.data
return
}
//
softwareStore.spin.tip = `正在提取文案,当前进度 ${value.data.progress.current} / ${value.data.progress.total} 。。。`
let index = reverseManageStore.selectBookTaskDetail.findIndex((item) => item.id == value.id)
if (index >= 0) {
reverseManageStore.selectBookTaskDetail[index].word = value.data.content
reverseManageStore.selectBookTaskDetail[index].afterGpt = value.data.content
}
})
//
window.api.setEventListen([DEFINE_STRING.BOOK.REMOVE_WATERMARK_RETURN], (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
let index = reverseManageStore.selectBookTaskDetail.findIndex((item) => item.id == value.id)
if (index >= 0) {
reverseManageStore.selectBookTaskDetail[index].oldImage =
value.data + '?time=' + new Date().getTime()
}
})
//
window.api.setEventListen([DEFINE_STRING.BOOK.REVERSE_PROMPT_RETURN], (value) => {
if (value.code == 0) {
errorResponse(value)
} else {
MJReverseResponse(value)
}
})
// MJ
window.api.setEventListen([DEFINE_STRING.BOOK.MJ_IMAGE_GENERATE_RETURN], (value) => {
if (value.code == 0) {
errorResponse(value)
}
MJImageResponse(value)
})
//
window.api.setEventListen([DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN], (value) => {
if (value.code == 0) {
errorResponse(value)
} else {
if (value.type == ResponseMessageType.REVERSE_PROMPT_TRANSLATE) {
ReversePromptTranslateResponse(value)
} else if (value.type == ResponseMessageType.GPT_PROMPT_TRANSLATE) {
GptPromptTranslateResponse(value)
} else {
message.error('错误的返回数据类型')
return
}
}
})
})
function errorResponse(value) {
switch (value.dialogType) {
case DialogType.DIALOG:
window.api.showGlobalMessageDialog(value)
break
case DialogType.MESSAGE:
message.error(value.message)
break
case DialogType.NOTIFICATION:
window.api.showGlobalNotificationDialog(value)
break
default:
window.api.showGlobalNotificationDialog(value)
break
}
// SD
function OriginalSDImageResponseReturn(value) {
console.log('OriginalSDImageResponseReturn', value)
//
if (value.data) {
let dataIndex = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == value.data.id
)
if (dataIndex >= 0) {
reverseManageStore.selectBookTaskDetail[dataIndex].mjMessage = value.data
reverseManageStore.selectBookTaskDetail[dataIndex].outImagePath = value.data.outImagePath
reverseManageStore.selectBookTaskDetail[dataIndex].subImagePath = value.data.subImagePath
}
onUnmounted(() => {
window.api.removeEventListen(DEFINE_STRING.BOOK.GET_COPYWRITING_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.REMOVE_WATERMARK_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.REVERSE_PROMPT_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.MJ_IMAGE_GENERATE_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN)
})
function MJImageResponse(value) {
//
if (value.data) {
let dataIndex = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == value.data.id
)
if (dataIndex >= 0) {
reverseManageStore.selectBookTaskDetail[dataIndex].mjMessage = value.data
reverseManageStore.selectBookTaskDetail[dataIndex].outImagePath = value.data.outImagePath
reverseManageStore.selectBookTaskDetail[dataIndex].subImagePath = value.data.subImagePath
}
}
if (value.data.status == 'error') {
message.error(value.data.message)
}
/**
* 处理翻译返回的数据主要是将翻译的数据放到对应的位置
* @param value 返回的数据数据结构如下
* bookTaskDetailId: string // ID
* reversePromptId: string // ID
* from: string //
* to: string // to zh promptCN to en promptprom
* prompt: string //
* promptCN: string //
*/
function ReversePromptTranslateResponse(value) {
if (!value.data) {
return
}
//
softwareStore.spin.tip = `翻译中 ... ${value.data.progress} / ${value.data.total}`
let detailIndex = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == value.data.bookTaskDetailId
)
if (detailIndex < 0) {
return
}
let dataObj = reverseManageStore.selectBookTaskDetail[detailIndex]
let reverseIndex = dataObj.reversePrompt.findIndex(
(item) => item.id == value.data.reversePromptId
)
if (reverseIndex < 0) {
return
}
if (value.data.to == 'en') {
reverseManageStore.selectBookTaskDetail[detailIndex].reversePrompt[reverseIndex].prompt =
value.data.prompt
reverseManageStore.selectBookTaskDetail[detailIndex].reversePrompt[reverseIndex].promptCN =
value.data.promptCN
} else if (value.data.to == 'zh') {
reverseManageStore.selectBookTaskDetail[detailIndex].reversePrompt[reverseIndex].promptCN =
value.data.promptCN
} else {
message.error('未知的翻译目标语言')
}
}
function GptPromptTranslateResponse(value) {
console.log('GptPromptTranslateResponse', value)
if (!value.data) {
return
}
let index = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == value.data.bookTaskDetailId
)
if (index < 0) {
return
}
reverseManageStore.selectBookTaskDetail[index].gptPrompt = value.data.prompt
//
softwareStore.spin.tip = `翻译中 ... ${value.data.progress} / ${value.data.total}`
}
/**
* MJ反推返回数据
*/
function MJReverseResponse(value) {
if (value.data && value.data.progress == 100) {
let dataIndex = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == value.data.id
)
if (dataIndex >= 0) {
reverseManageStore.selectBookTaskDetail[dataIndex].gptPrompt = undefined
reverseManageStore.selectBookTaskDetail[dataIndex].reversePrompt = JSON.parse(
value.data.prompt
)
}
}
}
return { softwareStore, reverseManageStore, bookType }
}
}
onMounted(async () => {
// SD
window.api.setEventListen([DEFINE_STRING.BOOK.SD_IMAGE_GENERATE_RETURN], (value) =>
OriginalSDImageResponseReturn(value)
)
// D3
window.api.setEventListen([DEFINE_STRING.BOOK.D3_IMAGE_GENERATE_RETURN], (value) => {
OriginalSDImageResponseReturn(value)
})
// FLUX API
window.api.setEventListen([DEFINE_STRING.BOOK.FLUX_API_IMAGE_GENERATE_RETURN], (value) =>
OriginalSDImageResponseReturn(value)
)
// FLUX FORGE
window.api.setEventListen([DEFINE_STRING.BOOK.FLUX_FORGE_IMAGE_GENERATE_RETURN], (value) =>
OriginalSDImageResponseReturn(value)
)
//
window.api.setEventListen([DEFINE_STRING.BOOK.GET_COPYWRITING_RETURN], (value) => {
if (value.code == 0) {
message.error(value.message)
code.value = code.value + '\n' + value.data
return
}
//
softwareStore.spin.tip = `正在提取文案,当前进度 ${value.data.progress.current} / ${value.data.progress.total} 。。。`
let index = reverseManageStore.selectBookTaskDetail.findIndex((item) => item.id == value.id)
if (index >= 0) {
reverseManageStore.selectBookTaskDetail[index].word = value.data.content
reverseManageStore.selectBookTaskDetail[index].afterGpt = value.data.content
}
})
//
window.api.setEventListen([DEFINE_STRING.BOOK.REMOVE_WATERMARK_RETURN], (value) => {
if (value.code == 0) {
message.error(value.message)
return
}
let index = reverseManageStore.selectBookTaskDetail.findIndex((item) => item.id == value.id)
if (index >= 0) {
reverseManageStore.selectBookTaskDetail[index].oldImage =
value.data + '?time=' + new Date().getTime()
}
})
//
window.api.setEventListen([DEFINE_STRING.BOOK.REVERSE_PROMPT_RETURN], (value) => {
if (value.code == 0) {
errorResponse(value)
return
}
if (value.type == ResponseMessageType.MJ_REVERSE) {
MJReverseResponse(value)
} else if (value.type == ResponseMessageType.SD_REVERSE) {
SDReverseResponse(value)
} else {
console.error('错误的返回数据类型')
return
}
})
// MJ
window.api.setEventListen([DEFINE_STRING.BOOK.MJ_IMAGE_GENERATE_RETURN], (value) => {
if (value.code == 0) {
errorResponse(value)
}
MJImageResponse(value)
})
//
window.api.setEventListen([DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN], (value) => {
if (value.code == 0) {
errorResponse(value)
} else {
if (value.type == ResponseMessageType.REVERSE_PROMPT_TRANSLATE) {
ReversePromptTranslateResponse(value)
} else if (value.type == ResponseMessageType.GPT_PROMPT_TRANSLATE) {
GptPromptTranslateResponse(value)
} else {
message.error('错误的返回数据类型')
return
}
}
})
})
function errorResponse(value) {
switch (value.dialogType) {
case DialogType.DIALOG:
window.api.showGlobalMessageDialog(value)
break
case DialogType.MESSAGE:
message.error(value.message)
break
case DialogType.NOTIFICATION:
window.api.showGlobalNotificationDialog(value)
break
default:
window.api.showGlobalNotificationDialog(value)
break
}
}
onUnmounted(() => {
window.api.removeEventListen(DEFINE_STRING.BOOK.GET_COPYWRITING_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.REMOVE_WATERMARK_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.REVERSE_PROMPT_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.MJ_IMAGE_GENERATE_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.REVERSE_PROMPT_TRANSLATE_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.SD_IMAGE_GENERATE_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.D3_IMAGE_GENERATE_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.FLUX_API_IMAGE_GENERATE_RETURN)
window.api.removeEventListen(DEFINE_STRING.BOOK.FLUX_FORGE_IMAGE_GENERATE_RETURN)
})
function MJImageResponse(value) {
//
if (value.data) {
let dataIndex = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == value.data.id
)
if (dataIndex >= 0) {
reverseManageStore.selectBookTaskDetail[dataIndex].mjMessage = value.data
reverseManageStore.selectBookTaskDetail[dataIndex].outImagePath = value.data.outImagePath
reverseManageStore.selectBookTaskDetail[dataIndex].subImagePath = value.data.subImagePath
}
}
}
/**
* 处理翻译返回的数据主要是将翻译的数据放到对应的位置
* @param value 返回的数据数据结构如下
* bookTaskDetailId: string // ID
* reversePromptId: string // ID
* from: string //
* to: string // to zh promptCN to en promptprom
* prompt: string //
* promptCN: string //
*/
function ReversePromptTranslateResponse(value) {
if (!value.data) {
return
}
//
softwareStore.spin.tip = `翻译中 ... ${value.data.progress} / ${value.data.total}`
let detailIndex = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == value.data.bookTaskDetailId
)
if (detailIndex < 0) {
return
}
let dataObj = reverseManageStore.selectBookTaskDetail[detailIndex]
let reverseIndex = dataObj.reversePrompt.findIndex(
(item) => item.id == value.data.reversePromptId
)
if (reverseIndex < 0) {
return
}
if (value.data.to == 'en') {
reverseManageStore.selectBookTaskDetail[detailIndex].reversePrompt[reverseIndex].prompt =
value.data.prompt
reverseManageStore.selectBookTaskDetail[detailIndex].reversePrompt[reverseIndex].promptCN =
value.data.promptCN
} else if (value.data.to == 'zh') {
reverseManageStore.selectBookTaskDetail[detailIndex].reversePrompt[reverseIndex].promptCN =
value.data.promptCN
} else {
message.error('未知的翻译目标语言')
}
}
function GptPromptTranslateResponse(value) {
console.log('GptPromptTranslateResponse', value)
if (!value.data) {
return
}
let index = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == value.data.bookTaskDetailId
)
if (index < 0) {
return
}
reverseManageStore.selectBookTaskDetail[index].gptPrompt = value.data.prompt
//
softwareStore.spin.tip = `翻译中 ... ${value.data.progress} / ${value.data.total}`
}
/**
* MJ反推返回数据
*/
function MJReverseResponse(value) {
if (value.data && value.data.progress == 100) {
let dataIndex = reverseManageStore.selectBookTaskDetail.findIndex(
(item) => item.id == value.data.id
)
if (dataIndex >= 0) {
reverseManageStore.selectBookTaskDetail[dataIndex].gptPrompt = undefined
reverseManageStore.selectBookTaskDetail[dataIndex].reversePrompt = JSON.parse(
value.data.prompt
)
}
}
}
/**
* SD反推返回数据
*/
function SDReverseResponse(value) {
if (value.data) {
let dataIndex = reverseManageStore.selectBookTaskDetail.findIndex((item) => item.id == value.id)
if (dataIndex >= 0) {
reverseManageStore.selectBookTaskDetail[dataIndex].gptPrompt = value.data
}
}
}
</script>
<style lang="css">
@@ -30,11 +30,29 @@
@update:checked-row-keys="handleCheck"
/>
</div>
<n-dropdown
placement="bottom-start"
trigger="manual"
:x="x"
:y="y"
:options="options"
:show="showDropdown"
:on-clickoutside="onClickoutside"
@select="handleSelect"
/>
</template>
<script setup>
import { ref, onMounted, defineComponent, onUnmounted, toRaw, watch, h } from 'vue'
import { useMessage, useDialog, NButton, NDataTable, NIcon, NWatermark } from 'naive-ui'
import { ref, onMounted, defineComponent, onUnmounted, toRaw, nextTick, h } from 'vue'
import {
useMessage,
useDialog,
NButton,
NDataTable,
NIcon,
NDropdown,
NPerformantEllipsis
} from 'naive-ui'
import { useReverseManageStore } from '../../../../stores/reverseManage'
import { useSoftwareStore } from '../../../../stores/software'
import { AddSharp } from '@vicons/ionicons5'
@@ -53,6 +71,12 @@ const router = useRouter()
let message = useMessage()
let columns = createColumns()
const checkedRowKeysRef = ref([])
let showDropdown = ref(false)
let x = ref(0)
let y = ref(0)
let selectRow = ref(null)
let options = []
onMounted(async () => {
window.api.setEventListen([DEFINE_STRING.BOOK.MAIN_DATA_RETURN], (value) => {
if (value.code == 0) {
@@ -107,39 +131,238 @@ function createColumns() {
width: 100
},
{
title: '操作',
key: 'action',
width: 215,
fixed: 'right',
title: '失败原因',
key: 'errorMsg',
width: 210,
render(row, index) {
return h(BookTaskListAction, {
bookTask: row
})
return h(
NPerformantEllipsis,
{
style: 'max-width: 200px'
},
row.errorMsg
)
}
}
]
}
/**
* 高清数据
*/
async function hdImageFunc(id, operateBookType) {
function createOptions(row) {
return [
{
label: `高清 ${row.name}`,
key: 'hd'
},
{
label: `生成草稿 ${row.name}`,
key: 'draft'
},
{
label: `合成视频 ${row.name}`,
key: 'generateVideo'
},
{
label: () => h('span', { style: { color: '#f4a534' } }, `重置 ${row.name}`),
key: 'reset'
},
{
label: () => h('span', { style: { color: 'red' } }, `删除 ${row.name}`),
key: 'delete'
}
]
}
async function HDImage(value) {
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在高清中。。。'
let res = await window.book.HDImage(id, 4, operateBookType)
softwareStore.spin.tip = '正在进行高清检查。。。'
let checkImage = await window.book.CheckImageFileSize(value.id, 10240, OperateBookType.BOOKTASK)
softwareStore.spin.spinning = false
if (res.code == 1) {
message.success('高清成功')
if (checkImage.code == 0) {
message.error(checkImage.message)
return
}
//
if (checkImage.data && checkImage.data.length > 0) {
//
let msg = checkImage.data.map((item, index) => {
return item.outImagePath + '\n'
})
dialog.warning({
title: '高清警告',
content: '下面的图片大于10MB,是否继续高清?' + '\n' + msg,
positiveText: '确定',
negativeText: '取消',
maskClosable: false,
onPositiveClick: async () => {
alert('确认高清')
await hdImageFunc(value.id, OperateBookType.BOOKTASK)
}
})
} else {
message.error(res.message)
//
await hdImageFunc(value.id, OperateBookType.BOOKTASK)
}
}
async function hdImageFunc(id, operateBookType) {
let da = dialog.warning({
title: '高清提示',
content: `是否确认高清,当前的高清倍数为 ${softwareStore.globalSetting.hdScale} 倍,是否继续?`,
positiveText: '继续',
negativeText: '取消',
onPositiveClick: async () => {
da.destroy()
softwareStore.spin.spinning = true
softwareStore.spin.tip = '正在高清中。。。'
let res = await window.book.HDImage(
id,
softwareStore.globalSetting.hdScale ?? 2,
operateBookType
)
softwareStore.spin.spinning = false
if (res.code == 1) {
message.success('高清成功')
} else {
message.error(res.message)
}
}
})
}
/**
* 生成草稿
*/
async function ClipDraft(value) {
dialog.info({
closeOnEsc: false,
title: `生成草稿前检查 ${value.name}`,
maskClosable: false,
content: () =>
h(ManageBookTaskGenerateInformation, {
bookTask: value,
type: 'bookTask',
optionType: 'draft'
})
})
}
/**
* 合成视频
*/
async function GenerateVideo(value) {
dialog.info({
closeOnEsc: false,
title: `合成视频前检查 ${value.name}`,
maskClosable: false,
content: () =>
h(ManageBookTaskGenerateInformation, {
bookTask: value,
type: 'bookTask',
optionType: 'video'
})
})
}
/**
* 重置小说数据
* @param e
*/
async function ReSetBookTaskDetail(value) {
dialog.warning({
title: '重置小说任务',
positiveText: '确定',
negativeText: '取消',
content:
'确定要重置小说任务吗?该操作不可逆,会将对应的批次任务的数据清空,分镜数据全部删除,请谨慎操作!',
onPositiveClick: async () => {
let res = await window.book.ReSetBookTask(value.id, OperateBookType.BOOKTASK)
if (res.code == 1) {
message.success('重置小说任务成功')
} else {
message.error(res.message)
}
}
})
}
/**
* 删除小说任务
*/
async function DeleteBookTask(value) {
dialog.warning({
title: '删除小说任务',
positiveText: '确定',
negativeText: '取消',
content:
'确定要删除小说任务吗?该操作不可逆,会将对应的批次任务数据和分镜数据全部删除,请谨慎操作!',
onPositiveClick: async () => {
let res = await window.book.DeleteBookTask(value.id, OperateBookType.BOOKTASK)
if (res.code == 1) {
//
let bookTaskRes = await reverseManageStore.GetBookTaskDataFromDB({
bookId: reverseManageStore.selectBook.id
})
softwareStore.spin.spinning = false
if (bookTaskRes.code == 0) {
message.error(bookTaskRes.message)
return
}
//
message.success('删除小说任务并刷新数据成功')
} else {
message.error(res.message)
}
}
})
}
async function handleSelect(key) {
showDropdown.value = false
switch (key) {
case 'hd':
await HDImage(selectRow.value)
break
case 'draft':
await ClipDraft(selectRow.value)
break
case 'generateVideo':
await GenerateVideo(selectRow.value)
break
case 'reset':
await ReSetBookTaskDetail(selectRow.value)
break
case 'delete':
await DeleteBookTask(selectRow.value)
break
default:
message.error('未知的下拉值')
break
}
}
function onClickoutside() {
showDropdown.value = false
}
// /**
// *
// */
// async function hdImageFunc2(id, operateBookType) {
// softwareStore.spin.spinning = true
// softwareStore.spin.tip = ''
// let res = await window.book.HDImage(id, 4, operateBookType)
// softwareStore.spin.spinning = false
// if (res.code == 1) {
// message.success('')
// } else {
// message.error(res.message)
// }
// }
/**
* 一键高清全部
*/
async function HDImageAll() {
console.log('一键高清', checkedRowKeysRef.value)
if (checkedRowKeysRef.value.length == 0) {
message.error('请选择要高清的数据')
return
@@ -214,21 +437,99 @@ async function DraftAll() {
* 一键生成视频
*/
async function VideoAll() {
alert('视频全部')
if (checkedRowKeysRef.value.length == 0) {
message.error('请选择要生成草稿的任务')
return
}
// 稿
dialog.info({
closeOnEsc: false,
title: `生成草稿前检查 ${reverseManageStore.selectBook.name}`,
maskClosable: false,
content: () =>
h(ManageBookTaskGenerateInformation, {
bookTask: reverseManageStore.selectBook,
type: 'book',
selectBookTask: [...checkedRowKeysRef.value],
optionType: 'video'
})
})
}
/**
* 一键重置
*/
async function ResetAll() {
alert('重置全部')
if (checkedRowKeysRef.value.length == 0) {
message.error('请选择要高清的数据')
return
}
dialog.warning({
title: '重置选中小说任务',
positiveText: '确定',
negativeText: '取消',
content:
'确定要重置选中的小说任务吗?该操作不可逆,会将对应的批次任务的数据清空,分镜数据全部删除,请谨慎操作!',
onPositiveClick: async () => {
let res = await window.book.ReSetBookTask(
[...checkedRowKeysRef.value],
OperateBookType.ASSIGNBOOKTASK
)
if (res.code == 1) {
//
let bookTaskRes = await reverseManageStore.GetBookTaskDataFromDB({
bookId: reverseManageStore.selectBook.id
})
softwareStore.spin.spinning = false
if (bookTaskRes.code == 0) {
message.error(bookTaskRes.message)
return
}
message.success('重置小说任务成功')
} else {
message.error(res.message)
}
}
})
}
/**
* 一键删除
*/
async function DeleteAll() {
alert('删除全部')
if (checkedRowKeysRef.value.length == 0) {
message.error('请选择要高清的数据')
return
}
dialog.warning({
title: '删除所选小说任务',
positiveText: '确定',
negativeText: '取消',
content:
'确定要删除选中的小说任务吗?该操作不可逆,会将对应的批次任务数据和分镜数据全部删除,请谨慎操作!',
onPositiveClick: async () => {
let res = await window.book.DeleteBookTask(
[...checkedRowKeysRef.value],
OperateBookType.ASSIGNBOOKTASK
)
if (res.code == 1) {
//
let bookTaskRes = await reverseManageStore.GetBookTaskDataFromDB({
bookId: reverseManageStore.selectBook.id
})
softwareStore.spin.spinning = false
if (bookTaskRes.code == 0) {
message.error(bookTaskRes.message)
return
}
//
message.success('删除小说任务并刷新数据成功')
} else {
message.error(res.message)
}
}
})
}
const renderIcon = () => {
return h(NIcon, null, {
@@ -245,6 +546,17 @@ const rowProps = (row) => {
softwareStore.spin.tip = '正在加载数据'
//
router.push({ name: 'manage_book', params: { id: row.id } })
},
onContextmenu: (e) => {
e.preventDefault()
selectRow.value = row
showDropdown.value = false
options = createOptions(row)
nextTick().then(() => {
showDropdown.value = true
x.value = e.clientX
y.value = e.clientY
})
}
}
}
@@ -87,7 +87,7 @@ import { isEmpty } from 'lodash'
import { TranslateType } from '../../../../../define/enum/translate'
import { DEFINE_STRING } from '../../../../../define/define_string'
import FindReplaceRound from '../../Icon/FindReplaceRound.vue'
import DatatableHeaderAfterGptSelectAndReplace from '../Components/DatatableHeaderAfterGptSelectAndReplace.vue'
import DatatableHeaderAfterGptSelectAndReplace from '../MJReverse/DatatableHeaderAfterGptSelectAndReplace.vue'
import { BookRepalceDataType } from '../../../../../define/enum/bookEnum'
let softwareStore = useSoftwareStore()
@@ -60,7 +60,7 @@ import { useSoftwareStore } from '../../../../../stores/software'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import { BookRepalceDataType, OperateBookType } from '../../../../../define/enum/bookEnum'
import FindReplaceRound from '../../Icon/FindReplaceRound.vue'
import DatatableHeaderAfterGptSelectAndReplace from '../Components/DatatableHeaderAfterGptSelectAndReplace.vue'
import DatatableHeaderAfterGptSelectAndReplace from '../MJReverse/DatatableHeaderAfterGptSelectAndReplace.vue'
let message = useMessage()
let dialog = useDialog()
let softwareStore = useSoftwareStore()
@@ -73,7 +73,7 @@ import { useReverseManageStore } from '../../../../../stores/reverseManage'
import ImportWordAndSrt from '../Components/ImportWord/ImportWordAndSrt.vue'
import CharacterAnalyze from '../Components/PresetLibrary/CharacterAnalyze.vue'
import PromptSetting from '../../Original/Components/PromptSetting.vue'
import MonitorStatus from '../Components/MonitorStatus.vue'
import MonitorStatus from '../MJReverse/MonitorStatus.vue'
import {
BookBackTaskType,
BookImageCategory,
@@ -20,8 +20,8 @@
<script setup>
import { ref, h, onMounted, watch } from 'vue'
import { NDataTable, useMessage } from 'naive-ui'
import DatatableHeaderAfterGpt from '../Components/DatatableHeaderAfterGpt.vue'
import DatatableAfterGpt from '../Components/DatatableAfterGpt.vue'
import DatatableHeaderAfterGpt from '../MJReverse/DatatableHeaderAfterGpt.vue'
import DatatableAfterGpt from '../MJReverse/DatatableAfterGpt.vue'
import ODatatableHeaderCharacterAndScene from './ODataTableHeaderCharacterAndScene.vue'
import ODatatableCharacterAndScene from './ODataTableCharacterAndScene.vue'
import ODataTableGptPrompt from './ODataTableGptPrompt.vue'
@@ -29,8 +29,8 @@ import ODataTableHeaderGptPrompt from './ODataTableHeaderGptPrompt.vue'
import ODataTableHeaderPrompt from './ODatatableHeaderPrompt.vue'
import ODatatablePrompt from './ODatatablePrompt.vue'
import ODataTableAction from './ODataTableAction.vue'
import DatatableHeaderGenerateImage from '../Components/DatatableHeaderGenerateImage.vue'
import DatatableGenerateImage from '../Components/DatatableGenerateImage.vue'
import DatatableHeaderGenerateImage from '../MJReverse/DatatableHeaderGenerateImage.vue'
import DatatableGenerateImage from '../MJReverse/DatatableGenerateImage.vue'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import { useSoftwareStore } from '../../../../../stores/software'
let reverseManageStore = useReverseManageStore()
@@ -171,7 +171,6 @@ async function ManageAccount(remote = null) {
settingStore.actionRemoteMJ = remote
}
//
let dW = 800
let dH = 600
dialog.create({
@@ -509,7 +509,6 @@ async function openGptBuyUrl() {
* 添加多个账号这样可以同时跑多个账号
*/
async function AddMultiMjAccount() {
//
let dW = window.innerWidth * 0.9
let dH = window.innerHeight * 0.9
dialog.create({
@@ -468,7 +468,6 @@ export default defineComponent({
}
//
//
dp = dialog.create({
name: 'progressDialog',
showIcon: false,