mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-11-08 18:23:45 +08:00
feat: auto translate and rewrite prompt for midjourney and stable-diffusion
This commit is contained in:
@@ -244,7 +244,7 @@
|
||||
|
||||
</template>
|
||||
<script setup>
|
||||
import {nextTick, onMounted, ref} from 'vue'
|
||||
import {nextTick, onMounted, onUnmounted, ref} from 'vue'
|
||||
import ChatPrompt from "@/components/ChatPrompt.vue";
|
||||
import ChatReply from "@/components/ChatReply.vue";
|
||||
import {
|
||||
@@ -339,6 +339,10 @@ onMounted(() => {
|
||||
window.onresize = () => resizeElement();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
socket.value = null
|
||||
})
|
||||
|
||||
// 初始化数据
|
||||
const initData = () => {
|
||||
// 检查会话
|
||||
@@ -699,12 +703,11 @@ const connect = function (chat_id, role_id) {
|
||||
});
|
||||
|
||||
_socket.addEventListener('close', () => {
|
||||
if (activelyClose.value) { // 忽略主动关闭
|
||||
if (activelyClose.value || socket.value === null) { // 忽略主动关闭
|
||||
return;
|
||||
}
|
||||
// 停止发送消息
|
||||
disableInput(true)
|
||||
socket.value = null;
|
||||
loading.value = true;
|
||||
checkSession().then(() => {
|
||||
connect(chat_id, role_id)
|
||||
|
||||
@@ -218,36 +218,13 @@
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div>
|
||||
<el-button type="primary" @click="translatePrompt(false)" :disabled="translating">
|
||||
<el-icon style="margin-right: 6px;font-size: 18px;">
|
||||
<Refresh/>
|
||||
</el-icon>
|
||||
翻译
|
||||
</el-button>
|
||||
|
||||
<el-tooltip
|
||||
class="box-item"
|
||||
effect="light"
|
||||
raw-content
|
||||
content="使用 AI 翻译并重写提示词,<br/>增加更多细节,风格等描述"
|
||||
placement="top-end"
|
||||
>
|
||||
<el-button type="success" @click="rewritePrompt" :disabled="translating">
|
||||
<el-icon style="margin-right: 6px;font-size: 18px;">
|
||||
<Refresh/>
|
||||
</el-icon>
|
||||
翻译并重写
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="param-line pt">
|
||||
<el-input v-model="params.prompt" :autosize="{ minRows: 4, maxRows: 6 }" type="textarea"
|
||||
ref="promptRef"
|
||||
placeholder="这里输入你的英文咒语,例如:A chinese girl walking in the middle of a cobblestone street"/>
|
||||
placeholder="请在此输入绘画提示词,系统会自动翻译中文提示词,高手请直接输入英文提示词"/>
|
||||
</div>
|
||||
|
||||
<div class="param-line pt">
|
||||
@@ -260,19 +237,13 @@
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-button type="primary" @click="translatePrompt(true)" :disabled="translating">
|
||||
<el-icon style="margin-right: 6px;font-size: 18px;">
|
||||
<Refresh/>
|
||||
</el-icon>
|
||||
翻译
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="param-line pt">
|
||||
<el-input v-model="params.neg_prompt" :autosize="{ minRows: 4, maxRows: 6 }" type="textarea"
|
||||
ref="promptRef"
|
||||
placeholder="这里输入你不希望出现在图片上的内容,元素"/>
|
||||
placeholder="请在此输入你不希望出现在图片上的内容,系统会自动翻译中文提示词"/>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
@@ -471,7 +442,7 @@
|
||||
|
||||
<script setup>
|
||||
import {nextTick, onMounted, onUnmounted, ref} from "vue"
|
||||
import {ChromeFilled, Delete, DocumentCopy, InfoFilled, Picture, Plus, Refresh} from "@element-plus/icons-vue";
|
||||
import {ChromeFilled, Delete, DocumentCopy, InfoFilled, Picture, Plus} from "@element-plus/icons-vue";
|
||||
import Compressor from "compressorjs";
|
||||
import {httpGet, httpPost} from "@/utils/http";
|
||||
import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
|
||||
@@ -560,50 +531,9 @@ const finishedJobs = ref([])
|
||||
|
||||
const socket = ref(null)
|
||||
const power = ref(0)
|
||||
const translating = ref(false)
|
||||
const userId = ref(0)
|
||||
const isLogin = ref(false)
|
||||
|
||||
const rewritePrompt = () => {
|
||||
if (!isLogin.value) {
|
||||
showLoginDialog.value = true
|
||||
return
|
||||
}
|
||||
|
||||
translating.value = true
|
||||
httpPost("/api/prompt/rewrite", {"prompt": params.value.prompt}).then(res => {
|
||||
params.value.prompt = res.data
|
||||
translating.value = false
|
||||
}).catch(e => {
|
||||
translating.value = false
|
||||
ElMessage.error("翻译失败:" + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
const translatePrompt = (negative) => {
|
||||
if (!isLogin.value) {
|
||||
showLoginDialog.value = true
|
||||
return
|
||||
}
|
||||
|
||||
translating.value = true
|
||||
let prompt = params.value.prompt
|
||||
if (negative) {
|
||||
prompt = params.value.neg_prompt
|
||||
}
|
||||
httpPost("/api/prompt/translate", {"prompt": prompt}).then(res => {
|
||||
if (negative) {
|
||||
params.value.neg_prompt = res.data
|
||||
} else {
|
||||
params.value.prompt = res.data
|
||||
}
|
||||
translating.value = false
|
||||
}).catch(e => {
|
||||
translating.value = false
|
||||
ElMessage.error("翻译失败:" + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
const heartbeatHandle = ref(null)
|
||||
const connect = () => {
|
||||
let host = process.env.VUE_APP_WS_HOST
|
||||
@@ -646,7 +576,9 @@ const connect = () => {
|
||||
});
|
||||
|
||||
_socket.addEventListener('close', () => {
|
||||
connect()
|
||||
if (socket.value !== null) {
|
||||
connect()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -663,6 +595,10 @@ onMounted(() => {
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
socket.value = null
|
||||
})
|
||||
|
||||
// 初始化数据
|
||||
const initData = () => {
|
||||
checkSession().then(user => {
|
||||
|
||||
@@ -117,26 +117,6 @@
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="param-line">
|
||||
<el-form-item label="面部修复">
|
||||
<template #default>
|
||||
<div class="form-item-inner">
|
||||
<el-switch v-model="params.face_fix" style="--el-switch-on-color: #47fff1;"/>
|
||||
<el-tooltip
|
||||
effect="light"
|
||||
content="仅对绘制人物图像有效果。"
|
||||
raw-content
|
||||
placement="right"
|
||||
>
|
||||
<el-icon style="margin-top: 6px">
|
||||
<InfoFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="param-line">
|
||||
<el-form-item label="高清修复">
|
||||
<template #default>
|
||||
@@ -248,34 +228,10 @@
|
||||
:autosize="{ minRows: 4, maxRows: 6 }"
|
||||
type="textarea"
|
||||
ref="promptRef"
|
||||
placeholder="正向提示词,例如:A chinese girl walking in the middle of a cobblestone street"
|
||||
placeholder="请在此输入绘画提示词,系统会自动翻译中文提示词,高手请直接输入英文提示词"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style="padding: 10px">
|
||||
<el-button type="primary" @click="translatePrompt" size="small">
|
||||
<el-icon style="margin-right: 6px;font-size: 18px;">
|
||||
<Refresh/>
|
||||
</el-icon>
|
||||
翻译
|
||||
</el-button>
|
||||
|
||||
<el-tooltip
|
||||
class="box-item"
|
||||
effect="dark"
|
||||
raw-content
|
||||
content="使用 AI 翻译并重写提示词,<br/>增加更多细节,风格等描述"
|
||||
placement="top-end"
|
||||
>
|
||||
<el-button type="success" @click="rewritePrompt" size="small">
|
||||
<el-icon style="margin-right: 6px;font-size: 18px;">
|
||||
<Refresh/>
|
||||
</el-icon>
|
||||
翻译并重写
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<div class="param-line pt">
|
||||
<span>反向提示词:</span>
|
||||
<el-tooltip
|
||||
@@ -516,7 +472,7 @@
|
||||
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
|
||||
<login-dialog :show="showLoginDialog" @hide="showLoginDialog = false" @success="initData"/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -553,14 +509,13 @@ const params = ref({
|
||||
height: 1024,
|
||||
sampler: samplers[0],
|
||||
seed: -1,
|
||||
steps: 30,
|
||||
steps: 20,
|
||||
cfg_scale: 7,
|
||||
face_fix: false,
|
||||
hd_fix: false,
|
||||
hd_redraw_rate: 0.5,
|
||||
hd_redraw_rate: 0.7,
|
||||
hd_scale: 2,
|
||||
hd_scale_alg: scaleAlg[0],
|
||||
hd_steps: 15,
|
||||
hd_steps: 0,
|
||||
prompt: "",
|
||||
negative_prompt: "nsfw, paintings,low quality,easynegative,ng_deepnegative ,lowres,bad anatomy,bad hands,bad feet",
|
||||
})
|
||||
@@ -574,38 +529,7 @@ if (_params) {
|
||||
params.value = JSON.parse(_params)
|
||||
}
|
||||
const power = ref(0)
|
||||
|
||||
const rewritePrompt = () => {
|
||||
if (!isLogin.value) {
|
||||
showLoginDialog.value = true
|
||||
return
|
||||
}
|
||||
|
||||
translating.value = true
|
||||
httpPost("/api/prompt/rewrite", {"prompt": params.value.prompt}).then(res => {
|
||||
params.value.prompt = res.data
|
||||
translating.value = false
|
||||
}).catch(e => {
|
||||
translating.value = false
|
||||
ElMessage.error("翻译失败:" + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
const translatePrompt = () => {
|
||||
if (!isLogin.value) {
|
||||
showLoginDialog.value = true
|
||||
return
|
||||
}
|
||||
|
||||
translating.value = true
|
||||
httpPost("/api/prompt/translate", {"prompt": params.value.prompt}).then(res => {
|
||||
params.value.prompt = res.data
|
||||
translating.value = false
|
||||
}).catch(e => {
|
||||
translating.value = false
|
||||
ElMessage.error("翻译失败:" + e.message)
|
||||
})
|
||||
}
|
||||
const sdPower = ref(0) // 画一张 SD 图片消耗算力
|
||||
|
||||
const socket = ref(null)
|
||||
const userId = ref(0)
|
||||
@@ -651,7 +575,9 @@ const connect = () => {
|
||||
});
|
||||
|
||||
_socket.addEventListener('close', () => {
|
||||
connect()
|
||||
if (socket.value !== null) {
|
||||
connect()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -666,10 +592,17 @@ onMounted(() => {
|
||||
clipboard.value.on('error', () => {
|
||||
ElMessage.error('复制失败!');
|
||||
})
|
||||
|
||||
httpGet("/api/config/get?key=system").then(res => {
|
||||
sdPower.value = res.data["sd_power"]
|
||||
}).catch(e => {
|
||||
ElMessage.error("获取系统配置失败:" + e.message)
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
clipboard.value.destroy()
|
||||
socket.value = null
|
||||
})
|
||||
|
||||
|
||||
@@ -699,7 +632,7 @@ const fetchRunningJobs = (userId) => {
|
||||
message: `任务ID:${jobs[i]['task_id']}<br />原因:${jobs[i]['err_msg']}`,
|
||||
type: 'error',
|
||||
})
|
||||
power.value += 1
|
||||
power.value += sdPower.value
|
||||
continue
|
||||
}
|
||||
_jobs.push(jobs[i])
|
||||
@@ -761,7 +694,7 @@ const generate = () => {
|
||||
params.value.session_id = getSessionId()
|
||||
httpPost("/api/sd/image", params.value).then(() => {
|
||||
ElMessage.success("绘画任务推送成功,请耐心等待任务执行...")
|
||||
power.value -= 1
|
||||
power.value -= sdPower.value
|
||||
}).catch(e => {
|
||||
ElMessage.error("任务推送失败:" + e.message)
|
||||
})
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {nextTick, onMounted, ref} from "vue";
|
||||
import {nextTick, onMounted, onUnmounted, ref} from "vue";
|
||||
import {showImagePreview, showNotify, showToast} from "vant";
|
||||
import {onBeforeRouteLeave, useRouter} from "vue-router";
|
||||
import {dateFormat, processContent, randString, renderInputText, UUID} from "@/utils/libs";
|
||||
@@ -147,6 +147,10 @@ onMounted(() => {
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
socket.value = null
|
||||
})
|
||||
|
||||
const chatData = ref([])
|
||||
const loading = ref(false)
|
||||
const finished = ref(false)
|
||||
@@ -347,12 +351,11 @@ const connect = function (chat_id, role_id) {
|
||||
});
|
||||
|
||||
_socket.addEventListener('close', () => {
|
||||
if (activelyClose.value) { // 忽略主动关闭
|
||||
if (activelyClose.value || socket.value === null) { // 忽略主动关闭
|
||||
return;
|
||||
}
|
||||
// 停止发送消息
|
||||
canSend.value = true;
|
||||
socket.value = null;
|
||||
// 重连
|
||||
checkSession().then(() => {
|
||||
connect(chat_id, role_id)
|
||||
|
||||
@@ -67,13 +67,7 @@
|
||||
label="提示词"
|
||||
autosize
|
||||
type="textarea"
|
||||
placeholder="如:一个美丽的中国女孩站在电影院门口,手上拿着爆米花,微笑,写实风格,电影灯光效果,半身像">
|
||||
<template #button>
|
||||
<van-button v-if="translating" disabled loading type="primary"/>
|
||||
<van-button v-else size="small" type="primary" @click="translatePrompt">翻译</van-button>
|
||||
</template>
|
||||
|
||||
</van-field>
|
||||
placeholder="请在此输入绘画提示词,系统会自动翻译中文提示词,高手请直接输入英文提示词"/>
|
||||
</div>
|
||||
|
||||
<van-collapse v-model="activeColspan">
|
||||
@@ -206,7 +200,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {nextTick, onMounted, ref} from "vue";
|
||||
import {nextTick, onMounted, onUnmounted, ref} from "vue";
|
||||
import {
|
||||
showConfirmDialog,
|
||||
showFailToast,
|
||||
@@ -221,9 +215,8 @@ import Compressor from "compressorjs";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {getSessionId} from "@/store/session";
|
||||
import {checkSession} from "@/action/session";
|
||||
import Clipboard from "clipboard";
|
||||
import {useRouter} from "vue-router";
|
||||
import {Delete, Picture} from "@element-plus/icons-vue";
|
||||
import {Delete} from "@element-plus/icons-vue";
|
||||
|
||||
const title = ref('MidJourney 绘画')
|
||||
const activeColspan = ref([""])
|
||||
@@ -281,6 +274,10 @@ onMounted(() => {
|
||||
});
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
socket.value = null
|
||||
})
|
||||
|
||||
const heartbeatHandle = ref(null)
|
||||
const connect = () => {
|
||||
let host = process.env.VUE_APP_WS_HOST
|
||||
@@ -315,13 +312,15 @@ const connect = () => {
|
||||
|
||||
_socket.addEventListener('message', event => {
|
||||
if (event.data instanceof Blob) {
|
||||
fetchRunningJobs(userId.value)
|
||||
fetchFinishJobs(userId.value)
|
||||
fetchRunningJobs()
|
||||
fetchFinishJobs(1)
|
||||
}
|
||||
});
|
||||
|
||||
_socket.addEventListener('close', () => {
|
||||
connect()
|
||||
if (socket.value !== null) {
|
||||
connect()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -512,24 +511,6 @@ const showPrompt = (item) => {
|
||||
const imageView = (item) => {
|
||||
showImagePreview([item['img_url']]);
|
||||
}
|
||||
|
||||
const translating = ref(false)
|
||||
const translatePrompt = () => {
|
||||
if (params.value.prompt === '') {
|
||||
return showToast("请输入中文提示词!")
|
||||
}
|
||||
|
||||
translating.value = true
|
||||
const prompt = params.value.prompt
|
||||
httpPost("/api/prompt/translate", {"prompt": prompt}).then(res => {
|
||||
params.value.prompt = res.data
|
||||
translating.value = false
|
||||
}).catch(e => {
|
||||
translating.value = false
|
||||
showFailToast("翻译失败:" + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
|
||||
Reference in New Issue
Block a user