Stackedit/src/components/modals/ChatGptModal.vue
2023-06-29 21:49:02 +08:00

128 lines
3.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<modal-inner class="modal__inner-1--chatgpt" aria-label="chatgpt">
<div class="modal__content">
<div class="modal__image">
<icon-chat-gpt></icon-chat-gpt>
</div>
<p><b>ChatGPT内容生成</b><br>生成时长受ChatGPT服务响应与网络响应时长影响时间可能较长</p>
<form-entry label="生成内容要求详细描述" error="content">
<textarea slot="field" class="text-input" type="text" placeholder="输入内容(支持换行)" v-model.trim="content" :disabled="generating"></textarea>
<div class="form-entry__info">
使用 <a href="https://chat1.52ai.pw/" target="_blank">chat1.52ai.pw</a> 的免费接口生成内容AI模型是GPT-3.5 Turbo
</div>
</form-entry>
<div class="modal__result">
<pre class="result_pre" v-if="generating && !result">(等待生成中...)</pre>
<pre class="result_pre" v-else v-text="result"></pre>
</div>
</div>
<div class="modal__button-bar">
<button class="button" @click="reject()">{{ generating ? '停止' : '关闭' }}</button>
<button class="button button--resolve" @click="generate" v-if="!generating && !!content">{{ !!result ? '重新生成' : '开始生成' }}</button>
<button class="button button--resolve" @click="resolve" v-if="!generating && !!result">确认插入</button>
</div>
</modal-inner>
</template>
<script>
import modalTemplate from './common/modalTemplate';
import chatGptSvc from '../../services/chatGptSvc';
import store from '../../store';
export default modalTemplate({
data: () => ({
generating: false,
content: '',
result: '',
xhr: null,
}),
methods: {
resolve(evt) {
evt.preventDefault();
const { callback } = this.config;
this.config.resolve();
callback(this.result);
},
process({ done, content, error }) {
if (done) {
this.generating = false;
// 已结束
} else if (content) {
this.result = this.result + content;
const container = document.querySelector('.result_pre');
container.scrollTo(0, container.scrollHeight); // 滚动到最底部
} else if (error) {
this.generating = false;
}
},
generate() {
this.generating = true;
this.result = '';
try {
this.xhr = chatGptSvc.chat({
content: `${this.content}\n(使用Markdown方式输出结果)`,
}, this.process);
} catch (err) {
this.generating = false;
store.dispatch('notification/error', err);
}
},
reject() {
if (this.generating) {
if (this.xhr) {
this.xhr.abort();
this.generating = false;
}
return;
}
const { callback } = this.config;
this.config.reject();
callback(null);
},
},
async created() {
// store chatgpt配置
const config = localStorage.getItem('chatgpt/config');
store.dispatch('chatgpt/setCurrConfig', JSON.parse(config || '{}'));
},
});
</script>
<style lang="scss">
@import '../../styles/variables.scss';
.modal__inner-1.modal__inner-1--chatgpt {
max-width: 560px;
.result_pre {
font-size: 0.9em;
font-variant-ligatures: no-common-ligatures;
line-height: 1.25;
white-space: pre-wrap;
word-break: break-word;
word-wrap: break-word;
height: 300px;
border: 1px solid rgb(126, 126, 126);
border-radius: $border-radius-base;
padding: 10px;
overflow-y: scroll; /* 开启垂直滚动条 */
}
.result_pre::-webkit-scrollbar {
display: none; /* 隐藏滚动条 */
}
.result_pre.scroll-bottom {
scroll-behavior: smooth;
}
.config-warning {
color: #f00;
}
.text-input {
min-height: 60px;
}
}
</style>