微信小程序集成通义千问:打造悬浮窗智能对话助手
1. 为什么要在微信小程序里集成通义千问最近两年AI对话助手火得一塌糊涂但大部分应用都是独立APP或者网页版。其实对于很多轻量级场景来说直接在微信小程序里集成AI助手反而更实用。想象一下当你在小程序里购物遇到问题时不用跳转到其他应用直接点击悬浮窗就能获得智能客服帮助这种体验是不是很爽我去年帮学弟做毕业设计时就用了这个方案。他们团队要做校园服务小程序想在咨询模块加入智能问答。传统方案要么对接第三方客服系统贵且复杂要么自己训练模型门槛太高。最后我们选择了阿里云通义千问API从接入到上线只用了3天效果还特别好。悬浮窗设计最大的优势就是非侵入性。用户不需要离开当前页面随时可以唤出对话框。这种设计模式在电商、教育、工具类小程序中特别实用。比如电商场景悬浮窗解答商品咨询学习场景随时提问知识点工具场景快速查询天气/翻译2. 前期准备工作2.1 注册阿里云账号并开通服务首先需要到阿里云官网注册账号已有账号可跳过。在控制台搜索通义千问进入产品页面后点击立即开通。目前新用户有免费额度足够毕业设计或小型项目使用。开通后要做三件事获取AccessKey在控制台AccessKey管理页面创建记录API调用地址一般是https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation查看计费方式注意免费额度用完后会按量计费建议在本地先测试API调用是否正常。这里给出Python测试代码import dashscope from dashscope import Generation dashscope.api_key 你的API_KEY response Generation.call( modelqwen-turbo, prompt你好介绍一下你自己 ) print(response)2.2 微信开发者工具配置在微信公众平台注册小程序账号个人类型即可下载开发者工具。创建新项目时注意勾选不使用云服务除非你需要云开发AppID填写你的小程序ID项目目录不要包含中文路径建议安装以下插件方便开发WXML格式化工具CSS预处理器支持ESLint代码检查基础项目结构应该是这样的├── pages │ ├── index │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss ├── utils │ └── api.js └── app.js3. 实现悬浮窗对话功能3.1 悬浮窗拖拽实现悬浮窗的核心是CSS定位和触摸事件处理。在index.wxml中添加以下代码view classfloating-window styleleft: {{windowX}}px; top: {{windowY}}px; bindtouchstarthandleTouchStart bindtouchmovehandleTouchMove image src/images/icon-chat.png/image /view对应的JS逻辑Page({ data: { windowX: 300, windowY: 500, startX: 0, startY: 0 }, handleTouchStart(e) { this.setData({ startX: e.touches[0].clientX, startY: e.touches[0].clientY }); }, handleTouchMove(e) { const { startX, startY, windowX, windowY } this.data; const deltaX e.touches[0].clientX - startX; const deltaY e.touches[0].clientY - startY; this.setData({ windowX: windowX deltaX, windowY: windowY deltaY, startX: e.touches[0].clientX, startY: e.touches[0].clientY }); } })样式方面要注意几点使用position: fixed脱离文档流添加z-index: 9999确保在最上层给悬浮窗添加阴影和圆角提升视觉效果.floating-window { position: fixed; width: 60px; height: 60px; background: #07C160; border-radius: 50%; display: flex; justify-content: center; align-items: center; box-shadow: 0 2px 10px rgba(0,0,0,0.2); z-index: 9999; } .floating-window image { width: 30px; height: 30px; }3.2 对话界面开发点击悬浮窗后应该弹出对话框。先完善WXML结构!-- 对话框 -- view classdialog-container wx:if{{showDialog}} view classdialog-header text智能助手/text button bindtapcloseDialog×/button /view scroll-view classmessage-list scroll-y block wx:for{{messages}} wx:keyid view classmessage {{item.role}} image wx:if{{item.roleassistant}} src/images/bot-avatar.png/image view classcontent{{item.content}}/view /view /block /scroll-view view classinput-area input placeholder输入问题... bindinputhandleInput value{{inputText}} / button bindtapsendMessage发送/button /view /view关键交互逻辑包括点击悬浮窗切换对话框显示状态输入框内容双向绑定发送消息时滚动到底部Page({ data: { showDialog: false, messages: [], inputText: }, toggleDialog() { this.setData({ showDialog: !this.data.showDialog }); }, handleInput(e) { this.setData({ inputText: e.detail.value }); }, sendMessage() { if (!this.data.inputText.trim()) return; const newMsg { id: Date.now(), role: user, content: this.data.inputText }; this.setData({ messages: [...this.data.messages, newMsg], inputText: }); // 调用API获取回复 this.getAIResponse(this.data.inputText); }, closeDialog() { this.setData({ showDialog: false }); } })4. 对接通义千问API4.1 封装API请求在utils/api.js中封装请求方法const API_KEY 你的API_KEY; const API_URL https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation; function callQianwen(prompt) { return new Promise((resolve, reject) { wx.request({ url: API_URL, method: POST, header: { Content-Type: application/json, Authorization: Bearer ${API_KEY} }, data: { model: qwen-turbo, input: { messages: [ { role: user, content: prompt } ] } }, success(res) { if (res.data res.data.output) { resolve(res.data.output.text); } else { reject(new Error(API返回格式异常)); } }, fail(err) { reject(err); } }); }); } module.exports { callQianwen };4.2 处理API响应完善之前的getAIResponse方法const { callQianwen } require(../../utils/api); Page({ // ...其他代码 async getAIResponse(prompt) { // 添加loading状态 const loadingMsg { id: Date.now() 1, role: assistant, content: 思考中... }; this.setData({ messages: [...this.data.messages, loadingMsg] }); try { const response await callQianwen(prompt); // 移除loading消息 const newMessages this.data.messages.slice(0, -1); this.setData({ messages: [ ...newMessages, { id: Date.now(), role: assistant, content: response } ] }); // 滚动到底部 this.scrollToBottom(); } catch (error) { console.error(API调用失败:, error); const newMessages this.data.messages.slice(0, -1); this.setData({ messages: [ ...newMessages, { id: Date.now(), role: assistant, content: 抱歉我遇到了一些问题请稍后再试 } ] }); } }, scrollToBottom() { this.createSelectorQuery() .select(.message-list) .boundingClientRect() .exec(res { if (res[0]) { wx.pageScrollTo({ scrollTop: res[0].height, duration: 300 }); } }); } })5. 性能优化与体验提升5.1 消息本地存储为了防止页面刷新导致消息丢失可以使用微信的本地存储Page({ onLoad() { const history wx.getStorageSync(chatHistory) || []; this.setData({ messages: history }); }, saveMessages() { wx.setStorageSync(chatHistory, this.data.messages); }, // 在sendMessage和getAIResponse的最后调用saveMessages })5.2 加载状态优化添加更友好的加载动画修改WXMLblock wx:if{{item.content 思考中...}} view classloading view classdot/view view classdot/view view classdot/view /view /block对应的CSS.loading { display: flex; padding: 10px; } .dot { width: 8px; height: 8px; margin: 0 3px; background-color: #999; border-radius: 50%; animation: bounce 1.4s infinite ease-in-out; } .dot:nth-child(2) { animation-delay: 0.2s; } .dot:nth-child(3) { animation-delay: 0.4s; } keyframes bounce { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } }5.3 网络错误处理增强网络异常时的用户体验async getAIResponse(prompt) { // 检查网络状态 const { networkType } await wx.getNetworkType(); if (networkType none) { wx.showToast({ title: 网络不可用, icon: none }); return; } // 显示加载中提示 wx.showLoading({ title: 思考中, mask: true }); try { // ...原有逻辑 } catch (error) { // 错误处理 let errorMsg 服务异常请重试; if (error.errMsg.includes(timeout)) { errorMsg 请求超时; } else if (error.errMsg.includes(fail)) { errorMsg 网络错误; } wx.showToast({ title: errorMsg, icon: none }); } finally { wx.hideLoading(); } }6. 实际开发中的坑与解决方案6.1 悬浮窗被遮挡问题在部分安卓机型上悬浮窗可能会被原生组件如video遮挡。解决方案是使用cover-view替代普通view调整z-index值在必要时刻隐藏悬浮窗cover-view classfloating-window styleleft: {{windowX}}px; top: {{windowY}}px; !-- 内容 -- /cover-view6.2 API响应慢的优化通义千问API在高峰期可能会有延迟可以采取以下措施添加请求超时设置实现消息队列避免频繁发送本地缓存常见问题的回答修改API调用代码wx.request({ // ...其他参数 timeout: 10000, // 10秒超时 fail(err) { if (err.errMsg.includes(timeout)) { reject(new Error(请求超时)); } else { reject(err); } } });6.3 小程序审核注意事项如果计划上线小程序需要注意AI回复内容要有过滤机制避免敏感话题悬浮窗不能遮挡主要功能明确告知用户这是AI生成内容可以在发送到API前做内容检查function checkSensitiveWords(text) { const forbidden [敏感词1, 敏感词2]; // 实际应该更长 return !forbidden.some(word text.includes(word)); } // 在sendMessage中添加检查 if (!checkSensitiveWords(this.data.inputText)) { wx.showToast({ title: 包含不合适内容, icon: none }); return; }
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2462620.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!