1. 项目概述与学习价值
这个医院预约挂号系统的开发教程,是专门为零基础学习者设计的全栈开发实战项目。作为一名有多年医疗系统开发经验的工程师,我认为这个项目特别适合计算机相关专业的毕业生作为毕业设计选题,也适合想转型全栈开发的职场新人练手。
为什么选择这个项目作为教学案例?首先,医疗信息化是当前数字化转型的重点领域,预约挂号系统作为医院对外的核心服务窗口,具有明确的市场需求和完整的业务闭环。其次,系统涵盖了企业级应用开发的典型技术栈:
- 前端采用Vue3组合式API开发
- 后端使用SpringBoot3构建RESTful接口
- 数据库设计包含多表关联和事务处理
- 系统集成需要考虑安全认证和性能优化
提示:即使完全没有Vue或SpringBoot基础,只要掌握基本的HTML/CSS/JavaScript和Java语法,通过本教程的循序渐进学习,完全可以独立完成这个项目。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术栈选型解析
2.1 为什么选择SpringBoot3
SpringBoot3于2022年底发布,相比2.x版本有几个重要升级:
- 全面支持Java17+特性(如record类、文本块)
- 原生镜像支持(通过GraalVM)
- 更完善的Micrometer观测性
- 对JDK21虚拟线程的预备支持
在挂号系统中,我们特别利用了:
- Spring Data JPA + QueryDSL实现动态查询
- Spring Security做OAuth2认证
- Spring Cache抽象做号源缓存
- Actuator端点做健康检查
java复制// 典型的科室查询接口示例
@RestController
@RequestMapping("/api/departments")
public class DepartmentController {
@Autowired
private DepartmentRepository repository;
@GetMapping
public Page<Department> search(
@RequestParam(required = false) String name,
Pageable pageable) {
return repository.findAll(
DepartmentPredicates.nameContains(name),
pageable);
}
}
2.2 Vue3的组合式API优势
相比Options API,Vue3的组合式API在复杂业务场景下更具优势:
- 逻辑关注点更集中(同一功能代码在一起)
- 更好的TypeScript支持
- 可组合复用的逻辑片段
在挂号前台页面中,我们使用:
<script setup>语法糖- Pinia状态管理
- Vue Router的导航守卫
- Element Plus组件库
javascript复制// 预约表单的典型逻辑封装
const useAppointment = () => {
const form = reactive({
patientId: '',
departmentId: null,
doctorId: null,
scheduleDate: ''
});
const availableDoctors = computed(() => {
return doctors.value.filter(d =>
d.departmentId === form.departmentId
);
});
const submit = async () => {
await appointmentAPI.create(form);
// 跳转到预约记录页
};
return { form, availableDoctors, submit };
};
3. 核心业务模块设计
3.1 数据库ER图设计
医院挂号系统的核心实体包括:
- 患者(patient)
- 科室(department)
- 医生(doctor)
- 排班(schedule)
- 预约(appointment)
关键关系:
- 医生属于某个科室(多对一)
- 排班关联医生和日期(一对多)
- 预约关联患者和排班(多对一)
sql复制CREATE TABLE `schedule` (
`id` bigint NOT NULL AUTO_INCREMENT,
`doctor_id` bigint NOT NULL,
`work_date` date NOT NULL,
`time_slot` varchar(20) NOT NULL,
`total_count` int NOT NULL COMMENT '总号源数',
`available_count` int NOT NULL COMMENT '剩余号源数',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_doctor_time` (`doctor_id`,`work_date`,`time_slot`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 预约业务流程
完整的预约流程包含以下关键步骤:
- 患者登录/注册(手机号验证)
- 查询科室列表(支持树形展示)
- 选择科室后加载医生列表
- 查看医生排班信息(分页展示)
- 选择时间段提交预约
- 支付(集成支付宝沙箱)
- 生成预约单(含二维码)
注意:号源扣减需要加分布式锁,防止超卖。我们采用Redis的SETNX实现:
java复制public boolean makeAppointment(Long scheduleId) {
String lockKey = "lock:schedule:" + scheduleId;
try {
// 获取分布式锁(有效期10秒)
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (Boolean.TRUE.equals(locked)) {
// 查询剩余号源
Schedule schedule = scheduleRepository.findById(scheduleId)
.orElseThrow(() -> new BusinessException("排班不存在"));
if (schedule.getAvailableCount() <= 0) {
throw new BusinessException("号源已约满");
}
// 扣减库存
scheduleRepository.decreaseAvailable(scheduleId);
return true;
}
throw new BusinessException("操作太频繁,请稍后再试");
} finally {
// 释放锁
redisTemplate.delete(lockKey);
}
}
4. 开发环境搭建指南
4.1 后端环境准备
- JDK17+(推荐Amazon Corretto)
- IntelliJ IDEA(社区版即可)
- MySQL 8.0(注意配置utf8mb4字符集)
- Redis 6.x(用于会话和缓存)
- Maven 3.8+
关键Maven依赖:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
4.2 前端开发环境
- Node.js 16+
- VS Code + Volar插件
- Vue CLI 5.x
创建项目:
bash复制npm init vue@latest hospital-booking
cd hospital-booking
npm install
npm install element-plus @element-plus/icons-vue pinia axios
推荐VS Code插件:
- Volar(Vue语言支持)
- ESLint(代码规范检查)
- Prettier(代码格式化)
- REST Client(API测试)
5. 典型问题解决方案
5.1 跨域问题处理
开发阶段常见跨域问题,解决方案:
后端配置(SpringBoot):
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:5173")
.allowedMethods("*")
.allowCredentials(true)
.maxAge(3600);
}
}
前端代理配置(vite.config.js):
javascript复制export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
})
5.2 文件上传下载
医生头像上传的典型实现:
前端(Vue3 + Element Plus):
vue复制<template>
<el-upload
action="/api/upload"
:show-file-list="false"
:on-success="handleSuccess"
:before-upload="beforeUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else><Plus /></el-icon>
</el-upload>
</template>
<script setup>
const beforeUpload = (file) => {
const isJPG = file.type === 'image/jpeg';
if (!isJPG) {
ElMessage.error('只能上传JPG格式!');
}
return isJPG;
};
</script>
后端SpringBoot控制器:
java复制@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
throw new BusinessException("请选择文件");
}
String fileName = UUID.randomUUID() +
file.getOriginalFilename().substring(
file.getOriginalFilename().lastIndexOf("."));
Path path = Paths.get("uploads/" + fileName);
try {
Files.copy(file.getInputStream(), path,
StandardCopyOption.REPLACE_EXISTING);
return "/uploads/" + fileName;
} catch (IOException e) {
throw new BusinessException("上传失败");
}
}
6. 项目部署实践
6.1 后端打包与运行
- 打包可执行JAR:
bash复制mvn clean package -DskipTests
- 生产环境启动(带性能调优参数):
bash复制java -server -Xms512m -Xmx512m -XX:+UseG1GC \
-jar hospital-booking.jar \
--spring.profiles.active=prod
- 推荐使用Docker部署:
dockerfile复制FROM amazoncorretto:17
COPY target/hospital-booking.jar /app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
6.2 前端静态资源部署
- 构建生产环境代码:
bash复制npm run build
- Nginx配置示例:
nginx复制server {
listen 80;
server_name booking.example.com;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://backend:8080;
proxy_set_header Host $host;
}
}
- 启用Gzip压缩(nginx.conf):
nginx复制gzip on;
gzip_types text/plain text/css application/json application/javascript;
7. 毕业设计扩展建议
如果想在基础功能上做创新点,可以考虑:
- 智能推荐医生(基于患者历史预约记录)
- 候诊队列实时通知(WebSocket推送)
- 检查报告查询(集成OCR识别)
- 患者满意度评价系统
- 基于微服务的架构改造
对于论文写作,建议章节安排:
- 绪论(背景意义、国内外现状)
- 关键技术分析(SpringBoot、Vue3等)
- 系统需求分析(用例图、流程图)
- 系统设计(架构图、ER图、接口设计)
- 系统实现(核心代码截图)
- 系统测试(测试用例、压力测试)
- 总结与展望
我在实际指导毕业生时发现,最容易出问题的环节是数据库事务处理。比如预约操作需要同时更新多个表,一定要加上@Transactional注解:
java复制@Transactional
public Appointment createAppointment(CreateAppointmentDTO dto) {
// 1. 检查号源可用性
// 2. 创建预约记录
// 3. 扣减号源数量
// 4. 生成支付订单
// 所有操作要么全部成功,要么全部回滚
}
