1. 项目概述:SpringBoot+Vue药品管理系统全栈解决方案
这个基于SpringBoot+Vue的药品管理系统是我在指导计算机专业毕业设计过程中反复打磨的一个经典案例。它完整覆盖了药品从入库到销售的全生命周期管理,特别适合作为Java Web方向的毕业设计选题。系统采用前后端分离架构,后端使用SpringBoot提供RESTful API,前端采用Vue.js构建响应式界面,数据库使用MySQL并附带了完整的SQL初始化脚本。
提示:这个项目之所以适合毕业设计,是因为它既包含了CRUD基础操作,又涉及库存管理、报表统计等业务逻辑,能够全面展示学生的技术能力。我在实际教学中发现,90%的药品管理系统的核心需求都可以用这个架构实现。
系统主要包含以下功能模块:
- 药品基础信息管理(分类、规格、供应商)
- 库存管理(入库、出库、库存预警)
- 销售管理(收银台、销售记录)
- 报表统计(销售分析、库存周转率)
- 系统管理(用户、角色、权限)
2. 技术架构深度解析
2.1 后端技术栈选型
SpringBoot 2.7.x版本是这个项目的最佳选择,原因有三:
- 自动配置特性大幅简化了SSM框架的整合
- 内嵌Tomcat服务器便于打包部署
- 丰富的Starter依赖(我们主要用到了:spring-boot-starter-web, spring-boot-starter-data-jpa, spring-boot-starter-security)
数据库访问层采用JPA+Hibernate的组合而非MyBatis,这是考虑到:
- 药品管理系统的数据关系相对规整
- JPA的Repository接口能快速实现基础CRUD
- 审计功能(@CreatedDate等注解)可以自动记录操作时间
java复制// 典型的药品实体类设计示例
@Entity
@Table(name = "medicine")
public class Medicine {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Enumerated(EnumType.STRING)
private MedicineType type;
@ManyToOne
@JoinColumn(name = "supplier_id")
private Supplier supplier;
// 其他字段和方法...
}
2.2 前端技术方案
Vue 3.x + Element Plus的组合提供了良好的开发体验:
- Composition API更适合复杂业务逻辑组织
- Element Plus的表格、表单组件能快速构建管理界面
- Axios处理HTTP请求,配合SpringSecurity实现JWT认证
前端项目结构建议如下:
code复制src/
├── api/ # 接口定义
├── assets/ # 静态资源
├── components/ # 公共组件
├── router/ # 路由配置
├── stores/ # Pinia状态管理
├── utils/ # 工具函数
└── views/ # 页面组件
3. 核心业务模块实现
3.1 药品库存管理设计
库存管理是系统的核心难点,需要处理并发问题和事务一致性。我们采用乐观锁机制防止超卖:
java复制@Service
@Transactional
public class InventoryService {
@Autowired
private MedicineRepository medicineRepo;
public void stockIn(Long medicineId, int amount) {
Medicine medicine = medicineRepo.findById(medicineId)
.orElseThrow(() -> new BusinessException("药品不存在"));
// 使用版本号控制并发
int affected = medicineRepo.increaseStock(
medicineId,
amount,
medicine.getVersion());
if (affected == 0) {
throw new OptimisticLockingFailureException("库存更新冲突");
}
}
}
对应的SQL脚本片段:
sql复制UPDATE medicine
SET stock = stock + #{amount},
version = version + 1
WHERE id = #{id} AND version = #{version}
3.2 销售业务实现
销售模块需要处理以下业务逻辑:
- 生成唯一订单号(日期+随机数)
- 校验库存是否充足
- 扣减库存
- 记录销售明细
- 更新会员积分(如有)
vue复制<!-- 前端收银台核心代码示例 -->
<template>
<el-table :data="cartItems">
<el-table-column prop="name" label="药品名称"/>
<el-table-column label="数量">
<template #default="{row}">
<el-input-number v-model="row.quantity" :min="1" :max="row.stock"/>
</template>
</el-table-column>
<!-- 其他列... -->
</el-table>
<el-button type="primary" @click="handleCheckout">结账</el-button>
</template>
<script setup>
const handleCheckout = async () => {
try {
await axios.post('/api/sales', {
items: cartItems.value,
paymentMethod: 'CASH'
});
ElMessage.success('销售成功');
} catch (err) {
ElMessage.error(err.response?.data?.message || '销售失败');
}
};
</script>
4. 项目部署与接口文档
4.1 数据库初始化
项目提供的SQL脚本包含:
- 表结构定义(DDL)
- 基础数据初始化(药品分类、管理员账号等)
- 视图创建(用于报表查询)
执行顺序建议:
- 创建数据库:
CREATE DATABASE medicine_db CHARACTER SET utf8mb4; - 执行主SQL脚本:
mysql -u root -p medicine_db < init.sql
4.2 接口文档规范
采用Swagger + OpenAPI 3.0生成交互式文档,关键配置:
java复制@Configuration
@OpenAPIDefinition(
info = @Info(
title = "药品管理系统API",
version = "1.0",
description = "毕业设计项目接口文档"
)
)
public class SwaggerConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList("JWT"))
.components(new Components()
.addSecuritySchemes("JWT",
new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")));
}
}
访问地址:http://localhost:8080/swagger-ui.html
5. 毕业设计常见问题解决方案
5.1 典型错误排查
- 跨域问题:确保后端添加了CORS配置
java复制@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*");
}
};
}
- JWT失效问题:检查前端请求头是否正确添加
javascript复制axios.interceptors.request.use(config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
5.2 功能扩展建议
如果想提升项目难度,可以考虑:
- 加入Redis缓存药品分类数据
- 使用EasyExcel实现批量导入导出
- 集成WebSocket实现库存预警通知
- 添加数据分析模块(使用ECharts)
java复制// Redis缓存示例
@Cacheable(value = "medicineTypes", key = "'all'")
public List<MedicineType> getAllTypes() {
return typeRepository.findAll();
}
6. 项目优化与性能考量
6.1 数据库查询优化
针对药品列表页的N+1查询问题,使用@EntityGraph优化:
java复制@EntityGraph(attributePaths = {"supplier"})
@Query("SELECT m FROM Medicine m WHERE m.stock < :threshold")
List<Medicine> findLowStockItems(@Param("threshold") int threshold);
6.2 前端性能技巧
- 表格数据分页加载(使用el-pagination组件)
- 路由懒加载减少首屏体积
javascript复制const MedicineList = () => import('./views/MedicineList.vue');
- 使用Webpack的SplitChunks分离第三方库
javascript复制// vue.config.js
configureWebpack: {
optimization: {
splitChunks: {
chunks: 'all'
}
}
}
在项目开发过程中,我发现药品批号管理是学生最容易忽略的细节。建议在实体设计中预留batchNumber字段,并实现以下业务规则:
- 同一药品不同批号视为不同库存
- 出库时优先使用较早批号(FIFO原则)
- 批号过期预警功能
