一套校园食堂综合管理系统,涵盖智能点餐、食材溯源、供应链采购、库存管理、设备能耗监控、饭卡管理、数据分析与决策支持等核心业务模块
智慧校园食堂解决方案 — 项目分析报告
一、项目概述
本项目是一套基于 Laravel 6.20.40 + MySQL 5.7 的校园食堂综合管理系统,涵盖智能点餐、食材溯源、供应链采购、库存管理、设备能耗监控、饭卡管理、数据分析与决策支持等核心业务模块。系统采用 PHP 8.0 运行,前端使用 Laravel Blade 模板引擎渲染 PC 端管理后台,UI 设计灵感来源于 Zapier 的温暖奶油色风格(Warm Cream Theme),独立自定义 CSS,不依赖 AdminLTE 或 Bootstrap JS。
二、技术栈
| 层级 | 技术 |
|---|---|
| 后端框架 | Laravel 6.20.40 |
| PHP 版本 | PHP 8.0 |
| 数据库 | MySQL 5.7(InnoDB 引擎) |
| 前端模板 | Laravel Blade(原生模板引擎) |
| UI 风格 | Zapier 暖奶油色设计系统,纯 CSS |
| 图表库 | ECharts 5(CDN 引入) |
| 图标 | 纯色 SVG 图标(无 emoji) |
| 字体 | Inter(Google Fonts CDN) |
| 测试工具 | PHPUnit 8.5+、Playwright |
三、目录结构
shitang/
├── app/
│ ├── Http/
│ │ ├── Controllers/
│ │ │ ├── Admin/ # 23 个后台管理控制器
│ │ │ ├── Api/ # 10 个 RESTful API 控制器
│ │ │ ├── Auth/ # 6 个 Laravel 脚手架认证控制器
│ │ │ └── Controller.php # 基础控制器
│ │ └── Kernel.php # HTTP 中间件配置
│ └── Models/
│ ├── Canteen/ # 食堂核心模型(用户、菜品、反馈、评价、推荐)
│ ├── Order/ # 订单模型(订单、订单明细、销售数据)
│ ├── Inventory/ # 供应链模型(16 个模型,最庞大的模块)
│ ├── Payment/ # 支付模型(支付记录、支付方式)
│ ├── Energy/ # 能耗模型(设备、能耗监测)
│ ├── Card/ # 饭卡模型(饭卡设备、消费记录、充值记录)
│ └── SystemSetting.php # 系统设置
├── database/
│ ├── shitang.sql # 数据库 DDL(33 张表)
│ ├── new_tables.sql # 扩展表 DDL
│ └── seeds/
│ ├── CanteenSeeder.php # 食堂核心模拟数据
│ └── EnhancedSupplySeeder.php # 供应链扩展模拟数据
├── resources/views/admin/ # 52 个 Blade 视图文件
├── routes/
│ ├── web.php # Web 路由(管理后台)
│ └── api.php # RESTful API 路由
├── public/images/ # 生成的菜品图片
├── screenshots/ # Playwright 截图(36 张)
└── DESIGN.md # UI 设计规范文档
四、数据库设计(33 张表)
所有表以 fa_ 为前缀,使用 InnoDB 引擎,支持外键约束。每张表包含统一字段:id(自增主键)、status(ENUM 软删除:0=正常,1=删除)、create_time(INT 时间戳)、update_time(INT 时间戳)。
4.1 智能点餐模块(5 张表)
| 表名 | 用途 | 核心字段 |
|---|---|---|
fa_users |
用户表 | username, password, role_data(学生/教职工/管理员), contactinfo |
fa_dishes |
菜品表 | dishname, price, description_content, dish_image |
fa_orders |
订单表 | userid(FK), order_time, totalamount, order_status_data(已下单/已支付/已取消) |
fa_orderdetails |
订单明细表 | orderid(FK), dishid(FK), quantity, unitprice |
fa_recommendations |
菜品推荐表 | userid(FK), dishid(FK), recommendation_time |
4.2 食材溯源与安全管理模块(3 张表)
| 表名 | 用途 | 核心字段 |
|---|---|---|
fa_suppliers |
供应商表 | name, contactinfo, certification |
fa_ingredients |
食材表 | name, supplierid(FK), purchase_time, storageconditions, expiration_time |
fa_ingredientmonitoring |
食材监测表 | ingredientid(FK), temperature, humidity, monitoring_time |
4.3 智能库存管理模块(2 张表)
| 表名 | 用途 | 核心字段 |
|---|---|---|
fa_inventory |
库存表 | ingredientid(FK), quantity, last_update_time |
fa_inventorychanges |
库存变动表 | inventoryid(FK), changequantity, changetype_data(入库/出库), change_time |
4.4 采购供应链管理模块(11 张表)
| 表名 | 用途 | 核心字段 |
|---|---|---|
fa_procurement_orders |
采购订单表 | orderno, supplierid(FK), orderstatus_data(草稿/待审核/已审核/已下单/配送中/已送达/已验收/已完成/已取消), totalamount, orderdate, deliveryaddress |
fa_procurement_order_items |
采购订单明细 | orderid(FK), ingredientid(FK), quantity, unit, unitprice, subtotal, receivedquantity |
fa_delivery_schedules |
配送计划表 | orderid(FK), scheduledtime, actualtime, status_data(待配送/配送中/已完成) |
fa_delivery_records |
配送记录表 | orderid(FK), deliverytime, receiver, quantity, condition_data(良好/一般/差) |
fa_supplier_assessments |
供应商评估表 | supplierid(FK), qualityscore, deliveriescore, pricescore, servicescore, totalscore, assessmentperiod |
fa_supplier_contracts |
供应商合同表 | supplierid(FK), contractno, contracttype, startdate, enddate, amount |
fa_supplier_qualifications |
供应商资质表 | supplierid(FK), qualificationtype, certificateno, issuedate, expirydate |
fa_ingredient_prices |
食材价格表 | ingredientid(FK), supplierid(FK), price, unit, recorddate |
fa_procurement_plans |
采购计划表 | planname, plandate, expectedamount, status_data(草稿/待审批/已审批/已取消) |
fa_procurement_plan_items |
采购计划明细 | planid(FK), ingredientid(FK), quantity, unit, estimatedprice |
fa_supplier_blacklist |
供应商黑名单表 | supplierid(FK), reason, blockdate, releasedate |
4.5 数据分析与决策支持模块(3 张表)
| 表名 | 用途 | 核心字段 |
|---|---|---|
fa_salesdata |
销售数据表 | orderid(FK), salesamount, sales_time |
fa_customerfeedback |
顾客反馈表 | userid(FK), orderid(FK), rating, comments_content |
fa_reviews |
评价表 | userid(FK), orderid(FK), reviewcontent, rating |
4.6 节能环保模块(2 张表)
| 表名 | 用途 | 核心字段 |
|---|---|---|
fa_devices |
设备表 | name, type_data(照明/空调), installationlocation |
fa_energymonitoring |
能耗监测表 | deviceid(FK), energyconsumption, monitoring_time |
4.7 支付模块(2 张表)
| 表名 | 用途 | 核心字段 |
|---|---|---|
fa_paymentmethods |
支付方式表 | name, description |
fa_payments |
支付记录表 | orderid(FK), paymentmethodid(FK), amount, payment_time, payment_status_data |
4.8 饭卡管理模块(3 张表)
| 表名 | 用途 | 核心字段 |
|---|---|---|
fa_card_devices |
饭卡设备表 | deviceno, devicename, installationlocation, status_data(正常/故障/停用) |
fa_card_consumption_records |
消费记录表 | deviceid(FK), cardno, amount, consumptiontime |
fa_card_recharge_records |
充值记录表 | deviceid(FK), cardno, amount, rechargetime |
4.9 系统配置模块(1 张表)
| 表名 | 用途 | 核心字段 |
|---|---|---|
fa_system_settings |
系统设置表 | settingkey, settingvalue, settinggroup, description |
五、核心业务模块详解
5.1 智能点餐系统
业务流程: 用户注册 → 浏览菜品 → 下单 → 生成订单明细 → 支付 → 生成销售数据 → 反馈/评价
核心逻辑:
- 用户分为三种角色:学生、教职工、管理员
- 订单状态流转:已下单 → 已支付 → 已完成 / 已取消
- 订单与明细为一对多关系,明细记录每道菜的数量和单价
- 支付记录关联订单和支付方式
- 销售数据从订单表同步,用于报表统计
- 菜品推荐系统基于用户历史订单
5.2 食材溯源与安全管理
业务流程: 供应商管理 → 食材入库 → 实时监测(温度/湿度) → 过期预警
核心逻辑:
- 供应商关联食材,支持资质认证管理
- 食材有采购日期、存储条件、保质期等溯源信息
- 食材监测表记录温度和湿度变化,支持食品安全审计
- 食材价格表跟踪不同供应商的价格变动
5.3 采购供应链管理
业务流程: 创建采购计划 → 审批 → 生成采购订单 → 提交审核 → 审核通过 → 配送 → 验收 → 完成
采购订单状态机:
草稿 → 待审核 → 已审核 → 已下单 → 配送中 → 已送达 → 已验收 → 已完成
↑ ↓
└──── 已取消 ←──────┘
核心逻辑:
- 采购订单自动生成单号(格式:PO + 日期 + 3位序号,如 PO20240101001)
- 采购订单包含主表和明细表,明细记录每种食材的数量、单价、小计
- 订单金额自动计算:Σ(数量 × 单价)
- 只有「草稿」和「待审核」状态允许编辑
- 审核通过后记录审核人和审核时间
- 配送计划和配送记录跟踪物流状态
- 采购计划支持动态添加明细行(前端 JS 实现)
5.4 供应商评估体系
评估维度与权重:
- 质量评分(35%):qualityscore
- 配送评分(25%):deliveriescore
- 价格评分(20%):pricescore
- 服务评分(20%):servicescore
- 综合评分 = quality × 0.35 + delivery × 0.25 + price × 0.20 + service × 0.20
排名逻辑: 取每个供应商最新一期评估的综合分,按分数降序排列,前三名用金银铜色标识。
5.5 供应商黑名单
业务逻辑:
- 可将供应商加入黑名单,记录原因和拉黑日期
- 支持解除黑名单(记录释放日期)
- 黑名单供应商在仪表盘统计中展示
5.6 合同与资质管理
业务逻辑:
- 供应商可关联多份合同,记录合同编号、类型、金额、起止日期
- 供应商可关联多项资质,记录资质类型、证书编号、颁发日期、到期日期
- 合同和资质均支持 CRUD 操作
5.7 库存管理
业务流程: 食材入库 → 库存增加 → 出库 → 库存减少 → 自动记录变动
核心逻辑:
- 库存表记录每种食材的当前数量
- 库存变动表记录每次出入库操作:变动数量、类型(入库/出库)、时间
- 库存 CRUD 操作自动触发变动记录写入
- 支持按食材和时间筛选变动记录
5.8 设备能耗监控
业务流程: 设备登记 → 实时能耗监测 → 数据汇总 → 能耗分析
核心逻辑:
- 设备分两种类型:照明、空调
- 能耗监测表记录每个设备的用电量和监测时间
- 仪表盘展示近7天能耗趋势(ECharts 柱状图)
- 数据报表页面展示能耗分析图表
5.9 饭卡管理
业务流程: 设备登记 → 消费记录 → 充值记录 → 状态管理
核心逻辑:
- 饭卡设备有三种状态:正常、故障、停用
- 消费记录关联设备,记录卡号、金额、消费时间
- 充值记录关联设备,记录卡号、金额、充值时间
- 支持设备状态切换(正常↔故障↔停用)
5.10 数据分析与报表
仪表盘统计卡片(12 个):
- 用户总数
- 菜品总数
- 订单总数
- 今日销售额
- 今日订单
- 库存食材
- 支付记录
- 今日能耗(kWh)
- 待审批采购
- 有效合同
- 供应商评估
- 黑名单供应商
ECharts 图表(4 个):
- 销售趋势折线图(近7天)
- 订单状态饼图
- 菜品销量 TOP 5 柱状图
- 能耗监控柱状图(近7天)
最近动态 Tab 页(4 个):
- 最新订单
- 最新反馈
- 最新支付
- 最新采购
六、认证与权限机制
6.1 管理员认证
系统未使用 Laravel 内置的 Auth 认证,而是采用自定义 Session 认证:
// AuthController::doLogin()
$user = User::where('username', $validated['username'])
->where('role_data', '管理员')
->first();
if ($user && Hash::check($validated['password'], $user->password)) {
Session::put('admin_user', $user->toArray());
return redirect('/admin');
}
- 登录验证:用户名 + 密码(Hash 校验)+ 角色必须为「管理员」
- 会话存储:
session('admin_user')存储完整用户数组 - 中间件检查:每个 Admin 控制器构造函数中手动检查
session('admin_user') - 退出登录:
Session::forget('admin_user')
6.2 权限模型
- 用户分为三种角色:学生、教职工、管理员
- 管理员可访问所有后台功能
- API 接口当前未启用认证(
auth:api中间件仅在默认/user路由上生效)
七、路由设计
7.1 Web 路由(routes/web.php)
所有后台路由挂载在 /admin 前缀下,共 120+ 条路由:
| 模块 | 路由前缀 | 路由数量 |
|---|---|---|
| 认证 | /admin/login, /admin/logout |
4 |
| 仪表盘 | /admin |
1 |
| 用户管理 | /admin/users |
6 |
| 菜品管理 | /admin/dishes |
6 |
| 订单管理 | /admin/orders |
4 |
| 供应商管理 | /admin/suppliers |
6 |
| 食材管理 | /admin/ingredients |
7 |
| 库存管理 | /admin/inventory |
5 |
| 设备管理 | /admin/devices |
7 |
| 支付管理 | /admin/payments |
4 |
| 反馈评价 | /admin/feedbacks, /admin/reviews |
4 |
| 数据报表 | /admin/reports |
1 |
| 系统设置 | /admin/system |
2 |
| 采购管理 | /admin/procurement |
10 |
| 配送管理 | /admin/delivery |
6 |
| 供应商评估 | /admin/assessment |
6 |
| 合同管理 | /admin/contracts |
4 |
| 资质管理 | /admin/qualifications |
4 |
| 价格管理 | /admin/prices |
4 |
| 采购计划 | /admin/plans |
7 |
| 黑名单 | /admin/blacklist |
4 |
| 饭卡管理 | /admin/card-machines |
7 |
7.2 API 路由(routes/api.php)
所有 API 路由挂载在 /api/canteen 前缀下,提供标准 RESTful CRUD 接口:
| 资源 | 路由 | 方法 |
|---|---|---|
| 用户 | /api/canteen/users |
GET/POST/PUT/DELETE |
| 菜品 | /api/canteen/dishes |
GET/POST/PUT/DELETE |
| 订单 | /api/canteen/orders |
GET/POST/PUT/DELETE |
| 供应商 | /api/canteen/suppliers |
GET/POST/PUT/DELETE |
| 食材 | /api/canteen/ingredients |
GET/POST/PUT/DELETE |
| 库存 | /api/canteen/inventory |
GET/POST/PUT/DELETE |
| 设备 | /api/canteen/devices |
GET/POST/PUT/DELETE |
| 支付 | /api/canteen/payments |
GET/POST/PUT/DELETE |
| 反馈 | /api/canteen/feedbacks |
GET/POST/DELETE |
| 评价 | /api/canteen/reviews |
GET/POST/DELETE |
八、Eloquent 模型关系图
User (fa_users)
├── hasMany → Order (fa_orders)
├── hasMany → Recommendation (fa_recommendations)
├── hasMany → CustomerFeedback (fa_customerfeedback)
└── hasMany → Review (fa_reviews)
Order (fa_orders)
├── belongsTo → User
├── hasMany → OrderDetail (fa_orderdetails)
├── hasOne → SalesData (fa_salesdata)
├── hasMany → Payment (fa_payments)
├── hasOneThrough → PaymentMethod (via Payment)
├── hasMany → CustomerFeedback
└── hasMany → Review
Supplier (fa_suppliers)
├── hasMany → Ingredient (fa_ingredients)
├── hasMany → ProcurementOrder (fa_procurement_orders)
├── hasMany → SupplierAssessment (fa_supplier_assessments)
├── hasMany → SupplierContract (fa_supplier_contracts)
├── hasMany → SupplierQualification (fa_supplier_qualifications)
├── hasMany → IngredientPrice (fa_ingredient_prices)
└── hasOne → SupplierBlacklist (fa_supplier_blacklist)
Ingredient (fa_ingredients)
├── belongsTo → Supplier
├── hasMany → IngredientMonitoring (fa_ingredientmonitoring)
├── hasOne → Inventory (fa_inventory)
├── hasMany → ProcurementOrderItem (via orderid)
├── hasMany → ProcurementPlanItem (via planid)
└── hasMany → IngredientPrice (fa_ingredient_prices)
Inventory (fa_inventory)
├── belongsTo → Ingredient
└── hasMany → InventoryChange (fa_inventorychanges)
ProcurementOrder (fa_procurement_orders)
├── belongsTo → Supplier
├── hasMany → ProcurementOrderItem (fa_procurement_order_items)
├── hasMany → DeliverySchedule (fa_delivery_schedules)
└── hasMany → DeliveryRecord (fa_delivery_records)
Device (fa_devices)
└── hasMany → EnergyMonitoring (fa_energymonitoring)
CardDevice (fa_card_devices)
├── hasMany → CardConsumptionRecord (fa_card_consumption_records)
└── hasMany → CardRechargeRecord (fa_card_recharge_records)
九、核心代码解析
9.1 软删除机制
系统未使用 Laravel 的 SoftDeletes trait,而是通过 status ENUM 字段实现软删除:
// 删除操作(控制器)
public function destroy($id)
{
$order = ProcurementOrder::findOrFail($id);
$order->update(['status' => '1']); // 标记为删除
return back()->with('success', '删除成功');
}
// 查询过滤(模型 scope)
public function scopeActive($query)
{
return $query->where('status', '0'); // 只查正常数据
}
9.2 时间戳处理
数据库中时间字段使用 INT 存储 Unix 时间戳,而非 MySQL 的 DATETIME:
// Model boot 方法自动设置时间戳
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->create_time = time();
$model->update_time = time();
});
static::updating(function ($model) {
$model->update_time = time();
});
}
9.3 采购订单号生成
public static function generateOrderNo()
{
$prefix = 'PO' . date('Ymd'); // 如 PO20240101
$lastOrder = static::where('orderno', 'like', $prefix . '%')
->orderBy('id', 'desc')->first();
if ($lastOrder) {
$seq = intval(substr($lastOrder->orderno, -3)) + 1;
} else {
$seq = 1;
}
return $prefix . str_pad($seq, 3, '0', STR_PAD_LEFT); // PO20240101001
}
9.4 供应商综合评分计算
public static function calculateTotalScore($quality, $delivery, $price, $service)
{
return round(
$quality * 0.35 + $delivery * 0.25 + $price * 0.20 + $service * 0.20,
2
);
}
9.5 采购订单状态机
// 提交审核:草稿 → 待审核
public function submit($id) {
$order->update(['orderstatus_data' => '待审核']);
}
// 审核通过:待审核 → 已审核
public function approve($id) {
$order->update([
'orderstatus_data' => '已审核',
'approvedby' => session('admin_user.username'),
'approvedtime' => time(),
]);
}
// 取消:非已完成/已取消状态 → 已取消
public function cancel($id) {
$order->update(['orderstatus_data' => '已取消']);
}
// 验收:已送达 → 已验收
public function receive($id) {
$order->update([
'orderstatus_data' => '已验收',
'actualdeliverytime' => time(),
]);
}
9.6 库存变动自动记录
// InventoryController::store() / update()
Inventory::updateOrCreate(
['ingredientid' => $request->ingredientid],
['quantity' => $request->quantity, 'last_update_time' => time()]
);
// 自动记录变动
InventoryChange::create([
'inventoryid' => $inventory->id,
'changequantity' => $changeQty,
'changetype_data' => $changeQty > 0 ? '入库' : '出库',
'change_time' => time(),
]);
9.7 仪表盘数据聚合
// 7天销售趋势
for ($i = 6; $i >= 0; $i--) {
$date = date('Y-m-d', strtotime("-{$i} days"));
$salesData[] = SalesData::whereBetween('sales_time', [
strtotime($date),
strtotime($date . ' 23:59:59')
])->sum('salesamount');
}
// 菜品销量 TOP 5(DB 原生查询 + Join)
$dishRanks = DB::table('fa_orderdetails')
->join('fa_dishes', 'fa_orderdetails.dishid', '=', 'fa_dishes.id')
->selectRaw('fa_dishes.dishname as name, SUM(quantity) as total')
->groupBy('fa_dishes.dishname')
->orderByDesc('total')
->limit(5)
->get();
十、前端架构
10.1 布局模板(resources/views/admin/layouts/app.blade.php)
- 全局布局:侧边栏 + 顶部导航 + 内容区域
- 侧边栏:23 个导航项,分组展示,SVG 图标
- 顶部导航:面包屑 + 用户下拉菜单(个人资料/退出)
- CSS 变量系统:使用 CSS Custom Properties 定义颜色主题
- 响应式:支持移动端侧边栏收起
10.2 设计系统(DESIGN.md)
- 背景色:
#fffefb(暖奶油色) - 主文字色:
#201515(带红棕调的近黑色) - 主题色:
#ff4f00(Zapier 橙色) - 边框色:
#c5c0b1(暖灰色) - 字体:Inter(Google Fonts)
- 间距系统:8px 基础间距
- 组件风格:边框优先(
1px solid)而非阴影
10.3 图表集成
- 使用 ECharts 5(CDN 引入)
- 4 种图表类型:折线图(销售趋势)、饼图(订单状态)、柱状图(菜品排名/能耗)
- 数据通过 Blade
@json指令注入 JavaScript 变量
十一、测试与质量保障
11.1 Playwright 自动化测试
- 测试文件:
test_full.js、test_fixes.js、screenshot_all.js - 覆盖范围:全部 36 个页面
- 测试内容:登录 → 逐页访问 → 检查 HTTP 状态码 → 检查 Laravel 错误 → 检查 JS 错误
- 截图保存:36 张全页截图保存至
screenshots/目录
11.2 测试结果
- 36/36 页面全部通过(HTTP 200,无 Laravel 错误,无 JS 错误)
- 修复的问题:
- Blade 编译器
{!! !!}内花括号冲突(procurement/edit) latest()查询使用created_at而非create_time(assessment/ranking)- 多处字段名不匹配修复
- Blade 编译器
十二、模拟数据
12.1 CanteenSeeder
- 8 个用户(含管理员、学生、教职工)
- 6 个菜品(含图片)
- 10+ 个订单及明细
- 5 个供应商
- 10+ 个食材
- 库存、设备、能耗、支付等基础数据
12.2 EnhancedSupplySeeder
- 采购订单(6 条)
- 采购订单明细(8+ 条)
- 配送计划和记录
- 供应商评估(5 条)
- 供应商合同(5 条)
- 供应商资质(7 条)
- 食材价格(8 条)
- 采购计划(4 条)
- 黑名单(1 条)
- 饭卡设备、消费记录、充值记录
