AI项目移动端

发布时间:2026/10/9 7:18:34
AI项目移动端
为什么选择uniapp跨平台更多通过条件编译优雅为某平台编写个性化功能开发效率高生态丰富支持NPM、支持小程序组件和SDK。微信生态的各种sdk可直接用于跨平台App。缺点性能欠缺原生 多端uniapp的生命周期页面生命周期onLoadonReadyonShowonHideonUnload组件生命周期beforeCreatecreatedbeforeMountmountedbeforeUpdateupdatedbeforeDestroydestroyed功能1. 登录1.1微信小程序无感登录#uniapp自带api uni.login({ provider:weixin, onlyAuthorize:true }) #得到code然后请求后端获取用户信息token并存储点击登录按钮》弹出微信内置验证手机号组件》验证通过登录成功弹出验证手机号组件微信向产品方收取费用view classlogin登录/view button open-typegetPhoneNumber getphonenumbergetPhoneNumber styleposition: absolute;left: 0;top: 0;width: 50px;height: 50px;z-index: 10;opacity: 0;登录/button #将button按钮覆盖住view元素并隐藏1.2APP-安卓1.2.1微信登录前提1. 要在微信开发平台中注册一个号并且申请微信登录》审核通过就有appid(企业移动应用详情)了。2. 在项目中打开manifest.json》APP模块配置》登录》微信登录的appid(形如wx061b4aebd4b88534)3. 而且必须要在自定义基座或真实环境中运行去测试。要不然不生效。在manifest.json的源码视图中添加签名关于appseceret必须和微信开放平台的一致1. 调用uniapp自带的方法uni.login()uni.login({provider:weixin,onlyAuthorize:true})无感登录返回1. errMsg提醒是否成功。 2.code用户登录的临时凭证。2. 请求后端提供的接口微信登录获取token需要传递参数code返回1. 用户信息。 2. token。1.2.2手机验证码登录1.2.3账号密码登录注意APP第一次审核提交必须有账号密码登录的方式上架过程中填写应用名称、上传图标填写分类、简介隐私协议政策的url提供账号密码用于客服测试1.3H51.3.1 手机验证码登录安全 》 防止短信验证码被刷方式post请求 》不能get不能明文增加环节(滑块识别物品) 》 需要校验 》 来自于生成时和用户完成时做的对比(服务端做) 不能跳过这个环节滑块发送验证码流程1.3.2 手机密码登录1.4APP-IOS前提1. 要在微信开发平台中注册一个号并且申请微信登录》审核通过就有appid了。2. 在项目中打开manifest.jsonAPP模块配置》登录》微信登录的appidwx77ffd205d3266248生成links链接3. 而且必须要在自定义基座或真实环境中运行去测试。要不然不生效。如何生成links链接1. 找到ios平台通用链接点击自动生成2. 若没实名认证先点击认证重启编译器再次回到此页面点击新建3.跳转页面点击新建服务空间完成新建服务空间4. 等待10-15分钟空间准备完成后回到编译器自动生成模块刷新出云服务空间选择进行下一步5. 自定义配置6. 跳转至服务空间继续添加域名域名为微信开发者平台中移动应用详情内》基础配置》应用官网的域名确定之后生成links7. 域名解析在服务器添加域名解析记录复制验证信息完成即可验证添加8. 以上步骤没问题回到自动生成模块点击完成即可在uniapp中生成链接微信开放平台生成链接之后在微信开放平台点击对应移动应用 在详情内检查Universal Link值与uniapp生成的要一致可编辑修改苹果开放平台参考uni-app官网登录苹果开发者后台 Apple Developer滑至最下方MAC电脑重新配置证书和描述文件mac os系统电脑打开钥匙串弄一个证书苹果开发平台中Certificates添加上a步骤的证书 》 完成后下载b步骤结束下载完成后双击打开在钥匙串中导出p12证书Profiles下载出来Profiles文件以上文件用来配置自定义基座然后可以进行调试了(最好用真机测试模拟器有缓存)登录面试1. 安卓微信登录在自定义基座上调试(标准基座问题颇多)有安卓开发证书(包名、证书别名、证书私钥密钥证书文件.KEYSTORE) ---公司提供在微信开放平台已经注册了微信登录在uniapp项目的mainfest.json中添加appid代码uni.login({ provider: weixin, // 登录方式 onlyAuthorize: true // 授权认证 }) // 若成功返回errMsg(提示信息)、code(登录凭证) // 将code通过接口传给后端若成功返回uer(用户信息)、token // 把信息存储到vuex并持久化2. IOS微信登录在自定义基座上调试(标准基座问题颇多)有IOS开发证书(appid、证书私钥密码、描述文件、私钥证书) ---公司提供如何配置开发证书1有苹果开发平台账号2申请appid时勾选登录能力在IOS使用第三方登录必须勾选苹果登录3私钥证书、证书私钥密码通过在MAC OS电脑配置导出p12证书4描述文件在苹果开发平台后台去获取在微信开放平台已经注册了微信登录在uniapp项目的mainfest.json中添加appid和links(要和微信开放平台中的移动应用一致)links如何创建需要创建阿里云服务器并且配置添加域名域名要去阿里云DNS解析验证links创建成功之后要和微信开发者平台保持一致代码同安卓一样uni.login({ provider: weixin, // 登录方式 onlyAuthorize: true // 授权认证 }) // 若成功返回errMsg(提示信息)、code(登录凭证) // 将code通过接口传给后端若成功返回uer(用户信息)、token // 把信息存储到vuex并持久化3.微信小程序登录无感登录let { errMsg, code } await uni.login() // 调用接口传递code若成功则传回user、token // 把信息存储到vuex并持久化验证手机组件登录可能追问id含义uid该公司注册微信开放平台的idappid每一个小程序应用idopenid每个用户在当前应用的id2. 支付2.1 APP-安卓微信支付准备mainfest.json勾选支付 -- 微信支付 --填写appid(安卓)let { data } await anWxpay({ tokensPriceId: id }) let {errMsg} await uni.requestPayment({ provider:wxpay, orderInfo:data.params }) if( errMsgrequestPayment:ok){ //支付成功 console.log(支付成功) }支付宝支付准备mainfest.json勾选支付 -- 支付宝支付//支付宝支付 let { data } await anAlipay({ tokensPriceId: id }) let { errMsg } await uni.requestPayment({ provider:alipay, orderInfo:data }) if( errMsgrequestPayment:ok){ console.log(支付成功) //支付成功 }2.2APP-IOS注意苹果应用内支付的支付说明苹果的支付如果支付的是虚拟产品(会员、游戏道具)必须是苹果应用内支付。必须有公司资质审批的苹果开发平台账号审核通过并且交付年费688元人民币。苹果开放平台账号必须签署2个协议免费协议和收费协议。苹果开放平台账号创建一个app新建的这个app中有【价格与销售范围】选择价格和国家》这个单价是制定的。【App 内购买项目】填写产品id 》在套餐列表中要呈现准备提交才可以用原数据丢失不能用manifest.json中》app模块配置〉Apple应用内支付勾选。提前准备好支付的沙箱账号用户和访问》沙盒》测试账户//IOS应用内支付 iosPayment(){ let that this; plus.payment.getChannels((channels) { for (var i in channels) { var channel channels[i]; if (channel.id appleiap) { let iap channel; iap.requestOrder([that.applyProductId],function( orderList ){ that.applePay(orderList[0]) },function( error ){ console.log( error ); }) } } }) }, async applePay( para ){ let { errMsg , transactionReceipt } await uni.requestPayment({ provider: appleiap, orderInfo: { productid: para.productid, optimize: true // 设置 optimize: true 解决丢单问题 } }) if( errMsg ! requestPayment:ok) return; let { code } await setIapCertificate({ userId:this.userInfo.userId, receipt:transactionReceipt }) if( code 0 ){ console.log(支付成功); }else{ console.log(支付失败); } },2.3微信小程序只能微信支付2.4H5端支付宝注意返回过来的form替换掉当前页面替换完成页面更新后后触发submit应用场景document.querySelector(body).innerHTML reswindow.document.forms[0].submit()微信注意要测试支付成功当前访问的域名 不能是localhost | 192.168...必须是微信商户平台产品中心H5支付域名中的其中域名// 支付宝支付 if ( this.paymentValue alipay){ let res await h5Alipay({ tokensPriceId: id }) document.querySelector(body).innerHTML res this.$nextTick((){ window.document.forms[0].submit() }) }else{ // 微信支付 let { data } await h5Wxpay({ tokensPriceId: id }) console.log(data) window.location.href data.h5_url }项目兼容问题uniapp iOS上拉边界下拉白色空白解决在pages.json中配置{ path: pages/index/index, style: { navigationBarTitleText: 首页, disableScroll: true //设置为 true 则页面整体不能上下滚动 } }在微信中打开h5连接url然后再跳转某页面再返回会在底部增加历史导航会影响本身网页的高度解决办法手动增加一个空的历史记录//main.js function isWXBrowser () { var ua window.navigator.userAgent.toLowerCase(); if (ua.match(/MicroMessenger/i) micromessenger) return true return false } // 判断是否是微信浏览器 if ( isWXBrowser() ) { window.history.pushState({}, , ) }页面高度动态计算的问题scroll原因有键盘弹起的操作H5小程序节点textarea :adjust-positionfalse :adjust-positionfalse 键盘弹起不上推页面动态计算对话内容区域高度在Focus中计算高度可视区域高度 - 头部 - 底部 - 键盘的高度APP节点textarea :adjust-positionfalse :adjust-positionfalse 键盘弹起不上推页面动态计算对话内容区域高度在Focus中计算高度可视区域高度 - 头部 - 底部 - 键盘的高度 - [可能有些设备需要减去安全区域高度]***安全区域高度可以设置在vuex中方便其他页面使用那么就在app.vue中获取存储到vuex中开发阶段跨域h5端 vue.config.js(没有就新建)module.exports { devServer: { proxy: { /api: { target: https://ai.xuexiluxian.cn, changeOrigin: true, secure: false, pathRewrite: { ^/api: / } } } } }微信小程序端右上角详情只需要不校验url即可APP端无需配置二次封装请求的封装封装内容配置基础url添加请求拦截器在实际将请求发送到服务器之前请求拦截器会被执行。你可以在请求拦截器中对请求进行预处理比如添加请求头、修改请求参数、进行身份验证等操作。ex给后端传递token添加响应拦截器HTTP 客户端库接收到服务器响应后会先将响应数据传递给响应拦截器进行处理。可以在响应拦截器中对响应数据进行统一处理比如解析响应数据、处理错误状态码、缓存响应数据等。ex校验token是否过期针对getpost等请求方式单独封装get(url, data {} , options {} ){ return this.request({ url, data, method:get, ...options }) }项目的难点和亮点网络通信http、https仅 请求-响应 方式一次请求一次响应ws长连接全双工通信服务端可以主动发给客户端性能不好心跳检测(定时发送消息确认连接未断开若断开会断线重连)SSE 请求一条数据返回多条数据直至传输结束分片默认get请求AI对话技术选型SSE难点AI对话返回的内容是需要解析的流式数据关于解析“流式数据”的解析》浏览器端pc、手机浏览器可以使用fetch(fetchEventSource)但是fetch在小程序和app中不支持关于解析“流式数据”的解析》微信小程序中不支持fetch那么怎么办可以使用uni.request关于小程序内置的api添加参数包括新增的事件来去支持。关于解析“流式数据”的解析》app中既不支持fetch又不支持以上小程序的那种处理方式。可以使用render.js来完成。解决方案H5端注意SSE默认支持GET请求cnpm i microsoft/fetch-event-source import { fetchEventSource } from microsoft/fetch-event-source; // 支持SSE的post请求SSE和ws的方法有点相似onopen连接成功 失败onmessage 服务端给客户端返回过来的数据基本使用// #ifdef H5 fetchEventSource(/api/xlx-chat/chatMessage/sendMessageSSE,{ method:post, headers, body:JSON.stringify({ id:this.id, userId:this.userInfo.userId, question:this.msgList.at(-1).content }), onopen() { console.log(sse连接成功); }, onmessage( msg ){ let { data } msg; if( data !data.includes(br/br/tokens) !data.includes([DONE]) ){ let parseData JSON.parse( data ); str parseData.content; //数据更新视图不更新解决办法是$set that.$set( that.msgList , len , { role:system, content:str }) } } }) // #endif微信小程序uni.requestlet requestTask uni.request({ url:https://ai.xuexiluxian.cn/api/xlx-chat/chatMessage/sendMessageSSE, enableChunked:true,//这个地方需要开启 header:headers,//这里是header method:post, data:JSON.stringify({ id:this.id, userId:this.userInfo.userId, question:this.msgList.at(-1).content }), success( res ){ //这里的success相当于close》而且必须写不写下面的事件用不了 console.log(连接关闭 , res ); } }) requestTask.onHeadersReceived(res{ //等同于 onopen console.log( 连接是否成功,res ); }) requestTask.onChunkReceived(res{ //等同于 onmessage })APP:renderjs在视图中使用btn方法要eventSource.btn script moduleeventSource langrenderjs //这里的eventSource是模块名称随便定义 export default{ methods:{ btn(){ console.log( 11 ); } } } /script renderjs中要使用其他js中的数据 button :propsmergeProps app端的发送/button //其他js的computed中 computed:{ mergeProps({ token , isSend , msgList , userId , id }){ return { token, isSend, msgList, userId, id } } }, 把renderjs中的数据传递给其他js中:this.$ownerInstance.callMethod(emits,{str, len } ); ***其中的$ownerInstance.callMethod是固定方法emits随意写。在其他js中接收 methods:{ emits({str,len}){ } }项目的难点如何解决ai对话的环节就是一问一答涉及多端h5、小程序、app3端-- 处理ai对话的环节中就很复杂。选择通讯的方式就是SSE在对话一问一答中SSE明显要比WS性能更好但是SSE在这3端的处理过程中很麻烦和复杂H5端SSE默认支持的是Get请求接口却是POST需要使用一个fetct的插件来支持POST请求的SSE微信小程序端不支持fetch(H5端支持Fetch)需要使用uniapp提供的uni.request并配置专属小程序的字段让他支持SSE同时需要注意必须写入success然后还要使用2个事件类似于onopenmesssageclose...app端以上两个方法均不可行需要使用renderjs来做的处理相当于一个视图层2个逻辑层并且逻辑层还有通信的交互。这就是我遇到最大的困难我们这个ai对话要实现3端支持每一端的处理方式都不同而且全网没有答案这个问题不管是在uniapp的插件市场中还是各种搜索引擎中都没有答案能支持3端// 所以我觉得要把我做的项目的难点内容分享出来我在uniapp插件市场发布了第一个封装支持ai对话3端的组件。项目上线H5发行 --网站(H5)1. 路径》manifest.json》WEB配置2. 代理》环境变量来切换请求的url(生产环境和开发环境)微信小程序前提有appid、开发者身份提前做好分包后台添加request合法域名(如果使用web-view需要在后台添加【业务域名】)在开发者工具中点击上传(如果之前有【线上版本】当前上传会自动版本1)APP-安卓前提APP设计第三方模块微信登录(appid)、支付(appid)、申请商店(华为、OPPO...)开发账号1. 在开发者工具中点击打包》填写对应包名等信息2. 在manifest.json配置各种内容3. 到对应的商店中提交应用名称...计算机软件著作权证书 --公司(消费)备案 -- 公司隐私政策注意uniapp打包的项目上传到某某商店中可能会不通过其中的原因是非法收集xxx那么我们需要在隐私政策中添加一句话https://xuexiluxian.cn/agreement/privacy-policyAPP-IOS前提到苹果开放平台申请账号》在没有做项目之前就要弄好》年费688APP涉及第三方模块微信登录appid、links、支付appid、links1. 在开发者工具中点击打包苹果区分开发证书和生产证书》填写对应包名等信息2. 进入app store后台网页需要注意1支付》免费协议和付费协议2和安卓类似的内容3. 上传包ipa需要使用xcode工具来进行上传操作中。性能优化了解性能优化发展历史和指标项(谷歌提出)Core Web Vitals在过去我们的项目可能会涉及到前后端不分离所以之前的指标是大多对于前后端不分离的指标项。 》onLoadWeb Vitals(2020提出)更多是针对于前后端分离的项目。 》请求的操作...工具 指标项DCLDOMContentLoadedDOM完全加载及解析事件触发LonLoad页面加载完成FPFirst Paint首次渲染》dom结构在网页中有所体现这里注意html标签有些是自带样式(边框)的。FCPFirst Contentful Paint首次内容渲染比如dom有了dom本身的内容也有了。就比如img节点是在fpimg的src(有内容)是在fcpFP、FCP专业术语白屏时间LCPLarge Content Paint : 最大内容绘制时间 》 当前的可视区域最晚最大的元素什么时候绘制的注意开发前必须有该小程序的APPID: wx061b4aebd4b88534必须有该小程序的开发者权限: sxlmzy2026(微信号)补充路由(跳转页面)uni.navigateTo({}) // 保留当前打开新页面 // 可以返回上一个历史记录注意页面跳转路径有层级限制不能无限制跳转新页面跳转到tabBar页面只能使用switchTab跳转uni.redirectTo // 关闭当前打开新页面 // 返回的是上一级页面使用场景: 不切换url但是切换url中参数如果用navaigateTo也会保留想要返回上一级就要redirectTo补充renderjs1. 在renderjs中不能使用onload这种页面生命周期只能使用组件的生命周期created...)2. 一旦这样写方法触发时机button :propsmergeProps :change:propseventSource.renderBeforeSend // 这里并不是点击了按钮才触发事件 v-showfalse app端的发送 /button3. 可能涉及到普通js和renderjs的通信// 普通js向renderjs通信 // 普通JS通过computed来定义 computed:{ mergeProps({ token , isSend }){ return { token, isSend, } } }, // renderJS接收 视图button :propsmergePropsapp端的发送/button methods:{ renderBeforeSend( nVal ){ let { isSend, token } nVal; }, } // renderjs向普通js的通信 // renderjs》this.$ownerInstance.callMethod(自定义事件名称:emits,{str, len } ); // 普通js接收》 methods:{ emits( { str , len }){ //... }) }补充VUE2中数据更新视图不更新解决办法this.$set(对象, key, value) 具体看官方文档补充web-view默认自动打开可通过v-if控制button clickisShow true打开B站/button web-view srchttps://www.bilibili.com/ v-ifisShow/web-view默认不会返回上一页可通过将web-view放入新页面点击按钮实现页面跳转实现返回上一级的需求// 原页面 template view classcontent button clickbtn打开B站/button /view /template script export default { data() { return { } }, onLoad() { }, methods: { btn(){ uni.navigateTo({ url:/pages/webview/webview }) } } } /script// webview页面 template view web-view srchttps://www.bilibili.com//web-view /view /template script export default { data() { return { } }, methods: { } } /script使用场景产品开展活动时通过后端管理系统添加url而产品代码中通过webview打开本页面即可。补充小程序分包注意小程序的分包在项目开始时就要进行,在subPackages中配置{ pages: [ //pages数组中第一项表示应用启动页参考https://uniapp.dcloud.io/collocation/pages { path: pages/tabbar/index, style: { navigationBarTitleText: 首页, disableScroll: true // 页面整体不能上下滚动 } }, { path: pages/tabbar/my, style: { navigationStyle: custom } } ], // 分包加载配置此配置为小程序的分包加载机制。 subPackages: [{ root: pagesPackage/, //子包根目录 pages: [{ path: myPage/user-config, // 配置页面路径 style: { navigationBarTitleText: 账号设置 } }, { path: loginPage/login, style: { navigationBarTitleText: 登录 } }, { path: payment/index, style: { navigationBarTitleText: 充值 } }, { path: commonPage/chat, style: { disableScroll: true, // 页面整体不能上下滚动 app-plus: { softinputMode: adjustResize } } } ] }], tabBar: { color: #7A7E83, selectedColor: #3cc51f, borderStyle: black, backgroundColor: #ffffff, list: [{ pagePath: pages/tabbar/index, text: 首页 }, { pagePath: pages/tabbar/my, text: 我的 }] }, globalStyle: { navigationBarTextStyle: black, navigationBarTitleText: uni-app, navigationBarBackgroundColor: #F8F8F8, backgroundColor: #F8F8F8 }, uniIdRouter: {} }1. 小程序分包大小限制整个小程序所有分包大小不超过 20M单个分包/主包大小不能超过 2M2. 优势性能提升页面按需加载项目对包有大小限制超出限制上线不了分包可以解决3. 分包思路主包放tabbar页面(导航栏) 公共资源(高频访问的公共资源)其他子包若干私有资源补充vuex注意本身vuex是一个状态管理并不能持久化存储(刷新之后信息全无)持久化存储可用插件cnpm i vuex-persistedstateimport Vue from vue import Vuex from vuex Vue.use(Vuex) import createPersistedstate from vuex-persistedstate // 用户模块 import user from ./modules/user.js const store new Vuex.Store({ modules: { user }, plugins: [ createPersistedstate({ storage: { getItem: key uni.getStorageSync(key), // 获取 setItem: (key, value) uni.setStorageSync(key, value), // 设置 removeItem: key uni.setStorageSync(key), // 删除 } }) ] }) export default store注意在小程序和app和h5中都要使用使用uniapp提供给的storeage方式不能直接使用localStorage并且小程序是不能使用cookie的h5可以。补充动态组件应用场景切换登录方式注意微信小程序不支持动态组件template view view v-foritem in loginList :keyitem.id clickloginTabs(item) {{item.name}} /view component :iscomp/component /view /template script import phone from ./components/phone.vue import password from ./components/password.vue export default { data() { return { comp: phone, loginList: [{ id: 1, name: 验证码登录, comp: phone }, { id: 2, name: 密码登录, comp: password }, ] } }, components: { phone, password }, methods: { // 切换登录方式 loginTabs(item) { console.log(this.comp) this.comp item.comp } } } /script补充所有端适配宽度rpx(100rpx50px)高度动态计算const res uni.getSystemInfoSync() //计算可视区域高度补充服务器安全性阿里云 腾讯云短信包腾讯审核松