ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PHP+UniApp场馆预订系统:从部署到多端上线的完整实战指南

PHP+UniApp场馆预订系统:从部署到多端上线的完整实战指南 最近手上整理了一套PHPUniApp组合开发的智能场馆预订系统源码前端一套UniApp代码可以同时编译成微信小程序、H5和安卓App后端用PHP统一提供接口不用给每个端单独写一套后端逻辑。这套系统本身就是我日常工作中经常接触的类型所以拿到后我没有直接丢给客户而是自己先把完整的部署链路跑了一遍。从环境搭建、数据库导入、接口联调到小程序编译、体积优化、多平台发布整个过程踩了不少坑也摸清了很多藏在源码里的细节。这篇文章就按我的实际操作顺序来写。如果你想自己部署一套场馆预订系统或者打算拿这套源码做二次开发又或者只是想在PHPUniApp这个技术组合上找一些实战经验那这篇文章应该能帮到你。我会把从零到上线每一步的关键操作、配置参数和踩坑记录都摆出来。1. 项目整体拆解这套系统到底做了什么1.1 选型逻辑为什么是PHPUniApp这个组合先聊选型。PHP在后端开发里被讨论很多年了但它的优势在中小型业务系统上非常明显部署简单、生态成熟、开发效率极高。场馆预订这种业务核心是场地管理、订单处理和支付回调没有特别离谱的高并发需求用PHP完全可以撑住。加上攻城狮普遍都熟悉LAMP或者LNMP这套环境后期维护成本也比较低。UniApp这边就更直接了——跨端。一套Vue语法的代码编译成微信小程序、支付宝小程序、H5、安卓App、iOS App。它的存在意义在于业务方不会只守着微信小程序一个入口很多场馆运营方还想要一个管理端H5甚至一个给用户的安卓App。如果每个端都单独开发光是前后端对接就要疯。UniApp把视图层统一了后端接口一套就够了。从成本角度看这套组合还有个好处PHP环境找到一家几十块的虚拟主机或者低配云服务器就能跑而UniApp编译出来的H5和微信小程序不需要额外购买跨端框架的服务。整个项目的边际成本主要在于服务器和域名这对于场馆经营者或者接单的外包团队来说都是很现实的考量。1.2 系统核心模块与业务流程我大致梳理了一下这套源码的业务模块核心是这几个场馆管理场馆基本信息、地址定位、营业时间、场馆图片、设施说明、公告通知。场地管理一个场馆下可以设置多个场地比如羽毛球馆的一号场、二号场篮球馆的半场、全场。排期与场次按日期生成可预订时段每个时段可以单独设置价格、可预订状态。用户端模块微信登录、手机号绑定、场地浏览、时段选择、下单支付、我的订单、取消预约、入场核销码。订单与支付下单锁场、时间内支付、微信支付回调、超时自动释放、订单退款。后台管理场地价格配置、订单管理、核销管理、数据统计。业务流程走起来是这样用户打开小程序授权微信登录选择场馆和日期系统按日期渲染出排期时段用户挑中某个时段下单。用户下单后系统先锁定这个时段给一个支付等待期用户完成微信支付后订单进入已支付状态。到店后场馆前台通过后台核销订单或者用户出示小程序里的核销码扫码验证。这里有一个容易被忽略的关键点排期和日期的关系。场地时段不是每天固定不变的经营者可能临时设置某天某个时段不可订或者单独调高节假日价格。所以数据库表结构里场次表通常会有一个日期字段和场地ID关联而不是只存周几几点。很多刚开始做预订系统的人会把排期做成模板后面遇到改价和停场需求就头疼。1.3 多平台部署的架构思路UniApp的多平台部署并不是简单地一套代码什么端都能用。实际编译时每个端还是会有自己的差异点。这套系统在架构上主要做了这几件事接口统一通过请求封装层调用所有端共用一套BaseURL配置。登录流程区分平台。微信小程序走uni.login拿code再去后端换openidApp端走uni.getUserProfile或者第三方登录。支付逻辑拆开。小程序端调用uni.requestPayment拉起微信支付H5端走公众号支付或者收银台模式App端用聚合支付SDK。条件编译处理平台差异。代码里用#ifdef MP-WEIXIN这类注释区分小程序端和H5端的特定逻辑。这种设计的核心价值在于版本迭代时改动业务逻辑只需要改一份代码。比如在后台加一个满减优惠活动只需后端加逻辑前端所有端同步生效。对运营来讲这个优势在后期会越来越明显。2. 拿到源码后的第一步环境准备与后端部署2.1 本地环境搭建PHP版本、数据库、伪静态刚拿到源码建议先在本地跑通别急着传服务器。我用的本地环境是PHPStudy原因无它快。一键启动Nginx和MySQL比手动配环境省事得多。先说PHP版本。现在很多PHP框架最低要求7.4推荐用8.0或8.1。我用的是PHP 8.1运行源码没遇到兼容性问题。如果你用的是老版本的系统也别无脑升8.x先看后端框架是哪个版本的ThinkPHP或者Laravel。有些老代码在PHP 8上会报函数签名冲突和动态属性创建错误这些一旦出现就得回头改源码非常被动。数据库我直接用了MySQL 5.7。这套源码的SQL语句中规中矩没有用到MySQL 8的窗口函数之类的特性所以5.7完全兼容。反正本地先跑通后面部署到服务器时数据库版本选择和本地保持一致即可避免出现备份恢复后SQL语句报错的尴尬情况。项目部署时要注意伪静态配置。大多数PHP后端代码都有友好的URL重写比如地址是https://域名/api/xxx而不是https://域名/index.php?s/api/xxx。在Nginx里需要配一段规则location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s$1 last; } }这个配置的核心是把不存在的文件路径交给入口文件处理。如果忘了配你会发现接口地址直接404而后端管理后台首页能打开这个现象非常容易让人误判成代码问题。2.2 导入数据库与配置环境文件源码包里一般会带一个SQL目录里面是数据库初始化脚本。打开PHPMyAdmin或者命令行执行导入即可。导入后要重点检查两张核心表的数据场馆列表和场地表。如果表里没有数据前端页面打开会空荡荡容易以为自己部署失败了。数据库导入完成后修改后端的环境配置文件。以ThinkPHP为例.env文件放在项目根目录需要修改的内容通常是APP_DEBUG true [APP] DEFAULT_TIMEZONE Asia/Shanghai [DATABASE] TYPE mysql HOSTNAME 127.0.0.1 DATABASE stadium_db USERNAME root PASSWORD 你的数据库密码 HOSTPORT 3306 CHARSET utf8mb4 [LANG] default_lang zh-cn这里有个细节本地开发时建议把APP_DEBUG打开这样接口报错时能看到完整的错误堆栈定位问题效率高很多。部署到生产环境时再把它关掉避免泄露服务器目录结构和数据库信息。还要注意charset必须写成utf8mb4因为手机号、昵称这些内容中可能包含emoji字符utf8mb4是唯一能完整支持四字节字符的编码。如果你在页面上看到问号或者乱码十有八九是表结构或者连接配置的字符集不对。2.3 接口自测先确认后端是通的环境配好以后我习惯先用浏览器直接访问几个接口确认后端没问题再去连前端。核心接口无非就是获取场馆列表和场地排期。比如在浏览器打开http://localhost/index.php/api/stadium/list如果返回JSON数据说明后端基本可用。接着测试场地排期接口http://localhost/api/field/list?stadium_id1date2024-12-20这里容易遇到一个坑接口如果做了签名校验或者用户登录鉴权直接浏览器访问可能返回未登录错误。这种时候不要慌先用后台的测试账号获取token或者在接口调试工具里配置请求头。我习惯用Postman或者Apifox把这几个接口配好后面调前端的时候可以直接验证后端逻辑避免前后端一起排查时晕头转向。后端通了以后还有一个必须做的事——检查接口返回的图片字段。场馆图片和场地图片在数据库里通常存的是相对路径比如/uploads/stadium/xxx.jpg。如果接口返回的图片地址是相对路径前端需要通过拼接域名来显示。很多人在这一步漏掉导致小程序里场馆图片全挂。检查的方法是看接口JSON里图片字段是否以http开头如果不是通常前端配置有一个统一的图片域名拼接前缀需要去前端代码里把域名改成自己的。3. UniApp前端项目解析与小程序打包3.1 前端目录结构核心文件都在哪后端跑通了现在开始看前端。UniApp项目的目录结构其实就是一个标准Vue项目加上一些uni-app特有的目录约定。我拿到源码后第一件事是看pages.json这个文件相当于小程序的全局配置文件里面配置了页面路由、底部TabBar、窗口样式、导航栏样式。pages.json的关键配置项有这几个{ pages: [ { path: pages/index/index, style: { navigationBarTitleText: 场馆预订, enablePullDownRefresh: true } }, { path: pages/stadium/detail, style: { navigationBarTitleText: 场馆详情 } } ], globalStyle: { navigationBarTextStyle: white, navigationBarTitleText: 智能场馆, navigationBarBackgroundColor: #2B85E4, backgroundColor: #F5F5F5 }, tabBar: { list: [ { pagePath: pages/index/index, text: 首页, iconPath: static/tab/home.png }, { pagePath: pages/order/list, text: 订单, iconPath: static/tab/order.png }, { pagePath: pages/my/index, text: 我的, iconPath: static/tab/my.png } ] } }启动项目后如果TabBar图标不显示先检查static/tab目录下有没有对应的png文件。这是非常常见的问题——下载的压缩包可能因为操作系统解压兼容问题漏掉了部分静态资源。除了pages.jsonmanifest.json是另一个核心文件。它管理的是应用级别的配置包括小程序AppID、App打包配置、H5配置等。还有一个容易忽视的文件是uni.scss里面定义了全局样式变量主色调、圆角大小、字体大小都在这里控制。改主题色只需要改这个文件里的变量值不用去每个页面逐个改style。3.2 manifest.json配置平台差异都在这里manifest.json是打包时的核心。拿到项目第一件事把里面的appid替换成自己的。如果你还没有微信小程序的AppID可以去微信公众平台注册一个小程序账号在“开发管理-开发设置”里找到AppID。注意这里有两个ID容易搞混AppID和AppSecret。AppID是公开的用于前端配置AppSecret是密钥必须放在后端绝不能出现在前端代码里。微信小程序相关的manifest配置长这样{ mp-weixin: { appid: wx你的appid, setting: { urlCheck: false, minified: true, postcss: true }, usingComponents: true, permission: { scope.userLocation: { desc: 用于获取您的定位以匹配附近场馆 } }, requiredPrivateInfos: [getLocation], lazyCodeLoading: requiredComponents } }这里每一项都有讲究。urlCheck是微信开发者工具里的一个校验开关它的作用是校验请求的域名是否在小程序后台配置了合法域名。本地开发时如果不开这个配置会在控制台看到“url not in domain list”的报错。但需要注意的是这只是本地调试的开关上线发布前必须在微信公众平台配置合法的request域名否则真机上会请求失败。requiredPrivateInfos是微信平台新增的隐私接口声明。如果代码里调用了uni.getLocation之类的接口但没在manifest里声明审核会被驳回来。很多人的代码明明能用但提交审核时因为缺少这个配置被拒就是踩了这里的坑。lazyCodeLoading设置按需注入可以缩减小程序包体积尤其是项目包含大量组件库时效果非常明显。3.3 编译到微信小程序的完整流程用HBuilderX打开前端项目目录这个是最直接的。打开后先等依赖安装完成然后点击菜单栏“运行-运行到小程序模拟器-微信开发者工具”。这里有一个很关键的细节运行之前确保微信开发者工具已经打开并且开启了“服务端口”选项。服务端口在微信开发者工具的“设置-安全设置-服务端口”里开启如果不打开HBuilderX无法自动唤起微信开发者工具。编译成功后微信开发者工具里会出现一个项目此时先看看控制台有没有报错。常见的一个报错是vendor.js 编译失败 TypeError: Cannot read properties of undefined这种问题一般是JS语法不兼容引起的排查思路是先看是哪个文件报错再确认项目是否缺少了某个依赖库。还有一个更常见的提示The source size of /pages/index/index.js exceeds the max limit 2MB这里要和微信小程序的2MB主包限制区分开。小程序要求整个主包不超过2MB如果超了这个限制就得做分包处理。具体怎么优化我在后面专门用一整个章节来写因为这是部署时最容易卡住人的地方。编译通过后在微信开发者工具里能看到小程序界面。此时如果接口请求报错查看具体错误内容——域名未配置、证书不合法、跨域等等。调试阶段最频繁的问题是本地后端是http://localhost而小程序要求接口必须是HTTPS且域名必须在小程序后台配置。解决办法是先用微信开发者工具的“不校验合法域名”开关把urlCheck关掉或者在工具的详情-本地设置里勾选“不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”。4. 前后端联调的四个关键战场4.1 跨域和BaseURL配置H5调试必看前后端联调第一个要解决的是跨域问题。H5端调试时前端运行在本地9527端口后端跑在80或者8080端口浏览器出于安全策略会拦截跨域请求。解决方案在后端加跨域头header(Access-Control-Allow-Origin: *); header(Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With); header(Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS);但这里有个前端的坑如果你在请求时设置了自定义header比如Authorization字段后端还必须在Access-Control-Allow-Headers里显式声明这个字段否则浏览器会报“Request header field authorization is not allowed by Access-Control-Allow-Headers”。另一种跨域问题是OPTIONS预检请求。当请求比较复杂时浏览器会先发一个OPTIONS请求测试服务器是否允许跨域。后端要在入口文件或者路由层直接拦截OPTIONS请求并返回200否则每次请求都会白白多花一次握手时间而且容易导致状态码混乱。BaseURL的配置建议统一放在一个文件里比如utils/config.js。配置项一般包含API域名、图片域名、版本号等export const BASE_URL https://api.yourdomain.com/index.php/api; export const IMG_URL https://api.yourdomain.com; export const VERSION v1.0.0;这里有一个经验之谈不要在前端代码里到处直接用绝对地址所有请求都走封装好的Request方法BaseURL只在一个文件里出现。原因很简单发布以后如果需要切换服务器只改这个文件就够了。我在实际项目里见过有人在十几个页面里硬编码了域名最后换服务器时痛苦到怀疑人生。4.2 微信登录 code2Session 换取openid微信小程序的登录流程和传统的账号密码登录完全不同。核心机制是前端调用uni.login拿到一个临时code把这个code发给后端后端用code去微信的接口换取openid和session_key。这个code有效期为5分钟而且只能使用一次。小程序端核心代码uni.login({ provider: weixin, success: function(loginRes) { uni.request({ url: BASE_URL /user/login, data: { code: loginRes.code }, success: function(res) { if (res.data.code 1) { uni.setStorageSync(token, res.data.data.token); } } }); } });后端拿到code后调用微信的接口$url https://api.weixin.qq.com/sns/jscode2session?appid{$appid}secret{$secret}js_code{$code}grant_typeauthorization_code; $result file_get_contents($url); $data json_decode($result, true); // $data[openid] 用户唯一标识 // $data[session_key] 加密会话密钥换取成功后后端应该返回一个自定义token给前端后续请求都通过token来识别用户身份。不要每次请求都调微信接口换取openid微信接口有调用频率限制而且每次都要走网络性能非常差。这里有一个很隐蔽的坑开发阶段微信开发者工具里的code和真机上拿到的code不是同一套体系吗其实是一样的但是如果你在开发者工具里勾选了“模拟登录”它模拟出来的code也是可以正常换取的。如果发现后端报了40029错误code无效先检查一下AppID和AppSecret是否匹配再检查系统时间是否正确时间偏差过大会导致session_key解析失败。4.3 手机号授权绑定获取微信手机号现在用的是按钮授权方式。小程序端在页面上放一个按钮用户点击后通过open-typegetPhoneNumber获取到加密的手机号数据把数据传给后端后由后端解出真实手机号。前端按钮button open-typegetPhoneNumber getphonenumbergetPhoneNumber微信一键登录/button前端逻辑methods: { getPhoneNumber(e) { if (e.detail.errMsg getPhoneNumber:ok) { uni.request({ url: BASE_URL /user/bindPhone, data: { code: e.detail.code, mobile: e.detail.encryptedData, iv: e.detail.iv } }); } } }后端解密手机号的逻辑$sessionKey 数据库里存的session_key; $encryptedData 前端传来的encryptedData; $iv 前端传来的iv; $pc new WXBizDataCrypt($appid, $sessionKey); $errCode $pc-decryptData($encryptedData, $iv, $data);这个流程的易错点在于session_key的过期问题。手机号解密依赖session_key而session_key在用户重新登录后可能变化。如果用户先登录了然后过了很久才点击手机号授权按钮后端用旧session_key去解密就会失败。稳妥的做法是点击手机号授权按钮时重新走一次uni.login获取新的code后后端重新去微信接口换取session_key再用这个新的session_key解密。另一个要注意的点是手机号授权按钮必须在微信开发者工具的真机调试里测试。开发者工具里模拟的授权数据虽然也能走通流程但真实性不足很容易让你误判问题。4.4 支付与订单状态同步场馆预订系统最核心的交易环节就是支付。微信小程序支付流程相比H5支付要简单不少因为它不需要额外的支付授权。小程序端用户在页面点击支付前端请求后端创建支付单后端调用微信支付统一下单接口生成支付参数返回给前端前端再调用uni.requestPayment拉起支付面板。后端生成支付参数的核心逻辑$order_sn SN . date(YmdHis) . rand(1000, 9999); $params [ body 场馆预订-羽毛球1号场地, out_trade_no $order_sn, total_fee $price * 100, spbill_create_ip 客户端IP, notify_url https://api.你的域名.com/api/pay/notify, trade_type JSAPI, openid 用户的openid ]; $result $wxpay-unifiedOrder($params); // 返回给前端使用然后前端拉起支付uni.requestPayment({ provider: wxpay, timeStamp: res.data.timeStamp, nonceStr: res.data.nonceStr, package: res.data.package, signType: MD5, paySign: res.data.paySign, success: function(result) { uni.showToast({ title: 支付成功 }); } });这里有三种订单状态需要后端关注待支付、已支付、已取消。用户发起支付后如果支付成功微信会异步回调一个通知地址后端收到回调后更新订单状态。要注意回调通知的网络地址必须是对外可访问的HTTPS地址且不能被防火墙拦截。如果支付回调漏处理了就会出现一种很尴尬的情况用户已经扣款成功但订单状态还是待支付。所以我在部署时会在回调逻辑里加日志记录file_put_contents(./logs/pay_notify_ . date(Ymd) . .log, json_encode($input), FILE_APPEND);这一步极其重要。有一次用户反馈支付后没到账最后排查发现不是因为回调没收到而是回调验签时因为证书路径配错了导致一直报错。有了日志就能区分是“没收到回调”还是“回调处理失败”这两种完全不同的情况。支付完成后的核销流程也需要提前跑通。后台有一个核销功能场馆前台输入订单号或者扫码即可核销。核销后订单状态变为已完成。如果核销接口和订单状态没有联动好会出现用户支付后场地管理员看到的订单还是待使用状态很容易造成线下纠纷。5. 打包体积超2MB的应对策略5.1 先用HBuilderX看清谁的体积最大微信小程序的主包限制是2MB。这套系统页面不少地图、轮播图、支付组件、UI组件库全部打包后很容易就超了。我在编译时就遇到过这个经典错误The source size of /pages/index/index.js exceeds the max limit 2MB遇到超限问题先不要急着删代码。HBuilderX的发行菜单里有一个“小程序-微信”发行流程发行前会先检查体积。但在检查之前你可以自己打开项目的unpackage/dist/dev/mp-weixin目录看看哪个目录最大。通常体积大头有三个js文件、组件库、静态图片。js文件里最常出问题的是uni_modules里的组件特别是那些全量引入的UI组件库。如果你用了类似uView或者ColorUI这类组件库打包时会把所有组件都编译进包里哪怕你只用了其中的Button组件。5.2 分包方案与公共代码抽离微信小程序支持分包加载。分包的思路是把不常用的页面从主包里拿出来单独放到一个子包目录里用户进入某个页面时才去加载对应的包。分包后主包只包含首页、登录页、TabBar页面等基础内容子包放场馆详情、订单详情、个人中心等二级页面。在pages.json里配置分包{ subPackages: [ { root: pagesStadium, pages: [ { path: detail, style: { navigationBarTitleText: 场馆详情 } }, { path: booking, style: { navigationBarTitleText: 预约下单 } } ] }, { root: pagesOrder, pages: [ { path: list, style: { navigationBarTitleText: 订单列表 } } ] } ] }这里必须注意分包的root不能和pages目录下的原有路径重叠否则编译时会报错。路由跳转时也要用分包后的完整路径比如uni.navigateTo({ url: /pagesStadium/detail?id1 })。如果跳转路径写错了控制台会报找不到页面的错误。另外小程序分包有大小限制单个分包不超过2MB所有分包加起来不超过20MB。对于场馆预订系统这种业务把页面拆到分包后主包基本能控制在几百KB范围内。5.3 实用压缩技巧汇总除了分包还有几个立竿见影的瘦身方法。第一个是静态资源压缩。场馆图片尽量走CDN不要放在小程序包里。首页轮播图、场地照片这些大图部署时传到服务器后在小程序里用完整的HTTPS图片地址展示。本地包里的图片只保留较小的图标文件。第二个是全局组件按需引入。如果你用的是uni_modules的组件库打开组件目录看看是否一次引入了整个库。以uView为例建议按需引入组件只注册需要用到的少数几个。有些组件库支持easycom规则自动按需引入配置正确后会省掉大量无效代码。第三个是清理无用文件和注释。很多源码压缩包会带一些无关文件比如文档里放错的备份文件、缓存文件。这些文件看似不起眼但如果被编译进包里也会占用体积。我在实际部署时遇到过一个情况源码目录下有一个带着几十张截图备份的assets目录体积超过了2MB删掉后包体立刻变小。发布前过一遍项目文件列表确认哪些是源码需要的哪些是多余的会省很多事。第四个是js压缩选项。manifest.json里minified配置为true代码压缩后能减少30%左右的体积。另外检查一下项目中是否有重复引入的第三方库比如同时引入axios和flyio这种冗余要清理掉。如果主包还是超了还有一个技巧把所有tabBar页面集中在首页目录下把非tabBar页面尽量放进分包小程序的tabBar页面必须放在主包里其他页面没有这种限制。6. 多平台发布与其他高频问题6.1 微信小程序审核与发布注意事项小程序开发完成自测通过下一步是发布。在微信开发者工具里点击“上传”版本号写上然后登录微信公众平台在“版本管理”里找到刚上传的版本提交审核。审核要注意几个容易踩雷的点。场馆预订涉及用户地理位置信息如果你的代码里调用了uni.getLocation审核时需要有明确的用途说明。在公众平台配置隐私保护指引时要把位置信息的使用场景写清楚比如“用于匹配用户附近的场馆”。另外一个高频驳回理由是“页面内容不完整”或者“功能不符合预期”。提交审核前一定要在真机上完整走一遍核心流程登录、查看场馆列表、选择时间、下单、支付。别人的审核员也是拿真机测的如果某个按钮点了没反应或者支付流程走不通很快就会被驳回。发布后还有一件事不能漏配置业务域名和服务器域名。在“开发管理-开发设置-服务器域名”里把接口域名配置到request合法域名里。注意这个域名必须支持HTTPS且证书要完整。很多人本地调试一切正常发布后真机上所有接口全部请求失败基本都是因为合法域名没配置或者证书有问题。6.2 安卓应用市场与H5发布要点小程序发布之后如果还要编译成安卓App在HBuilderX里点击“发行-原生App-云打包”填好包名、证书和图标后就能生成安装包。发布到安卓应用市场时要注意包名不能随便改一旦某个渠道已经用了这个包名后续更新都用同一个换了包名会变成一个全新的应用。H5端的发布相对简单。在HBuilderX里点击“发行-网站H5-手机版”生成一个静态文件目录把这个目录传到Nginx的web目录下即可。需要注意的一点是H5端的接口域名和页面域名不能是同一个域其实可以同一个域但要注意跨域问题。如果前后端在同一个域下且路径不同要确认Nginx把API路径正确代理到了后端服务。如果前后端不在同一个域那么后端必须配置好跨域Header。H5发布后还有一个功能要留意H5端的微信支付。如果你想在H5页面里使用微信支付需要先申请“H5支付”在支付场景上跟小程序的JSAPI支付是两套体系。很多人在配置H5支付时卡住其实核心是必须在商户平台里添加“H5支付域名”并且发起支付时要带上用户的IP和User-Agent。这套源码如果只做小程序和App可以先把H5支付功能关掉避免上线后出现支付异常用户投诉。6.3 导航栏适配、分享、动态标题等细节多平台发布后还有很多体验细节需要适配。微信小程序的顶部导航栏和手机状态栏不是一回事。很多人在开发时忽略了状态栏高度导致自定义导航栏的标题被“刘海”挡住。获取安全区域高度的代码const systemInfo uni.getSystemInfoSync(); const statusBarHeight systemInfo.statusBarHeight; // 导航栏高度 状态栏高度 胶囊按钮高度 胶囊按钮上下间距 const menuButton uni.getMenuButtonBoundingClientRect(); const navigationBarHeight (menuButton.top - statusBarHeight) * 2 menuButton.height;这段代码在App端也能用但App端没有胶囊按钮导航栏高度可以直接取44px。用条件编译区分// #ifdef MP-WEIXIN const menuButton uni.getMenuButtonBoundingClientRect(); // #endif // #ifndef MP-WEIXIN const menuButton { top: statusBarHeight 8, height: 44 }; // #endif分享功能也是场馆预订场景里重要的传播入口。用户在小程序里看到某个场馆不错想分享给朋友需要在小程序页面里配置onShareAppMessageonShareAppMessage() { return { title: this.stadium.name 预订, path: /pagesStadium/detail?id this.stadium.id, imageUrl: this.stadium.share_img }; }如果想让分享出去的卡片更好看可以在后端给场馆配置一张专门的分享图尺寸建议是5:4否则分享卡片显示出来会裁切。这个细节看起来不起眼但对打开率影响非常大。动态修改标题可以用uni.setNavigationBarTitle。比如用户进入某个场馆时把导航栏标题从“场馆详情”改成场馆名称。但需要注意这个接口必须在页面加载完成后调用而且某些安卓机型可能有缓存下次进入时标题不会自动恢复需要在onShow里重新设置一遍。关于日志不打印的问题很多人问为什么UniApp在真机上console.log不输出。在HBuilderX里调试真机时需要确认“控制台-过滤”里没有把log级别屏蔽掉。更稳妥的调试方式是临时用uni.showToast把关键信息显示在页面上虽然不够优雅但在某些环境里比console好用得多。热更新这个话题也可以提一下。UniApp的App端可以使用wgt资源包实现热更新也就是说修改了JS或者页面资源后不需要重新上架应用市场用户打开App时自动拉取新资源。但要注意原生插件、manifest.json的配置变更无法通过热更新生效这类型的改动必须走应用市场重新发布。部署时如果有App热更新的需求后端需要提供一个版本检测接口返回当前版本号和下载地址前端启动时对比版本然后决定是否需要更新。在测试热更新时我建议先在测试机上验证一次完整的更新流程确认更新后没有白屏和资源缺失问题再推广到全部用户。7. 部署完成后我再补几句掏心窝子的经验这套系统从拿到源码到跑通全流程我前前后后花了大约一个周末的时间。很多坑在文档里根本找不到比如微信开发者工具的端口没开启导致编译失败比如手机号解密的session_key过期问题比如打包后体积超标的处理顺序。这些东西如果不亲自踩一遍光看官方文档很难注意到。给准备上手的朋友几个建议。第一一定要先在本地完整跑通再上服务器不要一上来就在服务器上折腾服务器上的问题排查起来比本地慢太多。第二上线前把支付回调日志开起来至少在运营前半年不要关这是你排查资金问题的第一手依据。第三微信小程序和安卓App有各自平台的适配细节特别是H5和App的微信支付跟小程序不是一套东西业务上线前最好把所有端的功能全部走一遍。如果你拿这套源码是打算直接运营的那有一点必须重视场馆排期和订单的并发处理。多个用户同时抢一个场次后端没有加锁的话会出现超卖。我在本地测试时曾模拟过两个账号同时下单同一时段结果两个订单都创建成功了。后来在后端下单接口加了行锁才解决。给订单表和场次表加上唯一索引下单用事务这个问题就能防住。这类看似细小的并发问题往往能让一个看起来跑得很好的系统在运营压力下瞬间崩溃。关于二次开发的方向我觉得这套系统值得扩展的地方不少。比如活动促销模块比如会员储值卡再比如对接第三方地图做场馆周边配套展示。这些功能都建立在这套PHPUniApp的框架之上扩起来并不难。关键是把基础的东西搞扎实别急着堆功能先把预订、支付、核销这条主链路打磨到足够顺滑。
返回列表