C++实现餐厅管理系统(QT C++ GUI界面版)

AgenticCoding·十二月创作之星挑战赛 10w+人浏览 451人参与


往期源码回顾:
【C++】图书管理系统(完整板)
【Python】实现爬虫,爬取天气情况并进行分析(完整版)
【C++】C++实现图书管理系统(Qt C++ GUI界面版)

上述源码与本篇文章全部源码大家有需要可通过添加本篇博客最下方微信名片获取

C++实现餐厅管理系统(QT C++ GUI界面版)

在餐饮行业数字化转型的背景下,一款高效的点餐系统能显著提升餐厅运营效率和用户体验。本文将基于实际代码,详细解析一个基于Qt框架的餐厅点餐系统,从核心类设计到界面交互,带你了解系统的实现逻辑。

一、系统整体架构

该系统采用C++结合Qt框架开发,遵循面向对象设计思想,主要分为三个核心模块:

  • 数据模型层:负责菜品、订单、桌位等核心数据的定义与管理
  • 界面交互层:通过Qt Widgets实现用户与系统的交互(包含顾客端和管理端)
  • 数据持久层:通过文件IO实现数据的存储与读取(菜品、订单、桌位信息)

核心文件包括:CTable.cpp(桌位管理)、COrder.cpp(订单处理)、CDish.cpp(菜品数据)、RestaurantOrderingSystem.cpp(界面与业务逻辑)等,各模块职责清晰,通过类的封装实现低耦合。

二、点餐系统完整功能清单

基于系统代码实现,餐厅点餐系统涵盖顾客端商家管理端两大模块,各模块功能设计围绕餐饮业务全流程展开,满足用户点餐与商家运营管理需求。

在这里插入图片描述

一、顾客端功能

顾客端聚焦于用户点餐全流程,提供简洁直观的操作界面,核心功能包括:

  1. 桌位预订

    • 填写预订信息:姓名、联系电话、用餐人数、期望桌型(2人桌/4人桌/包间)
    • 选择预订时间:支持日期与时间段选择
    • 实时反馈:预订成功/失败提示(基于桌位实时状态判断)
      在这里插入图片描述
  2. 菜品点餐

    • 菜品浏览:按分类(热菜/凉菜/汤类/主食/饮料)筛选展示菜品
    • 菜品详情:显示名称、分类、价格、库存状态(可售/售罄)
    • 购物车管理:添加菜品、实时计算总价、提交订单
      在这里插入图片描述
  3. 订单查询

    • 凭手机号查询历史订单
    • 展示订单状态(待确认/已确认/已完成等)、点餐明细、金额等信息
      在这里插入图片描述

二、商家管理端功能

管理端面向餐厅运营人员,提供多维度的业务管理工具,通过四个核心模块实现全面管控:

1. 菜品管理

  • 菜品维护:添加、编辑、删除菜品信息
    • 信息字段:名称、分类(下拉选择固定分类)、价格(精确到分)、库存、图片路径(支持本地浏览选择)、状态(上架/下架)
  • 列表操作:刷新菜品列表、清空表单(快速重置输入)
  • 数据同步:操作结果实时保存至本地文件,确保数据持久化
    在这里插入图片描述

2. 订单管理

  • 订单监控:表格展示所有订单详情(订单号、顾客姓名、电话、时间、桌型、状态、金额)
  • 状态管理:支持更新订单状态(待确认→已确认→已上菜→已完成→已取消)
  • 筛选与刷新:按订单状态筛选(全部/待确认等)、实时刷新订单列表
    在这里插入图片描述

3. 桌位管理

  • 桌位监控:表格展示所有桌位信息(桌号、类型、状态)
  • 状态更新:修改桌位状态(空闲→已预订→已占用)
  • 初始化功能:一键创建默认桌位(5个2人桌T001-T005、5个4人桌T006-T010、3个包间V001-V003)
  • 实时同步:桌位状态变更实时保存,支撑顾客端预订判断
    在这里插入图片描述

4. 数据统计

  • 日营收查询:选择日期,查询指定日期的总营收金额
  • 月订单量查询:选择月份(最近12个月),查询该月订单总数
  • 统计结果展示:文本区域实时显示查询结果,支持多次查询累加展示
    在这里插入图片描述

功能特点总结

系统通过模块化设计实现“顾客点餐-商家管理-数据沉淀”的闭环,功能覆盖从前端交互到后端数据处理的全流程,同时通过文件IO确保数据持久化,无需数据库依赖即可稳定运行。

三、核心数据模型设计

1. 桌位模型(CTable类)

桌位是餐厅的基础资源,CTable类封装了桌位的核心属性:

// CTable.h 核心代码
class CTable {
private:
    string m_id;          // 桌位编号(如T001、V001)
    string m_type;        // 桌型(2人桌/4人桌/包间)
    string m_status;      // 状态(空闲/已预订/已占用)
public:
    CTable(string id, string type) : m_id(id), m_type(type), m_status("空闲") {}
    // Getter/Setter方法...
    friend ostream& operator<<(ostream& os, const CTable& tabel); // 写入文件
    friend istream& operator>>(istream& is, CTable& tabel);       // 读取文件
};

通过重载输入输出流运算符,实现桌位信息与文件的交互。例如写入文件时按“编号 类型 状态”格式存储:

// CTable.cpp 输出流重载
ostream& operator<<(ostream& os, const CTable& table) {
    os << table.m_id << " " << table.m_type << " " << table.m_status << endl;
    return os;
}

2. 订单模型(COrder类)

订单是系统的核心业务对象,COrder类需记录用户信息、点餐明细、支付状态等:

// COrder.h 核心代码
class COrder {
private:
    string m_orderId;      // 订单号
    string m_userName;     // 用户名
    string m_phone;        // 联系电话
    string m_dateTime;     // 预订/下单时间
    int m_peopleCount;     // 用餐人数
    string m_tableType;    // 桌型
    vector<OrderItem> m_items; // 点餐明细
    string m_status;       // 订单状态(待确认/已完成)
    string m_payStatus;    // 支付状态(未支付/已支付)
public:
    // 构造函数与Getter/Setter...
    void addItem(OrderItem item); // 添加菜品到订单
    friend ostream& operator<<(ostream& os, const COrder& order);
    friend istream& operator>>(istream& is, COrder& order);
};

订单的文件读写逻辑较复杂,尤其是包含空格的时间字段(如“2023-10-01 18:30”),通过双引号包裹处理:

// COrder.cpp 输入流重载(处理带空格的时间字段)
istream& operator>>(istream& is, COrder& order) {
    // 读取基础信息(订单号、姓名、电话)
    is >> orderId >> userName >> phone;
    // 处理带空格的时间(双引号包裹)
    char quote;
    is >> quote; 
    if (quote == '"') {
        getline(is, dateTime, '"'); // 读取到下一个双引号
    }
    // 读取剩余字段(人数、桌型、状态等)
    // ...
    return is;
}

3. 菜品模型(CDish类)

菜品信息包括名称、分类、价格、库存等,CDish类定义如下:

// CDish.h 核心代码
class CDish {
private:
    string m_name;        // 菜品名称
    string m_category;    // 分类(热菜/凉菜/汤类等)
    double m_price;       // 价格
    int m_stock;          // 库存
    string m_imagePath;   // 图片路径
    bool m_isAvailable;   // 是否可售
public:
    // Getter/Setter方法...
    friend ostream& operator<<(ostream& os, const CDish& dish);
    friend istream& operator>>(istream& is, CDish& dish);
};

通过文件IO实现菜品数据的持久化,读取时按“名称 分类 价格 库存 图片路径 可售状态”格式解析:

// CDish.cpp 输入流重载
istream& operator>>(istream& is, CDish& dish) {
    is >> dish.m_name >> dish.m_category >> dish.m_price 
       >> dish.m_stock >> dish.m_imagePath;
    int available;
    is >> available;
    dish.m_isAvailable = (available == 1); // 1表示可售,0表示售罄
    return is;
}

四、用户界面与交互实现

系统界面采用Qt的QWidgetQTabWidget构建,分为顾客端和管理端,这里重点解析顾客端界面。

1. 界面布局设计

顾客端界面通过setupCustomerInterface方法初始化,包含三个核心功能页签:

  • 桌位预订:填写姓名、电话、人数等信息,选择桌型和时间
  • 菜品点餐:左侧浏览菜品(按分类筛选),右侧购物车管理
  • 订单查询:通过手机号查询历史订单

核心代码片段(界面布局):

// RestaurantOrderingSystem.cpp 界面初始化
void RestaurantOrderingSystem::setupCustomerInterface() {
    m_customerPage = new QWidget;
    QVBoxLayout* mainLayout = new QVBoxLayout(m_customerPage);
    
    // 标题与返回按钮
    QHBoxLayout* headerLayout = new QHBoxLayout;
    QPushButton* backBtn = new QPushButton("返回主界面");
    QLabel* titleLabel = new QLabel("用户点餐系统");
    headerLayout->addWidget(backBtn);
    headerLayout->addStretch();
    headerLayout->addWidget(titleLabel);
    
    // 选项卡(预订/点餐/查询)
    m_customerTabs = new QTabWidget;
    m_customerTabs->addTab(reservationTab, "桌位预订");
    m_customerTabs->addTab(orderingTab, "菜品点餐");
    m_customerTabs->addTab(queryTab, "订单查询");
    
    mainLayout->addLayout(headerLayout);
    mainLayout->addWidget(m_customerTabs);
}

2. 核心交互功能实现

(1)菜品浏览与筛选

用户可通过分类下拉框(m_categoryCombo)筛选菜品,点击“刷新”按钮触发browseDishes方法:

// 浏览菜品功能
void RestaurantOrderingSystem::browseDishes() {
    m_dishList->clear();
    string category = m_categoryCombo->currentText().toStdString();
    // 遍历菜品列表,按分类筛选
    for (const auto& dish : m_manager.getDishes()) {
        if (category != "全部" && dish.getCategory() != category)
            continue;
        // 显示菜品信息(名称、分类、价格、状态)
        QString info = QString("%1(%2)  ¥%3  %4")
                         .arg(stdStrToQstr(dish.getName()))
                         .arg(stdStrToQstr(dish.getCategory()))
                         .arg(dish.getPrice())
                         .arg(dish.isAvailable() ? "可售" : "售罄");
        m_dishList->addItem(info);
    }
}
(2)加入购物车与总价计算

选中菜品后点击“加入购物车”,将菜品添加到m_cartList,并通过updateTotalPrice实时计算总价:

// 添加到购物车
void RestaurantOrderingSystem::addToCart() {
    QListWidgetItem* selected = m_dishList->currentItem();
    if (!selected) {
        QMessageBox::warning(this, "选择错误", "请先选择菜品!");
        return;
    }
    m_cartList->addItem(selected->text());
    updateTotalPrice(); // 更新总价
}

// 计算购物车总价
void RestaurantOrderingSystem::updateTotalPrice() {
    double total = 0;
    for (int i = 0; i < m_cartList->count(); i++) {
        QString text = m_cartList->item(i)->text();
        // 从文本中提取价格(格式:"xxx  ¥x.xx ...")
        int priceStart = text.indexOf("¥") + 1;
        int priceEnd = text.indexOf(" ", priceStart);
        QString priceStr = text.mid(priceStart, priceEnd - priceStart);
        total += priceStr.toDouble();
    }
    m_totalPrice->setText(QString("¥%1").arg(total, 0, 'f', 2));
}
(3)桌位预订功能

用户填写预订信息后,系统检查对应类型的空闲桌位,若存在则更新桌位状态并保存:

void RestaurantOrderingSystem::makeReservation() {
    // 获取用户输入
    QString name = m_customerName->text().trimmed();
    QString phone = m_customerPhone->text().trimmed();
    int people = m_peopleCount->value();
    QString tableType = m_tableTypeCombo->currentText();
    
    // 验证输入
    if (name.isEmpty() || phone.isEmpty()) {
        QMessageBox::warning(this, "输入错误", "姓名和电话不能为空!");
        return;
    }
    
    // 查找可用桌位
    bool hasAvailable = false;
    for (auto& table : m_manager.m_tables) {
        if (table.getType() == tableType.toStdString() && table.getStatus() == "空闲") {
            table.setStatus("已预订");
            hasAvailable = true;
            break;
        }
    }
    
    if (hasAvailable) {
        m_manager.saveTablesToFile(); // 保存桌位状态
        QMessageBox::information(this, "预订成功", "桌位预订成功!");
    } else {
        QMessageBox::warning(this, "预订失败", "该类型桌位暂时无可用!");
    }
}

四、系统亮点与可扩展方向

  1. 数据持久化设计:通过重载输入输出流运算符,简化文件读写逻辑,无需依赖数据库即可实现数据存储。
  2. 模块化界面:采用选项卡(QTabWidget)和栈窗口(QStackedWidget)实现多界面切换,结构清晰。
  3. 用户体验优化:实时计算总价、输入验证、状态提示等细节提升交互友好度。

可扩展方向:

  • 接入数据库(如SQLite)替代文件存储,提升数据处理效率
  • 增加扫码点餐功能,通过网络模块实现移动端交互
  • 加入后厨通知功能,订单提交后自动同步到后厨显示终端

五、代码实现

CDish.cpp

#include "CDish.h"
#include <fstream>

// 重载输出运算符:一条菜品数据占一行,空格分隔字段
ostream& operator<<(ostream& os, const CDish& dish) {
    // 字段顺序:名称 分类 价格 库存 图片路径 是否上架(1/0)
    os << dish.m_name << " "
        << dish.m_category << " "
        << dish.m_price << " "
        << dish.m_stock << " "
        << dish.m_imagePath << " "
        << (dish.m_isAvailable ? 1 : 0)  // 用1表示上架,0表示下架
        << endl;  // 每条数据结尾换行
    return os;
}

// 重载输入运算符:从一行中按空格分隔读取字段
istream& operator>>(istream& is, CDish& dish) {
    // 注意:>> 会自动跳过空格和换行,但字符串字段若含空格会被截断
    is >> dish.m_name          // 读取菜品名称
        >> dish.m_category      // 读取分类
        >> dish.m_price         // 读取价格(double)
        >> dish.m_stock         // 读取库存(int)
        >> dish.m_imagePath;    // 读取图片路径

     // 读取是否上架状态(1/0)
    int available;
    is >> available;
    dish.m_isAvailable = (available == 1);

    return is;
}

COrder.cpp

#include "COrder.h"
#include <fstream>

ostream& operator<<(ostream& os, const COrder& order) {
    os << order.m_orderId << " "
        << order.m_userName << " "
        << order.m_phone << " "
        << "\"" << order.m_dateTime << "\" "  // 用双引号包裹时间(关键修改)
        << order.m_peopleCount << " "
        << order.m_tableType << " "
        << order.m_status << " "
        << order.m_payStatus << " "
        << order.m_items.size() << " ";

    for (const auto& item : order.m_items) {
        os << item.dishName << " "
            << item.quantity << " "
            << item.price << " ";
    }
    os << endl;
    return os;
}

// 重载输入运算符:从一行中解析订单信息(包含动态订单项)
istream& operator>>(istream& is, COrder& order) {
    order.clearItems();

    string orderId, userName, phone, dateTime, tableType, status, payStatus;
    int peopleCount;

    // 读取前3个字段(无空格,直接用>>)
    is >> orderId >> userName >> phone;

    // 读取带引号的时间字段(关键修改)
    char quote;
    is >> quote;  // 读取开头的双引号(")
    if (quote == '"') {
        // 读取到下一个双引号前的所有内容(包括空格)
        getline(is, dateTime, '"');
    }
    else {
        // 兼容没有引号的情况(可选,根据实际数据处理)
        dateTime = quote;  // 把误读的字符加入dateTime
        getline(is, dateTime, ' ');  // 继续读到空格
    }

    // 读取剩余字段(无空格,直接用>>)
    is >> peopleCount >> tableType >> status >> payStatus;

    int itemCount;
    is >> itemCount;

    for (int i = 0; i < itemCount; i++) {
        OrderItem item;
        is >> item.dishName >> item.quantity >> item.price;
        order.addItem(item);
    }

    // 赋值给订单对象
    order.setOrderId(orderId);
    order.setUserName(userName);
    order.setPhone(phone);
    order.setDateTime(dateTime);  // 此时dateTime是完整的带空格的时间
    order.setPeopleCount(peopleCount);
    order.setTableType(tableType);
    order.setStatus(status);
    order.setPayStatus(payStatus);

    return is;
}

CTable.cpp

#include "CTable.h"
#include <fstream>

// 重载输出运算符:一行存储一个桌位信息,空格分隔字段
ostream& operator<<(ostream& os, const CTable& table) {
    // 字段顺序:桌位编号 桌位类型 桌位状态
    os << table.m_id << " "
        << table.m_type << " "
        << table.m_status
        << endl;  // 每条数据结尾换行
    return os;
}

// 重载输入运算符:从一行中按空格分隔读取桌位信息
istream& operator>>(istream& is, CTable& table) {
    // 按顺序读取:桌位编号 → 桌位类型 → 桌位状态
    is >> table.m_id
        >> table.m_type
        >> table.m_status;
    return is;
}

Main.cpp

#include "RestaurantOrderingSystem.h"
#include <QtWidgets/QApplication>
#include <QTextCodec>
#pragma execution_character_set("utf-8")
int main(int argc, char *argv[])
{

    QApplication app(argc, argv);
    RestaurantOrderingSystem window;
    window.show();
    return app.exec();
}

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工藤学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值