
简介这是一套面向计算机专业本科生的毕业设计/课程设计实战项目基于SpringBootVue实现前后端分离的医院陪诊管理系统聚焦医疗陪诊服务场景中的预约管理、人员调度、状态跟踪等核心业务。资源包共675个文件涵盖289个Java后端逻辑文件、104个Vue组件页、95个JS交互脚本、87个SVG图标资源以及yml配置、sql建表、bat部署脚本等关键文件整体2.22MB结构完整、开箱即用。已有320人学习下载适合希望系统掌握全栈开发流程的学习者。读者可直接复用完整源码深入理解RESTful接口设计、JWT鉴权、WebSocket实时通知、Vue Router路由控制及MyBatis/JPA数据操作等关键技术点并通过配套项目说明文档快速掌握系统架构、数据库ER图、权限角色划分与本地部署步骤。1. 为什么医院陪诊场景需要 SpringBoot Vue 的前后端分离架构一个真实的医院陪诊业务不是简单的挂号排队记录——它要实时同步陪诊员位置、动态更新患者检查进度、支持家属远程查看陪诊轨迹、对接院内HIS系统获取检验报告状态还要在微信小程序和PC后台共用同一套核心逻辑。这种多端协同、状态强一致、权限粒度细如家属只能看自己亲属护士可批量调度的场景硬套传统JSP或单体Vue SPA会迅速陷入耦合泥潭前端改个预约表单字段后端得重发war包HIS接口返回结构微调整个页面渲染逻辑全崩。而 SpringBoot Vue 的分离架构恰恰把「业务规则校验与数据持久化」锁死在后端SpringBoot 擅长事务控制、定时任务触发检验结果拉取、JWT 权限分级把「交互响应与视图状态管理」交给前端Vue 的 Composition API 能清晰组织陪诊地图组件、实时消息弹窗、多步骤预约表单。这不是为炫技选型而是当系统要接入医保电子凭证扫码、对接高德定位SDK、未来扩展AI陪诊语音提醒时唯一能低成本演进的技术底座。适合正在从Excel手工排班转向数字化陪诊运营的中小型民营医院信息科也适合想用真实医疗场景练手的Java全栈开发者——源码里藏着比教科书更复杂的权限树构建、检查项目动态配置、以及跨域请求下文件上传的分片续传实现。2. 后端服务搭建SpringBoot 2.7.x 构建医院陪诊核心API2.1 项目初始化与关键依赖选择使用 Spring Initializr 创建基础工程时必须勾选以下模块Spring Web提供 RESTful 接口、Spring Data JPA简化陪诊订单、患者档案等实体的CRUD、Spring Security实现角色权限控制、Lombok减少样板代码、Validation对预约时间、身份证号等字段做注解校验。特别注意不要勾选 Thymeleaf 或 Freemarker——这是前后端分离的前提所有页面由 Vue 承载后端只输出 JSON。!-- pom.xml 中需显式添加的依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency !-- MySQL 驱动版本需与数据库匹配 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- 用于生成 JWT Token -- dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-api/artifactId version0.11.5/version /dependency提示若项目说明中提到“自动建表”需在application.yml中配置spring.jpa.hibernate.ddl-autoupdate但生产环境严禁使用应改为validate并配合 Flyway 管理 SQL 迁移脚本。update会导致字段类型变更丢失数据比如将VARCHAR(50)改为VARCHAR(100)时可能清空原字段。2.2 核心实体设计以陪诊订单为中心的领域模型医院陪诊系统的核心不是“用户”而是“陪诊订单”AccompanyOrder。它必须关联三方患者Patient、陪诊员Escort、医院科室Department。实体间关系需严格遵循医疗合规要求——例如一个患者可有多次陪诊记录但一个订单只能绑定一名陪诊员陪诊员可同时接多个订单但系统需校验其当日排班时段是否冲突。Entity Table(name accompany_order) public class AccompanyOrder { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; ManyToOne(fetch FetchType.LAZY) JoinColumn(name patient_id, nullable false) private Patient patient; ManyToOne(fetch FetchType.LAZY) JoinColumn(name escort_id, nullable false) private Escort escort; ManyToOne(fetch FetchType.LAZY) JoinColumn(name department_id, nullable false) private Department department; Column(name order_status, length 20) Enumerated(EnumType.STRING) private OrderStatus status; // ENUM: PENDING, ASSIGNED, IN_PROGRESS, COMPLETED, CANCELLED Column(name appointment_time) private LocalDateTime appointmentTime; // 预约就诊时间非系统创建时间 Column(name created_at) private LocalDateTime createdAt; // getter/setter 省略 }2.2.1 关键校验逻辑预约时间冲突检测在AccompanyOrderService中创建订单前必须检查陪诊员在appointmentTime时间段内是否有其他未完成订单public boolean isEscortAvailable(Long escortId, LocalDateTime appointmentTime) { // 查询该陪诊员在 appointmentTime ± 2 小时内的所有非取消订单 LocalDateTime start appointmentTime.minusHours(2); LocalDateTime end appointmentTime.plusHours(2); long count orderRepository.countByEscortIdAndAppointmentTimeBetweenAndStatusNot( escortId, start, end, OrderStatus.CANCELLED); return count 0; }此方法直接调用 JPA 自定义查询避免先查再判断的 N1 问题。参数±2小时是医疗陪诊的典型服务窗口可根据实际业务调整。2.3 安全控制基于角色的 URL 级权限拦截Spring Security 不应只靠PreAuthorize注解分散在每个 Controller 方法上而应在SecurityConfig中集中声明资源访问规则。陪诊系统典型角色有ROLE_PATIENT仅查看本人订单、ROLE_ESCORT查看自己订单更新状态、ROLE_ADMIN管理陪诊员、审核订单。Configuration EnableWebSecurity public class SecurityConfig { Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf().disable() // 前后端分离项目通常禁用 CSRF由 JWT Token 保证安全 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeHttpRequests(authz - authz .requestMatchers(/api/auth/**).permitAll() // 登录接口放行 .requestMatchers(/api/patient/**).hasRole(PATIENT) .requestMatchers(/api/escort/**).hasRole(ESCORT) .requestMatchers(/api/admin/**).hasRole(ADMIN) .anyRequest().authenticated() ) .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } }注意hasRole(PATIENT)中的PATIENT是角色名前缀Spring Security 会自动添加ROLE_前缀因此数据库中角色字段存的是PATIENT而非ROLE_PATIENT。3. 前端工程构建Vue 3 Element Plus 实现陪诊业务视图3.1 Vue CLI 初始化与路由规划使用vue create hospital-accompany创建项目后必须安装vue-router4和axios。路由设计需严格对应后端 API 前缀例如后端/api/patient/orders对应前端/patient/orders// router/index.js const routes [ { path: /login, component: () import(/views/Login.vue) }, { path: /patient, component: () import(/layout/PatientLayout.vue), children: [ { path: orders, component: () import(/views/patient/OrderList.vue) }, { path: order/create, component: () import(/views/patient/OrderCreate.vue) } ] }, { path: /escort, component: () import(/layout/EscortLayout.vue), children: [ { path: dashboard, component: () import(/views/escort/Dashboard.vue) } ] } ]3.1.1 环境变量配置区分开发与生产 API 地址在根目录创建.env.development和.env.production# .env.development VUE_APP_API_BASE_URL http://localhost:8080/api # .env.production VUE_APP_API_BASE_URL https://api.hospital-accompany.com/api所有 API 请求通过axios封装自动注入 Base URL// utils/request.js import axios from axios import { ElMessage } from element-plus const service axios.create({ baseURL: process.env.VUE_APP_API_BASE_URL, timeout: 10000 }) service.interceptors.response.use( response response, error { if (error.response?.status 401) { // Token 过期跳转登录页 localStorage.removeItem(token) router.push(/login) } ElMessage.error(error.response?.data?.message || 请求失败) return Promise.reject(error) } )3.2 关键业务组件陪诊订单创建表单的动态验证患者创建陪诊订单时需动态加载科室列表、医生排班、并实时校验身份证号格式。Vue 3 的Composition API可将逻辑抽离为独立函数!-- views/patient/OrderCreate.vue -- template el-form :modelform :rulesrules refformRef el-form-item label就诊科室 propdepartmentId el-select v-modelform.departmentId placeholder选择科室 el-option v-fordept in departments :keydept.id :labeldept.name :valuedept.id / /el-select /el-form-item el-form-item label预约时间 propappointmentTime el-date-picker v-modelform.appointmentTime typedatetime value-formatYYYY-MM-DD HH:mm:ss :disabled-datedisabledDate / /el-form-item /el-form /template script setup import { ref, onMounted } from vue import { getDepartments } from /api/department const form ref({ departmentId: , appointmentTime: }) const departments ref([]) const formRef ref(null) onMounted(async () { departments.value await getDepartments() // 调用 API 获取科室列表 }) // 禁用过去的时间点 const disabledDate (date) { return date.getTime() Date.now() - 86400000 // 禁用今天之前的所有日期 } const rules { departmentId: [{ required: true, message: 请选择科室, trigger: change }], appointmentTime: [{ required: true, message: 请选择预约时间, trigger: change }] } /script提示value-formatYYYY-MM-DD HH:mm:ss确保提交给后端的字符串格式与 SpringBootLocalDateTime的默认解析格式一致避免Failed to convert property value错误。3.3 状态管理使用 Pinia 存储全局陪诊员信息陪诊员登录后其基本信息姓名、头像、可服务区域需在多个页面复用。Pinia 是 Vue 3 官方推荐的状态库比 Vuex 更轻量// stores/escort.js import { defineStore } from pinia export const useEscortStore defineStore(escort, { state: () ({ info: null, availableAreas: [] // 可服务的医院区域列表 }), actions: { async fetchEscortInfo() { const res await api.get(/escort/profile) this.info res.data this.availableAreas res.data.serviceAreas } } })在EscortLayout.vue中调用script setup import { useEscortStore } from /stores/escort const escortStore useEscortStore() escortStore.fetchEscortInfo() // 组件挂载时自动获取 /script4. 前后端联调解决跨域、Token 传递与文件上传4.1 开发阶段跨域代理配置Vue CLI 的vue.config.js必须配置代理将/api请求转发至 SpringBoot 服务避免浏览器 CORS 报错// vue.config.js module.exports { devServer: { proxy: { /api: { target: http://localhost:8080, // SpringBoot 启动端口 changeOrigin: true, pathRewrite: { ^/api: /api // 保持路径前缀不变 } } } } }注意此配置仅在npm run serve时生效构建后的静态文件部署到 Nginx 时需在 Nginx 配置反向代理而非依赖前端代理。4.2 JWT Token 的全流程传递Token 存储在localStorage中每次请求需通过AuthorizationHeader 传递// utils/request.js 中的请求拦截器 service.interceptors.request.use( config { const token localStorage.getItem(token) if (token) { config.headers.Authorization Bearer ${token} } return config }, error Promise.reject(error) )后端 SpringBoot 需解析该 Header// JwtAuthenticationFilter.java String authHeader request.getHeader(Authorization); if (authHeader ! null authHeader.startsWith(Bearer )) { String token authHeader.substring(7); // 去掉 Bearer 前缀 // 解析 token 并设置 SecurityContext }4.3 陪诊过程中的图片上传分片与断点续传实现陪诊员需上传检查报告图片单张可能超 10MB。直接axios.post会阻塞 UI 且无断点续传能力。源码中采用spark-md5计算文件哈希实现秒传与分片// utils/upload.js import SparkMD5 from spark-md5 export async function uploadFile(file, uploadUrl) { const chunkSize 2 * 1024 * 1024 // 2MB 分片 const chunks Math.ceil(file.size / chunkSize) const spark new SparkMD5.ArrayBuffer() const fileReader new FileReader() // 先计算整个文件 MD5用于秒传判断 const buffer await file.arrayBuffer() spark.append(buffer) const fileHash spark.end() // 检查服务端是否已存在该文件 const { data: exist } await axios.get(${uploadUrl}/check?hash${fileHash}) if (exist.exists) { return { url: exist.url } // 直接返回已有 URL } // 分片上传 for (let i 0; i chunks; i) { const start i * chunkSize const end Math.min(start chunkSize, file.size) const blob file.slice(start, end) const formData new FormData() formData.append(file, blob) formData.append(hash, fileHash) formData.append(chunk, i) formData.append(chunks, chunks) await axios.post(uploadUrl, formData) } // 合并分片 await axios.post(${uploadUrl}/merge, { hash: fileHash, filename: file.name }) return { url: /uploads/${fileHash}.jpg } }后端需提供/check、/merge等接口源码中已实现基于 Redis 的分片状态跟踪。5. 生产部署与性能优化Nginx Docker JVM 参数调优5.1 Nginx 静态资源托管与 API 反向代理Vue 构建后的dist目录需由 Nginx 托管并将/api路径代理至 SpringBoot# /etc/nginx/conf.d/hospital-accompany.conf server { listen 80; server_name accompany.hospital.com; # 静态资源 location / { root /var/www/hospital-accompany/dist; try_files $uri $uri/ /index.html; } # API 代理 location /api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }提示try_files $uri $uri/ /index.html;是 Vue Routerhistory模式的必需配置否则刷新页面会 404。5.2 SpringBoot 应用 Docker 化部署编写Dockerfile基于openjdk:17-jre-slim基础镜像减小体积FROM openjdk:17-jre-slim VOLUME [/tmp] ARG JAR_FILEtarget/hospital-accompany.jar COPY ${JAR_FILE} app.jar ENTRYPOINT [java,-Djava.security.egdfile:/dev/./urandom,-jar,/app.jar]构建并运行# 构建镜像 docker build -t hospital-accompany . # 运行容器映射 8080 端口挂载配置文件 docker run -d \ --name accompany-app \ -p 8080:8080 \ -v /opt/hospital/config/application-prod.yml:/app/config/application.yml \ -v /opt/hospital/uploads:/app/uploads \ hospital-accompany5.3 JVM 关键参数调优针对医院陪诊的 GC 策略医院陪诊系统特点是请求峰值明显早8点集中预约、对象生命周期短订单状态变更频繁。应避免默认的 G1GC 在小堆内存下频繁 Young GC# 启动命令中添加 JVM 参数 java -Xms512m -Xmx1024m \ -XX:UseZGC \ # JDK17 推荐 ZGC停顿时间 10ms -XX:MaxGCPauseMillis10 \ -XX:UnlockExperimentalVMOptions \ -jar app.jar若使用 JDK8则改用UseG1GC并调小MaxGCPauseMillis-XX:UseG1GC -XX:MaxGCPauseMillis200 -XX:G1HeapRegionSize2M5.3.1 数据库连接池 HikariCP 参数验证在application-prod.yml中HikariCP 的maximumPoolSize必须与 MySQLmax_connections匹配。假设 MySQL 设置为max_connections200则spring: datasource: hikari: maximum-pool-size: 50 # 留出余量给其他服务 minimum-idle: 10 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000验证连接池是否健康访问http://localhost:8080/actuator/metrics/hikaricp.connections.active观察活跃连接数是否长期接近maximum-pool-size若是说明数据库处理能力已达瓶颈需优化慢 SQL 或增加读库。5.4 Vue 生产构建优化代码分割与 CDN 加速在vue.config.js中启用externals将vue、element-plus等大依赖剥离通过 CDN 引入configureWebpack: { externals: { vue: Vue, element-plus: ElementPlus, axios: axios } }并在public/index.html中添加 CDNscript srchttps://unpkg.com/vue3.2.47/dist/vue.global.prod.js/script script srchttps://unpkg.com/element-plus2.3.4/dist/index.full.min.js/script script srchttps://unpkg.com/axios1.4.0/dist/axios.min.js/script构建后dist/js/app.xxx.js体积可减少 60%首屏加载更快。本文还有配套的精品资源点击获取