生成代码工程

This commit is contained in:
root 2026-05-06 10:54:13 +08:00
parent 0934be187d
commit aab7c7387d
13 changed files with 9014 additions and 2 deletions

45
CMakeLists.txt Normal file
View File

@ -0,0 +1,45 @@
cmake_minimum_required(VERSION 3.14)
project(MallSystem VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# MSVC UTF-8 support
if (MSVC)
add_compile_options(/utf-8)
endif()
# ============================================================
# Main executable
# ============================================================
set(SOURCES
src/main.cpp
src/app.cpp
src/product.cpp
src/shopping_cart.cpp
src/order.cpp
)
set(HEADERS
include/app.hpp
include/product.hpp
include/shopping_cart.hpp
include/order.hpp
)
add_executable(mall ${SOURCES} ${HEADERS})
target_include_directories(mall PRIVATE include)
# ============================================================
# Test executable (uses plain assert, no external dependency)
# ============================================================
set(TEST_SOURCES
tests/basic_test.cpp
src/app.cpp
src/product.cpp
src/shopping_cart.cpp
src/order.cpp
)
add_executable(mall_test ${TEST_SOURCES} ${HEADERS})
target_include_directories(mall_test PRIVATE include)

View File

@ -1,3 +1,44 @@
# 商城管理系统
# MallSystem —— 简约商城系统
商城管理系统
## 概述
使用 C++17 编写的控制台商城模拟系统,包含三大核心模块:
- **商品管理**Product商品名称、价格、库存
- **购物车**ShoppingCart添加/移除商品、计算总价
- **订单管理**Order从购物车生成订单、查看订单状态
## 构建与运行
```bash
# 构建
cmake -B build
cmake --build build
# 运行主程序
./build/mall
# 运行测试
./build/mall_test
```
## 工程结构
```
.
├── CMakeLists.txt
├── README.md
├── include/
│ ├── app.hpp # 应用入口封装
│ ├── product.hpp # 商品类
│ ├── shopping_cart.hpp # 购物车类
│ └── order.hpp # 订单类
├── src/
│ ├── main.cpp # 命令行入口
│ ├── app.cpp # 应用逻辑
│ ├── product.cpp # 商品实现
│ ├── shopping_cart.cpp # 购物车实现
│ └── order.cpp # 订单实现
└── tests/
└── basic_test.cpp # 单元测试assert
```

8257
events.ndjson Normal file

File diff suppressed because one or more lines are too long

62
include/app.hpp Normal file
View File

@ -0,0 +1,62 @@
#ifndef MALL_APP_HPP
#define MALL_APP_HPP
#include "product.hpp"
#include "shopping_cart.hpp"
#include "order.hpp"
#include <vector>
#include <memory>
/**
* @brief
*/
class App {
public:
/**
* @brief
*/
App();
/**
* @brief
*/
void run();
private:
std::vector<Product> products_; ///< 商品库
ShoppingCart cart_; ///< 当前购物车
std::vector<std::unique_ptr<Order>> orders_; ///< 历史订单列表
/**
* @brief
*/
void initProducts();
// ---- 菜单功能 ----
/** @brief 显示商品列表 */
void showProducts() const;
/** @brief 添加商品到购物车 */
void addToCart();
/** @brief 查看购物车 */
void showCart() const;
/** @brief 生成订单 */
void checkout();
/** @brief 查看历史订单 */
void showOrders() const;
/**
* @brief
* @return end()
*/
std::vector<Product>::const_iterator selectProduct() const;
/** @brief 打印菜单选项 */
static void printMenu();
};
#endif // MALL_APP_HPP

78
include/order.hpp Normal file
View File

@ -0,0 +1,78 @@
#ifndef MALL_ORDER_HPP
#define MALL_ORDER_HPP
#include "shopping_cart.hpp"
#include <string>
#include <vector>
#include <ctime>
/**
* @brief
*/
enum class OrderStatus {
Pending, ///< 待支付
Paid, ///< 已支付
Shipped, ///< 已发货
Delivered, ///< 已送达
Cancelled ///< 已取消
};
/**
* @brief
* @param status
* @return
*/
std::string orderStatusToString(OrderStatus status);
/**
* @brief
*/
class Order {
public:
/**
* @brief
*/
Order() = default;
/**
* @brief
* @param orderId
* @param cart
*/
explicit Order(uint64_t orderId, ShoppingCart& cart);
/** @brief 获取订单编号 */
uint64_t getOrderId() const noexcept { return orderId_; }
/** @brief 获取订单状态 */
OrderStatus getStatus() const noexcept { return status_; }
/**
* @brief
* @param status
*/
void setStatus(OrderStatus status) noexcept { status_ = status; }
/** @brief 获取订单创建时间(时间戳) */
std::time_t getCreateTime() const noexcept { return createTime_; }
/** @brief 获取订单条目 */
const std::vector<CartItem>& getItems() const noexcept { return items_; }
/** @brief 计算订单总金额 */
double totalPrice() const;
/**
* @brief
* @return
*/
std::string toString() const;
private:
uint64_t orderId_ = 0; ///< 订单编号
OrderStatus status_ = OrderStatus::Pending; ///< 订单状态
std::time_t createTime_ = 0; ///< 创建时间
std::vector<CartItem> items_; ///< 商品条目
};
#endif // MALL_ORDER_HPP

64
include/product.hpp Normal file
View File

@ -0,0 +1,64 @@
#ifndef MALL_PRODUCT_HPP
#define MALL_PRODUCT_HPP
#include <string>
#include <cstdint>
/**
* @brief
*/
class Product {
public:
/**
* @brief
*/
Product() = default;
/**
* @brief
* @param id
* @param name
* @param price
* @param stock
*/
Product(uint64_t id, std::string name, double price, int stock);
/** @brief 获取商品编号 */
uint64_t getId() const noexcept { return id_; }
/** @brief 获取商品名称 */
const std::string& getName() const noexcept { return name_; }
/** @brief 获取商品单价 */
double getPrice() const noexcept { return price_; }
/** @brief 获取库存数量 */
int getStock() const noexcept { return stock_; }
/**
* @brief
* @param quantity
* @return true false
*/
bool reduceStock(int quantity);
/**
* @brief
* @param quantity
*/
void addStock(int quantity);
/**
* @brief
* @return "[#1001] 苹果 ¥5.50 (库存:20)"
*/
std::string toString() const;
private:
uint64_t id_ = 0; ///< 商品编号
std::string name_; ///< 商品名称
double price_ = 0.0; ///< 单价
int stock_ = 0; ///< 库存数量
};
#endif // MALL_PRODUCT_HPP

70
include/shopping_cart.hpp Normal file
View File

@ -0,0 +1,70 @@
#ifndef MALL_SHOPPING_CART_HPP
#define MALL_SHOPPING_CART_HPP
#include "product.hpp"
#include <vector>
#include <utility>
/**
* @brief
*/
struct CartItem {
Product product; ///< 商品副本
int quantity = 0; ///< 购买数量
/** @brief 小计金额 = 单价 × 数量 */
double subtotal() const noexcept { return product.getPrice() * quantity; }
};
/**
* @brief
*/
class ShoppingCart {
public:
ShoppingCart() = default;
/**
* @brief
* @param product
* @param quantity
*/
void addItem(const Product& product, int quantity);
/**
* @brief
* @param productId
* @return true false
*/
bool removeItem(uint64_t productId);
/**
* @brief
* @param productId
* @param quantity 0
* @return true
*/
bool updateQuantity(uint64_t productId, int quantity);
/** @brief 清空购物车 */
void clear();
/** @brief 获取所有条目 */
const std::vector<CartItem>& getItems() const noexcept { return items_; }
/**
* @brief
* @return
*/
double totalPrice() const;
/** @brief 购物车是否为空 */
bool isEmpty() const noexcept { return items_.empty(); }
/** @brief 条目数量 */
size_t itemCount() const noexcept { return items_.size(); }
private:
std::vector<CartItem> items_; ///< 购物车条目列表
};
#endif // MALL_SHOPPING_CART_HPP

119
src/app.cpp Normal file
View File

@ -0,0 +1,119 @@
#include "app.hpp"
#include <iostream>
#include <iomanip>
#include <limits>
#include <algorithm>
App::App() {
initProducts();
}
void App::initProducts() {
products_.emplace_back(1001, "\xe8\x8b\xb9\xe6\x9e\x9c", 5.50, 100); // 苹果
products_.emplace_back(1002, "\xe9\xa6\x99\xe8\x95\x89", 3.20, 150); // 香蕉
products_.emplace_back(1003, "\xe7\x89\x9b\xe5\xa5\xb6", 12.80, 80); // 牛奶
products_.emplace_back(1004, "\xe9\x9d\xa2\xe5\x8c\x85", 8.90, 60); // 面包
products_.emplace_back(1005, "\xe6\x97\xa5\xe8\xae\xb0\xe6\x9c\xac", 15.00, 40); // 日记本
}
void App::printMenu() {
std::cout << "\n====== \xe5\x95\x86\xe5\x9f\x8e\xe7\xb3\xbb\xe7\xbb\x9f ======\n"; // 商城系统
std::cout << " 1. \xe6\x9f\xa5\xe7\x9c\x8b\xe5\x95\x86\xe5\x93\x81\xe5\x88\x97\xe8\xa1\xa8\n"; // 查看商品列表
std::cout << " 2. \xe5\x8a\xa0\xe5\x85\xa5\xe8\xb4\xad\xe7\x89\xa9\xe8\xbd\xa6\n"; // 加入购物车
std::cout << " 3. \xe6\x9f\xa5\xe7\x9c\x8b\xe8\xb4\xad\xe7\x89\xa9\xe8\xbd\xa6\n"; // 查看购物车
std::cout << " 4. \xe4\xb8\x8b\xe5\x8d\x95\xe7\xbb\x93\xe7\xae\x97\n"; // 下单结算
std::cout << " 5. \xe6\x9f\xa5\xe7\x9c\x8b\xe5\x8e\x86\xe5\x8f\xb2\xe8\xae\xa2\xe5\x8d\x95\n"; // 查看历史订单
std::cout << " 0. \xe9\x80\x80\xe5\x87\xba\n"; // 退出
std::cout << "\xe8\xaf\xb7\xe9\x80\x89\xe6\x8b\xa9: "; // 请选择
}
void App::run() {
int choice = 0;
do {
printMenu();
std::cin >> choice;
if (std::cin.fail()) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
choice = -1;
}
switch (choice) {
case 1: showProducts(); break;
case 2: addToCart(); break;
case 3: showCart(); break;
case 4: checkout(); break;
case 5: showOrders(); break;
case 0: std::cout << "\xe6\xac\xa2\xe8\xbf\x8e\xe4\xb8\x8b\xe6\xac\xa1\xe5\x85\x89\xe4\xb8\xb4!\n"; break; // 欢迎下次光临
default: std::cout << "\xe8\xaf\xb7\xe8\xbe\x93\xe5\x85\xa5\xe6\x9c\x89\xe6\x95\x88\xe9\x80\x89\xe9\xa1\xb9 (0-5)\n"; break; // 请输入有效选项
}
} while (choice != 0);
}
void App::showProducts() const {
std::cout << "\n------ \xe5\x95\x86\xe5\x93\x81\xe5\x88\x97\xe8\xa1\xa8 ------\n"; // 商品列表
for (const auto& p : products_) {
std::cout << " " << p.toString() << "\n";
}
}
std::vector<Product>::const_iterator App::selectProduct() const {
std::cout << "\xe8\xaf\xb7\xe8\xbe\x93\xe5\x85\xa5\xe5\x95\x86\xe5\x93\x81\xe7\xbc\x96\xe5\x8f\xb7: "; // 请输入商品编号
uint64_t id;
std::cin >> id;
return std::find_if(products_.begin(), products_.end(),
[id](const Product& p) { return p.getId() == id; });
}
void App::addToCart() {
showProducts();
auto it = selectProduct();
if (it == products_.end()) {
std::cout << "\xe6\x9c\xaa\xe6\x89\xbe\xe5\x88\xb0\xe8\xaf\xa5\xe5\x95\x86\xe5\x93\x81\xef\xbc\x81\n"; // 未找到该商品!
return;
}
std::cout << "\xe8\xaf\xb7\xe8\xbe\x93\xe5\x85\xa5\xe6\x95\xb0\xe9\x87\x8f: "; // 请输入数量
int qty;
std::cin >> qty;
if (qty <= 0) {
std::cout << "\xe6\x95\xb0\xe9\x87\x8f\xe5\xbf\x85\xe9\xa1\xbb\xe5\xa4\xa7\xe4\xba\x8e 0\xef\xbc\x81\n"; // 数量必须大于 0
return;
}
cart_.addItem(*it, qty);
std::cout << "\xe5\xb7\xb2\xe5\x8a\xa0\xe5\x85\xa5\xe8\xb4\xad\xe7\x89\xa9\xe8\xbd\xa6\xef\xbc\x81\n"; // 已加入购物车!
}
void App::showCart() const {
if (cart_.isEmpty()) {
std::cout << "\n\xe8\xb4\xad\xe7\x89\xa9\xe8\xbd\xa6\xe6\x98\xaf\xe7\xa9\xba\xe7\x9a\x84\xe3\x80\x82\n"; // 购物车是空的。
return;
}
std::cout << "\n------ \xe8\xb4\xad\xe7\x89\xa9\xe8\xbd\xa6 ------\n"; // 购物车
for (const auto& item : cart_.getItems()) {
std::cout << " " << item.product.getName()
<< " x" << item.quantity
<< " \xEF\xBF\xA5" << std::fixed << std::setprecision(2) << item.subtotal() << "\n";
}
std::cout << " \xe5\x90\x88\xe8\xae\xa1: \xEF\xBF\xA5" << std::fixed << std::setprecision(2) << cart_.totalPrice() << "\n"; // 合计
}
void App::checkout() {
if (cart_.isEmpty()) {
std::cout << "\n\xe8\xb4\xad\xc7\x89\xa9\xe8\xbd\xa6\xe4\xb8\xba\xe7\xa9\xba\xef\xbc\x8c\xe6\x97\xa0\xe6\xb3\x95\xe4\xb8\x8b\xe5\x8d\x95\xe3\x80\x82\n"; // 购物车为空,无法下单。
return;
}
static uint64_t nextOrderId = 10000;
auto order = std::make_unique<Order>(nextOrderId++, cart_);
std::cout << "\n\xe8\xae\xa2\xe5\x8d\x95\xe5\xb7\xb2\xe7\x94\x9f\xe6\x88\x90\xef\xbc\x81\n"; // 订单已生成!
std::cout << order->toString() << "\n";
orders_.push_back(std::move(order));
}
void App::showOrders() const {
if (orders_.empty()) {
std::cout << "\n\xe6\xb2\xa1\xe6\x9c\x89\xe5\x8e\x86\xe5\x8f\xb2\xe8\xae\xa2\xe5\x8d\x95\xe3\x80\x82\n"; // 没有历史订单。
return;
}
for (const auto& order : orders_) {
std::cout << order->toString() << "\n";
}
}

16
src/main.cpp Normal file
View File

@ -0,0 +1,16 @@
/**
* @file main.cpp
* @brief
*/
#include "app.hpp"
/**
* @brief
* @return 退
*/
int main() {
App app;
app.run();
return 0;
}

56
src/order.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "order.hpp"
#include <sstream>
#include <iomanip>
#include <ctime>
#include <numeric>
std::string orderStatusToString(OrderStatus status) {
switch (status) {
case OrderStatus::Pending: return "\xe5\xbe\x85\xe6\x94\xaf\xe4\xbb\x98"; // 待支付
case OrderStatus::Paid: return "\xe5\xb7\xb2\xe6\x94\xaf\xe4\xbb\x98"; // 已支付
case OrderStatus::Shipped: return "\xe5\xb7\xb2\xe5\x8f\x91\xe8\xb4\xa7"; // 已发货
case OrderStatus::Delivered: return "\xe5\xb7\xb2\xe9\x80\x81\xe8\xbe\xbe"; // 已送达
case OrderStatus::Cancelled: return "\xe5\xb7\xb2\xe5\x8f\x96\xe6\xb6\x88"; // 已取消
default: return "\xe6\x9c\xaa\xe7\x9f\xa5"; // 未知
}
}
Order::Order(uint64_t orderId, ShoppingCart& cart)
: orderId_(orderId)
, status_(OrderStatus::Pending)
, createTime_(std::time(nullptr))
{
items_ = std::move(cart.getItems());
cart.clear();
}
double Order::totalPrice() const {
return std::accumulate(items_.begin(), items_.end(), 0.0,
[](double sum, const CartItem& item) {
return sum + item.subtotal();
});
}
std::string Order::toString() const {
std::ostringstream oss;
char timeBuf[64] = {0};
std::tm* tmPtr = std::localtime(&createTime_);
if (tmPtr) {
std::strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", tmPtr);
}
oss << "\xe2\x94\x81\xe2\x94\x81\xe2\x96\xa0 \xe8\xae\xa2\xe5\x8d\x95 #" << orderId_
<< " \xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\n";
oss << " \xe7\x8a\xb6\xe6\x80\x81: " << orderStatusToString(status_) << "\n";
oss << " \xe6\x97\xb6\xe9\x97\xb4: " << timeBuf << "\n";
oss << " \xe5\x95\x86\xe5\x93\x81:\n";
for (const auto& item : items_) {
oss << " " << item.product.getName()
<< " x" << item.quantity
<< " \xEF\xBF\xA5" << std::fixed << std::setprecision(2) << item.subtotal()
<< "\n";
}
oss << " \xe5\x90\x88\xe8\xae\xa1: \xEF\xBF\xA5" << std::fixed << std::setprecision(2) << totalPrice() << "\n";
return oss.str();
}

28
src/product.cpp Normal file
View File

@ -0,0 +1,28 @@
#include "product.hpp"
#include <sstream>
#include <iomanip>
Product::Product(uint64_t id, std::string name, double price, int stock)
: id_(id), name_(std::move(name)), price_(price), stock_(stock) {}
bool Product::reduceStock(int quantity) {
if (quantity <= 0 || quantity > stock_) {
return false;
}
stock_ -= quantity;
return true;
}
void Product::addStock(int quantity) {
if (quantity > 0) {
stock_ += quantity;
}
}
std::string Product::toString() const {
std::ostringstream oss;
oss << "[#" << id_ << "] " << name_
<< " \xEF\xBF\xA5" << std::fixed << std::setprecision(2) << price_
<< " (\xe5\xba\x93\xe5\xad\x98:" << stock_ << ")";
return oss.str();
}

51
src/shopping_cart.cpp Normal file
View File

@ -0,0 +1,51 @@
#include "shopping_cart.hpp"
#include <algorithm>
#include <numeric>
void ShoppingCart::addItem(const Product& product, int quantity) {
if (quantity <= 0) return;
for (auto& item : items_) {
if (item.product.getId() == product.getId()) {
item.quantity += quantity;
return;
}
}
items_.push_back({product, quantity});
}
bool ShoppingCart::removeItem(uint64_t productId) {
auto it = std::find_if(items_.begin(), items_.end(),
[productId](const CartItem& item) {
return item.product.getId() == productId;
});
if (it == items_.end()) return false;
items_.erase(it);
return true;
}
bool ShoppingCart::updateQuantity(uint64_t productId, int quantity) {
auto it = std::find_if(items_.begin(), items_.end(),
[productId](const CartItem& item) {
return item.product.getId() == productId;
});
if (it == items_.end()) return false;
if (quantity <= 0) {
items_.erase(it);
} else {
it->quantity = quantity;
}
return true;
}
void ShoppingCart::clear() {
items_.clear();
}
double ShoppingCart::totalPrice() const {
return std::accumulate(items_.begin(), items_.end(), 0.0,
[](double sum, const CartItem& item) {
return sum + item.subtotal();
});
}

125
tests/basic_test.cpp Normal file
View File

@ -0,0 +1,125 @@
/**
* @file basic_test.cpp
* @brief 使 assert
*/
#include "product.hpp"
#include "shopping_cart.hpp"
#include "order.hpp"
#include <cassert>
#include <iostream>
#include <cmath>
/**
* @brief
*/
static void testProduct() {
Product p(1001, "Test Book", 29.99, 50);
assert(p.getId() == 1001);
assert(p.getName() == "Test Book");
assert(std::abs(p.getPrice() - 29.99) < 0.001);
assert(p.getStock() == 50);
assert(p.reduceStock(10) == true);
assert(p.getStock() == 40);
assert(p.reduceStock(100) == false); // 库存不足
assert(p.getStock() == 40);
p.addStock(5);
assert(p.getStock() == 45);
// toString 不应为空
assert(!p.toString().empty());
std::cout << "[PASS] testProduct\n";
}
/**
* @brief
*/
static void testShoppingCart() {
Product p1(2001, "Item A", 10.0, 100);
Product p2(2002, "Item B", 20.0, 100);
ShoppingCart cart;
assert(cart.isEmpty());
assert(cart.itemCount() == 0);
assert(std::abs(cart.totalPrice() - 0.0) < 0.001);
cart.addItem(p1, 2);
cart.addItem(p2, 3);
assert(!cart.isEmpty());
assert(cart.itemCount() == 2);
assert(std::abs(cart.totalPrice() - (10.0*2 + 20.0*3)) < 0.001);
// 再次添加相同商品应累加数量
cart.addItem(p1, 1);
assert(cart.itemCount() == 2);
assert(std::abs(cart.totalPrice() - (10.0*3 + 20.0*3)) < 0.001);
// 移除商品
assert(cart.removeItem(2001) == true);
assert(cart.itemCount() == 1);
// 修改数量
assert(cart.updateQuantity(2002, 5) == true);
assert(std::abs(cart.totalPrice() - 20.0*5) < 0.001);
// 修改不存在的商品
assert(cart.updateQuantity(9999, 1) == false);
// 清空
cart.clear();
assert(cart.isEmpty());
std::cout << "[PASS] testShoppingCart\n";
}
/**
* @brief
*/
static void testOrder() {
Product p1(3001, "Book", 25.0, 10);
Product p2(3002, "Pen", 3.5, 50);
ShoppingCart cart;
cart.addItem(p1, 2);
cart.addItem(p2, 4);
Order order(9001, cart);
assert(order.getOrderId() == 9001);
assert(order.getStatus() == OrderStatus::Pending);
assert(order.getItems().size() == 2);
assert(std::abs(order.totalPrice() - (25.0*2 + 3.5*4)) < 0.001);
// 确认购物车已被清空
assert(cart.isEmpty());
// 修改订单状态
order.setStatus(OrderStatus::Paid);
assert(order.getStatus() == OrderStatus::Paid);
// 订单摘要不为空
assert(!order.toString().empty());
std::cout << "[PASS] testOrder\n";
}
/**
* @brief orderStatusToString
*/
static void testOrderStatusString() {
assert(orderStatusToString(OrderStatus::Pending) == "\xe5\xbe\x85\xe6\x94\xaf\xe4\xbb\x98");
assert(orderStatusToString(OrderStatus::Delivered) == "\xe5\xb7\xb2\xe9\x80\x81\xe8\xbe\xbe");
std::cout << "[PASS] testOrderStatusString\n";
}
/**
* @brief
*/
int main() {
testProduct();
testShoppingCart();
testOrder();
testOrderStatusString();
std::cout << "\n===== \xe5\x85\xa8\xe9\x83\xa8\xe6\xb5\x8b\xe8\xaf\x95\xe9\x80\x9a\xe8\xbf\x87! =====\n"; // 全部测试通过!
return 0;
}