You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
2.8 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<base-container>
<h2 class="pt-5 pb-5">流式显示文本(需先启动node-local-server项目作为本地服务端)</h2>
<div>
<el-button
type="primary"
@click="handleSend"
>问个问题</el-button
>
<el-button
type="primary"
@click="handleClose"
>停止</el-button
>
</div>
<div
class="wordbox"
ref="contentRef"
@scroll="contentScrollFN"
>
<div
id="content"
v-html="content"
></div>
</div>
</base-container>
</template>
<script setup>
import { ref } from 'vue';
import { fetchEventSource } from '@microsoft/fetch-event-source';
import { useAutoScroll } from '@/hooks/useAutoScroll';
const { canAutoScroll, contentRef, contentScrollFN } = useAutoScroll();
const content = ref('');
const controller = ref(null);
const updateContent = (event) => {
content.value += event.data;
if (event.data === 'End') {
/**
* 注释部分为前端手动关闭sse连接的实现
* 这里不手动关闭原因是@microsoft/fetch-event-source这个框架可以正确检测后段服务端是否关闭了连接所以不需要手动关闭
* 浏览器原生new EventSource()方法无法检测后端服务端是否关闭连接,所以需要手动关闭(每次后段关闭都会进onerror事件)
* 具体请看另外一个demo sseNative.vue
*/
// handleClose();
}
};
const handleError = (event) => {
console.log(event);
console.log('sse连接出错');
};
const handleClose = () => {
console.log('sse关闭');
controller.value.abort();
};
const handleSend = () => {
canAutoScroll.value = true;
controller.value = new AbortController();
const signal = controller.value.signal;
/** @microsoft/fetch-event-source该框架支持POST方法并且支持传参 */
fetchEventSource('http://localhost:3000/events', {
method: 'POST',
body: JSON.stringify({
question: '你好,我是小雅,请问有什么可以帮助您?',
token: 'xxxx',
}),
onmessage: updateContent,
onerror: handleError,
onclose: handleClose,
signal,
});
};
</script>
<style lang="scss" scoped>
.wordbox {
width: 100%;
height: 200px;
position: relative;
overflow-y: auto;
overflow-x: hidden;
padding: 20px;
border: 1px solid #ccc;
margin: 20px 0;
border-radius: 5px;
scrollbar-width: none;
word-break: break-all;
}
.wordbox::-webkit-scrollbar {
display: none; /* 隐藏滚动条 */
}
@media screen and (min-width: 768px) {
.wordbox {
width: 400px;
}
}
</style>