1. 项目概述与核心价值
疫情隔离酒店管理系统是一个典型的B/S架构应用,采用SpringBoot+Vue前后端分离技术栈实现。这个系统本质上是一个垂直领域的酒店管理解决方案,专门针对疫情期间的隔离酒店运营场景设计。我在2020年参与过某市隔离点信息化建设,深知这类系统的核心痛点——既要满足常规酒店管理需求,又要兼顾防疫特殊要求。
这个项目的独特价值在于:
- 业务场景特殊性:相比普通酒店管理系统,需要额外处理核酸检测记录、隔离期计算、异常体温报警等防疫功能
- 技术栈典型性:SpringBoot+Vue是目前企业级应用最主流的技术组合,MySQL更是中小型项目的标配数据库
- 教学适配性:系统规模适中(约15-20个核心功能模块),包含完整的权限管理、数据报表等毕业设计必备要素
提示:选择隔离酒店作为毕设主题有个隐藏优势——防疫相关功能模块的文档规范非常完善,卫健委发布的《集中隔离医学观察点信息化建设指南》等文件可以直接作为需求参考依据。
2. 技术架构解析
2.1 后端技术选型
SpringBoot 2.7.x + MyBatis-Plus组合是经过验证的黄金搭档。这里特别说明几个关键配置点:
java复制// 典型的多环境配置示例
spring:
profiles:
active: dev
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/quarantine_hotel?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: deleted # 逻辑删除字段
logic-delete-value: 1
logic-not-delete-value: 0
选型考量:
- 放弃JPA选择MyBatis-Plus的原因:国内企业MyBatis生态更普及,且需要手写复杂SQL处理防疫统计报表
- 必须配置的Jackson时区参数:隔离日期计算涉及严格的时间判定,时区配置错误会导致严重业务漏洞
- 逻辑删除设计:所有业务表都需要增加deleted字段,这是酒店管理系统数据安全的基本要求
2.2 前端技术栈
Vue 3 + Element Plus的组合是目前最稳妥的选择。实测中发现几个关键配置:
javascript复制// axios拦截器典型配置
axios.interceptors.request.use(config => {
config.headers['Authorization'] = localStorage.getItem('token')
return config
})
axios.interceptors.response.use(response => {
if (response.data.code === 401) {
router.push('/login')
}
return response.data
}, error => {
return Promise.reject(error)
})
避坑指南:
- Vue 3的Composition API写法更适合复杂业务逻辑,但需要为团队成员预留学习成本
- 必须封装完善的权限指令,如
v-permission="['admin']",隔离酒店涉及多级权限管控 - 防疫看板建议使用ECharts实现,其地图组件能直观展示隔离人员分布
3. 核心功能实现
3.1 数据库设计要点
隔离酒店系统的数据库有三大核心表组:
- 基础信息表组(酒店、房间、物资)
sql复制CREATE TABLE `room` (
`id` bigint NOT NULL AUTO_INCREMENT,
`hotel_id` bigint NOT NULL COMMENT '所属酒店',
`room_number` varchar(20) NOT NULL COMMENT '房号',
`room_type` tinyint NOT NULL COMMENT '1-标准间 2-单人间 3-套房',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '0-空闲 1-已入住 2-消毒中',
`quarantine_type` tinyint NOT NULL COMMENT '1-居家隔离 2-集中隔离',
`daily_price` decimal(10,2) NOT NULL,
`floor` smallint NOT NULL,
`window_type` tinyint NOT NULL COMMENT '0-无窗 1-有窗',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_hotel_room` (`hotel_id`,`room_number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
- 人员管理表组(隔离人员、工作人员)
sql复制CREATE TABLE `guest` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`id_card` varchar(18) NOT NULL,
`phone` varchar(20) NOT NULL,
`health_code` varchar(20) NOT NULL COMMENT '健康码颜色',
`check_in_time` datetime NOT NULL,
`check_out_time` datetime DEFAULT NULL,
`room_id` bigint NOT NULL,
`source_area` varchar(100) NOT NULL COMMENT '来源地',
`close_contact` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否密接',
`temperature` decimal(3,1) DEFAULT NULL COMMENT '最近体温',
`symptom` varchar(200) DEFAULT NULL COMMENT '症状描述',
`emergency_contact` varchar(50) DEFAULT NULL,
`emergency_phone` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_room` (`room_id`),
KEY `idx_check_out` (`check_out_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
- 防疫业务表组(核酸检测、消毒记录)
sql复制CREATE TABLE `nucleic_test` (
`id` bigint NOT NULL AUTO_INCREMENT,
`guest_id` bigint NOT NULL,
`test_time` datetime NOT NULL,
`result` tinyint NOT NULL COMMENT '0-阴性 1-阳性',
`test_org` varchar(100) NOT NULL COMMENT '检测机构',
`test_type` tinyint NOT NULL COMMENT '1-咽拭子 2-鼻拭子',
`operator` varchar(50) NOT NULL COMMENT '操作人员',
`next_test_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_guest` (`guest_id`),
KEY `idx_test_time` (`test_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
重要提示:所有时间字段必须明确考虑时区问题,隔离期计算错误可能导致严重防疫事故。建议在MySQL配置中设置
default-time-zone='+8:00'
3.2 关键业务接口实现
隔离到期自动提醒功能:
java复制@Scheduled(cron = "0 0 9 * * ?") // 每天上午9点执行
public void autoCheckOutReminder() {
LocalDate tomorrow = LocalDate.now().plusDays(1);
List<Guest> guests = guestMapper.selectList(new LambdaQueryWrapper<Guest>()
.eq(Guest::getStatus, 1)
.apply("DATE(check_out_time) = {0}", tomorrow));
guests.forEach(guest -> {
String message = String.format(
"尊敬的%s,您的隔离期将于明日%s结束,请做好离店准备。",
guest.getName(),
guest.getCheckOutTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
);
smsService.send(guest.getPhone(), message);
});
}
体温异常预警功能:
java复制@PostMapping("/temperature")
public Result<?> reportTemperature(@RequestBody TemperatureDTO dto) {
Guest guest = guestService.getById(dto.getGuestId());
if (guest == null) {
return Result.error("隔离人员不存在");
}
// 记录体温
TemperatureRecord record = new TemperatureRecord();
record.setGuestId(dto.getGuestId());
record.setTemperature(dto.getTemperature());
record.setMeasureTime(LocalDateTime.now());
temperatureRecordService.save(record);
// 异常体温处理
if (dto.getTemperature().compareTo(new BigDecimal("37.3")) > 0) {
alarmService.triggerTemperatureAlarm(
guest.getId(),
dto.getTemperature(),
dto.getSymptoms()
);
}
return Result.ok();
}
4. 典型问题与解决方案
4.1 高并发场景下的房间状态同步
隔离酒店在疫情爆发期可能面临集中入住的情况,房间状态管理需要特殊处理:
- 乐观锁方案:
java复制public boolean checkIn(Long roomId, Guest guest) {
Room room = roomMapper.selectById(roomId);
if (room.getStatus() != 0) {
return false;
}
room.setStatus(1);
int updated = roomMapper.update(room,
new LambdaUpdateWrapper<Room>()
.eq(Room::getId, roomId)
.eq(Room::getStatus, 0)
);
if (updated > 0) {
guest.setRoomId(roomId);
guest.setCheckInTime(LocalDateTime.now());
guestMapper.insert(guest);
return true;
}
return false;
}
- Redis分布式锁方案:
java复制public boolean checkInWithLock(Long roomId, Guest guest) {
String lockKey = "room:lock:" + roomId;
String requestId = UUID.randomUUID().toString();
try {
// 尝试获取锁
boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, requestId, 30, TimeUnit.SECONDS);
if (!locked) {
return false;
}
Room room = roomMapper.selectById(roomId);
if (room.getStatus() != 0) {
return false;
}
room.setStatus(1);
roomMapper.updateById(room);
guest.setRoomId(roomId);
guest.setCheckInTime(LocalDateTime.now());
guestMapper.insert(guest);
return true;
} finally {
// 释放锁
if (requestId.equals(redisTemplate.opsForValue().get(lockKey))) {
redisTemplate.delete(lockKey);
}
}
}
4.2 防疫数据导出性能优化
核酸检测记录等数据导出时可能涉及大量数据:
java复制public void exportNucleicTest(HttpServletResponse response,
Date startDate, Date endDate) throws IOException {
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition",
"attachment;filename=nucleic_test_" + System.currentTimeMillis() + ".xlsx");
// 使用EasyExcel分页查询避免OOM
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
.head(NucleicTestExportVO.class)
.build();
int pageSize = 1000;
int pageNo = 1;
while (true) {
Page<NucleicTest> page = new Page<>(pageNo, pageSize);
LambdaQueryWrapper<NucleicTest> query = new LambdaQueryWrapper<NucleicTest>()
.ge(NucleicTest::getTestTime, startDate)
.le(NucleicTest::getTestTime, endDate)
.orderByAsc(NucleicTest::getTestTime);
Page<NucleicTest> result = nucleicTestMapper.selectPage(page, query);
if (result.getRecords().isEmpty()) {
break;
}
List<NucleicTestExportVO> exportData = result.getRecords().stream()
.map(this::convertToVO)
.collect(Collectors.toList());
WriteSheet writeSheet = EasyExcel.writerSheet("第" + pageNo + "页").build();
excelWriter.write(exportData, writeSheet);
if (result.getRecords().size() < pageSize) {
break;
}
pageNo++;
}
excelWriter.finish();
}
5. 项目部署与扩展建议
5.1 容器化部署方案
推荐使用Docker Compose进行一体化部署:
dockerfile复制# backend/Dockerfile
FROM openjdk:11-jre
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
dockerfile复制# frontend/Dockerfile
FROM nginx:alpine
COPY dist/ /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
yaml复制# docker-compose.yml
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: quarantine_hotel
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
command: --default-time-zone=+8:00
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/quarantine_hotel
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: 123456
frontend:
build: ./frontend
ports:
- "80:80"
depends_on:
- backend
volumes:
mysql_data:
5.2 项目扩展方向
- 物联网集成:对接智能体温计设备,实现自动体温上报
- 微信小程序:开发隔离人员自助服务小程序,减少接触
- 大数据分析:基于历史数据预测疫情传播风险
- 视频监控集成:对接门磁报警系统,防止隔离人员擅自外出
我在实际部署中发现Nginx有个关键配置需要注意:
nginx复制location /api {
proxy_pass http://backend: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;
# 解决413 Request Entity Too Large错误
client_max_body_size 20M;
}
这个项目最值得深入研究的其实是防疫业务流程与信息系统的结合点,比如隔离期计算算法如何与酒店管理系统原有功能无缝整合。建议有兴趣的同学可以深入研究《传染病防治法》中关于隔离管理的具体要求,这些法律条文实际上就是最好的需求文档。
