ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于Python+Vue的医疗预约系统开发实战:Django与Flask双版本并发处理与权限设计

基于Python+Vue的医疗预约系统开发实战:Django与Flask双版本并发处理与权限设计 带了三届毕业设计医疗预约系统是被问得最多的一种选题。倒不是因为哪所学校指定这个题目而是它太典型了用户角色天然分成患者、医生、管理员三层业务流程覆盖注册、挂号、排班、取消、就诊记录数据模型也不复杂但真要设计好号源、处理好并发预约又确实能看出一个人对后端基本功的掌握程度。更关键的是Python后端加Vue前端的组合恰好是现在简历上最常出现的两行技术栈。前几天帮一个学弟从零搭了一套在线医疗预约系统从PyCharm建虚拟环境开始到后端分别用Django REST Framework和Flask写了两版再到Vue页面联调、接口并发压测整套走下来踩了不少坑。这篇文章把全过程完整复盘一遍重点放在数据模型设计、预约冲突处理、角色权限、前端预约链路以及PyCharm联调技巧上适合正在做毕业设计、实训作业或者想拿这个项目练手找工作的朋友。后端是选Django还是Flask我会给出建议两版的核心代码也都会贴出来。1. 为什么Python Vue组合会成为医疗预约选题的事实标准1.1 这类系统的需求特征决定了技术选型的方向医疗预约系统不是电商秒杀系统它不会遇到几十万QPS但必须把业务逻辑做严谨。一个完整的需求清单大概是患者能注册登录、按科室找医生、查看医生排班、提交预约、取消预约、查看历史记录医生能维护自己的排班、查看预约名单管理员要管理科室、医生信息还要能补录诊断结果。所有操作加在一起本质上就是一个多角色CRUD 一组有状态约束的业务流程。这样的需求特征给技术选型划了几条硬杠杠。第一开发效率要高单人完成整个项目学生毕设场景尤其如此框架必须能快速把CRUD铺开第二权限模型要清晰因为涉及医疗数据的隐私边界医生只能看自己的号源这类规则必须好落地第三要有能力处理一个关键并发场景——多个患者同时预约同一时段时不能出现超卖。这三点分别对应框架全栈性、权限中间件、事务控制能力Python生态里的Django和Flask都能满足只是实现路径不同。1.2 Django vs Flask不是版本之争是工期之争很多人纠结Django和Flask选哪个其实只要把它们当成两种不同哲学的选择题就清楚了。Django是全家桶ORM、Admin后台、Auth、Session、表单校验、迁移工具全都给你内置好了再配上Django REST Framework出接口速度极快。尤其那个Admin后台几乎是白送的管理端毕设里管理员功能这一大块直接就有了这是我推荐Django的最重要理由。Flask是微框架只带路由和模板ORM要用SQLAlchemy、认证要接Flask-JWT-Extended、数据库迁移要配Alembic每一个组件都要你自己拼。听起来麻烦但换来的是完全透明所有代码都是你写的出问题好排查面试时也能把每个环节讲清楚。对想锻炼自己、或者项目规模不大但想展示底层理解的人Flask是很舒服的选择。对比维度Django DRFFlask SQLAlchemy后台管理Admin直接生成需自己写管理页面开发效率高内置多中需要手动组合技术要求理解框架约定掌握各组件拼装排错难度封装多报错层数多透明易定位适合场景毕设、快速交付面试展示、深入学习文档成熟度官方文档很全组件文档分散1.3 我个人对这个项目的选型建议如果时间紧、目标是论文答辩顺利通过优先Django。别小看Admin后台这一个优势它直接帮你覆盖了管理员维护医生信息这类页面论文里还能多写一章系统后台管理基于Django Admin的实现。如果时间充裕、想在简历和面试里多聊几句可以选Flask因为你能把每个细节讲得头头是道比如蓝图怎么拆、JWT怎么校验、SQLAlchemy会话怎么管理。这次帮学弟的项目主体用Django实现同时把预约、排班这两个核心接口用Flask重写了一份做对照。这样论文里可以写两套实现对比面试时也可以说我熟悉主流的两种Python Web框架属于性价比最高的做法。2. 数据模型先行把医生、号源、预约和用户角色一次理清2.1 六张核心表定下系统边界数据模型是这类系统的地基。我见过很多半途而废的项目都是因为后面发现表设计不对改来改去把代码改乱了。这个系统我建议从六张表起步不要一上来就堆字段。第一张是用户表存账号、密码、真实姓名、手机号和角色角色用patient、doctor、admin区分。第二张是患者扩展表一个用户对应一条存身份证号、出生日期、性别、既往病史。第三张是医生扩展表关联用户和科室存职称、擅长领域、个人简介。第四张是科室表就三个字段名称、位置、简介。第五张是排班表。第六张是预约单表。Django项目里用python manage.py startapp accounts和python manage.py startapp hospital创建两个应用前者放用户表和两个扩展表后者放科室、医生、排班、预约。注意配置AUTH_USER_MODEL时必须在第一次迁移前完成否则后面改起来很痛# accounts/models.py from django.contrib.auth.models import AbstractUser from django.db import models class User(AbstractUser): ROLE_CHOICES ( (patient, 患者), (doctor, 医生), (admin, 管理员), ) role models.CharField(max_length10, choicesROLE_CHOICES, defaultpatient) phone models.CharField(max_length20, blankTrue) class Meta: db_table user2.2 号源表把库存做成一眼能看懂的状态排班表是整个预约系统的核心说它是号源库存一点也不夸张。它记录了某个医生在某天某个时段放出了多少号已经约出去多少号。字段设计上work_date用来隔离具体日期period用am和pm区分上午下午start_time和end_time标记可预约时间段total_slots是该时段的总号源数booked_slots是已预约数剩余的号源就是total_slots减booked_slots。Django模型里我还加了一个unique约束保证同一个医生同一天同一个半天的排班只有一条记录这是防止重复排班的第一道防线# hospital/models.py class Schedule(models.Model): doctor models.ForeignKey(DoctorProfile, on_deletemodels.CASCADE, related_nameschedules) work_date models.DateField(verbose_name出诊日期) period models.CharField(max_length2, choices((am, 上午), (pm, 下午))) start_time models.TimeField() end_time models.TimeField() total_slots models.PositiveIntegerField(default30) booked_slots models.PositiveIntegerField(default0) class Meta: db_table schedule unique_together (doctor, work_date, period) indexes [models.Index(fields[doctor, work_date])]Flask那一版用SQLAlchemy写模型逻辑基本一样只要把db.Column字段类型对应上即可。这里有个设计取舍要说明为什么不用每个时间段单独一条记录的方式比如08:00-08:30一条、08:30-09:00一条。那样做更直观患者可以精确选到某一个30分钟时段但排班数据量会大不少而且预约冲突判断需要额外加时段重叠检查。对于常规门诊预约半天一个号源池的做法更接近真实医院挂号流程也方便后期写剩余号源的轮播展示和报表统计。如果论文里想多一个亮点也可以把号源池拆成更细的时间片但代价是前端时段选择器和后端约束校验都会复杂一档。2.3 一个患者同一时段不能预约两次预约单表是用户和排班的关联表核心字段是患者、排班、就诊序号、状态、创建时间。有一个约束最容易忽略同一个患者在同一时段只能有一条有效预约。Django里直接加unique约束双保险class Appointment(models.Model): STATUS_CHOICES ( (pending, 待就诊), (completed, 已就诊), (cancelled, 已取消), ) patient models.ForeignKey(PatientProfile, on_deletemodels.CASCADE, related_nameappointments) schedule models.ForeignKey(Schedule, on_deletemodels.CASCADE, related_nameappointments) appointment_no models.PositiveIntegerField(default1) status models.CharField(max_length10, choicesSTATUS_CHOICES, defaultpending) created_at models.DateTimeField(auto_now_addTrue) class Meta: db_table appointment unique_together (patient, schedule)为什么unique_together能起作用因为数据库唯一索引是在写入时强校验的不管应用层代码怎么漏只要两条记录的patient和schedule相同数据库就会直接拒绝。这种数据库层兜底应用层业务判断的写法是生产级系统常用的双保险思路。2.4 状态机预约单从生成到完成只允许这几条路径预约单的状态不能随便跳。一张单从创建开始只能走几条固定路径pending待就诊可以变为completed已就诊或cancelled已取消completed和cancelled都是终态不能再变。医生端如果允许确认接诊可以在中间加一个confirmed状态但不要加太多状态越多前端拉数据和后端校验的代码越碎。权限边界也和状态绑定患者只能取消自己处于pending的预约医生只能把排班范围内的预约标记为completed管理员最好只做数据修正和统计不做状态流转的日常操作。这个约束在后端代码里用角色状态联合判断前端只是隐藏按钮做体验辅助不能作为安全手段。3. 后端实现Django/DRF 与 Flask/JWT 双版本并行3.1 Django侧最省心的CRUD链路Model-Serializer-ViewSetDjango REST Framework把大部分CRUD逻辑封装好了我只写数据怎么过滤、怎么序列化剩下的list、retrieve、create都由ViewSet生成。先在settings.py里把rest_framework和simplejwt接上然后立刻建应用、写Model、写Serializer、写ViewSet、配路由这是一条成熟的固定链路# hospital/serializers.py from rest_framework import serializers from .models import Schedule class ScheduleSerializer(serializers.ModelSerializer): doctor_name serializers.CharField(sourcedoctor.user.real_name, read_onlyTrue) department_name serializers.CharField(sourcedoctor.department.name, read_onlyTrue) remaining serializers.SerializerMethodField() class Meta: model Schedule fields (id, doctor, doctor_name, department_name, work_date, period, start_time, end_time, total_slots, booked_slots, remaining) def get_remaining(self, obj): return obj.total_slots - obj.booked_slots# hospital/views.py from rest_framework import viewsets from rest_framework.permissions import IsAuthenticated from datetime import date from .models import Schedule from .serializers import ScheduleSerializer class ScheduleViewSet(viewsets.ReadOnlyModelViewSet): serializer_class ScheduleSerializer permission_classes [IsAuthenticated] def get_queryset(self): queryset Schedule.objects.select_related(doctor__user, doctor__department).all() department_id self.request.query_params.get(department_id) doctor_id self.request.query_params.get(doctor_id) if department_id: queryset queryset.filter(doctor__department_iddepartment_id) if doctor_id: queryset queryset.filter(doctor_iddoctor_id) return queryset.filter(work_date__gtedate.today())这里要注意select_related作用是一次性把关联的医生和科室查出来避免连续N次数据库查询。测试数据量小的时候感受不到差异但到了答辩演示的时候接口响应速度快慢表现会差很多。3.2 Flask侧的蓝图与JWT实现少一点封装多一点掌控Flask版我拆了四个蓝图auth、department、schedule、appointment。应用初始化用一个工厂函数create_app把扩展和蓝图统一注册进去这样测试和部署都方便。认证直接上Flask-JWT-Extendedaccess_token默认一个小时过期前端存在localStorage里每次请求带上Authorization头。# app/__init__.py from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_jwt_extended import JWTManager db SQLAlchemy() jwt JWTManager() def create_app(): app Flask(__name__) app.config.from_object(config.Config) db.init_app(app) jwt.init_app(app) from .routes import auth, department, schedule, appointment app.register_blueprint(auth.bp) app.register_blueprint(department.bp) app.register_blueprint(schedule.bp) app.register_blueprint(appointment.bp) return app一个排班列表接口在Flask里是这样写的很直白# app/routes/schedule.py from flask import Blueprint, jsonify, request from flask_jwt_extended import jwt_required from datetime import date from app.models import Schedule bp Blueprint(schedule, __name__, url_prefix/api/schedules) bp.route(, methods[GET]) jwt_required() def list_schedules(): query Schedule.query doctor_id request.args.get(doctor_id) if doctor_id: query query.filter(Schedule.doctor_id doctor_id) schedules query.filter(Schedule.work_date date.today()).all() return jsonify([{ id: s.id, doctor_id: s.doctor_id, work_date: s.work_date.isoformat(), period: s.period, start_time: s.start_time.strftime(%H:%M), end_time: s.end_time.strftime(%H:%M), total_slots: s.total_slots, booked_slots: s.booked_slots, } for s in schedules])Flask版本最大的优势就是调试直观。出问题的时候从路由函数开始每一步做了什么都在你眼前不会有Django那一层中间件帮你做了一堆你没写的事的黑盒感。3.3 预约扣减库存的并发安全写法预约接口是整个系统里最需要动脑子的地方。如果写成先查询还有没有号有就插入预约单再更新已预约数在并发场景下必出问题。假设号源池剩余1个两个患者同时发起请求两个进程都读到booked_slots29都判断还有号然后都插入预约单最后booked_slots被更新成31数据库里出现了第30、31条预约。这就是典型的超卖。解决办法是在事务里给排班记录加行锁。Django用select_for_updatefrom django.db import transaction from django.core.exceptions import ValidationError transaction.atomic def create_appointment(user, schedule_id): schedule Schedule.objects.select_for_update().get(pkschedule_id) if schedule.booked_slots schedule.total_slots: raise ValidationError(该时段号源已约满) schedule.booked_slots 1 schedule.save() return Appointment.objects.create( patientuser.patient_profile, scheduleschedule, appointment_noschedule.booked_slots )select_for_update的意思是在数据库层面把这一行锁住直到事务提交才释放。第二个请求进来后会等第一个请求提交然后重新读这时候booked_slots已经变成30了就会走到号源已约满的分支。这段逻辑一定要放在transaction.atomic里否则锁不会按预期生效。Flask加SQLAlchemy的写法更直接用一条UPDATE语句做原子扣减靠rowcount判断是否成功from sqlalchemy import update from app import db from app.models import Schedule def book_slot(schedule_id, patient_profile): result db.session.execute( update(Schedule) .where(Schedule.id schedule_id) .where(Schedule.booked_slots Schedule.total_slots) .values(booked_slotsSchedule.booked_slots 1) ) if result.rowcount 0: return None, 号源已约满 schedule db.session.get(Schedule, schedule_id) appointment_no schedule.booked_slots db.session.commit() return appointment_no, None这种条件更新的写法比先查后写更稳因为UPDATE语句本身在数据库引擎层面是原子的where条件不满足就直接影响0行不会出现并发插入。两种写法都是标准解法选一种吃透就够了。3.4 三类角色的权限边界怎么落到代码权限是这类医疗系统的第二道生命线。Django里自定义一个角色校验的权限类from rest_framework.permissions import BasePermission class IsDoctor(BasePermission): def has_permission(self, request, view): return request.user.is_authenticated and request.user.role doctor然后在ViewSet里把permission_classes设成对应组合。Flask版可以用一个装饰器在JWT里读出角色然后判断from functools import wraps from flask_jwt_extended import get_jwt, jwt_required def role_required(*roles): def wrapper(fn): wraps(fn) jwt_required() def decorator(*args, **kwargs): if get_jwt().get(role) not in roles: return {msg: 无权限访问}, 403 return fn(*args, **kwargs) return decorator return wrapper患者、医生、管理员三种角色的接口边界我的经验是宁可多分几个视图也别写一个大接口做全部分支判断。比如我的预约写一个PatientAppointmentView医生的工作台写一个DoctorScheduleView代码清晰权限也好配后面改需求不至于牵一发而动全身。4. Vue前端围绕选医生、选时间、看结果构建核心页面4.1 从路由到数据流的前端骨架前端用Vue 3加ViteUI库选Element Plus。如果环境里Node和npm还没装好先装Node 18以上的LTS版本然后npm create vuelatest就能得到一个带Vite的干净模板。路由结构我按预约主流程来设计/首页科室列表/doctors/:departmentId科室下的医生列表/schedule/:doctorId医生排班与号源选择/book/:scheduleId确认预约信息/appointments我的预约记录/login和/register/doctor/workbench医生工作台前端需要全局处理token。Axios实例里加请求拦截器每次请求自动带上Authorization头响应拦截器里遇到401就跳回登录页。这里有个容易踩的坑Vue的localStorage存token是明文XSS攻击下会被偷走毕设层面够用但论文里写了安全性就要注意这点至少要用HttpOnly的Cookie方案或者把token有效期缩短加刷新机制。4.2 时段选择器的组件级拆解预约流程里最核心的组件是时段选择器。它接受医生排班列表把今天和未来的日期分组展示选一个时段后高亮。Element Plus自带的日历组件样式和交互比较固定不如自己用flex布局排一个卡片列表来得直观。我一般把排班按日期分组每组里上午、下午各一张卡片卡片上显示时间段、号源剩余量号源为0的置灰不可点。template div v-foritem in groupedSchedules :keyitem.date classschedule-day h4{{ item.date }}/h4 div classslot-grid div v-fors in item.schedules :keys.id classslot-card :class{ disabled: s.remaining 0, active: selectedId s.id } clickhandleSelect(s) strong{{ s.period am ? 上午 : 下午 }}/strong span{{ s.start_time }} - {{ s.end_time }}/span span剩余 {{ s.remaining }}/span /div /div /div /template script setup import { ref } from vue const props defineProps({ schedules: { type: Array, required: true } }) const emit defineEmits([select]) const selectedId ref(null) function handleSelect(s) { if (s.remaining 0) return selectedId.value s.id emit(select, s) } /script4.3 预约提交流程里的反手逻辑前端提交预约时要注意处理三类后端返回结果200表示成功4xx表示业务错误比如号源已约满你已预约过该时段401表示token过期。很多初学者只在axios的then里写成功逻辑错误全甩给catch这样用户看到的是一堆看不懂的报错。我更建议在响应拦截器里统一把error.response.data里的message字段提出来在页面里用ElMessage显示同时按钮进入loading态防止用户重复点击。预约成功之后不要直接跳首页而是要跳到我的预约页面让用户立刻看到刚生成的那条记录这是一个很小的产品细节但对答辩演示的整体观感提升很明显。我还会在确认预约页展示一个红字提示请勿重复预约医生看诊前需提前15分钟到科室候诊这类文案也算系统功能的一部分。4.4 医生端排班管理的一个快速实现医生端不用做得很重一个工作台页面就够顶部显示当前医生的排班列表中间是号源卡点某一天某个时段可以看到已预约的患者名单。排班的新增和修改我用一个对话框搞定日期选择器选日期时间段下拉号源总数填数字提交后调排班接口。这里有一个Vue列表刷新的细节排班接口返回的日期是后端序列化后的字符串2026-03-10直接和前端Date()比较会出问题因为Date()会创建带时区的对象。建议前端全程用字符串比较或者用dayjs统一解析。这个问题在联调阶段特别容易踩前端显示出来的日期总是差一天排查半天发现是时区转换的锅后文我会专门讲。5. PyCharm环境搭建与前后端联调的实操记录5.1 虚拟环境和依赖一切坑的根源PyCharm里建项目时第一个动作就是指定虚拟环境。如果本机连Python都没装去官网下载3.10或者3.11的安装包注意勾选Add Python to PATH然后命令行里python --version能看到版本号就说明装好了。接下来千万不要图省事用全局的Python解释器不然三个月后你更新了某个包项目和论文全崩了都不知道原因。在PyCharm设置里Settings - Project - Python InterpreterAdd Interpreter - Virtualenv Environment新建一个venv目录就行。后端依赖务必写进requirements.txtdjango4.2.11 djangorestframework3.15.1 django-cors-headers4.3.1 djangorestframework-simplejwt5.3.1 pymysql1.1.0Flask版本对应是flask3.0.3 flask-sqlalchemy3.1.1 flask-jwt-extended4.6.0 pymysql1.1.0安装命令统一用pip install -r requirements.txt不要一个一个敲容易漏。5.2 PyCharm运行配置后端两个框架与前端分开跑Django项目在PyCharm里的运行配置选Django ServerScript填manage.py的绝对路径Parameters填runserver 0.0.0.0:8000Environment里把PYTHONUNBUFFERED设成1。Flask项目选PythonScript填入口文件app.py再在环境变量里加FLASK_APPapp.pyFlask自带的debug模式就能用了。前端项目不用在PyCharm里建配置直接用底部的Terminal面板敲npm run devVite默认跑在5173端口。记得同时把PyCharm的Settings - Tools - Terminal改成cmd或系统的bash不要用PowerShell在某些环境下的奇怪编码问题。5.3 Vite代理和CORS联调第一关前后端联调最大的坎是跨域。开发阶段最简单的方式是让Vite做代理前端请求的url用相对路径/api开头Vite dev server把它转发到后端的8000端口。在vite.config.js里加export default defineConfig({ server: { port: 5173, proxy: { /api: { target: http://127.0.0.1:8000, changeOrigin: true } } } })这样前端代码里请求写/api/schedules/就相当于请求http://127.0.0.1:8000/api/schedules/浏览器看到的始终是同源的5173不会触发CORS。等部署到线上再把Vue打包成静态文件用Nginx同时代理前端和后端/api路径也就能规避跨域问题。如果非要在开发环境直接访问后端接口那就得装django-cors-headers或者Flask-CORS在配置里把allow_origins设成前端地址。5.4 排查接口问题的三层定位法联调阶段接口报错是日常我的排查习惯分三层。第一层先打开浏览器开发者工具的Network面板看请求有没有发出、HTTP状态码是多少、响应正文是什么。这一步能过滤掉80%的问题比如404多半是路径写错了500多半是后端代码报错跨域报错则是浏览器控制台的红色CORS提示。第二层看后端控制台的日志Django会把每个请求的行号和方法都打出来Flask同样会打印Python Traceback从堆栈里能直接定位到哪一行代码炸了。第三层才是打断点调试。PyCharm的断点、变量预览窗口很好用在Django视图函数里打一个断点前端点到预约按钮请求就会停在后端代码里可以一步步看数据是怎么被处理的。我第一次带新手朋友做这个项目的时候他就是卡在前端点击没反应结果查到最后是后端settings里忘记加app了Django起动时就报错根本没跑起来。这类低级错误在控制台日志里一眼就能看到所以不要一上来就怀疑跨域先老老实实看请求是否到达了后端。6. 事务竞争、时区问题与部署前必做的检查项6.1 并发预约超卖问题的底线解法前文提过并发预约的行锁和条件更新两种写法这里再补充一个最底层的兜底方案数据库唯一约束。如果业务上能接受一个患者对同一排班最多一条预约那就在appointment表上加UniqueConstraint(patient, schedule)这样就算应用层代码写得有漏洞数据库也会拒绝重复插入。三防线齐下系统才敢说自己的预约逻辑是稳的。毕设答辩或项目汇报时这一块是必考技术点。面试官常会追问select_for_update锁的是表还是行答案是行锁。锁的粒度是数据库索引级别的所以排班表的id主键索引一定要在而且查询条件必须落到索引上否则会退化成表锁并发性能骤降。另一个追问是如果MySQL事务隔离级别是Read Committed和高版本默认的Repeatable Read行锁行为有什么区别。这一部分不用太深入但你要能说出锁住的行在事务提交前不可被其他事务修改这一层就已经过关了。6.2 日期与时区一个差一天的坑能毁掉整个排班这个坑我在好几个项目里都踩过。前端选择的日期是2026-03-10通过JSON传到后端Python里用datetime.strptime(2026-03-10, %Y-%m-%d)解析得到的是naive datetime没有时区信息。Django如果开启了USE_TZTrue数据库存的DateTimeField会自动加上UTC时区偏移导致你在代码里比较today和work_date时结果总是差8小时。这不是逻辑错了是系统把无时区的字符串当成了UTC时间。我的建议是和挂号日期相关的字段一律用DateField不要用DateTimeField。只有创建时间、更新时间这种时间点才用DateTimeField。前端传日期就用YYYY-MM-DD字符串后端解析后转成date对象存到DateField里全程不碰时区问题就消失了。Flask版本同理DateTime默认naive但你如果部署在docker容器里宿主机的时区不同也会让时间对不上所以排班相关字段用Date是最省心的。6.3 部署上线前的检查清单不管最后是部署到云服务器还是只在本地答辩演示提交前过一遍这个清单能避免当场翻车。第一Django把DEBUG改成False把SECRET_KEY改成环境变量ALLOWED_HOSTS填上服务器IP或域名。第二Vue打完包之后dist目录就是静态文件用Nginx托管同时把/api路径反向代理到Gunicorn或uWSGI监听的端口。第三MySQL的字符集用utf8mb4别用utf8否则患者填个生僻字就插入失败。第四给数据库做定时备份crontab凌晨跑一个mysqldump就够了。第五所有密码字段必须存哈希Django的make_password和Flask的generate_password_hash都现成可用。这里多说一句如果对Linux运维不熟纯新手又想在服务器上快速部署可以试试宝塔面板。它提供可视化的Nginx、MySQL、Python项目管理把Django项目传上去、绑定域名、开一个Python项目环境就能跑起来比自己手写systemd和Nginx配置省事很多。不过论文里如果不需要涉及部署本地跑通、录一段演示视频也完全够用。6.4 给扩展功能留的接口余量整个系统做稳定之后还有几个方向可以扩展。一是加Redis缓存排班查询接口数据变化不频繁可以把当天的排班缓存到Redis压力测试时性能提升明显。二是加消息通知预约成功或取消时通过邮件、短信或者微信公众号模板消息通知患者这个在答辩演示里特别加分因为能展示你考虑到了用户体验层面。三是加每周排班模板让医生设置固定的出诊习惯前端一次生成一周的排班省去手动一天天添加。这三个扩展方向里短信通知需要买第三方服务邮件可以用免费的smtp服务实现实现成本低、效果直观。如果论文篇幅不够加一个邮件通知预约成功就是很好的一章。我的经验是扩展功能不求多一两个位置做精比堆一堆半成品功能强很多。把这个项目的核心逻辑吃透之后再去套其他类似的预约场景比如疫苗预约、车辆年检预约、实验室设备借用基本就是换汤不换药数据库表结构微调预约冲突校验规则稍微改改前端换个主题色又是一套能打的项目。
返回列表