基于deepseek实现的ai问答小程序
2025年12月4日 19:02
功能预览
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
✨ 核心特性
🚀 流式数据处理
- 由于微信小程序这里对SSE的流式处理不支持,只有chunks的模式,故采用H5的方式来实现。
- SSE(Server-Sent Events)流式接收:实现了完整的流式数据处理机制,在收到第一块数据时立即渲染
- 分块解析与缓冲:支持多行 SSE 事件的正确解析,处理不完整的数据块
-
实时渲染反馈:使用
requestAnimationFrame优化渲染性能,避免频繁 DOM 更新导致的卡顿
💬 对话管理
- 消息追踪系统:自动生成唯一消息 ID,维护消息状态(pending/success/error)
- 会话隔离:支持多会话并行,可创建、切换、管理历史会话
- 消息快照存储:保存用户消息与 AI 回复的完整上下文
🎨 交互优化
- 思考中加载动画:AI 回复延迟时的优雅 UX——流式数据到达时即刻消失
- 自动滚动定位:智能滚动到最新消息,支持指定消息定位,避免内容变化导致的滚动位置偏移
- 消息操作面板:支持复制、点赞、重新生成等交互功能
🎯 多模型支持
-
模型切换器:支持在对话过程中动态选择不同 AI 模型
- 快速问答模式(deepseek-chat)
- 深度思考模式(deepseek-reasoner)
📝 Markdown 渲染
- 完整的 Markdown 支持:包括代码块、表格、列表、引用等
- 代码高亮:使用 highlight.js 实现多语言代码着色
- HTML 安全渲染:配置化处理,支持链接自动新窗口打开
🎨 设计系统
- 现代渐变设计:渐变色(紫→紫→粉)贯穿整个应用
- 响应式布局:基于 CSS 变量的深浅主题支持
- 动画细节:平滑的消息滑入、加载转圈、脉冲效果等
🏗️ 项目结构
src/
├── components/ # Vue 组件库
│ ├── MessageItem.vue # 单条消息渲染组件(含 Markdown 解析、操作面板)
│ ├── InputArea.vue # 输入框及工具栏(含模型选择、录音、新建会话)
│ ├── HistroySessions.vue # 历史会话管理弹窗
│ └── HelloWorld.vue # 示例组件
├── utils/
│ ├── type.ts # TypeScript 类型定义(ChatMessage、Session 等)
│ ├── request.ts # HTTP 请求封装(get/post)
│ ├── streamRequest.ts # SSE 流式请求实现
│ └── markdown.ts # Markdown 渲染引擎配置
├── assets/ # 静态资源
│ ├── regenerate-icon.svg # 重新生成按钮图标
│ ├── copy-icon.svg # 复制按钮图标
│ ├── like-icon.svg # 点赞按钮图标
│ ├── thinking-icon.svg # 思考中加载动画
│ └── logo1.png # AI 角色头像
├── App.vue # 主应用组件(核心业务逻辑)
├── main.ts # 应用入口
└── style.scss # 全局样式与设计系统变量
🔧 技术栈
| 技术 | 版本 | 用途 |
|---|---|---|
| Vue | 3.5.13 | 前端框架 |
| TypeScript | 5.8 | 类型安全 |
| Vite | 6.3.5 | 构建工具 |
| Markdown-it | 14.1.0 | Markdown 渲染 |
| highlight.js | 内置 | 代码高亮 |
| SCSS | 1.94.2 | 样式预处理 |
| Element Plus | 2.10.4 | UI 组件库(可选) |
| socket.io-client | 4.8.1 | WebSocket 支持(预留) |
📥 快速开始
前置要求
- Node.js >= 16
- npm 或 yarn
安装依赖
npm install
开发服务器
npm run dev
访问 http://localhost:5173
生产构建
npm run build
构建输出到 dist/ 目录
预览构建结果
npm run preview
🎯 核心业务流程
对话流程
用户输入 → 发送消息
↓
创建 User Message (pending)
显示在消息列表 → 自动滚动到底部
↓
调用 streamFetch(POST /api/ai/chat)
Assistant Message 创建 (pending)
↓
SSE 数据流开始接收
├─ 第一块数据到达 → status 变为 success(思考中 icon 消失)
├─ 持续接收 → 实时渲染 Markdown 内容
└─ 滚动到最新消息
↓
流结束 (onDone) → 最终更新消息状态
↓
用户可进行操作:复制、点赞、重新生成
会话管理流程
新建会话 → POST /api/ai/sessions
↓
获取 session.id → 用于后续对话上下文关联
↓
切换历史会话 → GET /api/ai/sessions/{id}/messages
↓
加载历史消息 → 等待 DOM 稳定 → 智能滚动到底部
🔐 API 接口约定
对话接口
POST /api/ai/chat
Body: {
messages: Array<{ role: string; content: string }>,
sessionId?: string | number,
stream: true,
model: string // "deepseek-chat" | "deepseek-reasoner"
}
Response: 流式 SSE
data: 文本块
[可选] event: 事件类型
[可选] id: 事件 ID
会话接口
POST /api/ai/sessions
Body: { title: string; summary?: string }
Response: { session: { id: string | number; ... } }
GET /api/ai/sessions/{id}/messages
Response: { messages: Array<HistoryMessage> }
HistoryMessage = {
role: "assistant" | "user",
content: string,
created_at?: string
}
💡 亮点分析
1. 高性能流式渲染
- 使用 requestAnimationFrame 进行 Markdown 渲染节流,避免频繁重排/重绘
- SSE 流数据的分块处理和缓冲机制确保即便数据包不完整也能正确解析
- 流式更新时的自动滚动采用两帧 rAF 等待,确保 CSS 动画和布局稳定
2. 响应式适配
- 使用rem单位做响应式适配,目前支持各种大小屏幕的设备,兼容PC端的良好显示。
关键代码
// 用于设置rem单位的字体大小(动态)
function setRem() {
const baseWidth = 375; // 设计稿宽度
const minFontSize = 6; // 最小字体
const maxFontSize = 16; // 最大字体(PC屏或大屏限制)
const html = document.documentElement;
const width = html.clientWidth;
let fontSize = (width / baseWidth) * 12;
if (fontSize < minFontSize) fontSize = minFontSize;
if (fontSize > maxFontSize) fontSize = maxFontSize;
html.style.fontSize = fontSize + 'px';
}
setRem();
window.addEventListener('resize', setRem);
## 🔄 后续优化方向
* [ ] 语音输入完整实现(当前预留)
* [ ] 消息搜索与过滤
* [ ] 导出对话记录(PDF、Markdown)
* [ ] 数据加密传输
* [ ] 更多 AI 模型集成
## 📄 相关文件说明
| 文件 | 说明 |
| ------------------ | -------------------------------- |
| `streamRequest.ts` | SSE 流式数据解析的核心实现,支持多行 data 字段 |
| `App.vue` | 主业务逻辑,包含对话流程、会话管理、自动滚动优化 |
| `MessageItem.vue` | 消息渲染与交互,思考中加载动画、Markdown 解析、操作按钮 |
| `InputArea.vue` | 输入框、模型切换、会话操作 |
| `markdown.ts` | Markdown-it 配置,代码高亮、链接处理 |
| `style.scss` | 全局设计系统,渐变、主题、动画 |