1. 项目背景与核心需求
火锅作为中国餐饮文化的代表性品类,其点餐场景具有鲜明的行业特性。传统纸质菜单+服务员记录的模式存在三大痛点:高峰期订单堆积导致上菜延迟、加菜需求响应慢、口味偏好难以沉淀。这套基于PHP的火锅店点餐系统正是针对这些行业痛点设计的数字化解决方案。
系统需要实现的核心功能模块包括:
- 多终端点餐界面(堂食平板/手机扫码)
- 实时库存联动(特别是涮品的新鲜度管理)
- 特色锅底定制(辣度/油量/配料的可视化选择)
- 多人分单结算(AA制/比例分摊的灵活处理)
- 会员积分与口味记忆(根据历史订单推荐搭配)
关键设计考量:火锅食材具有"生鲜时效性强"、"组合自由度大"的特点,系统需要特别关注库存实时更新机制和自定义搭配的交互体验。
2. 技术架构设计
2.1 整体技术栈选型
采用经典的三层架构:
- 前端:Vue.js + Element UI(考虑餐饮从业者操作习惯)
- 后端:PHP 7.4 + ThinkPHP 5.1(平衡开发效率与性能)
- 数据库:MySQL 8.0(事务处理与JSON字段支持)
特别选用ThinkPHP框架因其:
- 内置的DB类简化了复杂关联查询
- 支持Redis缓存无缝集成
- 符合餐饮系统高频读写的场景需求
2.2 数据库关键表结构
sql复制CREATE TABLE `hotpot_items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '菜品名称',
`category` enum('肉类','海鲜','蔬菜','锅底','酒水') NOT NULL,
`price` decimal(10,2) NOT NULL,
`fresh_level` tinyint(4) DEFAULT 100 COMMENT '新鲜度百分比',
`stock` int(11) NOT NULL COMMENT '实时库存',
`image_url` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `customized_option` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`item_id` int(11) NOT NULL,
`option_type` enum('辣度','油量','忌口') NOT NULL,
`option_values` json NOT NULL COMMENT '可选项与价格增量',
PRIMARY KEY (`id`),
KEY `item_id` (`item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 核心功能实现细节
3.1 实时库存管理
采用乐观锁解决并发减库存问题:
php复制public function decreaseStock($itemId, $quantity) {
$pdo = Db::getPdo();
$pdo->beginTransaction();
try {
$stmt = $pdo->prepare(
"SELECT stock FROM hotpot_items WHERE id=? FOR UPDATE"
);
$stmt->execute([$itemId]);
$current = $stmt->fetchColumn();
if($current >= $quantity) {
$update = $pdo->prepare(
"UPDATE hotpot_items SET stock=stock-? WHERE id=?"
);
$update->execute([$quantity, $itemId]);
$pdo->commit();
return true;
}
$pdo->rollBack();
return false;
} catch(Exception $e) {
$pdo->rollBack();
throw $e;
}
}
3.2 锅底定制化交互
前端采用可视化滑块组件实现参数调节:
javascript复制// Vue组件示例
<template>
<div class="spicy-control">
<el-slider
v-model="spicyLevel"
:marks="{0:'微辣',50:'中辣',100:'特辣'}"
@change="updatePrice">
</el-slider>
<span>当前辣度:{{spicyText}} (+{{extraPrice}}元)</span>
</div>
</template>
<script>
export default {
data() {
return {
spicyLevel: 30,
basePrice: 68,
extraPrice: 0
}
},
computed: {
spicyText() {
if(this.spicyLevel < 30) return '微辣';
if(this.spicyLevel < 70) return '中辣';
return '特辣';
}
},
methods: {
updatePrice(val) {
this.extraPrice = Math.floor(val / 10);
}
}
}
</script>
4. 典型业务场景解决方案
4.1 多人分单场景
采用账单快照+分摊算法:
- 生成主订单时记录所有菜品原始价格
- 根据选择的分摊模式计算:
- 按人数平均
- 按菜品食用者标记
- 自定义比例
- 生成子订单时保留价格计算痕迹
php复制class BillSplitter {
public static function splitByDiners($orderId, $diners) {
$mainOrder = OrderModel::get($orderId);
$items = json_decode($mainOrder->items, true);
$perPerson = $mainOrder->total / count($diners);
$subOrders = [];
foreach($diners as $diner) {
$subOrder = new SubOrderModel();
$subOrder->amount = $perPerson;
$subOrder->detail = $this->generateSplitDetail($items, $perPerson);
$subOrders[] = $subOrder;
}
return $subOrders;
}
private function generateSplitDetail($items, $amount) {
// 生成带有价格计算说明的详情
}
}
4.2 高峰期性能保障
通过三层级缓存策略:
- 静态菜单数据:Redis缓存 30分钟
- 库存信息:MySQL内存表+定时同步
- 订单提交:消息队列削峰
配置示例(ThinkPHP):
php复制// config/cache.php
return [
'default' => 'redis',
'stores' => [
'redis' => [
'type' => 'redis',
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'select' => 0,
'timeout' => 0,
'persistent' => false,
'prefix' => 'hotpot_'
],
'memory' => [
'type' => 'memcached',
'host' => '127.0.0.1',
'port' => 11211,
'prefix' => 'hotpot_mem_'
]
]
];
5. 部署与运维实践
5.1 环境搭建要点
推荐使用Docker-compose部署:
yaml复制version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile.php
ports:
- "8000:80"
volumes:
- ./src:/var/www/html
depends_on:
- db
- redis
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: hotpot123
MYSQL_DATABASE: hotpot
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
mysql_data:
5.2 常见问题排查
-
乱码问题:
- 确保数据库连接字符集:
'charset' => 'utf8mb4' - PHP文件头部添加:
header('Content-Type:text/html;charset=utf-8');
- 确保数据库连接字符集:
-
跨终端同步延迟:
php复制// 强制刷新缓存 Cache::clear('redis'); // 使用WebSocket推送更新 $ws = new \Swoole\WebSocket\Server('0.0.0.0', 9502); $ws->push($fd, json_encode(['type'=>'stock_update'])); -
打印小票格式错乱:
- 使用ESC/POS指令集规范
- 字体设置:
<esc>!38(双倍宽高) - 中文编码转换:
iconv('UTF-8','GB2312//IGNORE',$text)
6. 项目优化方向
6.1 后厨看板系统
通过WebSocket实现:
- 订单实时推送
- 菜品制作进度更新
- 紧急催单处理
6.2 智能推荐算法
基于用户历史数据:
php复制class Recommender {
public function getRecommendations($userId) {
$history = OrderModel::where('user_id', $userId)
->with('items')
->select();
$counter = [];
foreach($history as $order) {
foreach($order->items as $item) {
$counter[$item['category']][$item['id']] =
($counter[$item['category']][$item['id']] ?? 0) + 1;
}
}
arsort($counter['肉类']);
arsort($counter['海鲜']);
return [
'meat' => array_slice(array_keys($counter['肉类']), 0, 3),
'seafood' => array_slice(array_keys($counter['海鲜']), 0, 2)
];
}
}
6.3 移动端管理端
采用混合开发方案:
- 订单管理:React Native
- 数据报表:ECharts嵌入WebView
- 扫码功能:集成ZXing库
在开发过程中发现,使用PHP的GD库处理菜品图片时,适当增加锐化参数能显著提升移动端显示效果:
php复制$image = imagecreatefromjpeg($uploadPath);
imagefilter($image, IMG_FILTER_SELECTIVE_BLUR);
imagefilter($image, IMG_FILTER_CONTRAST, -20);
imagefilter($image, IMG_FILTER_SHARPEN, 60);
imagejpeg($image, $outputPath, 85);
