这个问题终于解决了!好开心。
先看最终效果:
video_20240724_141543_edit
项目背景:vue3
场景:像gpt一样可以对话,当用户发送问题之后,ai回复,ai是一部分一部分回复,像打印机式输出。后端返回的是流式数据,且这个数据是如下格式:
data里的content存放的就是ai回复的一部分数据,但这个数据是Unicode格式的字符串,前端(我)需要做的就是实现视频中的效果:打印机式的输出+实时解析markdown文本并正确渲染到页面上。
如果你只是要实现打印机式的输出,直接看我之前的一篇文章就行:
像ChatGPT一样实现打印机式输出_vue 仿gpt打印显示-CSDN博客
如果你要实现:打印机式的输出+实时解析markdown文本并正确渲染到页面上,就请继续往下看。
特别提示:如果你接收到的数据格式和我的不一样,我也不确定能不能帮到你,因为之前我的后端给我返回的数据格式不长这样,之前是直接是data:'数据'的格式,我试过很多方法都不能边接收markdown语法的数据,边正确解析渲染到页面上,当时我没想过可能是后端数据格式的问题,我就一直认为是我这边的问题。所以如果你怎么试都不成功,可以试着让后端改改。
解析Unicode格式的字符串的方法
// 解码包含Unicode转义序列的字符串
function decodeUnicode(str) {
return str.replace(/\\u[\dA-Fa-f]{4}/g, function(match) {
return String.fromCharCode(parseInt(match.substr(2), 16));
});
}
配置环境
//为了接收流式数据,需导入
npm install --save @microsoft/fetch-event-source
//这里我使用的是markdown-it这个库去解析markdown文本。
npm install markdown-it --save
下面两块代码,其实就是整个效果的完整代码
//script标签中
// 导入EventSource,这里使用fetchEventSource去接收流式数据
import { fetchEventSource } from '@microsoft/fetch-event-source';
// 导入解析markdown语法的第三方库markdown-it
import MarkdownIt from 'markdown-it'
let md: MarkdownIt = new MarkdownIt()
// 聊天框内容列表
let chatDatas = ref([])
// 解码包含Unicode转义序列的字符串
function decodeUnicode(str) {
return str.replace(/\\u[\dA-Fa-f]{4}/g, function(match) {
return String.fromCharCode(parseInt(match.substr(2), 16));
});
}
// 发送信息按钮
let sendMessage = async () => {
let arr1=reactive({
注意初始值要为空字符串,后面才能拼接
content: ''
});
chatDatas.push(arr1)
// 请求数据,流式输出
await fetchEventSource(baseURL+'/require/stream_generate_requirements', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify({
要传递的参数
}),
async onmessage(ev) {
// ev.data里面是实时传递过来的数据
// 根据后端返回的数据,我这里需要将字符串转成对象
let obj = JSON.parse(ev.data)
// 拿到具体的内容
let content = obj.content
// Unicode转成中文
let decodeContent = decodeUnicode(content)
// 拼接:这里是数据打印机式输出的关键
arr1.content+=decodeContent
},
//会话发送完毕时触发
onclose() {
这里可以写结束时,你需要做的事,如果没有,可以删除
}
})
}
// template标签中
<div
v-for="i in chatDatas"
:key="i.content"
>
<p v-html="md.render(i.content)"></p>
</div>
拓展:代码高亮
如果你收到的数据中包含代码,你想让代码高亮,则你需要添加这些东西:
配置:
npm install highlight.js --save
// script标签中
// 引入代码高亮
import hljs from 'highlight.js';
// 你用到了什么语言就要引入什么语言,目前我还不知道怎么样导入所有语言
import javascript from 'highlight.js/lib/languages/javascript';
// 这个是高亮的样式,有很多,我选了这个
import 'highlight.js/styles/ir-black.css';
hljs.registerLanguage('javascript', javascript);
let md: MarkdownIt = MarkdownIt({
highlight: function (str: string, lang: string) {
const language = hljs.getLanguage(lang);
if (language) {
try {
return `<div>
<div>
<span>${lang}</span>
</div>
<div class="hljs">
<code>${hljs.highlight(lang, str, true).value}</code>
</div>
</div>`;
} catch (error) {
console.error(error);
}
}
// 如果未指定语言或无法识别语言,则使用默认的逃逸 HTML 处理
return `<div class="hl-code">
<div>
<span>${lang}</span>
</div>
<div class="hljs">
<code>${md.utils.escapeHtml(str)}</code>
</div>
</div>`;
}
})
到这里,基本的功能和样式应该都实现了,希望能帮到你。
如果本文对你有帮助,希望能得到你的点赞或收藏或关注,这是对我最好的鼓励;
如你有问题或疑惑,欢迎在评论区写下,必将努力解答;
如本文有误区,希望你不吝赐教,让我们共勉!