作为一名长期从事医疗信息化开发的工程师,我最近完成了一个基于SpringBoot+Vue的老年人健康数据远程监控系统。这个项目源于某养老机构的实际需求——他们需要一套能够实时采集血压、血糖、心率等关键指标,并具备异常预警功能的数字化管理平台。
传统养老院采用纸质记录方式,存在三个致命缺陷:一是数据滞后性严重,护工往往晚上才统一录入当天的测量结果;二是异常情况难以及时发现;三是历史数据查询分析极其不便。我们的系统通过智能设备对接+Web端管理,实现了以下核心价值:
技术选型方面,后端采用SpringBoot 2.7 + MyBatis Plus构建RESTful API,前端使用Vue3+Element Plus实现响应式界面,数据库选用MySQL 8.0存储结构化数据,Redis 6.2缓存高频访问的实时监测数据。这种技术组合既保证了系统稳定性,又具备良好的扩展性。
系统采用经典的前后端分离架构,物理上分为四个层次:
设备接入层:
后端服务层:
java复制@SpringBootApplication
@EnableScheduling
@EnableCaching
public class HealthMonitorApplication {
public static void main(String[] args) {
SpringApplication.run(HealthMonitorApplication.class, args);
}
}
关键配置说明:
前端展示层:
vue复制<template>
<reactive-chart :options="chartOptions" />
</template>
<script setup>
const chartOptions = computed(() => ({
xAxis: { type: 'time' },
series: [{ data: healthData.value }]
}))
</script>
数据存储层:
核心表结构设计遵循医疗数据规范:
sql复制CREATE TABLE `health_record` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`user_id` BIGINT NOT NULL COMMENT '关联老人ID',
`metric_type` TINYINT NOT NULL COMMENT '1血压 2血糖 3血氧',
`measure_value` VARCHAR(20) NOT NULL COMMENT '收缩压/舒张压格式:120/80',
`device_sn` VARCHAR(32) COMMENT '设备序列号',
`measure_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`is_warning` TINYINT DEFAULT 0 COMMENT '是否异常',
PRIMARY KEY (`id`),
INDEX `idx_user_metric` (`user_id`, `metric_type`),
INDEX `idx_time` (`measure_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
设计注意事项:
设备通信采用自定义二进制协议:
code复制[HEADER][LENGTH][DEVICE_ID][TIMESTAMP][DATA...][CRC]
Java端使用Netty实现高并发处理:
java复制public class DeviceHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf buf = (ByteBuf) msg;
byte[] data = new byte[buf.readableBytes()];
buf.readBytes(data);
HealthRecord record = ProtocolParser.parse(data);
recordService.saveRecord(record);
if(record.isWarning()) {
alertService.notify(record);
}
}
}
关键点:
动态阈值计算逻辑:
java复制public class HealthAlertService {
private static final Map<Integer, Function<Double, Boolean>> RULES = Map.of(
1, value -> value > 140 || value < 90, // 血压
2, value -> value > 7.8 || value < 4.0 // 血糖
);
public boolean checkAbnormal(HealthRecord record) {
double value = parseValue(record);
return RULES.getOrDefault(record.getMetricType(), v -> false)
.apply(value);
}
}
预警升级策略:
使用ECharts实现动态图表:
javascript复制const setupLiveChart = () => {
const chart = echarts.init(dom);
const options = {
dataset: { source: [] },
series: [{
type: 'gauge',
data: [{ value: 0, name: '心率' }]
}]
};
socket.on('data', (newData) => {
options.dataset.source.push(newData);
chart.setOption(options);
});
}
性能优化技巧:
基于Vue3的组合式API:
vue复制<template>
<div class="container" :class="{ 'mobile': isMobile }">
<health-card v-for="item in data" :key="item.id" />
</div>
</template>
<script setup>
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
</script>
Docker Compose编排方案:
yaml复制version: '3'
services:
backend:
image: health-monitor:1.0
ports: ["8080:8080"]
depends_on:
- redis
- mysql
frontend:
image: nginx:1.21
ports: ["80:80"]
volumes:
- ./dist:/usr/share/nginx/html
关键配置:
压测指标对比:
| 优化措施 | QPS提升 | 平均响应时间下降 |
|---|---|---|
| Redis缓存热点数据 | 320% | 65ms → 22ms |
| 数据库连接池调优 | 150% | 41ms → 17ms |
| 异步日志处理 | - | 峰值延迟降低40% |
现象:夜间频繁出现设备离线
排查过程:
最终方案:
java复制// 在设备协议中添加心跳包
void scheduleHeartbeat() {
executor.scheduleAtFixedRate(() -> {
if(lastActiveTime < System.currentTimeMillis() - TIMEOUT) {
reconnect();
}
}, 0, 30, SECONDS);
}
现象:移动端偶尔显示旧数据
解决方案:
当前系统已稳定运行6个月,后续计划:
在开发过程中最深的体会是:医疗系统必须平衡实时性和可靠性,我们通过本地缓存+异步持久化的方式,在服务重启时仍能保持5分钟内的数据完整性。对于关键健康数据,宁可丢失也不能传递错误值,这是与普通业务系统最大的区别。