简介:这是一套完整的微信小程序毕业设计项目资源,面向计算机专业本科生及初学者,解决医院线上预约挂号场景下的前后端协同开发实践问题。资源包含前端小程序源码、Java后端服务、MySQL数据库脚本及详细部署说明与演示视频,覆盖需求分析、模块设计、接口联调到上线部署全流程,可直接用于课程设计或毕业答辩。压缩包共1922个文件,以125个JS逻辑文件、110个HTML/WXML页面文件、46个Java后端类、80个JSON配置及SQL数据库脚本为核心,辅以大量图片资源(150个GIF、29个PNG)和样式文件(33个WXSS),整体大小为120.5MB。已有3476人学习下载,配套内容完整:含后台管理(医生信息/排班/公告审核)、小程序前台(医生详情浏览、在线预约、用户评价查看)等全部功能模块,代码结构清晰、注释充分,部署文档步骤详尽,演示视频直观呈现核心交互流程。
1. 这不是“又一个小程序”,而是一套可落地的医疗轻服务闭环
微信小程序做医院预约挂号,听起来像毕业设计里最常见、最稳妥的选择——但真正跑通它,远不止“会写wxml+wxss”那么简单。我带过六届计算机和软件工程专业的毕设,每年至少有15%的学生选这个题,其中超过七成卡在“部署不起来”“用户登录失败”“号源同步不准”这三关。你手里的这个压缩包标题写着“源码+部署说明+演示视频”,但它真正的价值不在代码本身,而在于它把一套真实医疗场景下的轻量级服务链路,拆解成了本科生能理解、能复现、能答辩的完整模块:从微信授权登录的token安全流转,到号源库存的并发扣减逻辑;从分包加载策略对首屏时间的影响,到后台接口如何与医院HIS系统做最小化适配。这不是玩具Demo,它默认按三级医院日均3000+预约量的压力设计,所有数据库字段命名、API返回结构、错误码定义都遵循《医疗卫生信息互联互通标准化成熟度测评》里的基础规范。如果你是正在开题的学生,别急着改UI;先看懂它的预约状态机设计——为什么“已预约”不能直接变“已就诊”,中间必须经过“签到中”这个不可跳过的状态?为什么退号要走异步工单而不是实时回库?这些细节,才是答辩老师真正想听的“为什么”。关键词:微信小程序、毕业设计、医院预约挂号、源码、部署说明——它们不是并列关系,而是层层递进的实践路径:用源码理解架构,靠部署说明打通环境,借演示视频验证流程闭环。
2. 项目整体设计思路与核心逻辑拆解
2.1 为什么放弃“纯前端模拟”,坚持对接真实后端?
很多毕设作品用mock.js伪造号源数据,页面点一点就跳转成功,答辩时一问“如果两个用户同时抢最后一个号,怎么保证不超挂?”就哑火。本项目从第一天就明确:所有业务状态必须由后端原子性控制。它的后端采用Spring Boot 2.7 + MyBatis Plus构建,数据库用MySQL 8.0,关键表只有三张:doctor_schedule(医生排班)、appointment_order(预约订单)、user_profile(用户档案)。没有冗余的“科室表”“疾病分类表”,因为毕业设计不需要全院级建模——它只聚焦“挂号”这一件事。排班表里available_slots字段存的是JSON数组,比如["08:00-09:00", "10:00-11:00"],而不是拆成多行记录。这样设计不是偷懒,而是为了规避高并发下的行锁竞争:当用户点击“预约”时,后端直接用JSON_CONTAINS函数判断该时段是否可用,再用JSON_REMOVE原子性删除该时段,整个过程在单条SQL内完成,避免了传统“查-判-更”三步操作的竞态风险。我试过用Redis缓存号源,结果发现学生部署时Redis密码配错、连接池超时,反而让系统更不稳定。所以最终回归MySQL原生JSON支持——它够用,且调试直观。
2.2 小程序端为何强制分包?分包策略怎么定?
标题里没提,但源码里app.json的subNVue配置暴露了关键设计:首页、我的、预约记录三个Tab页各自独立分包,而“选择科室→医生→时段→确认”这个核心流程被打包进order分包。这不是为了凑技术指标,而是解决两个现实问题:第一,首页需加载轮播图、公告、热门医生头像等资源,体积超1MB,不分包会导致冷启动白屏超3秒;第二,“预约确认页”包含身份证OCR识别、电子签名Canvas、医保卡绑定弹窗等重型组件,若和首页混在一起,微信开发者工具编译直接报“内存溢出”。实际测试中,分包后首屏加载时间从2.8秒压到1.1秒,关键路径JS体积下降64%。更关键的是,它实现了状态隔离:用户在首页刷新不会丢失“已选医生ID”,因为order分包内的全局变量app.globalData.selectedDoctorId独立于主包生命周期。部署说明里特别强调“subNVue分包必须用wx.navigateTo跳转,禁用wx.switchTab”,就是因为后者会销毁当前分包实例——这点连很多辅导老师都忽略,导致学生反复出现“点了预约按钮却回到首页”的bug。
2.3 部署说明为什么比源码还厚?它到底在解决什么?
你拿到的部署说明.md有27页,远超代码注释量。这不是文档冗余,而是直面毕业生最痛的“环境鸿沟”:学校机房的CentOS 7.6、自己笔记本的Windows 10、云服务器的Ubuntu 20.04,三者对Node.js版本、MySQL字符集、SSL证书链的处理天差地别。比如MySQL部署环节,说明文档用整整两页讲utf8mb4_0900_as_cs和utf8mb4_unicode_ci的区别——前者是MySQL 8.0默认排序规则,但微信小程序的wx.login()返回的unionid含emoji符号,若用后者会导致插入失败报错“Incorrect string value”。再比如Nginx配置,文档给出三套方案:本地开发用proxy_pass http://localhost:8080,测试环境用proxy_pass https://api.xxx.com加proxy_ssl_verify off绕过自签名证书校验,生产环境则强制proxy_ssl_trusted_certificate指定CA根证书路径。这些细节,网上教程要么一笔带过,要么假定读者已精通运维。而本项目把每个chmod 755命令、每个systemctl restart nginx后的检查项(netstat -tuln | grep :443)都列出来,因为学生真会卡在“明明配置写了,但HTTPS就是打不开”这种问题上。
2.4 演示视频不是功能秀,而是故障推演录像
视频文件名demo_fault_simulation.mp4已经暗示重点。前3分钟展示正常预约流程:扫码登录→选科室→选医生→选时段→支付成功。但从第3分12秒开始,画面切到后台管理端,手动将某医生的available_slots字段清空,再回到小程序端刷新——此时页面显示“暂无号源”,而非崩溃或空白。接着演示网络弱网场景:用Chrome DevTools的Throttling调至“Slow 3G”,点击预约按钮后,界面上“加载中”动画持续4秒,期间用户无法重复提交,且倒计时结束后自动提示“网络超时,请重试”。最后是数据一致性验证:后台直接SQL删除一条订单记录,小程序“我的预约”列表仍显示该订单,但点击进入详情页时,后端返回{code: 404, msg: "订单不存在"},前端立即跳转到空状态页并提示“该预约已失效”。这种设计不是炫技,而是教学生理解前端乐观更新与后端最终一致性的平衡点——毕设答辩时,老师问“你怎么保证数据不脏读?”,你能指着视频说:“看这里,我们用HTTP状态码驱动UI状态,而不是靠前端定时轮询”。
3. 核心细节解析与实操要点
3.1 微信登录态管理:为什么不用wx.checkSession()?
几乎所有小程序教程都教用wx.checkSession()检测登录态,但本项目在app.js里完全弃用它。原因很现实:checkSession只验证本地session_key是否过期,而微信官方明确说明session_key有效期2小时,且同一用户多次登录会刷新。学生常犯的错误是——用户登录后,把session_key存入wx.setStorageSync,以为能长期使用。结果部署后发现,用户隔天打开小程序,checkSession返回true(本地key没过期),但用这个key解密手机号时失败,因为服务端的session_key早已被新登录覆盖。本项目采用双token机制:小程序端存储access_token(30天有效期,由后端颁发),每次请求携带Authorization: Bearer xxx;后端用JWT校验,payload里存openid和expire_time。登录流程是:wx.login()→ 传code给后端 → 后端调用微信接口换session_key+openid→ 生成JWT返回 → 小程序存access_token。这样做的代价是每次登录多一次HTTP请求,但换来的是状态可控。部署说明里专门提醒:“若修改JWT密钥,必须清空所有用户本地access_token,否则出现‘登录态异常’无法排查”。
3.2 号源库存扣减:为什么用MySQL JSON而不选Redis?
网上90%的挂号系统教程推荐Redis+Lua做库存扣减,理由是“高性能”。但本项目在AppointmentService.java里坚持用MySQL执行UPDATE doctor_schedule SET available_slots = JSON_REMOVE(available_slots, '$[0]') WHERE id = ? AND JSON_CONTAINS(available_slots, '"08:00-09:00"')。原因有三:第一,Redis需要额外部署和维护,学生云服务器通常只开MySQL端口,加Redis等于增加故障点;第二,Lua脚本调试困难,redis-cli --eval命令对新手不友好,而MySQL的EXPLAIN能直接看到执行计划;第三,也是最关键的一点:号源数据必须与医生排班强一致。Redis里存的号源是快照,若HIS系统调整排班(如医生临时停诊),MySQL能实时更新available_slots字段,Redis却需要额外的消息队列同步,毕设根本没精力做。实测数据:在阿里云2核4G MySQL实例上,该SQL平均耗时8ms,QPS达1200,足够应付毕业设计演示压力。注意事项:JSON_CONTAINS函数在MySQL 5.7需开启innodb_file_format=Barracuda,部署说明第12页有详细开关步骤。
3.3 分包异步化:wx.loadSubNVue的隐藏陷阱
标题热词里提到“微信小程序分包异步化”,本项目在pages/index/index.js里用wx.loadSubNVue动态加载预约流程分包,但源码里藏着关键补丁:
// pages/index/index.js onLoad() { // 延迟100ms再加载分包,避开微信初始化竞争 setTimeout(() => { this.subNVue = wx.loadSubNVue({ id: 'order', url: '/subNVue/order/order.nvue', styles: { top: '0px', bottom: '0px' } }); }, 100); }为什么加setTimeout?因为微信小程序启动时,app.js的onLaunch、onShow、页面onLoad的执行顺序不固定。若loadSubNVue在onLaunch完成前执行,subNVue实例会创建失败,但控制台不报错,只静默返回null。学生调试时会疯狂检查路径是否正确,却忽略时序问题。这个100ms是实测得出的最小安全值——在iPhone 12和华为Mate 40上均稳定。另一个坑是subNVue的show方法:文档说subNVue.show()即可显示,但实际需配合wx.setNavigationBarColor动态改导航栏颜色,否则iOS下出现“白条闪烁”。源码里order.nvue的mounted钩子中,先this.$nextTick(() => this.$scope.show()),再调用wx.setNavigationBarColor,确保渲染完成后再显示。
3.4 部署中的SSL证书:Let's Encrypt的“三步陷阱”
部署说明第18页的SSL配置,表面是certbot --nginx一行命令,实则埋着三个必踩的坑:
- 域名解析延迟:
certbot要求域名A记录指向服务器IP,但DNS生效需1-48小时。学生常卡在这里,以为命令失败,其实只是等待。解决方案:用dig yourdomain.com +short确认解析生效后再运行certbot。 - Nginx配置冲突:
certbot会自动改Nginx配置,但若学生之前手动加过location /api { proxy_pass ... },certbot可能把ssl_certificate指令插到错误位置,导致Nginx启动失败。部署说明给出修复命令:nginx -t && systemctl restart nginx,并强调“若报错,用journalctl -u nginx -n 50查具体哪行配置错”。 - 证书自动续期失效:
certbot renew默认每周日凌晨3点执行,但学生服务器常关机。部署说明要求添加crontab -e任务:0 3 * * 1 /usr/bin/certbot renew --quiet --post-hook "/bin/systemctl reload nginx",并验证systemctl list-timers | grep certbot确认定时器激活。这些细节,少一步,HTTPS就变成HTTP,微信小程序的wx.request直接拒绝连接。
4. 实操过程与核心环节实现
4.1 本地开发环境搭建:从零开始的12个关键步骤
别跳过这一步。很多学生直接上传代码到服务器,结果因环境差异浪费三天。以下是严格按部署说明执行的实操记录:
- Node.js安装:必须用v14.17.0(LTS),v16+版本
npm install会报node-sass兼容错误。Windows用户下载.msi安装包,勾选“Add to PATH”;macOS用brew install node@14,再brew link node@14 --force。 - MySQL初始化:执行
mysql -u root -p后,运行CREATE DATABASE hospital_app DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs;。注意不是utf8mb4_unicode_ci,否则插入unionid时报错。 - 后端启动:进入
backend/目录,mvn clean package -Dmaven.test.skip=true打包。生成的target/hospital-app.jar用java -jar hospital-app.jar --spring.profiles.active=dev启动。dev配置文件里spring.datasource.url必须是jdbc:mysql://localhost:3306/hospital_app?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai。 - 小程序开发者工具配置:在“详情→本地设置”中,关闭“ES6转ES5”和“增强编译”,因为源码已用Webpack 5预编译。勾选“不校验合法域名”,否则
http://localhost:8080请求被拦截。 - 前端启动:
cd frontend/→npm install→npm run dev。此时浏览器打开http://localhost:8080,应看到Vue版管理后台(用于模拟HIS系统录入排班)。 - 微信AppID配置:在
frontend/config/index.js里填入自己的AppID,appid: 'wx1234567890abcdef'。注意不是公众号AppID,必须是小程序AppID,且在微信公众平台开通“微信登录”和“获取手机号”权限。 - 数据库初始化数据:运行
backend/src/main/resources/init.sql,它会插入3个测试医生、5个科室、20条排班记录。关键字段doctor_schedule.available_slots是JSON字符串,如'["08:00-09:00","14:00-15:00"]'。 - 后端接口测试:用Postman访问
http://localhost:8080/api/v1/doctors?deptId=1,应返回JSON数组,含name、title、avatar字段。若返回404,检查application-dev.yml里server.port是否为8080。 - 小程序真机调试:在开发者工具点“预览”,用自己手机微信扫码。首次打开会提示“登录”,此时微信会弹出授权框。若卡在“正在登录”,检查
app.js里wx.login()回调是否被console.log阻塞(部署说明第7页警告:删掉所有console.log再上线)。 - 号源扣减验证:在管理后台“排班管理”页,找到医生A的某条排班,点击“减少号源”,后台执行
UPDATE doctor_schedule SET available_slots = JSON_REMOVE(available_slots, '$[0]')。然后小程序端刷新该医生页面,“可预约时段”应实时减少。 - 支付模拟:小程序里点“去支付”,跳转到
/pages/pay/pay页。此处不接真实微信支付,而是调用/api/v1/pay/mock接口,返回{payStatus: "success", orderNo: "202310010001"}。部署说明强调:正式部署时,此接口需替换为微信官方unifiedorder,且notify_url必须是公网可访问地址。 - 日志监控:后端启动后,
tail -f logs/app.log查看实时日志。当小程序发起预约请求,日志应输出INFO c.h.s.service.AppointmentService - [order-12345] 预约成功,扣减号源:08:00-09:00。若出现WARN级别日志,如号源不足,拒绝预约,说明库存逻辑生效。
提示:步骤3和步骤8是最高频失败点。学生常因MySQL密码错误或端口被占用导致后端启动失败,建议用
lsof -i :3306查端口占用,用mysql -u root -p -h 127.0.0.1测试连接。
4.2 云服务器部署全流程:以腾讯云CentOS 7为例
本地跑通不等于线上可用。以下是我在腾讯云CVM上部署的真实记录(配置:2核4G,50G SSD,CentOS 7.9):
第一步:基础环境安装
# 更新系统 yum update -y # 安装Java 8(必须!Spring Boot 2.7不支持Java 11) yum install java-1.8.0-openjdk-devel -y java -version # 确认输出1.8.0_xxx # 安装MySQL 8.0 rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm yum install mysql-community-server -y systemctl start mysqld systemctl enable mysqld # 获取初始密码 grep 'temporary password' /var/log/mysqld.log # 登录并改密码 mysql -u root -p ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourStrongPass123!';第二步:配置MySQL安全策略
-- 创建数据库 CREATE DATABASE hospital_app DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs; -- 创建专用用户 CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'AppPass123!'; GRANT ALL PRIVILEGES ON hospital_app.* TO 'appuser'@'localhost'; FLUSH PRIVILEGES; -- 关键!修改MySQL配置 echo "collation-server = utf8mb4_0900_as_cs" >> /etc/my.cnf echo "init-connect = 'SET NAMES utf8mb4'" >> /etc/my.cnf systemctl restart mysqld第三步:部署后端Jar包
# 创建部署目录 mkdir -p /opt/hospital-app/{logs,config} # 上传jar包到/opt/hospital-app/ # 上传application-prod.yml到/opt/hospital-app/config/ # 修改prod配置中的数据库密码 sed -i 's/your_password/AppPass123!/' /opt/hospital-app/config/application-prod.yml # 创建systemd服务 cat > /etc/systemd/system/hospital-app.service << 'EOF' [Unit] Description=Hospital Appointment Service After=network.target [Service] Type=simple User=root WorkingDirectory=/opt/hospital-app ExecStart=/usr/bin/java -jar /opt/hospital-app/hospital-app.jar --spring.config.location=file:/opt/hospital-app/config/application-prod.yml Restart=always RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable hospital-app systemctl start hospital-app # 查看日志 journalctl -u hospital-app -f第四步:Nginx反向代理配置
# 安装Nginx yum install nginx -y # 编辑配置 cat > /etc/nginx/conf.d/hospital.conf << 'EOF' upstream backend { server 127.0.0.1:8080; } server { listen 80; server_name your-domain.com; location /api/ { proxy_pass http://backend/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { root /opt/hospital-app/frontend; try_files $uri $uri/ /index.html; } } EOF systemctl start nginx systemctl enable nginx第五步:申请SSL证书并启用HTTPS
# 安装certbot yum install epel-release -y yum install python3-certbot-nginx -y # 申请证书(需提前解析域名) certbot --nginx -d your-domain.com # 此时certbot会自动改Nginx配置,启用443端口 # 验证HTTPS curl -I https://your-domain.com/api/v1/health # 应返回HTTP/2 200第六步:小程序域名配置
登录微信公众平台 → 开发管理 → 开发者工具 → 小程序服务器域名,添加:
- request合法域名:
https://your-domain.com - socket合法域名:留空(本项目不用WebSocket)
- uploadFile合法域名:同request域名
- downloadFile合法域名:同request域名
注意:必须是HTTPS,且证书由受信任CA颁发(Let's Encrypt符合要求)。添加后需管理员扫码确认,24小时内生效。
4.3 演示视频录制要点:让答辩老师一眼看懂价值
视频不是录屏幕,而是讲逻辑。以下是剪辑脚本(总长8分30秒):
0:00-1:20 痛点切入
画面:医院挂号窗口长队航拍镜头 → 切到手机微信“城市服务”里挂号入口 → 点击后加载转圈10秒 → 弹出“服务繁忙,请稍后再试”。画外音:“每天超200万人遭遇挂号难,而我们的系统,让这一切在3秒内完成。”
1:21-3:00 核心流程演示
分屏显示:左屏小程序操作,右屏后台数据库实时查询。操作:扫码登录 → 选“内科” → 列表滑动,医生头像旁有“今日剩余3号”红标 → 点医生A → 显示“08:00-09:00(剩2)”“14:00-15:00(剩1)” → 点“08:00-09:00” → 填写身份证 → 点“立即预约”。此时右屏执行SELECT available_slots FROM doctor_schedule WHERE id=123,显示["14:00-15:00"],证明号源已扣减。
3:01-5:15 故障应对演示
画面:左屏小程序,右屏终端SSH连接服务器。操作:在终端执行UPDATE doctor_schedule SET available_slots='[]' WHERE id=123;→ 小程序端刷新医生A页面 → 显示“暂无号源”灰色按钮。再模拟弱网:Chrome DevTools选“Slow 3G” → 点预约 → 左屏显示“请求中...(3s)” → 3秒后弹出“网络超时,请重试”。画外音:“状态由后端驱动,前端只负责呈现,这才是健壮系统的基石。”
5:16-7:40 数据一致性验证
画面:左屏小程序“我的预约”,右屏MySQL命令行。操作:在小程序点“取消预约” → 后端返回{code:200,msg:"已取消"}→ 左屏该订单消失。此时右屏执行SELECT * FROM appointment_order WHERE order_no='202310010001';→ 返回空集。画外音:“每一次用户操作,都在数据库留下不可篡改的痕迹,这正是医疗系统的生命线。”
7:41-8:30 技术栈总结
动态文字浮现:Spring Boot 2.7(后端)|MySQL 8.0 JSON(数据)|微信小程序原生(前端)|Nginx+Let's Encrypt(部署)。最后定格文字:“不是炫技,而是让每一行代码,都经得起真实场景的拷问。”
5. 常见问题与排查技巧实录
5.1 “小程序白屏”问题速查表
这是学生提问率最高的问题,90%源于配置错误。按优先级排查:
| 现象 | 可能原因 | 排查命令 | 解决方案 |
|---|---|---|---|
| 真机扫码白屏,开发者工具正常 | app.json中"usingComponents": true未开启 | 检查app.json根节点是否有"usingComponents": true | 添加该字段,重启开发者工具 |
| 开发者工具白屏,控制台无报错 | project.config.json里miniprogramRoot路径错误 | 查看project.config.json中miniprogramRoot值 | 改为"miniprogramRoot": "frontend/",(假设源码在frontend目录) |
白屏且控制台报VMxxxx:1 Uncaught SyntaxError: Unexpected token '<' | Nginx静态资源路由错误,返回了HTML而非JS | curl -I http://localhost:8080/app.js | 检查Nginx配置,location / { root /path/to/frontend; }必须指向build后目录 |
白屏且报fail net::ERR_CONNECTION_REFUSED | 后端服务未启动或端口被占 | netstat -tuln | grep :8080 | systemctl status hospital-app查服务状态,kill -9 $(lsof -t -i :8080)杀占用进程 |
白屏且报fail Error: connect ECONNREFUSED 127.0.0.1:8080 | 小程序请求域名未配或配错 | 查frontend/config/index.js中baseURL | 改为https://your-domain.com/api/,确保域名已备案且HTTPS可用 |
实操心得:我让学生养成习惯,遇到白屏先做三件事:1. 打开开发者工具Network面板,看第一个请求是否404;2. 在Console里输入
wx.getSystemInfoSync(),确认基础API可用;3. 用curl -v https://your-domain.com/api/v1/health测试后端连通性。80%的问题在这三步内定位。
5.2 “登录后无法获取手机号”问题深度解析
微信小程序获取手机号需用户主动点击<button open-type="getPhoneNumber">,但学生常遇到“点击无反应”或“回调返回empty”。根源在三个层面:
第一层:前端配置
- 按钮必须用
<button open-type="getPhoneNumber" bindgetphonenumber="onGetPhoneNumber">,不能用bindtap模拟。 onGetPhoneNumber事件回调中,e.detail.code为空,说明微信未返回加密数据。此时检查app.json是否开启了"requiredPrivateInfos": ["phoneNumber"](微信基础库2.29.0+必需)。
第二层:后端解密
- 后端收到
code后,需用session_key解密。但session_key由wx.login()的code换得,若前后两次code不同(用户快速点击两次按钮),session_key就失效。本项目在PhoneService.java里加了防抖:if (System.currentTimeMillis() - lastDecryptTime < 5000) return; lastDecryptTime = System.currentTimeMillis();。
第三层:微信配置
- 公众平台必须开通“获取手机号”权限,并在“接口权限”里勾选。
- 更隐蔽的坑:若小程序绑定了公众号,且公众号未认证,则手机号接口被禁用。解决方案:登录公众号后台,确认“微信认证”状态为“已认证”。
5.3 “号源显示错误”问题排查路径
学生常反馈:“后台明明还有号,小程序却显示‘已约满’”。这不是代码bug,而是数据同步问题:
Step 1:确认号源字段格式
执行SELECT available_slots FROM doctor_schedule WHERE id=123;,结果必须是JSON数组,如["08:00-09:00"]。若返回"08:00-09:00"(字符串非数组),JSON_CONTAINS永远返回false。修复:UPDATE doctor_schedule SET available_slots='["08:00-09:00"]' WHERE id=123;
Step 2:检查MySQL JSON函数支持
运行SELECT JSON_CONTAINS('["a","b"]', '"a"');,应返回1。若返回NULL,说明MySQL版本低于5.7或未启用JSON支持。升级MySQL或改用FIND_IN_SET替代。
Step 3:验证时区一致性
小程序前端用new Date().toLocaleString()获取本地时间,后端用LocalDateTime.now()。若服务器时区为UTC,而前端为东八区,时段匹配必然失败。部署说明要求:timedatectl set-timezone Asia/Shanghai,并在application-prod.yml中加spring.jackson.time-zone: GMT+8。
5.4 部署后“HTTPS请求失败”终极指南
微信小程序强制HTTPS,但学生部署后常遇request:fail ssl hand shake error。这不是证书问题,而是TLS协议版本不匹配:
现象诊断:
用openssl s_client -connect your-domain.com:443 -tls1_2测试,若返回Protocol: TLSv1.2且Verify return code: 0 (ok),说明证书正常。若返回SSL routines:ssl3_get_record:wrong version number,则是服务器TLS版本过低。
解决方案:
编辑/etc/nginx/nginx.conf,在http块中添加:
ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;然后nginx -t && systemctl reload nginx。
注意:CentOS 7默认OpenSSL版本1.0.2,不支持TLS 1.3。若需启用,需升级OpenSSL或改用TLS 1.2。本项目默认配置TLS 1.2,兼容性最佳。
5.5 毕设答辩高频问题应答清单
老师最爱问的5个问题,附标准答案逻辑:
Q1:为什么用MySQL JSON存号源,不用关系表?
答:关系表需JOIN查询,高并发下易锁表;JSON用单条SQL原子操作,实测QPS提升3倍。毕设场景数据量小,JSON更简洁,且MySQL 8.0对其优化完善。
Q2:如何防止黄牛刷号?
答:本项目未接入公安实名库,但预留了防刷机制:1. 同一openid24小时内限挂3次;2.wx.getPhoneNumber获取真实手机号,与挂号信息绑定;3. 后台可配置IP限频,nginx配置limit_req zone=api burst=5 nodelay;。
Q3:分包加载会影响SEO吗?
答:小程序无传统SEO,但分包提升用户体验。微信搜索会抓取小程序页面标题和描述,本项目在app.json中为每个分包页配置了"navigationBarTitleText"和"description",确保搜索曝光。
Q4:如果医院HIS系统不提供API,怎么对接?
答:本项目设计为“最小化适配”。只需HIS导出CSV排班表,后台用ScheduledExecutorService每日凌晨执行INSERT INTO doctor_schedule ... SELECT ... FROM CSV导入。无需实时API,降低对接成本。
Q5:毕业设计创新点在哪?
答:不是技术堆砌,而是医疗场景的精准建模:1. 号源状态机(预约→签到→就诊→完成);2. 分包异步化解决冷启动;3. 双token登录态管理保障安全。每处设计都源于真实挂号痛点。
6. 个人实操体会:这项目教会我的三件事
我在2019年第一次带这个毕设题,当时学生用PHP写了个单页应用,部署在虚拟主机上,答辩时演示到一半网站打不开。后来迭代到Java+MySQL+小程序,现在这套方案已稳定运行四年,服务过17所高校的毕设团队。回头来看,它教会我最深的三件事:
第一,“能跑通”比“用最新技术”重要一百倍。曾有个学生坚持用Vue 3 + Composition API重构前端,结果卡在ref响应式和微信小程序生命周期冲突上,答辩前一周还在debug。最后他删掉所有新特性,回归Vue 2 Options API,三天搞定。技术选型的第一原则是:团队能否在截止日前交付可演示的版本。Spring Boot 2.7、MySQL 8.0、微信基础库2.25
本文还有配套的精品资源,点击获取