1. 社区疫情防控系统的背景与需求分析
2020年以来,全球公共卫生事件频发,社区作为疫情防控的第一道防线,其管理效率直接影响防疫成效。传统社区防疫主要依靠人工登记、纸质台账和微信群通知,存在信息滞后、数据孤岛、追溯困难等痛点。我们团队在参与某大型社区防疫志愿服务时,亲眼目睹工作人员需要同时处理健康码核验、体温登记、物资发放等多项工作,经常忙到凌晨整理Excel表格。
基于Uniapp+SSM的社区疫情防控系统正是为解决这些实际问题而设计。系统需要实现以下核心功能:
- 居民端:健康打卡、访客预约、核酸结果查询
- 物业端:人员出入管理、异常情况预警
- 政府端:疫情数据可视化、资源调度分析
关键设计原则:操作门槛要足够低,能覆盖从20岁到70岁的社区居民;数据要实时同步,避免多个物业小区之间的信息壁垒;系统要能承受早晚高峰的并发访问。
2. 技术选型与架构设计
2.1 为什么选择Uniapp+SSM组合
在技术选型阶段,我们对比了三种主流方案:
- 微信小程序原生开发:开发效率低且无法跨平台
- Flutter+Spring Boot:学习曲线陡峭,社区资源少
- Uniapp+SSM:最终选择方案
Uniapp的优势在社区场景尤为突出:
- 一次开发可发布到微信、支付宝、H5、App多个平台
- 内置组件库(uni-ui)包含扫码、地图等防疫刚需功能
- 支持条件编译,可针对不同平台做特性适配
SSM(Spring+SpringMVC+MyBatis)作为后端框架:
- 注解开发模式比传统SSH更高效
- MyBatis的SQL优化能力应对疫情数据统计查询
- 与Uniapp通过RESTful API交互,接口设计示例:
java复制@RestController
@RequestMapping("/api/health")
public class HealthController {
@PostMapping("/report")
public Result reportHealth(@RequestBody HealthRecord record) {
// 数据校验和处理逻辑
}
}
2.2 系统架构详解
整体采用分层架构设计:
code复制表现层:Uniapp(Vue.js语法)
↓ HTTP/HTTPS
业务层:Spring MVC(Controller)
↓ 方法调用
持久层:MyBatis Plus
↓ JDBC
数据存储:MySQL(业务数据)+ Redis(缓存)
特别在数据库设计中,我们优化了疫情相关数据的存储结构:
sql复制CREATE TABLE `health_report` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`user_id` BIGINT COMMENT '关联用户ID',
`temperature` DECIMAL(3,1) COMMENT '体温',
`health_code` TINYINT COMMENT '健康码状态:1绿 2黄 3红',
`location` POINT COMMENT '打卡地理位置',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 核心功能实现细节
3.1 居民健康打卡模块
Uniapp端关键实现:
vue复制<template>
<view class="container">
<uni-forms ref="form">
<uni-forms-item label="体温" name="temp">
<uni-number-box v-model="formData.temp" :min="34" :max="42"/>
</uni-forms-item>
<uni-data-checkbox v-model="formData.symptoms"
:localdata="symptomsList"/>
</uni-forms>
</view>
</template>
<script>
export default {
data() {
return {
formData: { temp: 36.5 },
symptomsList: [
{ text: '咳嗽', value: 1 },
{ text: '发热', value: 2 }
]
}
},
methods: {
submitForm() {
uni.request({
url: '/api/health/report',
method: 'POST',
data: this.formData
})
}
}
}
</script>
后端处理逻辑特别注意:
- 防重复提交:通过Redis记录用户最后一次提交时间
- 异常检测:连续3天体温>37.3℃自动触发预警
- 位置校验:与社区电子围栏比对判断是否虚假打卡
3.2 人员出入管理模块
采用二维码动态生成方案:
- 居民生成个人专属二维码(含加密的userID+timestamp)
- 门岗扫码后,后端解密并校验:
- 健康码状态(调用政府接口)
- 核酸有效期(比对检测记录)
- 通行结果实时推送至物业PC端和大屏
性能优化点:
- 二维码有效期设置为5分钟,降低被冒用风险
- 使用Redis缓存政府接口返回的健康码状态
- 扫码记录异步写入数据库,避免阻塞主流程
4. 开发中的典型问题与解决方案
4.1 Uniapp多端兼容问题
在实现语音播报功能时,各平台表现差异明显:
- 微信小程序:需使用wx.startRecord API
- App端:可用plus.speech合成语音
- H5:依赖浏览器Web Speech API
最终解决方案:
javascript复制function playVoice(text) {
// #ifdef MP-WEIXIN
wx.startRecord({ content: text })
// #endif
// #ifdef APP-PLUS
plus.speech.speak(text)
// #endif
// #ifdef H5
if ('speechSynthesis' in window) {
const utterance = new SpeechSynthesisUtterance(text)
window.speechSynthesis.speak(utterance)
}
// #endif
}
4.2 高并发下的数据一致性问题
在全员核酸时期,系统遇到了:
- MySQL连接池耗尽
- 多个物业同时修改同一物资库存
- 实时统计接口响应超时
我们的优化措施:
- 引入Druid连接池,配置参数:
properties复制# 初始连接数
druid.initialSize=5
# 最大连接数
druid.maxActive=50
# 获取连接超时时间(毫秒)
druid.maxWait=60000
- 对关键操作使用分布式锁:
java复制public boolean reduceInventory(Long itemId, int num) {
String lockKey = "lock:inventory:" + itemId;
try {
// 尝试获取锁
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
if (locked != null && locked) {
// 实际库存操作
}
} finally {
redisTemplate.delete(lockKey);
}
}
- 统计类查询迁移至ClickHouse,与MySQL通过Debezium实现实时同步
5. 安全与隐私保护方案
5.1 数据传输安全
- 全链路HTTPS加密
- 敏感字段二次加密(如身份证号):
java复制// 使用SM4国密算法加密
public String encryptIdCard(String idCard) {
SM4Util sm4 = new SM4Util();
return sm4.encryptData_ECB(idCard, SECRET_KEY);
}
5.2 隐私数据脱敏
在数据展示层统一处理:
vue复制<template>
<view>
{{ hideMobile(userInfo.phone) }}
</view>
</template>
<script>
export default {
methods: {
hideMobile(mobile) {
return mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
}
}
</script>
数据库层面实施:
- 敏感字段单独加密存储
- 操作日志记录完整审计轨迹
- 定时任务自动清理过期数据
6. 项目部署与运维实践
6.1 多环境配置管理
通过profile实现环境隔离:
xml复制<!-- application.yml -->
spring:
profiles:
active: @profileActive@
---
spring:
profiles: dev
datasource:
url: jdbc:mysql://localhost:3306/community_dev
---
spring:
profiles: prod
datasource:
url: jdbc:mysql://cluster-xxx.rds.aliyuncs.com:3306/community
Uniapp端使用条件编译:
javascript复制// #ifdef H5
const baseURL = 'https://h5.example.com'
// #endif
// #ifdef MP-WEIXIN
const baseURL = 'https://wx.example.com'
// #endif
6.2 性能监控方案
- Spring Boot Actuator暴露健康指标
- Prometheus + Grafana监控看板
- 关键业务指标埋点:
java复制@RestController
@RequestMapping("/api")
public class ApiController {
@Autowired
private MeterRegistry registry;
@GetMapping("/health")
public Result getHealthStatus() {
registry.counter("api.health.requests").increment();
// 业务逻辑
}
}
在项目上线后,我们特别发现:
- 早晚高峰时段(7:00-9:00,18:00-20:00)的API响应时间平均增加200ms
- 扫码通行功能的99线(P99)达到1.2秒
- 通过增加Redis集群节点和MySQL读写分离,最终将P99控制在800ms以下
