最近學習Layui ,就準備通過Layui來實現之前練習的專案,
先建立一個新的Web 空專案,選MVC
新建專案
建立各種類庫,模組之間新增引用,並安裝必要Nuget包(EF包)
模組名稱 模組之間引用 安裝Nuget包
BizLogic-------業務邏輯 (BizModel.DLL, DataEntity.DLL, Util.DLL) entityframework
BizModel------實體類
DataEntity-----DB對映模組 (Util.DLL) entityframework
Util---------------公共類庫
Web--------------介面UI (BizLogic.DLL, BizModel.DLL, DataEntity.DLL, Util.DLL) entityframework
建立並生成EF
中小專案 可以直接關閉懶載入
連線DB配置,移動到UI層
下面編寫公共方法
DataResult.cs ------------通用資料結果類
PagedResult.cs----------分頁通過資料結果
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CarterHotel.Util { /// <summary> /// 通用資料結果類 /// </summary> /// <typeparam name="TModel"></typeparam> public class DataResult<TModel> { /// <summary> /// 操作是否成功 /// </summary> public bool IsSuccess { get; set; } /// <summary> /// 錯誤提示資訊 /// </summary> public string ErrorMessage { get; set; } /// <summary> /// 資料結果 /// </summary> public TModel Data { get; set; } public DataResult() { IsSuccess = true; } public DataResult(string errorMessage) { IsSuccess = false; ErrorMessage = errorMessage; } public DataResult(TModel data) { IsSuccess = true; Data = data; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CarterHotel.Util { /// <summary> /// 分頁通過資料結果 /// </summary> public class PagedResult<TModel>:DataResult<TModel>//繼承DataResult { /// <summary> /// 當前頁索引 /// </summary> public int PageIndex { get; set; } /// <summary> /// 每頁記錄條數 /// </summary> public int PageSize { get; set; } /// <summary> /// 資料記錄條數 /// </summary> public int TotalCount { get; set; } /// <summary> /// 當前頁資料 /// </summary> public List<TModel> CurrentPageData { get; set; } public PagedResult(int pageIndex, int pageSize, int totalCount, List<TModel> currentPageData) { IsSuccess = true; PageIndex = pageIndex; TotalCount = totalCount; CurrentPageData = currentPageData; } public PagedResult(int totalCount, List<TModel> currentPageData) { IsSuccess = true; TotalCount = totalCount; CurrentPageData = currentPageData; } } }
建立EncryptionMD5.cs 單向MD5加密
using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace CarterHotel.Util { /// <summary> /// MD5 /// 單向加密 /// </summary> public class EncryptionMD5 { /// <summary> /// 獲得一個字串的加密密文 /// 此密文為單向加密,即不可逆(解密)密文 /// </summary> /// <param name="plainText">待加密明文</param> /// <returns>已加密密文</returns> public static string EncryptString(string plainText) { return EncryptStringMD5(plainText); } /// <summary> /// 獲得一個字串的加密密文 /// 此密文為單向加密,即不可逆(解密)密文 /// </summary> /// <param name="plainText">待加密明文</param> /// <returns>已加密密文</returns> public static string EncryptStringMD5(string plainText) { MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider(); byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(plainText)); StringBuilder encryptText = new StringBuilder(); for (int i = 0; i < data.Length; i++) { encryptText.Append(data[i].ToString("x2")); } return encryptText.ToString(); } /// <summary> /// 判斷明文與密文是否相符 /// </summary> /// <param name="plainText">待檢查的明文</param> /// <param name="encryptText">待檢查的密文</param> /// <returns>bool</returns> public static bool EqualEncryptString(string plainText, string encryptText) { return EqualEncryptStringMD5(plainText, encryptText); } /// <summary> /// 判斷明文與密文是否相符 /// </summary> /// <param name="plainText">待檢查的明文</param> /// <param name="encryptText">待檢查的密文</param> /// <returns>bool</returns> public static bool EqualEncryptStringMD5(string plainText, string encryptText) { bool result = false; if (string.IsNullOrEmpty(plainText) || string.IsNullOrEmpty(encryptText)) return result; result = EncryptStringMD5(plainText).Equals(encryptText); return result; } } }
接下來對公共錯誤頁面的編寫
在UI層新建StaticContent資料夾 並將下載好的Layui 樣式 js 檔案放到資料夾下,並新增對應的檢視,異常處理過濾器
下面 錯誤頁面html程式碼
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>錯誤提示</title> <link href="~/StaticContent/layui/css/layui.css" rel="stylesheet" /> <style> .layadmin-tips { margin-top: 30px; text-align: center } .layadmin-tips .layui-icon[face] { display: inline-block; font-size: 300px; color: #393D49; } .layadmin-tips .layui-text { width: 500px; margin: 30px auto; padding-top: 20px; border-top: 5px solid #009688; font-size: 22px } </style> </head> <body> <div class="layui-fluid"> <div class="layadmin-tips"> <i class="layui-icon layui-icon-face-surprised" face></i> <div class="layui-text">好像出錯了</div> </div> </div> </body> </html>
增加異常處理過濾器 App_Start 新建立Filter-->HandleExceptionFileterAttribute類 並實現IExceptionFilter 介面;
2,在App_Start 下建立FilterConfig 過濾器配置類,並註冊過濾器
程式碼如下
using CarterHotel.Util; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace CarterHotel.Web.App_Start.Filters { /// <summary> /// 異常處理過濾器 /// </summary> public class HandleExceptionFileterAttribute : IExceptionFilter { public void OnException(ExceptionContext filterContext) { //判斷當前的請求是否為ajax bool isAjaxRequest = filterContext.HttpContext.Request.IsAjaxRequest(); if (isAjaxRequest) { filterContext.Result = new JsonResult() { Data = new DataResult<string>(errorMessage: "系統發生錯誤") }; } else { filterContext.Result = new RedirectResult(url: "/Error"); } //異常發生後,進行處理以後,需要告訴應用程式,這個異常處理意見處理過了 filterContext.ExceptionHandled = true; } } }
註冊過濾器
using CarterHotel.Web.App_Start.Filters; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace CarterHotel.Web.App_Start { /// <summary> /// 過濾器配置類 /// </summary> public static class FilterConfig { /// <summary> /// 過濾器註冊 /// </summary> /// <param name="filters"></param> public static void RegisterFilters(GlobalFilterCollection filters) { filters.Add(new HandleExceptionFileterAttribute()); } } }
控制器裡增加Home控制器
此時此刻公共錯誤頁面已經完成,我們可以測試,公共錯誤頁面是否有問題;
JS檔案
StaticContent-->scripts-->unobtrusive.js(內容如下)
layui.define(["jquery"], function (exports) { var jQuery = layui.jquery; (function ($) { var data_click = "unobtrusiveAjaxClick", data_target = "unobtrusiveAjaxClickTarget", data_validation = "unobtrusiveValidation"; function getFunction(code, argNames) { var fn = window, parts = (code || "").split("."); while (fn && parts.length) { fn = fn[parts.shift()]; } if (typeof (fn) === "function") { return fn; } argNames.push(code); return Function.constructor.apply(null, argNames); } function isMethodProxySafe(method) { return method === "GET" || method === "POST"; } function asyncOnBeforeSend(xhr, method) { if (!isMethodProxySafe(method)) { xhr.setRequestHeader("X-HTTP-Method-Override", method); } } function asyncOnSuccess(element, data, contentType) { var mode; if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us return; } mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase(); $(element.getAttribute("data-ajax-update")).each(function (i, update) { var top; switch (mode) { case "BEFORE": top = update.firstChild; $("<div />").html(data).contents().each(function () { update.insertBefore(this, top); }); break; case "AFTER": $("<div />").html(data).contents().each(function () { update.appendChild(this); }); break; case "REPLACE-WITH": $(update).replaceWith(data); break; default: $(update).html(data); break; } }); } function asyncRequest(element, options) { var confirm, loading, method, duration; confirm = element.getAttribute("data-ajax-confirm"); if (confirm && !window.confirm(confirm)) { return; } loading = $(element.getAttribute("data-ajax-loading")); duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0; $.extend(options, { type: element.getAttribute("data-ajax-method") || undefined, url: element.getAttribute("data-ajax-url") || undefined, cache: !!element.getAttribute("data-ajax-cache"), beforeSend: function (xhr) { var result; asyncOnBeforeSend(xhr, method); result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments); if (result !== false) { loading.show(duration); } return result; }, complete: function () { loading.hide(duration); getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments); }, success: function (data, status, xhr) { asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments); }, error: function () { getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments); } }); options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" }); method = options.type.toUpperCase(); if (!isMethodProxySafe(method)) { options.type = "POST"; options.data.push({ name: "X-HTTP-Method-Override", value: method }); } $.ajax(options); } function validate(form) { var validationInfo = $(form).data(data_validation); return !validationInfo || !validationInfo.validate || validationInfo.validate(); } $(document).on("click", "a[data-ajax=true]", function (evt) { evt.preventDefault(); asyncRequest(this, { url: this.href, type: "GET", data: [] }); }); $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) { var name = evt.target.name, target = $(evt.target), form = $(target.parents("form")[0]), offset = target.offset(); form.data(data_click, [ { name: name + ".x", value: Math.round(evt.pageX - offset.left) }, { name: name + ".y", value: Math.round(evt.pageY - offset.top) } ]); setTimeout(function () { form.removeData(data_click); }, 0); }); $(document).on("click", "form[data-ajax=true] :submit", function (evt) { var name = evt.currentTarget.name, target = $(evt.target), form = $(target.parents("form")[0]); form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []); form.data(data_target, target); setTimeout(function () { form.removeData(data_click); form.removeData(data_target); }, 0); }); $(document).on("submit", "form[data-ajax=true]", function (evt) { var clickInfo = $(this).data(data_click) || [], clickTarget = $(this).data(data_target), isCancel = clickTarget && clickTarget.hasClass("cancel"); evt.preventDefault(); if (!isCancel && !validate(this)) { return; } asyncRequest(this, { url: this.action, type: this.method || "GET", data: clickInfo.concat($(this).serializeArray()) }); }); }(jQuery)); exports('unobtrusive',null) });
StaticContent\image\user.png 圖片如下
二, 實現基於layui前臺頁面後臺管理的搭建
1, 新增區域
2, 在Shared-->_Layout.cshtml (新增)
3, Views-->_ViewStart.cshtml (新增)
_Layout.cshtml
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>後臺管理</title> <link href="~/StaticContent/layui/css/layui.css" rel="stylesheet" /> @RenderSection("styles",false) </head> <body> @RenderBody() <script src="~/StaticContent/layui/layui.js"></script> <script type="text/javascript"> </script> @RenderSection("scripts",false); </body> </html>
_ViewStart.cshtml
@{
Layout = "~/Areas/Manage/Views/Shared/_Layout.cshtml";
}
在增加的區域裡控制器增加Main控制器,並新增對應的檢視
檢視程式碼
<body class="layui-layout-body"> <div class="layui-layout-admin"> <!--頭部內容--> <div class="layui-header"> <div class="layui-logo">後臺管理</div> <ul class="layui-nav layui-layout-right"> <li class="layui-nav-item"> <a href="#"> <img src="~/StaticContent/image/user.png" class="layui-nav-img" /> Admin </a> <dl class="layui-nav-child"> <dd><a href="#">修改密碼</a></dd> <dd><a href="#">退出登入</a></dd> </dl> </li> </ul> </div> <!--側邊導航--> <div class="layui-side layui-bg-black"> <div class="layui-side-scroll"> <ul class="layui-nav layui-nav-tree"> <li class="layui-nav-item"> <a href="javascript:;"> <i class="layui-icon layui-icon-home">主頁</i> </a> </li> </ul> </div> </div> <!--主內容區--> <div class="layui-body" style="overflow:hidden"> <iframe src="https://www.baidu.com/" frameborder="0" style="height:100%;width:100%"></iframe> </div> <!--底部區域--> <div class="layui-footer"> ©1999-2020 個人開發 </div> </div> </body> @section Scripts { <script type="text/javascript"> layui.use('element') </script> }
執行測試,整個頁面已經搭建了7788,執行頁面如下
主頁面是用的度娘做的測試,下面我們建立Main頁面
Main頁面增加,測試OK的
到這裡我們已經整個框架已經搭建的差不多了,下面將實現具體功能的實現,
一, 實現登入功能
繼續完善中...............