vue使用post请求处理接口返回EventStream数据并进行展示

之前已经发过简单使用get请求接口EventStream数据:
vue处理接口返回EventStream数据并进行展示

使用post请求接口EventStream数据具体操作如下:

使用sse.js第三方插件实现:

安装sse.js:

javascript 复制代码
npm install sse

vue页面代码:

javascript 复制代码
import { SSE } from 'sse.js';
import { parseMarkdown } from '@/utils/markdownParser'
export default {
	name: "chat",
	data() {
		return {
			sseFun: null,
		};
	},
	methods: {
		// 使用 sse.js 实现
		connectSSEJS(data){
			let token = window.sessionStorage.getItem('token');
			let para = {
				参数1: 参数1的值,
				参数1: 参数2的值,
			}
			this.sseFun = new SSE(`接口地址`, {
				method: 'POST',
				payload: JSON.stringify(para),
				headers: {
					'Content-Type': 'application/json;charset=utf-8',
					'token': `${token}`
				},
			});
			let that = this;
			let _webSearchResultList = [];
			this.sseFun.onmessage = (event) => {
				// console.log('收到消息:', event.data);
				let _data= JSON.parse(this.decodeBase64ToUtf8(event.data));
				if(_data.state==='start'){
					// 接收数据的第一条标识:state为start(具体根据接口返回的情况进行判断),可储存或处理一些数据
				}
				// 对接收到的数据进行处理
				let dealTxt = String(_data.message);
				const newText = dealTxt.replace(/\$ref_(\d+)/g, (match, number) => {
					return `<span class="webmark" style="background: rgb(255, 232, 230);
					color: rgb(230, 0, 19);
					padding: 1px 8px;
					border-radius: 10px;
					margin-right: 4px;" 
					data-link="${_webSearchResultList.find(i=>i.refer == match).link}" 
					data-title="${_webSearchResultList.find(i=>i.refer == match).title}">网页 ${number}</span>`;
				});
				// 此处的parseMarkdown用于解析和渲染Markdown文本,具体代码在下面
				this.streamText = parseMarkdown(String(newText.replace(/\\\[/g, '$$$').replace(/\\\]/g, '$$$')));
				if(!_data.id){
					// 不存在id,认为数据返回完成
				}
			};
		},
		// 断开SSE连接
		disconnectSSE() {
			if (this.sseFun) {
				this.sseFun.close(); // 关闭SSE连接
				this.sseFun = null; // 清除引用,防止内存泄漏
			}
		},
	}
}

用于解析和渲染Markdown文本的markdownParser文件内容:

javascript 复制代码
import MarkdownIt from 'markdown-it'
import mk from 'markdown-it-katex';  // 匹配数学公式
import sanitizer from "markdown-it-sanitizer";
import hljs from 'highlight.js'; // 匹配代码
import DOMPurify from 'dompurify'

// 初始化 Markdown 解析器
const md = new MarkdownIt({
  html: true,         // 允许 HTML 标签
  linkify: false,      // 自动转换链接
  typographer: true,  // 优化排版
  tabels: true,       // 允许表格

  highlight: (str, lang) => {  // 代码高亮
    // 代码高亮逻辑
    if (lang && hljs.getLanguage(lang)) {
      try {
        return `<pre class="hljs"><code>${
          hljs.highlight(str, { language: lang, ignoreIllegals: true }).value
        }</code></pre>`;
      } catch (__) {}
    }
    // 未指定语言时,自动检测
    return `<pre class="hljs" style="background: #fafafa;"><code>${hljs.highlightAuto(str).value}</code></pre>`;
  }
})
md.use(mk, {
  macros: {
    // 物理符号
    "\\e": "\\mathrm{e}",
    "\\ii": "\\mathrm{i}",
    "\\dd": "\\mathop{}\\!\\mathrm{d}",
    "\\bra": ["\\left\\langle #1 \\right|", 1],
    "\\ket": ["\\left| #1 \\right\\rangle", 1],
    "\\vect": ["\\mathbf{#1}", 1],
    "\\tensor": ["\\underline{\\underline{#1}}", 1],
    "\\ev": ["\\left\\langle #1 \\right\\rangle", 1],
    
    // 数学符号
    "\\Z": "\\mathbb{Z}",
    "\\Q": "\\mathbb{Q}",
    "\\C": "\\mathbb{C}",
    "\\R": "\\mathbb{R}",
    "\\abs": ["\\left| #1 \\right|", 1],
    "\\pd": ["\\frac{\\partial #1}{\\partial #2}", 2],
    "\\matrix": "\\begin{pmatrix} #1 \\\\ #2 \\end{pmatrix}",
    "\\pmatrix": ["\\begin{pmatrix} #1 \\\\ #2 \\end{pmatrix}", 2],
    "\\eq": ["\\begin{equation} #1 \\end{equation}", 1],

    // 化学
    "\\xrightarrow": ["\\overset{#2}{\\longrightarrow}", 2],
    "\\chem": ["\\mathrm{#1}", 1],

    // 统计力学
    "\\kB": "k_{\\text{B}}",
    "\\mean": ["\\left\\langle #1 \\right\\rangle", 1],
    "\\var": ["\\operatorname{Var}(#1)", 1],
    "\\cov": ["\\operatorname{Cov}(#1, #2)", 2],
    "\\dB": ["\\, \\text{dB}", 0],

    // 动态宏
    "\\unit": (ctx) => {
      const args = ctx.consumeArgs(1);
      return `\\, \\text{${args[0]}}`;
    },
    "\\grad": (context) => {
      const args = context.consumeArgs(1); // 读取参数
      return `\\nabla ${args[0]}`;
    },
  },
  throwOnError: false,
  displayMode:true
}); // 启用 KaTeX 插件

// 自定义链接处理(设置 target="_blank")
md.renderer.rules.link_open = (tokens, idx, options) => {
  const token = tokens[idx]
  const hrefIndex = token.attrIndex('href')
  if (hrefIndex >= 0) {
    token.attrPush(['target', '_blank'])
    token.attrPush(['rel', 'noopener noreferrer'])
  }
  return md.renderer.renderToken(tokens, idx, options)
}

// 解析并净化 Markdown
export function parseMarkdown(content) {
  const rawHtml = md.render(content)
  return DOMPurify.sanitize(rawHtml)
}
相关推荐
css趣多多1 天前
this.$watch
前端·javascript·vue.js
Code小翊1 天前
JS语法速查手册,一遍过JS
javascript
干前端1 天前
Vue3虚拟滚动列表组件进阶:不定高度及原理分析!!!
前端·前端组件
子春一1 天前
Flutter for OpenHarmony:构建一个 Flutter 天气卡片组件,深入解析动态 UI、响应式布局与语义化设计
javascript·flutter·ui
雨季6661 天前
Flutter 三端应用实战:OpenHarmony “极简文本行数统计器”
开发语言·前端·flutter·ui·交互
有来技术1 天前
ASP.NET Core 权限管理系统(RBAC)设计与实现|vue3-element-admin .NET 后端
vue.js·后端·c#·asp.net·.net
qq_12498707531 天前
基于springboot的林业资源管理系统设计与实现(源码+论文+部署+安装)
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
MAHATMA玛哈特科技1 天前
以曲求直:校平技术中的反直觉哲学
前端·数据库·制造·校平机·矫平机·液压矫平机
C澒1 天前
前端技术核心领域与实践方向
前端·系统架构
Remember_9931 天前
Java 单例模式深度解析:设计原理、实现范式与企业级应用场景
java·开发语言·javascript·单例模式·ecmascript