当前位置: 首页 > news >正文

SpringBoot 医药咨询系统

在这里插入图片描述

概述

智慧医药系统(smart-medicine)是一个基于 SpringBoot 开发的Web 项目。整体页面简约大气,增加了AI医生问诊功能,功能设计的较为简单。

开源地址

https://gitcode.net/NVG_Haru/Java_04

界面预览

在这里插入图片描述

在这里插入图片描述

功能介绍

游客功能介绍

功能模块功能描述
登录注册方面注册成为系统用户
系统主页浏览系统主页、疾病、药品信息搜索、详情的查看(统计浏览量)

用户功能介绍

功能模块功能描述
登录注册方面填写用户信息进行账号注册(邮件接收验证码)、使用账号密码进行登录
个人资料方面修改个人资料(姓名、年龄、手机号、头像等)、修改登录密码
系统反馈方面提交系统反馈意见
智能医生方面与智能医生进行交流聊天

管理员功能介绍

功能模块功能描述
登录注册方面填写用户信息进行账号注册(邮件接收验证码)、使用账号密码进行登录
个人资料方面修改个人资料(姓名、年龄、手机号、头像等)、修改登录密码
系统反馈方面提交系统反馈意见
智能医生方面与智能医生进行交流聊天
疾病管理方面发布疾病、编辑(名称、原因、症状、分类等)、删除药品等
药品管理方面发布药品、编辑(名称、搜索关键词、功效、用法用量、类型等)、关联疾病、删除药品等
反馈管理方面管理用户提交的反馈信息

数据库设计

在这里插入图片描述

代码讲解

AI 问诊功能

这个功能借助阿里通义千问大模型实现,调用了com.alibaba.dashscope.*sdk提供的接口,主要流程如下:

  1. 创建Generation对象
  2. 创建MessageManager对象
  3. 创建系统消息
  4. 将系统消息和用户消息添加到MessageManager中
  5. 创建QwenParam对象
  6. 调用Generation的call方法,获取GenerationResult对象
  7. 获取GenerationResult对象的输出部分
  8. 获取输出中的第一个消息并返回
    public String query(String queryMessage) {// 设置API keyConstants.apiKey = apiKey;try {// 创建Generation对象Generation gen = new Generation();// 创建MessageManager对象MessageManager msgManager = new MessageManager(10);// 创建系统消息Message systemMsg = Message.builder().role(Role.SYSTEM.getValue()).content("你是智能医生,你只回答与医疗相关的问题,不要回答其他问题!").build();// 创建用户消息Message userMsg = Message.builder().role(Role.USER.getValue()).content(queryMessage).build();// 将系统消息和用户消息添加到MessageManager中msgManager.add(systemMsg);msgManager.add(userMsg);// 创建QwenParam对象QwenParam param = QwenParam.builder().model(Generation.Models.QWEN_TURBO).messages(msgManager.get()).resultFormat(QwenParam.ResultFormat.MESSAGE).build();// 调用Generation的call方法,获取GenerationResult对象GenerationResult result = gen.call(param);// 获取GenerationResult对象的输出部分GenerationOutput output = result.getOutput();// 获取输出中的第一个消息Message message = output.getChoices().get(0).getMessage();// 返回消息的内容return message.getContent();} catch (Exception e) {return "智能医生现在不在线,请稍后再试~";}}

反馈功能

主要讲解一下query这个查询函数,该函数接受一个Feedback实体函数,实际上这是一种偷懒的做法,最佳方案还是确定好哪些参数可以进入函数。

package world.xuewei.service;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import world.xuewei.dao.FeedbackDao;
import world.xuewei.entity.Feedback;
import world.xuewei.utils.Assert;
import world.xuewei.utils.BeanUtil;
import world.xuewei.utils.VariableNameUtils;import java.io.Serializable;
import java.util.List;
import java.util.Map;/*** 反馈服务类**/
@Service
public class FeedbackService extends BaseService<Feedback> {@Autowiredprotected FeedbackDao userDao;/*** 查询满足指定条件的Feedback列表** @param o 查询条件对象* @return 满足条件的Feedback列表*/@Overridepublic List<Feedback> query(Feedback o) {// 创建QueryWrapper对象QueryWrapper<Feedback> wrapper = new QueryWrapper();if (Assert.notEmpty(o)) {// 将对象转换为MapMap<String, Object> bean2Map = BeanUtil.bean2Map(o);// 遍历Map中的键值对for (String key : bean2Map.keySet()) {if (Assert.isEmpty(bean2Map.get(key))) {continue;}// 根据键值对创建查询条件wrapper.eq(VariableNameUtils.humpToLine(key), bean2Map.get(key));}}// 执行查询操作return userDao.selectList(wrapper);}@Overridepublic List<Feedback> all() {return query(null);}@Overridepublic Feedback save(Feedback o) {if (Assert.isEmpty(o.getId())) {userDao.insert(o);} else {userDao.updateById(o);}return userDao.selectById(o.getId());}@Overridepublic Feedback get(Serializable id) {return userDao.selectById(id);}@Overridepublic int delete(Serializable id) {return userDao.deleteById(id);}
}

疾病功能

package world.xuewei.service;import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import world.xuewei.dao.IllnessDao;
import world.xuewei.entity.*;
import world.xuewei.utils.Assert;
import world.xuewei.utils.BeanUtil;
import world.xuewei.utils.VariableNameUtils;import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 疾病服务类** @author XUEW*/
@Service
public class IllnessService extends BaseService<Illness> {@Autowiredprotected IllnessDao illnessDao;@Overridepublic List<Illness> query(Illness o) {QueryWrapper<Illness> wrapper = new QueryWrapper();if (Assert.notEmpty(o)) {Map<String, Object> bean2Map = BeanUtil.bean2Map(o);for (String key : bean2Map.keySet()) {if (Assert.isEmpty(bean2Map.get(key))) {continue;}wrapper.eq(VariableNameUtils.humpToLine(key), bean2Map.get(key));}}return illnessDao.selectList(wrapper);}@Overridepublic List<Illness> all() {return query(null);}@Overridepublic Illness save(Illness o) {if (Assert.isEmpty(o.getId())) {illnessDao.insert(o);} else {illnessDao.updateById(o);}return illnessDao.selectById(o.getId());}@Overridepublic Illness get(Serializable id) {return illnessDao.selectById(id);}@Overridepublic int delete(Serializable id) {return illnessDao.deleteById(id);}public Map<String, Object> findIllness(Integer kind, String illnessName, Integer page) {Map<String, Object> map = new HashMap<>(4);QueryWrapper<Illness> illnessQueryWrapper = new QueryWrapper<>();if (Assert.notEmpty(illnessName)) {illnessQueryWrapper.like("illness_name", illnessName).or().like("include_reason", illnessName).or().like("illness_symptom", illnessName).or().like("special_symptom", illnessName);}if (kind != null) {if (Assert.notEmpty(illnessName)) {illnessQueryWrapper.last("and (kind_id = " + kind + ") ORDER BY create_time DESC limit " + (page - 1) * 9 + "," + page * 9);} else {illnessQueryWrapper.eq("kind_id", kind);illnessQueryWrapper.orderByDesc("create_time");illnessQueryWrapper.last("limit " + (page - 1) * 9 + "," + page * 9);}} else {illnessQueryWrapper.orderByDesc("create_time");illnessQueryWrapper.last("limit " + (page - 1) * 9 + "," + page * 9);}int size = illnessDao.selectMaps(illnessQueryWrapper).size();List<Map<String, Object>> list = illnessDao.selectMaps(illnessQueryWrapper);list.forEach(l -> {Integer id = MapUtil.getInt(l, "id");Pageview pageInfo = pageviewDao.selectOne(new QueryWrapper<Pageview>().eq("illness_id", id));l.put("kindName", "暂无归属类");l.put("create_time", MapUtil.getDate(l, "create_time"));l.put("pageview", pageInfo == null ? 0 : pageInfo.getPageviews());Integer kindId = MapUtil.getInt(l, "kind_id");if (Assert.notEmpty(kindId)) {IllnessKind illnessKind = illnessKindDao.selectById(kindId);if (Assert.notEmpty(illnessKind)) {l.put("kindName", illnessKind.getName());}}});map.put("illness", list);map.put("size", size < 9 ? 1 : size / 9 + 1);return map;}public Map<String, Object> findIllnessOne(Integer id) {Illness illness = illnessDao.selectOne(new QueryWrapper<Illness>().eq("id", id));List<IllnessMedicine> illnessMedicines = illnessMedicineDao.selectList(new QueryWrapper<IllnessMedicine>().eq("illness_id", id));List<Medicine> list = new ArrayList<>(4);Map<String, Object> map = new HashMap<>(4);Pageview illness_id = pageviewDao.selectOne(new QueryWrapper<Pageview>().eq("illness_id", id));if (Assert.isEmpty(illness_id)) {illness_id = new Pageview();illness_id.setIllnessId(id);illness_id.setPageviews(1);pageviewDao.insert(illness_id);} else {illness_id.setPageviews(illness_id.getPageviews() + 1);pageviewDao.updateById(illness_id);}map.put("illness", illness);if (CollUtil.isNotEmpty(illnessMedicines)) {illnessMedicines.forEach(illnessMedicine -> {Medicine medicine = medicineDao.selectOne(new QueryWrapper<Medicine>().eq("id", illnessMedicine.getMedicineId()));if (ObjectUtil.isNotNull(medicine)) {list.add(medicine);}});map.put("medicine", list);}return map;}public Illness getOne(QueryWrapper<Illness> queryWrapper) {return illnessDao.selectOne(queryWrapper);}
}

讲一讲findIllnessOne,这个函数是一个用于查找疾病信息的方法。它接受三个参数:kind表示疾病类型,illnessName表示疾病名称,page表示页码。函数首先创建一个HashMap用于存储结果。然后创建一个QueryWrapper对象用于构建查询条件。如果illnessName不为空,则通过like操作符模糊匹配illness_name、include_reason、illness_symptom和special_symptom字段中的任意一个包含illnessName的内容。接下来根据kind和illnessName的值,构建查询条件,包括对kind_id和create_time的筛选和排序。然后通过调用illnessDao.selectMaps方法获取查询结果的列表。接着遍历列表,对每个疾病对象获取id,并通过pageviewDao.selectOne方法查询对应的pageview信息。然后将一些字段放入疾病对象的HashMap中,包括kindName(默认值为"暂无归属类")、create_time、pageview(如果查询失败则为0)和kindName(如果有)。接下来根据疾病列表的大小计算总页数,并将疾病列表和总页数放入HashMap中。最后将HashMap作为结果返回。

主要问题有:

  • 重复代码:在kind !=
    null和else部分,关于orderByDesc和last的查询条件重复了分页逻辑。可以简化这两个部分的代码。

  • 查询条件构造:like操作的字段和值应该使用占位符,这样可以避免SQL注入。

  • 断言Assert.notEmpty的使用:代码中使用了Assert.notEmpty,这通常用于校验条件,但在这个上下文中,这个校验似乎是多余的,因为如果illnessName为空,之前的like条件就无法匹配任何结果。

  • 使用更合适的数据容器:List和Map已经足够表达结果,可以考虑直接返回一个Page对象,而不是Map,其中包含数据列表和分页信息。

  • 代码可读性:一些变量的命名可以更加清晰,例如map变量可以命名为pageResult,以更清楚地表示它包含的是分页结果。

  • 避免硬编码:分页大小(即每页9条记录)被硬编码在查询中,可以作为常量提取出来。

  • 异常处理:在查询过程中,应该有适当的异常处理机制,以处理潜在的数据库访问错误。

  • 数据映射:数据映射和处理逻辑可以封装到单独的方法中,以提高代码的可读性和可维护性。

相关文章:

SpringBoot 医药咨询系统

概述 智慧医药系统&#xff08;smart-medicine&#xff09;是一个基于 SpringBoot 开发的Web 项目。整体页面简约大气&#xff0c;增加了AI医生问诊功能&#xff0c;功能设计的较为简单。 开源地址 https://gitcode.net/NVG_Haru/Java_04 界面预览 功能介绍 游客功能介绍 …...

C语言转WebAssembly的全流程,及Web端调用测试

第一步&#xff1a;安装环境 参考网址&#xff1a;https://emscripten.org/docs/getting_started/downloads.html 具体过程&#xff1a; 克隆代码&#xff1a;git clone https://github.com/emscripten-core/emsdk.git进入代码目录&#xff1a;cd emsdk获取最新远端代码&…...

前端--基础 目录文件夹和根目录 VScode打开目录文件夹

目录 目录文件夹和根目录 &#xff1a; 目录文件夹 &#xff1a; 根目录 &#xff1a; VScode 打开目录文件夹 &#xff1a; VScode 打开文件夹 &#xff1a; 拖拽目录文件夹 &#xff1a; 目录文件夹和根目录 &#xff1a; 我们都清楚&#xff0c;在实际的工作中会…...

传感器原理与应用复习--超声波、微波、红外及热电偶传感器

文章目录 上一篇超声波传感器微波传感器红外传感器热电偶传感器下一篇 上一篇 传感器原理与应用复习–光电式与半导体式传感器 超声波传感器 超过2万赫兹以上的波称为超声波 压电式超声波探头常用材料是压电晶体和压电陶瓷。它是利用压电材料的压电效应来工作的。 逆压电效…...

matlab概率论例子

高斯概率模型&#xff1a; [f,xi] ksdensity(x): returns a probability density estimate, f, for the sample in the vector x. The estimate is based on a normal kernel function, and is evaluated at 100 equally spaced points, xi, that cover the range of the da…...

Appium+python自动化(一)- 环境搭建—上(超详解)

简介 今天是高考各地由于降水&#xff0c;特别糟糕&#xff0c;各位考生高考加油&#xff0c;全国人民端午节快乐。最近整理了一下自动化的东西&#xff0c;先前整理的python接口自动化已经接近尾声。即将要开启新的征程和篇章&#xff08;Appium&python&#xff09;。那么…...

基于SpringBoot的精简博客系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的精简博客系统,java项目…...

STM32的在线升级(IAP)实现方法:BOOT+APP原理详解

0 工具准备 Keil uVision5 Cortex M3权威指南&#xff08;中文&#xff09; STM32参考手册 1 在线升级&#xff08;IAP&#xff09;设计思路 为了实现STM32的在线升级&#xff08;IAP&#xff09;功能&#xff0c;通常会将STM32的FLASH划分为BOOT和APP两个部分&#xff0c;BOO…...

【芯片DFX】Arm调试架构篇

【芯片DFX】万字长文带你搞懂JTAG的门门道道【芯片DFX】ARM:CoreSight、ETM、PTM、ITM、HTM、ETB等常用术语解析...

ES应用_ES实战

依靠知识库使用es总结一些使用技巧。 1 快速入门 ES是将查询语句写成类似json的形式&#xff0c;通过关键字进行查询和调用。 1.1 创建 下面创建了一个主分片为5&#xff0c;副本分片为1的ES结构。ES本身是一种noschema的结构&#xff0c;但是可以通过指定mapping编程schema的…...

Ubuntu上如何找到设备,打印串口日志

dmesg 找设备 sudo mincom -s 配置minicom mincom 打印串口日志 PS: Windows上使用MobaXterm / putty / Xshell / SecureCRT等 ubuntu串口的安装和使用&#xff08;usb转串口&#xff09;_ubuntu上如何把usb设备映射到tty-CSDN博客...

本地映射测试环境域名,解决登录测试环境后,也可以使用本地域名访问,可以正常跑本地项目

问题&#xff1a;单点登录进入系统不使用token&#xff0c;是将token携带在cookie中&#xff0c;登录成功后每次调用接口&#xff0c;都会在cookie中自动携带&#xff0c;这样导致即使在本地使用proxy代理解决了跨域&#xff0c;但由于本地域名不一致&#xff0c;也无法进行本地…...

VSCode使用Remote SSH远程连接Windows 7

结论 VSCode Server不能启动&#xff0c;无法建立连接。 原因 .vscode-server 目录中的 node.exe 无法运行。 原因是Node.js仅在Windows 8.1、Windows Server 2012 R2或更高版本上受支持。 由于vscode基于node.js v14&#xff0c;不支持Windows 7操作系统。 另&#xff…...

uniapp中uview组件库丰富的Calendar 日历用法

目录 基本使用 #日历模式 #单个日期模式 #多个日期模式 #日期范围模式 #自定义主题颜色 #自定义文案 #日期最大范围 #是否显示农历 #默认日期 基本使用 通过show绑定一个布尔变量用于打开或收起日历弹窗。通过mode参数指定选择日期模式&#xff0c;包含单选/多选/范围…...

云原生Kubernetes:K8S集群实现容器运行时迁移(docker → containerd) 与 版本升级(v1.23.14 → v1.24.1)

目录 一、理论 1.K8S集群升级 2.环境 3.升级策略 4.master1节点迁移容器运行时(docker → containerd) 5.master2节点迁移容器运行时(docker → containerd) 6.node1节点容器运行时迁移(docker → containerd) 7.升级集群计划&#xff08;v1.23.14 → v1.24.1&#…...

Redis 数据结构和常用命令

* 代表多个&#xff0c;&#xff1f;代表一个 &#xff08;不用全部敲出来&#xff0c;按住tab可以自动补全&#xff09; -2是无效&#xff0c;-1是永久有效 &#xff1b;贴心小提示&#xff1a;内存非常宝贵&#xff0c;对于一些数据&#xff0c;我们应当给他一些过期时间&a…...

Docker 容器命令总汇

目录 1、创建Docker容器&#xff08;不启动&#xff09; 2、创建Docker容器&#xff08;启动&#xff09; 3、列出正在运行的容器 4、停止和启动容器 5、重启容器 6、进入容器 7、查看容器信息 8、查看容器日志 9、删除容器和镜像 10、重命名容器 11、从旧容器复制数…...

react + redux 之 美团案例

1.案例展示 2.环境搭建 克隆项目到本地&#xff08;内置了基础静态组件和模版&#xff09; git clone http://git.itcast.cn/heimaqianduan/redux-meituan.git 安装所有依赖 npm i 启动mock服务&#xff08;内置了json-server&#xff09; npm run serve 启动前端服务 npm…...

【形式语言与自动机/编译原理】CFG-->Greibach-->NPDA(2)

本文将详细讲解《形式语言与自动机》&#xff08;研究生课程&#xff09;或《编译原理》&#xff08;本科生课程&#xff09;中的上下文无关文法&#xff08;CFG&#xff09;转换成Greibach范式&#xff0c;再转成下推自动机&#xff08;NPDA&#xff09;识别语言是否可以被接受…...

14.用户管理

目录 1、权限表 1、user表 1.用户列 2.权限列 3.安全列 4.资源控制列 2、db表和host 表 1.用户列 2.权限列 3. tables_priv 表和 columns _priv 表 4.procs_priv 表 2、账户管理 1. 登录和退出MySQL服务器 2、创建普通用户&#xff1a; 1.使用CREATE USER语创建…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...