經過一段時間的準備,新的一期【ASP.NET Core MVC開發實戰之商城系統】已經開始,今天著重講解佈局設計,環境搭建,系統配置,及首頁商品類型,banner條,友情鏈接等功能的開發。 ...
經過一段時間的準備,新的一期【ASP.NET Core MVC開發實戰之商城系統】已經開始,今天著重講解佈局設計,環境搭建,系統配置,及首頁商品類型,banner條,友情鏈接等功能的開發。
首頁佈局設計
首頁是商城系統的門面,首頁的設計的好壞關係著用戶的體驗,在本示例中,首頁主要分為以下幾個模塊,如下所示:
項目環境搭建
1. 安裝第三方庫
所謂“工欲善其事必先利其器”,在開發程式之前,先將項目配置好。項目需要安裝的第三方庫,可通過Nuget包管理器進行安裝。
目前程式用到的第三方庫有三個:
- 日誌組件:NLog,NLog.Web.AspNetCore,主要用於記錄系統日子。
- 資料庫組件:目前採用SqlSugarCore,訪問資料庫程式。
具體安裝庫和版本如下所示:
2. 啟動配置
汽配啟動配置主要配置註入服務,及路由,主要有以下幾個:
- Session服務,由於到進行用戶身份驗證,所以需要用到Session。
- 鑒權/授權組件,主要用於什麼驗證及許可權管理。
- 日誌組件,記錄程式執行過程的日誌,便於問題分析和解決。
- 路由控制器註入。
具體配置【Program.cs】參照如下所示:
using EasyBuyShop.DAL;
using EasyBuyShop.Utils;
using Microsoft.AspNetCore.Authentication.Cookies;
using NLog.Web;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
//1. 往容器中添加Session服務,啟用Session服務
builder.Services.AddSession(option =>
{
option.IdleTimeout = TimeSpan.FromMinutes(10);
option.Cookie.Name = "DemoMvcCore";
});
//添加鑒權服務
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.LoginPath = "/Auth/Login";
options.LogoutPath = "/Auth/Logout";
});
// NLog: Setup NLog for Dependency injection
builder.Logging.ClearProviders();
builder.Host.UseNLog();
LogHelper.LoadConfiguration();
var app = builder.Build();
//啟動時獲取資料庫連接字元串
BaseDal.ConnStr = app.Configuration.GetConnectionString("Default");
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
//2.使用Session中間件,主要用於攔截Http請求
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
3. 配置文件
配置文件【appsetting.json】主要配置資料庫連接字元串,及其他信息。如下所示:
{
"ConnectionStrings": {
"Default": "Server=localhost;Database=EasyBuyShop;Trusted_Connection=True;User Id=sa;Password=abc123"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
4. 日誌配置
日誌配置【nlog.config】主要配置NLog組件需要的日誌保存路徑以及層級等信息。如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info"
internalLogFile="\Logs\internal-nlog-AspNetCore.txt">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets>
<!-- File Target for all log messages with basic details -->
<target xsi:type="File" name="allfile" fileName="${basedir}\Logs\nlog-all-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" />
<!-- File Target for own log messages with extra web details using some ASP.NET core renderers -->
<target xsi:type="File" name="ownFile-web" fileName="${basedir}\Logs\nlog-own-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
<!--Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection -->
<target xsi:type="Console" name="lifetimeConsole" layout="${MicrosoftConsoleLayout}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Info" writeTo="allfile" />
<!--Output hosting lifetime messages to console target for faster startup detection -->
<logger name="*" minlevel="Info" writeTo="lifetimeConsole, ownFile-web" final="true" />
<!--Skip non-critical Microsoft logs and so log only own logs (BlackHole) -->
<logger name="Microsoft.*" minlevel="Info" final="true" />
<logger name="System.Net.Http.*" minlevel="Info" final="true" />
<logger name="*" minlevel="Info" writeTo="ownFile-web" />
</rules>
</nlog>
註意:NLog日誌組件不支持相對路徑配置,如果想讓日誌保存在程式根目錄,需要通過${basedir}進行配置,否則日誌如法保存。
頁面佈局
其中Header,Footer,前臺各個頁面都會用到,所以採用Layout佈局頁面展示【_Layout.cshtml】。如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - 易購商城</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/shop_style.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/EasyBuyShop.styles.css" asp-append-version="true" />
</head>
<body>
<header class="py-3 mb-3 border-bottom container" style="padding-left: 0px;padding-right: 0px;">
<div class="container-fluid d-grid gap-3 align-items-center" style="grid-template-columns: 1fr 9fr;width:100%;padding-left: 0px;padding-right: 0px;">
<div class="dropdown">
<a href="/Home/Index" class="d-flex align-items-center col-lg-4 mb-2 mb-lg-0 link-dark text-decoration-none dropdown-toggle">
<h2>易購商城</h2>
</a>
</div>
<div class="d-flex align-items-center">
<form class="w-100 me-3" role="search" action="/Product/Index/">
<div>
<input type="search" class="form-control" placeholder="商品名稱" aria-label="Search" style="width:85%;display:inline-block;line-height:1.7" name="productName">
<button type="submit" class="btn btn-outline-primary">搜索</button>
</div>
</form>
<div class="flex-shrink-0 dropdown">
@if (!string.IsNullOrEmpty(ViewBag.UserName))
{
<a href="#" class="d-block link-dark text-decoration-none dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
<span>@ViewBag.RealName</span>
</a>
<ul class="dropdown-menu text-small shadow" style="">
<li><a class="dropdown-item" href="/Cart/Index">購物車</a></li>
<li><a class="dropdown-item" href="/Personal/Setting">設置</a></li>
<li><a class="dropdown-item" href="/Personal/Index">個人信息</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="/Auth/Logout">登出</a></li>
</ul>
}
else
{
<a href="/Auth/Login" class="d-block link-dark text-decoration-none">
<span>親,請登錄</span>
</a>
}
</div>
</div>
</div>
</header>
<div class="container" style="padding-left:0px;padding-right:0px;">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="py-3 my-4 border-top footer text-muted" style="line-height:10px;margin-bottom:0.5rem!important;">
<p class="text-center text-muted">© 2023-2024 易購商城 老碼識途 公子小六</p>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
佈局頁面效果如下所示:
頁頭【Header】包含一個Form表單,用於查詢商品信息,如下所示:
頁腳【Footer】用於設置版權信息,如下所示:
商品類型功能
首先每一個商品有類型,類型分為大類【Category】,中類,小類【SubCategory】,細類等,本文為了簡化,只分為大類,小類兩種。
1. 資料庫設計
數據表結構設計如下:
大類Category表,如下所示:
建表語句如下所示:
CREATE TABLE [dbo].[EB_Category](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Category] [varchar](100) NULL,
[Description] [varchar](500) NULL,
[CreateTime] [datetime] NULL,
[CreateUser] [varchar](50) NULL,
[LastEditTime] [datetime] NULL,
[LastEditUser] [varchar](50) NULL
) ON [PRIMARY]
小類SubCategory表,如下所示:
註意:數據表中的分類內容,是從某寶抄下來的,然後整理好後,導入資料庫。
建表語句如下所示:
CREATE TABLE [dbo].[EB_SubCategory](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[CategoryId] [bigint] NULL,
[SubCategory] [varchar](100) NULL,
[Description] [varchar](500) NULL,
[CreateTime] [datetime] NULL,
[CreateUser] [varchar](50) NULL,
[LastEditTime] [datetime] NULL,
[LastEditUser] [varchar](50) NULL
) ON [PRIMARY]
2. 項目模型創建
SqlSurgar採用模型對象映射ORM操作資料庫,所以需要先創建模型對象。
大類Category模型對象,如下所示:
using SqlSugar;
namespace EasyBuyShop.Models
{
[SugarTable("EB_Category")]
public class Category : EntityModel
{
[SugarColumn(ColumnName ="Category")]
public string CategoryName { get; set; }
public string Description { get; set; }
}
}
小類SubCategory模型對象,如下所示:
using SqlSugar;
namespace EasyBuyShop.Models
{
[SqlSugar.SugarTable("EB_SubCategory")]
public class SubCategory : EntityModel
{
public long CategoryId { get; set; }
[SugarColumn(ColumnName = "SubCategory")]
public string SubCategoryName { get; set; }
public string Description { get; set; }
}
}
其中EntityModel為模型基類,為公共類型,如下所示:
using SqlSugar;
using System.ComponentModel.DataAnnotations.Schema;
using System.Security.Principal;
namespace EasyBuyShop.Models
{
public class EntityModel
{
[SugarColumn(IsNullable = false, IsIdentity = true)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public DateTime CreateTime { get; set; }
public string CreateUser { get; set; }
public DateTime LastEditTime { get; set; }
public string LastEditUser { get; set; }
}
}
3. 資料庫操作類
資料庫操作類位於DAL層,每一個表都有對應的DAL層,如下所示:
大類Category數據表操作DAL層,如下所示:
using EasyBuyShop.Models;
namespace EasyBuyShop.DAL
{
public class CategoryDal:BaseDal
{
public CategoryDal()
{
}
public List<Category> GetCategories()
{
return this.getTList<Category>();
}
}
}
小類SubCategory數據表操作DAL層,如下所示:
using EasyBuyShop.Models;
namespace EasyBuyShop.DAL
{
public class SubCategoryDal : BaseDal
{
public List<SubCategory> GetSubCategories()
{
return this.getTList<SubCategory>();
}
}
}
其中BaseDal為基類,資料庫操作的公共方法,如下所示:
using EasyBuyShop.Utils;
using SqlSugar;
namespace EasyBuyShop.DAL
{
public class BaseDal
{
public static string ConnStr = string.Empty;
/// <summary>
/// 獲取程式資料庫操作對象
/// </summary>
/// <param name="strConn">資料庫連接字元串</param>
/// <returns></returns>
public SqlSugarClient GetDb(string strConn)
{
var db = new SqlSugarClient(
new ConnectionConfig()
{
ConnectionString = strConn,
DbType = DbType.SqlServer,
IsAutoCloseConnection = true,
InitKeyType = InitKeyType.Attribute,
AopEvents = new AopEvents
{
OnLogExecuting = (sql, p) =>
{
LogHelper.Info(sql);
LogHelper.Info(string.Join(",", p?.Select(it => it.ParameterName + ":" + it.Value)));
}
}
});
return db;
}
/// <summary>
/// 查詢所有的用戶記錄
/// </summary>
/// <returns></returns>
public List<T> getTList<T>()
{
try
{
return this.GetDb(ConnStr).Queryable<T>().ToList();
}
catch (Exception ex)
{
LogHelper.Fatal(ex.Message);
return null;
}
}
/// <summary>
/// 插入一條記錄
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public int InsertT<T>(T model) where T : class, new()
{
try
{
return this.GetDb(ConnStr).Insertable<T>(model).ExecuteCommand();
}
catch (Exception ex)
{
LogHelper.Fatal(ex.Message);
return -1;
}
}
}
}
4. 商品類型控制器部分
商品類型只是首頁【/Home/Index】的一小部分,首頁的控制器獲取到商品類型信息,然後傳遞到視圖層即可。如下所示:
public IActionResult Index()
{
CategoryDal categoryDal = new CategoryDal();
SubCategoryDal subCategoryDal = new SubCategoryDal();
var categories = categoryDal.GetCategories();
var subCategories = subCategoryDal.GetSubCategories();
ViewData["Categories"] = categories;
ViewData["SubCategories"] = subCategories;
return View();
}
5. 商品類型視圖部分
商品類型視圖在首頁【/Home/Index.cshtml】中,如下所示:
<div mxs="x30_:_" class="left-nav" data-spm="1998549605" style="width: 280px;height: 280px;position: absolute;left: 0px;top: 0;z-index: 2;">
<div class="chanel-list-wrap" id="J_MAIN_CHANEL" style="background-color: #F8F8F8;border: 1px solid #eee;border-radius: 12px;font: 12px/1.5 tahoma, arial;height: 100%;">
@foreach(var category in ViewData["Categories"] as List<Category>)
{
var id = category.Id;
var subCategories = ViewData["SubCategories"] as List<SubCategory>;
var subCategoriesById = subCategories.Where(r => r.CategoryId == id);
<div class="chanel-container">
<div class="chanel-container-inner clearfix" style="border-radius: 12px 12px 0 0;">
<div class="chanel-tags-wrap">
<div class="chanel-title">
<a href="" class="atbfont" target="_blank">ↂ</a>
<a href="" class="title" target="_blank">@category.CategoryName</a>
</div>
<div class="chanel-tags clearfix">
@foreach(var subCategory in subCategoriesById)
{
<a href="/Product/Index/?CategoryId=@(id)&subCategoryId=@(subCategory.Id)" class="" target="_blank">@subCategory.SubCategoryName</a>
}
</div>
</div>
</div>
</div>
}
</div>
</div>
6. 商品類型示例
商品類型示例效果圖,如下所示:
banner條及友情鏈接
banner條主要用與廣告位之類的顯示,友情鏈接主要用於鏈接其他網站或者站內頁面。目前banner條設計了兩張靜態圖,友情鏈接參考了某寶內容,視圖文件如下所示:
<div mxa="x30_:b" class="main-right clearfix">
<div mxa="x30_:c" class="main-right-top" style="height: 280px;position: relative;z-index: 1;font-size: 0;">
<div mxa="x30_:d" class="slide-container clearfix">
<div mxa="x30_:e" class="slide-wrap swiper swiper-container-horizontal" id="index-mainSlide">
<div mxa="x30_:f" class="slide-con swiper-wrapper" style="height:280px;position:relative;left:0px;display:flex">
<div class="con-pannel swiper-slide swiper-slide-duplicate-active" data-swiper-slide-index="1">
<a href="#" target="_blank">
<img class="swiper-lazy swiper-lazy-loaded" src="~/imgs/001.jpg" width="730" height="280" />
</a>
</div>
<div class="con-pannel swiper-slide swiper-slide-duplicate-active" data-swiper-slide-index="0">
<a href="#" target="_blank">
<img class="swiper-lazy swiper-lazy-loaded" src="~/imgs/002.jpg" width="730" height="280" />
</a>
</div>
<div class="con-pannel swiper-slide swiper-slide-duplicate-active" data-swiper-slide-index="1">
<a href="#" target="_blank">
<img class="swiper-lazy swiper-lazy-loaded" src="~/imgs/001.jpg" width="730" height="280" />
</a>
</div>
<div class="con-pannel swiper-slide swiper-slide-duplicate-active" data-swiper-slide-index="0">
<a href="#" target="_blank">
<img class="swiper-lazy swiper-lazy-loaded" src="~/imgs/002.jpg" width="730" height="280" />
</a>
</div>
</div>
</div>
</div>
<div mxa="x30_:g" class="bl-right-navigation">
<div mxs="x30_:e" class="right-brands-title" data-spm="19985674830">
<a target="_blank" href="/Home/Index" style="color:#ff0036;"><i class="atbfont">✮</i>我的商城</a>
</div>
<ul mxa="x30_:h" class="right-brands-list clearfix">
<li data-spm="19985674831">
<a target="_blank" href="/Home/Index" style="text-decoration: none!important;">
<i class="atbfont" style="font-size: 22px;color:#c50a0a;">易購商城</i>
</a>
</li>
<li data-spm="19985674832">
<a target="_blank" href="">
<img src="~/imgs/others/taobao.gif" width="119" height="61">
</a>
</li>
<li data-spm="19985674833">
<a target="_blank" href="">
<img src="~/imgs/others/juhuasuan.gif" width="119" height="61">
</a>
</li>
<li data-spm="19985674834">
<a target="_blank" href="">
<img src="~/imgs/others/chaojiyouxuan.png" width="119" height="61">
</a>
</li>
<li data-spm="19985674835">
<a target="_blank" href="" style="text-decoration: none!important;">
<i class="atbfont" style="font-size: 22px;color:#ff4400;">九塊九</i>
</a>
</li>
<li data-spm="19985674836">
<a target="_blank" href="">
<img src="~/imgs/others/tianmaoguoji.png" width="119" height="61">
</a>
</li>
<li data-spm="19985674837">
<a target="_blank" href="">
<img src="~/imgs/others/tianmaochaoshi.gif" width="119" height="61">
</a>
</li>
<li data-spm="19985674838">
<a target="_blank" href="">
<img src="~/imgs/others/ailijiankang.png" width="119" height="61">
</a>
</li>
</ul>
</div>
</div>
</div>
以上就是ASP.NET Core MVC開發實戰之商城系統(環境搭建及首頁設計) 的全部內容,後續將繼續介紹其他模塊。
作者:小六公子
出處:http://www.cnblogs.com/hsiang/
本文版權歸作者和博客園共有,寫文不易,支持原創,歡迎轉載【點贊】,轉載請保留此段聲明,且在文章頁面明顯位置給出原文連接,謝謝。
關註個人公眾號,定時同步更新技術及職場文章