|
|
|
@ -14,18 +14,20 @@ |
|
|
|
|
<el-skeleton :rows="1" animated/> |
|
|
|
|
</div> |
|
|
|
|
<div v-else class="complete row flex-align-center"> |
|
|
|
|
<div class="col"><i class="el-icon-circle-check"></i>文章已生成 |
|
|
|
|
</div> |
|
|
|
|
<div class="col"><i class="el-icon-circle-check"></i>文章已生成</div> |
|
|
|
|
<el-button type="primary" @click="insertEditor" |
|
|
|
|
v-if="isComplete">插入 |
|
|
|
|
</el-button> |
|
|
|
|
</div> |
|
|
|
|
<div class="ai-editor_html v-overflow-y" ref="generatedContent" v-html="formattedText"></div> |
|
|
|
|
<div class="ai-editor_html v-overflow-y" ref="generatedContent" v-html="rawTextChunks"></div> |
|
|
|
|
<div class="ai-editor__tips" v-if="isComplete"><i class="el-icon-warning-outline"></i>内容由AI生成,请注意甄别真实性 |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<VEditor :content="EditorText"></VEditor> |
|
|
|
|
<VEditor :content="EditorText" ref="vEditor"></VEditor> |
|
|
|
|
<div class="v-edit-tool" v-if="!isGenerating"> |
|
|
|
|
<div class="v-edit-tool-item down" @click="downLoadDoc"><i class="iconfont icon-down"></i></div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<!-- 对话右侧 --> |
|
|
|
|
<div class="ai-edit-right m-r-large" :class="showPage?'show':'hide'"> |
|
|
|
@ -107,10 +109,20 @@ |
|
|
|
|
</el-form> |
|
|
|
|
</div> |
|
|
|
|
<div class="ai-ecode-bot"> |
|
|
|
|
<el-button :disabled="!isComplete" type="primary" size="small" style="width: 100%;" |
|
|
|
|
@click="generateContent"> |
|
|
|
|
<i class="iconfont icon-generate ai-icon-small"></i> 重新生成 |
|
|
|
|
</el-button> |
|
|
|
|
<el-row :gutter="20"> |
|
|
|
|
<el-col :span="12"> |
|
|
|
|
<el-button :disabled="!isComplete" type="primary" size="small" style="width: 100%;" |
|
|
|
|
@click="generateContent"> |
|
|
|
|
<i class="iconfont icon-generate ai-icon-small"></i> 重新生成 |
|
|
|
|
</el-button> |
|
|
|
|
</el-col> |
|
|
|
|
<el-col :span="12"> |
|
|
|
|
<el-button :disabled="!isComplete" type="primary" size="small" style="width: 100%;" |
|
|
|
|
@click="generateContent"> |
|
|
|
|
<i class="el-icon-download ai-icon-small"></i> MarkDown下载 |
|
|
|
|
</el-button> |
|
|
|
|
</el-col> |
|
|
|
|
</el-row> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
@ -178,13 +190,18 @@ |
|
|
|
|
> |
|
|
|
|
<div class="ai-knowledge-dialog"> |
|
|
|
|
<div class="knowledge-search"> |
|
|
|
|
<div class="row flex-align-center flex-justify-end text-right" v-if="!searchState" @click="searchState=true"><i class="el-icon-search m-r-mimi"></i>搜索 |
|
|
|
|
<div class="row flex-align-center flex-justify-end text-right" v-if="!searchState" @click="searchState=true"> |
|
|
|
|
<i class="el-icon-search m-r-mimi"></i>搜索 |
|
|
|
|
<el-divider direction="vertical"></el-divider> |
|
|
|
|
</div> |
|
|
|
|
<div v-else> |
|
|
|
|
<el-input placeholder="请输入内容" v-model="input2"> |
|
|
|
|
<template slot="prepend"><el-button slot="append" icon="el-icon-arrow-left" @click="searchState=false"></el-button></template> |
|
|
|
|
<template slot="append"> <el-button slot="append" icon="el-icon-search"></el-button></template> |
|
|
|
|
<template slot="prepend"> |
|
|
|
|
<el-button slot="append" icon="el-icon-arrow-left" @click="searchState=false"></el-button> |
|
|
|
|
</template> |
|
|
|
|
<template slot="append"> |
|
|
|
|
<el-button slot="append" icon="el-icon-search"></el-button> |
|
|
|
|
</template> |
|
|
|
|
</el-input> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
@ -227,7 +244,7 @@ |
|
|
|
|
|
|
|
|
|
<script> |
|
|
|
|
import FileUpload from '@/components/FileUpload2' |
|
|
|
|
import VEditor from "@/views/components/v-editor/index.vue"; |
|
|
|
|
import VEditor from "@/views/components/v-editor/index1.vue"; |
|
|
|
|
import * as AiApi from '@/api/ai-api' |
|
|
|
|
import MarkdownIt from "markdown-it"; |
|
|
|
|
import {getUrlContent} from '@/api/ai-api' |
|
|
|
@ -250,9 +267,8 @@ export default { |
|
|
|
|
}; |
|
|
|
|
return { |
|
|
|
|
buffer: "", |
|
|
|
|
partialHTML: "", |
|
|
|
|
md: new MarkdownIt(), |
|
|
|
|
rawTextChunks: [], |
|
|
|
|
rawTextChunks: "", |
|
|
|
|
EditorText: "", |
|
|
|
|
validate: validateUrl, |
|
|
|
|
showPage: true,//页面展开与隐藏 |
|
|
|
@ -281,11 +297,7 @@ export default { |
|
|
|
|
searchState: false |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
computed: { |
|
|
|
|
formattedText() { |
|
|
|
|
return this.rawTextChunks.join(''); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
computed: {}, |
|
|
|
|
mounted() { |
|
|
|
|
if (this.$route.params.prompt) { |
|
|
|
|
this.form.prompt = this.$route.params.prompt |
|
|
|
@ -293,13 +305,18 @@ export default { |
|
|
|
|
} else { |
|
|
|
|
this.form.prompt = localStorage.getItem('prompt') |
|
|
|
|
} |
|
|
|
|
this.isComplete = true |
|
|
|
|
//this.generateContent(); |
|
|
|
|
//this.isComplete = true |
|
|
|
|
this.generateContent(); |
|
|
|
|
}, |
|
|
|
|
methods: { |
|
|
|
|
downLoadDoc(){ |
|
|
|
|
console.log(this.$refs,this.$refs['vEditor'].getAiEditor()) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}, |
|
|
|
|
insertEditor() { |
|
|
|
|
this.isGenerating = false |
|
|
|
|
this.EditorText = this.partialHTML |
|
|
|
|
this.EditorText = this.rawTextChunks |
|
|
|
|
}, |
|
|
|
|
processChunk(Chunk) { |
|
|
|
|
if (!Chunk) { |
|
|
|
@ -307,21 +324,21 @@ export default { |
|
|
|
|
} else { |
|
|
|
|
this.buffer += Chunk; |
|
|
|
|
} |
|
|
|
|
// 智能分段处理 - 避免切割Markdown语法结构 |
|
|
|
|
let lastNewLine |
|
|
|
|
lastNewLine = this.buffer.lastIndexOf(' <br>'); |
|
|
|
|
if (lastNewLine === -1) return ''; |
|
|
|
|
const complete = this.buffer.substring(0, lastNewLine); |
|
|
|
|
this.buffer = this.buffer.substring(lastNewLine); |
|
|
|
|
let lastNewLine = this.buffer.lastIndexOf(' <br>'); |
|
|
|
|
let html |
|
|
|
|
// 异步解析并返回HTML |
|
|
|
|
if (complete.includes('img')) { |
|
|
|
|
html = complete.replace(' <br>', '') |
|
|
|
|
if (this.buffer.includes('#')) { |
|
|
|
|
if (lastNewLine === -1) return ''; |
|
|
|
|
const complete = this.buffer.substring(0, lastNewLine); |
|
|
|
|
html = this.md.render(complete); |
|
|
|
|
this.buffer = "" |
|
|
|
|
} else { |
|
|
|
|
html = this.md.render(complete.replace(' <br>', '')); |
|
|
|
|
if (lastNewLine != -1) { |
|
|
|
|
this.buffer = "" |
|
|
|
|
} else { |
|
|
|
|
html = Chunk |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
this.partialHTML += html; |
|
|
|
|
return html; |
|
|
|
|
return html |
|
|
|
|
}, |
|
|
|
|
/** 生成 页面内容 */ |
|
|
|
|
async generateContent(type) { |
|
|
|
@ -340,7 +357,7 @@ export default { |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
// 重置状态 |
|
|
|
|
this.rawTextChunks = [] |
|
|
|
|
this.rawTextChunks = "" |
|
|
|
|
this.isGenerating = true; |
|
|
|
|
this.isComplete = false; |
|
|
|
|
this.progressText = "" |
|
|
|
@ -376,7 +393,7 @@ export default { |
|
|
|
|
try { |
|
|
|
|
const html = this.processChunk(data); |
|
|
|
|
if (html) { |
|
|
|
|
this.rawTextChunks.push(html); // 直接存储原始数据(可能包含HTML标签) |
|
|
|
|
this.rawTextChunks += html; // 直接存储原始数据(可能包含HTML标签) |
|
|
|
|
this.$nextTick(this.scrollToBottom('generatedContent')) |
|
|
|
|
} |
|
|
|
|
} catch (e) { |
|
|
|
@ -579,4 +596,3 @@ export default { |
|
|
|
|
} |
|
|
|
|
</script> |
|
|
|
|
|
|
|
|
|
<style src="@wangeditor/editor/dist/css/style.css"></style> |
|
|
|
|