1. 项目概述
这个基于SpringBoot的药店销售系统是一个典型的医药行业信息化解决方案。我在实际开发过程中发现,药店管理系统与传统零售系统存在显著差异,需要特别关注药品批号管理、效期预警、处方药销售控制等医药行业特有需求。
系统采用SpringBoot 2.7.x + MyBatis-Plus + Vue.js技术栈实现,包含完整的药品进销存管理、会员管理、销售统计等功能模块。源码结构清晰,采用分层架构设计,便于二次开发和业务扩展。
2. 核心功能解析
2.1 药品信息管理
药品作为特殊商品,其管理系统需要处理以下关键属性:
- 药品分类(处方药/OTC/医疗器械)
- 批准文号管理
- 批次号和有效期控制
- 库存预警阈值设置
数据库设计中特别需要注意:
sql复制CREATE TABLE `medicine` (
`id` bigint NOT NULL AUTO_INCREMENT,
`code` varchar(20) NOT NULL COMMENT '药品编码',
`name` varchar(100) NOT NULL,
`spec` varchar(50) NOT NULL COMMENT '规格',
`batch_number` varchar(50) NOT NULL COMMENT '批号',
`approval_number` varchar(50) NOT NULL COMMENT '批准文号',
`expire_date` date NOT NULL COMMENT '有效期',
`stock` int NOT NULL DEFAULT '0',
`warning_stock` int NOT NULL DEFAULT '10' COMMENT '库存预警值',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2 销售管理模块
处方药销售需要特殊处理流程:
- 执业药师审核处方
- 系统记录处方编号
- 限制购买数量
- 特殊药品销售登记
销售核心业务逻辑示例:
java复制public class SaleService {
@Transactional
public SaleResult saleMedicine(SaleDTO saleDTO) {
// 1. 校验处方药
if(medicine.isPrescription()) {
validatePrescription(saleDTO.getPrescriptionNo());
}
// 2. 库存检查
checkStock(saleDTO.getMedicineCode(), saleDTO.getQuantity());
// 3. 创建销售记录
SaleRecord record = createSaleRecord(saleDTO);
// 4. 更新库存
updateStock(saleDTO.getMedicineCode(), -saleDTO.getQuantity());
// 5. 记录特殊药品销售
if(medicine.isControlled()) {
recordControlledMedicineSale(record);
}
return buildResult(record);
}
}
3. 关键技术实现
3.1 效期预警功能
药品效期管理是药店系统的核心需求,我们实现了多级预警机制:
- 30天预警(黄色提醒)
- 15天预警(橙色提醒)
- 7天紧急预警(红色提醒)
效期检查定时任务配置:
java复制@Scheduled(cron = "0 0 8 * * ?") // 每天上午8点执行
public void checkExpireWarning() {
LocalDate now = LocalDate.now();
List<Medicine> medicines = medicineMapper.selectList(null);
medicines.forEach(medicine -> {
long days = ChronoUnit.DAYS.between(now, medicine.getExpireDate());
if(days <= 7) {
sendExpireWarning(medicine, "紧急预警");
} else if(days <= 15) {
sendExpireWarning(medicine, "中级预警");
} else if(days <= 30) {
sendExpireWarning(medicine, "初级预警");
}
});
}
3.2 销售数据分析
系统提供多维度的销售统计分析:
- 药品品类销售排行
- 时段销售热力图
- 会员消费分析
- 毛利率计算
使用MyBatis-Plus实现动态SQL查询:
xml复制<select id="selectSaleAnalysis" resultType="SaleAnalysisVO">
SELECT
m.category,
SUM(s.quantity) as total_quantity,
SUM(s.amount) as total_amount,
SUM(s.profit) as total_profit
FROM sale_record s
JOIN medicine m ON s.medicine_code = m.code
<where>
<if test="startDate != null">
AND s.sale_time >= #{startDate}
</if>
<if test="endDate != null">
AND s.sale_time <![CDATA[<=]]> #{endDate}
</if>
<if test="category != null">
AND m.category = #{category}
</if>
</where>
GROUP BY m.category
ORDER BY total_amount DESC
</select>
4. 系统部署方案
4.1 环境要求
推荐生产环境配置:
- 服务器:2核4G以上
- 数据库:MySQL 5.7+
- JDK:1.8+
- 缓存:Redis 5.0+
4.2 部署步骤
- 数据库初始化:
bash复制mysql -u root -p < db_init.sql
- 应用打包:
bash复制mvn clean package -DskipTests
- 启动应用:
bash复制java -jar pharmacy-system.jar --spring.profiles.active=prod
- Nginx配置示例:
nginx复制server {
listen 80;
server_name pharmacy.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
}
location /static/ {
alias /opt/pharmacy/static/;
expires 30d;
}
}
5. 常见问题解决方案
5.1 效期预警不准确
可能原因及解决方法:
- 服务器时区设置不正确
- 解决方案:确保服务器时区与药店所在地时区一致
- 批次日结未执行
- 解决方案:检查定时任务是否正常执行
5.2 销售记录重复
典型场景:
- 网络延迟导致重复提交
- 前端防重复提交失效
解决方案:
java复制@PostMapping("/sale")
public Result sale(@RequestBody SaleDTO dto) {
// 生成唯一业务ID
String saleNo = generateSaleNo(dto);
// 检查是否已存在
if(saleRecordMapper.exists(saleNo)) {
return Result.fail("请勿重复提交");
}
// 处理销售业务
return saleService.saleMedicine(dto);
}
5.3 库存不同步
常见于高并发场景,解决方案:
- 使用数据库乐观锁
java复制@Update("UPDATE medicine SET stock = stock - #{qty}, version = version + 1
WHERE code = #{code} AND version = #{version}")
int deductStockWithLock(@Param("code") String code,
@Param("qty") int qty,
@Param("version") int version);
- 引入Redis分布式锁
java复制public boolean saleWithLock(SaleDTO dto) {
String lockKey = "stock_lock:" + dto.getMedicineCode();
try {
// 获取分布式锁
boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if(locked) {
return saleMedicine(dto);
}
return false;
} finally {
redisTemplate.delete(lockKey);
}
}
6. 扩展功能建议
在实际药店运营中,可以考虑增加以下功能:
- 医保对接模块
- 电子处方流转接口
- 智能推荐系统(基于会员购药记录)
- 移动端盘点功能
- 供应商协同平台
医保对接示例代码结构:
code复制src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── pharmacy/
│ │ ├── insurance/
│ │ │ ├── InsuranceService.java
│ │ │ ├── dto/
│ │ │ │ └── InsuranceClaimDTO.java
│ │ │ └── api/
│ │ │ ├── InsuranceApi.java
│ │ │ └── InsuranceConfig.java
开发这类系统最关键的体会是:药品管理无小事,每个数据字段都可能关系到用药安全。在开发过程中,我们特别加强了以下方面的校验:
- 药品效期的严格管控
- 处方药的销售流程控制
- 库存变化的实时准确性
- 操作日志的完整记录
一个实用的建议是:在开发初期就与执业药师充分沟通,了解实际业务流程中的各种特殊情况和监管要求,这能避免后期大量的返工修改。