Python+uniapp+微信小程序:驾校预约考试练车管理系统全栈开发实战
1. 项目定位与整体方案拆解1.1 为什么是这个组合Python uniapp 微信小程序驾校预约考试练车管理系统表面上是个普通的业务管理系统但拆开看它其实覆盖了三条完全不同的技术链路后端业务逻辑与数据管理、跨端应用开发、微信生态对接。选择Python uniapp 微信小程序这个组合不是随便拍的是我在对比过几套方案之后确定下来的。先说后端。Python在这个场景里的优势非常明确Django或Flask都能快速把预约、考试、练车这类业务模型搭起来ORM写起来省时间admin后台开箱即用还自带一套完整的用户认证体系。如果你选Java Spring Boot当然也能做但同等功能下代码量大概多出30%到40%对于驾校这类中小规模业务系统来说属于过度设计。有人会问Node.js行不行行但Python生态里做定时任务、报表导出、权限管理这些驾校业务高频需求的库更成熟踩坑成本低。再说前端。uniapp这个选型核心考量是“一套代码多端跑”。驾校的业务场景里学员要用微信小程序约车、约考但教练和驾校管理员可能用的是App或者H5后台。如果每个端都单独写一套维护成本直接翻倍。uniapp基于Vue语法编译到微信小程序平台时性能表现稳定而且它的API层对微信生态做了大量适配比如wx.login的封装、支付、位置定位这些能力都有现成方案。最后是微信小程序这个载体。驾校学员的典型使用场景是“打开就用用完就走”微信小程序完美命中这个需求不需要下载安装、微信内直接打开、分享给朋友约同一辆车也方便。而且微信小程序的订阅消息能力可以做预约成功提醒、考试通知提醒这是H5做不到的。1.2 系统核心功能域梳理在做这个项目之前我先把驾校业务流程从头到尾理了一遍。驾校的日常运营可以拆成三个核心链路第一个链路是学员端的预约练车。学员登录小程序、选择教练、选择时间段、提交预约、到场练车、教练确认学时。这里最核心的难点是“时间冲突检测”同一辆车、同一个教练在同一个时间段不能被两个人同时预约。第二个链路是考试预约管理。科目一、科目二、科目三、科目四的考试名额有限教务人员需要手动排期学员在小程序里看到可预约的考试场次、提交预约、查看审核结果。和练车预约不同考试预约需要走一个“审核-确认”的流程因为考试名额涉及交管系统的对接不能像练车那样即时生效。第三个链路是后台管理。教练管理排班、请假、教学记录、车辆管理状态、保养提醒、学员管理学时统计、考试进度、财务管理报名费、补考费、教练提成。这些如果全靠Excel驾校规模到两百个学员之后就撑不住了。我在第一版设计时把功能范围控制在以上三个链路内没有过度加功能。很多同类项目一上来就想要“智能推荐教练”“学员行为分析”但在MVP阶段这些都是伪需求。先把预约和考试这两条主链路跑通后面再迭代这才是务实的做法。1.3 技术选型的三个关键决策这里把我做技术选型时纠结过的几个点展开说一下每个决策背后都有实际开发成本考量。Python后端框架我选了Django而不是Flask。原因很简单驾校管理系统里有三种用户角色学员、教练、管理员权限逻辑并不简单Django自带的后台管理、认证体系和中间件机制能省大量开发时间。Flask性能确实更轻但权限、ORM、表单验证都要自己搭建项目工期会明显拉长。实际测试下来Django的ORM在预约冲突检测这类事务场景下也能扛住并发没有性能瓶颈。uniapp版本选择选了Vue3版本而不是Vue2版本。Vue3版本的uniapp在TypeScript支持、组合式API、性能表现上都更好而且现在是uniapp官方的主力维护方向。如果你现在新起项目直接选Vue3 TS即可。UI方案选了uview-plus。这是基于Vue3的uniapp组件库表单组件日期选择、时间段选择、日历组件都够用省了从零写组件的时间。说实话这个项目的UI工作量占整体开发量的四成左右如果不用现成组件库两个月根本做不完。2. 数据库设计与后端核心实现2.1 数据模型设计的五个核心表后端开发的第一步是数据建模。这个系统里表结构设计直接决定了后面预约冲突检测、学时统计这些功能好不好实现。我最终设计了五张核心表外加几张辅助表。用户表User统一存储学员、教练、管理员三类账号。用role字段区分角色student / coach / admin不会给三种角色分别建三张表这样登录认证环节只需要一套逻辑。学员和教练各自的额外信息如学员的考试进度、教练的车型资质放在关联表中。教练表Coach关联User表记录教练的准教车型、所属校区、当前状态可预约/休息中/请假。这里我特意加了“服务时段”字段比如某教练只在工作日8:00-17:00教学那么学员在前端预约时直接过滤掉不可用时段避免前端展示了一些根本约不了的时段。车辆表Vehicle记录车牌号、车型、所属教练或公共车辆、当前状态空闲/使用中/维修中。驾校的车辆通常是教练车一车一教练绑定但科目二的模拟考试车可能是公共的两种模式都要支持所以加了一个is_public字段。预约单表Appointment这是整个系统的核心表记录时间段、日期、教练、车辆、学员、状态。关键设计点是“时间段”的粒度。驾校练车通常是按小时算比如教练8:00-10:00带A学员10:00-12:00带B学员所以预约的最小粒度设为1小时。考试场次表ExamSession和考试预约表ExamAppointment考试场次由管理员创建包含考试日期、科目、名额上限考试预约表关联场次和学员记录审核状态。我这里把建表语句补一下方便直接参考CREATE TABLE appointment ( id INT PRIMARY KEY AUTO_INCREMENT, student_id INT NOT NULL, coach_id INT NOT NULL, vehicle_id INT NOT NULL, appointment_date DATE NOT NULL, start_time TIME NOT NULL, end_time TIME NOT NULL, status TINYINT DEFAULT 0 COMMENT 0-待练车 1-已完成 2-已取消, remark VARCHAR(255), created_at DATETIME DEFAULT CURRENT_TIMESTAMP );2.2 预约冲突检测的核心逻辑预约功能最关键的硬骨头是“并发冲突检测”。场景是这样的两个学员同时在手机上一秒内预约同一个教练的同一时间段如果代码处理不当两个人都预约成功线下必然打架。我用了两种方案结合来处理数据库唯一约束 Django事务锁。数据库层面给appointment表加一个联合唯一索引ALTER TABLE appointment ADD UNIQUE INDEX uk_coach_slot (coach_id, appointment_date, start_time);这个索引的作用是“硬兜底”即使应用层代码出了bug数据库也会拒绝两条相同记录。但Django这边也需要处理这个冲突不能一有冲突就报500错误。应用层用了Django的select_for_update()做行级锁配合事务保证一次只有一个请求在处理某个教练的时间段from django.db import transaction transaction.atomic def create_appointment(student_id, coach_id, date, start_time, end_time): # 锁定教练在该日期的时间记录防止并发修改 coach_schedule CoachSchedule.objects.select_for_update().get( coach_idcoach_id, datedate ) # 检查该时间段是否已被约 conflict Appointment.objects.filter( coach_idcoach_id, appointment_datedate, start_time__ltend_time, end_time__gtstart_time ).exists() if conflict: raise SlotConflictError(该时间段已被预约) # 创建预约 Appointment.objects.create(...)select_for_update()的作用是让并发请求排队执行。这在驾校场景下完全够用一个教练一天最多接待10个学员并发量不可能高到哪里去。如果你的系统需要扛住上万量级的并发那就要引入Redis分布式锁或者消息队列了但这个项目不需要。2.3 考试预约的审批流状态机设计考试预约和练车预约不一样它不是即时生效的因为每个场次有名额限制而且驾校方面需要核实学员的学时是否达标才能允许报名科目二、科目三。所以考试预约设计了一个简单的状态机待提交-待审核-已通过/已拒绝/已取消待提交状态是为了防止学员误操作。学员填写预约信息后点击“提交”此时状态变成待审核教务管理员在后台看到申请记录后核实学时、确认名额然后通过或拒绝。通过后学员会收到微信订阅消息通知。这里有一个细节考试场次的名额控制。每个场次有一个total_slots字段管理员创建时设定。在审核通过时需要扣减剩余名额并且要用事务保证并发审核时不会超卖transaction.atomic def approve_exam_appointment(appointment_id): exam_appointment ExamAppointment.objects.select_for_update().get(idappointment_id) session ExamSession.objects.select_for_update().get(idexam_appointment.session_id) if session.remaining_slots 0: raise SlotFullError(该场次名额已满) session.remaining_slots - 1 session.save() exam_appointment.status approved exam_appointment.save()如果不加select_for_update()两个管理员同时审核最后两个名额时可能都会看到剩余1个名额然后都审核通过超卖。这种情况在培训学校里发生概率不高但系统不能有这种低级漏洞。2.4 Django接口层设计要点后端接口我统一采用了RESTful风格配合Django REST FrameworkDRF。核心接口列表如下接口路径方法功能权限/api/auth/wxloginPOST微信登录换取JWT公开/api/coaches/GET获取可预约教练列表登录用户/api/coaches/{id}/slots/GET获取教练某日可约时段登录用户/api/appointments/POST / GET创建/查询练车预约学员/api/appointments/{id}/cancel/POST取消预约学员/api/exams/sessions/GET获取可约考试场次登录用户/api/exams/appointments/POST提交考试预约学员/api/admin/exams/appointments/PUT审核考试预约管理员权限控制用DRF的permission_classes实现配合自定义的IsCoach / IsAdmin权限类。JWT认证用了simplejwt库对接微信登录时前端拿到 wx.login 返回的 code后端调微信的code2Session接口换取openid然后用openid作为用户唯一标识签发JWT。这里有个实操经验要分享微信小程序的code2Session接口需要用到appid和secret。secret绝对不能放在前端代码里必须由后端调用微信接口。这个错误很多新手会犯一旦小程序代码包被反编译secret泄露别人就能冒充你的小程序后端。正确的做法是前端传code给后端后端自己调微信接口。3. uniapp前端开发与微信小程序适配细节3.1 项目搭建与目录结构规划uniapp前端项目的搭建我用的是HBuilderX创建的项目模板选vue3版本。之所以不用命令行创建的Vite模板是因为HBuilderX对微信小程序开发的支持更完整能可视化配置manifest.json调试起来也直观。创建完项目后我按模块划分了目录src/ ├── api/ # 接口请求封装 ├── components/ # 自定义组件 ├── pages/ # 页面文件 │ ├── login/ # 登录页 │ ├── index/ # 首页推荐教练/场次 │ ├── appoint/ # 预约练车 │ ├── exam/ # 考试预约 │ ├── mine/ # 个人中心 ├── store/ # Pinia状态管理 ├── static/ # 静态资源 └── utils/ # 工具函数pages目录下的每个功能页面都保持独立路由通过pages.json管理。小程序端页面路径不能动态生成所以pages.json里必须把所有要用到的页面都提前注册好这个和H5开发里的路由懒加载不一样提前写全。3.2 微信登录与用户态管理小程序的登录流程和H5完全不同不能用传统的账号密码登录。整体流程是前端调用uni.login()获取临时code把code发送给后端后端用code换openid查库/建用户签发JWT前端把JWT存到uni.getStorageSync之后所有请求带上Authorization头实际编码时我在utils/request.js里封装了请求方法统一处理token注入和401跳转export const request (options) { return new Promise((resolve, reject) { const token uni.getStorageSync(token) uni.request({ url: BASE_URL options.url, method: options.method || GET, data: options.data || {}, header: { Content-Type: application/json, Authorization: token ? Bearer ${token} : }, success: (res) { if (res.statusCode 401) { // token过期跳转登录页 uni.navigateTo({ url: /pages/login/index }) reject(未登录) } else { resolve(res.data) } }, fail: (err) reject(err) }) }) }这里要注意uni.request的header里不要写死Content-Type: application/json如果遇到上传文件的场景会报错要单独处理。3.3 教练列表与可约时段展示教练列表页的数据来源是/api/coaches/接口在uniapp中用onLoad生命周期请求数据用v-for渲染卡片。每个卡片上展示教练姓名、准教车型、评分、头像。点击卡片进入教练详情页该页面展示教练的7天可约时间段。这个页面的技术难点是时间段的数据结构。后端返回的数据是{ date: 2025-01-20, slots: [ {start: 08:00, end: 09:00, status: available}, {start: 09:00, end: 10:00, status: booked} ] }前端要做的是渲染一个7天的横向选择器类似日期条选中某天后显示该天的时段网格。被约满的时段置灰置禁用。我用uview-plus的u-calendar组件改造了一下发现它的自定义插槽不够灵活最终自己写了一个七天日期条组件。这也算一个踩坑记录组件库的日历组件在“教练可约时段”这种场景下经常不适用因为你需要同时展示多天的可用状态小圆点uview-plus的日历组件对自定义标记的支持有限。3.4 小程序页面适配的几个坑这里的适配细节都是我实际调试过程中踩过的。顶部导航栏高度。小程序的标准导航栏高度是44pxiOS和48pxAndroid但全面屏手机还有状态栏高度差异。获取真实高度的代码// 获取状态栏高度 const statusBarHeight uni.getSystemInfoSync().statusBarHeight // 获取胶囊按钮位置 const menuButton uni.getMenuButtonBoundingClientRect() // 导航栏高度 胶囊顶部距离 - 状态栏高度 胶囊高度 (胶囊底部距离 - 状态栏高度 - 胶囊高度) / 2这个在自定义导航栏时用得到。如果直接用系统默认导航栏就不用关心这些但默认导航栏的样式定制能力比较弱标题字体颜色和背景色调整空间小所以我这个项目最终用了自定义导航栏样式更统一。底部安全区。小程序在iPhone X及以上机型有底部home indicator区域如果不处理底部按钮会被遮挡。解决办法是在页面底部加占位符高度为safe-area-inset-bottom。uniapp提供了env(safe-area-inset-bottom)的支持.safe-bottom { padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); }小程序分包机制。微信小程序有2MB的代码包体积限制超过之后需要分包加载。我的项目在不做任何处理时主包体积1.6MB加上uview-plus组件库后逼近1.9MB比较紧张。后来我把考试预约相关页面拆到subpackages分包中主包降到了1.3MB左右并通过了审核。3.5 微信订阅消息实现预约提醒微信小程序的订阅消息是一次性订阅用户在授权后后端只能给用户发送一次订阅消息。所以这个系统的消息策略是练车预约成功后请求用户授权订阅消息弹窗让用户勾选“允许”模板选“预约成功提醒”考试审核通过后同样请求授权模板选“审核结果通知”每次订阅授权只能发送一条消息如果想持续通知需要在每次用户操作时重复请求授权后端发送逻辑大致是这样在Django视图里import requests def send_subscribe_message(openid, template_id, page, data_dict): access_token get_wx_access_token() # 获取全局access_token url fhttps://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token{access_token} payload { touser: openid, template_id: template_id, page: page, data: data_dict } requests.post(url, jsonpayload)需要特别注意的是access_token的有效期是2小时需要缓存并定时刷新不能每次都重新请求微信接口否则很快就撞上接口调用频率限制。我在项目里用Django的cache框架存access_token过期前自动刷新。4. 微信小程序打包与发布全流程4.1 微信开发者工具中的环境配置开发完成后HBuilderX项目需要被微信开发者工具识别才能进行预览和调试。这个环节我在实际操作中发现有几个新手容易卡住的点。首先HBuilderX中“运行到小程序模拟器”会自动启动微信开发者工具但这要求微信开发者工具开启了服务端口。具体位置是微信开发者工具 - 设置 - 安全设置 - 服务端口必须设置为开启状态。没开启时HBuilderX会报错无法连接。其次是项目ID配置。在manifest.json的mp-weixin配置项中需要填写微信小程序的AppID{ mp-weixin: { appid: 你的小程序AppID, setting: { urlCheck: false, es6: true, postcss: true, minified: true }, usingComponents: true } }urlCheck是开发时用来关闭域名校验的选项上线前要把它改为true否则真机预览时请求非HTTPS域名会被拦截。4.2 代码包体积控制与分包分包微信小程序的主包体积限制为2MB。如果你的应用加了uview-plus、echarts之类的大型组件库很容易突破这个数字。我的项目里遇到的问题是source size 2612kb exceed max limit 2mb这个报错相信很多人都见过。我当时做了三件事第一移除不用的uview-plus组件。uview-plus默认是全量引入但我实际只用了表单、弹出层、标签等约20个组件。改成按需引入后体积立刻降了400KB左右。第二图片全部从代码包中迁移到OSS或图床。如果使用本地静态图片每张图都占打包体积。把图片传到云端代码里使用URL引用体积大幅下降。第三配置分包。pages.json中配置subPackages把考试报名、后台管理这类低频页面拆出去{ subPackages: [ { root: subpackage-exam, pages: [ pages/exam-list/index, pages/exam-detail/index ] } ] }配置好之后微信开发者工具会自动识别分包主包和分包的体积都有独立限制。这样即使后面继续加功能主包体积也能稳定在1.5MB以内。4.3 微信小程序上线的审核要点微信审核是很多开发者被卡住的一个环节。驾校预约系统属于工具类目审核时要注意几点类目选择。驾校培训服务类提交时需要提供营业执照、道路运输经营许可证等资质文件。如果个人开发者没有这些资质可以考虑选择“生活服务 其他生活服务”类目但审核人员可能会要求补充说明。功能完整性。我第一版提交审核时因为没有“意见反馈”入口被打回了一次。审核人员会以真实用户视角体验完整流程从登录到预约到支付如果有。如果有一个流程断掉了比如登录后无法退出、页面白屏、按钮无响应都会被以“功能不完整”为由驳回。建议提交审核前用体验版把全流程走一遍。隐私合规。如果你的系统会获取用户信息昵称、头像、手机号微信会要求有对应的隐私保护指引并在小程序后台填写“用户隐私保护指引”。uniapp项目中manifest.json中要声明用到了哪些隐私接口比如uni.getUserProfile、uni.getLocation等。4.4 uniapp打包安卓APK的差异点标题里提到了“uniapp上架安卓应用市场”这个也是很多团队会遇到的后续需求。微信小程序做完后需要出一个安卓App版本的话uniapp可以一键打包。这个环节有一个关键点和微信小程序计算方式完全不同App的包体积限制宽松很多但你需要处理离线打包或者云打包的配置。云打包时在HBuilderX的“发行 - 原生App-云打包”中需要配置Android证书。证书用keytool生成keytool -genkey -alias youralias -keyalg RSA -keysize 2048 -validity 36500 -keystore yourname.keystore这个证书要妥善保存后续应用市场版本更新、上架应用商店都需要用它来进行签名校验。我遇到过开发者在云打包时选了“使用公共测试证书”结果打出来的包无法上架应用市场只能重新换证书打包的情况前期的这个细节省得麻烦。App端和微信小程序端还有一个显著差异获取用户登录态的方式不同。App端没有wx.loginuniapp需要用plus.oauth来获取登录授权或使用uni.login的provider参数。后端需要同时兼容两种登录方式实际上就是让前端多传一个provider字段后端根据provider走不同的验证逻辑。5. 常见问题与排查技巧实录5.1 Charles抓包与调试网络请求调试小程序接口时Charles是非常好用的工具。用法很简单电脑和手机连同一个Wi-Fi手机HTTP代理指向电脑IP的8888端口Charles上安装SSL证书后就能看到HTTPS请求明文。但有一个新手容易忽略的步骤微信开发者工具的“不校验合法域名”开关。在开发者工具右上角“详情 - 本地设置 - 不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”必须勾选否则请求localhost或者内网接口会被拦截。真机调试时要在微信中打开调试模式同样也需要关闭域名校验。上线后域名必须配置为HTTPS并在小程序后台配置业务域名否则无法正常发请求。5.2 微信小程序10002错误的真实含义搜索热词里有“微信小程序 10002”这个关键词这是很多人在请求API时遇到的错误码。10002是“系统内部错误”通常出现在调用微信接口时传入参数类型不正确的情况。我在项目中遇到过一次原因是后端在传template_id时传了字符串类型但微信接口要求字段str类型严格一致实际是python里bytes类型被序列化了。排查方法很简单把请求参数打印出来对照微信文档检查类型和格式。5.3 uniapp不打印日志信息的排查热词里有一条“uniapp 不打印日志信息”。这个问题的常见原因有两个一是代码中用了console.log()但在生产环境编译时被tree-shaking移除了二是小程序端的日志输出走了vConsole直接看HBuilderX控制台是看不到的需要打开微信开发者工具的Console面板。如果你在HBuilderX运行到微信开发者工具后发现console.log没有输出不要急着怀疑代码问题。先在微信开发者工具的Console面板里看日志通常日志是在那里的。另外如果你用了uni.showToast来调试注意调试模式下弹窗是会被自动折叠的要检查是否开了静默模式。5.4 常见问题速查表问题原因解决方法source size 2612kb exceed max limit 2mb主包体积超限分包加载、图片外链、按需引入组件微信登录后token无效JWT过期时间设置过短检查simplejwt配置通常设7天有效期预约冲突测试失败缺少数据库唯一索引添加联合唯一索引uk_coach_slot订阅消息发送失败43101用户取消授权或授权次数已用完重新发起订阅授权优化引导弹窗时机真机预览白屏域名校验未通过关闭urlCheck或配置合法域名安卓App无法定位缺少权限声明manifest.json中配置权限并申请权限6. 项目复盘与经验心得6.1 开发周期与人力评估我按照实践经验估算假设一个熟悉Django和uniapp的全栈工程师来做从零到上线大约需要6到8周。其中数据库设计和后端接口开发约2周uniapp前端页面开发约3周联调测试和微信审核上架约1到2周。如果团队里还有UI设计师和测试人员周期可以压缩到5周但如果是一人全包建议按8周准备。驾校预约类系统的开发难点从来不在技术本身而在业务细节的沟通。预约时段划分、教练请假规则、考试名额分配方式、学时统计口径这些业务规则如果不和驾校实际管理人员沟通清楚做出来的系统和实际使用场景会脱节。我建议在项目启动前先花两天时间驻场调研看看驾校的实际排班表、学员手动预约的Excel表长什么样拿这些业务单据直接转化成数据模型比凭空设计效率高得多。6.2 上线后的运维与迭代方向系统上线后最容易被攻击的是预约接口。我之前遇到过有人写脚本刷接口占车位恶意提交预约导致真实学员约不上然后私下倒卖时段。解决方案是加了一层简单的防刷同一学员一天内预约次数上限3次取消次数上限2次超过则需要联系管理员手动处理。这个限制是通过IP 用户openid两层维度的计数实现的代码量不大但非常有效。后续迭代方面可以做的方向包括教练端小程序让教练自己查看每日预约列表、确认学时、提交请假学时统计报表按日/周/月导出教练带教小时数直接对接财务提成计算消息通知优化接入公众号模板消息让学员在非小程序环境下也能收到练车提醒。其中教练端小程序的开发成本和学员端差不多但价值很高因为目前教练只能通过管理员后台看自己的预约体验很差。6.3 我踩过的一些坑提前帮你们避一下最后说几个比较零散、但实际开发中会浪费大量时间的坑。第一微信开发者工具与HBuilderX的目录同步问题。如果HBuilderX编译后的代码有缓存改了前端代码但小程序端看不到效果先在HBuilderX里点击“重新运行到小程序模拟器”不是刷新页面是重新编译。这个操作很多人不知道容易以为代码写错了。第二Django的时区设置。如果你用了TIME_ZONE UTC而数据库存的是UTC时间前端拿到的时间转换成北京时间后会差8小时。我在开发阶段没注意这个上线后学员反馈预约时间全部偏移了8小时排查了很久才发现是时区配置问题。解决方法是settings.py中设置TIME_ZONE Asia/Shanghai USE_TZ True并且所有需要展示到前端的datetime字段序列化时统一转换成北京时间字符串。第三微信小程序的“单选框”组件坑。小程序原生的radio组件样式非常有限颜色、大小调整都比较受限而且不同机型的渲染效果不一致。如果你需要做“选择支付方式”“选择预约时段”这类交互建议直接使用uview-plus的u-radio组件或者自己写一个简单的点击态切换组件会比调原生radio样式效率高很多。第四关于代码版本管理。这个项目建议从一开始就用Gituniapp的unpackage编译输出目录加到.gitignore里这个目录每次编译都会变提交进去会让仓库非常臃肿。Django的秘密密钥不要提交到代码仓库用环境变量管理。这个系统做完之后我最大的感受是驾校这类传统行业的管理系统市场需求一直存在但技术门槛其实并不高真正考验的是对业务场景的理解深度。预约、排班、审核、通知这套逻辑在健身私教、美容美发、教育培训等很多行业都能快速复用。如果你手头也有类似的预约类项目需求希望能从这篇文章里找到可以参考的架构设计和避坑经验。最后再分享一个小技巧开发过程中多去翻微信官方文档的更新日志。微信小程序每个月都会有接口调整订阅消息模板、getUserProfile的改版就曾经让很多开发者的线上功能突然失效。把官方文档加个书签每次发布前扫一眼能避免很多线上事故。