最近学习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,运行页面如下
三,实现登入功能