☰
微信小程序预约挂号系统全栈开发实战:从数据库设计到部署避坑
2026/10/6 8:11:31 网站建设 项目流程

简介:这是一套基于微信小程序与Java SSM框架的预约挂号系统毕业设计项目,面向计算机相关专业学生与需要快速搭建可运行课设/毕设的开发者。系统完整覆盖管理员、医生、用户三类角色,包括科室与医生信息管理、排班、预约、取消预约、调班申请等核心模块,后台可在浏览器登录管理,小程序端使用微信开发者工具运行,MySQL作为本地数据库。资源包共1210个文件,约18.92MB,主要包含png界面截图、vue与js前端逻辑、java后台代码、json配置、wxml/wxss小程序页面及sql数据库脚本,内附本地安装与运行脚本,便于按目录理解前后端结构并快速复现。已有77人学习浏览,适合用于项目参考、功能复现或答辩讲解。

1. 小程序前端只是外皮,预约挂号系统的另一半在服务端

如果没做过全栈,第一次打开这份基于微信小程序的预约挂号系统源码包时,多半会把注意力放到pages/index/index.wxml的科室卡和医生列表上。真做过的人会告诉你,决定毕设答辩能不能顺利走完的,是藏在服务端的号源池设计、微信登录 session 维护和预约状态流转。它解决的问题很明确:让患者在小程序里完成“选科室→选医生→选时段→填就诊人→提交预约→收到通知”的完整闭环。和上一轮交付的 2048 小程序不同,那是一次性的前端练手,这回要把数据库、接口、鉴权和小程序端串成一条线。适合人群是刚入行小程序、想拿一个完整全栈项目做课程设计或毕业设计的在校生,也适合想换工作面试时拿出全栈作品的人。


2. 先立骨架:预约挂号系统的表结构、后端选型与接口清单

这一章先把数据模型和接口边界定下来。预约挂号系统和普通商城订单系统长得像,但有一个本质差别:商城的库存是“商品数量”,挂号系统里是“号源”,号源带时间、带医生、带状态,而且会产生超时释放。如果直接套订单表去设计,后面一定会遇到号源被占死、用户重复预约、医生排班时间冲突这些诡异问题。

2.1 核心表结构:用户、医生、排班、号源、订单

我一般会把表拆成 8 张:用户表、就诊人表、科室表、医生表、排班表、号源表、预约订单表、操作日志表。下面是最核心的 5 张:

CREATE TABLE `doctor` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `department_id` int NOT NULL, `title` varchar(20) DEFAULT '主治医师', `intro` varchar(500) DEFAULT '', `avatar` varchar(255) DEFAULT '', PRIMARY KEY (`id`), KEY `idx_dept` (`department_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `schedule` ( `id` int NOT NULL AUTO_INCREMENT, `doctor_id` int NOT NULL, `work_date` date NOT NULL, `start_time` time NOT NULL, `end_time` time NOT NULL, `total_count` int DEFAULT 0, PRIMARY KEY (`id`), KEY `idx_doctor_date` (`doctor_id`, `work_date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `number_source` ( `id` int NOT NULL AUTO_INCREMENT, `schedule_id` int NOT NULL, `period_no` int NOT NULL, `period_text` varchar(50) DEFAULT '08:00-08:30', `status` tinyint NOT NULL DEFAULT 0, `lock_expire_at` datetime DEFAULT NULL, `version` int NOT NULL DEFAULT 0, PRIMARY KEY (`id`), KEY `idx_schedule_status` (`schedule_id`, `status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `appointment` ( `id` int NOT NULL AUTO_INCREMENT, `order_no` varchar(32) NOT NULL, `user_id` int NOT NULL, `patient_id` int NOT NULL, `number_source_id` int NOT NULL, `status` tinyint NOT NULL DEFAULT 0, `cancel_reason` varchar(200) DEFAULT '', `created_at` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_order_no` (`order_no`), KEY `idx_user` (`user_id`), KEY `idx_source` (`number_source_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `patient` ( `id` int NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL, `name` varchar(50) NOT NULL, `id_card` varchar(18) DEFAULT '', `phone` varchar(20) DEFAULT '', `is_default` tinyint DEFAULT 0, PRIMARY KEY (`id`), KEY `idx_user` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

讲几个容易被忽略的点。number_source表里的version字段不是摆设,它用来做乐观锁,防止两个用户同时抢到同一个号。schedule表单独存work_date和start_time,而不是让排班表直接去接前端传来的字符串,是因为后续要支持“按医生 + 日期”排班查重,这种结构才能建上联合索引。appointment表里冗余了patient_id,是因为预约记录要永久可查,不能因为用户删掉就诊人就让历史订单显示不出姓名。

注意:number_source和appointment表之间不要直接做外键约束。线上系统没人会给核心订单表挂外键,毕设答辩如果被问起来,可以用“外键在应用层控制、方便分库分表”这个理由回应。

2.2 后端选型:微信云开发、Node + MySQL 还是 Java?

有三条常见路线:微信云开发、Node.js + Express + MySQL、Java Spring Boot + MySQL。如果只是想把页面跑起来,云开发最快,不用买服务器也不用管数据库,但有两个问题:云开发的数据库是 NoSQL 集合结构,把医生的排班和号源做成关系模型会很别扭;毕业答辩时,老师大概率会问“表结构怎么设计、事务怎么处理”,云开发很难展开讲。我一般建议用 Node.js + MySQL,主要原因是代码量少、小程序端可以用 JavaScript 同步理解服务端逻辑,而且本机装一个 MySQL 就能完成演示,不需要额外买云服务器。

登录接口是小程序端绕不开的第一个接口,标准写法是把微信的登录凭证换成本系统的登录态:

// 小程序端 app.js App({ onLaunch() { wx.login({ success: async (res) => { const loginRes = await wx.request({ url: `${this.globalData.baseUrl}/api/user/login`, method: 'POST', data: { code: res.code, nickname: '', avatar: '' } }); const { token, userId } = loginRes.data.data; wx.setStorageSync('token', token); wx.setStorageSync('userId', userId); } }); } });

这段逻辑的流程是:小程序端先wx.login()获得一个一次性code,把code交给后端;后端拿code调用微信的code2session接口换回openid和session_key。关键在于:session_key只能留在后端,不能下发到小程序端,否则有心人拿session_key可以伪造登录态。服务端把openid映射成一个自签 token 返回前端,前端后续所有接口都带着这个 token,形成持久登录。

选型时还有一个隐性成本要算进去:如果选云开发,微信云开发的免费额度对个人够用,但云函数冷启动导致的接口首屏延迟在小程序里非常明显,答辩演示时容易给人“系统很慢”的印象。自建 Node 服务没有冷启动问题,代价是要处理服务器和数据库的进程管理。

2.3 接口清单:预约挂号系统常用的 10 个接口,字段名怎么定

预约挂号系统的接口数量一般不会太少,前后端联调时最容易因为字段名对不上而卡住。我会在项目里固定一个统一的请求封装,所有接口都从同一个入口走:

// utils/request.js const app = getApp(); function request({ url, method = 'GET', data = {} }) { return new Promise((resolve, reject) => { wx.request({ url: `${app.globalData.baseUrl}${url}`, method, data, header: { 'Content-Type': 'application/json', Authorization: wx.getStorageSync('token') || '' }, success(res) { if (res.data.code === 0) resolve(res.data.data); else if (res.data.code === 401) { wx.removeStorageSync('token'); reject(new Error('登录已过期')); } else { wx.showToast({ title: res.data.msg, icon: 'none' }); reject(new Error(res.data.msg || '请求失败')); } }, fail(err) { wx.showToast({ title: '网络错误,请重试', icon: 'none' }); reject(err); } }); }); } module.exports = { request };

注意这里对响应做了统一处理:code === 0表示业务成功,返回核心数据;code === 401表示 token 失效,清掉本地登录态;其余非零状态码直接 toast 给用户。像微信开发者工具里偶发的网络抖动,或者在真机上遇到10002这类网络错误,也会被fail分支兜住并提示重试,避免白屏。

接口清单我习惯固定成下面这批,前后端都照着这个列表开发:

接口方法入参返回数据
/api/user/loginPOSTcodetoken、userId
/api/user/profileGET无用户昵称、头像
/api/patient/listGET无就诊人列表
/api/patient/addPOSTname、idCard、phone就诊人Id
/api/department/listGET无科室列表
/api/doctor/listGETdepartmentId、page、pageSize医生列表与分页信息
/api/schedule/listGETdoctorId、date排班与号源剩余
/api/appointment/submitPOSTpatientId、numberSourceId订单号
/api/appointment/cancelPOSTorderNo是否成功
/api/appointment/listGET无我的预约列表

接口命名越直白越好。很多毕设翻车不是逻辑难写,而是前后端字段名不一致,一个叫hospitalId一个叫hospital_id,联调能调一晚上。项目里统一用驼峰命名,返回值里的日期统一用YYYY-MM-DD HH:mm:ss字符串,避免时区问题。


3. 把核心流程跑通:登录态、号源列表、锁号与订阅消息

这一章做的事是预约挂号系统的完整调用链。从用户打开小程序到收到预约成功通知,中间经过的四段代码,每一段都有值得注意的边界条件。

3.1 登录态:为什么不能只信wx.login

上一节已经列出了登录接口,这里重点说一个很容易被忽略的问题:wx.login返回的code有效期只有 5 分钟,而且用了一次就作废。很多同学把code直接存在本地,等到下次打开小程序再拿去换 token,结果后端报错“code 无效”,用户就停留在登录页出不去。

正确的姿势是:每次冷启动都重新wx.login(),但 token 失效之后不要连带把用户数据也清了,而是保留 userId,让用户无感续期。服务端要维护一张简单的 token 表,记录 token、userId、过期时间。session_key只在服务端使用,不落库、不下发。

有的项目为了省事直接让前端把openid当 userId 用,这在开发阶段确实能跑,但一旦后续加了“家庭成员绑定就诊人”的需求就会非常痛。还是老老实实走 token 体系,服务端每次请求都在中间件里做一次校验:

// middleware/auth.js(Node.js 服务端) const jwt = require('jsonwebtoken'); module.exports = function auth(req, res, next) { const token = req.headers.authorization; if (!token) return res.status(401).json({ code: 401, msg: '未登录' }); try { const payload = jwt.verify(token, process.env.JWT_SECRET); req.userId = payload.userId; next(); } catch (e) { return res.status(401).json({ code: 401, msg: '登录已过期' }); } };

这里的 JWT_SECRET 从环境变量读取,不要写死在代码里,否则源码一旦被传到公开仓库,任何人都能伪造用户身份。另外一个常见坑是:用 JWT 时 token 一旦签发就不好主动失效,所以预约系统的某些高敏感操作(取消预约、修改就诊人)建议把用户ID再和业务数据里的 user_id 做一次比对,避免越权操作。

3.2 科室→医生→排班→号源:四层列表的分页加载

科室列表是小程序首页的核心。很多同学会一次性把科室、医生、排班全查出来渲染,一打开页面发出三十几个请求。这在小程序端非常不稳定,也会让真机预览变慢。我一般按三层加载:页面加载时只请求科室;点了科室才请求医生列表;点了医生才请求排班。

小程序里的“页面列表加载更多”在医生列表一段很典型。用onReachBottom做滚动分页,同时要设置isLoading标志位防止重复请求:

// pages/doctor/doctor.js Page({ data: { list: [], page: 1, pageSize: 10, isLoading: false, hasMore: true }, async getDoctors(reset = false) { if (this.data.isLoading) return; if (!reset && !this.data.hasMore) return; const page = reset ? 1 : this.data.page; this.setData({ isLoading: true }); try { const res = await request({ url: '/api/doctor/list', data: { departmentId: this.data.departmentId, page, pageSize: this.data.pageSize } }); const list = reset ? res.list : this.data.list.concat(res.list); this.setData({ list, page: page + 1, hasMore: res.list.length === this.data.pageSize, isLoading: false }); } catch (e) { this.setData({ isLoading: false }); wx.showToast({ title: '加载失败', icon: 'none' }); } }, onReachBottom() { this.getDoctors(false); } });

注意:onReachBottom在页面没有超出屏幕时不会触发,但不要因此就不做分页。很多毕设演示用的医生数据只有 5 条,看不出问题;等你自己灌了 50 条数据,不分页的版本就会明显卡顿。

号源列表建议返回剩余号的数量,而不是把时间段排满。schedule/list接口要按日期过滤,返回每个 timePeriod 的可约状态,前端用单选框组件展示:

<radio-group bindchange="onPeriodChange"> <label wx:for="{{periodList}}" wx:key="id"> <radio value="{{item.id}}" disabled="{{item.remaining === 0}}" /> <text>{{item.periodText}}(余{{item.remaining}})</text> </label> </radio-group>

radio-group本身是单选框,但点击区域默认只有圆圈那一小块,所以要用label把整行文字包起来,这样用户点整行都能选中,这是预约操作体验上的一个关键细节。

3.3 锁号与超时释放:别让前端倒计时来决定号源归属

预约流程里最容易出问题的是“用户进入确认页后号源被谁占住”。常见方案有两种:第一种是提交预约时直接占号,不支付则等用户取消;第二种是锁号后给 15 分钟支付窗口,超时自动释放。我强烈建议用第二种,因为真实医院系统里号源是稀缺资源,用户只是打开了确认页但一直不点提交,号源不能一直被占着。

服务端的锁号逻辑要在 MySQL 事务里完成:

-- 伪代码:锁定号源并创建订单 START TRANSACTION; SELECT status, lock_expire_at, version FROM number_source WHERE id = #{numberSourceId} FOR UPDATE; -- 校验状态:0 表示可预约,且锁未过期 UPDATE number_source SET status = 1, lock_expire_at = DATE_ADD(NOW(), INTERVAL 15 MINUTE), version = version + 1 WHERE id = #{numberSourceId} AND status = 0 AND version = #{oldVersion}; INSERT INTO appointment (order_no, user_id, patient_id, number_source_id, status) VALUES (#{orderNo}, #{userId}, #{patientId}, #{numberSourceId}, 0); COMMIT;

这个方案的要点在于FOR UPDATE把这一行号源锁住,后续的更新必须基于正确的version。如果更新影响行数为 0,说明号源已经被别人占走,业务层直接提示“该时段已被预约,请选择其他时间”。

超时释放不用写定时任务,在用户查询订单时做一次懒清理即可:查询订单时检查lock_expire_at是否已过,如果已过就把号源状态改回 0、订单标记为已取消。这样演示时不用专门等 15 分钟去验证。

另外,前端也应监听页面的onHide和onUnload,在用户中途退出时提示“号源暂未锁定,请尽快提交”。但这只是体验提示,真正释放以服务端lock_expire_at为准,前端倒计时只是障眼法。

3.4 订阅消息:预约成功的通知不是发就能发的

“微信小程序订阅消息授权弹框”是很多人的第一个认知盲区:微信已经不给开发者自动推送消息的能力了,用户必须主动点击“允许”后,开发者才能使用一次性订阅消息给用户发一条通知。预约成功提醒就是典型的场景。

调用方式是在用户确认预约时先询问授权:

wx.requestSubscribeMessage({ tmplIds: ['预约成功提醒模板ID'], success(res) { if (res.errMsg === 'requestSubscribeMessage:ok' && res['预约成功提醒模板ID'] === 'accept') { // 用户允许,后端可以发订阅消息 wx.showToast({ title: '预约成功,已开启消息提醒', icon: 'none' }); } else { // 用户拒绝,不影响预约,只是不发通知 wx.showToast({ title: '预约成功', icon: 'success' }); } }, fail() { wx.showToast({ title: '预约成功', icon: 'success' }); } });

这里要注意:一次性订阅消息模板通常只能在用户产生一次点击后下发一条消息,想发多条就要让用户多点几次授权。毕设阶段演示用的是体验版 + 订阅消息模板,需要在微信公众平台申请模板,并保证所选类目和“预约挂号”主题一致。如果类目不符,模板审核会直接被驳回。

另外,订阅消息只是锦上添花的功能,不要把它做成预约成功的唯一凭证。演示时如果微信平台接口临时抽风,页面里还要有“预约成功”的完成态和订单列表兜底,保证核心流程不依赖外部接口。


4. 预约挂号系统避坑手册:从开发到答辩的 8 个翻车现场

这一章没有任何新知识,全是血泪经验。我把做这类小程序最容易踩的坑按阶段整理成“现象→原因→解决”三段式,你可以直接按图索骥。

4.1 开发期:顶部导航栏高度、单选框和日期选择器

现象:真机上自定义顶部导航背景错位,胶囊按钮遮住标题;模拟器正常,iPhone 上整个导航栏往下掉。

原因:自定义导航栏时,顶部安全区高度在 iPhone 上从 20pt 变成 44pt,导致手动加的状态栏高度不准。

解决:用wx.getMenuButtonBoundingClientRect()取胶囊按钮的位置来做导航栏高度,而不是硬编码 64px:

const menu = wx.getMenuButtonBoundingClientRect(); const statusBarHeight = wx.getSystemInfoSync().statusBarHeight; const navBarHeight = (menu.top - statusBarHeight) * 2 + menu.height;

现象:单选框点击整行没反应,只有点中小圆圈才生效。

原因:radio组件的默认点击区域太小。

解决:用<label>包裹整行,像 3.2 节那样写。

现象:日期选择器能选到已经过期的排班,或者预约了明天的号但“今天”还显示有号。

原因:picker 的start和end没有动态绑定当天时间。

解决:设置start="{{todayStr}}",todayStr从Date.now()格式化出来。

4.2 联调期:request 合法域名与真机白屏

现象:开发者工具里接口都通,把预览二维码发给别人,别人手机打开页面是一片空白或者接口全部报错。

原因:开发者工具默认勾选了“不校验合法域名”,真机上微信强制校验 request 合法域名,http://127.0.0.1:3000这种本机地址在真机上直接请求失败。

解决:开发联调阶段,在微信开发者工具的“详情→本地设置”勾选“不校验合法域名”;演示前,把后端部署到一台局域网内可访问的服务器,并在微信公众平台的“开发设置→服务器域名”里加入https://你的域名或测试用的局域网 IP。体验版不支持配置局域网 IP,所以演示往往只能用开发者工具或录屏。

如果坚持用开发者工具做演示,还有一点要注意:开发者工具的“不校验合法域名”只对工具本身生效,你发给别人试用的体验版还是要走正式域名。所以最稳的演示方式是电脑开开发者工具 + 真机用体验版双通道。把体验版二维码发给同学,对方扫码即可试用,不需要对方也装开发者工具。

4.3 答辩期:IP 变了、数据库没起、录屏是后悔药

现象:昨晚演示时一切正常,今天到答辩教室一打开就报“连接服务器失败”。

原因:笔记本从宿舍换到教室,Wi-Fi 网段变了,后端服务和数据库没跟着起来,或者小程序端的 baseURL 还停留在昨天的局域网 IP。

解决:演示前 30 分钟执行一次健康检查脚本,确认后端进程、MySQL、接口三项都正常。最保险的做法是提前录一份完整演示视频放在手机相册,一旦现场翻车就切到视频演示。

这里还要留一个后手:不要在现场临时改代码。答辩现场最容易出的问题不是代码 bug,而是环境,把环境变量和启动脚本写好,比临场改 baseURL 靠谱得多。我自己的习惯是随身带一个 U 盘,里面放一份后端启动脚本和数据库初始化 SQL,万一答辩机器不是自己的笔记本,也能快速恢复。

4.4 上线期:医疗服务类目、认证费用与个人主体

现象:小程序做好了,提交微信审核,被拒原因写着“你的小程序涉及医疗相关服务,需要提供《医疗机构执业许可证》”。

原因:预约挂号系统在微信小程序平台归类为“医疗-医疗机构”或“就医服务”类目,个人主体不具备资质,即使花 300 元做了微信认证,认证的主体如果没有医疗机构执业许可证,依然过不了类目审核。

解决:如果你是毕设项目,不要执着于上线发布,用“体验版”加“开发者工具演示”就是完整交付。如果真正要投产,正确路线是找到有资质的医院或第三方挂号平台挂靠,或用企业主体申请合适的类目。这块的坑在于很多同学觉得“先认证了再说”,结果 300 元的认证费花出去,类目还是过不了,属于典型的打水漂。

注意:不要为了过审而把页面改成“医疗咨询”,然后在登录后偷偷跳转到挂号页。小程序审核不只看首页,一旦被平台复查到,轻则下架,重则封号。


5. 把毕设部署成可演示状态:服务端启动、小程序配置与演示数据

拿到这类项目之后,第一步不是打开微信开发者工具,而是先把环境和数据准备齐。我每次部署预约挂号类项目都按下面三步走,十分钟内能恢复到可演示状态。

5.1 服务端:Node.js + MySQL 最小启动流程

假设你已经装好了 MySQL 8.x 和 Node.js 16+。在服务端目录执行:

# 1. 建库建表 mysql -uroot -p -e "CREATE DATABASE IF NOT EXISTS hospital_appointment DEFAULT CHARSET utf8mb4;" mysql -uroot -p hospital_appointment < server/sql/init.sql # 2. 安装依赖并启动 cd server cp .env.example .env npm install npm run start

这里init.sql里应该包括第 2 章那 8 张表和基础索引。.env.example里要配置 MySQL 连接串、JWT_SECRET、端口和微信小程序 appid/secret。启动成功后,在浏览器访问http://localhost:3000/api/department/list,能看到一个 JSON 数组表示服务端已经跑通。

注意:如果本机已经装了 MySQL 但端口被占用,改.env里的DB_PORT即可,不需要重装。

再给一个排查用的命令组合:服务端起不来时,先看端口有没有被占用,再看 MySQL 连没连上,最后看 Node 进程的报错日志。这三个顺序基本能解决九成的启动失败。

lsof -i :3000 mysql -uroot -p -e "SELECT 1" node server.js

5.2 小程序端:AppID、baseURL 与基础库版本

小程序端的配置分散在两个文件,一个是project.config.json,一个是app.js里的globalData。打开微信开发者工具导入项目时,AppID 要用自己申请的测试号,开发阶段不需要认证。app.js里改成:

globalData: { baseUrl: 'http://127.0.0.1:3000', appId: 'wx你的测试号appid' }

如果你用的是开发者工具演示,http://127.0.0.1:3000是可行的;如果接下来要切到真机预览,必须把 baseUrl 换成电脑在局域网内的 IP,比如http://192.168.1.5:3000。

基础库版本建议在project.config.json里设置一个相对高一点的版本,比如 2.30.0 以上。订阅消息、新版组件都依赖基础库,版本太低不会提示错误,只会静默失败,排查起来非常折磨人。把项目发给别人试用之前,记得在“小程序项目如何启动”这类文档里写清楚两步:先起后端,再在开发者工具里导入项目,否则别人拿到工程也不知道从哪里下手。

5.3 演示数据预置:让医生列表和排班永远“明天有号”

对接完环境和接口,最后一步是灌演示数据。很多毕设的演示数据是手工在数据库里一条条插入的,排班日期写死成某个固定日期,到了答辩那天早就过期了。正确做法是用 SQL 动态生成未来 7 天的排班:

INSERT INTO schedule (doctor_id, work_date, start_time, end_time, total_count) SELECT d.id, DATE_ADD(CURDATE(), INTERVAL seq.n DAY), '08:00', '12:00', 10 FROM doctor d CROSS JOIN ( SELECT 1 AS n UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 ) seq;

这段 SQL 的逻辑是让每个医生都生成从今天起未来 7 天的上午排班,CURDATE()保证日期永远跟随系统时间。号源表也要同步生成,每段号源默认状态为 0(可约),这样打开小程序时所有时段都有号可约。

演示数据不要做得太满,我一般会故意留一两个时段显示“约满”,这样演示页面能看到不同状态。如果所有时段都显示有号,反而显得数据不真实。也可以考虑在某个医生的排班里留一条“剩余 1 个号”的时段,用来演示抢号的边界情况。


6. 验收与演示技巧:从“能跑”到“答辩能过”

最后分享一套我一直在用的验收清单和演示技巧。所谓“能跑”,是指代码没有报错;所谓“答辩能过”,是指整个操作链在指定设备和网络环境下能顺畅重现,而且关键环节都有数据佐证。

演示前我建议按这个顺序自测:冷启动小程序→微信登录→进入科室列表→选医生→看排班号源→选一个时段→添加就诊人→提交预约→收到订阅消息→在“我的预约”里看到订单→执行取消。每一步如果有 toast 提示或页面状态变化,就算通过。特别要注意“添加就诊人”这一步,很多项目把就诊人和注册用户混在一起,导致一个人无法给父母挂号,这在预约挂号场景里是不完整的。

录视频是性价比最高的后悔药。现场演示时,我会用手机录屏把完整操作流程录 3 遍,第一遍用开发者工具模拟器,第二遍用真机体验版,第三遍带讲解旁白。答辩当天如果网络抽风,直接放视频,至少不会冷场。平时迭代代码前也养成了随手截图的习惯,改一版留一张“上一版在这个页面是正常的”截图,排查回归问题时会非常有帮助。

还要提醒一句:演示用的就诊人姓名、身份证号、手机号一定要用测试数据,不要用真实信息。身份证号和手机号这类隐私信息一旦出现在截图或录屏里,传到公开渠道就是事故。这也是我做这类系统时的一个习惯:凡是涉及个人信息的字段,开发环境一律用“张三”“110101199001011234”这种假数据,只有生产环境才接真实信息。

希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询