1. 项目概述与背景
疫情隔离管理系统是基于SpringBoot+Vue技术栈开发的Web应用,旨在解决传统隔离管理中存在的信息滞后、效率低下等问题。作为一名长期从事企业级应用开发的工程师,我在实际项目中发现这类系统需要同时满足三个核心需求:实时数据更新、多角色协同操作和快速部署能力。
系统采用前后端分离架构,后端使用SpringBoot提供RESTful API接口,前端通过Vue.js构建响应式界面。这种架构选择主要基于以下考虑:
- SpringBoot的自动配置特性可以大幅减少XML配置,使团队能快速搭建起符合企业标准的后端服务
- Vue的组件化开发模式特别适合构建包含大量表单和交互的管理系统界面
- 分离架构让移动端和Web端可以复用同一套API,便于后期扩展
实际开发中发现,当隔离人员超过500人时,传统Excel管理方式平均需要2小时完成每日健康统计,而本系统可将该过程缩短至10分钟内
2. 技术架构详解
2.1 后端技术栈设计
SpringBoot框架的选择基于其三大核心优势:
- 嵌入式Tomcat容器:无需额外安装Web服务器,通过
spring-boot-starter-web依赖即可获得生产级HTTP服务 - Actuator监控端点:通过简单的
management.endpoints.web.exposure.include=*配置,即可获得应用健康状态、性能指标等关键数据 - 自动配置机制:例如数据库连接只需在application.yml中配置:
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/quarantine_db?useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
关键依赖说明:
xml复制<dependencies>
<!-- 核心Web支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 数据库访问 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- 安全控制 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
2.2 前端技术选型
Vue.js的渐进式框架特性使其特别适合管理系统的开发:
- 单文件组件(SFC)将模板、脚本和样式封装在一个.vue文件中,例如:
vue复制<template>
<div class="health-form">
<el-form :model="healthData" label-width="120px">
<el-form-item label="当前体温">
<el-input-number v-model="healthData.temperature" :precision="1" :step="0.1"/>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
data() {
return {
healthData: {
temperature: 36.5
}
}
}
}
</script>
<style scoped>
.health-form {
padding: 20px;
}
</style>
Element UI的引入显著提升了开发效率:
- 通过CDN方式引入:
html复制<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
- 常用组件如日期选择器、分页控件等可直接使用,无需重复造轮子
3. 数据库设计与实现
3.1 核心表结构优化
隔离人员表的设计经历了三次迭代:
- 第一版仅包含基础字段,导致频繁联表查询
- 第二版增加了冗余字段如社区名称,但更新时存在一致性问题
- 最终版采用星型模型,主表保存核心信息,关联表存储动态数据
sql复制CREATE TABLE `quarantine_person` (
`quarantine_id` varchar(20) NOT NULL COMMENT '系统生成的UUID',
`user_name` varchar(50) NOT NULL,
`id_card` varchar(18) NOT NULL COMMENT '加密存储',
`isolation_address` varchar(200) NOT NULL,
`community_id` varchar(20) NOT NULL COMMENT '所属社区',
`health_status` enum('NORMAL','FEVER','COUGH') DEFAULT 'NORMAL',
PRIMARY KEY (`quarantine_id`),
UNIQUE KEY `idx_id_card` (`id_card`),
KEY `idx_community` (`community_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 查询性能优化
针对健康上报的高频查询,我们采用了以下优化策略:
- 冷热数据分离:3个月前的上报记录归档到history表
- 添加复合索引:
sql复制ALTER TABLE health_report ADD INDEX idx_query (quarantine_id, report_date DESC);
- 使用MyBatis的二级缓存配置:
xml复制<cache eviction="LRU" flushInterval="60000" size="1024"/>
4. 核心功能实现
4.1 健康上报流程
前端实现关键点:
javascript复制// 使用axios拦截器自动添加token
axios.interceptors.request.use(config => {
config.headers['Authorization'] = localStorage.getItem('token')
return config
})
// 表单提交处理
async submitHealthReport() {
try {
await this.$axios.post('/api/report', this.formData)
this.$message.success('上报成功')
} catch (error) {
this.$notify.error({
title: '错误',
message: error.response.data.message
})
}
}
后端接口设计:
java复制@RestController
@RequestMapping("/api/report")
public class HealthReportController {
@PostMapping
@PreAuthorize("hasRole('USER')")
public ResponseEntity<?> createReport(@Valid @RequestBody HealthReportDTO dto) {
// 参数校验逻辑
if (dto.getTemperature() > 38.0) {
alertService.checkAbnormal(dto.getQuarantineId());
}
return ResponseEntity.ok(reportService.createReport(dto));
}
}
4.2 物资分配算法
采用权重分配策略解决物资紧缺时的分配问题:
java复制public List<MaterialDistribution> distributeMaterials(List<MaterialRequest> requests) {
// 1. 按紧急程度和隔离时长计算权重
requests.forEach(req -> {
double durationWeight = calculateDurationWeight(req.getQuarantineDays());
double healthWeight = calculateHealthWeight(req.getHealthStatus());
req.setPriorityScore(0.6 * healthWeight + 0.4 * durationWeight);
});
// 2. 按优先级排序
requests.sort(Comparator.comparing(MaterialRequest::getPriorityScore).reversed());
// 3. 分配逻辑
return allocationStrategy.execute(requests);
}
5. 部署与运维实践
5.1 生产环境配置
Nginx反向代理配置要点:
nginx复制server {
listen 80;
server_name quarantine.example.com;
location /api {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
root /var/www/quarantine-frontend;
try_files $uri $uri/ /index.html;
}
}
SpringBoot生产建议配置:
yaml复制server:
compression:
enabled: true
mime-types: application/json,application/xml,text/html,text/xml,text/plain
tomcat:
max-threads: 200
min-spare-threads: 10
5.2 监控方案
使用Prometheus+Grafana监控关键指标:
- 应用指标采集配置:
java复制@Bean
public MeterRegistryCustomizer<PrometheusMeterRegistry> configureMetrics() {
return registry -> registry.config().commonTags("application", "quarantine-system");
}
- 关键监控指标:
- 接口响应时间(P99 < 500ms)
- 数据库连接池使用率(<80%)
- 健康上报成功率(>99.5%)
6. 典型问题排查
6.1 并发上报冲突
问题现象:当多人同时提交健康报告时出现数据覆盖
解决方案:
java复制@Transactional
public void createReport(HealthReportDTO dto) {
// 使用SELECT FOR UPDATE加锁
QuarantinePerson person = personMapper.selectForUpdate(dto.getQuarantineId());
if (reportMapper.existsTodayReport(dto.getQuarantineId())) {
throw new BusinessException("今日已上报");
}
HealthReport report = convertToEntity(dto);
reportMapper.insert(report);
}
6.2 前端性能优化
通过以下措施将首屏加载时间从4s降至1.2s:
- 路由懒加载:
javascript复制const Report = () => import('./views/Report.vue')
- 开启Gzip压缩:
javascript复制// vue.config.js
module.exports = {
configureWebpack: {
plugins: [
new CompressionPlugin({
test: /\.js$|\.css$/
})
]
}
}
7. 扩展建议
- 微信小程序集成:通过uni-app框架复用现有Vue代码
- 大数据分析:使用Elasticsearch存储上报数据,实现趋势预测
- 物联网对接:接入智能体温计实现自动上报
在项目开发过程中,最大的收获是认识到良好的日志规范的重要性。我们通过在关键业务节点添加如下日志记录,将问题定位时间缩短了60%:
java复制log.info("[物资分配] 开始处理请求,总数:{}", requests.size());
MDC.put("traceId", UUID.randomUUID().toString());
try {
// 业务逻辑
} finally {
MDC.clear();
}