跟着AI学习C#之项目实战-电商平台 Day5

📅 Day 5:订单提交与支付模拟

✅ 今日目标:

  • 创建 OrderOrderItem 模型
  • 实现从购物车生成订单的功能
  • 模拟支付流程(成功/失败页面)
  • 添加订单状态跟踪(如“待付款”、“已发货”等)
  • 提交 Git 版本记录进度

🧩 功能概览

页面功能
/Checkout/Index.cshtml确认订单信息
/Checkout/Success.cshtml支付成功页面
/Checkout/Failed.cshtml支付失败页面
/Orders/Index.cshtml我的订单列表
数据库模型Order, OrderItem

🛠️ 知识点预览

技术内容
数据模型Order 表示订单,OrderItem 表示订单中的商品
购物车转订单将 Session 中的购物车数据保存为订单
支付模拟使用按钮或自动跳转模拟支付结果
用户身份验证只有登录用户才能下单
UI 设计Bootstrap + Razor Pages 构建订单确认页

🧱 第一步:创建订单相关模型

Models 文件夹中创建以下两个类:

✅ Order.cs

using System.ComponentModel.DataAnnotations;namespace ECommercePlatform.Models
{public enum OrderStatus{Pending,Paid,Shipped,Completed,Cancelled}public class Order{public int Id { get; set; }[Required]public string UserId { get; set; } = string.Empty;public DateTime OrderDate { get; set; } = DateTime.Now;public decimal TotalAmount { get; set; }public OrderStatus Status { get; set; } = OrderStatus.Pending;public List<OrderItem> Items { get; set; } = new();}
}

✅ OrderItem.cs

namespace ECommercePlatform.Models
{public class OrderItem{public int Id { get; set; }public int ProductId { get; set; }public string ProductName { get; set; } = string.Empty;public decimal Price { get; set; }public int Quantity { get; set; }public decimal TotalPrice => Price * Quantity;public int OrderId { get; set; }public Order Order { get; set; } = null!;}
}

🧰 第二步:更新数据库上下文

打开 ApplicationDbContext.cs 并添加以下代码:

public DbSet<Order> Orders { get; set; }
public DbSet<OrderItem> OrderItems { get; set; }

然后执行迁移命令:

dotnet ef migrations add AddOrderAndOrderItem
dotnet ef database update

🛒 第三步:创建订单服务逻辑

✅ 创建 Services/IOrderService.cs

using ECommercePlatform.Models;public interface IOrderService
{Task<int> CreateOrderFromCart(string userId, IList<CartItem> cartItems);Task<IList<Order>> GetOrdersByUser(string userId);Task<Order?> GetOrderById(int id, string userId);
}

✅ 创建 Services/OrderService.cs

using Microsoft.AspNetCore.Identity;
using ECommercePlatform.Models;
using ECommercePlatform.Services;public class OrderService : IOrderService
{private readonly ApplicationDbContext _context;private readonly UserManager<IdentityUser> _userManager;public OrderService(ApplicationDbContext context, UserManager<IdentityUser> userManager){_context = context;_userManager = userManager;}public async Task<int> CreateOrderFromCart(string userId, IList<CartItem> cartItems){if (cartItems.Count == 0) throw new ArgumentException("购物车为空");var order = new Order{UserId = userId,OrderDate = DateTime.Now,TotalAmount = cartItems.Sum(i => i.TotalPrice),Items = cartItems.Select(i => new OrderItem{ProductId = i.ProductId,ProductName = i.Name,Price = i.Price,Quantity = i.Quantity}).ToList()};_context.Orders.Add(order);await _context.SaveChangesAsync();return order.Id;}public async Task<IList<Order>> GetOrdersByUser(string userId){return await _context.Orders.Include(o => o.Items).Where(o => o.UserId == userId).OrderByDescending(o => o.OrderDate).ToListAsync();}public async Task<Order?> GetOrderById(int id, string userId){return await _context.Orders.Include(o => o.Items).FirstOrDefaultAsync(o => o.Id == id && o.UserId == userId);}
}

注册服务到 Program.cs

builder.Services.AddScoped<IOrderService, OrderService>();

📋 第四步:创建订单确认页面(Checkout/Index)

✅ Checkout/Index.cshtml.cs

using Microsoft.AspNetCore.Mvc.RazorPages;
using ECommercePlatform.Services;
using ECommercePlatform.Models;namespace ECommercePlatform.Pages.Checkout
{[Authorize]public class IndexModel : PageModel{private readonly IShoppingCartService _cartService;private readonly UserManager<IdentityUser> _userManager;public IndexModel(IShoppingCartService cartService, UserManager<IdentityUser> userManager){_cartService = cartService;_userManager = userManager;}public IList<CartItem> CartItems { get; set; } = new List<CartItem>();public decimal TotalPrice { get; set; }public async Task<IActionResult> OnGetAsync(){CartItems = _cartService.GetCartItems();TotalPrice = _cartService.GetTotalPrice();if (CartItems.Count == 0){return RedirectToPage("/Cart/Index");}return Page();}public async Task<IActionResult> OnPostAsync(){var user = await _userManager.GetUserAsync(User);if (user == null) return NotFound();var cartItems = _cartService.GetCartItems();if (cartItems.Count == 0) return BadRequest();// 创建订单var orderService = HttpContext.RequestServices.GetService<IOrderService>();var orderId = await orderService.CreateOrderFromCart(user.Id, cartItems);// 清空购物车_cartService.ClearCart();return RedirectToPage("/Checkout/Success", new { id = orderId });}}
}

✅ Checkout/Index.cshtml

@page
@model ECommercePlatform.Pages.Checkout.IndexModel<h2>确认订单</h2><table class="table"><thead><tr><th>名称</th><th>单价</th><th>数量</th><th>总价</th></tr></thead><tbody>@foreach (var item in Model.CartItems){<tr><td>@item.Name</td><td>$@item.Price</td><td>@item.Quantity</td><td>$@item.TotalPrice</td></tr>}</tbody>
</table><h4>总计:$@Model.TotalPrice</h4><form method="post"><button type="submit" class="btn btn-success">立即支付</button>
</form>

✅ 第五步:创建支付成功页面(Checkout/Success)

✅ Success.cshtml.cs

using Microsoft.AspNetCore.Mvc.RazorPages;namespace ECommercePlatform.Pages.Checkout
{public class SuccessModel : PageModel{public void OnGet(int id){// 这里可以显示订单编号或详细信息}}
}

✅ Success.cshtml

@page
@model ECommercePlatform.Pages.Checkout.SuccessModel<h2>✅ 支付成功!</h2>
<p>您的订单已提交。订单号:@Request.Query["id"]</p>
<a asp-page="/Orders/Index" class="btn btn-primary">查看我的订单</a>

❌ 第六步:创建支付失败页面(Checkout/Failed)

✅ Failed.cshtml.cs

using Microsoft.AspNetCore.Mvc.RazorPages;namespace ECommercePlatform.Pages.Checkout
{public class FailedModel : PageModel{public void OnGet(){}}
}

✅ Failed.cshtml

@page
@model ECommercePlatform.Pages.Checkout.FailedModel<h2>❌ 支付失败</h2>
<p>请返回重新尝试支付。</p>
<a asp-page="/Cart/Index" class="btn btn-warning">返回购物车</a>

📦 第七步:创建我的订单页面(Orders/Index)

✅ Orders/Index.cshtml.cs

using Microsoft.AspNetCore.Mvc.RazorPages;
using ECommercePlatform.Services;
using ECommercePlatform.Models;
using Microsoft.AspNetCore.Identity;namespace ECommercePlatform.Pages.Orders
{[Authorize]public class IndexModel : PageModel{private readonly IOrderService _orderService;private readonly UserManager<IdentityUser> _userManager;public IndexModel(IOrderService orderService, UserManager<IdentityUser> userManager){_orderService = orderService;_userManager = userManager;}public IList<Order> Orders { get; set; } = new List<Order>();public async Task OnGetAsync(){var user = await _userManager.GetUserAsync(User);if (user != null){Orders = await _orderService.GetOrdersByUser(user.Id);}}}
}

✅ Orders/Index.cshtml

@page
@model ECommercePlatform.Pages.Orders.IndexModel<h2>我的订单</h2>@if (Model.Orders.Count == 0)
{<p>暂无订单。</p>
}
else
{<table class="table"><thead><tr><th>订单号</th><th>日期</th><th>总金额</th><th>状态</th><th>操作</th></tr></thead><tbody>@foreach (var order in Model.Orders){<tr><td>@order.Id</td><td>@order.OrderDate.ToShortDateString()</td><td>$@order.TotalAmount</td><td>@order.Status</td><td><a asp-page="/Orders/Details" asp-route-id="@order.Id" class="btn btn-info btn-sm">查看详情</a></td></tr>}</tbody></table>
}

📦 第八步:提交 Git 版本

git add .
git commit -m "Day5: Added order submission and payment simulation with order status tracking"

📝 今日总结

今天你完成了:

✅ 创建 OrderOrderItem 模型
✅ 实现从购物车生成订单的功能
✅ 模拟支付流程(成功/失败页面)
✅ 订单状态跟踪(Pending、Paid、Shipped 等)
✅ 提交版本控制记录


📆 明日计划(Day6)

我们将进入 后台管理系统开发阶段

  • 创建管理员页面
  • 实现商品管理(CRUD)
  • 实现订单管理(查看、状态变更)
  • 权限控制(仅管理员可见)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/912232.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/912232.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

复杂驱动开发-TLE9471的休眠流程与定时唤醒

文章目录 前言休眠流程定时唤醒功能总结 前言 开发SBC时非常重要的一环就是开发休眠流程&#xff0c;其目的是为了保证接KL30的ECU在休眠模式下尽可能小的消耗低压蓄电池的电量&#xff0c;防止车辆放置长时间后出现亏电。而定时唤醒功能在部分ECU中会有需求休眠后定期对车辆状…

Spark 之 Reuse

src/main/scala/org/apache/spark/sql/execution/reuse/ReuseExchangeAndSubquery.scala case object ReuseExchangeAndSubquery extends Rule[SparkPlan] {def apply(plan: SparkPlan): SparkPlan = {if (conf.exchan

Solidity学习 - 错误处理

文章目录 前言EVM错误处理机制EVM错误处理的核心特性程序中的错误处理 错误抛出方法require()函数require()触发异常的场景关键特性 assert()函数assert()触发异常的场景关键特性 require() vs assert()&#xff1a;选择指南revert()函数关键特性 异常捕获&#xff1a;try/catc…

如何永久删除Android上的短信[无法恢复]

当您不再保留 Android 设备时&#xff0c;您将需要彻底删除所有私人数据&#xff0c;包括短信。因此&#xff0c;有必要了解如何永久删除Android上的短信。现在&#xff0c;阅读本指南&#xff0c;掌握消除信息的实用方法。 第 1 部分&#xff1a;如何一键永久删除 Android 上的…

P12894 [蓝桥杯 2025 国 Java B] 智能交通信号灯

[Problem] \color{blue}{\texttt{[Problem]}} [Problem] 给定一个长度为 n n n 的数组 a 1 … n a_{1\dots n} a1…n​&#xff0c;进行 m m m 次一下操作&#xff1a; 给定 l , r l,r l,r&#xff0c;求出 ∑ l ≤ i < j ≤ r mex { a i , a j } \sum\limits_{l \le…

华为云Flexus+DeepSeek征文|基于华为云一键部署的 Dify-LLM 平台构建智能试卷生成助手

目录 前言 1 华为云Dify-LLM应用平台部署 1.1 一键部署平台简介 1.2 四步完成部署流程 2 接入华为云 DeepSeek 自定义大模型 2.1 ModelArts Studio 模型服务介绍 2.2 配置自定义大模型 3 创建试卷生成工具&#xff08;工作流&#xff09; 3.1 设计 DSL 工作流 3.2 工…

嵌入式硬件与应用篇---寄存器GPIO控制

在 ARM 架构中&#xff0c;通过 32 位寄存器控制 GPIO&#xff08;通用输入输出&#xff09;的核心步骤和方法可分为以下几个关键环节&#xff0c;结合不同芯片的实现差异&#xff0c;具体操作需参考对应的数据手册&#xff1a; 一、GPIO 控制的核心步骤 1. 使能 GPIO 时钟 …

Fiddler中文版抓包工具在跨域与OAuth调试中的深度应用

跨域和OAuth授权流程一直是Web和移动开发中最容易踩坑的领域。复杂的CORS配置、重定向中的Token传递、授权码流程的跳转&#xff0c;以及多域名环境下的Cookie共享&#xff0c;常常让开发者陷入调试困境。此时&#xff0c;一款能够精准捕获、修改、重放请求的抓包工具显得至关重…

React用户交互事件

在React中处理用户交互事件&#xff08;如点击、输入、提交等&#xff09;的方式与原生JavaScript类似&#xff0c;但有一些语法差异和最佳实践。以下是常见交互事件的处理方法及代码示例&#xff1a; 一、基本事件处理&#xff08;点击、输入等&#xff09; 1. 点击事件&…

DHT11 STM32 HAL驱动库 整数

dht11.h #ifndef __DHT11_H #define __DHT11_H#include "stm32f1xx_hal.h" // 根据实际芯片型号调整&#xff08;如stm32f4xx_hal.h&#xff09;// DHT11数据结构 typedef struct {GPIO_TypeDef *GPIOx; // GPIO端口&#xff08;如GPIOA&#xff09;uint16_t GP…

【Actix Web 精要】Rust Web 服务开发核心技术与实战指南

目录 一、Actix Web 核心架构解析1.1 核心组件交互流程1.2 关键组件说明&#xff1a; 二、项目初始化与配置2.1 创建项目2.2 添加依赖 (Cargo.toml)2.3 项目结构 三、核心模块实现3.1 配置管理 (src/config.rs)3.2 应用状态管理 (src/main.rs)3.3 数据模型 (src/models/user.rs…

从URL到视频:用Python和AI构建自动化内容讲解视频生成管道

摘要 本文旨在从技术层面&#xff0c;深入探讨并实践一个将任意网页链接&#xff08;如飞书文档、博客文章&#xff09;自动转换为带有配音和字幕的讲解视频的系统。我们将详细拆解整个实现流程&#xff0c;覆盖从内容抓取与解析、利用大语言模型&#xff08;LLM&#xff09;智…

Java 使用 Easy Excel 进行 Excel 数据导入导出

1. 通过 Maven 下载 Easy Excel 依赖包 在项目的 pom.xml 文件中添加以下依赖&#xff1a; <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version> <!-- 使用最新版本 -->…

国产化条码类库Spire.Barcode教程:如何使用 C# 读取 PDF 中的条码(两种方法轻松实现)

在 PDF 文档的 .NET 平台处理流程中&#xff0c;使用 C# 读取 PDF 条码 是一项常见需求&#xff0c;特别适用于处理扫描件或电子表单。无论是物流、金融、医疗还是制造行业&#xff0c;PDF 文档中经常包含用于追踪或识别的条码。这些条码可能是嵌入图像&#xff0c;也可能是矢量…

2023国赛数字取证-流量分析

数据取证 - 1 A 集团的⽹络安全监控系统发现恶意份⼦正在实施⾼级可持续攻击&#xff08;APT&#xff09;&#xff0c;并抓取了部分可疑流量包。请 您根据捕捉到的流量包&#xff0c;搜寻出⽹络攻击线索&#xff0c;分解出隐藏的恶意程序&#xff0c;并分析恶意程序的⾏为。 …

【预约小程序】-健身房预约课程小程序——仙盟创梦IDE

东方仙盟-坐拥万个代码 免费报表 阿雪技术观 让我们积极投身于技术共享的浪潮中&#xff0c;不仅仅是作为受益者&#xff0c;更要成为贡献者。无论是分享自己的代码、撰写技术博客&#xff0c;还是参与开源项目的维护和改进&#xff0c;每一个小小的举动都可能成为推动技术进…

SmartETL中数据库操作与流程解耦的设计与应用

正如ETL这个概念本身所指示的&#xff0c;数据库读写访问是ETL的最常用甚至是最主要的操作。现代信息系统的设计与运行基本都是围绕数据库展开的&#xff0c;很多应用的核心功能都是对数据库的CRUD&#xff08;创建、检索、更新、删除&#xff09;操作。 SmartETL框架设计之初…

【记录解决问题】activiti--sql 转义符设置

一、背景 %、&#xff01;、_在sql查询时需要转义&#xff0c;转义的语法 like %?2% escape ?#{escapeCharacter()}二、activiti转义配置 String wildcardEscapeClause ""; if (this.databaseWildcardEscapeCharacter ! null && this.databaseWildcard…

Unity AR构建维护系统的以AI驱动增强现实知识检索系统

本博客概述了为维护开发的AI驱动增强现实&#xff08;AR&#xff09;知识检索系统的开发过程&#xff0c;该系统集成了Unity用于AR、Python服务器用于后端处理&#xff0c;以及ChatGPT用于自然语言处理。该系统允许维护工人通过AR设备&#xff08;如HoloLens 2&#xff09;查询…

Java面向对象核心:方法值传递与封装机制精讲

文章目录 Java面向对象编程核心笔记一、方法值传递机制1. 基本数据类型传递2. 引用数据类型传递值传递总结 二、面向对象核心概念1. 类与对象关系2. 类定义规范3. 对象创建与使用 三、封装机制详解1. 封装三大要素2. 封装示例&#xff08;GirlFriend类&#xff09;3. 测试类4. …