ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Spring Boot+Vue+MySQL前后端分离药品管理系统设计与实操指南

Spring Boot+Vue+MySQL前后端分离药品管理系统设计与实操指南 简介本资源是一套面向高校计算机专业毕业设计的完整药房管理信息系统解决方案聚焦中小型药店信息化管理痛点适用于Java全栈开发初学者与毕设学生。系统采用Spring Boot Vue前后端分离架构MySQL作为持久层覆盖用户管理、药品/保健品分类与信息维护、疫情常识发布、订单处理及系统权限配置等十余个核心模块具备典型B/S架构工程实践价值。压缩包共93.19MB包含可直接运行的源码、结构清晰的毕业论文含需求分析与系统设计、答辩用PPT、详细开发文档及功能演示视频各类文件协同支撑从编码到汇报的全流程。目前已有77人学习下载内容组织注重教学适配性源码含完整前后端工程结构与注释论文符合本科毕设规范视频实录关键操作流程文档说明部署步骤与常见问题便于快速理解系统逻辑并完成二次开发或答辩准备。 做毕设或者公司练手项目的时候我见过太多人一头扎进“大而全”的系统里结果光环境就折腾了两周。今天拿这个“逍遥大药房管理系统”当例子聊聊为什么 Spring Boot Vue MySQL 这套前后端分离的组合特别适合做药品管理这类业务清晰、流程固定的管理系统。本文不贴大段源码重点讲清楚每个模块为什么这么设计、数据表为什么这么建、联调时坑在哪最后附上完整可落地的部署运行步骤和问题排查经验给准备动手复现或二次开发的朋友做参考。1. 项目整体设计与技术选型思路1.1 为什么是前后端分离而不是传统JSP如果你去看前几年的毕设或者小公司内部系统很大概率是 JSP Spring MVC 一套搞定页面扔在 WEB-INF 下面前后端代码揉在一起。逍遥大药房这个项目选了前后端分离不是赶时髦而是这类管理系统确实有分离的必要。药品管理系统的业务特点是表单多、状态多、权限分明前端交互复杂程度上去了JSP 那种服务端渲染的方式会让页面切换变的很重。你点一个“入库单查询”整个页面刷新一遍用户体感差开发时前后端一起改也容易互相踩脚。分离之后前端只关心页面渲染和用户交互通过 Axios 调后端接口拿 JSON 数据后端只负责业务逻辑和数据库读写接口定义清楚了两边并行开发没有阻塞。而且分开部署也灵活前端可以扔 Nginx后端独立起在 8080 端口扩展的时候加个负载均衡就行。对于药房这种可能以后要扩展连锁门店业务的系统前后端分离天然就是为多端接入准备的。1.2 Spring Boot、Vue、MySQL 各自的角色与选型考量这套组合里每个角色都不可替代。后端用 Spring Boot核心价值是“约定大于配置”。药房系统的业务逻辑本身并不复杂无非是增删改查加一些状态流转如果花大量时间在 XML 配置和依赖管理上就本末倒置了。Spring Boot 的自动配置特性让你能快速把项目跑起来内嵌 Tomcat 更是省去了单独装服务器的麻烦。我见过有人用 Spring Cloud 那套做这种单体就够的系统完全是给自己找罪受服务拆分的复杂度远超业务本身。前端选 Vue 而不是 React主要考虑的是上手成本和生态。Vue 的模板语法更接近 HTML 思维对做管理系统的团队来说学习曲线平缓。配合 Element UI 组件库表格、表单、对话框、分页这些管理系统的高频组件开箱即用UI 风格统一开发效率很高。具体到药房这种场景需要一个像“药品信息录入”这样的动态表单Vue 的双向绑定和响应式机制写起来比操作 DOM 舒服太多。MySQL 在数据库层面的优势是成熟稳定、运维成本低、资料多。药房系统数据量再大也到不了亿级单库单表加合理索引完全够用没必要上 PostgreSQL 或者拆分布式。MySQL 的事务支持对销售单这种要求“要么全成功要么全失败”的场景至关重要。1.3 系统功能模块划分我从项目的实际功能出发把它拆成五个核心模块来看系统管理模块用户登录、退出、密码修改、角色权限控制。药品管理模块药品信息的增删改查、药品分类管理、药品图片上传。库存管理模块入库单管理、出库单管理、库存预警、批次有效期管理。销售管理模块收银台/销售开单、销售记录查询、退换货处理。统计报表模块销售额趋势、药品销售排行、库存周转情况。为什么要这样划分因为药房管理系统的数据流转是有清晰链条的——采购入库产生库存销售出库消耗库存库存变化又反哺采购计划。模块之间的边界画清楚了接口设计就不会混乱。比如你查“某个药品的库存”肯定走的是库存模块的接口而不是在销售模块里查职责分离是后端 Controller 设计的基本原则。2. 核心功能与数据库设计实战2.1 药品管理模块的设计细节药品管理是整个系统最基础也最核心的模块。和普通的商品管理不同药品有几个特殊属性必须考虑批准文号、生产厂家、规格、单位、有效期、存储条件。在页面上药品信息表单通常包含这些字段药品编号、药品名称、通用名、分类、规格、单位、生产厂家、批准文号、采购价、零售价、库存上下限、存储条件、有效期至。新增药品和编辑药品共用一个表单组件通过路由参数或对话框的type判断是“新增”还是“编辑”。后端接口设计遵循 RESTful 风格但要注意一点药品列表查询必须支持模糊搜索和多条件组合。用户输入“阿莫”应该能搜出“阿莫西林胶囊”和“阿莫西林分散片”所以接口参数建议用keyword categoryId status组合SQL 层面用LIKE CONCAT(%, #{keyword}, %)实现模糊匹配。这里有一个前端比较容易被忽视的细节药品分类在大多数药房系统里是两级结构比如“抗生素类”下面有“青霉素类”“头孢菌素类”。如果做成单级下拉框数据一多就找不到了。建议用 Element UI 的el-cascader级联选择器后端只存categoryId前端根据选中路径拆出父级 ID 和子级 ID。2.2 库存管理与批次有效期药房的库存和普通电商库存不一样有严格的批次和效期要求。同一个药品不同批号进价可能不同有效期也不同销售出库时必须遵守“先进先出”原则——先到期的先卖否则容易出现药品过期报废。在数据库设计上库存表要与入库单关联记录每个批次的剩余数量。核心字段drug_id、batch_no批号、manufacture_date生产日期、expire_date有效期至、quantity剩余数量、purchase_price采购价。当某个批次数量归零时逻辑上该批次关闭不再参与出库匹配。库存预警是药房系统的刚需功能。设置安全库存阈值当某药品的总库存低于阈值时在首页或库存列表给出醒目提醒同时在数据初始化时置为待采购状态。实现上最简单的方案是定时任务每天扫一遍所有药品把低于安全库存的丢到预警表里也可以不做定时任务每次入库、出库操作后触发一次检查实时性更好代价是多几次数据库查询。2.3 销售开单与库存扣减的原子性销售模块是药房业务的重头戏这里有一个并发安全陷阱多个窗口同时收银同一个药品被同时卖出库存可能扣成负数。解决思路是在扣减库存的 SQL 里加条件判断UPDATE drug_stock SET quantity quantity - #{saleCount} WHERE drug_id #{drugId} AND quantity #{saleCount}这条语句的核心价值在于利用数据库行锁保证原子性。如果影响行数为 0说明库存不够直接抛出业务异常提示“库存不足”前端收到后中止提交订单。加上这层保障即使两个用户同时提交也只有一个能成功扣减。销售订单和销售明细建议用事务包裹主表保存订单总金额、实收金额、操作人、时间子表保存每个药品的单价、数量、小计。MySQL 默认 InnoDB 引擎支持事务在 Service 层加Transactional注解就能保证要么全部写入成功要么全部回滚。2.4 数据库表结构设计要点设计药房系统数据库时我踩过一个坑——药房相关的表命名尽量语义化不要用 a、b、c 这种缩写。下面这张表是整理后的核心表清单表名用途关键字段sys_user系统用户id, username, password, real_name, role_idsys_role角色表id, role_name, descriptiondrug_category药品分类id, parent_id, namedrug_info药品基本信息id, drug_code, name, category_id, spec, manufacturer, approval_number, retail_price, safe_stockdrug_stock药品库存批次id, drug_id, batch_no, expire_date, quantity, purchase_priceinbound_order入库单id, order_no, supplier_id, operator, total_count, create_timeinbound_order_item入库明细id, inbound_id, drug_id, batch_no, quantity, pricesale_order销售订单id, order_no, user_id, total_amount, receive_amount, status, create_timesale_order_item销售明细id, sale_id, drug_id, batch_id, price, countsupplier供应商id, name, contact, phone, address药品基本信息里不建议把库存数量直接放在 drug_info 表里虽然查询方便但每次出入库都要 update 汇总值并发高时容易出现数据不一致。更好的做法是库存只存在 drug_stock 表中按批次统计需要总库存时用SUM(quantity) GROUP BY drug_id查出配合索引性能完全够用。3. 环境搭建与项目运行实操3.1 开发环境版本搭配与安装这个项目基于 Spring Boot 2.1 开发对应的 JDK 版本建议 1.8不要一上来就装 JDK 17很多老依赖和配置会不兼容。MySQL 用 5.7 或 8.0 都可以需要注意 8.0 和 5.7 的驱动类名不同连接 URL 也要带serverTimezoneAsia/Shanghai否则会报时区错误。前端是 Vue 2.x 工程Node.js 版本建议 14 或 16。如果你装的是 Node 18 以上可能出现 node-sass 安装失败的问题解决方案是改用 sassdart-sass或者把 node-sass 换成对应版本的预编译二进制。用 npm 安装依赖时建议配置淘宝镜像源npm config set registry https://registry.npmmirror.com不配置镜像源在国内网络环境下node_modules 下载大概率卡在某个包上。前端开发环境的关键是 Vue CLI 版本必须与 Node 版本匹配。Vue CLI 4.x 支持 Node 8.95.x 需要 Node 12。在创建工程时建议固定 vue-cli 版本防止升级带来的兼容问题。3.2 后端的启动步骤与关键配置拿到项目源码后第一步是改配置文件。Spring Boot 项目的核心配置在application.yml里面数据源和端口是最需要关注的两项server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/yaofang?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver配置好后需要把数据库导入。项目通常会附带sql/init.sql文件直接用 Navicat 或命令行执行mysql -u root -p init.sql执行完成后检查一下sys_user表里有没有初始账号和密码如果没有需要手动插一条否则登录不上。我建议在导入后立刻确认一下SELECT * FROM sys_user;后端启动前确认 Maven 仓库配置了阿里云镜像在conf/settings.xml里加mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror3.3 前端的运行步骤与接口代理配置前端工程打开后先在根目录执行依赖安装npm install如果项目里面有package-lock.json建议直接用npm ci来安装速度更快也不会因为版本浮动产生意外问题。前端与后端联调时最大的坑是跨域。开发环境下有两种方案一是后端加 CORS 全局配置二是前端用 Vue CLI 的 proxy 代理。我更推荐第二种因为线上部署时前后端通常同域不需要额外处理跨域。vue.config.js里配置代理module.exports { devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: } } } } }注意这里有个细节如果后端接口路径是/api/user/login后端 Controller 的 RequestMapping 已经是/api开头那么 pathRewrite 就不用改如果后端路径没有/api前缀就需要用上面的方式重写否则会出现 404。启动前端npm run serve访问http://localhost:8081如果登录页能正常打开说明前端环境没问题。此时先做一次登录操作验证后端连通性如果发现网络请求报 404优先检查代理配置和后端接口前缀是否匹配。3.4 项目打包部署的注意点本地跑通后要打包上线的话前后端都要处理。后端用 Maven 打包mvn clean package -DskipTests生成的 jar 包直接用java -jar启动即可。需要注意服务器的内存配置Spring Boot 默认堆内存可能偏大小内存机器建议java -jar -Xms512m -Xmx512m yaofang-manage.jar前端打包npm run build生成dist目录把 dist 下的文件部署到 Nginx 的 html 目录即可。Nginx 配置要解决两个问题一是 history 模式路由刷新 404二是反向代理后端接口location /api/ { proxy_pass http://127.0.0.1:8080; } location / { try_files $uri $uri/ /index.html; }Vue Router 默认使用 hash 模式URL 带 #但如果项目里改成了 history 模式没有上面try_files这行刷新页面就会白屏这个坑很隐蔽排查时先确认是哪种路由模式。4. 常见问题与排查技巧实录4.1 MySQL 连接和初始化报错药房管理系统开发时数据库报错是出现频率最高的。常见的有三种。一种是连接报错Access denied for user rootlocalhost原因是密码不匹配或 MySQL 8.0 的认证插件问题。MySQL 8.0 默认使用 caching_sha2_password而老版本驱动不支持建议在连接 URL 里显式指定allowPublicKeyRetrievaltrueuseSSLfalse。另一种是中文乱码表结构导入后中文全部变成问号。这通常是因为创建数据库时没有指定 utf8mb4 字符集。推荐建库语句直接用CREATE DATABASE yaofang DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;utf8mb4 比 utf8 多的地方在于它是完整 Unicode 支持因为药房管理系统里可能有特殊符号或生僻字utf8mb4 能避免后面返工。还有一种是外键约束导致导入失败。如果 init.sql 里表的加载顺序有问题比如先建子表后建父表外键检查会报错。临时解决办法是导入前执行SET FOREIGN_KEY_CHECKS0;导入完再改回来。4.2 前后端接口联调 404 与跨域排查思路前端能打开页面后端也起来了但登录一提交就报 404 或 500。这时候我习惯先打开浏览器 F12 看 Network 面板确定请求发的地址和后端接口地址是否一致。常见情况是后端接口写的是/user/login前端请求写的却是/api/user/login代理也没有正确重写前缀结果 404。另一个常见情况是 Controller 类上没加CrossOrigin注解后端又没有全局 CORS 配置浏览器控制台报跨域错误请求连后端代码都没到。排查口诀先确定请求有没有到达后端看后端控制台日志到了再查业务逻辑没到就查前端代理和请求地址。日志里没有请求记录说明问题在网络层或代理层。4.3 依赖版本兼容性问题Spring Boot 2.x 对依赖版本很敏感。如果 pom.xml 里手动指定了某个依赖的高版本比如把 MyBatis 的版本调到 3.5.10 以上而 Spring Boot 2.1 内部管理的版本是 3.4.x可能出现类型转换异常或者其他诡异报错。建议不要随意指定版本除非特别清楚兼容性。前端这边 node-sass 是重灾区。项目如果指定node-sass4.x那要求 Node 不能超过 14。不换 Node 版本的话推荐把 node-sass 替换成 sassnpm uninstall node-sass npm install sass -D替换后注意代码里如果用了/deep/或::v-deep这类深度选择器编译器的写法可能有差异需要改成:deep()。4.4 几个容易被忽略的细节坑还有几个问题虽然不是报错型的但会直接影响系统可用性。JWT 登录 token 过期时间设置太短用户操作一会儿就弹出登录失效。建议过期时间设置为 2 小时以上或者做成“活跃即续期”的机制。数据库密码和前端表单密码传输是明文的虽然这个项目没有加 HTTPS但至少建议在后端加一层 MD5加盐处理后再入库避免数据库泄露时密码直接裸露。JWT 密钥也不要写死在代码里放到配置文件中或者用环境变量注入。Element UI 的表格组件默认不会自动处理“数据为空”的展示要在表格上设置empty-text暂无数据否则用户看到空白表格会误以为系统出错了。这个细节虽然简单但在演示视频里观感影响很大。5. 写在最后的个人经验药房管理系统这种毕业设计或练手项目看起来模块多、工作量大但核心也就是“一个表单 一张表 一个列表 一个弹窗”的排列组合真正有技术门槛的地方是库存扣减的事务处理和前后端联调的排错能力。如果你准备拿这个项目做二次开发我建议在现有基础上优先加这两个功能一个是操作日志记录谁在什么时间改了哪些药品价格另一个是药品效期提醒在药品过期前 30 天自动预警提示。这两个功能做进去系统的完整度和答辩的加分项都解决了。最后分享一个小技巧跑这个项目时先把后端启动日志里“Tomcat started on port 8080”这句话截出来看清楚了再去启动前端。很多人卡在“页面打不开”的问题上实际上是后端根本没起来这个顺序排查的效率最高。本文还有配套的精品资源点击获取
返回列表