尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Flask+Vue构建医院康复预约系统:设计与实现
1. 项目概述与整体设计思路1.1 医院康复预约到底在解决什么问题康复科这个场景很有意思它跟普通门诊挂号有本质区别。普通挂号只需要科室、医生、时间三个信息康复预约则多出了项目归属和疗程连续性。一个脑卒中恢复期的患者可能一周要去三次理疗每次一小时且最好固定同一个治疗师否则康复方案容易断档。如果仍然用传统的人工排班电话预约会出现三个典型痛点工作日高峰时段治疗师被约满、迟到和临时取消导致时段空转、治疗师之间时间撞车无人查重。我在设计这个系统时把核心需求拆成了三类角色。患者端要能查看康复项目的介绍、看到某治疗师某天的可用时段、在线上完成预约并查看我的预约记录治疗师端要能设置本人可接诊的时段、确认或取消预约、查看当日排班管理员端则负责患者基础信息维护、治疗师与项目建档、全科预约数据看板。这套角色权限划分直接决定了后面的接口设计也决定了前端页面路由的区分策略所以第一步不是写代码而是把角色和状态边界画清楚。1.2 技术选型为什么是 Flask 和 Vue而不是其他方案这个项目当时有四种组合可选DjangoVue、FlaskVue、FastAPIReact、SpringBootVue。我最终选了 FlaskVue核心原因偏务实。Django 确实自带 Admin 和 ORM但对前后端分离场景来说Django 的复杂度有一半用不上而且模板和表单的理念会诱导新手继续写服务端渲染偏离了我想要的 API 优先架构。FastAPI 的异步性能和自动文档确实香但它对 SQLAlchemy 事务和 Flas 生态里很多现成插件的兼容方式和 Flask 不完全一样项目组其他人不熟。这里顺便对比一下 Flask 和 FastAPI也是群里被问得最多的Flask 的请求模型是同步阻塞但实际业务里预约系统属于低频事务型接口单机每秒几十个请求很够用FastAPI 的优势在 IO 密集和并发规模大的场景比如实时推送、流式接口这里有后面接入康复设备的 IoT 数据采集但初期根本没必要引入异步复杂度。FlaskSQLAlchemy 的搭配经过十年以上大规模项目检验出问题网上都有答案FastAPI 的 Pydantic 确实让参数校验更优雅但 Flask 配合 Marshmallow 同样能做最终选了 Flask核心因素就是团队熟练度、插件生态和可维护性。表格对比一下不同技术选型的适配场景方案上手难度适合场景不适合场景Flask Vue低中小型管理类系统、传统多点业务大规模高并发实时系统Django Vue中后台复杂、权限模型繁重的系统轻量 API 为主的项目FastAPI Vue中高高并发、流式接口、AI 推理服务强耦合 Django Admin 思维的项目SpringBoot Vue高企业级多系统集成、Java 团队小团队快速原型验证前端选 Vue 的理由也很简单生态中庸不激进中文资料非常全从 Vue2 过渡到 Vue3 组成都可以接受而且招聘市场上会 Vue 的工程师比会 React 的多以后接手的人压力小。组件库我用 Element Plus样式统一又省时间后面所有页面的表格、表单、弹窗不用自己写 CSS。1.3 整体架构与系统模块规划系统结构分三层。最底层是 MySQL 数据库存储患者、治疗师、项目、时段、预约五类核心数据外加管理员账号。中间层是 Flask 提供的 RESTful API统一返回 JSON 格式通过 JWT 做登录态校验通过装饰器做角色权限限制。最上层是 Vue 单页应用用 Vue Router 管理页面跳转用 Pinia 管理用户会话状态用 Axios 跟后端通信。前后端分离的关键约束是后端不关心页面长什么样前端不关心数据从哪个表来。接口返回什么字段前端就消费什么字段两边维持一个约定好的契约格式。这个项目里我定义了统一的响应结构——{code:200, msg:success, data:{...}}——所有接口都遵守前端拦截器统一处理code不要在页面里写一层层判断。模块规划上按业务拆成六大块用户认证模块、患者信息管理、康复项目管理、治疗师排班管理、预约记录管理、统计看板。每一个模块在后端都是独立的 Flask Blueprint前端对应独立的 Vue 页面目录这样的好处是开发后期可以多人并行一个人负责预约模块一个人负责排班模块互不覆盖。2. 核心业务逻辑与数据库设计2.1 数据模型的五张核心表数据库是整个系统的地基我在这里花的时间比写接口还多。康复预约系统的核心表有八张但主干链路是五张patient患者表、therapist治疗师表、rehab_item康复项目表、time_slot时段表、appointment预约记录表。另外还有admin管理员表、therapist_item关联表表示治疗师擅长哪些项目。患者表字段并不复杂id、name、phone、gender、age、medical_record_no病历号、created_at。注意要加唯一索引在phone或medical_record_no上预约系统的患者凭证就是电话号码或病历号后面查询记录全靠它。治疗师表除了基本字段外要有title职称、department科室、max_appointments_per_day每日最大预约量这个字段是后面时间冲突校验的一个兜底条件。康复项目表要存name、category分类、duration_minutes单次时长、price价格、description描述。时长很重要它不直接存在预约里而是让系统计算治疗师的时间被占用几格。时段表time_slot是提前用脚本生成的把每一天从 8:30 到 17:30 切成 30 分钟一格的时段slot_date、start_time、end_time、therapist_id、is_booked五个字段。时段表的优势是预约冲突检测从日期时间运算简化成了查记录这是这个项目最核心的一个设计决策。预约记录表appointment包含patient_id、therapist_id、rehab_item_id、slot_id、status、remark。status是字符串枚举取值有pending待确认、confirmed已确认、completed已完成、cancelled已取消、noshow爽约。为什么不直接用布尔字段因为预约的全生命周期管理需要一个状态机后面讲。2.2 预约时段与冲突检测的实现预约系统最怕撞车一个治疗师四点到五点的那格时段同时被两个患者约走这种数据事故一旦发生康复科现场就得争执打架。设计上我用两层防护。第一层是数据库唯一约束。在appointment表上建一个联合唯一索引字段是therapist_id slot_id status其中status限定为有效状态pending 和 confirmed。也就是说同一治疗师同一天同一时段只允许存在一条未取消的预约记录。这层防护是最终底线任何代码层面的逻辑 bug 都没办法绕过数据库约束。第二层是业务层的预校验。在插入预约之前先把待选时段通过SELECT ... FOR UPDATE锁定再检查is_booked如果已经预约就返回提示该时段已被预约。有人会问直接用唯一索引就够了为什么还要加业务锁实际原因是用户体验如果你等到插入时报唯一约束错误前端拿到的报错信息很难做到友好但如果你在查询阶段把已被占的时段直接置灰患者根本不会约到已经满的时段。前者是兜底后者是体验。时段表生成脚本的做法很简单循环日期范围加时间区间用 Python 的datetime和timedelta组合生成。要注意节假日不上班所以排班表里还要排除周六周日这个可以在生成时段时配置is_weekend参数也方便管理员后续按节假日手动调整。2.3 预约状态机的流转设计状态机是预订类系统里最容易做乱的地方。我见过很多系统把状态字段随便拼如把取消状态和设备状态搞成一锅粥。这次预约系统只用了五种状态但五状态之间的流转关系必须收敛清楚。初始化是pending患者提交预约后进入待确认。治疗师或管理员操作确认后进入confirmed这意味着时段的is_booked置为 true其他患者看到该时段已满。到达治疗当天治疗师点击完成状态转向completed同时如果未进行治疗则标记为noshow爽约。pending和confirmed状态都可以发起cancelled取消但completed和noshow是终态不能回退。状态机的实现可以写在Appointment模型里也可以写成独立的 service 层。我在这个项目里用的是 Flask-SQLAlchemy 的模型方法在Appointment类上定义cancel()、confirm()、complete()、noshow()四个方法每个方法内部先检查当前状态是否允许跳转不允许就抛异常允许则执行状态变更并同步更新时段表的is_booked字段。这样做的好处是状态逻辑收敛在一处不是散落在各个视图函数里未来加新状态只需要改这一个模型。3. Flask 后端开发接口从定义到落地3.1 项目初始化与依赖配置后端我用的是经典的 Flask 应用工厂模式项目结构如下rehab-backend/ ├── app/ │ ├── __init__.py # 应用工厂创建 app 实例 │ ├── models/ # SQLAlchemy 模型 │ │ ├── __init__.py │ │ ├── patient.py │ │ ├── therapist.py │ │ ├── rehab_item.py │ │ ├── time_slot.py │ │ └── appointment.py │ ├── blueprints/ # 蓝图路由 视图 │ │ ├── __init__.py │ │ ├── auth.py # 认证登录 │ │ ├── patient.py # 患者模块 │ │ ├── therapist.py # 治疗师模块 │ │ ├── appointment.py # 预约模块 │ │ ├── slot.py # 时段查询 │ │ └── dashboard.py # 看板统计 │ ├── utils/ # 工具函数 │ │ ├── response.py # 统一响应封装 │ │ ├── decorators.py # 角色权限装饰器 │ │ └── validators.py # 参数校验 │ ├── config.py # 配置文件 │ └── extensions.py # db, jwt, cors 等扩展实例 ├── migrations/ # Flask-Migrate 迁移目录 ├── requirements.txt └── run.py # 启动入口依赖文件requirements.txt里核心打包如下flask2.3.3 flask-sqlalchemy3.1.2 flask-cors4.0.0 flask-jwt-extended4.5.2 flask-migrate4.0.5 mysqlclient2.2.0 marshmallow3.20.1 gunicorn21.2.0这里有个版本坑要注意Flask 3 开始把before_first_request移除了网上很多老教程用这个钩子初始化数据照着抄会直接报错。我选 Flask 2.3 主要是为了稳定兼容后面不需要升级也能跑完整个项目等你熟练了再往 Flask 3 迁移不迟。另一个坑是mysqlclient在 Windows 上安装比较麻烦如果你用 Windows 开发建议配置pymysql作为替代驱动连接字符串写法不一样但功能完全等价。3.2 JWT 登录认证与角色权限控制登录模块是整个安全链路的入口。我用 flask-jwt-extended 生成 JWT Token用户登录成功后返回access_token和refresh_token。access_token生命周期设两小时refresh_token设七天前端在 Axios 响应拦截器里发现 401 时自动用刷新 Token 重新换取实现无感续期。Token 里除了存用户 id还要存role角色字段。这个项目有三种角色patient患者、therapist治疗师、admin管理员。为什么不在鉴权时每次查数据库拿角色因为每一次请求都多一次数据库查询性能就差在细微处尤其是预约列表这种高频接口。JWT 里的role字段是签发时写死的角色变更在有效期内的概率极低可以容忍少量延迟。权限控制使用自定义装饰器。flask-jwt-extended 提供了jwt_required()校验登录但角色校验要自己写我用一个简单版本实现from functools import wraps from flask import jsonify from flask_jwt_extended import verify_jwt_in_request, get_jwt def role_required(*roles): def wrapper(fn): wraps(fn) def decorator(*args, **kwargs): verify_jwt_in_request() claims get_jwt() if claims.get(role) not in roles: return jsonify({code: 403, msg: 权限不足}), 403 return fn(*args, **kwargs) return decorator return wrapper访问预约接口时在视图函数上方加上role_required(patient)即可。注意装饰器的顺序jwt_required()要在role_required下方否则get_jwt取不到 claims这个顺序我踩过好几次。3.3 CORS 跨域配置与全局异常处理前后端分离后跨域问题几乎必现。前端跑在 localhost:5173后端跑在 localhost:5000两者端口不同浏览器默认阻止跨域请求。最简单的处理是使用 flask-cors 扩展一行代码允许所有来源from flask_cors import CORS CORS(app, supports_credentialsTrue, resources{r/api/*: {origins: *}})实际开发中不要一味用通配符生产环境要限定前端域名否则潜在安全隐患有人写脚本带着你的 Token 去请求接口。更稳妥的写法是把origins配置为一个列表来自.env环境变量部署时修改即可。另外注意如果接口需要携带 Cookiesupports_credentialsTrue必须开启同时前端 Axios 也要设置withCredentials: true否则取不到 Cookie。全局异常处理是 Flask 项目里不可或缺的一环。默认情况下 Flask 的异常会返回 HTML 错误页前后端分离后前端根本解析不了。我写了一个统一的异常处理器from flask import jsonify app.errorhandler(Exception) def handle_exception(e): if isinstance(e, HTTPException): code e.code msg e.description else: code 500 msg 服务器内部错误 # 记录完整堆栈到日志 app.logger.error(fException: {e}, exc_infoTrue) return jsonify({code: code, msg: msg, data: None}), code这样做以后前端拦截器只需要判断response.data.code不等于 200 就在页面上弹出msg提示因此所有接口的错误提示格式统一排查问题的时候也能在后端日志里留痕。3.4 核心预约接口的实现细节预约接口是核心交互我拆成三个接口查可用时段、提交预约、取消预约。查询可用时段接口的返回格式是前端渲染日历的关键设计时字段必须完整。我给前端的 JSON 里包含slot_id、date、start_time、end_time、is_booked五个字段前端的日历组件根据is_booked把时段渲染成灰色或绿色。创建预约的接口实现里面业务逻辑按四个步骤走第一步校验患者 id 和治疗师 id 是否存在第二步校验该时段是否属于该治疗师且未被预约第三步校验预约日期是否在未来第四步插入预约记录并把时段is_booked改为 true。查询和插入之间我用数据库事务包裹配合SELECT ... FOR UPDATE防止并发问题这个细节后面单独讲。取消预约的实际写法如下用commit包裹两个数据变更bp.route(/appointments/int:appointment_id/cancel, methods[POST]) role_required(patient) def cancel_appointment(appointment_id): appointment Appointment.query.get(appointment_id) if not appointment: return resp(404, 预约不存在) try: appointment.cancel() # 方法内改变状态并释放时段 db.session.commit() return resp(200, 取消成功) except StateTransitionError as e: return resp(400, str(e))状态机的好处在这里体现视图函数不需要写一堆 if 判断当前状态是否允许取消模型方法内部统一处理。3.5 数据库迁移 Flask-Migrate 使用开发过程中表结构必然要改比如我一开始设计的time_slot表没有is_booked字段后来在预约状态流转时需要就通过 Flask-Migrate 平滑升级没有手动删表重建。先初始化迁移环境flask db init flask db migrate -m add is_booked to time_slot flask db upgrade不用 Flask-Migrate 的团队往往直接修改模型定义然后db.create_all()这样一旦有线上数据就会全部丢失。有了迁移机制以后每次改模型生成一个新的迁移版本线上执行flask db upgrade就能完成增量更新团队协作也不会出现你加了字段我没加的窘况。有一点必须在团队里统一迁移文件是受版本控制的不要直接改已经生成过的迁移脚本每一次表结构变更都通过新迁移来完成。否则一旦有人执行过旧迁移再拉取新脚本就会出现差异校验失败。4. Vue 前端开发从脚手架到页面交互4.1 环境搭建与项目初始化前端部分我用 Vite 搭建 Vue3 项目相比 Vue CLI 的热更新速度快很多。在搭建之前先确认 Node 环境node -v建议 18 以上npm -v6.9 以上。如果电脑还没装 Node去官网下载 LTS 版本即可记得勾选Add to PATH之后终端才能直接执行node命令。初始化命令是在后端项目同级目录下创建的npm create vitelatest rehab-frontend -- --template vue cd rehab-frontend npm install npm install axios vue-router pinia element-plus安装完成以后在main.js里注册 Element Plusimport { createApp } from vue import App from ./App.vue import ElementPlus from element-plus import element-plus/dist/index.css import router from ./router import { createPinia } from pinia const app createApp(App) app.use(ElementPlus) app.use(router) app.use(createPinia()) app.mount(#app)这里有个体验细节Element Plus 全量引入会让首屏包体变大但开发效率高。这个项目的用户都是医院内部和患者使用不需要追求极致的首屏加载速度全量引入换来的是不用按需配置取舍是合理的。如果是面向 C 端大流量场景就用unplugin-vue-components做按需引入。4.2 路由配置与动态路由守卫项目采用两种路由混合方式。固定路由是登录页、注册页、项目介绍页等对所有人生效的页面动态路由是登录后根据角色动态添加的页面。以患者角色为例登录成功后返回的 user 信息里有role字段前端根据角色把对应页面路由注册进 Vue Router。这样做的好处是患者不会看到管理端的菜单和路由直接在路由层面隔断了越权访问而不仅仅靠按钮隐藏来做界面安全。路由守卫设置如下router.beforeEach((to, from, next) { const userStore useUserStore() if (to.meta.public) { next() } else { if (!userStore.token) { next({ path: /login, query: { redirect: to.fullPath } }) } else if (to.meta.roles !to.meta.roles.includes(userStore.role)) { ElMessage.error(无权限访问该页面) next({ path: / }) } else { next() } } })动态路由的调试是新手最容易迷茫的环节明明在菜单里点击跳转没问题但刷新页面后路由突然失效。原因很简单Vue Router 的 addRoute 添加的路由是存在内存中的刷新后重新初始化就丢失了。解决方案是刷新后从后端重新拉取用户信息和权限再重新动态注册路由。我在 Pinia 的 user store 中做了一个fetchUserAndRoutes方法在应用初始化时调用确保刷新不掉线。4.3 状态管理与 Axios 封装前端的状态管理用 Pinia主要管理三块用户的 Token 和基本信息、当前选择的预约筛选条件、页面加载状态。Token 存储用 localStorage每次请求在 Axios 请求拦截器里自动附带同时如果 Token 不存在直接拦截并跳到登录页。Axios 封装是一个独立模块request.js里面做三件事import axios from axios import { ElMessage } from element-plus import { useUserStore } from ../stores/user import router from ../router const service axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 10000 }) service.interceptors.request.use(config { const userStore useUserStore() if (userStore.token) { config.headers[Authorization] Bearer ${userStore.token} } return config }) service.interceptors.response.use( response { const res response.data if (res.code ! 200) { ElMessage.error(res.msg || 请求失败) if (res.code 401) { userStore.logout() router.push(/login) } return Promise.reject(new Error(res.msg)) } return res }, error { ElMessage.error(error.response?.data?.msg || 网络异常) return Promise.reject(error) } ) export default service封装好以后每个页面组件不需要关心 Token 怎么带、错误怎么提示只要写业务代码调用request.get(/api/slots)即可。时间一长你就会发现Axios 封装质量决定了前端的开发效率因为业务代码里 70% 都是请求和回显。4.4 预约页面的组件实现预约页面是系统里交互复杂度最高的页面拆成三个子组件日期选择器、时段日历、预约表单弹窗。日期选择器用 Element Plus 的el-calendar组件默认显示整月日期点击某天时触发接口查询该天的时段数据。时段日历用表格渲染行为逻辑是已约满的时段渲染成 disabled 状态点击无效当前时间已过的时段标记为过期同样不可选可用时段高亮点击后弹出预约表单。这里有一个关键细节后端返回的时段是后端时区下的日期时间前端必须确认时区一致否则会出现日期偏移。我开发时统一用08:00时区前端不做本地时区转换直接用字符串比较避免 DST 类的麻烦。预约表单的字段包括患者姓名、联系电话、备注等患者端登录后自动填充如果是管理员代预约还需要手动选择患者。提交成功后再调一次时段列表接口刷新日历状态。整个链路不长但把用户操作逻辑串起来需要前后端接口定义得足够清晰。5. 前后端联调、部署与排错5.1 联调过程中最容易踩的坑联调阶段往往是整个项目最痛苦的阶段前后端各写各的一对接各种一一不符。我总结了三类高频问题。第一类是字段命名不一致后端习惯snake_case前端习惯camelCase比如后端返回user_id前端却用的是userId页面一直拿不到值。解决办法是在后端定义序列化输出时就统一改成前端想要的格式或者直接约定所有接口字段都用snake_case前端配合不转。无所谓哪种关键是白纸黑字写进接口文档别靠口头约定。第二类是时间格式的坑。后端用 Python 的datetime在 JSON 序列化时默认格式是2024-05-20T14:30:00前端如果用new Date(res.date)解析这个格式在现代浏览器能解析但在一些 App 内嵌 WebView 里就可能报 Invalid Date。稳妥做法是后端统一输出2024-05-20 14:30:00格式前端把它当字符串处理或手动转new Date(str.replace( , T))。第三类是接口 404 问题。Flask 路由默认的 404 是 HTML 响应前端 axios 响应拦截器里的错误提示可能拿到的是 HTML 字符串。如果后端没有做统一的异常处理前端就会弹出一堆乱码排查时第一直觉是跨域或地址写错但实际往往是路由拼写差异。5.2 生产环境部署方案本地跑通以后部署是另一个战场。前端用npm run build打包后会生成一个dist目录里面是纯静态文件。后端着用 Gunicorn 作为 WSGI 服务启动 Flask 应用。部署架构用 Nginx 做反向代理短板路径分开/指向前端静态目录/api转发到后端 Gunicorn 监听的本机端口。Nginx 配置核心部分server { listen 80; server_name your.domain.com; # 前端静态文件 root /var/www/rehab-frontend/dist; index index.html; # 后端 API 反向代理 location /api/ { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 前端路由 history 模式需要回退到 index.html location / { try_files $uri $uri/ /index.html; } }Gunicorn 启动命令如下gunicorn -w 4 -b 127.0.0.1:8000 run:app-w 4表示开四个 worker 进程对应四核 CPU 的典型配置。这里注意 Gunicorn 只适合部署在 Unix 系服务器上如果公司服务器是 Windows得用 waitress 替代两者启动命令格式基本一样。很多朋友问 Vue 打包后为什么打开是空白页面。这基本是静态资源路径问题要么是 Vite 配置里的base没设置为/要么是 Nginxlocation路径配错。解决方案是在vite.config.js中设置base: /同时确保 Nginx 的 root 路径指向dist/index.html所在目录本地部署前也可以用serve dist先做一个自测。5.3 常见问题速查表在实际开发里我记录了下面这份问题排查速查表很多问题不是一次就能定位到根因的需要按现象逐层排查常见现象可能原因排查步骤页面请求接口报 401Token 过期、未携带检查 localstorage 是否有 token检查请求头是否有 Authorization接口返回 403角色权限不足核对登录用户的 role检查装饰器 roles 配置预约时报时段冲突时段已被占、状态未变查 datetime 的时区查时段is_booked字段是否变更前端刷新路由 404Vue Router history 模式未配 fallbackNginxtry_files配置缺失中文乱码数据库字符集不是 utf8mb4建库时指定utf8mb4连接串加charsetutf8mb4CORS 跨域报错后端未加 CORS 配置检查flask-cors是否配置了目标域名Gunicorn 启动报端口占用端口被其他进程占用lsof -i :8000查进程kill 后重启第三行这种报错往往是业务逻辑 bug不要因为是偶发就跳过在数据层面查一下硬件表结构看到底有没有多条预约同时插进去。5.4 并发预约与数据一致性处理预约系统的并发问题集中体现在同一时刻多个患者抢同一个治疗师时段。如果不用任何手段处理两个请求同时读到时段未预约然后同时插入预约记录数据库里就会出现两条有效预约这个后果很严重。我在设计里用了三层对策。第一层是数据库唯一约束也就是前面讲过的联合唯一索引这是最底层的保险。第二层是事务内行级锁在 Flask 视图函数里手动开启事务执行查询时加上with_for_update()锁定时段行注意 SQLite 不支持行锁所以生产环境必须用 MySQL。第三层是前端层面的防重复提交提交预约按钮单击后立刻变成 loading禁用二次点击。三层叠加基本可以防住多数并发场景。这里分享一个调优点把with_for_update()尽量放在事务开始后的第一条语句锁定的时间越短越好锁住的行越少越好。比如你在读患者信息时不需要锁时段行那就在查询时段之前先查患者最后才锁时段避免长时间持有锁影响其他患者的预约。锁的范围要及时释放事务提交后锁自动解除。我在实际压测时模拟过同时 50 个请求抢同一个时段最终只有一条能预约成功其余全部返回该时段已被预约。这离不开数据库层的兜底单靠业务逻辑是有破绽的分布式环境尤其如此。写在最后整个系统从设计到上线前后搞了三周中间改过两版数据库结构踩过的坑基本都记录在前面几节里了。如果只能给出一条建议那就是项目开工前先花两天时间把数据模型和接口文档定清楚剩下的 CRUD 只是体力活。很多开发同学一上来就想着写接口、写页面最后往往在数据库字段对不上和状态逻辑混乱中反复返工磨掉的是整个团队的耐心。关于后续扩展这个项目还可以在三个方向迭代一是增加消息通知预约状态变化时通过公众号或短信触达患者否则患者可能不知道预约被确认二是引入治疗师工作量统计按项目、时段、治疗师维度输出康复科运营报表三是接入电子病历数据让治疗师在查看预约时能看到患者的康复进度。这三个方向都不需要动已有核心架构都是在现有接口上扩展这也印证了前期设计的重要性。最后再分享一个小技巧如果你也是从 Flask 后端起手学 Vue先别急着把所有组件都抽象成通用高阶组件等页面重复出现三次以上再抽象也不迟。前期多写一点重复代码反而能让你更快摸清每个组件的真实用法后面再重构效率高得多。
RELATED

相关推荐

基于Spring Boot+Vue的校园互助交易平台开发实战

基于Spring Boot+Vue的校园互助交易平台开发实战

1. 选题拆解:校园互助交易平台到底在研究什么1.1 从一个很朴素的痛点说起高校里的闲置物品交易、二手教材买卖、代取快递、拼车拼单、技能互助,这些需求在校园里是真实存在且高频发生的。但当前大部分信息的流转方式是QQ群、微信群、表白墙、朋友圈&…

📅 2026/10/10 20:34:14
S/4HANA Cloud FICO过账字段为空?合并单元与FS项目派生排查指南

S/4HANA Cloud FICO过账字段为空?合并单元与FS项目派生排查指南

先别急着怀疑配置是不是全错了。我见过不止一个项目组,财务同事在S/4HANA Cloud里做FICO过账(比如总账凭证、供应商发票),发现凭证界面上有“合并单元”“FS项目(基金中心、承诺项目)”这类字段&#xff0c…

📅 2026/10/10 20:29:14
Python Flask开发教师科研成果管理系统:架构设计与部署实战

Python Flask开发教师科研成果管理系统:架构设计与部署实战

做高校科研成果管理这块,绕不开的一个场景就是:学院每年要把教师的论文、项目、专利、获奖情况统计一遍,年底考核要数据、职称评审要数据、学科评估又要数据。以前用Excel来回传,版本混乱、格式不统一,真到了要用的时候…

📅 2026/10/10 20:29:14
MORE NEWS

更多资讯

📰

模型预测控制提升风电一次调频能力:原理与Matlab仿真实践

风电装机并网越多,系统频率反而越容易“飘”——这个现象在前些年刚做新能源并网仿真时,我一度觉得很矛盾:风不是清洁又便宜吗,怎么还会给电网添乱?后来才意识到,问题不在风本身,而在风机的“接…

📰

2026计算机就业指南:热门方向、真实门槛与零基础入行路线

要说2026年的计算机就业,先说一个我观察到的结论:行情没有网上传的那么惨,但也绝对回不到前几年“疯狂抢人”的时代了。现在整个行业进入了一个结构性调整期,简单说就是“门槛变高、需求分化、能力为王”。这篇内容想帮你看清2026…

📰

2024国赛C题种植策略建模:线性规划与Python求解实战

简介:2024国赛C题农作物的种植策略完整方案包,面向全国大学生数学建模竞赛参赛者及相关领域研究者,提供从问题分析、思路设计到代码实现的一站式参考。方案以贪心算法与优先队列为核心,结合价格弹性、间作等现实条件应对复杂约束&…

📰

Python数据分析实战:网易云音乐歌单爬取与可视化全流程解析

简介:这是一份基于Python数据可视化的网易云音乐歌单分析系统完整源码与文档说明,面向需要完成Python数据分析与可视化期末大作业、课程设计或毕业设计的学生,也适合希望快速上手数据分析项目的新手。系统中包含数据清洗、统计分析与多种可视…

📰

深度学习工业缺陷检测实战:从数据标注到mAP评估全流程

简介:面向毕业设计与课程作业的深度学习工业缺陷检测Python项目源码,适合具备一定Python基础、希望快速搭建可演示系统的本科及高职学生。项目包含完整的模型训练、数据预处理、评估与预测流程,采用ResNet/SE-ResNet等卷积网络结构&#xff0…

📰

滑动窗口解力扣438:字母异位词与Python频次数组优化

先交代一下背景。力扣438题《找到字符串中所有字母异位词》,是一道非常经典的滑动窗口入门题,也是我在刷题前期花最多时间“悟”明白的一道题。很多教程把它归类为“中等难度”,但在我看来,这道题真正的价值不在于它本身的代码量&…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬