[回馈]ASP.NET Core MVC开发实战之商城系统(六)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面,商品详情,购物车等功能的开发,今天继续讲解订单管理功能开发,仅供学习分享使用,如有不足之处,还请指正。订单管理功能说明
在商城系统中,当用户需要购买商品时,就会进行下单。购买的入口有很多,比如:
[*]首页或商品列表页面,看到商品缩略图,可以点击【立即购买】按钮进行下单;
[*]在商品详情页面,查看商品的详细参数后,也可以点击【立即购买】按钮进行下单;
[*]在购物车页面,选择购物车中的商品,进行批量下单。
以上3个入口,下单方式大致相同,却又略有差异。具体如下所示:
[*]1,2两种方式是单个商品的购买。
[*]3是批量商品下单或单个商品下单,可以自由选择。
[*]1是默认商品参数进行下单,2是可以自由选择商品参数进行下单。
所以在不同是入口进行下单,要进行细微的调整。但是在跳转的下单页面,又可以进行统一。
同样立即购买功能,和添加购物车功能一样,需要用户的信息,需要登录才可以。
商品下单流程图
在易购商城系统中,商品下单流程图,如下所示:
订单管理功能开发
1. 数据表创建
订单表【EB_Purchase】,主要保存用户的订单信息,包括订单ID,商品ID,用户ID,物流ID,收货地址,商品备注等信息。具体如下所示:
订单表创建表语句如下所示:
CREATE TABLE .(
IDENTITY(1,1) NOT NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
(200) NULL,
(300) NULL,
NOT NULL,
(50) NULL,
NULL,
(50) NULL
) ON
2. 订单表实体模型创建
实体模型和数据库表字段保持一致,便于进行数据映射,具体如下所示:
using SqlSugar;
namespace EasyBuyShop.Models
{
public class Purchase : EntityModel
{
public long ProductId { get; set; }
public long CustomerId { get; set; }
public int BuyCount { get; set; }
public decimal TotalPrice { get; set; }
public long LogisticsId { get; set; }
/// <summary>
/// 收件地址ID
/// </summary>
public string RecvAddr { get; set; }
/// <summary>
/// 订单状态
/// </summary>
public int Status { get; set; }
public string Remark { get; set; }
}
}
3. 数据处理层DAL
数据处理层DAL,主要进行订单的查询,插入等操作。如下所示:
using EasyBuyShop.Models;
using EasyBuyShop.Utils;
namespace EasyBuyShop.DAL
{
public class PurchaseDal : BaseDal
{
/// <summary>
/// 获取当前用户的订单列表
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public List<Purchase> GetPurchases(long userId)
{
try
{
using (var db = this.GetDb(BaseDal.ConnStr))
{
return db.Queryable<Purchase>().Where(r => r.CustomerId == userId).ToList();
}
}
catch (Exception ex)
{
LogHelper.Fatal(ex.Message);
return new List<Purchase>();
}
}
}
}
4. 控制器获取
控制器主要包括订单管理【如:查询,删除等操作】,下单购买功能,根据上述分析,不同的入口单独进行处理。如下所示:
using EasyBuyShop.DAL;
using EasyBuyShop.Models;
using Microsoft.AspNetCore.Mvc;
namespace EasyBuyShop.Controllers
{
public class PurchaseController : Controller
{
public IActionResult Index()
{
var username = HttpContext.Session.GetString("username");
var realName = HttpContext.Session.GetString("realname");
var userId = HttpContext.Session.GetInt32("userid");
ViewData["Username"] = username;
ViewData["RealName"] = realName;
var purchaseDal = new PurchaseDal();
var purchases =purchaseDal.GetPurchases(userId.Value);
var products=new List<Product>();
var shops = new List<Shop>();
if (purchases != null && purchases.Count() > 0)
{
var productDal = new ProductDal();
var pIds = purchases.Select(x => x.ProductId).ToList();
products = productDal.GetProductListByIds(pIds);
if (products != null && products.Count() > 0)
{
var shopDal = new ShopDal();
shops = shopDal.GetShops(products.Select(r => r.ShopId).ToList());
}
}
ViewData["Shops"] = shops;
ViewData["ProductList"] = products;
ViewData["Purchases"] = purchases;
return View();
}
/// <summary>
/// 首页或商品列表快捷下单
/// </summary>
/// <param name="productId"></param>
/// <returns></returns>
public IActionResult Buy(int productId)
{
Msg msg = new Msg();
var userId = HttpContext.Session.GetInt32("userid");
var userName = HttpContext.Session.GetString("username");
var realName = HttpContext.Session.GetString("realname");
ViewData["Username"] = userName;
ViewData["RealName"] = realName;
if (userId == null)
{
msg.code = -1;
msg.message = "尚未登录";
return Redirect("/Auth/Login");
}
var shopDal = new ShopDal();
var productDal = new ProductDal();
var addrDal = new AddrDal();
var product = productDal.GetProduct(productId);
var shop = shopDal.GetShopById(product.ShopId);
var addrs = addrDal.GetAddrByUserId((long)userId);
List<Product> products = new List<Product>() { product };
List<Shop> shops = new List<Shop>() { shop };
Dictionary<string, string> productConfigs = new Dictionary<string, string>();
ViewData["Products"] = products;
ViewData["Shops"] = shops;
ViewData["Addrs"] = addrs;
ViewData["ProductConfigs"] = productConfigs;
return View();
}
/// <summary>
/// 确认下单
/// </summary>
/// <returns></returns>
public IActionResult Buy()
{
Msg msg = new Msg();
var userId = HttpContext.Session.GetInt32("userid");
var userName = HttpContext.Session.GetString("username");
if (userId == null)
{
msg.code = -1;
msg.message = "尚未登录";
return Redirect("/Auth/Login");
}
var addr = Request.Form["addr"];
var productIds = Request.Form["productId"].ToList();
foreach (var productId in productIds)
{
var remark = Request.Form[$"textarea_{productId}"];
var quantity = Request.Form[$"quantity_{productId}"];
var productDal = new ProductDal();
var product = productDal.GetProduct(long.Parse(productId));
if (product != null)
{
var pruchaseDal = new PurchaseDal();
var purchase = new Purchase();
purchase.ProductId = long.Parse(productId);
purchase.CustomerId = userId.Value;
purchase.BuyCount = int.Parse(quantity);
purchase.TotalPrice = product.PreferentialPrice * int.Parse(quantity);
purchase.LogisticsId = 0;//物流ID,下单时为空,商家发货后制定
purchase.Remark = remark;
purchase.Status = 0;
purchase.RecvAddr = addr;
purchase.CreateUser = userName;
purchase.CreateTime = DateTime.Now;
purchase.LastEditUser = userName;
purchase.LastEditTime = DateTime.Now;
int id = pruchaseDal.InsertT<Purchase>(purchase);
if (id > 0)
{
msg.code = 0;
msg.message = "成功";
}
else
{
msg.code = -1;
msg.message = "购买失败";
break;
}
}
else
{
msg.code = -1;
msg.message = "商品不存在";
break;
}
}
if (msg.code < 0)
{
ViewData["Msg"] = msg;
return View();
}
else
{
return Redirect("/Purchase/Index");
}
}
/// <summary>
/// 从详情页面下单
/// </summary>
/// <returns></returns>
public IActionResult BuyWithForm()
{
Msg msg = new Msg();
var userId = HttpContext.Session.GetInt32("userid");
var userName = HttpContext.Session.GetString("username");
if (userId == null)
{
msg.code = -1;
msg.message = "尚未登录";
return Json(msg);
}
var productId = long.Parse(Request.Form["productId"]);
var quantity = int.Parse(Request.Form["quantity"]);
var color = Request.Form["color"];
var size = Request.Form["size"];
var remark = $"颜色:{color},大小:{size}";
var productDal = new ProductDal();
var product = productDal.GetProduct(productId);
var shopDal = new ShopDal();
var addrDal = new AddrDal();
var shop = shopDal.GetShopById(product.ShopId);
var addrs = addrDal.GetAddrByUserId((long)userId);
List<Product> products = new List<Product>() { product };
List<Shop> shops = new List<Shop>() { shop };
Dictionary<string, string> productConfigs = new Dictionary<string, string>();
productConfigs.Add($"remark_{productId}", remark);
productConfigs.Add($"quantity_{productId}", quantity.ToString());
ViewData["Products"] = products;
ViewData["Shops"] = shops;
ViewData["Addrs"] = addrs;
ViewData["ProductConfigs"] = productConfigs;
return View("/Views/Purchase/Buy.cshtml");
}
/// <summary>
/// 从购物车下单
/// </summary>
/// <returns></returns>
public IActionResult BuyWithCart()
{
Msg msg = new Msg();
var userId = HttpContext.Session.GetInt32("userid");
var userName = HttpContext.Session.GetString("username");
if (userId == null)
{
msg.code = -1;
msg.message = "尚未登录";
return Json(msg);
}
var cartIds = Request.Form["chkCart"];
if (string.IsNullOrEmpty(cartIds))
{
msg.code = -1;
msg.message = "没有选择任何商品";
return Json(msg);
}
var cartIdArr = cartIds.ToString().Split(',');
if(cartIdArr!=null && cartIdArr.Length > 0)
{
var cartDal = new CartDal();
var productDal = new ProductDal();
var shopDal = new ShopDal();
var addrDal = new AddrDal();
List<Product> products = new List<Product>();
List<Shop> shops = new List<Shop>();
Dictionary<string, string> productConfigs = new Dictionary<string, string>();
foreach (var cartId in cartIdArr)
{
var cart = cartDal.GetCart(long.Parse( cartId));
var product = productDal.GetProduct(cart.ProductId);
if (product != null)
{
products.Add(product);
}
var shop = shopDal.GetShopById(product.ShopId);
if (shop != null)
{
shops.Add(shop);
}
productConfigs.Add($"remark_{cart.ProductId}", cart.Remark);
productConfigs.Add($"quantity_{cart.ProductId}", cart.Quantity.ToString());
}
var addrs = addrDal.GetAddrByUserId((long)userId);
ViewData["Products"] = products;
ViewData["Shops"] = shops;
ViewData["Addrs"] = addrs;
ViewData["ProductConfigs"] = productConfigs;
return View("/Views/Purchase/Buy.cshtml");
}
else
{
return View("/Views/Cart/Index");
}
}
}
}
5. 视图层展示
订单相关功能主要有两个页面,一个下单页面,一个订单管理页面。
下单页面主要功能是展示商品列表,下单按钮,以及用户的选择,备注,价格等信息。如下所示:
<form method="post" action="/Purchase/Buy">
@{
var addrs = ViewData["Addrs"] as List<Address>;
addrs = addrs.OrderByDescending(r => r.IsDefault).ToList();
var defaultAddr = addrs.FirstOrDefault(r => r.IsDefault);
var productConfigs = ViewData["ProductConfigs"] as Dictionary<string, string>;
var total = 0M;
}
<h2 >
确认收货地址
<arel="noopener noreferrer" target="_blank" href="//member1.taobao.com/member/fresh/deliver_address.htm">管理收货地址</a>
</h2>
<input type="hidden" name="addr" id="addr" value="@($"{defaultAddr.ToString()} ({defaultAddr.Name} 收) {defaultAddr.Phone}")" />
@{
for (int i = 0; i < addrs.Count; i++)
{
var addr = addrs;
if (addr.IsDefault)
{
<i >♥</i>
寄送至
<label dir="ltr" aria-checked="true" >
<input role="radio" tabindex="0" type="radio" aria-checked="true"checked="">
@addr.Province
@addr.City
@addr.District
@addr.Street
@addr.Detail
(@(addr.Name) 收)
@addr.Phone
默认地址
</label>
<atitle="设置当前地址为默认">设置为默认收货地址</a>
<a title="修改地址" >修改本地址</a>
}
else
{
<label dir="ltr" aria-checked="false" >
<input role="radio" tabindex="0" type="radio" aria-checked="false" >
@addr.Province
@addr.City
@addr.District
@addr.Street
@addr.Detail
(@(addr.Name) 收)
@addr.Phone
默认地址
</label>
<atitle="设置当前地址为默认">设置为默认收货地址</a>
}
}
}
<a>使用其它地址</a>
<h2 >确认订单信息</h2>
店铺宝贝
商品属性
单价
数量
优惠方式
小计
@{
var products = ViewData["Products"] as List<Product>;
var shops = ViewData["Shops"] as List<Shop>;
for (int i = 0; i < products.Count; i++)
{
var product = products;
var quantity_key = $"quantity_{product.Id}";
var remark_key = $"remark_{product.Id}";
var quantity = 1;
var remark = "";
if (productConfigs != null || productConfigs.Count > 0)
{
if (productConfigs.ContainsKey(quantity_key))
{
quantity = int.Parse(productConfigs);
}
if (productConfigs.ContainsKey(remark_key))
{
remark = productConfigs;
}
}
var shop = shops.FirstOrDefault(r => r.Id == product.ShopId);
total += (product.PreferentialPrice * quantity);
<input type="hidden" name="productId" value="@(product.Id)" />
店铺:
<a href="https://www.cnblogs.com/Shop/Index?id=@(product.ShopId)" target="_blank" rel="noopener noreferrer" title="" >@(shop.Description)</a>
卖家:
<a href="https://www.cnblogs.com/##" target="_blank" rel="noopener noreferrer" title="@(shop.Description)" >@(shop.Name)</a>
<a href="https://www.cnblogs.com/" target="_blank"title=""></a>
<a href="https://www.cnblogs.com/Product/Detail/@(product.Id)" target="_blank" rel="noopener noreferrer" >
<imgsrc="https://www.cnblogs.com/@(product.ImageUrl)">
</a>
<a href="https://www.cnblogs.com/Product/Detail/@(product.Id)" target="_blank" rel="noopener noreferrer" >@(product.Name)</a>
<a href="https://www.cnblogs.com/##" target="_blank" rel="noopener noreferrer" title="如实描述 - 消费者保障服务,卖家承诺商品如实描述" >
<img src="https://www.cnblogs.com/~/imgs/others/quanyi.png">
</a>
<a target="_blank" rel="noopener noreferrer" title="7天无理由退货" ><img></a>
<p>
基础风格:@(product.BasicStyle)
</p>
<p>
商品类型:@(product.ProductStyle)
</p>
@(Math.Round(product.Price, 2))
<p><input type="text" name="quantity_@(product.Id)" id="quantity_@(product.Id)" value="@(quantity)"onchange="javascript:confirmTotalPrice(@(product.Id));" /></p>
<p >@(product.Preferential > 0 ? Math.Round(product.Preferential * 100, 2).ToString() + "%" : "无优惠")</p>
<input type="hidden" value="@(Math.Round(product.PreferentialPrice,2))" id="preferentitalprice_@(product.Id)" />
@(Math.Round(product.PreferentialPrice * quantity, 2))
<label >
给卖家留言:
</label>
<textarea placeholder="选填,请先和商家协商一致,付款后商家可见" id="textarea_@(product.Id)" name="textarea_@(product.Id)" maxlength="200" data-real="true" rows="1">@(remark)</textarea>
0/200
运送方式:
<label >普通配送</label>
<label ></label>
快递¥10.00
10.00
运费险:
<label >
<i ></i>
<input type="checkbox" aria-checked="false" >
运费险
退换货可赔付10元
</label>
<img src="https://www.cnblogs.com/~/imgs/others/msg.png" >
退换货可赔付10元
<a href="https://www.cnblogs.com/##" target="_blank" >
<imgsrc="https://www.cnblogs.com/~/imgs/others/ask.png">
</a>
0.00
店铺合计(含运费)
¥@(Math.Round(product.PreferentialPrice * quantity, 2))
}
}
实付款:
¥
@(Math.Round(total, 2))
寄送至:
@defaultAddr.ToString();
收货人:
@defaultAddr.Name @defaultAddr.Phone
<atarget="_self" role="button" title="返回购物车" href="//cart.taobao.com/cart.htm">返回购物车</a>
<input type="submit" title="提交订单" value="提交订单"></input>
若价格变动,请在提交订单后联系卖家改价,并查看已买到的宝贝
</form>订单管理页面
订单管理页面,主要查看已经购买过从商品信息。如下所示:
@{
var purchases = ViewData["Purchases"] as List<Purchase>;
var products = ViewData["ProductList"] as List<Product>;
var shops = ViewData["Shops"] as List<Shop>;
}
所有订单
|
待付款
|
待发货
|
待收货
|
待评价
|
分阶段
<imgsrc="https://www.cnblogs.com/~/imgs/TB1G5QqIFXXXXbvXFXXcmA2.FXX-11-12.png" alt="订单回收站">
订单回收站
<form >
<input type="text" placeholder="输入商品标题或订单号进行搜索" >
<button type="submit" >订单搜索</button>
<button type="button" >
更多筛选条件
<img src="https://www.cnblogs.com/~/imgs/TB1jK1dIVXXXXXzXVXXXXXXXXXX.png">
</button>
<label>
订单类型
全部
<b></b>
</label>
成交时间
<inputplaceholder="请选择时间范围起始" type="text">
-
<inputplaceholder="请选择时间范围结束" type="text">
<label >
卖家昵称
<inputtype="text">
</label>
<label>
评价状态
全部
<b></b>
</label>
<label data-reactid=".0.2.1.1.1.0">
交易状态
全部
<b></b>
</label>
<label >
售后服务
全部
<b></b>
</label>
</form>
<table >
<colgroup data-reactid=".0.4.0">
<col >
<col >
<col >
<col >
<col >
<col >
<col >
</colgroup>
<tbody data-reactid=".0.4.1">
<tr data-reactid=".0.4.1.0">
<th>宝贝</th>
<th>单价</th>
<th>数量</th>
<th>商品操作</th>
<th>实付款</th>
<th>
交易状态
<b></b>
</th>
<th>交易操作</th>
</tr>
</tbody>
</table>
<buttondisabled="">上一页</button>
<button >下一页</button>
@if (purchases != null && purchases.Count > 0)
{
foreach (var purchase in purchases)
{
var product = products.FirstOrDefault(r => r.Id == purchase.ProductId);
var shop = shops.FirstOrDefault(r => r.Id == product.ShopId);
<table >
<colgroup>
<col >
<col >
<col >
<col >
<col >
<col >
<col >
</colgroup>
<tbody >
<tr>
<td >
<label >
<input type="checkbox" disabled="">
@(purchase.CreateTime.ToString("yyyy-MM-dd"))
</label>
订单号
:
@purchase.Id
</td>
<td colspan="2" >
<a href="https://www.cnblogs.com/"title="@shop.Name" target="_blank" rel="noopener noreferrer">@shop.Name</a>
</td>
<td>
<a href="https://www.cnblogs.com/" target="_blank"title=""></a>
</td>
<td colspan="3" >
<a href="https://www.cnblogs.com/"title="编辑标记信息,仅自己可见" target="_blank" rel="noopener noreferrer" id="flag">
<i ></i>
</a>
<a href="https://www.cnblogs.com/###"title="删除订单" target="_blank" rel="noopener noreferrer" action="a7" data="" id="delOrder">
<i ></i>
</a>
</td>
</tr>
</tbody>
<tbody>
<tr>
<td >
<a href="https://www.cnblogs.com/Product/Detail/@(product.Id)"target="_blank" rel="noopener noreferrer">
<img src="https://www.cnblogs.com/@(product.ImageUrl)">
</a>
<p>
<a href="https://www.cnblogs.com/Product/Detail/@(product.Id)" target="_blank" rel="noopener noreferrer">
@product.Name
</a>
</p>
<p>
<a href="https://www.cnblogs.com/Rule/Real" title="正品保证" type="3"target="_blank">
<img src="https://www.cnblogs.com/~/imgs/T1SyeXFpliXXaSQP_X-16-16.png">
</a>
<a href="https://www.cnblogs.com/Rule/XiaoBao" title="如实描述" type="3"target="_blank"><img src="https://www.cnblogs.com/~/imgs/TB1PDB6IVXXXXaVaXXXXXXXXXXX.png"></a>
</p>
</td>
<td >
<p>
¥
@(Math.Round(product.PreferentialPrice, 2))
</p>
</td>
<td >
<p>@(purchase.BuyCount)</p>
</td>
<td>
<p >
申请售后
</p>
</td>
<td >
<p>
<strong>
¥
@(purchase.TotalPrice)
</strong>
</p>
<p >
</p>
</td>
<td >
<p >购买成功</p>
<p >
<a href="https://www.cnblogs.com/"target="_blank" rel="noopener noreferrer" id="viewDetail">订单详情</a>
</p>
</td>
<td >
<p >
<a href="https://www.cnblogs.com/"target="_blank" rel="noopener noreferrer">追加评论</a>
</p>
<p >
再次购买
</p>
</td>
</tr>
</tbody>
</table>
}
}
else
{
<imgsrc="https://www.cnblogs.com/~/imgs/avif/noorder.avif">
没有符合条件的宝贝,请尝试其他搜索条件。
}
<ulunselectable="unselectable">
<li title="上一页" ><a></a></li>
<li title="1" ><a>1</a></li>
<li title="2" ><a>2</a></li>
<li title="3" ><a>3</a></li>
<li title="4" ><a>4</a></li>
<li title="下一页" ><a></a></li>
<noscript></noscript>
</ul>
下单及订单管理展示
运行程序,点击登录,在登录成功后,选择商品点击【立即购买】或者购物车页面点击【购买】,然后跳转到下单页面,如下所示:
订单管理页面
运行程序,点击登录,在登录成功后,在右上角个人名称,点击下拉菜单,选择订单管理,然后打开订单管理页面,如下所示:
以上就是ASP.NET Core MVC开发实战之商城系统第六部分内容,后续将继续介绍其他模块,敬请期待。
来源:https://www.cnblogs.com/hsiang/archive/2023/08/27/17659726.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页:
[1]