☰
Python+uniapp+微信小程序:驾校预约考试练车管理系统全栈开发实战
2026/10/7 3:27:29 网站建设 项目流程

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_id=coach_id, date=date ) # 检查该时间段是否已被约 conflict = Appointment.objects.filter( coach_id=coach_id, appointment_date=date, start_time__lt=end_time, end_time__gt=start_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(id=appointment_id) session = ExamSession.objects.select_for_update().get(id=exam_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 Framework(DRF)。核心接口列表如下:

接口路径方法功能权限
/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完全不同,不能用传统的账号密码登录。整体流程是:

  1. 前端调用uni.login()获取临时code
  2. 把code发送给后端
  3. 后端用code换openid,查库/建用户,签发JWT
  4. 前端把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 小程序页面适配的几个坑

这里的适配细节,都是我实际调试过程中踩过的。

顶部导航栏高度。小程序的标准导航栏高度是44px(iOS)和48px(Android),但全面屏手机还有状态栏高度差异。获取真实高度的代码:

// 获取状态栏高度 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 = f"https://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, json=payload)

需要特别注意的是,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.login,uniapp需要用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样式效率高很多。

第四,关于代码版本管理。这个项目建议从一开始就用Git,uniapp的unpackage编译输出目录加到.gitignore里,这个目录每次编译都会变,提交进去会让仓库非常臃肿。Django的秘密密钥不要提交到代码仓库,用环境变量管理。

这个系统做完之后,我最大的感受是:驾校这类传统行业的管理系统,市场需求一直存在,但技术门槛其实并不高,真正考验的是对业务场景的理解深度。预约、排班、审核、通知这套逻辑,在健身私教、美容美发、教育培训等很多行业都能快速复用。如果你手头也有类似的预约类项目需求,希望能从这篇文章里找到可以参考的架构设计和避坑经验。

最后再分享一个小技巧:开发过程中,多去翻微信官方文档的更新日志。微信小程序每个月都会有接口调整,订阅消息模板、getUserProfile的改版就曾经让很多开发者的线上功能突然失效。把官方文档加个书签,每次发布前扫一眼,能避免很多线上事故。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询