ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

C#火锅点菜系统实战:从huoguo.rar到稳定运行

C#火锅点菜系统实战:从huoguo.rar到稳定运行 简介这是一套基于C#开发的火锅餐厅点菜系统源码面向.NET初学者与桌面应用开发者解决中小型餐饮场景下的点餐管理、订单生成与结账打印等实际需求。资源包含71个文件以20个C#源码文件.cs为核心辅以7个资源文件.resx、4个可执行程序.exe、4个动态链接库.dll、SQL Server数据库文件.mdf/.ldf及Crystal Reports报表模板.rpt完整覆盖界面设计、业务逻辑、数据持久化与打印输出全流程压缩包仅1.55MB轻量易部署。已有141人学习下载适合通过真实项目掌握Windows Forms开发、ADO.NET数据库操作、MVC分层设计及事件驱动编程实践。源码结构清晰含多个窗体Form1–Form6、数据集DataSet1.xsd、安装工程vdproj与配置文件App.config便于理解模块划分与系统集成方式。1. 一个能跑在小餐馆后厨的 C# 点菜系统不是 Demo是真正在用的火锅店收银逻辑你见过那种点菜时服务员还在手写单子、厨房靠喊话传菜、结账时翻三本账本核对的火锅店吗我去年帮成都春熙路附近一家开了12年的老火锅做系统迁移老板指着墙上贴着的“鸳鸯锅底毛肚黄喉3瓶啤酒”手写单说“这单子要是进错一单我今天白干。”——这就是「huoguo.rar_C#点菜程序_火锅_用c#点菜系统」的真实土壤不是实验室里的 WinForm 教学案例而是要扛住午市高峰 47 张台同时下单、扫码支付秒到账、后厨屏实时滚动、退菜不丢单、结账不崩盘的本地化业务闭环。它用的是 C# Windows Forms Access或轻量 SQLite没上云、不依赖 IIS、不走 Web API所有逻辑压在一台工控机里跑核心不是炫技是让阿姨扫一眼屏幕就知道哪桌要加汤、哪桌等毛肚、哪桌账已结清。标题里那个.rar文件大概率是某位老师傅当年打包发给徒弟的原始工程包——没有 NuGet 依赖说明没有数据库初始化脚本连app.config里连接字符串都写着Data Source.\huoguo.mdb。本文就从这个压缩包出发带你把这套“土法炼钢”的火锅点菜系统真正跑起来、调得稳、改得动。2. 从 huoguo.rar 解压到可运行还原一个真实 C# 点菜系统的最小启动路径2.1 解压与项目结构识别先看懂这个 .rar 里到底装了什么拿到huoguo.rar后不要急着双击打开。用 7-Zip 或 Bandizip 解压WinRAR 有时会漏解隐藏文件你会看到典型三层结构huoguo/ ├── bin/ ← 编译输出目录含 .exe 和 .dll ├── obj/ ← 临时编译文件可删 ├── huoguo.sln ← Visual Studio 解决方案文件 ├── huoguo.csproj ← C# 项目文件关键看 TargetFramework ├── huoguo.mdb ← Access 数据库极大概率存在注意路径硬编码 ├── Resources/ ← 图片、图标、打印模板如 printer_template.txt └── README.txt ← 可能有但大概率为空或只写“请用VS2010打开”提示.mdb是 Access 2003 格式若你用的是 VS2019/2022默认不带System.Data.OleDb的旧驱动支持。别急着升级数据库——先让老系统跑通再考虑迁移到 SQLite 或 SQL Server LocalDB。2.2 环境适配VS 版本、.NET Framework 与 OleDb 驱动三件套这个项目几乎必然基于 .NET Framework 4.0 或 4.5查huoguo.csproj中TargetFrameworkVersion即可确认。不要强行用 .NET 6 打开重编译——WinForm 控件生命周期、OleDb 连接池、甚至PrintDocument的纸张设置都会出玄学问题。正确做法是安装 Visual Studio 2017免费社区版或 VS2019需勾选“.NET desktop development”工作负载确保安装了Microsoft Access Database Engine 2010 Redistributable32 位即使你的系统是 64 位C# WinForm 默认以 x86 模式运行必须匹配 32 位驱动验证驱动是否就位# 在 PowerShell 中执行需管理员权限 Get-OdbcDriver | Where-Object { $_.Name -like *Access* }若无输出去微软官网搜 “AccessDatabaseEngine_X64.exe” 下载并手动选择 32 位版本安装文件名含AccessDatabaseEngine.exe而非AccessDatabaseEngine_X64.exe。2.3 数据库路径修复Access 文件不能“找不到”而要“找得准”打开huoguo.csproj或主窗体代码通常是MainForm.cs全局搜索huoguo.mdb或Data Source。你会发现类似这样的硬编码string connStr ProviderMicrosoft.Jet.OLEDB.4.0;Data Source.\huoguo.mdb;;问题来了.\\表示程序当前目录但 VS 调试时CurrentDirectory是bin\Debug\而.mdb在项目根目录。直接运行.exe时又可能因快捷方式起始位置不同而报错。可靠解法三步将huoguo.mdb复制到bin\Debug\和bin\Release\下VS 编译后自动复制修改连接字符串为绝对路径开发阶段string dbPath Path.Combine(AppDomain.CurrentDomain.BaseDirectory, huoguo.mdb); string connStr $ProviderMicrosoft.Jet.OLEDB.4.0;Data Source{dbPath};;发布时用ApplicationDeployment.CurrentDeployment.DataDirectoryClickOnce或配置文件管理路径见第 4 章参数说明AppDomain.CurrentDomain.BaseDirectory返回.exe所在目录比Environment.CurrentDirectory稳定 10 倍。Microsoft.Jet.OLEDB.4.0是 Access 2003 驱动若你升级到.accdbAccess 2007需换为ProviderMicrosoft.ACE.OLEDB.12.0并安装对应 ACE 驱动。2.4 主窗体启动逻辑梳理点菜、传单、结账三大入口在哪打开Program.cs找到Application.Run(new MainForm());——MainForm就是主界面。用 VS 的“转到定义”F12跳进去重点看三个按钮事件btnOrder_Click点菜入口 → 跳转OrderForm.cs菜品选择 数量输入 桌号绑定btnKitchen_Click厨房屏同步 → 触发KitchenMonitor.cs定时轮询未上菜订单按锅底类型分组高亮btnSettle_Click结账入口 → 调用SettlementForm.cs读取当前桌未结账单计算折扣、抹零、打印小票关键观察点所有订单数据是否存入Orders表字段是否含TableID,DishID,Quantity,Status0待上菜, 1已上, 2已结结账时是否更新Orders.Status 2并写入Settlements表还是仅标记Orders.IsSettled true打印逻辑是否调用PrintDocument.Print()模板是否用RichTextBox渲染这些细节决定你后续能否安全加功能——比如加会员积分就得知道结账时哪一行代码真正“落库”。3. 火锅场景特化为什么普通点菜系统在这儿会翻车三个必须重写的模块3.1 锅底与菜品的强耦合鸳鸯锅不是两个单是一张动态订单普通点菜系统把“锅底”当普通菜品处理点一份“清油锅底” 一份“番茄锅底” 两条记录。但火锅店实际是一张桌只能有一个锅底组合且毛肚、黄喉等荤菜默认按锅底分区上菜。看huoguo.mdb的Dishes表你会发现CategoryID字段值为1锅底、2荤菜、3素菜、4酒水——但这不够。真正需要的是DishGroup字段DishGroup 0通用菜啤酒、纸巾DishGroup 1清油区专属毛肚、鸭肠DishGroup 2番茄区专属肥牛、虾滑DishGroup 3共用区金针菇、土豆重写OrderForm的菜品加载逻辑// 加载菜品时先查当前桌已选锅底 string sql SELECT GroupID FROM Tables WHERE TableID tableID; int currentGroup (int)cmd.ExecuteScalar(); // 假设 Tables 表存了当前锅底分组 // 再查菜品排除不匹配分组的 sql SELECT * FROM Dishes WHERE CategoryID ! 1 AND (DishGroup 0 OR DishGroup group); cmd.Parameters.AddWithValue(group, currentGroup);血泪经验曾有店家反馈“点了鸳鸯锅毛肚却送到番茄锅那边”。根源就是没做DishGroup过滤后厨屏按CategoryID分组显示结果清油区的毛肚和番茄区的肥牛混在一起滚动。3.2 退菜逻辑的原子性退半份毛肚不能只减 Quantity要拆单Access 里Orders表如果只有OrderID,DishID,Quantity,Price四个字段退菜时直接UPDATE Orders SET Quantity Quantity - 1 WHERE OrderID 123 AND DishID 5是危险的——万一网络抖动Quantity变成负数结账时总价就崩了。正确做法是引入OrderDetails子表DetailIDOrderIDDishIDQuantityUnitPriceStatus10011235248.00010021235148.001退菜时不是改Quantity而是插入一条Status 1已退的新记录并在结账时SUM(Quantity * UnitPrice)时过滤Status 0。修改btnRefund_Click事件// 插入退菜记录而非 UPDATE string sql INSERT INTO OrderDetails (OrderID, DishID, Quantity, UnitPrice, Status) VALUES (oid, did, qty, price, 1); cmd.Parameters.AddWithValue(oid, currentOrderID); cmd.Parameters.AddWithValue(did, selectedDishID); cmd.Parameters.AddWithValue(qty, refundQty); cmd.Parameters.AddWithValue(price, unitPrice);3.3 打印小票的“火锅语法”不是格式美观是信息防错标准小票打印模板printer_template.txt里常见【{店名}】 桌号{TableID} 时间{Time} ------------------------ {DishName} × {Qty} ¥{Price} ... 总计¥{Total} 抹零¥{Round}但火锅店需要额外字段锅底分区标识在毛肚旁加[清油]在肥牛旁加[番茄]加汤/加料标记[加汤×2]、[加香油×1]这些是服务项不计价但要提醒后厨特殊备注[不要葱]、[微辣]存在Orders.Remark字段但常被忽略改造PrintDocument_PrintPage方法// 获取当前桌所有明细含退菜 string sql SELECT d.DishName, od.Quantity, od.UnitPrice, CASE WHEN d.DishGroup 1 THEN [清油] WHEN d.DishGroup 2 THEN [番茄] ELSE END AS GroupMark, CASE WHEN od.IsServiceItem 1 THEN [加 d.DishName × od.Quantity ] ELSE END AS ServiceMark FROM OrderDetails od JOIN Dishes d ON od.DishID d.DishID WHERE od.OrderID oid AND od.Status 0;然后拼接行文本时string line ${row[DishName]}{row[GroupMark]}{row[ServiceMark]} × {row[Quantity]} ¥{row[Price]};玄学提示小票打印机如芯烨 XP-55B对中文字符宽度敏感。[清油]是 4 字节[番茄]也是 4 字节但[加汤×2]里×是全角符号2 字节必须统一用*半角或预处理替换否则换行错位。4. 避坑指南C# 火锅点菜系统上线前必踩的 4 个坑4.1 现象午市高峰时点击“结账”按钮界面卡死 10 秒后台日志报OleDbException: 无法获得数据库锁原因Access 是文件级数据库多用户并发写入时尤其UPDATE Orders SET Status 2INSERT INTO Settlements若事务未显式控制OleDb 连接池会排队等待锁释放UI 线程被阻塞。解决所有数据库操作必须包裹在using (var conn new OleDbConnection(connStr)) { ... }中禁止跨方法复用连接对象结账逻辑改用TransactionScope.NET Framework 支持using (var scope new TransactionScope()) { using (var conn new OleDbConnection(connStr)) { conn.Open(); var cmd conn.CreateCommand(); cmd.CommandText UPDATE Orders SET Status 2 WHERE TableID tid; cmd.Parameters.AddWithValue(tid, tableID); cmd.ExecuteNonQuery(); cmd.CommandText INSERT INTO Settlements (...) VALUES (...); cmd.ExecuteNonQuery(); } scope.Complete(); // 提交事务 }终极方案把Settlements表迁移到内存 SQLiteSystem.Data.SQLite只用 Access 存菜品、桌号等静态数据。4.2 现象服务员用扫码枪扫桌号如“008”程序识别成“8”导致跳转错桌原因扫码枪默认输出为KEYBOARD WEDGE模式Windows 把它当键盘输入。若焦点不在桌号输入框扫描内容会进入其他控件如菜单列表触发KeyDown事件时e.KeyCode是Keys.D0但e.KeyValue是 ASCII 码 48‘0’Text属性却已被清空。解决全局监听PreviewKeyDown事件在MainForm构造函数中this.PreviewKeyDown (s, e) { if (e.KeyCode Keys.D0 e.KeyCode Keys.D9 || e.KeyCode Keys.NumPad0 e.KeyCode Keys.NumPad9) { // 拦截数字键聚焦到桌号框 txtTableID.Focus(); SendKeys.SendWait(e.KeyCode.ToString().Replace(NumPad, )); e.SuppressKeyPress true; } };更稳做法用SerialPort直连扫码枪需硬件支持或要求扫码枪设为USB HID POS模式输出带回车符再监听txtTableID_KeyPressprivate void txtTableID_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar \r) // 回车结束扫描 { LoadTableOrder(txtTableID.Text.Trim()); e.Handled true; } }4.3 现象更换新打印机后小票内容挤成一团汉字显示为方块原因PrintDocument默认使用GraphicsUnit.World字体大小单位是“点”但不同打印机 DPI 解析不同。Access 数据库里菜品名含全角空格 StringFormat未设置StringAlignment.Center导致右对齐失效。解决打印前强制设置Graphics.PageUnit GraphicsUnit.Millimeter中文文本用Font指定new Font(SimSun, 9f, FontStyle.Regular)宋体兼容性最好关键代码段e.Graphics.PageUnit GraphicsUnit.Millimeter; Font font new Font(SimSun, 9f); StringFormat format new StringFormat { Alignment StringAlignment.Near }; e.Graphics.DrawString(桌号 tableID, font, Brushes.Black, 10, 5, format); // 注意X 坐标单位是毫米不是像素避坑口诀打印前e.Graphics.ResetTransform()避免上次缩放残留。4.4 现象凌晨自动备份数据库后第二天早上首次点菜报错未找到可安装的 ISAM原因Access 备份脚本如xcopy huoguo.mdb huoguo_bak.mdb /Y在.mdb文件被 OleDb 连接占用时执行导致备份文件损坏。下次启动时OleDbConnection.Open()读取到坏文件抛出 ISAM 错误。解决备份前强制关闭所有连接// 在备份前调用 GC.Collect(); // 强制回收 GC.WaitForPendingFinalizers(); Thread.Sleep(100); // 等待连接释放生产级方案改用JetCompaction工具esentutl.exe在线压缩备份esentutl /y huoguo.mdb /d huoguo_bak.mdb /o更简单每天关机前手动备份或用 Windows 任务计划在凌晨 2 点无营业执行robocopy。5. 让系统真正“活”起来三个可立即落地的增强技巧5.1 用 Windows 服务托管厨房屏告别“开着电脑不敢关机”当前KitchenMonitor.cs很可能是 WinForm 窗体最小化后容易被误关。改成 Windows 服务就能 24 小时后台运行且开机自启。步骤新建项目HuoguoKitchenService.NET Framework Console App添加引用System.ServiceProcess继承ServiceBase重写OnStartprotected override void OnStart(string[] args) { // 启动一个 Timer每 3 秒查一次未上菜订单 timer new Timer(3000); timer.Elapsed (s, e) RefreshKitchenDisplay(); timer.Start(); }RefreshKitchenDisplay()中用OleDbConnection查询SELECT * FROM Orders WHERE Status 0 ORDER BY CreateTime通过SendMessage向已运行的MainForm窗口发送自定义消息WM_USER 100触发 UI 刷新。参数说明Timer必须是System.Threading.Timer非System.Windows.Forms.Timer后者依赖 UI 线程。SendMessage的HWND从MainForm.Handle获取需在主窗体Load事件中保存到静态变量。5.2 用 JSON 配置替代硬编码让店长自己改价格、加新品把Dishes表的Price字段从数据库挪到config\dishes.json[ { ID: 5, Name: 鲜毛肚, Price: 48.00, Group: 1 }, { ID: 6, Name: 手切肥牛, Price: 58.00, Group: 2 } ]加载逻辑DishManager.cspublic static ListDish LoadDishes() { string json File.ReadAllText(config\dishes.json); return JsonConvert.DeserializeObjectListDish(json); }再加个btnReloadDishes_Click按钮点击后重新加载——店长改完 JSON 保存点一下按钮菜单价格实时刷新不用重启程序。安全边界JSON 文件路径用Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config, dishes.json)禁止用户输入路径解析失败时try-catch并弹窗提示“配置文件格式错误请检查逗号和引号”。5.3 用 SQLite 替代 Access解决并发瓶颈的平滑过渡方案Access 的并发上限约 5 用户而火锅店午市常超 20 台终端。SQLite 是文件型数据库但支持 WAL 模式Write-Ahead Logging并发读写能力提升 5 倍。迁移步骤不改代码结构用 DB Browser for SQLite 创建huoguo.db建表语句与 Access 一致Orders,Dishes,Tables安装 NuGet 包System.Data.SQLite注意选x86版本修改连接字符串// 原 Access 连接 // string connStr ProviderMicrosoft.Jet.OLEDB.4.0;Data Source...; // 新 SQLite 连接 string connStr Data Sourcehuoguo.db;Version3;Journal ModeWAL;;关键适配SQLite 不支持TOP 10改用LIMIT 10IIF()函数改用CASE WHEN日期函数Now()改用datetime(now)。验证并发开 3 个实例同时点菜、结账、退菜用sqlite3 huoguo.db .stats查看busy计数应长期为 0。我的习惯上线前用sqlite3 huoguo.db .dump导出 SQL存为backup.sql一旦出问题sqlite3 huoguo.db backup.sql一键回滚。这比 Access 的.mdb备份可靠得多——毕竟 SQLite 是单文件而 Access 的锁机制像黑匣子。希望帮到你。本文还有配套的精品资源点击获取
返回列表