拓冰建站拓冰建站
首页 / 资讯中心 / 正文

【免费】AI智能医疗问诊平台系统(RAG+Spring AI2.0+Neo4j知识图谱+SpringBoot4+Vue3) 锋哥原创出品,必属精品

大家好我是Java1234_小锋老师分享一套锋哥原创的AI智能医疗问诊平台系统(RAGSpring AI2.0Neo4j知识图谱SpringBoot4Vue3) 。项目介绍随着分级诊疗制度持续推进和居民健康管理意识不断增强基层医疗机构与互联网平台都面临着“咨询量大、专科医生相对不足、健康知识获取渠道分散”的现实矛盾。传统在线问诊系统多以表单留言或人工即时通讯为主难以对患者的自然语言症状描述进行结构化理解也缺少可追溯的医学依据。与此同时大语言模型、检索增强生成RAG和图数据库技术日趋成熟为构建“可引用、可解释、可转诊”的智能问诊系统提供了技术条件。本文设计并实现了一套面向本科毕业设计场景的AI智能医疗问诊平台系统。系统采用前后端分离架构后端基于Java 17与Spring Boot 4构建RESTful服务集成Spring AI 2.0对接通义千问大语言模型前端采用Vue 3、Vite与Element Plus实现患者门户、医生工作台和管理后台三端界面。业务数据存储于MySQL 8数据库库名db_ai_medical表名均以t_开头医学实体关系存储于Neo4j知识图谱指南类文档经分块与向量化后写入本地向量库形成“关系数据 向量检索 图谱推理”的混合知识底座。在功能层面系统支持患者注册登录、AI多轮问诊、症状图谱推理、人工咨询、预约挂号、健康档案查询和健康资讯浏览支持医生处理咨询工单、确认预约并维护患者档案支持管理员进行用户与科室管理、知识库上传向量化、图谱可视化、文章公告运营以及首页数据统计。AI问诊采用SSE流式输出回答中附带知识库引用片段和图谱候选疾病并明确提示“仅供参考、不能替代面诊”以降低误导风险。测试结果表明系统三角色权限隔离正确核心业务流程闭环完整知识库文件可完成解析、分块与向量化图谱能够根据症状返回候选疾病及推荐科室。本系统对探索大模型在医疗咨询场景中的工程落地具有一定的参考价值。源码下载链接: https://pan.baidu.com/s/1eBPdVADGePMNl83McSUO7Q?pwd1234提取码: 1234系统展示核心代码package com.java1234.controller; import com.java1234.common.PageResult; import com.java1234.common.Result; import com.java1234.dto.AppointmentCreateRequest; import com.java1234.interceptor.RequireRoles; import com.java1234.service.AppointmentService; import jakarta.validation.Valid; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.web.bind.annotation.*; import java.time.LocalDate; import java.util.List; import java.util.Map; /** * 预约挂号接口 */ RestController RequestMapping(/api/v1/appointments) public class AppointmentController { private final AppointmentService appointmentService; public AppointmentController(AppointmentService appointmentService) { this.appointmentService appointmentService; } /** * 创建预约患者 */ PostMapping(/create) RequireRoles(user) public ResultMapString, Object create(Valid RequestBody AppointmentCreateRequest req) { return Result.success(appointmentService.createAppointment(req), 预约成功); } /** * 我的预约患者 */ GetMapping(/my) RequireRoles(user) public ResultListMapString, Object my() { return Result.success(appointmentService.myAppointments()); } /** * 医生的预约 */ GetMapping(/doctor/my) RequireRoles(doctor) public ResultListMapString, Object doctorMy() { return Result.success(appointmentService.doctorAppointments()); } /** * 管理员预约列表 */ GetMapping(/admin/list) RequireRoles(admin) public ResultPageResultMapString, Object adminList( RequestParam(defaultValue 1) int page, RequestParam(name page_size, defaultValue 10) int pageSize, RequestParam(defaultValue ) String keyword, RequestParam(name department_id, required false) Integer departmentId, RequestParam(name visit_date, required false) DateTimeFormat(iso DateTimeFormat.ISO.DATE) LocalDate visitDate, RequestParam(required false) Integer status) { PageResultMapString, Object result appointmentService.adminList( page, pageSize, keyword, departmentId, visitDate, status); return Result.page(result.getItems(), result.getTotal(), result.getPage(), result.getPageSize()); } /** * 管理员删除预约 */ DeleteMapping(/admin/{appt_id}) RequireRoles(admin) public ResultVoid adminDelete(PathVariable(appt_id) Integer apptId) { appointmentService.adminDelete(apptId); return Result.success(null, 删除成功); } /** * 更新预约状态管理员/医生 */ PutMapping(/{appt_id}/status) RequireRoles({admin, doctor}) public ResultVoid updateStatus(PathVariable(appt_id) Integer apptId, RequestParam Integer status) { appointmentService.updateStatus(apptId, status); return Result.success(null, 状态更新成功); } }script setup import { ref, onMounted, onUnmounted } from vue import { ElMessage, ElMessageBox } from element-plus import { Upload } from element-plus/icons-vue import request from /utils/request import { formatDateTime, parseListData } from /utils/format const list ref([]) const loading ref(false) const uploading ref(false) /** 搜索关键词 */ const keyword ref() /** 分页参数 */ const page ref(1) const pageSize ref(10) const total ref(0) /** 状态轮询定时器 */ let pollTimer null /** 判断是否存在待处理或处理中的文件 */ function hasPendingFiles(items) { return items.some((item) item.vector_status 0 || item.vector_status 1) } /** 获取列表请求参数 */ function getListParams() { return { page: page.value, page_size: pageSize.value, keyword: keyword.value.trim(), } } /** 启动状态轮询向量化完成后自动停止 */ function startPolling() { if (pollTimer) return pollTimer setInterval(() { refreshList() }, 3000) } /** 停止状态轮询 */ function stopPolling() { if (pollTimer) { clearInterval(pollTimer) pollTimer null } } /** 加载知识库列表 */ async function loadList(silent false) { if (!silent) loading.value true try { const res await request.get(/knowledge/list, { params: getListParams() }) list.value parseListData(res) total.value res.data?.total ?? list.value.length if (hasPendingFiles(list.value)) { startPolling() } else { stopPolling() } } catch { list.value [] total.value 0 stopPolling() } finally { if (!silent) loading.value false } } /** 静默刷新列表轮询时使用避免 loading 闪烁 */ async function refreshList() { try { const res await request.get(/knowledge/list, { params: getListParams() }) list.value parseListData(res) if (!hasPendingFiles(list.value)) { stopPolling() } } catch { /* 轮询失败时忽略下次继续 */ } } /** 搜索知识库文件 */ function handleSearch() { page.value 1 loadList() } /** 重置搜索条件 */ function handleReset() { keyword.value page.value 1 loadList() } /** 分页切换 */ function handlePageChange(p) { page.value p loadList() } /** 上传知识文件 */ async function handleUpload({ file }) { uploading.value true const formData new FormData() formData.append(file, file) try { await request.post(/knowledge/upload, formData, { headers: { Content-Type: multipart/form-data }, }) ElMessage.success(上传成功正在向量化处理) page.value 1 await loadList() } catch { /* */ } finally { uploading.value false } } /** 删除知识库文件 */ async function handleDelete(row) { try { await ElMessageBox.confirm( 确定删除知识库文件「${row.file_name}」吗删除后不可恢复。, 提示, { type: warning }, ) await request.delete(/knowledge/${row.id}) ElMessage.success(删除成功) if (list.value.length 1 page.value 1) { page.value - 1 } await loadList() } catch { /* */ } } onMounted(loadList) onUnmounted(stopPolling) /script template div div classpage-header h2 classpage-title知识库管理/h2 el-upload :show-file-listfalse :http-requesthandleUpload accept.txt,.pdf,.doc,.docx,.md el-button typeprimary classgradient-btn :loadinguploading :iconUpload 上传文件 /el-button /el-upload /div div classmodern-card !-- 搜索栏 -- div classsearch-bar el-input v-modelkeyword placeholder搜索文件名 / 文件类型 clearable stylewidth: 280px keyup.enterhandleSearch / el-button typeprimary clickhandleSearch搜索/el-button el-button clickhandleReset重置/el-button /div el-table :datalist v-loadingloading classadaptive-table stripe el-table-column propid labelID min-width60 / el-table-column propfile_name label文件名 min-width200 show-overflow-tooltip / el-table-column propfile_type label类型 min-width100 template #default{ row } el-tag sizesmall{{ row.file_type || row.type || - }}/el-tag /template /el-table-column el-table-column propfile_size label大小 min-width100 template #default{ row } {{ row.file_size ? (row.file_size / 1024).toFixed(1) KB : (row.size ? (row.size / 1024).toFixed(1) KB : -) }} /template /el-table-column el-table-column propvector_status label状态 min-width100 template #default{ row } el-tag :typerow.vector_status 2 ? success : row.vector_status 3 ? danger : info sizesmall {{ row.vector_status 2 ? 已向量化 : row.vector_status 3 ? 失败 : row.vector_status 1 ? 处理中 : 已上传 }} /el-tag /template /el-table-column el-table-column propcreate_time label上传时间 min-width170 template #default{ row }{{ formatDateTime(row.create_time || row.created_at) }}/template /el-table-column el-table-column label操作 min-width100 fixedright template #default{ row } el-button link typedanger clickhandleDelete(row)删除/el-button /template /el-table-column /el-table el-empty v-if!loading !list.length description暂无知识库文件 / !-- 分页 -- div v-iftotal 0 classpagination-wrap el-pagination v-model:current-pagepage :page-sizepageSize :totaltotal layouttotal, prev, pager, next background current-changehandlePageChange / /div /div /div /template style scoped .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .search-bar { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; } .pagination-wrap { display: flex; justify-content: flex-end; margin-top: 16px; } /style
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门