SpringBoot 医药咨询系统

news2025/1/24 2:18:01

在这里插入图片描述

概述

智慧医药系统(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 key
        Constants.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> {

    @Autowired
    protected FeedbackDao userDao;

        /**
     * 查询满足指定条件的Feedback列表
     *
     * @param o 查询条件对象
     * @return 满足条件的Feedback列表
     */
    @Override
    public List<Feedback> query(Feedback o) {
        // 创建QueryWrapper对象
        QueryWrapper<Feedback> wrapper = new QueryWrapper();
        if (Assert.notEmpty(o)) {
            // 将对象转换为Map
            Map<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);
    }

    @Override
    public List<Feedback> all() {
        return query(null);
    }

    @Override
    public Feedback save(Feedback o) {
        if (Assert.isEmpty(o.getId())) {
            userDao.insert(o);
        } else {
            userDao.updateById(o);
        }
        return userDao.selectById(o.getId());
    }

    @Override
    public Feedback get(Serializable id) {
        return userDao.selectById(id);
    }

    @Override
    public 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> {

    @Autowired
    protected IllnessDao illnessDao;

    @Override
    public 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);
    }

    @Override
    public List<Illness> all() {
        return query(null);
    }

    @Override
    public Illness save(Illness o) {
        if (Assert.isEmpty(o.getId())) {
            illnessDao.insert(o);
        } else {
            illnessDao.updateById(o);
        }
        return illnessDao.selectById(o.getId());
    }

    @Override
    public Illness get(Serializable id) {
        return illnessDao.selectById(id);
    }

    @Override
    public 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条记录)被硬编码在查询中,可以作为常量提取出来。

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1347206.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

现实世界中的人工智能:工业制造的 4 个成功案例研究

现实世界中的人工智能&#xff1a;工业制造的 4 个成功案例研究 从抓鸡翅到建立整个虚拟工厂&#xff0c;各种规模的制造商都利用人工智能以更快的速度、更低的成本和更低的风险生产更多的产品。 我们能否让工厂变得足够聪明&#xff0c;在发生故障之前告诉我们&#xff1f;我…

C语言实现关键字匹配算法(复制即用)

文章目录 前言功能要求运行截图全部代码 前言 无套路&#xff0c;均已上机通过&#xff0c;求个关注求个赞&#xff0c;提供答疑解惑服务。 功能要求 一份C源代码存储在一个文本文件中&#xff0c;请统计该文件中关键字出现的频度&#xff0c;并按此频度对关键字进行排序。要…

Kafka安装及简单使用介绍

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

政务大数据能力平台建设方案:文件全文30页,附下载

关键词&#xff1a;智慧政务解决方案&#xff0c;智慧政务建设&#xff0c;智慧政务服务平台&#xff0c;智慧政务大数据&#xff0c;数字政务一体化平台。大数据&#xff0c;政务大数据建设 一、智慧政务建设需求 1、政务服务需求&#xff1a;智慧政务建设需要满足人民群众的…

Jenkins 系列:Jenkins 安装(Windows、Mac、Centos)和简介

文章目录 简介发展历史应用场景 Jenkins 安装部署先决条件硬件要求软件包下载war 包部署linux 系统部署mac 系统部署windows 系统部署安装后基本配置解锁自定义 jenkins 插件创建用户配置更新站点 配置文件 简介 Jenkins前身是 Hudson&#xff0c;使用 java 语言开发的自动化发…

基于SpringBoot实现的前后端分离电影评分项目,功能:注册登录、浏览影片、热门影片、搜索、评分、片单、聊天、动态

一、项目介绍 本项目主要基于SpringBoot、Mybatis-plus、MySQL、Redis实现的影片评分项目。 本系统是前后端分离的&#xff0c;分别由三个子项目构成&#xff1a;java服务端、用户前端、管理员管理前端 关键词&#xff1a;springboot java vue mysql reids websocket 毕业设计…

【Leetcode】1154. 一年中的第几天

文章目录 题目思路代码 题目 1154. 一年中的第几天链接 思路 题目要求是给定一个字符串 date&#xff0c;它代表一个日期&#xff0c;采用标准的 YYYY-MM-DD 格式。需要计算这个日期是当年的第几天。 首先&#xff0c;我们可以通过字符串的索引来提取年、月和日的数值&…

python的pywebio库给孩子做加减法数学题

效果展示 程序执行后&#xff0c;打开浏览器&#xff0c;展示一些100以内的加减法混合运算的数学题并输入答案后判断对错&#xff0c;这样倒是省了买教材的钱了。 在题目下方的框中&#xff0c;输入答案&#xff0c;然后点击提交后&#xff0c; 会输出结果 pywebio库介绍 安装…

Resnet BatchNormalization 迁移学习

时间&#xff1a;2015 网络中的亮点&#xff1a; 超深的网络结构&#xff08;突破1000层&#xff09;提出residual模块使用Batch Normalization加速训练&#xff08;丢弃dropout&#xff09; 层数越深效果越好&#xff1f; 是什么样的原因导致更深的网络导致的训练效果更差呢…

计算机组成原理复习7

内存管理 文章目录 内存管理存储器概述存储器的分类按在计算机中的作用&#xff08;层次&#xff09;分类按存储介质分类按存取方式分类按信息的可保存性分类 存储器的性能指标存储容量单位成本存储速度&#xff1a;数据传输率数据的宽度/存储周期 存储器的层次化结构多级存储系…

【实用工具】vim常用命令

快速移动(上下左右箭头可替代) 左移 h 右移 l 下移 j 上移 K在本行操作 0 移动到本行行首 ^ 移动到本行的第一个不是 blank 字符 $ 移动到本行行尾 w 光标移动到下一个单词的开头 e 光标移动到下一个单词的结尾跨行移动光标 nG 光标定位到第n行的行首 gg 光标定位到第一行的…

SPI机制原理+使用

一、概述 SPI全称&#xff08;Service Provider Interface&#xff09;&#xff0c;是JDK内置的一种服务提供发现机制&#xff1b;SPI机制提供了组件发现和注册方式&#xff0c;可以为应用程序提供灵活的插件机制&#xff0c; 主要原理&#xff1a;接口 反射 配置文件。 二、…

Visual Studio 2015 中 SDL2 开发环境的搭建

Visual Studio 2015 中 SDL2 开发环境的搭建 Visual Studio 2015 中 SDL2 开发环境的搭建新建控制台工程拷贝并配置 SDL2 开发文件拷贝 SDL2 开发文件配置 SDL2 开发文件 测试SDL2 开发文件的下载链接 Visual Studio 2015 中 SDL2 开发环境的搭建 新建控制台工程 新建 Win32 …

学习使用echats实现双刻度echarts双Y轴,左右Y轴数据的方法

学习使用echats实现双刻度echarts双Y轴&#xff0c;左右Y轴数据的方法 代码效果图 代码 <!--此示例下载自 https://echarts.apache.org/examples/zh/editor.html?cline-stack&langjs --> <!DOCTYPE html> <html lang"en" style"height: 10…

工业机器人与计算机技术:驱动现代工业变革

工业机器人与计算机技术&#xff1a;驱动现代工业变革 随着科技的飞速发展&#xff0c;工业机器人与计算机技术已经成为现代工业制造的核心驱动力。这两者之间的联系日益紧密&#xff0c;共同推动着工业生产的自动化、智能化和高效化。 一、工业机器人&#xff1a;从机械手臂…

以太坊代币标准解读及相关Dapp的搭建

文章目录 什么是以太坊代币标准1、什么是以太坊2、以太坊代币标准 同质化代币 Dapp 搭建1、MetaMask 的安装2、Ganache 的安装3、实现 ERC-20 代币协议4、前端页面的编写5、部署流程及操作演示 什么是以太坊代币标准 1、什么是以太坊 以太坊&#xff08;Ethereum&#xff09;是…

Linux环境grep搜索方法记录

1 grep grep 命令&#xff0c;用来搜索字符串所在位置&#xff0c;可以具体到不同文件&#xff0c;不同行&#xff1b; 在Linux 下&#xff0c;查看命令释义如下 zhaocubuntu2004:~$ grep --help Usage: grep [OPTION]... PATTERNS [FILE]... Search for PATTERNS in each FI…

安装Hadoop:Hadoop的单机模式、伪分布式模式——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项

前言 Hadoop包括三种安装模式&#xff1a; 单机模式&#xff1a;只在一台机器上运行&#xff0c;存储是采用本地文件系统&#xff0c;没有采用分布式文件系统HDFS&#xff1b;伪分布式模式&#xff1a;存储采用分布式文件系统HDFS&#xff0c;但是&#xff0c;HDFS的名称节点…

【VRTK】【VR开发】【Unity】18-VRTK与Unity UI控制的融合使用

课程配套学习项目源码资源下载 https://download.csdn.net/download/weixin_41697242/88485426?spm=1001.2014.3001.5503 【背景】 VRTK和Unity自身的UI控制包可以配合使用发挥效果。本篇就讨论这方面的实战内容。 之前可以互动的立体UI并不是传统的2D UI对象,在实际使用中…

Mac 安装 Minikube 及解决 “[ERROR ImagePull]: failed to pull image“ 问题

文章目录 1. 引言2. Mac 安装 Docker3. Mac 安装 Minikube4. 拉起集群4.1 启动4.2 验证 5. 参考 1. 引言 Minikube 是一种轻量化的 Kubernetes 集群&#xff0c;旨在帮助开发者和学习者更好地学习和体验 Kubernetes 的功能。它可以在个人计算机的虚拟化环境中快速构建和启动 Ku…