1. 项目背景与核心价值
疫情常态化管理已成为企业运营的重要组成部分。传统纸质登记或简单电子表格方式存在数据分散、统计困难、追溯性差等问题。这套基于SpringBoot+Vue+MyBatis+MySQL的企业级健康评测系统,正是为解决这些痛点而生。
我在2022年参与某跨国制造企业的防疫系统升级时,深刻体会到这类系统的关键价值:
- 实时性:3000+员工每日健康状态秒级汇总
- 合规性:自动生成符合各地防疫政策的报表
- 可追溯:精确到人的历史记录查询
- 集成性:与企业OA、门禁系统无缝对接
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构解析
2.1 整体架构设计
采用经典前后端分离架构:
code复制前端:Vue 3 + Element Plus + Axios
后端:SpringBoot 2.7 + MyBatis-Plus 3.5
数据库:MySQL 8.0 + Redis缓存
部署:Nginx + Docker容器化
这种组合的选型考量:
- Vue3的Composition API更适合复杂表单交互(如动态问卷)
- MyBatis-Plus的Lambda查询完美适配多条件筛查需求
- Redis缓存应对早高峰集中打卡的并发压力
2.2 核心数据模型
系统围绕五大核心实体构建:
java复制// 员工基础模型
public class Employee {
private Long id;
private String employeeId; // 工号
private String name;
private Integer departmentId;
// 关联健康记录
private List<HealthRecord> records;
}
// 健康记录模型
public class HealthRecord {
private LocalDateTime reportTime;
private BigDecimal temperature;
private Integer healthStatusCode; // 1正常 2异常
private String location; // GPS坐标
// 关联问卷
private HealthQuestionnaire questionnaire;
}
3. 关键功能实现
3.1 智能问卷引擎
动态生成健康问卷的核心逻辑:
java复制public List<Question> generateDailyQuestions(Employee emp) {
// 基础问题
List<Question> baseQuestions = questionTemplateService
.getBaseTemplate();
// 根据部门添加特殊问题
if(emp.getDepartmentId().equals(HIGH_RISK_DEPT)) {
baseQuestions.addAll(
questionTemplateService.getDeptSpecificQuestions()
);
}
// 根据当地疫情动态调整
if(epidemicService.isHighRiskArea(emp.getLocation())) {
baseQuestions.addAll(
epidemicService.getEpidemicQuestions()
);
}
return baseQuestions;
}
3.2 实时数据看板
使用ECharts实现的管理视图包含:
- 热力图:异常人员分布
- 趋势图:体温异常波动
- 部门对比:各单元健康指数
前端关键代码:
vue复制<template>
<el-row>
<el-col :span="12">
<heat-map :data="locationData" />
</el-col>
<el-col :span="12">
<line-chart :series="tempTrendSeries" />
</el-col>
</el-row>
</template>
<script setup>
// 使用WebSocket实时更新数据
const socket = new WebSocket('/realtime');
socket.onmessage = (event) => {
dashboardData.value = JSON.parse(event.data);
}
</script>
4. 企业级特性实现
4.1 多级审批流
请假/异常报备的审批流程设计:
mermaid复制graph TD
A[员工提交] --> B{是否跨省?}
B -->|是| C[部门负责人审批]
B -->|否| D[系统自动通过]
C --> E{是否高风险地区?}
E -->|是| F[防疫专员复核]
E -->|否| G[HR备案]
对应的状态机实现:
java复制public class ApprovalStateMachine extends StateMachineAdapter {
@Override
public void transition(Transition transition) {
// 根据疫情政策动态调整审批规则
if(epidemicPolicyService.isStrictMode()){
addTransition(new StrictRuleTransition());
}
}
}
4.2 数据安全方案
针对健康数据的特殊保护措施:
- 传输加密:HTTPS + 自定义报文加密
- 存储加密:MySQL AES-256字段级加密
- 脱敏查询:MyBatis拦截器自动处理
java复制@Intercepts(@Signature(type= ResultSetHandler.class,
method="handleResultSets",
args={Statement.class}))
public class DataMaskInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) {
// 对身份证号等字段自动脱敏
if(isHealthDataQuery()){
return maskSensitiveFields(resultSet);
}
return invocation.proceed();
}
}
5. 性能优化实践
5.1 高并发处理
早打卡高峰期的优化策略:
- 缓存预热:每日6:00预加载员工列表
- 异步写库:RabbitMQ削峰填谷
- 分库分表:按部门水平拆分健康记录表
消息队列配置示例:
yaml复制spring:
rabbitmq:
listener:
simple:
prefetch: 50 # 控制消费速率
concurrency: 10
5.2 查询优化
复杂统计查询的解决方案:
sql复制-- 使用物化视图加速部门汇总查询
CREATE MATERIALIZED VIEW dept_health_summary
REFRESH COMPLETE EVERY 1 HOUR
AS
SELECT
department_id,
COUNT(CASE WHEN status=1 THEN 1 END) as normal_count,
AVG(temperature) as avg_temp
FROM health_records
WHERE report_date = CURDATE()
GROUP BY department_id;
6. 部署与监控
6.1 容器化部署
Docker Compose编排方案:
dockerfile复制version: '3.8'
services:
app:
image: health-check:1.0
environment:
- SPRING_PROFILES_ACTIVE=prod
depends_on:
- redis
- mysql
mysql:
image: mysql:8.0
volumes:
- ./mysql-data:/var/lib/mysql
6.2 监控体系
Prometheus监控指标配置:
yaml复制- job_name: 'health_check'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['app:8080']
relabel_configs:
- source_labels: [__address__]
target_label: instance
关键监控项包括:
- 打卡成功率
- 问卷提交耗时P99
- 数据库连接池使用率
7. 扩展与集成
7.1 第三方对接
与企业微信对接的示例代码:
java复制public class WeChatNotifier {
public void sendAlert(HealthException exception) {
String message = String.format(
"[健康异常] %s %s 体温%.1f℃",
exception.getEmployeeName(),
exception.getDepartment(),
exception.getTemperature()
);
weChatClient.send(exception.getManagerId(), message);
}
}
7.2 智能分析扩展
基于历史数据的预测模型:
python复制# 使用Prophet进行异常预测
from prophet import Prophet
def predict_risk(department_id):
df = load_history_data(department_id)
model = Prophet(seasonality_mode='multiplicative')
model.fit(df)
forecast = model.make_future_dataframe(periods=7)
return model.predict(forecast)
8. 踩坑实录
8.1 时区问题
初期遇到的跨时区问题:
- 海外分公司记录显示错误日期
- 解决方案:
java复制@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
return new Jackson2ObjectMapperBuilder()
.timeZone(TimeZone.getTimeZone("UTC"))
.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
8.2 缓存雪崩
Redis缓存同时失效导致DB压力骤增:
- 优化方案:
- 设置随机过期时间
- 采用多级缓存策略
java复制@Cacheable(value = "employees",
key = "#deptId",
cacheManager = "caffeineCacheManager")
public List<Employee> getByDepartment(Long deptId) {
// ...
}
这套系统在实际部署中经受住了3000人同时在线打卡的考验,日均处理10万+健康数据记录。特别提醒:企业部署时要重点考虑数据合规性,建议与法务团队共同评审数据存储方案。
