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

发布时间:2026/10/7 16:36:52
基于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-javaMySQL 驱动、lombok简化实体类。如果源码用的是 MyBatis-Plus那基本不用写太多 XML实体类加注解就能映射表。!-- pom.xml 关键依赖片段 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3/version !-- 按源码实际版本调整 -- /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/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.Driver5.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~16Vue 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以及连接串里有没有加characterEncodingutf8。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连接串加useUnicodetruecharacterEncodingutf8Spring 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.port9090前端改devServer.port8081同时检查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 打包部署后刷新 404Vue 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.includehealth,info,metrics按需开放不要全部暴露到公网。5.2 用 ECharts 做药品销售统计图演示视频里如果只有表格会显得单薄加一个 ECharts 柱状图展示近 7 天出库量或者饼图展示药品类别占比效果会好很多。Vue 里用echarts的init方法绑定一个div数据从后端/api/stat/sales接口拿。注意图表容器要有明确高度否则渲染不出来。参数上xAxis的type设成categoryyAxis设成value数据更新时调setOption而不是重新init。5.3 验证系统是否真正可用的三个检查点第一个检查点新增一个药品入库 100 盒出库 30 盒查库存是不是 70。第二个检查点把某个批号的效期改成 60 天后看预警列表里有没有它。第三个检查点用普通店员账号登录看能不能看到删除药品的按钮——如果能看到说明权限拦截没生效。这三个点过了系统基本就能拿去演示了。5.4 源码阅读与二次开发的入手顺序拿到源码后不要从头到尾读按这个顺序效率最高先看application.yml确认数据库和端口配置再看entity包了解表结构然后看controller包知道有哪些接口最后看service包理解业务逻辑。前端先看router知道有哪些页面再看api目录知道调了哪些后端接口。二次开发时加新功能就照着已有的 Controller-Service-Mapper 三层抄一遍改改表名和字段就行。我自己的习惯是每次改完代码先跑一遍那三个检查点确认没把原来的功能弄坏。药品管理系统的核心就是库存和效期这两块不出错其他都是锦上添花。希望帮到你。本文还有配套的精品资源点击获取