更新记录
uni-ai-chat 1.1(2026-07-30) 下载此版本
✅ 第一阶段开发完成 - 项目骨架 + 核心 Chat UI 组件
按照 uni-ai-chat-plugin-plan.md 计划,第一阶段(第1周)的所有文件已创建完成:
平台兼容性
uni-app(5.08)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| - | √ | - | - | - | - | - | - | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | - | - | - | - | - | - | - | - | - | - | - |
🤖 uni-ai-chat 插件使用说明
UniApp AI 智能对话组件 — 支持多模型接入、SSE 流式输出、会话管理、暗黑模式、国际化等特性。
📋 目录
🚀 快速开始
1. 安装依赖
npm install uni-ai-chat pinia
# 或
yarn add uni-ai-chat pinia
2. 注册组件
在 main.js 中注册 Pinia 和组件:
import { createSSRApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
export function createApp() {
const app = createSSRApp(App)
// 注册 Pinia 状态管理(必须)
app.use(createPinia())
return { app }
}
3. 页面中使用
<template>
<view class="chat-page">
<UniAiChat
apiKey="your-api-key-here"
model="gpt-4o-mini"
systemPrompt="你是一个智能助手,请用中文回答用户的问题。"
:contextRounds="10"
@error="handleError"
/>
</view>
</template>
<script setup>
import UniAiChat from '@/uni-ai-chat/components/uni-ai-chat/index.vue'
function handleError(error) {
console.error('Chat error:', error.message)
}
</script>
<style>
.chat-page {
height: 100vh;
}
</style>
📦 安装与配置
方式一:npm 安装(推荐)
npm install uni-ai-chat
方式二:手动引入
将 uni-ai-chat 目录复制到项目的 uni_modules/ 或 components/ 目录下,然后直接引用:
import UniAiChat from '@/uni-ai-chat/components/uni-ai-chat/index.vue'
配置 Vite 别名
在 vite.config.js 中配置 @ 别名:
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import path from 'path'
export default defineConfig({
plugins: [uni()],
resolve: {
alias: {
'@': path.resolve(__dirname, './')
}
}
})
微信小程序注意事项
微信小程序不支持 AbortController,需要引入 polyfill:
// main.js 顶部
import './uni-ai-chat/utils/abort-controller-polyfill.js'
📖 组件 Props
| 参数 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
apiKey |
String | '' |
是 | API Key,用于调用 AI 模型接口 |
model |
String | 'gpt-4o-mini' |
否 | 模型名称,详见支持的模型 |
apiEndpoint |
String | '' |
否 | 自定义 API 端点,留空使用模型默认端点 |
systemPrompt |
String | '你是一个智能助手...' |
否 | 系统提示词,定义 AI 角色和行为 |
contextRounds |
Number | 10 |
否 | 上下文记忆轮数(每轮一问一答) |
temperature |
Number | 0.7 |
否 | 温度参数 (0-2),值越高回答越随机 |
maxTokens |
Number | 2048 |
否 | 最大 Token 数,限制单次回答长度 |
enableVoice |
Boolean | false |
否 | 是否启用语音输入按钮 |
darkMode |
Boolean/String | 'auto' |
否 | 暗黑模式:true 开启、false 关闭、'auto' 跟随系统 |
locale |
String | '' |
否 | 语言设置:'zh-CN'、'en-US'、'ja-JP'、'ko-KR',留空自动检测 |
showSessionList |
Boolean | true |
否 | 是否显示左侧会话列表 |
sessionListTitle |
String | '' |
否 | 会话列表标题,留空使用默认 |
inputPlaceholder |
String | '' |
否 | 输入框占位符文本,留空使用默认 |
emptyText |
String | '' |
否 | 空状态提示文本,留空使用默认 |
Props 使用示例
<UniAiChat
:apiKey="'sk-xxx'"
:model="'deepseek-chat'"
:apiEndpoint="'https://api.deepseek.com/v1'"
:systemPrompt="'你是一名资深的前端工程师,擅长 Vue 和 UniApp 开发。'"
:contextRounds="20"
:temperature="0.8"
:maxTokens="4096"
:enableVoice="true"
:darkMode="'auto'"
:locale="'zh-CN'"
:showSessionList="true"
:sessionListTitle="'历史对话'"
:inputPlaceholder="'请输入您的问题...'"
:emptyText="'开始一段新的对话吧 ✨'"
/>
📡 组件 Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
@error |
请求出错时触发 | (error: Error) |
@send |
发送消息时触发 | (message: Object) — { id, role, content, timestamp } |
@response |
收到完整响应时触发 | (response: String) — 完整响应文本 |
@sessionChange |
切换会话时触发 | (sessionId: String) |
Events 使用示例
<template>
<UniAiChat
ref="chatRef"
:apiKey="apiKey"
@error="onError"
@send="onSend"
@response="onResponse"
@sessionChange="onSessionChange"
/>
</template>
<script setup>
function onError(error) {
console.error('请求出错:', error.message)
uni.showToast({ title: `错误:${error.message}`, icon: 'none' })
}
function onSend(message) {
console.log('用户发送消息:', message.content)
}
function onResponse(response) {
console.log('AI 响应完成')
}
function onSessionChange(sessionId) {
console.log('切换到会话:', sessionId)
}
</script>
🛠️ 组件 Methods
通过 ref 获取组件实例后调用:
| 方法名 | 说明 | 参数 |
|---|---|---|
toggleDarkMode() |
切换暗黑模式 | 无 |
clearMessages() |
清除当前会话所有消息 | 无 |
createSession() |
创建新会话 | 无 |
switchSession(id) |
切换到指定会话 | sessionId: String |
Methods 使用示例
<template>
<view>
<button @click="toggleDark">切换暗黑模式</button>
<button @click="clearChat">清除对话</button>
<button @click="newSession">新建会话</button>
<UniAiChat ref="chatRef" :apiKey="apiKey" />
</view>
</template>
<script setup>
import { ref } from 'vue'
const chatRef = ref(null)
const apiKey = 'sk-xxx'
function toggleDark() {
chatRef.value?.toggleDarkMode()
}
function clearChat() {
chatRef.value?.clearMessages()
}
function newSession() {
chatRef.value?.createSession()
}
</script>
🤖 支持的模型
| 模型标识 | 模型名称 | 提供商 | 适配器 | 默认端点 |
|---|---|---|---|---|
gpt-4o |
GPT-4o | OpenAI | openai | https://api.openai.com/v1 |
gpt-4o-mini |
GPT-4o Mini | OpenAI | openai | https://api.openai.com/v1 |
deepseek-chat |
DeepSeek V3 | DeepSeek | openai | https://api.deepseek.com/v1 |
ernie-4.0 |
文心一言 4.0 | 百度 | ernie | https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat |
qwen-max |
通义千问 Max | 阿里云 | qwen | https://dashscope.aliyuncs.com/api/v1 |
使用自定义模型
如果使用与 OpenAI 兼容接口的模型(如 Claude 通过 API 代理、本地 LLM 等),只需设置 apiEndpoint 即可:
<UniAiChat
apiKey="sk-xxx"
model="gpt-4o-mini" <!-- 模型标识可自定义 -->
apiEndpoint="https://your-proxy.com/v1"
/>
🏗️ 项目结构
uni-ai-chat/
├── components/
│ └── uni-ai-chat/ # 核心组件
│ ├── index.vue # 主组件入口(聊天界面整体布局)
│ ├── chat-message.vue # 消息气泡组件(渲染对话消息)
│ ├── chat-input.vue # 输入框组件(文本输入/发送/停止)
│ ├── chat-session.vue # 会话列表组件(管理多会话)
│ ├── sse-parser.js # SSE 流式解析器(解析 AI 流式响应)
│ └── style.scss # 样式文件(浅色/深色主题)
├── utils/
│ ├── api.js # API 请求封装(多模型适配、流式请求)
│ ├── storage.js # 本地存储工具(基于 uni-storage)
│ ├── markdown.js # Markdown 渲染工具(解析→节点树→HTML)
│ └── i18n.js # 国际化工具(中/英/日/韩)
├── store/
│ └── chat.js # Pinia 状态管理(会话、消息、流式更新)
├── config/
│ └── index.js # 配置文件(模型列表、默认参数、存储键名)
├── USAGE.md # 本使用说明文档
├── README.md # 项目简介文档
└── package.json # 包信息
💻 完整示例
基础聊天页面
<template>
<view class="chat-container">
<!-- 顶部工具栏 -->
<view class="toolbar" :style="{ paddingTop: safeAreaTop + 'px' }">
<view class="toolbar-left">
<button class="tool-btn" @click="toggleSessionList">
<text>☰</text>
</button>
</view>
<view class="toolbar-center">
<text class="toolbar-title">AI 智能对话</text>
<text class="toolbar-subtitle">{{ currentModelName }}</text>
</view>
<view class="toolbar-right">
<button class="tool-btn" @click="toggleDark">
<text>{{ isDark ? '☀️' : '🌙' }}</text>
</button>
<button class="tool-btn" @click="showSettings = true">
<text>⚙️</text>
</button>
</view>
</view>
<!-- 聊天组件 -->
<view class="chat-wrapper">
<UniAiChat
ref="chatRef"
:apiKey="settings.apiKey"
:model="settings.model"
:apiEndpoint="settings.apiEndpoint"
:systemPrompt="settings.systemPrompt"
:contextRounds="settings.contextRounds"
:temperature="settings.temperature"
:maxTokens="settings.maxTokens"
:darkMode="isDark ? true : 'auto'"
:showSessionList="showSessions"
@error="handleError"
/>
</view>
<!-- 设置弹窗 -->
<view class="modal-overlay" v-if="showSettings" @click="showSettings = false">
<view class="modal-content" @click.stop>
<view class="modal-header">
<text>⚙️ 设置</text>
<button @click="showSettings = false">✕</button>
</view>
<scroll-view class="modal-body" scroll-y>
<view class="form-group">
<text>API Key</text>
<input v-model="settings.apiKey" type="text" password />
</view>
<view class="form-group">
<text>系统提示词</text>
<textarea v-model="settings.systemPrompt" maxlength="500" />
</view>
<view class="form-group">
<text>上下文轮数:{{ settings.contextRounds }}</text>
<slider v-model="settings.contextRounds" :min="1" :max="50" />
</view>
</scroll-view>
<view class="modal-footer">
<button @click="saveSettings">保存设置</button>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import UniAiChat from '@/uni-ai-chat/components/uni-ai-chat/index.vue'
import { SUPPORTED_MODELS } from '@/uni-ai-chat/config/index'
const chatRef = ref(null)
const isDark = ref(false)
const showSettings = ref(false)
const showSessions = ref(true)
const safeAreaTop = ref(44)
const settings = reactive({
apiKey: '',
model: 'gpt-4o-mini',
apiEndpoint: '',
systemPrompt: '你是一个智能助手,请用中文回答用户的问题。',
contextRounds: 10,
temperature: 0.7,
maxTokens: 2048
})
const currentModelName = computed(() => {
return SUPPORTED_MODELS[settings.model]?.name || settings.model
})
onMounted(() => {
loadSettings()
// 适配状态栏高度
try {
const info = uni.getSystemInfoSync()
safeAreaTop.value = (info.statusBarHeight || 20) + 44
} catch (e) {}
})
function toggleDark() {
isDark.value = !isDark.value
chatRef.value?.toggleDarkMode()
}
function toggleSessionList() {
showSessions.value = !showSessions.value
}
function loadSettings() {
try {
const saved = uni.getStorageSync('chat-settings')
if (saved) Object.assign(settings, saved)
} catch (e) {}
}
function saveSettings() {
try {
uni.setStorageSync('chat-settings', settings)
} catch (e) {}
showSettings.value = false
uni.showToast({ title: '设置已保存', icon: 'success' })
}
function handleError(error) {
uni.showToast({ title: error.message, icon: 'none' })
}
</script>
<style>
.chat-container {
display: flex;
flex-direction: column;
height: 100vh;
background-color: #F5F5F5;
}
.toolbar {
display: flex;
align-items: center;
padding: 6px 12px;
background-color: #FFFFFF;
border-bottom: 1px solid #E5E5EA;
z-index: 10;
}
.toolbar-center {
flex: 1;
text-align: center;
}
.toolbar-title {
font-size: 16px;
font-weight: 600;
}
.toolbar-subtitle {
font-size: 11px;
color: #8E8E93;
}
.chat-wrapper {
flex: 1;
overflow: hidden;
}
/* 设置弹窗样式 */
.modal-overlay {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.4);
z-index: 1000;
display: flex;
align-items: flex-end;
justify-content: center;
}
.modal-content {
width: 100%;
max-height: 80vh;
background: #FFFFFF;
border-radius: 16px 16px 0 0;
}
.modal-body {
padding: 16px 20px;
max-height: 50vh;
}
.form-group {
margin-bottom: 16px;
}
.form-group text {
display: block;
font-size: 14px;
margin-bottom: 6px;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 10px 12px;
border: 1px solid #E5E5EA;
border-radius: 8px;
font-size: 14px;
background: #F5F5F5;
box-sizing: border-box;
}
.form-group textarea {
height: 80px;
resize: none;
}
</style>
🔧 高级用法
1. 自定义 API 代理
通过后端代理转发请求,避免前端暴露 API Key:
<UniAiChat
:apiKey="'proxy-token'"
:apiEndpoint="'https://your-backend.com/api/chat'"
:model="'gpt-4o'"
/>
后端代理示例(Node.js):
app.post('/api/chat', async (req, res) => {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`
},
body: JSON.stringify(req.body)
})
// 流式转发
response.body.pipe(res)
})
2. 多模型切换
<template>
<view>
<picker :range="modelList" @change="onModelChange">
<text>{{ currentModel }}</text>
</picker>
<UniAiChat ref="chatRef" :apiKey="apiKey" :model="currentModel" />
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { SUPPORTED_MODELS } from '@/uni-ai-chat/config/index'
const currentModel = ref('gpt-4o-mini')
const modelList = computed(() =>
Object.entries(SUPPORTED_MODELS).map(([key, val]) => `${val.name} (${key})`)
)
function onModelChange(e) {
const keys = Object.keys(SUPPORTED_MODELS)
currentModel.value = keys[e.detail.value]
}
</script>
3. 暗黑模式跟随系统
<UniAiChat
:darkMode="'auto'"
@sessionChange="onSessionChange"
/>
配合外部切换按钮:
function toggleDarkMode() {
chatRef.value?.toggleDarkMode()
}
4. 国际化配置
<!-- 英文 -->
<UniAiChat :locale="'en-US'" />
<!-- 日文 -->
<UniAiChat :locale="'ja-JP'" />
<!-- 韩文 -->
<UniAiChat :locale="'ko-KR'" />
5. 移动端适配(隐藏会话列表)
<template>
<UniAiChat
:showSessionList="!isMobile"
@sessionChange="onSessionChange"
/>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const isMobile = ref(false)
onMounted(() => {
try {
const info = uni.getSystemInfoSync()
isMobile.value = info.windowWidth < 768
} catch (e) {}
})
</script>
❓ 常见问题
Q1: 如何获取 API Key?
- OpenAI: 在 platform.openai.com/api-keys 创建
- DeepSeek: 在 platform.deepseek.com 获取
- 通义千问: 在阿里云 DashScope 控制台获取
- 文心一言: 在百度智能云控制台获取
Q2: 为什么消息发送后没有响应?
- 检查
apiKey是否正确配置 - 检查网络连接是否正常
- 查看控制台是否有 CORS 错误(微信小程序需配置合法域名)
- 检查 API 余额是否充足
Q3: 微信小程序中无法使用?
微信小程序需要:
- 在
manifest.json的mp-weixin中配置urlCheck: false - 在微信公众平台配置
request合法域名(如api.openai.com) - 引入
AbortControllerpolyfill
Q4: 如何清除所有聊天记录?
// 通过组件方法清除当前会话
chatRef.value?.clearMessages()
// 或通过 Storage 工具清除所有数据
import Storage from '@/uni-ai-chat/utils/storage'
Storage.clearAll()
Q5: 如何自定义样式?
组件使用 CSS 变量控制主题,可以覆盖这些变量:
/* 覆盖主题色 */
.uni-ai-chat {
--chat-user-bubble: #4CAF50; /* 用户气泡颜色 */
--chat-link-color: #FF5722; /* 链接/主题色 */
--chat-bg: #FAFAFA; /* 背景色 */
}
Q6: 支持哪些平台?
- ✅ H5(浏览器)
- ✅ 微信小程序
- ✅ App(iOS/Android)
- ✅ 支付宝小程序
- ✅ 百度小程序
- ✅ 头条小程序
Q7: 如何接入其他模型?
如果模型使用 OpenAI 兼容接口,直接设置 apiEndpoint 即可:
<UniAiChat
apiKey="sk-xxx"
model="custom-model"
apiEndpoint="https://your-api.com/v1"
/>
如需添加新的模型适配器,可在 config/index.js 中添加模型配置,并在 utils/api.js 中添加对应的请求格式处理。
📄 许可证
MIT License © 2024
💡 提示: 更多信息请查看 README.md 或访问项目主页。

收藏人数:
下载插件并导入HBuilderX
下载插件ZIP
赞赏(0)
下载 0
赞赏 0
下载 12467892
赞赏 1936
赞赏
京公网安备:11010802035340号