毕业设计实战:基于Spring Boot的新冠病毒密接者跟踪系统全栈开发

40 阅读12分钟

一、项目背景:疫情防控数字化的必然趋势

在新冠疫情常态化防控背景下,传统流行病学调查面临着信息收集慢、轨迹追溯难、管理效率低三大核心痛点。据疫情防控统计显示,2023年仍有超过50%的地区采用纸质登记和人工排查方式,导致密接者信息更新不及时、轨迹追溯不准确、资源分配不合理,而防疫人员也缺乏系统化的信息管理工具。

为破解这一困境,基于Spring Boot的新冠病毒密接者跟踪系统应运而生。系统以"信息实时化、追溯精准化、管理智能化"为核心目标,采用B/S架构构建一体化疫情防控管理平台,整合用户轨迹管理、核酸检测管理、疫苗预约管理、口罩预订管理等核心功能,建立"管理员统筹-用户参与"的双层应用模式,推动疫情防控从"传统人工式"向"数字化、智能化、精准化"转型。

二、技术架构:疫情防控系统的全栈技术选型

项目围绕"稳定性优先、安全性强、响应快"三大原则,选用成熟且贴合疫情防控需求的技术栈:

技术模块具体工具/技术核心作用
后端框架Spring Boot 2.x快速构建高效API接口,处理疫情防控核心业务逻辑
前端技术前端框架 + 模板引擎构建清晰直观的管理界面,适配多角色操作
数据库MySQL 8.0安全存储用户信息、轨迹数据、检测记录等敏感数据
开发工具Eclipse集成开发环境,提高开发效率
安全框架Spring Security保障系统数据安全,防止信息泄露
服务器Tomcat轻量级应用服务器,支持快速部署

三、项目全流程:6步完成疫情防控系统开发

3.1 第一步:需求分析——明确系统核心价值

针对传统疫情防控的"效率低、精度差"痛点,系统聚焦"轨迹精准记录、检测及时跟踪、资源合理分配",明确双角色的核心需求:

3.1.1 功能性需求

  1. 双角色权限体系

    • 管理员:字典管理、地点管理、公告信息管理、用户轨迹管理、核酸检测管理、口罩管理、口罩预订管理、医护人员管理、疫苗管理、疫苗预约管理、用户管理;
    • 用户:个人信息维护、轨迹上报、核酸检测查询、疫苗预约、口罩预订、公告查看。
  2. 核心业务功能

    • 用户轨迹全生命周期管理:从轨迹记录、地点关联到风险分析;
    • 核酸检测闭环管理:检测安排→结果录入→状态跟踪→统计分析;
    • 疫苗预约流程:疫苗信息发布→用户预约→接种安排→记录归档;
    • 防疫物资管理:口罩库存管理、预订分配、发放跟踪;
    • 信息发布系统:疫情公告、政策通知、防控指南。

3.1.2 非功能性需求

  • 系统性能:支持1000+用户同时使用,关键操作响应时间<1秒;
  • 数据安全:敏感信息加密存储,严格的权限控制机制;
  • 可靠性:7×24小时稳定运行,关键数据多重备份;
  • 易用性:界面简洁明了,操作流程简单直观。

3.2 第二步:系统设计——构建整体架构

系统采用分层设计思想,确保各模块职责清晰、可维护性强:

3.2.1 系统总体架构

  1. 前端架构

    • 基于响应式设计,适配不同设备访问;
    • 组件化开发,提高代码复用性;
    • 实时数据更新,提升用户体验。
  2. 后端架构

    • 基于Spring Boot实现RESTful API;
    • 统一异常处理机制,提供友好错误提示;
    • 接口权限验证,保障系统安全。
  3. 数据持久层

    • MyBatis实现数据库操作,SQL优化;
    • 数据库事务管理,保证数据一致性;
    • 敏感数据加密存储。

3.2.2 核心数据库设计

系统设计12张核心数据表,覆盖疫情防控全业务场景:

表名核心字段作用
用户表(user)id、yonghu_name、yonghu_phone、jiankang_types存储用户基本信息和健康状态
地点表(location)id、didian_name、didian_types存储风险地点信息
用户轨迹表(user_track)id、yonghu_id、didian_id、guiji_time记录用户行程轨迹
核酸检测表(nucleic_test)id、yonghu_id、jiance_types、jiance_time管理核酸检测记录
疫苗表(vaccine)id、yimiao_name、yimiao_types、yimiao_number存储疫苗库存信息
疫苗预约表(vaccine_appointment)id、yonghu_id、yimiao_id、yimiaoyuyue_types管理疫苗预约流程
口罩表(mask)id、kouzhao_name、kouzhao_types、kouzhao_number管理口罩库存信息
口罩预订表(mask_booking)id、yonghu_id、kouzhao_id、yueding_number管理口罩预订分配
医护人员表(medical_staff)id、yihu_name、yihu_phone、yihu_id_number存储医护人员信息
公告信息表(announcement)id、gonggao_name、gonggao_types、gonggao_content存储系统公告
字典表(dictionary)id、dic_code、dic_name、code_index管理系统字典数据
管理员表(admin)id、username、password、role存储管理员账号信息

3.3 第三步:后端核心功能实现——Spring Boot架构

基于Spring Boot框架实现系统核心业务逻辑,重点突破"轨迹管理""检测跟踪""资源分配"三大核心场景:

3.3.1 用户轨迹管理功能实现

@RestController
@RequestMapping("/api/track")
public class TrackController {
    
    @Autowired
    private TrackService trackService;
    
    /**
     * 记录用户轨迹
     */
    @PostMapping("/record")
    public ResponseEntity<?> recordTrack(@RequestBody TrackRecordDTO trackDTO,
                                        @RequestHeader("userId") Long userId) {
        try {
            // 参数校验
            if (trackDTO.getDidianId() == null || trackDTO.getGuijiTime() == null) {
                return ResponseEntity.badRequest().body("地点ID、轨迹时间不能为空");
            }
            
            // 记录轨迹
            UserTrack track = trackService.recordTrack(trackDTO, userId);
            return ResponseEntity.ok("轨迹记录成功");
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("轨迹记录失败:" + e.getMessage());
        }
    }
    
    /**
     * 获取用户轨迹历史
     */
    @GetMapping("/history")
    public ResponseEntity<?> getTrackHistory(
            @RequestHeader("userId") Long userId,
            @RequestParam String startDate,
            @RequestParam String endDate) {
        try {
            List<UserTrackVO> tracks = trackService.getTrackHistory(userId, startDate, endDate);
            return ResponseEntity.ok(tracks);
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("获取轨迹历史失败:" + e.getMessage());
        }
    }
    
    /**
     * 密接者分析
     */
    @PostMapping("/contact/analysis")
    public ResponseEntity<?> analyzeCloseContacts(@RequestBody ContactAnalysisDTO analysisDTO) {
        try {
            List<CloseContactVO> contacts = trackService.analyzeCloseContacts(analysisDTO);
            return ResponseEntity.ok(contacts);
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("密接者分析失败:" + e.getMessage());
        }
    }
}

@Service
@Transactional
public class TrackServiceImpl implements TrackService {
    
    @Autowired
    private UserTrackMapper trackMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private LocationMapper locationMapper;
    
    @Override
    public UserTrack recordTrack(TrackRecordDTO dto, Long userId) {
        // 1. 验证用户存在
        User user = userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 2. 验证地点存在
        Location location = locationMapper.selectByPrimaryKey(dto.getDidianId());
        if (location == null) {
            throw new RuntimeException("地点不存在");
        }
        
        // 3. 构建轨迹记录
        UserTrack track = new UserTrack();
        track.setYonghuId(userId);
        track.setDidianId(dto.getDidianId());
        track.setGuijiTime(dto.getGuijiTime());
        track.setInsertTime(new Date());
        track.setCreateTime(new Date());
        
        // 4. 保存轨迹记录
        trackMapper.insert(track);
        
        // 5. 更新用户健康状态(如果地点为风险地区)
        if (location.getDidianTypes() == 2) { // 风险地区
            user.setJiankangTypes(2); // 设为风险状态
            userMapper.updateByPrimaryKey(user);
        }
        
        return track;
    }
    
    @Override
    public List<UserTrackVO> getTrackHistory(Long userId, String startDate, String endDate) {
        // 构建查询条件
        UserTrackExample example = new UserTrackExample();
        example.createCriteria()
            .andYonghuIdEqualTo(userId)
            .andGuijiTimeBetween(
                java.sql.Date.valueOf(startDate),
                java.sql.Date.valueOf(endDate)
            );
        example.setOrderByClause("guiji_time DESC");
        
        // 执行查询
        List<UserTrack> tracks = trackMapper.selectByExample(example);
        
        // 转换为VO对象,包含关联信息
        return tracks.stream()
            .map(track -> {
                UserTrackVO vo = new UserTrackVO();
                BeanUtils.copyProperties(track, vo);
                
                // 获取地点信息
                Location location = locationMapper.selectByPrimaryKey(track.getDidianId());
                if (location != null) {
                    vo.setLocationName(location.getDidianName());
                    vo.setLocationType(location.getDidianTypes());
                }
                
                return vo;
            }).collect(Collectors.toList());
    }
    
    @Override
    public List<CloseContactVO> analyzeCloseContacts(ContactAnalysisDTO dto) {
        // 1. 获取确诊用户轨迹
        UserTrackExample example = new UserTrackExample();
        example.createCriteria()
            .andYonghuIdEqualTo(dto.getConfirmedUserId())
            .andGuijiTimeBetween(dto.getStartTime(), dto.getEndTime());
        
        List<UserTrack> confirmedTracks = trackMapper.selectByExample(example);
        
        List<CloseContactVO> closeContacts = new ArrayList<>();
        
        // 2. 分析每个轨迹点的密接者
        for (UserTrack confirmedTrack : confirmedTracks) {
            // 查找同一时间段在同一地点的其他用户
            List<UserTrack> contactTracks = trackMapper.selectCloseContacts(
                confirmedTrack.getDidianId(),
                confirmedTrack.getGuijiTime(),
                dto.getTimeWindow()
            );
            
            // 转换为密接者VO
            for (UserTrack contactTrack : contactTracks) {
                if (!contactTrack.getYonghuId().equals(dto.getConfirmedUserId())) {
                    CloseContactVO contact = new CloseContactVO();
                    contact.setUserId(contactTrack.getYonghuId());
                    contact.setLocationId(contactTrack.getDidianId());
                    contact.setContactTime(contactTrack.getGuijiTime());
                    contact.setRiskLevel(calculateRiskLevel(confirmedTrack, contactTrack));
                    
                    // 获取用户信息
                    User user = userMapper.selectByPrimaryKey(contactTrack.getYonghuId());
                    if (user != null) {
                        contact.setUserName(user.getYonghuName());
                        contact.setUserPhone(user.getYonghuPhone());
                    }
                    
                    closeContacts.add(contact);
                }
            }
        }
        
        return closeContacts;
    }
    
    /**
     * 计算风险等级
     */
    private Integer calculateRiskLevel(UserTrack confirmedTrack, UserTrack contactTrack) {
        long timeDiff = Math.abs(confirmedTrack.getGuijiTime().getTime() - 
                               contactTrack.getGuijiTime().getTime());
        long minutesDiff = timeDiff / (1000 * 60);
        
        if (minutesDiff <= 30) {
            return 1; // 高风险
        } else if (minutesDiff <= 120) {
            return 2; // 中风险
        } else {
            return 3; // 低风险
        }
    }
}

3.3.2 核酸检测管理功能实现

@RestController
@RequestMapping("/api/nucleic")
public class NucleicTestController {
    
    @Autowired
    private NucleicTestService testService;
    
    /**
     * 录入检测结果
     */
    @PostMapping("/result")
    public ResponseEntity<?> recordTestResult(@RequestBody TestResultDTO resultDTO,
                                             @RequestHeader("adminId") Long adminId) {
        try {
            // 参数校验
            if (resultDTO.getYonghuId() == null || resultDTO.getJianceTypes() == null) {
                return ResponseEntity.badRequest().body("用户ID、检测结果不能为空");
            }
            
            // 录入结果
            NucleicTest test = testService.recordTestResult(resultDTO);
            return ResponseEntity.ok("检测结果录入成功");
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("检测结果录入失败:" + e.getMessage());
        }
    }
    
    /**
     * 获取用户检测历史
     */
    @GetMapping("/history")
    public ResponseEntity<?> getTestHistory(
            @RequestParam Long userId,
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size) {
        try {
            PageResult<TestHistoryVO> result = testService.getTestHistory(userId, page, size);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("获取检测历史失败:" + e.getMessage());
        }
    }
    
    /**
     * 统计检测数据
     */
    @GetMapping("/statistics")
    public ResponseEntity<?> getTestStatistics(@RequestParam String date) {
        try {
            TestStatisticsVO statistics = testService.getTestStatistics(date);
            return ResponseEntity.ok(statistics);
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("获取检测统计失败:" + e.getMessage());
        }
    }
}

@Service
@Transactional
public class NucleicTestServiceImpl implements NucleicTestService {
    
    @Autowired
    private NucleicTestMapper testMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Override
    public NucleicTest recordTestResult(TestResultDTO dto) {
        // 1. 验证用户存在
        User user = userMapper.selectByPrimaryKey(dto.getYonghuId());
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 2. 构建检测记录
        NucleicTest test = new NucleicTest();
        test.setYonghuId(dto.getYonghuId());
        test.setJianceTypes(dto.getJianceTypes());
        test.setJianceTime(dto.getJianceTime() != null ? dto.getJianceTime() : new Date());
        test.setInsertTime(new Date());
        test.setCreateTime(new Date());
        
        // 3. 保存检测记录
        testMapper.insert(test);
        
        // 4. 更新用户健康状态
        user.setJiankangTypes(dto.getJianceTypes() == 1 ? 1 : 3); // 1:阴性-健康, 其他:阳性-感染
        userMapper.updateByPrimaryKey(user);
        
        return test;
    }
    
    @Override
    public PageResult<TestHistoryVO> getTestHistory(Long userId, int page, int size) {
        // 分页配置
        PageHelper.startPage(page, size);
        
        // 构建查询条件
        NucleicTestExample example = new NucleicTestExample();
        example.createCriteria().andYonghuIdEqualTo(userId);
        example.setOrderByClause("jiance_time DESC");
        
        // 执行查询
        List<NucleicTest> tests = testMapper.selectByExample(example);
        PageInfo<NucleicTest> pageInfo = new PageInfo<>(tests);
        
        // 转换为VO对象
        List<TestHistoryVO> voList = tests.stream()
            .map(test -> {
                TestHistoryVO vo = new TestHistoryVO();
                BeanUtils.copyProperties(test, vo);
                
                // 获取用户信息
                User user = userMapper.selectByPrimaryKey(test.getYonghuId());
                if (user != null) {
                    vo.setUserName(user.getYonghuName());
                }
                
                return vo;
            }).collect(Collectors.toList());
        
        return new PageResult<>(voList, pageInfo.getTotal());
    }
    
    @Override
    public TestStatisticsVO getTestStatistics(String date) {
        TestStatisticsVO statistics = new TestStatisticsVO();
        statistics.setDate(date);
        
        // 统计总检测数
        NucleicTestExample totalExample = new NucleicTestExample();
        totalExample.createCriteria().andJianceTimeLike(date + "%");
        statistics.setTotalTests(testMapper.countByExample(totalExample));
        
        // 统计阳性数
        NucleicTestExample positiveExample = new NucleicTestExample();
        positiveExample.createCriteria()
            .andJianceTimeLike(date + "%")
            .andJianceTypesEqualTo(2); // 阳性
        statistics.setPositiveTests(testMapper.countByExample(positiveExample));
        
        // 统计阴性数
        NucleicTestExample negativeExample = new NucleicTestExample();
        negativeExample.createCriteria()
            .andJianceTimeLike(date + "%")
            .andJianceTypesEqualTo(1); // 阴性
        statistics.setNegativeTests(testMapper.countByExample(negativeExample));
        
        // 计算阳性率
        if (statistics.getTotalTests() > 0) {
            double positiveRate = (double) statistics.getPositiveTests() / statistics.getTotalTests() * 100;
            statistics.setPositiveRate(Double.parseDouble(String.format("%.2f", positiveRate)));
        }
        
        return statistics;
    }
}

3.3.3 疫苗预约管理功能实现

@RestController
@RequestMapping("/api/vaccine")
public class VaccineController {
    
    @Autowired
    private VaccineService vaccineService;
    
    /**
     * 疫苗预约
     */
    @PostMapping("/appointment")
    public ResponseEntity<?> makeAppointment(@RequestBody AppointmentDTO appointmentDTO,
                                            @RequestHeader("userId") Long userId) {
        try {
            // 参数校验
            if (appointmentDTO.getYimiaoId() == null) {
                return ResponseEntity.badRequest().body("疫苗ID不能为空");
            }
            
            // 执行预约
            VaccineAppointment appointment = vaccineService.makeAppointment(appointmentDTO, userId);
            return ResponseEntity.ok("疫苗预约成功");
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("疫苗预约失败:" + e.getMessage());
        }
    }
    
    /**
     * 获取可预约疫苗列表
     */
    @GetMapping("/available")
    public ResponseEntity<?> getAvailableVaccines() {
        try {
            List<VaccineVO> vaccines = vaccineService.getAvailableVaccines();
            return ResponseEntity.ok(vaccines);
        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                .body("获取疫苗列表失败:" + e.getMessage());
        }
    }
}

3.4 第四步:前端界面实现——疫情防控主题平台

基于现代前端技术构建用户界面,贴合疫情防控系统的"专业、清晰、易用"需求:

3.4.1 核心界面设计

  1. 管理员后台

    • 数据看板:关键指标统计、疫情趋势图表;
    • 轨迹管理:用户轨迹查询、密接者分析;
    • 检测管理:检测结果录入、统计报表;
    • 疫苗管理:库存管理、预约统计;
    • 物资管理:口罩库存、预订分配;
    • 系统管理:用户管理、字典配置;
  2. 用户前端

    • 个人中心:基本信息、健康状态;
    • 轨迹上报:地点选择、时间记录;
    • 检测查询:历史记录、结果查看;
    • 疫苗预约:疫苗选择、时间安排;
    • 物资预订:口罩预订、领取记录;
    • 公告查看:疫情通知、防控指南。

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

3.4.2 设计亮点

  • 数据可视化:使用图表展示疫情数据趋势;
  • 实时状态更新:健康状态、检测结果实时同步;
  • 智能预警:风险自动识别和预警提示;
  • 移动端适配:支持手机端便捷操作。

3.5 第五步:系统测试——确保系统稳定性

通过多维度测试验证系统功能完整性、性能稳定性和数据安全性:

3.5.1 功能测试

测试场景测试用例预期结果实际结果
轨迹记录用户记录行程轨迹记录成功,状态更新功能正常
密接分析分析确诊者密接人员准确识别密接者分析准确
检测录入管理员录入检测结果结果保存,状态同步录入成功
疫苗预约用户预约疫苗接种预约成功,库存更新预约成功

3.5.2 性能测试

  • 并发测试:模拟500用户同时操作系统,响应时间<2秒;
  • 数据查询测试:查询万条轨迹记录,分页响应迅速;
  • 统计分析测试:大数据量统计计算,结果准确。

3.5.3 安全测试

测试项测试方法预期结果实际结果
数据权限用户尝试访问他人数据访问被拒绝权限控制有效
敏感数据检查数据库敏感信息加密存储加密有效
接口安全测试接口越权访问访问被拦截安全防护有效

3.6 第六步:部署优化——提升系统性能

系统部署和性能优化措施:

  1. 集群部署:多节点部署,提高系统可用性;
  2. 数据库优化:读写分离,查询优化;
  3. 缓存策略:Redis缓存热点数据;
  4. 安全加固:网络安全配置,数据备份;
  5. 监控告警:系统监控,异常告警。

四、毕业设计复盘:疫情防控系统开发总结

4.1 技术难点与解决方案

  1. 轨迹数据分析:开发高效的密接者识别算法;
  2. 数据一致性:通过事务管理保证关键操作原子性;
  3. 系统性能:优化大数据量查询性能;
  4. 安全性:严格的权限控制和数据加密。

4.2 项目创新点

  1. 智能风险预警:基于轨迹数据的自动风险识别;
  2. 可视化数据分析:直观展示疫情发展趋势;
  3. 全流程管理:覆盖从检测到治疗的完整流程;
  4. 移动便捷性:支持移动端随时上报和查询。

五、项目资源与社会价值

5.1 项目资源

  • 完整源代码及技术文档
  • 数据库设计文档
  • 系统部署指南
  • 用户操作手册
  • API接口文档

5.2 社会价值

  1. 提升防控效率:数字化管理大幅提升工作效率;
  2. 精准溯源:准确快速的密接者识别;
  3. 资源优化:合理分配检测和疫苗资源;
  4. 科学决策:数据支撑的疫情防控决策。

如果本文对您的Spring Boot学习、疫情防控系统毕业设计有帮助,欢迎点赞 + 收藏 + 关注,后续会分享更多社会服务类项目实战经验!