news 2026/10/7 16:36:49

基于Spring Boot+Vue+MySQL的药品信息管理系统:从设计到部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Spring Boot+Vue+MySQL的药品信息管理系统:从设计到部署

简介:这份资源是面向高校计算机专业学生与Java初学者的一套药品信息管理系统完整项目,基于Spring Boot、Vue与MySQL技术栈开发,可作为毕业设计、课程设计或企业级后台管理练手项目。系统分为管理员与员工两类角色:管理员负责管理员信息、员工信息、药品类别与药品信息管理,并以表格和图表形式统计库存;员工可修改个人资料、管理供应商信息、查看药品信息,并完成药品入库、出库与库存统计等操作,业务闭环较为完整。压缩包共约2000个文件,以1430个md说明文档、507个js脚本、54个json配置为主,另含sql建库脚本、docx论文与html页面,整体约120.75MB,目录结构清晰,便于按模块查阅源码与文档。资源还附带需求分析、演示视频与设计实现论文,能帮助读者快速理解系统架构、数据库设计与前后端交互逻辑,对照源码完成部署与二次开发。目前已有98人学习下载,适合需要完整项目方案与排错参考的读者。

1. 药品信息管理系统到底在管什么:从一张入库单说起

药房库管老张每天要面对三件事:供货商送来的药品批号对不对、库存里哪些药还有三个月过期、处方发药时系统能不能立刻扣减对应批次的库存。这三件事背后,就是一套药品信息管理系统要解决的核心问题——批号追溯、效期预警、库存联动。基于 Spring Boot + Vue + MySQL 的药品信息管理系统,本质上是把药品的基础档案、采购入库、销售出库、库存盘点、效期告警这几条业务线串成一个闭环,让每一盒药的流向都能在数据库里查到记录。

这套技术栈适合谁?适合正在做课程设计或毕业设计的计算机专业学生,也适合中小药店、社区诊所里想自己搭一套轻量管理工具的开发者。Spring Boot 负责后端接口和业务逻辑,Vue 负责前端页面交互,MySQL 存数据,三者配合能覆盖从药品录入到报表导出的完整流程。需求分析阶段要搞清楚角色权限——管理员、库管员、普通店员看到的功能不一样,这是后面做权限拦截的基础。演示视频里通常会走一遍“新增药品→入库→出库→库存查询”的流程,源码和论文则分别对应实现细节和设计文档。这一章先把业务边界划清楚,后面再讲怎么把环境跑起来、表怎么设计、接口怎么写。

2. 环境搭建与项目骨架:把 Spring Boot、Vue、MySQL 三件套跑通

2.1 后端 Spring Boot 工程的初始化与依赖选择

拿到源码后第一步不是急着改代码,而是先把后端跑起来。我一般用 IntelliJ IDEA 社区版打开后端目录,确认pom.xml里的 Spring Boot 版本和 JDK 版本匹配。药品信息管理系统常见的依赖包括spring-boot-starter-web(提供 REST 接口)、mybatis-plus-boot-starter或spring-boot-starter-data-jpa(操作数据库)、mysql-connector-java(MySQL 驱动)、lombok(简化实体类)。如果源码用的是 MyBatis-Plus,那基本不用写太多 XML,实体类加注解就能映射表。

<!-- pom.xml 关键依赖片段 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3</version> <!-- 按源码实际版本调整 --> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>

逻辑说明:spring-boot-starter-web内嵌 Tomcat,启动后默认监听 8080 端口;MyBatis-Plus 的BaseMapper提供了单表增删改查,药品档案、库存记录这类表用它能省掉大量重复 SQL。参数方面,如果 8080 被占用,在application.yml里改server.port即可,比如改成 9090。注意 MySQL 驱动版本要和本机 MySQL 版本对应,MySQL 8.0 以上用com.mysql.cj.jdbc.Driver,5.7 用com.mysql.jdbc.Driver,写错会报Loading class ... is deprecated或直接连接失败。

2.2 Vue 前端环境配置与依赖安装

前端部分通常是 Vue 2 或 Vue 3 项目,用 Vue CLI 或 Vite 构建。先确认本机 Node.js 版本,Vue 2 项目建议 Node 14~16,Vue 3 + Vite 建议 Node 16 以上。进入前端目录后执行npm install或yarn install,如果卡在某个包下载不动,换国内镜像源再试。安装完成后npm run serve启动开发服务器,默认端口 8080 或 8081,如果和后端端口冲突,在vue.config.js里改devServer.port。

# 前端启动常用命令 npm install # 安装依赖,首次执行时间较长 npm run serve # 开发模式启动,支持热更新 npm run build # 打包生成 dist 目录,用于部署

逻辑说明:npm run serve启动的是开发服务器,接口请求通常通过vue.config.js里的proxy转发到后端,避免跨域。参数上,proxy的target要写成后端实际地址,比如http://localhost:9090。如果打包后要放进 Spring Boot 的static目录,publicPath要改成./,否则刷新页面会 404。这里有个血泪经验:前端路由用 history 模式时,Spring Boot 需要配置一个 fallback 到index.html的控制器,不然直接访问/drug/list这种路径会报 404。

2.3 MySQL 建库建表与初始数据导入

数据库是药品信息管理系统的地基。先在 MySQL 里建一个库,字符集用utf8mb4,排序规则utf8mb4_general_ci。然后执行源码里附带的.sql文件,通常会创建drug_info(药品档案)、stock_in(入库记录)、stock_out(出库记录)、inventory(库存)、user(用户)等表。导入前注意检查 SQL 文件里有没有CREATE DATABASE语句,如果没有就手动建库再USE。

-- 建库与建表示例(简化版) CREATE DATABASE drug_mgr DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE drug_mgr; CREATE TABLE drug_info ( id BIGINT PRIMARY KEY AUTO_INCREMENT, drug_name VARCHAR(100) NOT NULL COMMENT '药品名称', batch_no VARCHAR(50) NOT NULL COMMENT '生产批号', expire_date DATE NOT NULL COMMENT '有效期至', stock_qty INT DEFAULT 0 COMMENT '库存数量', create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) COMMENT '药品基础信息表';

逻辑说明:batch_no和expire_date是药品管理的核心字段,批号用于追溯,效期用于预警。stock_qty不建议直接手动改,而是通过入库、出库操作自动增减,避免数据不一致。参数上,expire_date用DATE类型就够,不需要精确到秒。导入数据时如果遇到Incorrect string value报错,检查数据库和表的字符集是不是utf8mb4,以及连接串里有没有加characterEncoding=utf8。

3. 核心业务表设计与接口实现:药品档案、库存、效期怎么落库

3.1 药品档案表与库存表的字段设计要点

药品档案表不是简单记个名字就行。实际业务里,同一种药可能有不同厂家、不同规格、不同批号,所以drug_info表里通常要有drug_code(药品编码)、drug_name、spec(规格)、manufacturer(生产厂家)、unit(单位)、category(类别)这些字段。库存表inventory则要关联drug_id和batch_no,因为同一药品不同批号的效期不一样,必须分开管理。常见做法是库存表用drug_id + batch_no做联合唯一索引,入库时如果已有相同批号就累加数量,没有就新增一条。

字段名类型说明是否必填
drug_codeVARCHAR(50)药品编码,唯一是
drug_nameVARCHAR(100)药品名称是
specVARCHAR(50)规格,如 0.25g*24粒是
batch_noVARCHAR(50)生产批号是
expire_dateDATE有效期至是
stock_qtyINT当前库存是
warn_thresholdINT库存预警阈值否

逻辑说明:warn_threshold是给库存预警用的,比如设成 10,当stock_qty低于 10 时前端标红提醒。batch_no和expire_date组合起来能算出近效期药品列表。参数上,expire_date建议加索引,因为效期查询是高频操作。注意不要用drug_name做唯一键,同名不同厂的药很常见,用drug_code更稳妥。

3.2 入库与出库接口的编写与库存联动

入库接口要做两件事:写一条入库记录,同时更新库存。出库接口同理,但要先校验库存够不够。用 MyBatis-Plus 的话,可以在 Service 层用@Transactional保证两个操作要么都成功要么都回滚。下面是一个简化的入库接口示例。

@RestController @RequestMapping("/api/stock") public class StockController { @Autowired private InventoryService inventoryService; @PostMapping("/in") @Transactional(rollbackFor = Exception.class) public Result stockIn(@RequestBody StockInDTO dto) { // 1. 写入库记录 StockIn record = new StockIn(); record.setDrugId(dto.getDrugId()); record.setBatchNo(dto.getBatchNo()); record.setQty(dto.getQty()); record.setInTime(new Date()); stockInMapper.insert(record); // 2. 更新库存:存在则累加,不存在则新增 Inventory inv = inventoryService.getByDrugIdAndBatch(dto.getDrugId(), dto.getBatchNo()); if (inv == null) { inv = new Inventory(); inv.setDrugId(dto.getDrugId()); inv.setBatchNo(dto.getBatchNo()); inv.setStockQty(dto.getQty()); inventoryService.save(inv); } else { inv.setStockQty(inv.getStockQty() + dto.getQty()); inventoryService.updateById(inv); } return Result.ok("入库成功"); } }

逻辑说明:@Transactional注解保证入库记录和库存更新在同一个事务里,任何一步失败都会回滚。参数上,StockInDTO里至少要包含drugId、batchNo、qty,前端传参时注意qty要大于 0。出库接口要多一步stockQty >= qty的判断,不够就抛异常返回“库存不足”。这里有个踩坑点:并发出库时可能两个请求同时读到相同库存然后都扣减,导致超卖。解决办法是在库存表加乐观锁版本号,或者用UPDATE inventory SET stock_qty = stock_qty - ? WHERE drug_id = ? AND batch_no = ? AND stock_qty >= ?这种原子操作。

3.3 效期预警与库存预警的查询实现

效期预警的 SQL 逻辑不复杂:查expire_date在当前日期到未来 90 天之间的库存记录,按expire_date升序排列。库存预警则是查stock_qty < warn_threshold的记录。这两个查询可以放在一个/api/warn/list接口里返回,前端用两个 Tab 展示。

-- 近效期药品查询(90天内) SELECT d.drug_name, d.spec, i.batch_no, i.expire_date, i.stock_qty FROM inventory i JOIN drug_info d ON i.drug_id = d.id WHERE i.expire_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 90 DAY) ORDER BY i.expire_date ASC; -- 库存不足预警 SELECT d.drug_name, d.spec, i.stock_qty, d.warn_threshold FROM inventory i JOIN drug_info d ON i.drug_id = d.id WHERE i.stock_qty < d.warn_threshold;

逻辑说明:BETWEEN ... AND ...包含边界值,DATE_ADD(CURDATE(), INTERVAL 90 DAY)算出 90 天后的日期。参数上,90 天这个阈值可以做成配置项,不同药店要求不一样。注意expire_date如果存的是字符串而不是DATE类型,比较会出错,建表时一定要用日期类型。前端拿到数据后用表格展示,近效期行标黄,已过期行标红,这是演示视频里比较出效果的部分。

4. 避坑与排查:药品管理系统落地时最容易翻车的 5 个地方

4.1 中文乱码:从数据库到前端一路问号

现象:新增药品时名称显示成???或者乱码。原因通常是 MySQL 库、表、连接串三处字符集不一致。解决:建库时指定utf8mb4,连接串加useUnicode=true&characterEncoding=utf8,Spring Boot 的application.yml里url也要带上这个参数。如果已经建了表,用ALTER TABLE drug_info CONVERT TO CHARACTER SET utf8mb4;改一下。

4.2 端口冲突:8080 被占导致启动失败

现象:Spring Boot 启动报Port 8080 was already in use,或者 Vue 启动报端口被占用。原因:本机装了其他服务(比如另一个 Tomcat、Nginx)占了 8080。解决:后端改server.port=9090,前端改devServer.port=8081,同时检查vue.config.js里的proxy目标端口有没有同步改。

4.3 跨域请求被拦截:前端调后端接口报 CORS 错误

现象:浏览器控制台报Access-Control-Allow-Origin相关错误。原因:前端开发服务器和后端端口不同,浏览器同源策略拦截。解决:后端加一个全局 CORS 配置类,允许前端地址访问;或者在前端vue.config.js里配proxy转发。两种方式选一种就行,不要同时用,否则可能重复加头导致报错。

4.4 库存扣减出现负数:并发下的超卖问题

现象:出库操作后库存变成负数。原因:两个请求同时读到相同库存,各自扣减后写回,后写的覆盖了先写的。解决:用原子 SQLUPDATE inventory SET stock_qty = stock_qty - ? WHERE drug_id = ? AND batch_no = ? AND stock_qty >= ?,根据返回的影响行数判断是否成功。或者给库存表加version字段做乐观锁。

4.5 打包部署后刷新 404:Vue history 模式与 Spring Boot 静态资源冲突

现象:npm run build后把dist放进 Spring Boot 的static目录,访问首页正常,但刷新/drug/list就 404。原因:Vue 用 history 模式时,前端路由由 JavaScript 控制,刷新时浏览器直接请求后端,后端没有对应路径。解决:Spring Boot 加一个ErrorController或者配置类,把所有未匹配的请求转发到index.html。或者前端改用 hash 模式,但 URL 会带#,看个人取舍。

5. 从能跑到好用:药品管理系统的进阶技巧与验证方法

5.1 用 Spring Boot Admin 监控接口健康状态

项目跑起来之后,怎么知道后端接口是不是正常?我一般会加spring-boot-starter-actuator暴露健康检查端点,再配一个 Spring Boot Admin 服务端来可视化监控。这样能实时看到/health、/metrics这些信息,接口响应慢或者数据库连接池满了能提前发现。配置上,management.endpoints.web.exposure.include=health,info,metrics按需开放,不要全部暴露到公网。

5.2 用 ECharts 做药品销售统计图

演示视频里如果只有表格会显得单薄,加一个 ECharts 柱状图展示近 7 天出库量,或者饼图展示药品类别占比,效果会好很多。Vue 里用echarts的init方法绑定一个div,数据从后端/api/stat/sales接口拿。注意图表容器要有明确高度,否则渲染不出来。参数上,xAxis的type设成category,yAxis设成value,数据更新时调setOption而不是重新init。

5.3 验证系统是否真正可用的三个检查点

第一个检查点:新增一个药品,入库 100 盒,出库 30 盒,查库存是不是 70。第二个检查点:把某个批号的效期改成 60 天后,看预警列表里有没有它。第三个检查点:用普通店员账号登录,看能不能看到删除药品的按钮——如果能看到,说明权限拦截没生效。这三个点过了,系统基本就能拿去演示了。

5.4 源码阅读与二次开发的入手顺序

拿到源码后不要从头到尾读,按这个顺序效率最高:先看application.yml确认数据库和端口配置,再看entity包了解表结构,然后看controller包知道有哪些接口,最后看service包理解业务逻辑。前端先看router知道有哪些页面,再看api目录知道调了哪些后端接口。二次开发时,加新功能就照着已有的 Controller-Service-Mapper 三层抄一遍,改改表名和字段就行。

我自己的习惯是,每次改完代码先跑一遍那三个检查点,确认没把原来的功能弄坏。药品管理系统的核心就是库存和效期,这两块不出错,其他都是锦上添花。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 16:35:18

SD-WAN进入规模落地期,企业广域网架构迎来新变化

过去十年&#xff0c;企业广域网&#xff08;WAN&#xff09;的演进几乎被一条主线贯穿&#xff1a;从“以专线为中心”向“以应用为中心”迁移。2026年&#xff0c;SD-WAN&#xff08;软件定义广域网&#xff09;已不再是一个需要论证的新概念&#xff0c;而是成为了多数中大型…

作者头像 李华
网站建设 2026/10/7 16:32:56

Java AI应用高并发实战:异步化设计、线程池调优与踩坑总结

最近两周我一直在调一个 Java 写的 AI 应用&#xff0c;真真切切体会到了什么叫“并发一上来&#xff0c;问题全暴露”。这个应用本身不复杂&#xff1a;用户提需求&#xff0c;我们把 prompt 拆解成多路子任务&#xff0c;丢给不同的大模型并行处理&#xff0c;再把结果汇总返…

作者头像 李华
网站建设 2026/10/7 16:32:45

深度 | 鸿海德州厂投产:美国拿走的是组装,台湾守住的是CoPoS核心技术,这轮供应链本土化被误读了

鸿海德州厂启动 AI 服务器生产&#xff0c;全力支援甲骨文的云基础设施。甲骨文 OCI 负责人亲访德州厂&#xff0c;见证英伟达 Vera Rubin 系统迈向量产。 同一批新闻里还有另一句&#xff1a;台积电把玻璃材料列为 CoPoS 架构的核心材料选项&#xff0c;预计 2028 年量产。这两…

作者头像 李华
网站建设 2026/10/7 16:32:39

基于 UE5 的瓷砖实时渲染方案:连纹、釉面光泽与尺寸精度的工程实现

基于 UE5 的瓷砖实时渲染方案&#xff1a;连纹、釉面光泽与尺寸精度的工程实现 直接回答 传统 AI 换砖工具之所以“不像”&#xff0c;根源在于它们处理的是像素&#xff0c;而不是空间中的物理对象。基于 UE5 的实时渲染方案&#xff0c;通过次表面散射材质、世界坐标 UV 投影…

作者头像 李华