这个问题终于解决了!好开心。
先看最终效果:
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>`;
}
})
到这里,基本的功能和样式应该都实现了,希望能帮到你。
如果本文对你有帮助,希望能得到你的点赞或收藏或关注,这是对我最好的鼓励;
如你有问题或疑惑,欢迎在评论区写下,必将努力解答;
如本文有误区,希望你不吝赐教,让我们共勉!