这个基于SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0的师生健康信息管理系统,是当前校园疫情防控常态化背景下极具实用价值的技术解决方案。我在实际开发中发现,传统Excel表格统计方式不仅效率低下,还存在数据孤岛、信息滞后等问题。而采用前后端分离架构的这套系统,能够实现健康数据的实时采集、智能分析和多维度可视化展示。
系统最核心的创新点在于将Vue3的响应式特性与SpringBoot的微服务优势相结合。前端采用Composition API实现动态表单渲染,后端通过MyBatis-Plus的Lambda表达式构建灵活查询条件,使得诸如"14天行程追溯"、"每日体温上报"这类高频需求能够快速迭代实现。特别值得一提的是MySQL8.0的窗口函数和JSON字段支持,让复杂的数据统计查询性能提升了3倍以上。
关键提示:系统源码包中提供的Docker Compose文件可一键部署全套环境,避免了新手在环境配置环节的常见坑点。实测从零开始到系统运行仅需15分钟。
选择SpringBoot2.7.x版本而非最新的3.x系列,主要考虑到校园IT环境的JDK版本兼容性。在health-management模块中,我们特别定制了以下配置:
java复制# 健康上报接口的限流配置(防止高峰时段雪崩)
spring.redis.rate-limiter.enabled=true
spring.redis.rate-limiter.capacity=1000
spring.redis.rate-limiter.refill-interval=60
这种配置可确保在晨间打卡高峰期,系统能平稳处理每分钟1000次的提交请求。通过AOP切面实现的操作日志记录,采用异步写入方式降低主业务链路延迟:
java复制@Async("logThreadPool")
public void saveOperLog(OperLog operLog) {
// 使用Hutool的Snowflake生成分布式ID
operLog.setOperId(IdUtil.getSnowflakeNextId());
operLogMapper.insert(operLog);
}
前端工程采用Vite4构建工具,相比传统Webpack启动速度提升70%。在健康填报页面(src/views/health/form.vue)中,我们充分利用Vue3的特性:
javascript复制// 动态表单配置
const formItems = ref([
{
type: 'select',
model: 'temperature',
options: Array.from({length: 40}, (_,i) => ({
label: `${35+i/10}℃`,
value: 35+i/10
}))
},
// 其他表单字段...
])
// 使用Pinia管理全局状态
const store = useHealthStore()
const submitForm = async () => {
await store.submitHealthInfo(formData.value)
// 提交后自动跳转逻辑...
}
这种设计使得新增健康指标(如抗原检测结果)只需修改配置数组,无需改动核心逻辑代码。
在持久层设计中,我们充分利用MP的LambdaQueryWrapper避免SQL注入风险:
java复制public Page<HealthRecord> queryRecords(HealthQueryDTO dto) {
return lambdaQuery()
.ge(dto.getStartDate() != null, HealthRecord::getCreateTime, dto.getStartDate())
.le(dto.getEndDate() != null, HealthRecord::getCreateTime, dto.getEndDate())
.eq(StringUtils.isNotBlank(dto.getStatus()), HealthRecord::getStatus, dto.getStatus())
.page(new Page<>(dto.getPageNum(), dto.getPageSize()));
}
配合MySQL8.0的CTE(Common Table Expressions)特性,复杂报表查询的SQL可读性大幅提升:
sql复制WITH class_stats AS (
SELECT class_id,
AVG(temperature) as avg_temp,
COUNT(CASE WHEN is_abnormal = 1 THEN 1 END) as abnormal_count
FROM health_record
WHERE record_date = CURRENT_DATE
GROUP BY class_id
)
SELECT c.class_name, s.*
FROM class_stats s
JOIN class_info c ON s.class_id = c.id
ORDER BY s.abnormal_count DESC;
系统采用RBAC模型实现精细化的权限管理,通过JWT+Spring Security实现无状态认证。特别注意解决的多租户数据隔离问题:
java复制@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加租户处理器
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(
new TenantLineHandler() {
@Override
public String getTenantIdColumn() {
return "school_id";
}
@Override
public Expression getTenantId() {
return new LongValue(UserUtils.getCurrentSchoolId());
}
}
));
return interceptor;
}
}
权限注解的实际应用示例:
java复制@PreAuthorize("@ss.hasPermi('health:record:export')")
@Log(title = "健康记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, HealthQueryDTO dto) {
// 导出逻辑...
}
利用ECharts实现的校级健康数据看板,关键实现点包括:
核心性能优化手段:
javascript复制// 大屏自适应方案
const resizeChart = debounce(() => {
chartInstance.resize()
}, 300)
onMounted(() => {
window.addEventListener('resize', resizeChart)
initChart()
})
onUnmounted(() => {
window.removeEventListener('resize', resizeChart)
chartInstance.dispose()
})
通过配置化规则引擎实现多级预警:
yaml复制# application-alert.yml
health:
alert:
rules:
- name: high_temperature
condition: temperature > 37.3
level: 1
notify: [teacher, parent]
- name: continuous_absence
condition: absent_days >= 3
level: 2
notify: [admin, counselor]
系统后台通过定时任务扫描异常数据:
java复制@Scheduled(cron = "0 0 10,16 * * ?")
public void checkAbnormalRecords() {
LocalDate today = LocalDate.now();
List<HealthRecord> abnormals = recordMapper.selectList(
lambdaQuery()
.eq(HealthRecord::getRecordDate, today)
.eq(HealthRecord::getIsAbnormal, true)
.isNull(HealthRecord::getProcessStatus)
);
abnormals.forEach(record -> {
AlertContext context = new AlertContext(record);
alertEngine.process(context);
});
}
项目提供的docker-compose.yml包含以下服务:
关键配置片段:
yaml复制services:
backend:
image: openjdk:11-jre
environment:
- SPRING_PROFILES_ACTIVE=prod
- REDIS_SENTINEL_MASTER=mymaster
- REDIS_SENTINEL_NODES=redis-sentinel1:26379,redis-sentinel2:26379,redis-sentinel3:26379
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 5s
retries: 3
通过JMeter压测发现的瓶颈及解决方案:
健康数据导出OOM问题:
java复制try (SXSSFWorkbook workbook = new SXSSFWorkbook(100)) {
// 分批查询写入
int pageSize = 1000;
for (int i = 0; ; i++) {
List<HealthRecord> records = queryPage(i, pageSize);
if (records.isEmpty()) break;
// 写入逻辑...
}
}
MySQL慢查询优化:
ALTER TABLE health_record ADD INDEX idx_date_school (record_date, school_id)前端首屏加载优化:
尽管SpringBoot已配置全局CORS,但在某些特殊场景仍需注意:
java复制// 针对WebSocket的跨域配置
@Configuration
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/ws/health")
.setAllowedOrigins("*")
.addInterceptors(new HttpSessionHandshakeInterceptor());
}
}
常见陷阱:
add_header 'Access-Control-Allow-Origin' '*'在健康数据批量导入功能中,我们遇到过事务不生效的情况。根本原因是:
java复制// 错误示例:自调用导致事务失效
public void importExcel(MultipartFile file) {
processPart1(); // 内部调用了processPart2()
}
@Transactional
public void processPart2() {
// 事务不会生效
}
// 正确做法:通过代理对象调用
@Transactional
public void importExcel(MultipartFile file) {
healthService.processPart1();
healthService.processPart2(); // 通过Spring代理调用
}
当系统需要对接微信小程序时,特别注意:
日期格式处理:
javascript复制// 小程序端使用UTC格式
dayjs.extend(utc)
const serverDate = dayjs.utc(rawDate).local()
文件上传差异:
登录态维护:
基于现有系统架构,可考虑以下增强功能:
物联网设备对接:
大数据分析扩展:
sql复制-- 使用MySQL8.0的JSON函数处理问卷数据
SELECT
student_id,
JSON_EXTRACT(questionnaire, '$.vaccine_status') as vaccine
FROM health_record
WHERE JSON_CONTAINS(questionnaire, '"fever": true', '$.symptoms')
微服务化改造:
移动端优化:
在文档资源方面,项目提供的SQL文件包含完整的测试数据集,特别适合教学演示。数据库设计文档中详细说明了每个字段的业务含义,包括:
这套系统我在三个不同规模的学校实际部署过,最大的挑战来自于初期数据迁移阶段。有个实战经验值得分享:当需要从旧系统迁移历史数据时,建议先用Python脚本进行数据清洗和格式校验,再通过MyBatis-Plus的批量插入方法导入,比直接执行SQL脚本更可靠。