基于 uni-app 与 vue3 整合对接 deepseek-v3,实战开发一套支持跨平台(小程序、Web、App端)的流式输出AI问答系统。该系统被命名为 uni-vue3-deepseek。
该项目支持暗黑与亮色主题模式,并可编译运行至 H5、小程序及 App 端。
技术栈
项目采用以下技术栈进行构建:
- 开发工具:Hbuilder X 4.57
- 核心技术框架:Uniapp + Vue3 + Pinia2 + Vite5.x
- 大模型框架:DeepSeek-V3
- UI组件库:uni-ui 与 uv-ui
- 代码高亮:highlight.js
- Markdown解析:ua-markdown
- 本地缓存:pinia-plugin-unistorage
- 支持平台:H5、小程序、APP端
项目结构与框架
本项目使用 uniapp 搭配 vue3 搭建整体框架,并整合了 deepseek-v3 以实现流式AI对话功能。
核心配置
main.js 配置
在 main.js 中使用 createSSRApp 创建应用实例,并引入 Pinia 进行状态管理。
import App from './App'
import { createSSRApp } from 'vue'
// 引入pinia状态管理
import pinia from '@/pinia'
export function createApp() {
const app = createSSRApp(App)
app.use(pinia)
return {
app,
pinia
}
}
环境变量配置
在项目根目录下创建 .env 配置文件,用于管理API密钥等敏感信息。
# 项目名称
VITE_APPNAME = 'Uniapp-DeepSeek'
# 运行端口
VITE_PORT = 5173
# DeepSeek API配置
VITE_DEEPSEEK_API_KEY = 替换为你的APIKey
VITE_DEEPSEEK_BASE_URL = https://api.deepseek.com
项目模板与布局
项目采用了一个包含导航栏、聊天主区域和底部输入框的布局。主视图根据当前会话状态动态显示聊天记录或欢迎信息。
欢迎界面展示了项目Logo和简介,并提供了示例提问选项,用户可以点击或更换这些提示语。
聊天编辑器部分支持 Markdown 内容的解析与渲染,具备以下特性:
- 支持代码块的横向滚动显示。
- 可显示代码行号(关闭可提升性能)。
- 提供代码复制功能(H5/App端)。
- 图片渲染宽度自适应为100%。
- 支持图片预览功能(H5/App端)。
- 支持链接跳转功能(H5/App端)。
跨端流式输出实现
为实现不同平台下的流式输出,项目采用了平台特定的实现方案。
H5 和 APP 端:通过 renderjs 模式下的 fetch 方法调用 DeepSeek API,并设置 stream: true 开启流式传输。
// #ifdef APP-PLUS || H5
this.fetchAppH5({
url: baseURL+'/v1/chat/completions',
method: 'POST',
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKEY}`,
},
body: {
messages: this.multiConversation ? this.historySession : [{role: 'user', content: editorValue}],
model: 'deepseek-chat', // 也可使用 deepseek-reasoner 推理模型
stream: true, // 流式输出
max_tokens: 8192,
temperature: 0.4,
}
})
// #endif
小程序端:使用 uni.request 并开启 enableChunked: true 选项以实现分块流式传输,通过 onChunkReceived 事件回调处理接收到的数据块。
// #ifdef MP-WEIXIN
try {
const requestTask = await uni.request({
url: baseURL+'/v1/chat/completions',
method: 'POST',
header: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKEY}`,
},
data: {
messages: this.multiConversation ? this.historySession : [{role: 'user', content: editorValue}],
model: 'deepseek-chat',
stream: true,
max_tokens: 8192,
temperature: 0.4,
},
enableChunked: true, // 开启分块传输
})
requestTask.onChunkReceived((res) => {
const uint8Array = new Uint8Array(res.data)
let text = String.fromCharCode.apply(null, uint8Array)
const buffer = decodeURIComponent(escape(text))
this.parseBuffer(buffer) // 解析数据
})
} catch (error) {
// 错误处理...
}
// #endif