1. 项目背景与核心价值
高校疫情防控系统是后疫情时代校园管理的刚需工具。去年我在某211高校信息化部门参与了一套防疫系统的落地,深刻体会到这类系统需要同时满足三个核心诉求:实时精准的疫情数据采集、多角色协同的应急处置流程、可溯源的统计分析与预警。传统Excel表格+微信群的方式不仅效率低下,还存在数据滞后、信息孤岛等问题。
这套基于SpringBoot2+Vue3的技术方案,正是为了解决这些痛点而生。前端采用Vue3的组合式API开发管理后台,后端通过SpringBoot提供RESTful接口,配合MyBatis-Plus的动态SQL能力,实现了从学生每日报备到管理员决策的全链路数字化。特别在返校季高峰期,系统需要承受每分钟上千次的健康打卡请求,我们通过Redis缓存热点数据和MySQL读写分离保证了系统稳定。
2. 技术架构解析
2.1 前后端分离设计
系统采用经典的前后端分离架构,通过JSON格式进行数据交互。前端Vue3项目通过axios封装了统一的请求拦截器,处理了以下关键逻辑:
// 请求拦截示例 service.interceptors.request.use(config => { if (store.getters.token) { config.headers['X-Token'] = getToken() } // 对打卡这类高频请求启用防抖 if (config.url.includes('/health/report')) { config.debounce = true } return config })后端则通过SpringBoot的@RestControllerAdvice实现了全局异常处理,统一返回格式中包含业务状态码:
@Data public class Result<T> { private Integer code; // 200成功 500失败 private String msg; private T data; public static <T> Result<T> success(T data) { return new Result<>(200, "操作成功", data); } }2.2 核心功能模块
系统主要包含六大模块:
- 健康打卡系统:学生端微信小程序+网页双端填报,支持地理位置校验
- 行程轨迹管理:通过百度地图API实现行程卡模拟
- 核酸疫苗统计:可视化展示各院系接种率
- 隔离观察管理:床位资源调度与状态追踪
- 疫情预警看板:ECharts实现实时数据可视化
- 消息通知中心:WebSocket推送紧急通知
3. 关键技术实现
3.1 高并发打卡处理
面对早8点的打卡高峰,我们采用多级缓存策略:
- Redis缓存基础数据(如班级列表)
- Caffeine本地缓存用户历史记录
- MySQL使用分库分表(按学院拆分)
核心代码示例:
@Cacheable(value = "dailyReport", key = "#userId+'_'+#date") public DailyReport getDailyReport(Long userId, String date) { // 先查Redis String redisKey = "report:" + userId + ":" + date; DailyReport report = redisTemplate.opsForValue().get(redisKey); if (report == null) { // 查数据库 report = mapper.selectOne(new QueryWrapper<DailyReport>() .eq("user_id", userId) .eq("report_date", date)); if (report != null) { redisTemplate.opsForValue().set(redisKey, report, 6, TimeUnit.HOURS); } } return report; }3.2 可视化疫情地图
利用Vue3的setup语法糖配合高德地图JS API:
<script setup> import { onMounted, ref } from 'vue' const map = ref(null) onMounted(() => { AMapLoader.load({ key: 'your-key', version: '2.0' }).then(AMap => { map.value = new AMap.Map('container', { viewMode: '3D', zoom: 15, center: [116.397428, 39.90923] }) // 添加疫情热力图 const heatmap = new AMap.Heatmap(map.value, { radius: 25, opacity: [0, 0.8] }) heatmap.setDataSet({ data: props.heatData, max: 100 }) }) }) </script>4. 数据库设计要点
4.1 核心表结构
CREATE TABLE `student_health` ( `id` bigint NOT NULL AUTO_INCREMENT, `student_id` varchar(20) NOT NULL COMMENT '学号', `temperature` decimal(3,1) DEFAULT NULL, `health_status` tinyint DEFAULT '0' COMMENT '0正常 1发热 2疑似', `location` point NOT NULL COMMENT 'GPS坐标', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), SPATIAL KEY `idx_location` (`location`), KEY `idx_student_date` (`student_id`,`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `isolation_record` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_id` bigint NOT NULL, `start_date` date NOT NULL, `end_date` date NOT NULL, `dorm_id` varchar(20) NOT NULL COMMENT '隔离宿舍号', `status` tinyint DEFAULT '0' COMMENT '0观察中 1已解除', PRIMARY KEY (`id`), KEY `idx_user_status` (`user_id`,`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;4.2 查询优化实践
- 空间索引加速地理位置查询
- 联合索引优化高频查询场景
- 使用MySQL8.0的窗口函数进行统计计算
5. 部署与运维经验
5.1 服务器配置建议
- 生产环境推荐配置:
- 前端:Nginx + 对象存储(静态资源)
- 后端:2核4G × 2(负载均衡)
- 数据库:4核8G + SSD(主从架构)
- Redis:哨兵模式部署
5.2 常见问题排查
打卡提交缓慢:
- 检查Redis连接池配置
- 验证MySQL慢查询日志
- 添加
@Transactional注解时注意隔离级别
地图加载异常:
- 确认JS API密钥有效
- 检查跨域配置(特别是Nginx的CORS设置)
- 使用
v-if控制组件加载时机
Excel导出OOM:
// 使用EasyExcel的异步导出 public void export(HttpServletResponse response) { ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()) .head(HealthReport.class) .build(); // 分页查询写入 int pageSize = 1000; int pageNo = 1; while (true) { Page<HealthReport> page = new Page<>(pageNo, pageSize); IPage<HealthReport> pageResult = mapper.selectPage(page, null); if (pageResult.getRecords().isEmpty()) { break; } excelWriter.write(pageResult.getRecords(), EasyExcel.writerSheet("健康报表").build()); pageNo++; } excelWriter.finish(); }
6. 扩展开发建议
- 微信消息模板推送:集成公众号API实现自动提醒
- 人脸识别打卡:配合USB摄像头实现人证核验
- 疫情预测模型:基于历史数据训练LSTM神经网络
- 移动端适配:使用Uniapp打包跨平台应用
这套系统在实际运行中平均每天处理2.3万次健康申报,峰值QPS达到158。最大的收获是认识到技术架构需要为业务场景量身定制——比如我们为留学生宿舍单独增加了多语言支持和时区转换功能。如果重新设计,我会考虑引入Elasticsearch来处理更复杂的统计分析需求。