ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

微信小程序医院预约挂号系统设计与数据库并发控制详解

微信小程序医院预约挂号系统设计与数据库并发控制详解 简介这是一套面向医院门诊场景的微信小程序预约挂号系统完整项目包含前后端源码、数据库文件及配套论文适合计算机专业学生用于毕业设计、课程设计或项目实战练习。压缩包共2000个文件以PHP后端、Vue/JS前端逻辑、WXML/WXSS小程序页面为主附带SQL数据库、Excel数据表以及一键部署脚本整体大小约19.82MB目录结构清晰便于按模块查阅。系统实现用户注册登录、科室医生信息查询、在线预约、支付取号、取消预约及后台排班管理等完整业务流程覆盖小程序开发、API接口调用、微信支付集成、数据库设计等多项关键技术点。资源还包含后台管理端页面和论文文档可帮助理解系统架构与实现思路。已有372人学习下载对于需要快速上手项目开发的计算机专业学生这是一份可直接运行、二次开发和写入简历的宝贵资料。1. 微信小程序医院预约挂号系统不只是一张小程序页面微信小程序医院预约挂号系统是毕业设计里出现频率很高的一个选题前端一个小程序后端一套接口数据库几张表再加一篇论文。它的价值不在技术难度而在于把真实业务里的“预约”“排班”“退号”“爽约”这几个状态流转完整做了一遍。这个题目适合正在找毕业设计方向的计算机专业学生也适合想用完整项目入门微信小程序开发的从业者。很多人以为难点在微信小程序的页面写法实际情况是页面一两天就能写完号源排班和并发下的余号扣减才是让项目翻车的地方。这篇内容就按“先建表、再写接口、最后填页面”的顺序把每一步的可复现细节和坑位讲清楚。2. 先把预约挂号拆成数据模型数据库设计决定系统上限2.1 科室、医生、用户三张基础表的字段与索引我一般拿到这种选题先不急着建小程序页面而是把数据库表画出来。预约挂号系统的实体关系不复杂但表之间怎么关联、哪些字段参与业务状态流转直接决定后面接口好不好写。热点词里那些“数据库”“增删改查”是真的核心先拆表再写业务可以少走很多弯路。用户表存储小程序端授权登录的用户。核心字段id 主键、openid 微信用户唯一标识、nickname 昵称、phone 手机号、create_time 注册时间。openid 需要加唯一索引微信登录时要用它反查用户如果允许手机号登录phone 也建议加唯一索引。这里有个细节不要把微信返回的 session_key 存进数据库。session_key 每次登录都会变存它只会让“登录态过期”的排查更难。科室表字段简单id、name 科室名、intro 科室介绍。医院科室层级一般是“内科到心血管内科”这种两级结构毕业设计做成一级就够真要做两级加一个 parent_id 字段预留好总比后面改表舒服。医生表要小心。字段包括id、dept_id 所属科室、name 医生姓名、title 职称、intro 简介、week_schedule 出诊星期。week_schedule 很容易设计错常见做法是存字符串“1,2,3,4,5”表示周一到周五出诊也有用 JSON 数组存每天出诊时间段的。我更推荐后者因为上午、下午的出诊时段不一样单纯一个字符串表达不了。dept_id 加普通索引因为科室页面要按它查医生列表。title 不要做成数字枚举直接存“主任医师”“副主任医师”这种字符串页面渲染少一次字典转换论文里写起来也直观。2.2 号源表与预约订单表状态机才是灵魂很多选这个题的人会把预约订单当成核心表其实真正的核心是号源表 schedule。它描述“某医生在某个日期某个时间段放了多少个号”预约订单只是对这个号的占用记录。schedule 表字段id、doctor_id 医生、dept_id 科室冗余方便查询、work_date 出诊日期、start_time 开始时间、end_time 结束时间、total_count 总号数、booked_count 已约号数、status 状态、version 版本号。status 建议用 0 正常、1 已约满、2 停诊。已约满这个状态其实可以由 booked_count total_count 推导出来但保留它能让列表页筛选更直接接口少一次计算。appointment 预约订单表字段id、order_no 订单号、user_id 用户、doctor_id 医生、schedule_id 号源、appoint_date 预约日期、status 状态、create_time 下单时间、cancel_time 取消时间。订单状态机是这套系统要讲清楚的重点。习惯定义成0 待支付、1 已预约、2 已完成、3 已取消、4 爽约。待支付和已预约必须分开很多医院要求先付费再占号不想要支付环节的课设可以直接从 0 变 1但论文里的状态图就少了一个分支。爽约状态靠定时任务或用户主动操作触发用户约了当天号源没到诊也没取消系统就把订单标记为 4。这个逻辑在答辩时很加分因为它体现的不只是增删改查而是把业务闭环想清楚了。2.3 MySQL 建库建表脚本用 Navicat 跑通初始化数据库我用 MySQL 8.0管理工具用 Navicat。下面是完整建表脚本直接用 Navicat 新建查询执行注意字符集、索引和外键这三个点。-- 医院预约挂号系统核心表初始化脚本 CREATE DATABASE IF NOT EXISTS hospital_appointment DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE hospital_appointment; -- 用户表 CREATE TABLE user ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, openid VARCHAR(64) NOT NULL COMMENT 微信openid, nickname VARCHAR(50) DEFAULT COMMENT 昵称, phone VARCHAR(20) DEFAULT COMMENT 手机号, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_openid (openid) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表; -- 科室表 CREATE TABLE department ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(50) NOT NULL COMMENT 科室名称, intro VARCHAR(500) DEFAULT COMMENT 科室介绍, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT科室表; -- 医生表 CREATE TABLE doctor ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, dept_id INT UNSIGNED NOT NULL COMMENT 所属科室, name VARCHAR(50) NOT NULL, title VARCHAR(30) DEFAULT COMMENT 职称, intro VARCHAR(500) DEFAULT , week_schedule VARCHAR(100) NOT NULL DEFAULT [] COMMENT 出诊安排JSON, PRIMARY KEY (id), KEY idx_dept (dept_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT医生表; -- 号源表 CREATE TABLE schedule ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, doctor_id INT UNSIGNED NOT NULL, dept_id INT UNSIGNED NOT NULL, work_date DATE NOT NULL COMMENT 出诊日期, start_time TIME NOT NULL, end_time TIME NOT NULL, total_count INT NOT NULL DEFAULT 30 COMMENT 总号数, booked_count INT NOT NULL DEFAULT 0 COMMENT 已约号数, status TINYINT NOT NULL DEFAULT 0 COMMENT 0正常 1约满 2停诊, version INT NOT NULL DEFAULT 0 COMMENT 乐观锁版本号, PRIMARY KEY (id), KEY idx_doctor_date (doctor_id, work_date) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT号源表; -- 预约订单表 CREATE TABLE appointment ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL COMMENT 订单号, user_id INT UNSIGNED NOT NULL, doctor_id INT UNSIGNED NOT NULL, schedule_id INT UNSIGNED NOT NULL, appoint_date DATE NOT NULL COMMENT 预约就诊日期, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待支付 1已预约 2已完成 3已取消 4爽约, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, cancel_time DATETIME DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no), KEY idx_user_status (user_id, status), KEY idx_schedule (schedule_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT预约订单表; -- 黑名单表 CREATE TABLE blacklist ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, user_id INT UNSIGNED NOT NULL, reason VARCHAR(200) DEFAULT COMMENT 拉黑原因, expire_time DATETIME NOT NULL COMMENT 解禁时间, PRIMARY KEY (id), KEY idx_user (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT黑名单表;这套脚本建库时先把数据库字符集固定成 utf8mb4后面所有表默认继承。user、order在 MySQL 里是保留字表名全用反引号包住order_no 字段避开保留字。唯一索引uk_openid保证同一个微信用户只占一行idx_doctor_date支撑“按医生查某天号源”的高频查询。三个重点解释一下。第一字符集一定要用 utf8mb4不要用 utf8。小程序端昵称里一旦出现 emojiutf8 表会直接报Incorrect string value。第二外键我故意没建。毕业设计图方便删数据用逻辑关联代替物理外键真要加外键Navicat 按脚本顺序导入时容易因为表引用顺序报错。第三order_no 不要用自增 id 当订单号应用层生成格式可以是当天日期加时间戳加四位随机数保证全局唯一且能看出下单时间。提示MySQL 8.0 默认认证插件是 caching_sha2_password老版本 Navicat 连接会报 “Client does not support authentication protocol”。解决方法是把用户认证改回 mysql_native_passwordALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码;或者直接升级 Navicat。3. 微信小程序端最小可运行代码从登录授权到提交预约3.1 项目结构与技术选型原生微信小程序够用很多人在“原生微信小程序还是 uniapp”之间纠结。uniapp 在热词里常被拿来对比 Android、iOS、鸿蒙的多端复用好处是一套代码编译多端代价是每端行为差异都要填坑。预约挂号这个题目的核心是业务本身我的建议是用原生微信小程序理由有三官方文档就是现成的学习资料预览调试路径最短答辩被问到页面生命周期时能直接指到 Page 代码不用隔着一层框架解释。项目结构按功能拆目录页面只放四个首页科室列表、科室详情医生列表、预约提交页、我的预约列表。├── app.js # 全局逻辑、登录态初始化 ├── app.json # 页面路由与 window 配置 ├── utils/ │ └── request.js # wx.request 统一封装 ├── pages/ │ ├── index/ # 首页科室列表 │ ├── department/ # 科室详情医生列表 │ ├── booking/ # 预约提交页 │ └── order/ # 我的预约列表app.json 里要注意微信小程序顶部导航栏高度。默认导航栏在不同机型上高度不一样iPhone X 以上带刘海Android 普遍 48px 左右。做排班页头部固定时建议用navigationStyle: custom后自己算状态栏高度否则真机预览会看到导航栏和内容重叠。不想自定义时直接保留默认导航栏在 app.json 里配置navigationBarTitleText省掉适配问题。3.2 全局配置与 wx.request 请求封装登录流程小程序端只做一件事调用 wx.login 拿 code发给后端换 token。token 过期时间要自己管理不要依赖微信 session_key因为 session_key 有效期不稳定会出现“小程序还开着后端已经说登录过期”的体验断裂。// app.js - 小程序入口 App({ globalData: { token: , userInfo: null }, onLaunch() { this.login() }, login() { wx.login({ success: (res) { if (res.code) { // 把 code 发给后端后端通过 code2session 换 openid 并返回自定义 token wx.request({ url: http://localhost:8080/api/auth/login, method: POST, data: { code: res.code }, success: (res) { if (res.data.code 0) { const token res.data.data.token this.globalData.token token // 本地缓存 token 和过期时间 wx.setStorageSync(token, token) wx.setStorageSync(token_expire, Date.now() 7200 * 1000) } } }) } } }) } })token_expire 是我建议加的很多项目只存 token 不存过期时间用户隔天打开时 token 早已失效接口返回 401 才跳登录白屏一整个页面。小程序端先判断本地过期时间失效直接走登录流程这个细节写进论文里能体现你考虑过状态管理。http://localhost:8080是本地开发地址真机预览时 localhost 指向手机本身必须改成局域网 IP 或 HTTPS 域名这是新手最容易“开发工具能跑、手机一打开全失败”的根因。请求封装要解决三件事统一注入 token、统一处理业务码、统一处理 401。下面的封装是我最常用的结构。// utils/request.js - 微信小程序网络请求封装 const BASE_URL http://192.168.1.100:8080/api function request(path, method GET, data {}) { return new Promise((resolve, reject) { const token wx.getStorageSync(token) wx.request({ url: BASE_URL path, method: method, data: data, header: { Content-Type: application/json, Authorization: token ? Bearer token : }, success: (res) { if (res.data.code 0) { resolve(res.data.data) } else if (res.data.code 401) { // token 过期清缓存并跳登录 wx.removeStorageSync(token) wx.removeStorageSync(token_expire) wx.navigateTo({ url: /pages/login/login }) reject(res.data) } else { reject(res.data) } }, fail: (err) reject(err) }) }) } module.exports { request, BASE_URL }BASE_URL 独立到一个文件里换后端地址时只改一处。后端返回格式统一成{ code, message, data }code 0 成功401 表示登录态失效。这个约定要在前后端接口文档里写死后面论文接口设计章节直接引用。3.3 科室列表与医生排班页WXML 渲染与预约提交科室列表页用 3.2 的封装请求后端接口加载完渲染到 WXML。医生排班页要根据 doctorId 查号源列表每个号源显示日期、时段和余号余号由totalCount - bookedCount计算前端只展示不计算业务逻辑。// pages/index/index.js - 科室列表 const { request } require(../../utils/request) Page({ data: { departments: [], loading: false }, onLoad() { this.loadDepartments() }, async loadDepartments() { this.setData({ loading: true }) try { const departments await request(/department/list, GET) this.setData({ departments: departments }) } catch (e) { wx.showToast({ title: 加载失败, icon: none }) } finally { this.setData({ loading: false }) } } })预约提交是核心动作。用户点“确认预约”后前端把 doctorId 和 scheduleId 传给后端按钮立刻禁用等接口返回再恢复。这能拦住手滑连点但真正防止重复订单要靠后端幂等控制前端防重只是体验层面的第一道防线。// pages/booking/booking.js - 预约提交 const { request } require(../../utils/request) Page({ data: { doctorId: , scheduleId: , submitting: false }, onLoad(options) { this.setData({ doctorId: options.doctorId, scheduleId: options.scheduleId }) }, submitOrder() { if (this.data.submitting) return this.setData({ submitting: true }) request(/appointment/create, POST, { doctorId: this.data.doctorId, scheduleId: this.data.scheduleId }).then((data) { wx.showToast({ title: 预约成功, icon: success }) wx.redirectTo({ url: /pages/order/order?id data.appointmentId }) }).catch((err) { wx.showToast({ title: err.message || 预约失败, icon: none }) this.setData({ submitting: false }) }) } })对应 WXML 里按钮绑定 submitting 状态view classdoctor-info text classname{{doctorInfo.name}}/text text classtitle{{doctorInfo.title}}/text /view view classschedule-info text就诊日期{{schedule.workDate}}/text text号源剩余{{schedule.totalCount - schedule.bookedCount}}/text /view button classsubmit-btn disabled{{submitting}} bindtapsubmitOrder {{submitting ? 提交中... : 确认预约}} /button事件绑定里直接写方法名bindtapsubmitOrder不要写成bindtapsubmitOrder()后者在自定义组件里会失效这是小程序开发里常见的玄学报错之一。数据绑定里做过一次减法计算真实的项目建议把remainCount在 JS 里算好再塞进 dataWXML 只负责展示排查问题时少一层逻辑。支付环节如果要做就在 submitOrder 成功后调 wx.requestPayment 发起微信支付后端返回支付参数课设一般用模拟支付代替把订单状态直接置为已支付论文里注明生产环境需要对接微信支付商户平台。到这里小程序端闭环了授权登录拿 token、科室列表加载、医生排班展示、预约提交。整套代码量不大但每一步都依赖后端接口约定下面一章把后端接口和管理端逻辑补上。4. 后端接口与管理端排班、余号扣减与退号黑名单4.1 接口选型Spring Boot 还是 Node.js后端技术栈在标题里没写死但“源码”通常指后端完整工程。我见过最多的是 Spring Boot MyBatis-Plus也有用 Node.js Express 的。如果你已经会 Spring Boot直接用答辩时“事务管理”是个加分点如果想整个项目全栈都用 JavaScriptNode.js 写起来快但并发那块容易被追问底层实现。这里我按 Java Spring Boot 风格写因为 Transactional 声明式事务和 MySQL 的配合最成熟讲并发控制时更有底气。接口清单建议固定一套约定前后端联调按这个走POST /api/auth/login code 换 token GET /api/department/list 科室列表 GET /api/doctor/list 按科室查医生 GET /api/schedule/list 按医生查号源 POST /api/appointment/create 提交预约 POST /api/appointment/cancel 退号 GET /api/appointment/mine 我的预约后端工程里我会单独抽一层 Service 处理业务Controller 只做参数接收和结果包装。这样做的好处是事务边界清晰排班、预约、退号这些核心方法都能用注解控制事务粒度。4.2 预约接口事务与乐观锁防止号源被抢超号源超卖是预约系统最经典的并发问题。两个用户同时看到余号 1同时提交如果代码是先查 booked_count判断小于 total_count再更新两个请求都能通过检查最后超卖。解决这个要用数据库行锁或乐观锁先看行锁版本/** * 预约接口 - 行锁版本 * 数据库事务里执行锁住当前号源行防止并发修改余号 */ Override Transactional(rollbackFor Exception.class) public Long createAppointment(Long userId, Long scheduleId) { // 1. 查询号源并加行锁SELECT ... FOR UPDATE Schedule schedule scheduleMapper.selectByIdForUpdate(scheduleId); if (schedule null) { throw new BusinessException(号源不存在); } if (schedule.getBookedCount() schedule.getTotalCount()) { throw new BusinessException(该时段号源已约满); } // 2. 创建预约订单 Appointment appointment new Appointment(); appointment.setOrderNo(generateOrderNo()); appointment.setUserId(userId); appointment.setScheduleId(scheduleId); appointment.setDoctorId(schedule.getDoctorId()); appointment.setAppointDate(schedule.getWorkDate()); appointment.setStatus(0); appointmentMapper.insert(appointment); // 3. 扣减余号 scheduleMapper.increaseBookedCount(scheduleId); return appointment.getId(); }selectByIdForUpdate 对应 SQL 是SELECT * FROM schedule WHERE id ? FOR UPDATE锁住这行直到事务提交。第二个请求进来在这行等锁前一个事务提交后再读读到的是更新后的 booked_count超卖从根上堵住。注意 selectByIdForUpdate 这个查询必须在事务里执行否则行锁会立刻释放等于白写。行锁的代价是高并发下排队性能有上限。乐观锁是另一个方案SQL 长这样UPDATE schedule SET booked_count booked_count 1, version version 1 WHERE id #{scheduleId} AND booked_count total_count AND version #{oldVersion}Java 里先读一次 schedule 拿到旧 version再执行乐观锁更新影响行数为 0 说明有人抢先了回滚订单并提示用户。乐观锁适合读多写少的场景但医院号源是稀缺资源写冲突不低所以行锁更好讲、更直观。答辩时两个方案的区别是高频考点至少能说清楚行锁锁行、乐观锁靠条件更新。4.3 退号接口与黑名单管理把爽约变成可运营数据退号不能做成 DELETE 一条预约记录正确做法是改状态。订单表关联号源、支付记录和后续就诊记录物理删除会让统计无从谈起。退号接口做三件事校验订单归属、改状态、释放号源。Override Transactional(rollbackFor Exception.class) public void cancelAppointment(Long userId, Long appointmentId) { Appointment appointment appointmentMapper.selectById(appointmentId); // 1. 校验归属权和状态 if (appointment null || !appointment.getUserId().equals(userId)) { throw new BusinessException(订单不存在); } if (appointment.getStatus() 2 || appointment.getStatus() 4) { throw new BusinessException(已完成或爽约订单不能退号); } // 2. 状态改为已取消 appointment.setStatus(3); appointment.setCancelTime(new Date()); appointmentMapper.updateById(appointment); // 3. 释放号源 scheduleMapper.decreaseBookedCount(appointment.getScheduleId()); }黑名单逻辑放在预约创建前用户退号次数达到阈值比如一周内退号超过 3 次后端在创建预约前查 blacklist 表命中就拦截。黑名单存 expire_time到期自动失效查询条件写expire_time NOW()。这个模块很小但能撑起论文“业务创新点”部分比单纯增删改查有说服力得多。排班展开逻辑也放在后端管理员选一个医生和日期范围系统遍历每一天判断星期几是否匹配医生 week_schedule 里的配置匹配则生成一条 schedule 记录total_count 默认 30。周几判断用 Java 标准库LocalDate.getDayOfWeek().getValue()返回 1 到 7 对应周一到周日如果手写 getDay 或者用字符串截取极容易踩到 0 优先还是 1 优先的坑这条放在第 5 章当典型踩坑记录展开。5. 避坑记录医院预约挂号系统最容易翻车的 5 个环节5.1 同一用户重复预约同一号源现象用户反复点“确认预约”生成了多条预约记录号源余量被扣了 3 次。原因前端做了按钮防重复但绕过前端直接调接口或者后端接口没做“是否已预约过”的校验。解决在 appointment 表的 user_id schedule_id 加唯一索引插入前查询当前用户是否已有未取消订单。状态为 3 的已取消记录允许重新预约所以唯一索引约束不了“非取消状态”。我的做法是业务层先查有效订单再插入数据库层再加 user_id schedule_id status 普通索引兜底让重复数据在慢查询日志里更容易暴露。5.2 并发下号源超卖现象压测 100 个并发请求预约最后 1 个号成功 20 个后台 booked_count 超过 total_count。原因接口先 SELECT 判断余号再 UPDATE 扣减两次操作之间有间隙并发请求都通过了判断。解决用 4.2 的SELECT ... FOR UPDATE行锁或乐观锁。行锁后 100 个并发请求最终只有 1 个成功其余返回“号源约满”。这个坑值得写进论文测试章节并发前后各查一次 booked_count截图对比答辩直接加分。5.3 登录态过期与 code 重复使用现象小程序第一次打开正常隔天再打开接口全部 401或者连续操作时偶发登录失败。原因wx.login 的 code 只能用一次有效期只有 5 分钟。有些项目把 code 缓存在本地反复传后端用同一个 code 调 code2session第二次直接报错。解决登录流程只在小程序启动或 token 过期时执行一次。后端登录接口用 code 换到 openid 后生成自定义 tokenUUID 或 JWT并设置过期时间小程序端像 3.2 那样存 token 和 token_expire。token 过期时间建议 2 小时配 token_expire 在失效前主动跳登录用户体验最顺。5.4 排班展开时的星期与日期错位现象管理员设置“周一、周三出诊”生成的号源里周二也在放号或者周一反而没有号。原因week_schedule 存的是 0-6 还是 1-7 没约定。后端 JavagetDayOfWeek().getValue()返回 1-7前端 JSnew Date().getDay()返回 0-6两端直接拼字符串比较必然错位。解决统一约定 1-7 对应周一至周日后端负责生成号源前端只看展示。前端真需要判断星期用getDay()后加 1 再比较。这条写在接口文档第一行能省掉大量无意义调试。5.5 Navicat 导入 SQL 脚本报错与数据库连接池超时现象把项目里的 .sql 文件导入新环境报错一堆或者系统跑一会儿后接口变慢报连接池获取连接超时。原因导入报错常见是脚本有外键且表顺序不对、字段用了关键字、字符集没指定。连接池超时常见是 MySQL wait_timeout 默认 8 小时连接空闲后被服务端断开连接池还拿着旧连接。解决SQL 脚本按第 2 章写法不建外键、表名和字段名避开 order、group 等关键字、文件头显式写DEFAULT CHARSETutf8mb4。连接池配置把 max-lifetime 设为 60 秒小于 MySQL 的 wait_timeout同时开启 connection-test-query 保活检测代码里不要自己 new Connection全部走连接池。提示连接池超时报错信息通常是Connection is not available, request timed out after 30000ms。先查连接池配置再查 MySQL wait_timeout这个排查顺序别反过来最常见原因是 max-lifetime 大于 wait_timeout连接在池里已经死了。6. 论文、答辩与验证把源码和数据库变成能讲清楚的项目6.1 论文结构怎么排拿到源码和数据库后论文顺序我建议需求分析背景加用例图、系统设计架构图加 ER 图、数据库设计表结构加字段说明、系统实现核心功能截图加关键代码、系统测试功能测试用例表加并发测试截图。ER 图可以从 Navicat 模型功能直接导出但论文里一定要把 appointment 和 schedule 的关系线画清楚这张图是答辩老师第一眼会看的图。6.2 答辩必问的三个问题并发与超卖怎么解决把 FOR UPDATE 和乐观锁的思路讲透。状态流转向量把 0 待支付到 4 爽约的状态流转背出来重点解释为什么退号是改状态而不是删记录。权限与安全区分用户端和管理员端用户端用 token 鉴权管理员账号单独做权限校验不能只靠前端隐藏入口。6.3 用 Postman 和压测数据给系统验证答辩前我一定做的一件事用 Postman 跑通完整流程登录、科室、医生、号源、预约、退号。然后把并发预约的截图放进测试章节Postman runner 配置 50 个并发请求打到同一个号源最终只有约定数量的请求成功旁边标注“剩余号源为 0无超卖”。这张截图的说明力大于一整章文字。这套源码和数据库交付的不是几份文件而是一个你能完整讲清楚的系统。我自己的习惯是答辩前一周不看代码在纸上把订单状态流转和各表关联画一遍再自己写一遍。画得出来答得出来项目就是你的。希望帮到你。本文还有配套的精品资源点击获取
返回列表