打造沉浸式智能AI问答助手:Vue3 + UniApp 全端实战(支持 Markdown/公式/多模态交互)
在移动互联网时代,用户期待的不再是一个简单的关键词匹配机器人,而是一个能理解上下文、支持富文本展示、甚至能解答数学难题的智能对话助手。
本文将基于真实的 Vue3 + UniApp 项目代码,深入剖析如何构建一个企业级智能问答 H5/小程序应用。我们将重点讲解会话状态管理 、Markdown 与 LaTeX 公式渲染 、多模式推荐算法 以及附件预览下载等核心功能的实现细节。
🎯 系统核心亮点
本系统不仅是一个聊天界面,它解决的是复杂知识表达 与流畅交互体验的痛点:
- 双模式智能应答:支持"模型优化模式"(直接回答)与"知识匹配模式"(推荐相关问题),灵活适配不同业务场景。
- 专业内容渲染 :集成
markdown-it与katex,完美支持富文本、代码高亮及复杂的数学公式渲染。 - 会话生命周期管理:自动检测会话超时,支持本地缓存恢复断点续聊,确保用户体验不中断。
- 多模态交互:支持图文混排、附件在线预览/下载、一键复制、满意度评价(已解决/未解决)等丰富操作。
🏗️ 核心模块深度解析
1. 沉浸式对话流与状态机
对话列表采用经典的"左问右答"布局,通过时间轴串联整个会话过程。系统内置严谨的状态机,处理新建会话、追加提问、超时结束等逻辑。
💾 会话持久化与断点续聊
利用 uni.setStorageSync 缓存 sessionId,用户刷新页面或重新进入时,自动恢复上次会话上下文。
typescript
const CACHE_KEY = 'intelligent_qa_session_id';
const CACHE_EXPIRE_TIME = 60 * 60 * 1000; // 1 小时过期
// 从本地缓存获取 sessionId
const getSessionFromCache = (): number | null => {
try {
const cacheData = uni.getStorageSync(CACHE_KEY);
if (!cacheData) return null;
const parsed = JSON.parse(cacheData);
// 检查缓存是否过期
if (Date.now() - parsed.timestamp > CACHE_EXPIRE_TIME) {
uni.removeStorageSync(CACHE_KEY);
return null;
}
return parsed.sessionId;
} catch (error) {
return null;
}
};
// 发送消息时自动创建或复用会话
const handleSend = async () => {
if (data.sessionId) {
// 复用现有会话
await AddSessionQARecord({ question: data.message, sessionId: data.sessionId });
} else {
// 创建新会话
const res = await AddSessionInfo({ question: data.message });
data.sessionId = res.data.sessionId;
saveSessionToCache(res.data.sessionId); // 缓存 ID
// 启动定时器轮询会话状态(判断是否超时)
addSessionTimer = setInterval(findSessionDetailById, 30000);
}
await findSessionQARecordList(); // 刷新列表并滚动到底部
};
⏳ 超时自动结束
后端返回 endTime 后,前端停止轮询并显示"会话已结束"提示,禁止继续发送消息。
vue
<template>
<div v-if="data.sessionEndTime" class="question-answer-end-list">
<div class="question-answer-end-list-title">
客户会话超时,本次会话已经结束 {{ moment(data.sessionEndTime).calendar() }}
</div>
</div>
<!-- 发送前校验 -->
<div @click="handleRecommendClick(answer)">
<!-- 若已超时,点击推荐问题也无效 -->
<script>
if(data.sessionEndTime){
message.warning('客户会话超时,本次会话已经结束');
return;
}
</script>
</div>
</template>
2. 强大的内容渲染引擎 (Markdown + LaTeX)
针对教育、科研等场景,系统必须支持复杂的数学公式和富文本。我们使用 markdown-it 配合 markdown-it-katex 插件实现。
typescript
import MarkdownIt from 'markdown-it';
import markdownItKatex from 'markdown-it-katex';
// 初始化渲染器
const md = new MarkdownIt();
md.use(markdownItKatex); // 启用 LaTeX 支持
// 渲染函数
const renderedMarkdown = (item: any) => {
const content = item.answer;
// 移除模型模式下的特殊标记(可选)
const cleanContent = data.systemSessionModel === '1' ? content.replace(/<[^>]+>/g, '') : content;
return md.render(cleanContent);
};
UI 展示:
- 通过
v-html将渲染后的 HTML 插入页面。 - 引入
katex.min.css确保公式样式正确。 - 支持行内公式
$E=mc^2$和块级公式$$...$$。
vue
<div class="question-answer-content-item-content-text">
<!-- 模型优化模式:直接渲染 answer -->
<span v-if="data.systemSessionModel==='1'" v-html="renderedMarkdown(item)"></span>
<!-- 知识匹配模式:渲染第一个匹配知识的答案 -->
<span v-else-if="item?.answerList?.length===1" v-html="renderedMarkdownHtml(item.answerList[0])"></span>
</div>
3. 多模式智能应答策略
系统支持两种核心应答模式,通过后端配置动态切换:
模式一:模型优化模式 (Direct Answer)
AI 直接生成最终答案,适合通用问答。
- 逻辑 :直接渲染
item.answer字段。 - 特点:响应快,无需用户二次选择。
🔍 模式二:知识匹配模式 (Recommendation)
当问题模糊或存在多个相关知识时,系统返回候选列表,引导用户精准提问。
vue
<!-- 推荐列表展示 -->
<div class="question-answer-recommend-section" v-if="data.systemSessionModel==='2' && item.answerList.length > 1">
<div class="question-answer-recommend-title">您是否要咨询以下问题呢:</div>
<div class="question-answer-recommend-list">
<div
v-for="(answer, idx) in item.answerList"
:key="answer.knowledgeId"
class="question-answer-recommend-item"
@click="handleRecommendClick(answer)"
>
{{ answer.question }}
</div>
</div>
</div>
<!-- 无匹配结果兜底 -->
<div v-else-if="data.systemSessionModel==='2' && item.answerList.length === 0">
<div class="question-answer-recommend-title">
很抱歉,目前我没有这个问题的相关答案...
</div>
</div>
交互逻辑 :
点击推荐问题后,自动将该问题填入输入框并模拟发送 (simulateAddSessionQARecord),形成闭环。
4. 附件管理与多媒体交互
支持在答案中携带附件(PDF、Word、图片等),提供预览和下载功能。
vue
<div class="question-answer-attachment-section" v-if="item.answerList[0]?.annexList?.length > 0">
<div class="question-answer-attachment-header">
<span>附件</span><span class="question-answer-attachment-line"></span>
</div>
<div class="question-answer-attachment-list">
<div v-for="annex in item.answerList[0].annexList" :key="annex.id" class="question-answer-attachment-item">
<img src="@/static/images/common-type-file.svg" />
<!-- 文件名截断显示 -->
<span class="question-answer-attachment-name" @click="handlePreview(annex)">
{{ annex.name.length > 40 ? annex.name.substring(0, 40) + '...' : annex.name }}
</span>
<!-- 下载按钮 -->
<img src="@/static/images/Download.svg" @click.stop="handleDownload(annex)" />
</div>
</div>
</div>
核心方法:
- 预览 :拼接
onlinePreviewPath+ Base64 编码的文件路径,在新窗口打开。 - 下载 :使用
file-saver库,通过fetch获取 Blob 流并触发浏览器下载。
typescript
const handleDownload = async (item: any) => {
const prefixPath = data.prefixPath || '';
try {
const response = await fetch(`${prefixPath}${item.path}`);
const blob = await response.blob();
saveAs(blob, item.name); // 触发下载
} catch (error) {
// 降级处理:直接跳转链接
window.open(`${prefixPath}${item.path}`);
}
};
5. 用户反馈与辅助功能
- 满意度评价:每条回答下方提供"已解决"/"未解决"按钮,实时上报反馈数据,用于优化知识库。
- 一键复制:支持复制纯文本答案,方便用户留存。
- 消息提醒:顶部导航栏集成 Badge 红点,提示有待处理的留言回复,点击直达留言页。
typescript
// 评价逻辑
const handleResolve = async (item: any) => {
item.evaluate = item.evaluate === 1 ? null : 1; // 切换状态
await EvaluateSessionQARecord({
sessionId: data.sessionId,
qaRecordId: item.id,
evaluate: item.evaluate,
});
message.success('感谢您的反馈!');
};
💡 最佳实践与细节优化
- 平滑滚动 :每次新消息加载后,使用
scrollIntoView({ behavior: 'smooth' })自动滚动到底部,提升阅读体验。 - 防抖与加载态 :发送消息时显示
uni.showLoading,防止重复提交;输入框限制 500 字并实时提示。 - 响应式布局 :适配 H5 全屏模式与弹窗模式 (
isFullScreen/isModal),动态计算容器高度。 - 安全过滤:在渲染 Markdown 前,根据模式选择性过滤 HTML 标签,防止 XSS 攻击(视具体需求而定)。
- 视觉分层 :
- 用户消息:蓝色气泡,右对齐。
- 系统消息:灰色背景,左对齐,带圆角。
- 推荐问题:可点击链接样式,引导性强。
📊 效果总结
- ** 智能灵活**:双模式切换,既能直接作答又能引导探索,适应不同复杂度场景。
- 📐 专业呈现:完美支持 LaTeX 公式与富文本,满足学术、技术类问答需求。
- 🔄 体验连贯:会话缓存、超时控制、自动滚动,打造如原生 App 般的流畅体验。
- 📎 功能完备:附件预览下载、满意度评价、消息通知,覆盖用户全链路需求。
✅ 结语
这套智能问答系统不仅实现了基础的对话功能,更在内容渲染能力 、交互逻辑严密性 和用户反馈闭环 上做了深度打磨。它适用于高校教务咨询、企业技术支持、图书馆参考咨询等多种场景,是构建现代化智能客服体系的优秀范本。
💡 未来展望:后续可引入语音输入/输出、多轮对话上下文记忆、以及基于用户画像的个性化推荐,让助手更加"懂你"。
技术栈 :Vue3 | UniApp | TypeScript | Markdown-it | Katex | File-saver
适用场景:智能客服 | 教育问答 | 技术支持 | 知识库检索
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏!有任何关于 Markdown 渲染优化或会话状态管理的问题,欢迎在评论区交流~