一、博客系统进度回顾
目前已经完成了,前台展示,以及后台发布的功能,最近都在做这个,其实我在国庆的时候就可以弄完的,但是每天自己弄,突然最后国庆2天,连电脑都不想碰,所以就一直拖着,上一篇写了前端实现用到的一些WebUI框架以及一些系统中用到的js插件,其实写了这么久,还是第一次,有人留言,不要烂尾的,感觉还是有点点价值的,至少有人关注。
废话不多说,现在开始上代码。
二、博客系统后台布局实现
2.1.这里所用的是MVC的布局页来实现的,后台主要分为三部分:导航、菜单、主要内容
代码实现:
这里把后台单独放在一个区域里面,所以我这里建立一个admin的区域
在布局页_Layout.cshtml引入公共的一些css文件以及js文件
布局页代码_Layout.cshtml:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>@ViewBag.Title - 博客系统后台管理</title> 7 <link href="~/Content/CSS/zui.css" rel="stylesheet" /> 8 <link href="~/Content/CSS/zui-theme.css" rel="stylesheet" /> 9 <link href="//cdn.bootcss.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet"> 10 <link href="~/Content/lib/metisMenu/metisMenu.css" rel="stylesheet" /> 11 <link href="~/Content/CSS/index.css" rel="stylesheet" /> 12 @RenderSection("stylesheet", required: false) 13 <script src="~/Content/JS/jquery-1.12.4.min.js"></script> 14 <script src="~/Content/JS/zui.js"></script> 15 <script src="~/Content/lib/metisMenu/metisMenu.js"></script> 16 <script src="~/Content/JS/index.js"></script> 17 18 <!--[if lt IE 9]> 19 <script src="http://libs.useso.com/js/html5shiv/3.7/html5shiv.min.js"></script> 20 <script src="http://libs.useso.com/js/respond.js/1.4.2/respond.min.js"></script> 21 <script src="lib/ieonly/excanvas.js"></script> 22 <![endif]--> 23 24 </head> 25 <body> 26 <!--header--> 27 <header> 28 <div class="navbar navbar-inverse " role="navigation"> 29 <div class="navbar-header"> 30 <!--移动设备上的导航切换按钮--> 31 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-example"> 32 <span class="sr-only">切换导航</span> 33 <span class="icon-bar"></span> 34 <span class="icon-bar"></span> 35 <span class="icon-bar"></span> 36 </button> 37 <!--品牌名称或logo--> 38 <a class="navbar-brand">系统后台</a> 39 </div> 40 <div class="collapse navbar-collapse navbar-collapse-example"> 41 <ul class="nav navbar-nav navbar-right"> 42 <li><a><i class="icon icon-user"></i> 您好,admin</a></li> 43 <li><a><i class="icon icon-exchange"></i> 隐藏菜单</a></li> 44 <li><a href="/admin/Home"><i class="icon icon-home"></i> 首页</a></li> 45 <li><a><i class="icon icon-question-sign"></i> 帮助</a></li> 46 <li><a><i class="icon icon-off"></i> 退出</a></li> 47 </ul> 48 </div> 49 </div> 50 </header> 51 <!--header end--> 52 <!--content--> 53 <div class="clearfix"> 54 @Html.Partial("_sidebar") 55 <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 rightmain"> 56 <div class="col-sm-12 col-md-12 rightcontent"> 57 @RenderBody() 58 </div> 59 </div> 60 </div> 61 <!--content end--> 62 <!--footer--> 63 <footer class="col-md-12 footer footerstyle"> 64 <p>© @DateTime.Now.Year - 我的博客系统</p> 65 </footer> 66 <!--footer end--> 67 68 <script src="~/Scripts/jquery.validate.js"></script> 69 <script src="~/Scripts/jquery.validate.unobtrusive.js"></script> 70 <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script> 71 @RenderSection("scripts", required: false) 72 </body> 73 </html>
菜单部分页_sidebar.cshtml代码
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 @{ 2 string url = Request.Url.ToString().ToLower(); 3 } 4 @if (url.Contains("home")) 5 { 6 <aside class="col-sm-3 col-md-2 sidebar"> 7 <nav class="sidebar-nav"> 8 <ul class="metismenu" id="menu"> 9 <li class="active"> 10 <a href="#" aria-expanded="true"> 11 <i class="icon icon-github"></i> 12 系统统计<i class="fa arrow fa-fw"></i> 13 </a> 14 <ul aria-expanded="true"> 15 <li> 16 <a href="/admin/statistics/visitor"> 17 <i class="icon icon-list"></i> 18 访问统计 19 </a> 20 </li> 21 <li> 22 <a href="/admin/statistics/usesr"> 23 <i class="icon icon-github"></i> 24 用户统计 25 </a> 26 </li> 27 </ul> 28 </li> 29 <li> 30 <a href="#" aria-expanded="false">博客管理<i class="fa arrow fa-fw"></i></a> 31 <ul aria-expanded="false"> 32 <li><a href="/admin/BlogArticle/Index">博客列表</a></li> 33 <li><a href="/admin/BlogArticle/Add">发布博客</a></li> 34 </ul> 35 </li> 36 <li> 37 <a href="#" aria-expanded="false">广告管理<i class="fa arrow fa-fw"></i></a> 38 <ul aria-expanded="false"> 39 <li><a href="@Url.Action("index", "Advertisement")">轮播图管理</a></li> 40 </ul> 41 </li> 42 <li> 43 <a href="#" aria-expanded="false">用户管理<i class="fa arrow fa-fw"></i></a> 44 <ul aria-expanded="false"> 45 <li><a href="#">修改信息</a></li> 46 <li><a href="#">修改密码</a></li> 47 <li> 48 <a href="#" aria-expanded="false">用户信息管理<span class="fa plus-times"></span></a> 49 <ul aria-expanded="false"> 50 <li><a href="#">修改信息</a></li> 51 <li><a href="#">修改密码</a></li> 52 </ul> 53 </li> 54 </ul> 55 </li> 56 <li> 57 <a href="#" aria-expanded="false">权限管理<i class="fa arrow fa-fw"></i></a> 58 <ul aria-expanded="false"> 59 <li><a href="#">用户授权</a></li> 60 <li><a href="#">用户组管理</a></li> 61 <li><a href="#">用户组授权</a></li> 62 </ul> 63 </li> 64 <li> 65 <a href="#" aria-expanded="false">日志管理<i class="fa arrow fa-fw"></i></a> 66 <ul aria-expanded="false"> 67 <li><a href="#">用户日志</a></li> 68 <li><a href="#">系统日志</a></li> 69 </ul> 70 </li> 71 </ul> 72 </nav> 73 </aside> 74 } 75 else if (url.Contains("blogarticle")) 76 { 77 <aside class="col-sm-3 col-md-2 sidebar"> 78 <nav class="sidebar-nav"> 79 <ul class="metismenu" id="menu"> 80 <li> 81 <a href="#" aria-expanded="true"> 82 <i class="icon icon-github"></i> 83 系统统计<i class="fa arrow fa-fw"></i> 84 </a> 85 <ul aria-expanded="true"> 86 <li> 87 <a href="/admin/statistics/visitor"> 88 <i class="icon icon-list"></i> 89 访问统计 90 </a> 91 </li> 92 <li> 93 <a href="/admin/statistics/usesr"> 94 <i class="icon icon-github"></i> 95 用户统计 96 </a> 97 </li> 98 </ul> 99 </li> 100 <li class="active"> 101 <a href="#" aria-expanded="false">博客管理<i class="fa arrow fa-fw"></i></a> 102 <ul aria-expanded="false"> 103 <li><a href="/admin/BlogArticle/Index">博客列表</a></li> 104 <li><a href="/admin/BlogArticle/Add">发布博客</a></li> 105 </ul> 106 </li> 107 <li> 108 <a href="#" aria-expanded="false">广告管理<i class="fa arrow fa-fw"></i></a> 109 <ul aria-expanded="false"> 110 <li><a href="@Url.Action("index", "Advertisement")">轮播图管理</a></li> 111 </ul> 112 </li> 113 <li> 114 <a href="#" aria-expanded="false">用户管理<i class="fa arrow fa-fw"></i></a> 115 <ul aria-expanded="false"> 116 <li><a href="#">修改信息</a></li> 117 <li><a href="#">修改密码</a></li> 118 <li> 119 <a href="#" aria-expanded="false">用户信息管理<span class="fa plus-times"></span></a> 120 <ul aria-expanded="false"> 121 <li><a href="#">修改信息</a></li> 122 <li><a href="#">修改密码</a></li> 123 </ul> 124 </li> 125 </ul> 126 </li> 127 <li> 128 <a href="#" aria-expanded="false">权限管理<i class="fa arrow fa-fw"></i></a> 129 <ul aria-expanded="false"> 130 <li><a href="#">用户授权</a></li> 131 <li><a href="#">用户组管理</a></li> 132 <li><a href="#">用户组授权</a></li> 133 </ul> 134 </li> 135 <li> 136 <a href="#" aria-expanded="false">日志管理<i class="fa arrow fa-fw"></i></a> 137 <ul aria-expanded="false"> 138 <li><a href="#">用户日志</a></li> 139 <li><a href="#">系统日志</a></li> 140 </ul> 141 </li> 142 </ul> 143 </nav> 144 </aside> 145 } 146 else if (url.Contains("advertisement")) 147 { 148 <aside class="col-sm-3 col-md-2 sidebar"> 149 <nav class="sidebar-nav"> 150 <ul class="metismenu" id="menu"> 151 <li> 152 <a href="#" aria-expanded="true"> 153 <i class="icon icon-github"></i> 154 系统统计<i class="fa arrow fa-fw"></i> 155 </a> 156 <ul aria-expanded="true"> 157 <li> 158 <a href="/admin/statistics/visitor"> 159 <i class="icon icon-list"></i> 160 访问统计 161 </a> 162 </li> 163 <li> 164 <a href="/admin/statistics/usesr"> 165 <i class="icon icon-github"></i> 166 用户统计 167 </a> 168 </li> 169 </ul> 170 </li> 171 <li > 172 <a href="#" aria-expanded="false">博客管理<i class="fa arrow fa-fw"></i></a> 173 <ul aria-expanded="false"> 174 <li><a href="/admin/BlogArticle/Index">博客列表</a></li> 175 <li><a href="/admin/BlogArticle/Add">发布博客</a></li> 176 </ul> 177 </li> 178 <li class="active"> 179 <a href="#" aria-expanded="false">广告管理<i class="fa arrow fa-fw"></i></a> 180 <ul aria-expanded="false"> 181 <li><a href="@Url.Action("index", "Advertisement")">轮播图管理</a></li> 182 </ul> 183 </li> 184 <li> 185 <a href="#" aria-expanded="false">用户管理<i class="fa arrow fa-fw"></i></a> 186 <ul aria-expanded="false"> 187 <li><a href="#">修改信息</a></li> 188 <li><a href="#">修改密码</a></li> 189 <li> 190 <a href="#" aria-expanded="false">用户信息管理<span class="fa plus-times"></span></a> 191 <ul aria-expanded="false"> 192 <li><a href="#">修改信息</a></li> 193 <li><a href="#">修改密码</a></li> 194 </ul> 195 </li> 196 </ul> 197 </li> 198 <li> 199 <a href="#" aria-expanded="false">权限管理<i class="fa arrow fa-fw"></i></a> 200 <ul aria-expanded="false"> 201 <li><a href="#">用户授权</a></li> 202 <li><a href="#">用户组管理</a></li> 203 <li><a href="#">用户组授权</a></li> 204 </ul> 205 </li> 206 <li> 207 <a href="#" aria-expanded="false">日志管理<i class="fa arrow fa-fw"></i></a> 208 <ul aria-expanded="false"> 209 <li><a href="#">用户日志</a></li> 210 <li><a href="#">系统日志</a></li> 211 </ul> 212 </li> 213 </ul> 214 </nav> 215 </aside> 216 }
其实我这个菜单选中的效果做的很垃圾,我自己都觉得不要,但是目前我也只能想到这个方法,因为每次加载一个嵌套的页面就会从新去加载一次布局页_Layout.cshtml的内容,我这个菜单是有一个active选中的样式的,这个是菜单插件里面已经写好了,这里遇到的问题就是每次刷新都会把页面选中效果设置到默认的菜单上,假如点击了发布博客菜单应该显示博客管理这个菜单内容,但是从新加载的时候就会回到默认的系统统计菜单上,所以这里就用地址路径来判断应该显示那个菜单,方法真的很笨,见谅,各位。
2.2博客信息添加功能实现
在model层的Models文件创建一个BlogArticle类,然后在创建一个文件VeiwModels,Models文件夹里面的类是用来生成数据库对应的表,而VeiwModels文件夹里面对应的类是用来在view视图页面展示数据用的,当你一个表字段很多不需要所有数据都展示,或者要做一些处理计算的类,这样就需要一个VeiwModels类来分离。
BlogArticle类:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 namespace Wchl.WMBlog.Model.Models 2 { 3 /// <summary>博客文章 4 /// 5 /// </summary 6 public class BlogArticle 7 { 8 /// <summary> 9 /// 10 /// </summary> 11 public int bID { get; set; } 12 /// <summary>创建人 13 /// 14 /// </summary> 15 public string bsubmitter { get; set; } 16 17 /// <summary>博客标题 18 /// 19 /// </summary> 20 public string btitle { get; set; } 21 22 /// <summary>类别 23 /// 24 /// </summary> 25 public string bcategory { get; set; } 26 27 /// <summary>内容 28 /// 29 /// </summary> 30 public string bcontent { get; set; } 31 32 /// <summary> 33 /// 访问量 34 /// </summary> 35 public int btraffic { get; set; } 36 37 /// <summary> 38 /// 评论数量 39 /// </summary> 40 public int bcommentNum { get; set; } 41 42 /// <summary> 修改时间 43 /// 44 /// </summary> 45 public DateTime bUpdateTime { get; set; } 46 47 /// <summary> 48 /// 创建时间 49 /// </summary> 50 public System.DateTime bCreateTime { get; set; } 51 /// <summary>备注 52 /// 53 /// </summary> 54 public string bRemark { get; set; } 55 } 56 }
BlogViewModels类:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 namespace Wchl.WMBlog.Model.VeiwModels 2 { 3 /// <summary> 4 /// 博客信息展示类 5 /// </summary> 6 public class BlogViewModels 7 { 8 /// <summary> 9 /// 10 /// </summary> 11 public int bID { get; set; } 12 /// <summary>创建人 13 /// 14 /// </summary> 15 public string bsubmitter { get; set; } 16 17 /// <summary>博客标题 18 /// 19 /// </summary> 20 public string btitle { get; set; } 21 22 /// <summary>摘要 23 /// 24 /// </summary> 25 public string digest { get; set; } 26 27 /// <summary> 28 /// 上一篇 29 /// </summary> 30 public string previous { get; set; } 31 32 /// <summary> 33 /// 上一篇id 34 /// </summary> 35 public int previousID { get; set; } 36 37 /// <summary> 38 /// 下一篇 39 /// </summary> 40 public string next { get; set; } 41 42 /// <summary> 43 /// 下一篇id 44 /// </summary> 45 public int nextID { get; set; } 46 47 /// <summary>类别 48 /// 49 /// </summary> 50 public string bcategory { get; set; } 51 52 /// <summary>内容 53 /// 54 /// </summary> 55 public string bcontent { get; set; } 56 57 /// <summary> 58 /// 访问量 59 /// </summary> 60 public int btraffic { get; set; } 61 62 /// <summary> 63 /// 评论数量 64 /// </summary> 65 public int bcommentNum { get; set; } 66 67 /// <summary> 修改时间 68 /// 69 /// </summary> 70 public DateTime bUpdateTime { get; set; } 71 72 /// <summary> 73 /// 创建时间 74 /// </summary> 75 public System.DateTime bCreateTime { get; set; } 76 /// <summary>备注 77 /// 78 /// </summary> 79 public string bRemark { get; set; } 80 } 81 }
在maps文件夹中添加相应的约束
BlogArticleMap类:
:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 namespace Wchl.WMBlog.Model.Maps 2 { 3 public class BlogArticleMap: EntityTypeConfiguration<BlogArticle> 4 { 5 public BlogArticleMap() 6 { 7 this.HasKey(p => p.bID); 8 this.Property(p => p.btitle).HasMaxLength(256); 9 this.Property(p => p.bsubmitter).HasMaxLength(60); 10 this.Property(p => p.bcontent).HasColumnType("Text").IsMaxLength(); 11 } 12 } 13 }
然后在控制台使用更新数据库命令:update database -force,一定要选择model层
创建好了表,然后就是在仓储层以及业务层创建相应的接口和实现类
IBlogArticleRepository类:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 namespace Wchl.WMBlog.IRepository 2 { 3 public interface IBlogArticleRepository:IBaseRepository<BlogArticle> 4 { 5 } 6 } 7
BlogArticleRepository类:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 namespace Wchl.WMBlog.Repository 2 { 3 public class BlogArticleRepository: BaseRepository<BlogArticle>, IBlogArticleRepository 4 { 5 } 6 }
IBlogArticleServices类:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 namespace Wchl.WMBlog.IServices 2 { 3 public interface IBlogArticleServices: IBaseServices<BlogArticle> 4 { 5 /// <summary> 6 /// 获取视图博客详情信息 7 /// </summary> 8 /// <param name="id"></param> 9 /// <returns></returns> 10 BlogViewModels getBlogDetails(int id); 11 } 12 }
BlogArticleServices类:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 namespace Wchl.WMBlog.Services 2 { 3 public class BlogArticleServices: BaseServices<BlogArticle>, IBlogArticleServices 4 { 5 IBlogArticleRepository dal; 6 7 public BlogArticleServices(IBlogArticleRepository dal) 8 { 9 this.dal = dal; 10 base.baseDal = dal; 11 } 12 13 /// <summary> 14 /// 获取视图博客详情信息 15 /// </summary> 16 /// <param name="id"></param> 17 /// <returns></returns> 18 public BlogViewModels getBlogDetails(int id) 19 { 20 BlogArticle blogArticle = dal.QueryWhere(a => a.bID == id).FirstOrDefault(); 21 BlogArticle nextblog= dal.QueryWhere(a => a.bID == id-1).FirstOrDefault(); 22 BlogArticle prevblog = dal.QueryWhere(a => a.bID == id+1).FirstOrDefault(); 23 blogArticle.btraffic += 1; 24 dal.Edit(blogArticle, new string[] { "btraffic" }); 25 dal.SaverChanges(); 26 //AutoMapper自动映射 27 Mapper.Initialize(cfg => cfg.CreateMap<BlogArticle, BlogViewModels>()); 28 BlogViewModels models = Mapper.Map<BlogArticle, BlogViewModels>(blogArticle); 29 if (nextblog!=null) 30 { 31 models.next = nextblog.btitle; 32 models.nextID = nextblog.bID; 33 } 34 35 if (prevblog != null) 36 { 37 models.previous = prevblog.btitle; 38 models.previousID = prevblog.bID; 39 } 40 models.digest = Tools.ReplaceHtmlTag(blogArticle.bcontent).Length > 100 ? Tools.ReplaceHtmlTag(blogArticle.bcontent).Substring(0, 200) : Tools.ReplaceHtmlTag(blogArticle.bcontent); 41 return models; 42 43 } 44 45 46 } 47 }
2.3博客添加页面实现功能
在区域admin的控制器下创建一个add方法用来展示页面。
add方法
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 public ActionResult Add() 2 { 3 return View(); 4 }
然后View添加视图选择使用布局页
布局页代码
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 2 @{ 3 ViewBag.Title = "添加博客"; 4 } 5 6 <link href="~/Content/CSS/animate.css" rel="stylesheet" /> 7 <link href="~/Content/lib/wangEditor/dist/css/wangEditor.css" rel="stylesheet" /> 8 <link href="~/Content/CSS/blogArticleStyle.css" rel="stylesheet" /> 9 <script src="~/Content/lib/wangEditor/dist/js/wangEditor.js"></script> 10 <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script> 11 <script type="text/javascript"> 12 $(function () { 13 // 获取元素 14 var textarea = document.getElementById('bcontent'); 15 // 生成编辑器 16 var editor = new wangEditor(textarea); 17 // 自定义菜单 18 editor.config.menus = [ 19 'source', 20 '|', 21 'bold', 22 'underline', 23 'italic', 24 'eraser', 25 'forecolor', 26 'bgcolor', 27 '|', 28 'quote', 29 'fontfamily', 30 'fontsize', 31 'head', 32 'unorderlist', 33 'orderlist', 34 'alignleft', 35 'aligncenter', 36 'alignright', 37 '|', 38 'link', 39 'unlink', 40 'emotion', 41 '|', 42 'img', 43 'insertcode', 44 '|', 45 'undo', 46 'redo', 47 'fullscreen' 48 ]; 49 // 上传图片(举例) 50 editor.config.uploadImgUrl = '/admin/BlogArticle/upload'; 51 editor.config.uploadImgFileName = 'imgFile' 52 editor.create(); 53 }); 54 //添加博文之后 55 function afterAddBlog(data) { 56 var serverData = data.split(':'); 57 if (serverData[0] == "ok") 58 { 59 alert(serverData[1]); 60 window.location.reload(); 61 } 62 }; 63 </script> 64 <div class="blogcontent"> 65 <!-- head star --> 66 <div class="tnav row border-bottom white-bg page-heading"> 67 <div class="col-sm-4"> 68 <h2 class="fl">博客后台</h2> 69 <ol class="breadcrumb fl"> 70 <li><a href="/admin/Home">博客管理</a></li> 71 <li><strong>发布博客</strong></li> 72 </ol> 73 </div> 74 </div> 75 <!-- head end --> 76 <!-- form star --> 77 <div class=""> 78 <div class="wrapper wrapper-content animated fadeInUp" style="height:600px;padding-bottom:30px;overflow:auto"> 79 @using (Ajax.BeginForm("Add", "BlogArticle", new { }, new AjaxOptions() { HttpMethod = "post", OnSuccess = "afterAddBlog" }, new { @class = "form-horizontal" })) 80 { 81 <div class="form-group"> 82 <label class="col-md-1 control-label">标题 :</label> 83 <div class="col-md-11"> 84 <input type='text' name='btitle' id='title' value='' class='form-control' placeholder='' /> 85 </div> 86 </div> 87 <div class="form-group"> 88 <label class="col-md-1 control-label">类别 :</label> 89 <div class='col-md-2'> 90 <select name='bcategory' id='original' class='form-control'> 91 <option value='技术博文' selected='selected'>技术博文</option> 92 <option value='随笔日志'>随笔日志</option> 93 </select> 94 </div> 95 </div> 96 <div class="form-group"> 97 <label class="col-md-1 control-label">内容 :</label> 98 <div class='col-md-11'> 99 <textarea id="bcontent" rows="18" name="bcontent" class='form-control'> 100 <p>请输入内容...</p> 101 </textarea> 102 </div> 103 </div> 104 <div class="form-group"> 105 <div class="col-md-offset-1 col-md-10"> 106 <input type='submit' id='submit' class='btn btn-info' value='保存' data-loading='稍候...' /> 107 </div> 108 </div> 109 110 } 111 </div> 112 </div> 113 <!-- form end --> 114 </div> 115 116 117 118
效果图
在控制器中添加一个上传图片的方法,用于富文本编辑器上传图片
upload方法
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 //图片上传 2 public ActionResult upload() 3 { 4 //文件保存目录路径 5 String savePath = "/upload/"; 6 7 //定义允许上传的文件扩展名 8 Hashtable extTable = new Hashtable(); 9 extTable.Add("image", "gif,jpg,jpeg,png,bmp"); 10 extTable.Add("flash", "swf,flv"); 11 extTable.Add("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb"); 12 extTable.Add("file", "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2"); 13 14 //最大文件大小 15 int maxSize = 1000000; 16 17 HttpPostedFileBase imgFile = Request.Files["imgFile"]; 18 if (imgFile == null) 19 { 20 return Content("error|请选择文件。"); 21 } 22 23 String dirPath = Server.MapPath(savePath); 24 if (!Directory.Exists(dirPath)) 25 { 26 return Content("error|上传目录不存在。"); 27 } 28 29 String dirName = Request.QueryString["dir"]; 30 if (String.IsNullOrEmpty(dirName)) 31 { 32 dirName = "image"; 33 } 34 if (!extTable.ContainsKey(dirName)) 35 { 36 return Content("error|目录名不正确。"); 37 } 38 39 String fileName = imgFile.FileName; 40 String fileExt = Path.GetExtension(fileName).ToLower(); 41 42 if (imgFile.InputStream == null || imgFile.InputStream.Length > maxSize) 43 { 44 return Content("error|上传文件大小超过限制。"); 45 } 46 47 if (String.IsNullOrEmpty(fileExt) || Array.IndexOf(((String)extTable[dirName]).Split(','), fileExt.Substring(1).ToLower()) == -1) 48 { 49 return Content("error|上传文件扩展名是不允许的扩展名。\n只允许" + ((String)extTable[dirName]) + "格式。"); 50 } 51 52 //创建文件夹 53 dirPath += dirName + "/"; 54 if (!Directory.Exists(dirPath)) 55 { 56 Directory.CreateDirectory(dirPath); 57 } 58 String ymd = DateTime.Now.ToString("yyyyMMdd", DateTimeFormatInfo.InvariantInfo); 59 dirPath += ymd + "/"; 60 if (!Directory.Exists(dirPath)) 61 { 62 Directory.CreateDirectory(dirPath); 63 } 64 65 String newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", DateTimeFormatInfo.InvariantInfo) + fileExt; 66 String filePath = dirPath + newFileName; 67 68 imgFile.SaveAs(filePath); 69 70 String fileUrl = savePath + "image/" + ymd + "/" + newFileName; 71 return Content(fileUrl); 72 }
调用的位置:
提交博客使用的是异步提交
在博客控制器添加一个add方法用来添加数据
add方法
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 //新增博文 2 [HttpPost] 3 [ValidateInput(false)] 4 public ActionResult Add(BlogArticle blogArticle) 5 { 6 blogArticle.bCreateTime = DateTime.Now; 7 blogArticle.bsubmitter = "admin"; 8 blogArticle.bUpdateTime = DateTime.Now; 9 blogArticle.bRemark = string.Empty; 10 BlogArticleServive.Add(blogArticle); 11 BlogArticleServive.SaverChanges(); 12 return Content("ok:添加成功!"); 13 }
记住在使用之前需要把接口和对应的方法实现在构造方法中调用
三、博客系统前台布局实现
3.1接下来就改前台展示部分,同样使用的是布局页
设计页面如下:
前台布局页_Layout.cshtml代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 5 <meta charset="utf-8" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <link href="~/Content/CSS/zui.css" rel="stylesheet" /> 8 @*<link href="~/Content/CSS/zui-blog-theme.css" rel="stylesheet" />*@ 9 <link href="~/Content/CSS/zui-theme-blue.css" rel="stylesheet" /> 10 <link href="~/Content/CSS/HomeIndex.css" rel="stylesheet" /> 11 <link href="~/Content/CSS/pagerstyles.css" rel="stylesheet" /> 12 <title>@ViewBag.Title - WMBlog博客</title> 13 14 15 </head> 16 <body> 17 <!--导航部分--> 18 @Html.Partial("_NavbarPage") 19 <!--主体内容--> 20 <div class="main"> 21 <div class="row"> 22 <!--左边主要内容--> 23 @*<article style="margin-top: 10px;"> 24 <div class="col-md-8" id="leftmain"> 25 @RenderBody() 26 </div> 27 </article>*@ 28 <!--左边主要内容--> 29 <!--右边栏--> 30 <!--主题部分--> 31 @{ 32 if (ViewBag.controllername != "statistical") 33 { 34 <article style="margin-top: 10px;"> 35 <div class="col-md-8" id="leftmain"> 36 @RenderBody() 37 </div> 38 </article> 39 @Html.Partial("_RightPage") 40 } 41 else 42 { 43 @RenderBody() 44 } 45 46 } 47 48 <!--右边栏--> 49 </div> 50 </div> 51 <!--主题部分--> 52 <!--底部版权部分--> 53 @Html.Partial("_FooterPage") 54 55 <script src="~/Content/JS/jquery-1.12.4.min.js"></script> 56 <script src="~/Content/JS/zui.js"></script> 57 <script src="~/Scripts/jquery.validate.js"></script> 58 <script src="~/Scripts/jquery.validate.unobtrusive.js"></script> 59 <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script> 60 <script type="text/javascript"> 61 $(function () { 62 //用于控制导航样式 63 var name = '@ViewBag.controllername' 64 $('#' + name).attr("class", "active") 65 }) 66 </script> 67 @RenderSection("scripts", false) 68 </body> 69 </html> 70
部分布局页导航部分_NavbarPage
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 <!--导航--> 2 <nav class="navbar navbar-default navbar-fixed-top"> 3 <div class="container"> 4 <!--小屏幕导航按钮和logo--> 5 <div class="navbar-header"> 6 <button class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> 7 <span class="icon-bar"></span> 8 <span class="icon-bar"></span> 9 <span class="icon-bar"></span> 10 </button> 11 <a href="index.html" class="navbar-brand">WM Blog</a> 12 </div> 13 <!--小屏幕导航按钮和logo--> 14 <!--导航--> 15 <div class="navbar-collapse collapse"> 16 <ul class="nav navbar-nav"> 17 <li id="home"><a href="/home/index" id="index"><i class="icon icon-home"></i> 首页</a></li> 18 <li id="blog"><a href="/blog/index" id="content"><i class="icon icon-list-alt"></i> 博文</a></li> 19 <li><a href="/movie/index"><i class="icon icon-film"></i> 随笔</a></li> 20 <li><a href="/statistical/index"><i class="icon icon-bar-chart"></i> 访问</a></li> 21 <li><a href="/about/index"><span class="icon icon-tags"></span> 关于</a></li> 22 </ul> 23 <form class="navbar-form navbar-right" role="search"> 24 <div class="form-group"> 25 <input type="text" class="form-control" placeholder="搜索"> 26 </div> 27 <button type="submit" class="btn btn-primary"><i class="icon icon-search"></i> 搜索</button> 28 </form> 29 </div> 30 <!--导航--> 31 32 </div> 33 </nav> 34 <!--导航--> 35 36
部分布局页右侧统计部分_RightPage
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 <!--右边栏部分--> 2 <aside> 3 <div class="col-md-4"> 4 <section class="youbianlan"> 5 <div class="panel-group"> 6 <div class="panel"> 7 <div class="panel-heading"> 8 <div class="panel-title panel-info"> 9 <h4>最新发布</h4> 10 </div> 11 </div> 12 <div class="panel-body"> 13 <ul> 14 @{ 15 if (ViewBag.blogtimelist != null) 16 { 17 for (int i = 0; i < 10; i++) 18 { 19 <li><a href="/blog/Detail/@ViewBag.blogtimelist[i].bID">@ViewBag.blogtimelist[i].btitle</a></li> 20 } 21 } 22 23 } 24 </ul> 25 </div> 26 </div> 27 </div> 28 </section> 29 <section class="youbianlan"> 30 <div class="panel-group"> 31 <div class="panel"> 32 <div class="panel-heading"> 33 <div class="panel-title panel-info"> 34 <h4>阅读排行榜</h4> 35 </div> 36 </div> 37 <div class="panel-body"> 38 <ul> 39 @{ 40 if (ViewBag.blogtrafficlist != null) 41 { 42 for (int i = 0; i < 10; i++) 43 { 44 <li><a href="/blog/Detail/@ViewBag.blogtrafficlist[i].bID">@ViewBag.blogtrafficlist[i].btitle</a></li> 45 } 46 } 47 48 } 49 </ul> 50 </div> 51 </div> 52 </div> 53 </section> 54 <section class="youbianlan"> 55 <div class="panel-group"> 56 <div class="panel"> 57 <div class="panel-heading"> 58 <div class="panel-title panel-info"> 59 <h4>评论排行榜</h4> 60 </div> 61 </div> 62 <div class="panel-body"> 63 <ul> 64 @{ 65 List<TopgbViewModels> list = ViewBag.blogguestbooklist as List<TopgbViewModels>; 66 if (list != null && list.Any()) 67 { 68 if (list.Count < 10) 69 { 70 for (int i = 0; i < list.Count; i++) 71 { 72 <li><a href="/blog/Detail/@list[i].blogId">@list[i].btitle</a></li> 73 } 74 } 75 else 76 { 77 for (int i = 0; i < 10; i++) 78 { 79 <li><a href="/blog/Detail/@list[i].blogId">@list[i].btitle</a></li> 80 } 81 } 82 83 } 84 85 } 86 </ul> 87 </div> 88 </div> 89 </div> 90 </section> 91 </div> 92 </aside> 93 <!--右边栏部分结束--> 94 95
部分布局页底部版权部分_FooterPage
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 <!--页脚部分--> 2 <div id="footer_wrapper" class="col-md-12"> 3 <footer> 4 <ul> 5 <li><a href="content.html">版权信息</a></li> 6 <li><a href="content.html">站点地图</a></li> 7 <li><a href="content.html">联系我们</a></li> 8 </ul> 9 <p>Copyright ©2016 WMBlog</p> 10 </footer> 11 </div> 12 <!--页脚部分结束--> 13
3.2实现主页面展示
在控制器下的文件夹中创建一个home控制器,然后创建一个index视图页面
index视图页代码
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 @model PagedList<Wchl.WMBlog.Model.Models.BlogArticle> 2 @using Webdiyer.WebControls.Mvc 3 @{ 4 ViewBag.Title = "首页"; 5 } 6 7 <section id="lunbotu"> 8 <div id="myNiceCarousel" class="carousel slide" data-ride="carousel"> 9 <!-- 圆点指示器 --> 10 <ol class="carousel-indicators"> 11 <li data-target="#myNiceCarousel" data-slide-to="0" class="active"></li> 12 <li data-target="#myNiceCarousel" data-slide-to="1"></li> 13 <li data-target="#myNiceCarousel" data-slide-to="2"></li> 14 </ol> 15 16 <!-- 轮播项目 --> 17 <div class="carousel-inner"> 18 @foreach (var item in ViewBag.adList) 19 { 20 if (item == ViewBag.adList[0]) 21 { 22 <div class="item active"> 23 <a href="@item.Url" title="@item.Title" target="_blank"> 24 <img alt="First slide" src="@item.ImgUrl"> 25 </a> 26 <div class="carousel-caption"> 27 <h3>@item.Title</h3> 28 </div> 29 </div> 30 } 31 else 32 { 33 <div class="item"> 34 <a href="@item.Url" title="@item.Title" target="_blank"> 35 <img alt="Second slide" src="@item.ImgUrl"> 36 </a> 37 38 <div class="carousel-caption"> 39 <h3>@item.Title</h3> 40 </div> 41 </div> 42 } 43 } 44 @*<div class="item active"> 45 <a href="http://www.baidu.com" title="baidu" target="_blank"> 46 <img alt="First slide" src="/upload/20161006/1.jpg"> 47 </a> 48 <div class="carousel-caption"> 49 <h3>我是第一张幻灯片</h3> 50 </div> 51 </div> 52 <div class="item"> 53 <img alt="Second slide" src="/upload/20161006/2.jpg"> 54 <div class="carousel-caption"> 55 <h3>我是第二张幻灯片</h3> 56 </div> 57 </div> 58 <div class="item"> 59 <img alt="Third slide" src="/upload/20161006/3.jpg"> 60 <div class="carousel-caption"> 61 <h3>我是第三张幻灯片</h3> 62 </div> 63 </div>*@ 64 </div> 65 66 <!-- 项目切换按钮 --> 67 <a class="left carousel-control" href="#myNiceCarousel" data-slide="prev"> 68 <span class="icon icon-chevron-left"></span> 69 </a> 70 <a class="right carousel-control" href="#myNiceCarousel" data-slide="next"> 71 <span class="icon icon-chevron-right"></span> 72 </a> 73 </div> 74 </section> 75 <section id="boke"> 76 @foreach (var item in Model) 77 { 78 <div class="day"> 79 <div class="dayTitle"> 80 <a class="btn btn-primary">@item.bCreateTime.ToString("yyyy年MM月dd日")</a> 81 </div> 82 <div class="postTitle"> 83 <a id="1" class="postTitle2" href="/blog/Detail/@item.bID">@item.btitle</a> 84 </div> 85 <div class="postCon"> 86 <div class="c_b_p_desc"> 87 摘要:@item.bcontent...... 88 <a href="/blog/Detail/@item.bID" class="btn btn-primary">阅读全文</a> 89 </div> 90 </div> 91 <div class="postDesc"> 92 <p>posted @@ @item.bCreateTime @item.bsubmitter 阅读(@item.btraffic) 评论(@item.bcommentNum) </p> 93 </div> 94 </div> 95 } 96 97 <footer class="pagination"> 98 @Ajax.Pager(Model, new PagerOptions { PageIndexParameterName = "pageindex", ContainerTagName = "ul", CssClass = "pager", CurrentPagerItemTemplate = "<li class=\"active\"><a href=\"#\">{0}</a></li>", DisabledPagerItemTemplate = "<li class=\"disabled\"><a>{0}</a></li>", PagerItemTemplate = "<li>{0}</li>" }, new MvcAjaxOptions { UpdateTargetId = "boke", OnBegin = "alert('onbegin事件引发')", OnSuccess = "handleSuccess", OnComplete = "function(xhr,status){alert('oncomplete事件引发,Http响应代码:'+xhr.status+',响应内容:'+xhr.statusText+',状态代码:'+status)}", OnFailure = "handleFailure" }) 99 @*@Html.Pager(Model, new PagerOptions { PageIndexParameterName = "pageindex", ContainerTagName = "ul", CssClass = "pager", CurrentPagerItemTemplate = "<li class=\"active\"><a href=\"#\">{0}</a></li>", DisabledPagerItemTemplate = "<li class=\"disabled\"><a>{0}</a></li>", PagerItemTemplate = "<li>{0}</li>" })*@ 100 @*@Html.Pager(Model, new PagerOptions { PageIndexParameterName = "pageindex", CurrentPagerItemTemplate = "<span class=\"current\">{0}</span>", DisabledPagerItemTemplate = "<span class=\"disabled\">{0}</span>", Id = "badoopager" })*@ 101 </footer> 102 </section> 103 104 105 106
然后在控制器index下实现查询博客信息代码
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 public ActionResult Index(int pageindex = 1) 2 { 3 //获取控制器名称 4 ViewBag.controllername = RouteData.Values["controller"].ToString().ToLower(); 5 6 int pagesize = 6; 7 //获取发布博文信息 8 var blogArticleList = BlogArticleServive.QueryWhere(a => true).OrderByDescending(a => a.bCreateTime).ToPagedList(pageindex, pagesize); 9 foreach (var item in blogArticleList) 10 { 11 if (!string.IsNullOrEmpty(item.bcontent)) 12 { 13 item.bcontent = Tools.ReplaceHtmlTag(item.bcontent); 14 if (item.bcontent.Length > 200) 15 { 16 item.bcontent = item.bcontent.Substring(0, 200); 17 } 18 } 19 20 } 21 //获取轮播广告新 22 ViewBag.adList = AdvertisementServices.QueryOrderBy(a => true, a => a.Createdate, false).ToPagedList(1, 3); 23 //发布时间排序 24 ViewBag.blogtimelist = BlogArticleServive.QueryOrderBy(c => true, c => c.bCreateTime, false); 25 //评论排序 26 ViewBag.blogtrafficlist = BlogArticleServive.QueryOrderBy(c => true, c => c.btraffic, false); 27 //留言排序 28 string sql = @"select a.*,b.btitle from (select blogId,count(1) as counts from Guestbook group by blogId) as a 29 inner join BlogArticle as b 30 on 31 b.bID=a.blogId order by counts desc"; 32 33 ViewBag.blogguestbooklist = GuestbookServices.RunProc<TopgbViewModels>(sql); 34 35 36 return View(blogArticleList); 37 }
效果展示:
四、博客系统发布博客功能以及展示功能总结
这里使用到了的两个插件一个是后台的富文本编辑器;一个是mvc分页插件,具体插件可以去相应的官网查看详细的使用方法,富文本编辑器官网:http://www.wangeditor.com/;mvc分页插件官网:http://www.webdiyer.com/mvcpager/
主要的分布实现是使用到了mvc布局页来实现的,实现页面功能的时候,一般都是先把静态页面做出来,然后在把前台页面移至到项目中,把需要展示数据的地方修改成动态的就可以了。
这里在说明一下我的文件夹设计我在Content文件夹下创建了CSS、fonts、images、JS、lib文件夹,把所有自定和用到的主要UI框架文件分类放在对应的文件夹中,lib文件夹主要放所有的第三方的插件文件,另外还添加了一个upload文件夹主要存放所有上传的文件图片的。
以上博客中使用的文字信息来之IT之家网站,页面布局都是传统的布局方式,风格参考我的博客园的风格。
下一篇博客会介绍系统中留言、轮播图管理的实现,我会的也就这么多了,希望大家多提提意见,有什么不够好的地方我会尽量改正的,谢谢大家。