【免费】基于Spark实时医疗健康数据监测与疾病预测系统(Java版本+可视化大屏+Kafka+SpringBoot+Vue3) 锋哥原创出品,必属精品

大家好,我是Java1234_小锋老师,分享一套锋哥原创的基于Spark实时医疗健康数据监测与疾病预测系统(Java版本+可视化大屏+Kafka+SpringBoot+Vue3) 

项目介绍

随着医疗信息化与物联网可穿戴设备的快速发展,医院与健康管理机构面临着体征数据规模大、产生速度快、分析时效性要求高的挑战。传统以事后统计为主的信息系统难以满足实时监测与早期预警需求。本文设计并实现了一套基于Spark的实时医疗健康数据监测与疾病预测系统,围绕“数据采集—消息传输—流式聚合—风险预测—可视化展示”的完整链路开展研究与开发。

系统后端采用Java 17与Spring Boot 3构建RESTful服务,结合Spring Security与JWT完成管理员身份认证;数据访问层使用MyBatis-Plus操作MySQL数据库db_health;实时事件通过Apache Kafka主题health_vitals进行解耦传输;计算层引入Apache Spark SQL与Spark MLlib,对按小时窗口聚合的风险指数序列进行线性回归预测,并计算RMSE、MAE、MAPE误差指标。前端采用Vue 3、Vite、Element Plus与ECharts实现管理后台与数据大屏,支持患者档案管理、体征记录查询、实时统计分析、疾病风险预测对比以及个人中心(头像上传、资料修改、密码修改)等功能。

测试结果表明,系统能够稳定完成模拟体征数据的持续接入与入库,实时统计与预测结果可在前端动态刷新,功能完整性与交互可用性满足本科毕业设计要求。本课题将大数据流处理、机器学习预测与Web工程实践相结合,对智慧医疗场景下的实时健康管理具有一定参考价值。

源码下载 

链接: https://pan.baidu.com/s/1hNYZ5_11TXkswBhGGYhZHg?pwd=1234
提取码: 1234

系统展示

核心代码

package com.java1234.controller;

import com.java1234.common.PageResult;
import com.java1234.common.Result;
import com.java1234.dto.PatientCreateRequest;
import com.java1234.dto.PatientUpdateRequest;
import com.java1234.service.PatientService;
import com.java1234.vo.PatientVo;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

/**
 * 患者管理控制器
 */
@RestController
@RequestMapping("/api/patient")
@RequiredArgsConstructor
public class PatientController {

    private final PatientService patientService;

    /**
     * 分页查询患者列表
     */
    @GetMapping("/list")
    public Result<PageResult<PatientVo>> list(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false) String keyword) {
        return Result.success(patientService.listPatients(page, size, keyword));
    }

    /**
     * 新增患者
     */
    @PostMapping("/create")
    public Result<PatientVo> create(@RequestBody PatientCreateRequest request) {
        return Result.success(patientService.createPatient(request));
    }

    /**
     * 更新患者信息
     */
    @PutMapping("/update/{patientId}")
    public Result<PatientVo> update(@PathVariable Integer patientId,
                                    @RequestBody PatientUpdateRequest request) {
        return Result.success(patientService.updatePatient(patientId, request));
    }

    /**
     * 删除患者
     */
    @DeleteMapping("/delete/{patientId}")
    public Result<Void> delete(@PathVariable Integer patientId) {
        patientService.deletePatient(patientId);
        return Result.success("删除成功");
    }

    /**
     * 获取疾病类型列表
     */
    @GetMapping("/diseases")
    public Result<List<Map<String, Object>>> diseases() {
        return Result.success(patientService.listDiseases());
    }
}
<template>
  <div class="page-container">
    <div class="page-card">
      <div class="page-title">患者管理</div>
      <div style="margin-bottom:16px;display:flex;gap:12px">
        <el-input v-model="keyword" placeholder="搜索患者姓名" clearable style="width:240px" @clear="loadData" @keyup.enter="loadData" />
        <el-button type="primary" @click="loadData">搜索</el-button>
        <el-button type="success" @click="openDialog()">新增患者</el-button>
      </div>
      <el-table :data="tableData" stripe border style="width:100%">
        <el-table-column prop="id" label="ID" min-width="60" />
        <el-table-column prop="name" label="姓名" min-width="100" />
        <el-table-column prop="gender" label="性别" min-width="70" />
        <el-table-column prop="age" label="年龄" min-width="70" />
        <el-table-column prop="city" label="城市" min-width="100" />
        <el-table-column prop="disease_name" label="疾病类型" min-width="120" />
        <el-table-column prop="phone" label="联系电话" min-width="130" />
        <el-table-column prop="create_time" label="创建时间" min-width="170">
          <template #default="{ row }">{{ formatDateTime(row.create_time) }}</template>
        </el-table-column>
        <el-table-column label="操作" min-width="160" fixed="right">
          <template #default="{ row }">
            <el-button type="primary" link size="small" @click="openDialog(row)">编辑</el-button>
            <el-button type="danger" link size="small" @click="handleDelete(row.id)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        style="margin-top:16px;justify-content:flex-end"
        v-model:current-page="page"
        v-model:page-size="size"
        :total="total"
        :page-sizes="[10, 20, 50]"
        layout="total, sizes, prev, pager, next"
        @change="loadData"
      />
    </div>

    <el-dialog v-model="dialogVisible" :title="editId ? '编辑患者' : '新增患者'" width="500px">
      <el-form :model="form" label-width="90px">
        <el-form-item label="姓名"><el-input v-model="form.name" /></el-form-item>
        <el-form-item label="性别">
          <el-select v-model="form.gender" style="width:100%">
            <el-option label="男" value="男" /><el-option label="女" value="女" /><el-option label="未知" value="未知" />
          </el-select>
        </el-form-item>
        <el-form-item label="年龄"><el-input-number v-model="form.age" :min="0" :max="120" style="width:100%" /></el-form-item>
        <el-form-item label="城市"><el-input v-model="form.city" /></el-form-item>
        <el-form-item label="疾病类型">
          <el-select v-model="form.disease_id" style="width:100%">
            <el-option v-for="d in diseases" :key="d.id" :label="d.name" :value="d.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="联系电话"><el-input v-model="form.phone" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleSave">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
/**
 * 患者管理页面
 */
import { ref, reactive, onMounted } from 'vue'
import request from '@/utils/request'
import { formatDateTime } from '@/utils/format'
import { ElMessage, ElMessageBox } from 'element-plus'

const tableData = ref([])
const diseases = ref([])
const page = ref(1)
const size = ref(10)
const total = ref(0)
const keyword = ref('')
const dialogVisible = ref(false)
const editId = ref(null)
const form = reactive({ name: '', gender: '未知', age: 0, city: '', disease_id: null, phone: '' })

async function loadData() {
  const res = await request.get('/patient/list', { params: { page: page.value, size: size.value, keyword: keyword.value || undefined } })
  tableData.value = res.data.items
  total.value = res.data.total
}

async function loadDiseases() {
  const res = await request.get('/patient/diseases')
  diseases.value = res.data
}

function openDialog(row) {
  editId.value = row?.id || null
  form.name = row?.name || ''
  form.gender = row?.gender || '未知'
  form.age = row?.age || 0
  form.city = row?.city || ''
  form.disease_id = row?.disease_id || null
  form.phone = row?.phone || ''
  dialogVisible.value = true
}

async function handleSave() {
  if (editId.value) {
    await request.put(`/patient/update/${editId.value}`, form)
  } else {
    await request.post('/patient/create', form)
  }
  ElMessage.success('保存成功')
  dialogVisible.value = false
  loadData()
}

async function handleDelete(id) {
  await ElMessageBox.confirm('确定删除该患者?', '提示', { type: 'warning' })
  await request.delete(`/patient/delete/${id}`)
  ElMessage.success('删除成功')
  loadData()
}

onMounted(() => { loadData(); loadDiseases() })
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值