温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系名片!
一、项目背景与意义
餐饮行业的利润空间高度依赖食材成本控制。传统中小餐饮企业普遍采用手工记账、电话订货、Excel 统计的方式管理采购,存在采购价格不透明、库存与消耗脱节、成本核算滞后等突出问题。食材价格波动频繁,若不能及时掌握单品成本与毛利变化,很容易出现"营业额上涨但利润下降"的情况。
本系统基于 Spring Boot + Vue3 前后端分离架构,围绕"采购---入库---领用---成本核算---分析决策"的完整链路进行设计,目标是帮助餐饮企业实现采购流程线上化、库存数据实时化、成本分析可视化,从而降低采购成本、减少食材浪费、提升经营决策效率。
二、系统总体架构
系统采用前后端分离架构,前端负责交互与数据可视化,后端负责业务逻辑与数据持久化,整体分为四层:
- 表现层:Vue3 + Element Plus + ECharts,负责页面渲染、表单交互与图表展示。
- 接口层:Spring Boot Controller,统一 RESTful 接口规范,配合 JWT 完成鉴权。
- 业务层:Service 层实现采购、库存、成本核算等核心业务逻辑,使用事务保证数据一致性。
- 数据层:MyBatis-Plus + MySQL,负责数据持久化与复杂统计查询。
三、技术选型
| 层次 | 技术 | 说明 |
|---|---|---|
| 后端框架 | Spring Boot 3.x | 快速构建、自动装配、内嵌 Tomcat |
| 持久层 | MyBatis-Plus | 简化 CRUD,支持分页与条件构造器 |
| 数据库 | MySQL 8.0 | 存储业务数据,支持窗口函数做统计分析 |
| 缓存 | Redis | 缓存字典数据与登录令牌 |
| 鉴权 | Spring Security + JWT | 无状态认证,支持角色权限控制 |
| 前端框架 | Vue3 + Vite | 组合式 API,构建速度快 |
| UI 组件 | Element Plus | 后台管理常用组件库 |
| 图表 | ECharts 5 | 成本趋势、占比分析可视化 |
四、核心功能模块设计
4.1 基础数据管理
维护食材档案(名称、规格、单位、分类、参考单价)、供应商档案(联系人、结算方式、供货品类)以及仓库与部门信息。食材档案是后续采购与成本核算的基础,需保证单位统一,避免出现"斤/公斤"混用导致成本失真。
4.2 采购管理
采购流程覆盖采购申请 → 采购订单 → 到货验收 → 入库四个环节。系统支持按供应商比价,记录同一食材的历史采购价格,为议价提供依据。
java
@Service
public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, PurchaseOrder> implements PurchaseOrderService {
@Resource
private InventoryService inventoryService;
@Override
@Transactional(rollbackFor = Exception.class)
public void confirmInbound(Long orderId) {
PurchaseOrder order = getById(orderId);
if (order == null || !"PENDING".equals(order.getStatus())) {
throw new BizException("订单状态异常,无法入库");
}
// 逐条明细写入库存
for (PurchaseOrderItem item : order.getItems()) {
inventoryService.increaseStock(item.getMaterialId(), item.getQuantity(), item.getUnitPrice());
}
order.setStatus("INBOUND");
updateById(order);
}
}
4.3 库存与领用管理
库存采用移动加权平均法计算结存单价,每次入库后重新计算平均成本,领用时按当前平均单价出库。系统提供库存预警,当某食材库存低于安全库存时自动提醒采购。
sql
-- 移动加权平均单价计算
SELECT
material_id,
SUM(quantity) AS total_qty,
SUM(amount) / SUM(quantity) AS avg_price
FROM inventory_in_record
WHERE material_id = #{materialId}
GROUP BY material_id;
4.4 成本核算
成本核算按"部门 + 期间"维度归集,包含食材成本、损耗成本两部分。系统支持按菜品 BOM 反算理论成本,与实际领用成本对比,识别异常损耗。
- 理论成本:菜品销量 × 单份标准用量 × 食材平均单价。
- 实际成本:期间领用金额合计。
- 成本差异率:(实际成本 − 理论成本) / 理论成本 × 100%。
4.5 成本分析看板
基于 ECharts 提供多维度分析视图:采购成本趋势、食材成本占比、供应商价格对比、部门成本排名、成本差异预警。所有统计接口均支持按时间区间与部门筛选。
java
@GetMapping("/cost/trend")
public Result<List<CostTrendVO>> costTrend(@RequestParam String startDate,
@RequestParam String endDate,
@RequestParam(required = false) Long deptId) {
return Result.ok(costAnalysisService.queryTrend(startDate, endDate, deptId));
}
五、数据库设计要点
核心表包括:食材表 material、供应商表 supplier、采购订单表 purchase_order 与明细表 purchase_order_item、库存表 inventory、出入库流水表 inventory_record、领用单表 requisition、成本核算表 cost_summary。
设计时需注意:
- 金额字段统一使用
DECIMAL(12,2),数量使用DECIMAL(12,3),避免浮点误差。 - 出入库流水表只追加不修改,保证成本可追溯。
- 成本汇总表按"期间 + 部门 + 食材"建立唯一索引,防止重复核算。
六、关键实现难点与解决方案
6.1 成本数据一致性
入库、领用、核算涉及多表写入,统一使用 @Transactional 保证原子性;对并发领用场景,通过数据库行锁 SELECT ... FOR UPDATE 锁定库存记录,避免超领。
6.2 统计查询性能
成本分析涉及大量聚合查询,采取三项优化:为时间字段与部门字段建立联合索引;对月度汇总数据做预计算并落库;对高频访问的字典数据使用 Redis 缓存。
6.3 前后端权限控制
后端通过 Spring Security 的 @PreAuthorize 做接口级鉴权,前端通过路由守卫与按钮级指令控制展示,二者配合实现"看不到也调不通"。









七、系统运行效果与总结
系统上线后,采购流程由线下电话订货转为线上下单,采购单据可追溯;库存数据实时更新,缺货预警提前触发;成本看板使管理者能够按周查看各部门成本差异,及时调整采购策略与菜品结构。
本项目以 Spring Boot + Vue3 为基础,将采购、库存与成本分析打通,形成数据闭环。后续可进一步扩展的方向包括:接入供应商比价爬虫、引入菜品销量预测模型做智能采购建议、支持多门店成本对比分析。