2026最新款爆肝tauri2.10+deepseek-v3.2+vite7+arco电脑端流式打字AI问答模板。
tauri2-deepseek-ai :基于vite7.3+vue3.5+tauri2+arco+markdown-it深度接入deepseek-v3.2 通用大模型。内置浅色+暗黑 主题,支持深度思考链、katex数学公式、mermaid图渲染、代码高亮/复制代码等功能。
使用技术
- 开发工具:vscode
- 跨端框架:tauri^2.10
- 前端技术框架:vite^7.3.1+vue^3.5.29+vue-router^5.0.3
- ai大模型:deepseek-v3.2 + openai
- 组件库:arco-design^2.57.0
- 状态管理:pinia^3.0.4
- 本地存储:pinia-plugin-persistedstate^4.7.1
- markdown解析:markdown-it^14.1.0
- katex公式渲染:@mdit/plugin-katex^0.25.0
项目功能性
- 跨平台Tauri2.10 框架,接入DeepSeek-V3.2,流式打字更丝滑
- 支持各种代码高亮/复制代码/下载代码、便于分享代码片段
- 支持暗黑+浅色 主题、深度思考链、上下文多轮对话、本地存储对话
- 支持katex数学公式
- 支持mermaid图解析(支持缩放/拖拽/下载svg/下载png)
- 支持点击链接跳转浏览器打开
- 使用arco-design组件库,整体风格统一
tauri2-deepseek跨端智能ai系统已经更新到我的原创作品铺,欢迎下载使用。
项目结构目录
基于 vite7.3+tauri2.10 搭建项目模板, vue3 setup 语法糖开发页面。
项目环境变量配置
修改项目根目录下.env文件里的key,替换为自己的deepseek apikey,即可丝滑体验流式对话功能。
# 项目名称
VITE_APPNAME = 'Tauri2-DeepSeek'
# 运行端口
VITE_PORT = 1420
# DeepSeek API配置
VITE_DEEPSEEK_API_KEY = 替换为你的 API Key
VITE_DEEPSEEK_BASE_URL = https://api.deepseek.com
入口文件main.js
import { createApp } from "vue"
import App from "./App.vue"
import './style.scss'
// 引入插件配置
import Plugins from './plugins'
// 引入路由/状态管理
import Router from './router'
import Pinia from './pinia'
createApp(App)
.use(Plugins)
.use(Router)
.use(Pinia)
.mount("#app")
通用布局模板
<script setup>
import { appState } from '@/pinia/modules/app'
import Titlebar from '@/layouts/components/titlebar/index.vue'
import Sidebar from '@/layouts/components/sidebar/index.vue'
const appstate = appState()
</script>
<template>
<div class="vu__chatbot">
<div class="vu__container" :style="{'--themeSkin': appstate.config.skin}">
<div class="vu__layout flexbox flex-col">
<!-- 导航栏 -->
<Titlebar />
<div class="vu__layout-body flex1 flexbox">
<!-- 侧边栏 -->
<Sidebar />
<!-- 主面板 -->
<div class="vu__layout-main flex1">
<router-view v-slot="{ Component, route }">
<keep-alive>
<component :is="Component" :key="route.path" />
</keep-alive>
</router-view>
</div>
</div>
</div>
</div>
</div>
</template>
自定义latex公式+mermaid图渲染
import { imgSize } from '@mdit/plugin-img-size' // 支持带尺寸图片
import { katex } from "@mdit/plugin-katex"; // 支持数学公式
import 'katex/dist/katex.min.css'
// 渲染mermaid图表
import { markdownItMermaidPlugin } from '@/components/markdown/plugins/mermaidPlugin'
渲染markdown数据
<Markdown
:source="item.content"
:html="true"
:linkify="true"
:typographer="true"
:plugins="[
[katex, {delimiters: 'all'}],
[markdownItMermaidPlugin]
]"
@copy="onCopy"
@preview="onPreview"
/>
封装mermaid图解析
export const markdownItMermaidPlugin = (md, options) => {
const defaultFence = md.renderer.rules.fence
md.renderer.rules.fence = (...args) => {
const [tokens, idx] = args
const token = tokens[idx]
const lang = token.info.replace(/\[.*\]/, '').trim() || ''
if(lang === 'mermaid') {
const code = token.content.trim()
const hash = generateHash(code)
const uuid = `${hash}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`
// 如果有缓存,加载缓存图表
if(renderCache.has(hash)) {
// console.log('加载缓存mermaid图表')
return `
${ defaultFence(...args) }
<div class="mermaid-container">${renderCache.get(hash)}</div>
`
}
nextTickRender(uuid)
return `
${ defaultFence(...args) }
<div class="mermaid-container" id="${uuid}" data-mermaid-hash="${hash}" data-mermaid-code="${encodeURIComponent(code)}">
<div class="mermaid-loading">📊Mermaid 图表加载中...</div>
</div>
`
}
return defaultFence(...args)
}
function nextTickRender(containerId) {
// 如果容器存在,直接渲染
if(document.getElementById(containerId)) {
renderMermaidDiagram(containerId)
return
}
// 使用MutationObserver监听DOM更新
const observer = new MutationObserver((mutations, ob) => {
const container = document.getElementById(containerId)
if(container) {
ob.disconnect()
renderMermaidDiagram(containerId)
}
})
observer.observe(document.body, {
childList: true,
subtree: true
})
}
async function renderMermaidDiagram(containerId) {
const container = document.getElementById(containerId)
if (!container) {
console.warn(`Mermaid container #${containerId} not found`)
return
}
const code = decodeURIComponent(container.dataset.mermaidCode)
const hash = container.dataset.mermaidHash
if (!code) {
return
}
// 检查 mermaid 是否可用
if (typeof window.mermaid === 'undefined') {
showError(container, 'Mermaid 库未加载!')
return
}
try {
// 配置 mermaid(如果还未配置)
if (!window.mermaid.initialized) {
window.mermaid.initialize({
startOnLoad: false,
theme: 'default',
securityLevel: 'loose',
})
window.mermaid.initialized = true
}
let svg
// 检查缓存
if(renderCache.has(hash)) {
svg = renderCache.get(hash)
}else {
const { isValid } = await verifyMermaid(code)
if(!isValid) {
showError(container, `<pre>渲染语法错误:\n${ code }\n</pre>`)
return
}
// 使用唯一ID渲染(避免图表冲突)
const {svg: renderedSvg} = await window.mermaid.render(`mermaid-${containerId}`, code)
svg = renderedSvg
renderCache.set(hash, svg)
}
// 更新容器内容
container.innerHTML = svg
container.removeAttribute('data-mermaid-hash')
container.removeAttribute('data-mermaid-code')
} catch (error) {
console.error('Mermaid 渲染失败:', error)
showError(container, `<pre>渲染图表时出错: \n ${error.message}\n</pre>`)
}
}
}
AI编辑器
<template>
<div class="v3ai__footbar flexbox flex-col">
<!-- 技能栏 -->
<div v-if="skillbar" class="v3ai__skills flexbox flex-alignc">
<div class="item" v-for="(item, index) in skills" :key="index" @click="handleSkill(item)">
<i class="iconfont" :class="item.icon"></i><span class="text">{{item.text}}</span>
</div>
</div>
<!-- 编辑栏 -->
<div class="v3ai__inputbox flexbox flex-col">
<div class="v3ai__editor flexbox">
<a-textarea v-model="editorText" :auto-size="autoSize" placeholder="想问点什么..." spellcheck="false" @input="handleInput" />
</div>
<!-- 操作栏 -->
<div class="v3ai__tools flexbox flex-alignc">
<div class="option flex1 flexbox">
<div class="btn" @click="isDeep =! isDeep"><i class="iconfont ai-deepthink"></i> 深度思考 <span class="fs-12">(R1)</span></div>
<div class="btn" @click="isNetwork =! isNetwork"><i class="iconfont ai-network"></i> 联网</div>
</div>
<a-dropdown trigger="hover" :show-arrow="false" position="lb" :content-style="{'min-width': '250px'}">
<a-button shape="circle"><icon-attachment size="18" /></a-button>
<template #content>
<a-dgroup>
<template #title><div style="margin-bottom: 5px;">从网盘添加</div></template>
<a-doption value="wx"><icon-more /> 选择网盘文件</a-doption>
</a-dgroup>
<a-dgroup>
<template #title><div style="margin-bottom: 5px;">从本地添加</div></template>
<a-doption value="wx"><icon-apps /> 上传文件</a-doption>
<a-dsubmenu trigger="hover" position="rb" :popup-translate="[8, 8]" value="option-1">
<template #default><icon-apps /> 上传代码</template>
<template #content>
<a-doption value="pyq"><icon-apps /> 代码文件</a-doption>
<a-doption value="qq"><icon-apps /> 代码文件夹</a-doption>
<a-doption value="qq"><icon-apps /> GitHub仓库</a-doption>
</template>
</a-dsubmenu>
</a-dgroup>
</template>
</a-dropdown>
<a-dropdown :show-arrow="false" position="top" :popup-translate="[-5, -5]" :content-style="{'min-width': '150px'}">
<a-button shape="circle"><icon-plus size="18" /></a-button>
<template #content>
<a-doption value="image"><icon-file-image /> 图片</a-doption>
<a-doption value="file"><icon-file /> 本地文件</a-doption>
<a-doption value="pdf"><icon-file-pdf /> PDF文档分析</a-doption>
<a-doption value="page"><icon-cloud /> 网页总结</a-doption>
</template>
</a-dropdown>
<a-divider direction="vertical" style="margin: 0 7px;" />
<a-button class="submit" type="primary" shape="circle" @click="handleSubmit">
<icon-send v-if="!sessionstate.loading" size="20" />
<icon-loading v-else size="18" />
</a-button>
</div>
</div>
</div>
</template>
tauri2+vue3调用deepseek流式效果
// 调用deepseek接口
const completion = await openai.chat.completions.create({
// 单一会话
// messages: [{role: 'user', content: editorValue}],
// 多轮会话
messages: props.multiConversation ? historySession.value : [{role: 'user', content: editorValue}],
// deepseek-chat对话模型 deepseek-reasoner推理模型
model: sessionstate.thinkingEnabled ? 'deepseek-reasoner' : 'deepseek-chat',
stream: true, // 流式输出
max_tokens: 8192,
temperature: 0.4
})
// 处理流式返回结果
for await (const chunk of completion) {
// 检查是否已终止
if(sessionstate.aborted) break
const content = chunk.choices[0]?.delta?.content || ''
// 获取推理内容
const reasoningContent = chunk.choices[0]?.delta?.reasoning_content || ''
if(content || reasoningContent) {
answerText += content
reasoningText += reasoningContent
// 限制更新频率:每100ms最多更新一次
const now = Date.now()
if(now - lastUpdate > 100) {
lastUpdate = now
requestAnimationFrame(() => {
// ...
})
}
}
if(chunk.choices[0]?.finish_reason === 'stop') {
// ...
}
}
综上就是tauri2.10+vite7接入deepseek搭建跨端ai应用的一些分享,希望对大家有些帮助!
附上几个最新实例项目
uniapp+deepseek流式ai助理|uniapp+vue3对接deepseek三端Ai问答模板
Vite7+DeepSeek网页版Ai助手|vue3+arco网页web流式生成ai聊天问答系统
electron39-vue3ai电脑端AI模板|electron39+deepseek+vite7聊天ai应用
vite7+deepseek流式ai模板|vue3.5+deepseek3.2+markdown打字输出ai助手
Electron38-Vue3OS客户端OS系统|vite7+electron38+arco桌面os后台管理
electron38-admin桌面端后台|Electron38+Vue3+ElementPlus管理系统
Electron38-Wechat电脑端聊天|vite7+electron38仿微信桌面端聊天系统
最新版Flutter3.38+Dart3.10仿写抖音APP直播+短视频+聊天应用程序
flutter3-deepseek流式AI模板|Flutter3.27+Dio+DeepSeeek聊天ai助手
最新版uniapp+vue3+uv-ui跨三端短视频+直播+聊天【H5+小程序+App端】
最新版uni-app+vue3+uv-ui跨三端仿微信app聊天应用【h5+小程序+app端】
Flutter3-MacOS桌面OS系统|flutter3.32+window_manager客户端OS模板