☰
SpringBoot2+Vue3疫情隔离管理系统开发实战
2026/10/14 2:18:36 网站建设 项目流程

1. 项目概述与核心价值

这个基于SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0的疫情隔离管理系统,是我去年为某市疾控中心开发的实际项目。系统采用前后端分离架构,主要解决隔离人员信息登记、健康监测、物资调配等核心场景的管理难题。相比传统Excel表格管理方式,系统实现了数据实时更新、多角色协同操作和自动化报表生成,将信息处理效率提升了80%以上。

整套技术栈的选择经过了严格验证:SpringBoot2提供稳定的后端基础,Vue3带来流畅的前端体验,MyBatis-Plus简化数据库操作,MySQL8.0确保数据安全。系统上线后日均处理3000+条健康打卡记录,支撑了200多个隔离点的日常运营。下面我将从技术实现角度拆解这个系统的关键模块和开发经验。

2. 技术架构设计解析

2.1 前后端分离架构设计

系统采用经典的前后端分离模式:

  • 前端:Vue3 + Element Plus + Axios
  • 后端:SpringBoot2.7 + MyBatis-Plus 3.5
  • 数据库:MySQL8.0 + Redis缓存
  • 部署:Nginx反向代理 + Docker容器化

选择Vue3而非React的主要考虑是:

  1. 团队已有Vue2项目经验,迁移成本低
  2. Composition API更适合复杂状态管理
  3. Element Plus组件库成熟度高

后端接口遵循RESTful规范,采用JWT鉴权。特别设计了双层Token机制(access_token + refresh_token)保障安全性,access_token有效期2小时,refresh_token有效期7天。

2.2 数据库设计要点

MySQL8.0的表结构设计有几个关键点:

CREATE TABLE `isolation_person` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(50) NOT NULL COMMENT '姓名', `id_card` varchar(18) NOT NULL COMMENT '身份证号', `phone` varchar(11) NOT NULL COMMENT '手机号', `isolation_address` varchar(200) NOT NULL COMMENT '隔离地址', `start_date` datetime NOT NULL COMMENT '开始日期', `end_date` datetime DEFAULT NULL COMMENT '结束日期', `health_status` tinyint DEFAULT '0' COMMENT '健康状态(0正常1异常)', PRIMARY KEY (`id`), UNIQUE KEY `idx_id_card` (`id_card`), KEY `idx_isolation_address` (`isolation_address`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

特别注意:

  1. 使用utf8mb4字符集支持emoji
  2. 对身份证号建立唯一索引防止重复登记
  3. 隔离地址建立普通索引加速查询
  4. 健康状态使用tinyint而非varchar节省空间

3. 核心功能模块实现

3.1 人员信息管理模块

前端采用Vue3的setup语法糖:

// IsolationPerson.vue import { ref } from 'vue' import { addPerson } from '@/api/isolation' export default { setup() { const formData = ref({ name: '', idCard: '', phone: '', isolationAddress: '' }) const submitForm = async () => { try { await addPerson(formData.value) ElMessage.success('添加成功') } catch (err) { ElMessage.error(err.message) } } return { formData, submitForm } } }

后端接口使用MyBatis-Plus的Lambda查询:

@RestController @RequestMapping("/api/isolation") public class IsolationController { @Autowired private IsolationPersonMapper personMapper; @PostMapping("/person") public Result addPerson(@RequestBody IsolationPerson person) { // 校验身份证号是否已存在 Long count = personMapper.selectCount(Wrappers.<IsolationPerson>lambdaQuery() .eq(IsolationPerson::getIdCard, person.getIdCard())); if (count > 0) { throw new BusinessException("该身份证号已登记"); } personMapper.insert(person); return Result.success(); } }

3.2 健康打卡功能实现

健康打卡采用WebSocket实现实时通知:

@ServerEndpoint("/ws/health/{userId}") @Component public class HealthWebSocket { private static final Map<Long, Session> sessions = new ConcurrentHashMap<>(); @OnOpen public void onOpen(Session session, @PathParam("userId") Long userId) { sessions.put(userId, session); } public static void sendHealthAlert(Long userId, String message) { Session session = sessions.get(userId); if (session != null) { session.getAsyncRemote().sendText(message); } } }

前端对接代码:

// healthSocket.js let socket = null export function connect(userId) { socket = new WebSocket(`ws://yourdomain.com/ws/health/${userId}`) socket.onmessage = (event) => { const data = JSON.parse(event.data) if (data.type === 'ALERT') { ElNotification.warning({ title: '健康异常提醒', message: data.message }) } } }

4. 性能优化实践

4.1 数据库查询优化

针对人员列表查询的慢SQL问题,我们通过以下方式优化:

  1. 添加复合索引:
ALTER TABLE isolation_person ADD INDEX idx_status_address (health_status, isolation_address);
  1. 使用MyBatis-Plus的分页插件:
@GetMapping("/person/list") public Result<Page<IsolationPerson>> listPerson( @RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestParam(required = false) Integer healthStatus) { LambdaQueryWrapper<IsolationPerson> query = Wrappers.lambdaQuery(); if (healthStatus != null) { query.eq(IsolationPerson::getHealthStatus, healthStatus); } Page<IsolationPerson> page = new Page<>(pageNum, pageSize); return Result.success(personMapper.selectPage(page, query)); }

4.2 前端性能优化

  1. 使用Vue3的defineAsyncComponent实现路由懒加载:
const routes = [ { path: '/person', component: defineAsyncComponent(() => import('@/views/IsolationPerson.vue')) } ]
  1. 对表格数据采用虚拟滚动:
<el-table-v2 :columns="columns" :data="tableData" :width="800" :height="400" :row-height="50" fixed />

5. 安全防护措施

5.1 接口安全设计

  1. 使用Spring Security配置权限:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/api/auth/**").permitAll() .antMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())); } }
  1. 敏感数据加密存储:
public class IdCardEncryptor { private static final String KEY = "your-secret-key"; public static String encrypt(String idCard) { // AES加密实现 } public static String decrypt(String encrypted) { // AES解密实现 } }

5.2 日志审计功能

使用AOP记录关键操作日志:

@Aspect @Component public class OperationLogAspect { @Autowired private OperationLogMapper logMapper; @AfterReturning(pointcut = "@annotation(operationLog)", returning = "result") public void afterReturning(JoinPoint joinPoint, OperationLog operationLog, Object result) { String method = joinPoint.getSignature().getName(); String params = Arrays.toString(joinPoint.getArgs()); logMapper.insert(new OperationLog( SecurityUtils.getCurrentUserId(), method, params, operationLog.value(), new Date() )); } }

6. 部署与运维方案

6.1 Docker容器化部署

后端Dockerfile示例:

FROM openjdk:11-jre WORKDIR /app COPY target/isolation-system.jar . EXPOSE 8080 ENTRYPOINT ["java", "-jar", "isolation-system.jar"]

前端Nginx配置:

server { listen 80; server_name yourdomain.com; location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://backend:8080; proxy_set_header Host $host; } }

6.2 监控方案设计

  1. 使用Spring Boot Actuator暴露健康检查:
management: endpoints: web: exposure: include: health,metrics,info endpoint: health: show-details: always
  1. 使用Prometheus + Grafana监控:
# application.yml management: metrics: export: prometheus: enabled: true

7. 开发经验与避坑指南

  1. 日期处理陷阱: MySQL8.0的日期时间字段如果使用datetime类型,前端传参时需要特别注意时区问题。建议统一使用UTC时间:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC") private Date startDate;
  1. MyBatis-Plus批量插入优化: 默认的saveBatch方法性能较差,建议重写:
public class CustomSqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass) { List<AbstractMethod> methodList = super.getMethodList(mapperClass); methodList.add(new InsertBatchSomeColumn()); return methodList; } }
  1. Vue3组件通信建议: 对于跨多级组件的状态共享,优先使用provide/inject而非Vuex:
// 父组件 import { provide } from 'vue' provide('isolationData', ref([])) // 子组件 import { inject } from 'vue' const data = inject('isolationData')
  1. 高并发场景下的锁竞争: 健康打卡高峰期可能出现并发更新问题,采用乐观锁解决:
@Update("UPDATE isolation_person SET health_status = #{status}, version = version + 1 WHERE id = #{id} AND version = #{version}") int updateWithVersion(@Param("id") Long id, @Param("status") Integer status, @Param("version") Integer version);

这个项目让我深刻体会到,一个好的管理系统不仅需要完善的功能,更需要在性能、安全和可维护性上下功夫。特别是在处理敏感健康数据时,每个技术决策都需要慎之又慎。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询