Pārlūkot izejas kodu

文章访问追踪优化

懒得勤快 3 gadi atpakaļ
vecāks
revīzija
cbe10ced3d

+ 15 - 7
src/Masuit.MyBlogs.Core/Controllers/PostController.cs

@@ -37,6 +37,7 @@ using System.Linq.Expressions;
 using System.Net;
 using System.Text;
 using System.Text.RegularExpressions;
+using System.Web;
 using SameSiteMode = Microsoft.AspNetCore.Http.SameSiteMode;
 
 namespace Masuit.MyBlogs.Core.Controllers
@@ -47,12 +48,19 @@ namespace Masuit.MyBlogs.Core.Controllers
     public class PostController : BaseController
     {
         public IPostService PostService { get; set; }
+
         public ICategoryService CategoryService { get; set; }
+
         public ISeminarService SeminarService { get; set; }
+
         public IPostHistoryVersionService PostHistoryVersionService { get; set; }
+
         public IWebHostEnvironment HostEnvironment { get; set; }
+
         public ISearchEngine<DataContext> SearchEngine { get; set; }
+
         public ImagebedClient ImagebedClient { get; set; }
+
         public IPostVisitRecordService PostVisitRecordService { get; set; }
 
         /// <summary>
@@ -91,7 +99,7 @@ namespace Masuit.MyBlogs.Core.Controllers
 
             if (!HttpContext.Request.IsRobot() && string.IsNullOrEmpty(HttpContext.Session.Get<string>("post" + id)))
             {
-                HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.RecordPostVisit), args: new dynamic[] { id, ClientIP, Request.Headers[HeaderNames.Referer].ToString() });
+                HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.RecordPostVisit), args: new dynamic[] { id, ClientIP, Request.Headers[HeaderNames.Referer].ToString(), HttpUtility.UrlDecode(Request.Scheme + "://" + Request.Host + Request.Path + Request.QueryString), Request.Headers.ToJsonString() });
                 HttpContext.Session.Set("post" + id, id.ToString());
             }
 
@@ -371,7 +379,6 @@ namespace Masuit.MyBlogs.Core.Controllers
             BackgroundJob.Enqueue(() => CommonHelper.SendMail(Request.Host + "博客访问验证码", $"{Request.Host}本次验证码是:<span style='color:red'>{token}</span>,有效期为24h,请按时使用!", email, ClientIP));
             RedisHelper.Set("get:" + email, token, 120);
             return ResultData(null);
-
         }
 
         /// <summary>
@@ -437,7 +444,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                 return ResultData(null, false, "您已经提交过一次修改请求正在待处理,暂不能继续提交修改请求!");
             }
 
-            #endregion
+            #endregion 合并验证
 
             #region 直接合并
 
@@ -450,7 +457,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                 return await PostService.SaveChangesAsync() > 0 ? ResultData(null, true, "你是文章原作者,无需审核,文章已自动更新并在首页展示!") : ResultData(null, false, "操作失败!");
             }
 
-            #endregion
+            #endregion 直接合并
 
             var merge = post.PostMergeRequests.FirstOrDefault(r => r.Id == dto.Id && r.MergeState != MergeStatus.Merged);
             if (merge != null)
@@ -782,6 +789,7 @@ namespace Masuit.MyBlogs.Core.Controllers
 
                     post.Regions = post.Regions.Replace(",", "|").Replace(",", "|");
                     break;
+
                 case RegionLimitMode.AllowRegionExceptForbidRegion:
                 case RegionLimitMode.ForbidRegionExceptAllowRegion:
                     if (string.IsNullOrEmpty(post.ExceptRegions))
@@ -1038,7 +1046,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             if (!string.IsNullOrEmpty(kw))
             {
                 kw = Regex.Escape(kw);
-                where = where.And(e => Regex.IsMatch(e.IP + e.Location + e.Referer, kw));
+                where = where.And(e => Regex.IsMatch(e.IP + e.Location + e.Referer + e.RequestUrl, kw));
             }
 
             var pages = await PostVisitRecordService.GetPagesAsync<DateTime, PostVisitRecordViewModel>(page, size, where, e => e.Time, false);
@@ -1075,6 +1083,6 @@ namespace Masuit.MyBlogs.Core.Controllers
             return View(PostService[id]);
         }
 
-        #endregion
+        #endregion 后端管理
     }
-}
+}

+ 5 - 1
src/Masuit.MyBlogs.Core/Extensions/Hangfire/HangfireBackJob.cs

@@ -110,7 +110,9 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
         /// <param name="pid"></param>
         /// <param name="ip"></param>
         /// <param name="refer"></param>
-        public void RecordPostVisit(int pid, string ip, string refer)
+        /// <param name="url"></param>
+        /// <param name="headers"></param>
+        public void RecordPostVisit(int pid, string ip, string refer, string url, string headers)
         {
             var time = DateTime.Now.AddMonths(-3);
             _recordService.GetQuery(b => b.Time < time).DeleteFromQuery();
@@ -128,6 +130,8 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
                 Referer = refer,
                 Location = ip.GetIPLocation(),
                 Time = DateTime.Now,
+                RequestHeader = headers,
+                RequestUrl = url,
                 PostId = pid
             });
             _postService.SaveChanges();

+ 2 - 1
src/Masuit.MyBlogs.Core/Extensions/Hangfire/IHangfireBackJob.cs

@@ -29,7 +29,8 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
         /// <param name="pid"></param>
         /// <param name="ip"></param>
         /// <param name="refer"></param>
-        void RecordPostVisit(int pid, string ip, string refer);
+        /// <param name="url"></param><param name="headers"></param>
+        void RecordPostVisit(int pid, string ip, string refer, string url, string headers);
 
         /// <summary>
         /// 每日任务

+ 3 - 3
src/Masuit.MyBlogs.Core/Masuit.MyBlogs.Core.csproj

@@ -45,7 +45,7 @@
         <PackageReference Include="CHTCHSConv" Version="1.0.0" />
         <PackageReference Include="CLRStats" Version="1.0.0" />
         <PackageReference Include="CSRedisCore" Version="3.6.6" />
-        <PackageReference Include="EFCoreSecondLevelCacheInterceptor" Version="3.2.2" />
+        <PackageReference Include="EFCoreSecondLevelCacheInterceptor" Version="3.2.3" />
         <PackageReference Include="Hangfire" Version="1.7.27" />
         <PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" />
         <PackageReference Include="htmldiff.net-core" Version="1.3.6" />
@@ -56,7 +56,7 @@
         <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.0" />
         <PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="6.0.0" />
         <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="6.0.0" />
-        <PackageReference Include="Microsoft.Graph" Version="4.10.0" />
+        <PackageReference Include="Microsoft.Graph" Version="4.11.0" />
         <PackageReference Include="Microsoft.Graph.Auth" Version="1.0.0-preview.7" />
         <PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
         <PackageReference Include="OpenXmlPowerTools-NetStandard" Version="4.4.21" />
@@ -66,7 +66,7 @@
         <PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.14" />
         <PackageReference Include="TimeZoneConverter" Version="3.5.0" />
         <PackageReference Include="WilderMinds.RssSyndication" Version="1.7.0" />
-        <PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="6.13.1" />
+        <PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="6.13.2" />
     </ItemGroup>
     <ItemGroup>
         <Content Update="appsettings.json">

+ 4 - 0
src/Masuit.MyBlogs.Core/Models/Entity/PostVisitRecord.cs

@@ -13,6 +13,10 @@ namespace Masuit.MyBlogs.Core.Models.Entity
 
         public string Referer { get; set; }
 
+        public string RequestUrl { get; set; }
+
+        public string RequestHeader { get; set; }
+
         public DateTime Time { get; set; }
     }
 }

+ 8 - 1
src/Masuit.MyBlogs.Core/Models/ViewModel/PostVisitRecordViewModel.cs

@@ -3,8 +3,15 @@
     public class PostVisitRecordViewModel
     {
         public string IP { get; set; }
+
         public string Location { get; set; }
+
         public string Referer { get; set; }
+
+        public string RequestUrl { get; set; }
+
+        public string RequestHeader { get; set; }
+
         public string Time { get; set; }
     }
-}
+}

+ 3 - 3
src/Masuit.MyBlogs.Core/Views/Post/Details.cshtml

@@ -55,10 +55,10 @@
                                     <div class="padding-bot10">
                                         <span class="label label-info">
                                             <a asp-controller="Home" asp-action="Author" asp-route-author="@Model.Author">@Model.Author</a>
-                                        </span>发表于<span class="text-info">@Model.PostDate.ToString("yyyy-MM-dd HH:mm:ss")</span> |
+                                        </span>发表于<span class="text-info">@Model.PostDate.ToString("yyyy-MM-dd HH:mm")</span> |
                                         <span class="label label-info">
                                             <a asp-controller="Home" asp-action="Author" asp-route-author="@Model.Modifier">@Model.Modifier</a>
-                                        </span>最后修改于<span class="text-success">@Model.ModifyDate.ToString("yyyy-MM-dd HH:mm:ss")</span>
+                                        </span>最后修改于<span class="text-success">@Model.ModifyDate.ToString("yyyy-MM-dd HH:mm")</span>
                                     </div>
                                 </div>
                                 @{
@@ -81,7 +81,7 @@
                                 <div class="col-md-12 line-height24">
                                     分类:<i class="icon-map-pin"></i>
                                     <a asp-controller="Home" asp-action="Category" asp-route-id="@Model.CategoryId" class="label label-info">@Model.Category.Name</a>
-                                    | 评论总数:<span class="text-danger">@Model.Comment.Count</span>条 | 热度:<span class="text-danger">@Model.TotalViewCount</span>℃ | @(await Html.RenderComponentAsync<PostOnline>(RenderMode.ServerPrerendered, new{ Model.Id,IP=Context.Connection.RemoteIpAddress.ToString()}))
+                                    | 评论总数:<span class="text-danger">@Model.Comment.Count</span>条 | @(await Html.RenderComponentAsync<PostOnline>(RenderMode.ServerPrerendered, new{ Model.Id,IP=Context.Connection.RemoteIpAddress.ToString()}))
                                     @if (Model.Seminar.Any())
                                     {
                                         <span> | 所属专题:</span>

+ 385 - 385
src/Masuit.MyBlogs.Core/Views/Post/Details_Admin.cshtml

@@ -10,311 +10,311 @@
 @using Masuit.Tools.Systems
 @model Masuit.MyBlogs.Core.Models.Entity.Post
 @{
-    ViewBag.Title = Model.Title;
-    Layout = "~/Views/Shared/_Layout.cshtml";
-    string[] colors = { "success", "info", "primary", "warning", "danger", "default", "primary" };
-    UserInfoDto user = Context.Session.Get<UserInfoDto>(SessionKey.UserInfo);
-    var cid = Context.Request.RouteValues["cid"] ?? (string.IsNullOrEmpty(Context.Request.Query["cid"]) ? "0" : Context.Request.Query["cid"]);
-    Advertisement ad = ViewBag.Ads;
+	ViewBag.Title = Model.Title;
+	Layout = "~/Views/Shared/_Layout.cshtml";
+	string[] colors = { "success", "info", "primary", "warning", "danger", "default", "primary" };
+	UserInfoDto user = Context.Session.Get<UserInfoDto>(SessionKey.UserInfo);
+	var cid = Context.Request.RouteValues["cid"] ?? (string.IsNullOrEmpty(Context.Request.Query["cid"]) ? "0" : Context.Request.Query["cid"]);
+	Advertisement ad = ViewBag.Ads;
 }
 <script src="https://cdn.staticfile.org/jqueryui/1.12.1/jquery-ui.min.js" async defer></script>
 <environment names="Development">
-    <link href="~/Assets/jquery.tocify/jquery.tocify.css" rel="stylesheet" />
-    <link href="~/Assets/UEditor/third-party/SyntaxHighlighter/styles/shCore.css" rel="stylesheet" />
-    <link href="~/Assets/highlight/css/highlight.css" rel="stylesheet" />
-    <script src="/Assets/highlight/js/highlight.js"></script>
-    <script src="/Assets/UEditor/third-party/SyntaxHighlighter/scripts/shCore.js"></script>
-    <script src="/Assets/UEditor/third-party/SyntaxHighlighter/scripts/bundle.min.js"></script>
-    <script src="/Assets/jquery.tocify/jquery.tocify.js"></script>
-    <script src="/Scripts/global/article.js"></script>
-    <script src="/Assets/highlight/js/highlight.js"></script>
+	<link href="~/Assets/jquery.tocify/jquery.tocify.css" rel="stylesheet" />
+	<link href="~/Assets/UEditor/third-party/SyntaxHighlighter/styles/shCore.css" rel="stylesheet" />
+	<link href="~/Assets/highlight/css/highlight.css" rel="stylesheet" />
+	<script src="/Assets/highlight/js/highlight.js"></script>
+	<script src="/Assets/UEditor/third-party/SyntaxHighlighter/scripts/shCore.js"></script>
+	<script src="/Assets/UEditor/third-party/SyntaxHighlighter/scripts/bundle.min.js"></script>
+	<script src="/Assets/jquery.tocify/jquery.tocify.js"></script>
+	<script src="/Scripts/global/article.js"></script>
+	<script src="/Assets/highlight/js/highlight.js"></script>
 </environment>
 <environment names="Stage,Production">
-    @await Styles.RenderAsync("/bundles/article.css")
-    @await Scripts.RenderAsync("/bundles/article.js")
+	@await Styles.RenderAsync("/bundles/article.css")
+	@await Scripts.RenderAsync("/bundles/article.js")
 </environment>
 <div class="container">
-    <ol class="cd-breadcrumb triangle">
-        <li><a asp-controller="Home" asp-action="Index">首页</a></li>
-        <li><a asp-controller="Home" asp-action="Post">文章列表</a></li>
-        <li class="current"><em>@ViewBag.Title</em></li>
-    </ol>
-    <div class="wrapper-content article">
-        <div class="ibox">
-            <div class="ibox-content animated fadeIn">
-                <main>
-                    <section>
-                        <header class="page-header">
-                            <div class="text-center">
-                                <a>
-                                    <h2 class="padding-bot10">
-                                        @Model.Title
-                                    </h2>
-                                </a>
-                            </div>
-                            <div class="row">
-                                <div class="col-sm-8">
-                                    <div class="padding-bot10">
-                                        <span class="label label-info">
-                                            <a asp-controller="Home" asp-action="Author" asp-route-author="@Model.Author">@Model.Author</a>
-                                        </span>发表于<span class="text-info">@Model.PostDate.ToString("yyyy-MM-dd HH:mm:ss")</span> |
-                                        <span class="label label-info">
-                                            <a asp-controller="Home" asp-action="Author" asp-route-author="@Model.Modifier">@Model.Modifier</a>
-                                        </span>最后修改于<span class="text-success">@Model.ModifyDate.ToString("yyyy-MM-dd HH:mm:ss")</span>
-                                    </div>
-                                </div>
-                                @{
-                                    if (!string.IsNullOrEmpty(Model.Label))
-                                    {
-                                        <div class="pull-right margin-right20">
-                                            <div>
-                                                @foreach (string s in Model.Label.Split(new[] { ',', ',' }, StringSplitOptions.RemoveEmptyEntries))
-                                                {
-                                                    <a asp-controller="Home" asp-action="Tag" asp-route-tag="@s">
-                                                        <span class="label label-@colors[new Random().Next() % colors.Length]">@s</span>
-                                                    </a>
-                                                }
-                                            </div>
-                                        </div>
-                                    }
-                                }
-                            </div>
-                            <div class="row">
-                                <div class="col-md-12 line-height24">
-                                    分类:<i class="icon-map-pin"></i>
-                                    <a asp-controller="Home" asp-action="Category" asp-route-id="@Model.CategoryId" class="label label-info">@Model.Category.Name</a>
-                                    | 评论总数:<span class="text-danger">@Model.Comment.Count</span>条 | 热度:<span class="text-danger">@Model.TotalViewCount</span>℃ | @(await Html.RenderComponentAsync<PostOnline>(RenderMode.ServerPrerendered, new { Model.Id,IP=Context.Connection.RemoteIpAddress.ToString(),IsAdmin=true })) | 状态:@Model.Status.GetDisplay()
-                                    @if (Model.Seminar.Any())
-                                    {
-                                        <span> | 所属专题:</span>
-                                        var seminars = Model.Seminar;
-                                        foreach (var s in seminars)
-                                        {
-                                            <a asp-controller="Seminar" asp-action="Index" asp-route-id="@s.Id" class="label label-info">@s.Title</a><text> </text>
-                                        }
-                                    }
-                                </div>
-                                @if (Model.LimitMode > 0)
-                                {
-                                    <div class="col-md-6 col-sm-12 text-red margin-top10">
-                                        本文 @string.Format(Model.LimitMode.GetDescription(), Model.Regions, Model.ExceptRegions)
-                                    </div>
-                                }
-                                <div class="col-md-6 col-sm-12 pull-right">
-                                    <div class="btn-group pull-right">
-                                        <a asp-controller="Post" asp-action="Refresh" asp-route-id="@Model.Id" class="btn btn-info">刷新</a>
-                                        @if (Model.IsFixedTop)
-                                        {
-                                            <button class="btn btn-success" id="pin">取消置顶</button>
-                                        }
-                                        else
-                                        {
-                                            <button class="btn btn-success" id="pin">置顶</button>
-                                        }
-                                        @if (Model.Status == Status.Pending)
-                                        {
-                                            <button class="btn btn-primary" id="pass">通过</button>
-                                        }
-                                        <a asp-controller="Dashboard" asp-action="Index" asp-fragment="/post/[email protected]" class="btn btn-primary" target="_blank">修改</a>
-                                        <a asp-controller="Dashboard" asp-action="Index" asp-fragment="/[email protected]" class="btn btn-info" target="_blank">复制</a>
-                                        <button class="btn btn-danger" id="del">删除</button>
-                                        <a asp-controller="Post" asp-action="PostVisitRecordInsight" asp-route-id="@Model.Id" class="btn btn-primary" target="_blank">洞察</a>
-                                    </div>
-                                </div>
-                            </div>
-                        </header>
-                        <article class="article" id="article">
-                            @if (DateTime.Now - Model.ModifyDate > TimeSpan.FromDays(365))
-                            {
-                                <p class="text-focus text-center">该文章已经超过1年未更新,可能无法为您提供及时准确的资讯,请根据当下实际情况,酌情参考本文内容。</p>
-                            }
-                            @Html.Raw(Model.Content)
-                            @Html.Raw(Model.ProtectContent)
-                        </article>
-                    </section>
-                </main>
-                <hr class="margin-top10 marginbot10" />
-                @if (ad != null)
-                {
-                    await Html.RenderPartialAsync("_ArticleListAdvertisement", ad);
-                }
-                <section class="wow fadeIn row padding-top40 padding-bot20">
-                    <div class="col-xs-6">
-                        <div class="btn-group">
-                            <button type="button" id="voteup" class="btn btn-success btn-lg">
-                                <i class="icon-thumbsup"></i><span>@Model.VoteUpCount</span>
-                            </button>
-                            <button type="button" id="votedown" class="btn btn-danger btn-lg">
-                                <i class="icon-thumbsdown"></i><span>@Model.VoteDownCount</span>
-                            </button>
-                        </div>
-                    </div>
-                </section>
-                <section class="wow row size16 animated fadeIn">
-                    <div class="col-xs-6">
-                        上一篇:
-                        @{
-                            PostModelBase prev = ViewBag.Prev;
-                            if (prev != null)
-                            {
-                                <a asp-controller="Post" asp-action="Details" asp-route-id="@prev.Id">@prev.Title</a>
-                            }
-                            else
-                            {
-                                <a>没有了</a>
-                            }
-                        }
-                    </div>
-                    <div class="col-xs-6 text-right">
-                        下一篇:
-                        @{
-                            PostModelBase next = ViewBag.Next;
-                            if (next != null)
-                            {
-                                <a asp-controller="Post" asp-action="Details" asp-route-id="@next.Id">@next.Title</a>
-                            }
-                            else
-                            {
-                                <a>没有了</a>
-                            }
-                        }
-                    </div>
-                </section>
-                @if (Model.PostHistoryVersion.Any())
-                {
-                    <section class="wow margintop20 animated fadeIn">
-                        <h3>文章历史版本:</h3>
-                        <p>
-                            修改次数:@Model.PostHistoryVersion.Count 次
-                            <a asp-controller="Post" asp-action="History" asp-route-id="@Model.Id">查看历史版本</a>
-                        </p>
-                    </section>
-                }
-                @{
-                    var posts = (Dictionary<int, string>)ViewBag.Related;
-                    if (posts.Count > 1)
-                    {
-                        <section class="wow margintop20 animated fadeIn">
-                            <h3>相关推荐:</h3>
-                            <table class="table table-condensed size16">
-                                @for (int i = 1; i < posts.Count; i += 2)
-                                {
-                                    <tr>
-                                        <td style="width: 50%"><a asp-controller="Post" asp-action="Details" asp-route-id="@posts.ElementAt(i - 1).Key">@posts.ElementAt(i - 1).Value</a></td>
-                                        <td><a asp-controller="Post" asp-action="Details" asp-route-id="@posts.ElementAt(i).Key">@posts.ElementAt(i).Value</a></td>
-                                    </tr>
-                                }
-                            </table>
-                        </section>
-                    }
-                }
-                <section class="wow padding-bot20 animated fadeIn">
-                    <h3>版权声明:</h3>
-                    <p class="text-red size16">
-                        @if (Model.DisableCopy)
-                        {
-                            <text>🈲⚠本文为作者原创,仅用于本站访客学习、研究和交流目的,未经授权禁止转载。️⚠🈲</text>
-                        }
-                        else
-                        {
-                            <text>本文仅用于学习、研究和交流目的,欢迎非商业性质转载。本文链接:<a asp-controller="Post" asp-action="Details" asp-route-id="@Model.Id">@HttpUtility.UrlDecode(Context.Request.Scheme + "://" + Context.Request.Host + Context.Request.Path)</a>。</text>
-                            @Html.Raw(CommonHelper.SystemSettings["Disclaimer"])
-                        }
-                    </p>
-                </section>
-                <section class="wow row animated fadeIn">
-                    <div class="col-lg-12">
-                        <h3>评论区:</h3>
-                        <form class="form-horizontal animated pulse" id="comment" method="post">
-                            @Html.AntiForgeryToken()
-                            <input type="hidden" name="PostId" value="@Model.Id" />
-                            <input type="hidden" id="OperatingSystem" name="OperatingSystem" />
-                            <input type="hidden" name="Browser" id="Browser" />
-                            <input type="hidden" value="@user.NickName" class="form-control" name="NickName" id="name">
-                            <input type="hidden" value="@user.Email" class="form-control" name="Email" id="email">
-                            <div class="form-group overlay animated fadeInDown" style="margin-bottom: 0px !important;">
-                                <textarea class="layui-textarea" id="layedit" name="Content" style="height: 100px"></textarea>
-                            </div>
-                            <input type="hidden" name="Agree" value="true" />
-                            <div class="form-group">
-                                <div class="col-xs-12">
-                                    <button type="submit" class="btn btn-info btn-lg">提交</button>
-                                    <a class="text-red">评论框可粘贴网络图片</a>
-                                </div>
-                            </div>
-                        </form>
-                        <ul class="wow media-list"></ul>
-                        @if (Model.Comment.Any(c => c.Status == Status.Published))
-                        {
-                            <div class="row">
-                                <div class="col-md-12 text-center">
-                                    <div id="pageToolbar"></div>
-                                </div>
-                            </div>
-                        }
-                        else
-                        {
-                            <h4>还没有评论哦,赶紧来写评论吧</h4>
-                        }
-                    </div>
-                </section>
-            </div>
-        </div>
-    </div>
+	<ol class="cd-breadcrumb triangle">
+		<li><a asp-controller="Home" asp-action="Index">首页</a></li>
+		<li><a asp-controller="Home" asp-action="Post">文章列表</a></li>
+		<li class="current"><em>@ViewBag.Title</em></li>
+	</ol>
+	<div class="wrapper-content article">
+		<div class="ibox">
+			<div class="ibox-content animated fadeIn">
+				<main>
+					<section>
+						<header class="page-header">
+							<div class="text-center">
+								<a>
+									<h2 class="padding-bot10">
+										@Model.Title
+									</h2>
+								</a>
+							</div>
+							<div class="row">
+								<div class="col-sm-8">
+									<div class="padding-bot10">
+										<span class="label label-info">
+											<a asp-controller="Home" asp-action="Author" asp-route-author="@Model.Author">@Model.Author</a>
+										</span>发表于<span class="text-info">@Model.PostDate.ToString("yyyy-MM-dd HH:mm:ss")</span> |
+										<span class="label label-info">
+											<a asp-controller="Home" asp-action="Author" asp-route-author="@Model.Modifier">@Model.Modifier</a>
+										</span>最后修改于<span class="text-success">@Model.ModifyDate.ToString("yyyy-MM-dd HH:mm:ss")</span>
+									</div>
+								</div>
+								@{
+									if (!string.IsNullOrEmpty(Model.Label))
+									{
+										<div class="pull-right margin-right20">
+											<div>
+												@foreach (string s in Model.Label.Split(new[] { ',', ',' }, StringSplitOptions.RemoveEmptyEntries))
+												{
+													<a asp-controller="Home" asp-action="Tag" asp-route-tag="@s">
+														<span class="label label-@colors[new Random().Next() % colors.Length]">@s</span>
+													</a>
+												}
+											</div>
+										</div>
+									}
+								}
+							</div>
+							<div class="row">
+								<div class="col-md-12 line-height24">
+									分类:<i class="icon-map-pin"></i>
+									<a asp-controller="Home" asp-action="Category" asp-route-id="@Model.CategoryId" class="label label-info">@Model.Category.Name</a>
+									| 评论总数:<span class="text-danger">@Model.Comment.Count</span>条 | 热度:<span class="text-danger">@Model.TotalViewCount</span>℃ | @(await Html.RenderComponentAsync<PostOnline>(RenderMode.ServerPrerendered, new { Model.Id,IP=Context.Connection.RemoteIpAddress.ToString(),IsAdmin=true })) | 状态:@Model.Status.GetDisplay()
+									@if (Model.Seminar.Any())
+									{
+										<span> | 所属专题:</span>
+										var seminars = Model.Seminar;
+										foreach (var s in seminars)
+										{
+											<a asp-controller="Seminar" asp-action="Index" asp-route-id="@s.Id" class="label label-info">@s.Title</a><text> </text>
+										}
+									}
+								</div>
+								@if (Model.LimitMode > 0)
+								{
+									<div class="col-md-6 col-sm-12 text-red margin-top10">
+										本文 @string.Format(Model.LimitMode.GetDescription(), Model.Regions, Model.ExceptRegions)
+									</div>
+								}
+								<div class="col-md-6 col-sm-12 pull-right">
+									<div class="btn-group pull-right">
+										<a asp-controller="Post" asp-action="Refresh" asp-route-id="@Model.Id" class="btn btn-info">刷新</a>
+										@if (Model.IsFixedTop)
+										{
+											<button class="btn btn-success" id="pin">取消置顶</button>
+										}
+										else
+										{
+											<button class="btn btn-success" id="pin">置顶</button>
+										}
+										@if (Model.Status == Status.Pending)
+										{
+											<button class="btn btn-primary" id="pass">通过</button>
+										}
+										<a asp-controller="Dashboard" asp-action="Index" asp-fragment="/post/[email protected]" class="btn btn-primary" target="_blank">修改</a>
+										<a asp-controller="Dashboard" asp-action="Index" asp-fragment="/[email protected]" class="btn btn-info" target="_blank">复制</a>
+										<button class="btn btn-danger" id="del">删除</button>
+										<a asp-controller="Post" asp-action="PostVisitRecordInsight" asp-route-id="@Model.Id" class="btn btn-primary" target="_blank">洞察</a>
+									</div>
+								</div>
+							</div>
+						</header>
+						<article class="article" id="article">
+							@if (DateTime.Now - Model.ModifyDate > TimeSpan.FromDays(365))
+							{
+								<p class="text-focus text-center">该文章已经超过1年未更新,可能无法为您提供及时准确的资讯,请根据当下实际情况,酌情参考本文内容。</p>
+							}
+							@Html.Raw(Model.Content)
+							@Html.Raw(Model.ProtectContent)
+						</article>
+					</section>
+				</main>
+				<hr class="margin-top10 marginbot10" />
+				@if (ad != null)
+				{
+					await Html.RenderPartialAsync("_ArticleListAdvertisement", ad);
+				}
+				<section class="wow fadeIn row padding-top40 padding-bot20">
+					<div class="col-xs-6">
+						<div class="btn-group">
+							<button type="button" id="voteup" class="btn btn-success btn-lg">
+								<i class="icon-thumbsup"></i><span>@Model.VoteUpCount</span>
+							</button>
+							<button type="button" id="votedown" class="btn btn-danger btn-lg">
+								<i class="icon-thumbsdown"></i><span>@Model.VoteDownCount</span>
+							</button>
+						</div>
+					</div>
+				</section>
+				<section class="wow row size16 animated fadeIn">
+					<div class="col-xs-6">
+						上一篇:
+						@{
+							PostModelBase prev = ViewBag.Prev;
+							if (prev != null)
+							{
+								<a asp-controller="Post" asp-action="Details" asp-route-id="@prev.Id">@prev.Title</a>
+							}
+							else
+							{
+								<a>没有了</a>
+							}
+						}
+					</div>
+					<div class="col-xs-6 text-right">
+						下一篇:
+						@{
+							PostModelBase next = ViewBag.Next;
+							if (next != null)
+							{
+								<a asp-controller="Post" asp-action="Details" asp-route-id="@next.Id">@next.Title</a>
+							}
+							else
+							{
+								<a>没有了</a>
+							}
+						}
+					</div>
+				</section>
+				@if (Model.PostHistoryVersion.Any())
+				{
+					<section class="wow margintop20 animated fadeIn">
+						<h3>文章历史版本:</h3>
+						<p>
+							修改次数:@Model.PostHistoryVersion.Count 次
+							<a asp-controller="Post" asp-action="History" asp-route-id="@Model.Id">查看历史版本</a>
+						</p>
+					</section>
+				}
+				@{
+					var posts = (Dictionary<int, string>)ViewBag.Related;
+					if (posts.Count > 1)
+					{
+						<section class="wow margintop20 animated fadeIn">
+							<h3>相关推荐:</h3>
+							<table class="table table-condensed size16">
+								@for (int i = 1; i < posts.Count; i += 2)
+								{
+									<tr>
+										<td style="width: 50%"><a asp-controller="Post" asp-action="Details" asp-route-id="@posts.ElementAt(i - 1).Key">@posts.ElementAt(i - 1).Value</a></td>
+										<td><a asp-controller="Post" asp-action="Details" asp-route-id="@posts.ElementAt(i).Key">@posts.ElementAt(i).Value</a></td>
+									</tr>
+								}
+							</table>
+						</section>
+					}
+				}
+				<section class="wow padding-bot20 animated fadeIn">
+					<h3>版权声明:</h3>
+					<p class="text-red size16">
+						@if (Model.DisableCopy)
+						{
+							<text>🈲⚠本文为作者原创,仅用于本站访客学习、研究和交流目的,未经授权禁止转载。️⚠🈲</text>
+						}
+						else
+						{
+							<text>本文仅用于学习、研究和交流目的,欢迎非商业性质转载。本文链接:<a asp-controller="Post" asp-action="Details" asp-route-id="@Model.Id">@HttpUtility.UrlDecode(Context.Request.Scheme + "://" + Context.Request.Host + Context.Request.Path)</a>。</text>
+							@Html.Raw(CommonHelper.SystemSettings["Disclaimer"])
+						}
+					</p>
+				</section>
+				<section class="wow row animated fadeIn">
+					<div class="col-lg-12">
+						<h3>评论区:</h3>
+						<form class="form-horizontal animated pulse" id="comment" method="post">
+							@Html.AntiForgeryToken()
+							<input type="hidden" name="PostId" value="@Model.Id" />
+							<input type="hidden" id="OperatingSystem" name="OperatingSystem" />
+							<input type="hidden" name="Browser" id="Browser" />
+							<input type="hidden" value="@user.NickName" class="form-control" name="NickName" id="name">
+							<input type="hidden" value="@user.Email" class="form-control" name="Email" id="email">
+							<div class="form-group overlay animated fadeInDown" style="margin-bottom: 0px !important;">
+								<textarea class="layui-textarea" id="layedit" name="Content" style="height: 100px"></textarea>
+							</div>
+							<input type="hidden" name="Agree" value="true" />
+							<div class="form-group">
+								<div class="col-xs-12">
+									<button type="submit" class="btn btn-info btn-lg">提交</button>
+									<a class="text-red">评论框可粘贴网络图片</a>
+								</div>
+							</div>
+						</form>
+						<ul class="wow media-list"></ul>
+						@if (Model.Comment.Any(c => c.Status == Status.Published))
+						{
+							<div class="row">
+								<div class="col-md-12 text-center">
+									<div id="pageToolbar"></div>
+								</div>
+							</div>
+						}
+						else
+						{
+							<h4>还没有评论哦,赶紧来写评论吧</h4>
+						}
+					</div>
+				</section>
+			</div>
+		</div>
+	</div>
 </div>
 <div style="position: absolute; left: -20000px; bottom: 0;">
-    <div id="reply" class="container-fluid">
-        <form class="form-horizontal" id="reply-form" method="post">
-            @Html.AntiForgeryToken()
-            <input type="hidden" name="PostId" id="postId" value="@Model.Id" />
-            <input type="hidden" name="OperatingSystem" id="OperatingSystem2" />
-            <input type="hidden" name="Browser" id="Browser2" />
-            <input type="hidden" value="@user.NickName" class="form-control" name="NickName" id="name2">
-            <input type="hidden" value="@user.Email" class="form-control" name="Email" id="email2">
-            <input type="hidden" value="" id="uid" name="ParentId" />
-            <div class="form-group overlay animated fadeInDown">
-                <textarea class="layui-textarea" id="layedit2" name="Content" style="height: 80px"></textarea>
-            </div>
-            <input type="hidden" name="Agree" value="true" />
-            <div class="form-group">
-                <div class="col-xs-12">
-                    <div class="btn-group">
-                        <button type="submit" class="btn btn-info btn-lg">
-                            提交回复
-                        </button>
-                        <button type="button" class="btn-cancel btn btn-danger btn-lg">
-                            取消回复
-                        </button>
-                    </div>
-                </div>
-            </div>
-        </form>
-    </div>
+	<div id="reply" class="container-fluid">
+		<form class="form-horizontal" id="reply-form" method="post">
+			@Html.AntiForgeryToken()
+			<input type="hidden" name="PostId" id="postId" value="@Model.Id" />
+			<input type="hidden" name="OperatingSystem" id="OperatingSystem2" />
+			<input type="hidden" name="Browser" id="Browser2" />
+			<input type="hidden" value="@user.NickName" class="form-control" name="NickName" id="name2">
+			<input type="hidden" value="@user.Email" class="form-control" name="Email" id="email2">
+			<input type="hidden" value="" id="uid" name="ParentId" />
+			<div class="form-group overlay animated fadeInDown">
+				<textarea class="layui-textarea" id="layedit2" name="Content" style="height: 80px"></textarea>
+			</div>
+			<input type="hidden" name="Agree" value="true" />
+			<div class="form-group">
+				<div class="col-xs-12">
+					<div class="btn-group">
+						<button type="submit" class="btn btn-info btn-lg">
+							提交回复
+						</button>
+						<button type="button" class="btn-cancel btn btn-danger btn-lg">
+							取消回复
+						</button>
+					</div>
+				</div>
+			</div>
+		</form>
+	</div>
 </div>
 <script>
-    function getcomments() {
-        window.get("/comment/getcomments?id=" + $("#postId").val()+"&page=1&size=10&cid="+@cid,function(data) {
-            data = data.Data;
+	function getcomments() {
+		window.get("/comment/getcomments?id=" + $("#postId").val()+"&page=1&size=10&cid="+@cid,function(data) {
+			data = data.Data;
 			document.querySelector(".media-list").innerHTML = loadParentComments(data);
 			bindReplyBtn();
 			commentVoteBind(); //评论投票
-        });
-    }
+		});
+	}
 	window.onload = function() {
-        const keywords = @Html.Raw(ViewData["keywords"] ?? "[]");
-        for (let i = 0; i < keywords.length; i++) {
-            $("#article p").highlight(keywords[i]);
-            $("#article div").highlight(keywords[i]);
-            $("#article h3").highlight(keywords[i]);
-            $("#article h4").highlight(keywords[i]);
-        }
+		const keywords = @Html.Raw(ViewData["keywords"] ?? "[]");
+		for (let i = 0; i < keywords.length; i++) {
+			$("#article p").highlight(keywords[i]);
+			$("#article div").highlight(keywords[i]);
+			$("#article h3").highlight(keywords[i]);
+			$("#article h4").highlight(keywords[i]);
+		}
 		loading();
 		$('#pageToolbar').Paging({ //异步加载评论
 			pagesize: 10,
 			count: @Model.Comment.Count(c =>c.ParentId==0&& c.Status==Status.Published),
 			toolbar: true,
 			callback: function(page, size, count) {
-                window.get("/comment/getcomments?id=" [email protected]+"&page=" + page + "&size=" + size, function (data) {
+				window.get("/comment/getcomments?id=" [email protected]+"&page=" + page + "&size=" + size, function (data) {
 					data = data.Data;
 					if (data) {
 						document.querySelector(".media-list").innerHTML = loadParentComments(data);
@@ -342,13 +342,13 @@
 						text: data.Message,
 						time: 4
 					});
-                }, () => {
-                    window.notie.alert({
+				}, () => {
+					window.notie.alert({
 						type: 3,
 						text: "请求失败,请稍候再试!",
 						time: 4
 					});
-                });
+				});
 			}, function () {
 			});
 		});
@@ -359,13 +359,13 @@
 					text: data.Message,
 					time: 4
 				}, () => {
-                    window.notie.alert({
+					window.notie.alert({
 						type: 3,
 						text: "请求失败,请稍候再试!",
 						time: 4
 					});
-                });
-                location.reload();
+				});
+				location.reload();
 			});
 		});
 		$("#pin").on("click", function (e) {
@@ -375,13 +375,13 @@
 					text: data.Message,
 					time: 4
 				}, () => {
-                    window.notie.alert({
+					window.notie.alert({
 						type: 3,
 						text: "请求失败,请稍候再试!",
 						time: 4
 					});
-                });
-                location.reload();
+				});
+				location.reload();
 			});
 		});
 		loadingDone();
@@ -392,7 +392,7 @@
 		loading();
 		var html = '';
 		if (data) {
-            var rows = data.rows;
+			var rows = data.rows;
 			var page = data.page;
 			var size = data.size;
 			var maxPage = Math.ceil(data.total / size);
@@ -401,27 +401,27 @@
 			var startfloor = data.parentTotal - (page - 1) * size;
 			for (let i = 0; i < rows.length; i++) {
 				html += `<li class="msg-list media animated fadeInRight" id='${rows[i].Id}'>
-                            <div class="media-body">
-                                <article class="panel panel-info">
-                                    <header class="panel-heading ${rows[i].IsMaster ? "text-red" : ""} ${rows[i].IsAuthor ? "text-bold" : ""}">${startfloor--}# ${rows[i].IsMaster ? `<i class="icon icon-user"></i>` : ""}${rows[i].NickName}${rows[i].IsMaster ? `(管理员)` : ""} | ${rows[i].CommentDate}
-                                        <span class="pull-right" style="font-size: 10px;">${rows[i].Status == 4 ? `<a class="label label-success" onclick="pass(${rows[i].Id})">通过</a> |` : ""} <a class="label label-danger" onclick="del(${rows[i].Id})">删除</a> | ${GetOperatingSystem(rows[i].OperatingSystem) + " | " + GetBrowser(rows[i].Browser)}</span>
-                                    </header>
-                                    <div class="panel-body">
-                                        ${rows[i].Content}
-                                        <span class="cmvote label label-info" data-id="${rows[i].Id}"><i class="icon-thumbsup"></i>(<span class="count">${rows[i].VoteCount}</span>)</span>
-                                        <a class="label label-info" href="?uid=${rows[i].Id}"><i class="icon-comment"></i></a><div class="margin-top10"></div>
-                                        <div class="pull-left">
-                                            <span class="label label-success">${rows[i].IP}</span>
-                                            <span class="label label-primary">${rows[i].Location}</span>
-                                        </div>
-                                        <div class="pull-right">
-                                            <span class="label label-success" onclick="bounceEmail('${rows[i].Email}')">${rows[i].Email}</span>
-                                        </div><br/>
-                                        ${loadComments(rows[i].Children)}
-                                    </div>
-                                </article>
-                            </div>
-                        </li>`;
+							<div class="media-body">
+								<article class="panel panel-info">
+									<header class="panel-heading ${rows[i].IsMaster ? "text-red" : ""} ${rows[i].IsAuthor ? "text-bold" : ""}">${startfloor--}# ${rows[i].IsMaster ? `<i class="icon icon-user"></i>` : ""}${rows[i].NickName}${rows[i].IsMaster ? `(管理员)` : ""} | ${rows[i].CommentDate}
+										<span class="pull-right" style="font-size: 10px;">${rows[i].Status == 4 ? `<a class="label label-success" onclick="pass(${rows[i].Id})">通过</a> |` : ""} <a class="label label-danger" onclick="del(${rows[i].Id})">删除</a> | ${GetOperatingSystem(rows[i].OperatingSystem) + " | " + GetBrowser(rows[i].Browser)}</span>
+									</header>
+									<div class="panel-body">
+										${rows[i].Content}
+										<span class="cmvote label label-info" data-id="${rows[i].Id}"><i class="icon-thumbsup"></i>(<span class="count">${rows[i].VoteCount}</span>)</span>
+										<a class="label label-info" href="?uid=${rows[i].Id}"><i class="icon-comment"></i></a><div class="margin-top10"></div>
+										<div class="pull-left">
+											<span class="label label-success">${rows[i].IP}</span>
+											<span class="label label-primary">${rows[i].Location}</span>
+										</div>
+										<div class="pull-right">
+											<span class="label label-success" onclick="bounceEmail('${rows[i].Email}')">${rows[i].Email}</span>
+										</div><br/>
+										${loadComments(rows[i].Children)}
+									</div>
+								</article>
+							</div>
+						</li>`;
 			}
 		}
 		loadingDone();
@@ -430,37 +430,37 @@
 
 	//加载子楼层
 	function loadComments(comments, depth = 0) {
-        comments.sort(function(x, y) {
-            return x.Id - y.Id
-        });
+		comments.sort(function(x, y) {
+			return x.Id - y.Id
+		});
 
 		var colors = ["info", "success", "primary", "warning", "danger"];
 		var floor = 1;
 		depth++;
 		var html = '';
-        for (let item of comments) {
-            var color = colors[depth % 5];
-            html += `<article id="${item.Id}" class="panel panel-${color}">
-                            <div class="panel-heading ${item.IsMaster ? "text-red" : ""} ${item.IsAuthor ? "text-bold" : ""}">
-                                ${depth}-${floor++}# ${item.IsMaster ? `<i class="icon icon-user"></i>` : ""}${item.NickName}${item.IsMaster ? `(管理员)` : ""} | ${item.CommentDate}
-                                <span class="pull-right" style="font-size: 10px;">${item.Status == 4 ? `<a class="label label-success" onclick="pass(${item.Id})">通过</a> |` : ""} <a class="label label-danger" onclick="del(${item.Id})">删除</a> | ${GetOperatingSystem(item.OperatingSystem) + " | " + GetBrowser(item.Browser)}</span>
-                            </div>
-                            <div class="panel-body">
-                                ${item.Content}
-                                <span class="cmvote label label-${color}" data-id="${item.Id}"><i class="icon-thumbsup"></i>(<span class="count">${item.VoteCount}</span>)</span>
-                                <a class="label label-${color}" href="?uid=${item.Id}"><i class="icon-comment"></i></a>
-                                <div class="margin-top10"></div>
-                                <div class="pull-left">
-                                    <span class="label label-success">${item.IP}</span>
-                                    <span class="label label-primary">${item.Location}</span>
-                                </div>
-                                <div class="pull-right">
-                                    <span class="label label-success" onclick="bounceEmail('${item.Email}')">${item.Email}</span>
-                                </div><br/>
-                                ${loadComments(item.Children, depth)}
-                            </div>
-                        </article>`;
-        }
+		for (let item of comments) {
+			var color = colors[depth % 5];
+			html += `<article id="${item.Id}" class="panel panel-${color}">
+							<div class="panel-heading ${item.IsMaster ? "text-red" : ""} ${item.IsAuthor ? "text-bold" : ""}">
+								${depth}-${floor++}# ${item.IsMaster ? `<i class="icon icon-user"></i>` : ""}${item.NickName}${item.IsMaster ? `(管理员)` : ""} | ${item.CommentDate}
+								<span class="pull-right" style="font-size: 10px;">${item.Status == 4 ? `<a class="label label-success" onclick="pass(${item.Id})">通过</a> |` : ""} <a class="label label-danger" onclick="del(${item.Id})">删除</a> | ${GetOperatingSystem(item.OperatingSystem) + " | " + GetBrowser(item.Browser)}</span>
+							</div>
+							<div class="panel-body">
+								${item.Content}
+								<span class="cmvote label label-${color}" data-id="${item.Id}"><i class="icon-thumbsup"></i>(<span class="count">${item.VoteCount}</span>)</span>
+								<a class="label label-${color}" href="?uid=${item.Id}"><i class="icon-comment"></i></a>
+								<div class="margin-top10"></div>
+								<div class="pull-left">
+									<span class="label label-success">${item.IP}</span>
+									<span class="label label-primary">${item.Location}</span>
+								</div>
+								<div class="pull-right">
+									<span class="label label-success" onclick="bounceEmail('${item.Email}')">${item.Email}</span>
+								</div><br/>
+								${loadComments(item.Children, depth)}
+							</div>
+						</article>`;
+		}
 		return html;
 	}
 
@@ -469,58 +469,58 @@
 			swal(res.Message, "", res.Success ? "success" : "error");
 			getcomments();
 		}, () => {
-            swal("操作失败,请稍候再试", "", "error");
-        });
+			swal("操作失败,请稍候再试", "", "error");
+		});
 	}
 
 	function bounceEmail(email) {
-        swal({
-            title: "确定将这个邮箱添加到黑名单吗?",
-            showCancelButton: true,
-            confirmButtonColor: "#DD6B55",
-            confirmButtonText: "确定",
-            cancelButtonText: "取消",
-            showLoaderOnConfirm: true,
-            animation: true,
-            allowOutsideClick: false
-        }).then(function () {
-            window.post("/system/BounceEmail", { email: email }, function () {
-                swal("邮箱添加到黑名单成功", "", "success");
-            }, (e) => {
-                swal("操作失败,请稍候再试", "", "error");
-            });
-        }, function () { });
+		swal({
+			title: "确定将这个邮箱添加到黑名单吗?",
+			showCancelButton: true,
+			confirmButtonColor: "#DD6B55",
+			confirmButtonText: "确定",
+			cancelButtonText: "取消",
+			showLoaderOnConfirm: true,
+			animation: true,
+			allowOutsideClick: false
+		}).then(function () {
+			window.post("/system/BounceEmail", { email: email }, function () {
+				swal("邮箱添加到黑名单成功", "", "success");
+			}, (e) => {
+				swal("操作失败,请稍候再试", "", "error");
+			});
+		}, function () { });
 	}
 
 	function del(id) {
-        swal({
-            title: "确定删除这条评论吗?",
-            showCancelButton: true,
-            confirmButtonColor: "#DD6B55",
-            confirmButtonText: "确定",
-            cancelButtonText: "取消",
-            showLoaderOnConfirm: true,
-            animation: true,
-            allowOutsideClick: false
-        }).then(function () {
-            $.post("/comment/delete", {
-                id: id
-            }, function (res) {
-                swal(res.Message, "", res.Success ? "success" : "error");
-                getcomments();
-            });
-        }, function () { });
+		swal({
+			title: "确定删除这条评论吗?",
+			showCancelButton: true,
+			confirmButtonColor: "#DD6B55",
+			confirmButtonText: "确定",
+			cancelButtonText: "取消",
+			showLoaderOnConfirm: true,
+			animation: true,
+			allowOutsideClick: false
+		}).then(function () {
+			$.post("/comment/delete", {
+				id: id
+			}, function (res) {
+				swal(res.Message, "", res.Success ? "success" : "error");
+				getcomments();
+			});
+		}, function () { });
 	}
 
 function showViewer(data) {
-    var html="";
-    for (let item of data) {
-        html+=`<p><a href="/tools/ip/${item.key}" target="_blank">${item.key}</a>:${item.value}</p>`;
-    }
-    layer.open({
-      type: 1,
-      area: ['800px',"60%"], //宽高
-      content: html
-    });
+	var html="";
+	for (let item of data) {
+		html+=`<p><a href="/tools/ip/${item.key}" target="_blank">${item.key}</a>:${item.value}</p>`;
+	}
+	layer.open({
+	  type: 1,
+	  area: ['800px',"60%"], //宽高
+	  content: html
+	});
 }
 </script>

+ 151 - 133
src/Masuit.MyBlogs.Core/Views/Post/PostVisitRecordInsight.cshtml

@@ -1,150 +1,168 @@
 @model Masuit.MyBlogs.Core.Models.Entity.Post
 
 @{
-    Layout = null;
+	Layout = null;
 }
 
 <!DOCTYPE html>
 <html>
 <head>
-    <meta charset="utf-8">
-    <title>文章《@Model.Title》洞察分析</title>
-    <meta content="webkit" name="renderer">
-    <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
-    <meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
-    <link href="/Assets/layui/css/layui.min.css" media="all" rel="stylesheet">
-    <style>
-        .mp-results.mp-bottomleft {
-            top: unset !important;
-            bottom: 0;
-        }
-    </style>
+	<meta charset="utf-8">
+	<title>文章《@Model.Title》洞察分析</title>
+	<meta content="webkit" name="renderer">
+	<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
+	<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
+	<link href="/Assets/layui/css/layui.min.css" media="all" rel="stylesheet">
+	<link href="https://cdn.jsdelivr.net/gh/abodelot/jquery.json-viewer@master/json-viewer/jquery.json-viewer.css" media="all" rel="stylesheet">
+	<style>
+		.mp-results.mp-bottomleft {
+			top: unset !important;
+			bottom: 0;
+		}
+	</style>
 </head>
 <body style="overflow-x: hidden">
-    <h3 align="center">文章《@Model.Title》洞察分析</h3>
-    <div class="searchTable">
-        <div class="layui-inline">
-            <input class="layui-input" name="kw" id="kw">
-        </div>
-        <button class="layui-btn" data-type="reload">搜索</button>
-    </div>
-    <table class="layui-hide" id="table" lay-filter="tableEvent"></table>
-    <div id="chart" style="height: 500px"></div>
-    <mini-profiler max-traces="5" />
+	<h3 align="center">文章《@Model.Title》洞察分析</h3>
+	<div class="searchTable">
+		<div class="layui-inline">
+			<input class="layui-input" name="kw" id="kw">
+		</div>
+		<button class="layui-btn" data-type="reload">搜索</button>
+	</div>
+	<table class="layui-hide" id="table" lay-filter="tableEvent"></table>
+	<div id="chart" style="height: 500px"></div>
+	<mini-profiler max-traces="5" />
 </body>
 </html>
-
+<script type="text/html" id="actionButton">
+  <a class="layui-btn layui-btn-xs" lay-event="showjson">查看</a>
+</script>
+<script src="https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js"></script>
 <script src="/Assets/layui/layui.js"></script>
 <script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js" type="text/javascript"></script>
+<script src="https://cdn.jsdelivr.net/gh/abodelot/jquery.json-viewer@master/json-viewer/jquery.json-viewer.js" type="text/javascript"></script>
 <script>
-    layui.use('table', function() {
-        var table = layui.table;
-        table.render({
-            elem: '#table',
-            url: '/@Model.Id/records',
-            cellMinWidth: 80, //全局定义常规单元格的最小宽度,layui 2.2.1 新增
-            cols: [
-                [
-                    { field: 'IP', title: 'IP', align: 'center', event: 'tool-ip', width:320 },
-                    { field: 'Location', title: '位置和网络', align: 'center'},
-                    { field: 'Referer', title: '页面来源', align: 'center', event: 'visit' },
-                    { field: 'Time', title: '访问时间', align: 'center',width:180 }
-                ]
-            ],
-            page: true,
-            limit:20,
-            request: {
-                limitName: 'size' //每页数据量的参数名,默认:limit
-            },
-            parseData: function(res) { //res 即为原始返回的数据
-                return {
-                    "code": res.TotalCount > 0 ? 0 : 1, //解析接口状态
-                    "msg": "暂无数据", //解析提示文本
-                    "count": res.TotalCount, //解析数据长度
-                    "data": res.Data //解析数据列表
-                };
-            }
-        });
-        table.on('tool(tableEvent)', function(obj){
-            var data = obj.data;
-            if(obj.event === 'tool-ip'){
-                window.open("/tools/ip/"+data.IP);
-            }
-            if(obj.event === 'visit'){
-                window.open(data.Referer);
-            }
-        });
+	layui.use('table', function() {
+		var table = layui.table;
+		table.render({
+			elem: '#table',
+			url: '/@Model.Id/records',
+			cellMinWidth: 80, //全局定义常规单元格的最小宽度,layui 2.2.1 新增
+			cols: [
+				[
+					{ field: 'IP', title: 'IP', align: 'center', event: 'tool-ip', width:320 },
+					{ field: 'Location', title: '位置和网络', align: 'center'},
+					{ field: 'RequestUrl', title: '请求URL', align: 'center' },
+					{ field: 'Referer', title: '页面来源', align: 'center', event: 'visit' },
+					{ field: 'Time', title: '访问时间', align: 'center',width:180 },
+					{ title:'请求头', toolbar: '#actionButton',width:80 }
+				]
+			],
+			page: true,
+			limit:20,
+			request: {
+				limitName: 'size' //每页数据量的参数名,默认:limit
+			},
+			parseData: function(res) { //res 即为原始返回的数据
+				return {
+					"code": res.TotalCount > 0 ? 0 : 1, //解析接口状态
+					"msg": "暂无数据", //解析提示文本
+					"count": res.TotalCount, //解析数据长度
+					"data": res.Data //解析数据列表
+				};
+			}
+		});
+		table.on('tool(tableEvent)', function(obj){
+			var data = obj.data;
+			if(obj.event === 'tool-ip'){
+				window.open("/tools/ip/"+data.IP);
+			}
+
+			if(obj.event === 'visit'){
+				window.open(data.Referer);
+			}
+			
+			if(obj.event === 'showjson'){
+				layer.open({
+				  type: 1,
+				  area: ['600px', '80%'], //宽高
+				  content: ""+data.RequestHeader
+				});
+				$('.layui-layer-content').jsonViewer(eval("("+data.RequestHeader+")"), {withQuotes: true, withLinks: true});
+				$('.layui-layer-content').css("word-wrap"," break-word");
+			}
+		});
 
-        var $ = layui.$;
-        $('.searchTable .layui-btn').on('click', function () {
-            table.reload('table', {
-                page: {
-                    curr: 1
-                },
-                where: {
-                    kw: $('#kw').val()
-                }
-            });
-        });
-    });
-    window.fetch("/@Model.Id/records-chart", {
-        credentials: 'include',
-        method: 'GET',
-        mode: 'cors'
-    }).then(function(response) {
-        return response.json();
-    }).then(function(res) {
-        var data = [];
-        for (let item of res) {
-            data.push([Date.parse(item.Date), item.Count]);
-        }
-        var chartDom = document.getElementById('chart');
-        var myChart = echarts.init(chartDom);
-        var option = {
-            tooltip: {
-                trigger: 'axis',
-                position: function(pt) {
-                    return [pt[0], '10%'];
-                }
-            },
-            title: {
-                left: 'center',
-                text: '最近90天访问趋势,日均:' + (res.reduce((acr, cur) => acr + cur.Count, 0) / (new Date() - new Date(res[0].Date)) * (1000 * 60 * 60 * 24)).toFixed(2)
-            },
-            xAxis: {
-                type: 'time',
-                axisLabel: {
-                    formatter:function (value){
-                        var dt=new Date(value);
-                        return dt.toLocaleDateString();
-                    }
-                }
-            },
-            yAxis: {
-                type: 'value'
-            },
-            series: [
-                {
-                    name: '访问量',
-                    type: 'line',
-                    smooth: true,
-                    symbol: 'none',
-                    areaStyle: {},
-                    data: data,
-                    markPoint: {
-                        data: [
-                            { type: 'max', name: '最大值' },
-                            { type: 'min', name: '最小值' }
-                        ]
-                    },
-                    markLine: {
-                        data: [
-                            { type: 'average', name: '平均值' }
-                        ]
-                    }
-                }
-            ]
-        };
-        myChart.setOption(option);
-    });
+		var $ = layui.$;
+		$('.searchTable .layui-btn').on('click', function () {
+			table.reload('table', {
+				page: {
+					curr: 1
+				},
+				where: {
+					kw: $('#kw').val()
+				}
+			});
+		});
+	});
+	window.fetch("/@Model.Id/records-chart", {
+		credentials: 'include',
+		method: 'GET',
+		mode: 'cors'
+	}).then(function(response) {
+		return response.json();
+	}).then(function(res) {
+		var data = [];
+		for (let item of res) {
+			data.push([Date.parse(item.Date), item.Count]);
+		}
+		var chartDom = document.getElementById('chart');
+		var myChart = echarts.init(chartDom);
+		var option = {
+			tooltip: {
+				trigger: 'axis',
+				position: function(pt) {
+					return [pt[0], '10%'];
+				}
+			},
+			title: {
+				left: 'center',
+				text: '最近90天访问趋势,日均:' + (res.reduce((acr, cur) => acr + cur.Count, 0) / (new Date() - new Date(res[0].Date)) * (1000 * 60 * 60 * 24)).toFixed(2)
+			},
+			xAxis: {
+				type: 'time',
+				axisLabel: {
+					formatter:function (value){
+						var dt=new Date(value);
+						return dt.toLocaleDateString();
+					}
+				}
+			},
+			yAxis: {
+				type: 'value'
+			},
+			series: [
+				{
+					name: '访问量',
+					type: 'line',
+					smooth: true,
+					symbol: 'none',
+					areaStyle: {},
+					data: data,
+					markPoint: {
+						data: [
+							{ type: 'max', name: '最大值' },
+							{ type: 'min', name: '最小值' }
+						]
+					},
+					markLine: {
+						data: [
+							{ type: 'average', name: '平均值' }
+						]
+					}
+				}
+			]
+		};
+		myChart.setOption(option);
+	});
 </script>

+ 2 - 4
src/Masuit.MyBlogs.Core/Views/Shared/_ArticleListItem.cshtml

@@ -42,7 +42,7 @@
                         <a asp-controller="Home" asp-action="Author" asp-route-author="@(Model.Modifier??Model.Author)">@(Model.Modifier??Model.Author)</a>
                     </strong>
                     <span class="text-muted">
-                        | 发表时间:<i class="fa fa-clock-o"></i> @Model.ModifyDate.ToString("yyyy-MM-dd HH:mm") | 分类:<i class="icon-map-pin"></i>
+                        | 更新时间:<i class="fa fa-clock-o"></i> @Model.ModifyDate.ToString("yyyy-MM-dd") | 分类:<i class="icon-map-pin"></i>
                         <a asp-controller="Home" asp-action="Category" asp-route-id="@Model.CategoryId">@Model.CategoryName</a>
                     </span>
                 </div>
@@ -67,9 +67,7 @@
             <div class="col-md-6 pull-right">
                 <div class="small text-right">
                     <i class="fa fa-eye"></i>@online 在看 |
-                    <i class="fa fa-comments-o"></i>@Model.CommentCount 评论 |
-                    <i class="fa fa-eye"></i>@Model.TotalViewCount 浏览 |
-                    <i class="icon-thumbsup"></i>@Model.VoteUpCount 支持
+                    <i class="fa fa-comments-o"></i>@Model.CommentCount 评论
                 </div>
             </div>
         </div>

+ 1 - 1
src/Masuit.MyBlogs.Core/Views/Shared/_ArticleListItem_Admin.cshtml

@@ -43,7 +43,7 @@
                         <a asp-controller="Home" asp-action="Author" asp-route-author="@(Model.Modifier??Model.Author)">@(Model.Modifier??Model.Author)</a>
                     </strong>
                     <span class="text-muted">
-                        | 发表时间:<i class="fa fa-clock-o"></i> @Model.ModifyDate.ToString("yyyy-MM-dd HH:mm") |
+                        | 更新时间:<i class="fa fa-clock-o"></i> @Model.ModifyDate.ToString("yyyy-MM-dd HH:mm") |
                         分类:<i class="icon-map-pin"></i>
                         <a asp-controller="Home" asp-action="Category" asp-route-id="@Model.CategoryId">@Model.CategoryName</a>
                     </span>

+ 147 - 144
src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/post.js

@@ -1,5 +1,5 @@
 myApp.controller("postlist", ["$scope", "$http", "NgTableParams", "$timeout", function ($scope, $http, NgTableParams, $timeout) {
-    var self = this;
+	var self = this;
 	self.stats = [];
 	self.data = {};
 	$scope.kw = "";
@@ -25,27 +25,27 @@
 		}
 	});
 
-    function stat() {
+	function stat() {
 		fetch("/post/Statistic",{
-            headers:{
-                'Accept': 'application/json',
-                'Content-Type': 'application/json'
-            }
-        }).then(function(response) {
-            return response.json();
-        }).then(function(res) {
-		    if(res.Success) {
-			    $scope.agg = res.Data;
-			    $scope.$apply();
-		    } else {
-			    window.notie.alert({
-				    type:3,
-				    text:res.data.Message,
-				    time:4
-			    });
-		    }
-	    });
-    }
+			headers:{
+				'Accept': 'application/json',
+				'Content-Type': 'application/json'
+			}
+		}).then(function(response) {
+			return response.json();
+		}).then(function(res) {
+			if(res.Success) {
+				$scope.agg = res.Data;
+				$scope.$apply();
+			} else {
+				window.notie.alert({
+					type:3,
+					text:res.data.Message,
+					time:4
+				});
+			}
+		});
+	}
 
 	stat();
 	setInterval(stat,5000);
@@ -64,15 +64,15 @@
 				}
 			});
 			
-            var params = JSON.parse(localStorage.getItem("postlist-params"));
-	        if (params) {
-		        $scope.kw = params["kw"];
-		        $scope.paginationConf.currentPage= params["page"];
+			var params = JSON.parse(localStorage.getItem("postlist-params"));
+			if (params) {
+				$scope.kw = params["kw"];
+				$scope.paginationConf.currentPage= params["page"];
 				$timeout(() => {
-                    $('.category').dropdown('set selected', params["cid"]);
-	                $('.orderby').dropdown('set selected', params["orderby"]);
-                },10);
-            }
+					$('.category').dropdown('set selected', params["cid"]);
+					$('.orderby').dropdown('set selected', params["orderby"]);
+				},10);
+			}
 		} else {
 			window.notie.alert({
 				type: 3,
@@ -211,8 +211,8 @@
 		}, 500);
 	}
 	
-    $scope.toggleDisableComment= function(row) {
-        $scope.request("/post/DisableComment", {
+	$scope.toggleDisableComment= function(row) {
+		$scope.request("/post/DisableComment", {
 			id: row.Id
 		}, function(data) {
 			window.notie.alert({
@@ -221,10 +221,10 @@
 				time: 4
 			});
 		});
-    }
+	}
 
-    $scope.toggleDisableCopy= function(row) {
-        $scope.request("/post/DisableCopy", {
+	$scope.toggleDisableCopy= function(row) {
+		$scope.request("/post/DisableCopy", {
 			id: row.Id
 		}, function(data) {
 			window.notie.alert({
@@ -233,38 +233,40 @@
 				time: 4
 			});
 		});
-    }
+	}
 
-    $scope.rssSwitch= function(id) {
-        $scope.request("/post/"+id+"/rss-switch",null, function(data) {
+	$scope.rssSwitch= function(id) {
+		$scope.request("/post/"+id+"/rss-switch",null, function(data) {
 			window.notie.alert({
 				type: 1,
 				text: data.Message,
 				time: 4
 			});
 		});
-    }
+	}
 
-    $scope.lockedSwitch= function(id) {
-        $scope.request("/post/"+id+"/locked-switch",null, function(data) {
+	$scope.lockedSwitch= function(id) {
+		$scope.request("/post/"+id+"/locked-switch",null, function(data) {
 			window.notie.alert({
 				type: 1,
 				text: data.Message,
 				time: 4
 			});
 		});
-    }
+	}
 	self.insight= function(row) {
-        layer.full(layer.open({
-          type: 2,
-          title: '文章《'+row.Title+'》洞察分析',
-          maxmin: true, //开启最大化最小化按钮
-          area: ['893px', '100vh'],
-          content: '/'+row.Id+'/insight'
-        }));
-    }
+		layer.full(layer.open({
+		  type: 2,
+		  title: '文章《'+row.Title+'》洞察分析',
+		  maxmin: true, //开启最大化最小化按钮
+		  area: ['893px', '100vh'],
+		  content: '/'+row.Id+'/insight'
+		}));
+	}
 }]);
 myApp.controller("writeblog", ["$scope", "$http", "$timeout","$location", function ($scope, $http, $timeout,$location) {
+	UEDITOR_CONFIG.autoHeightEnabled=false;
+	UEDITOR_CONFIG.initialFrameHeight=window.innerHeight*0.8;
 	clearInterval(window.interval);
 	$scope.post = {
 		Title: "",
@@ -279,24 +281,24 @@ myApp.controller("writeblog", ["$scope", "$http", "$timeout","$location", functi
 	$scope.post.Author =$scope.user.NickName || $scope.user.Username;
 	$scope.post.Email = $scope.user.Email;
 	var refer = $location.search()['refer'];
-    if (refer) {
-        $scope.request("/post/get", {
-		    id: refer
-	    }, function (data) {
-            $scope.post = data.Data;
+	if (refer) {
+		$scope.request("/post/get", {
+			id: refer
+		}, function (data) {
+			$scope.post = data.Data;
 			delete $scope.post.Id;
-            $('.ui.dropdown.keyword').dropdown({
-			    allowAdditions: true,
-			    onChange: function(value) {
-				    $scope.post.Keyword = value;
-			    }
-		    });
-		    $('.ui.dropdown.keyword').dropdown('set selected', $scope.post.Keyword.split(','));
-	    });
-    }
+			$('.ui.dropdown.keyword').dropdown({
+				allowAdditions: true,
+				onChange: function(value) {
+					$scope.post.Keyword = value;
+				}
+			});
+			$('.ui.dropdown.keyword').dropdown('set selected', $scope.post.Keyword.split(','));
+		});
+	}
 	$scope.getCategory = function () {
-        $http.post("/category/getcategories", null).then(function (res) {
-            var data = res.data;
+		$http.post("/category/getcategories", null).then(function (res) {
+			var data = res.data;
 			if (data.Success) {
 				$scope.cat = data.Data;
 				$('.ui.dropdown.category').dropdown({
@@ -352,11 +354,11 @@ myApp.controller("writeblog", ["$scope", "$http", "$timeout","$location", functi
 	});
 	//上传Word文档
 	$scope.upload = function() {
-        $("#docform").ajaxSubmit({
+		$("#docform").ajaxSubmit({
 			url: "/Upload/UploadWord",
 			type: "post",
 			success: function(data) {
-                console.log(data);
+				console.log(data);
 				if (data.Success) {
 					window.notie.alert({
 						type: 1,
@@ -410,7 +412,7 @@ myApp.controller("writeblog", ["$scope", "$http", "$timeout","$location", functi
 		}
 		$http.post("/Post/write", post).then(function(res) {
 			var data = res.data;
-            if (data.Success) {
+			if (data.Success) {
 				window.notie.alert({
 					type: 1,
 					text: data.Message,
@@ -432,8 +434,8 @@ myApp.controller("writeblog", ["$scope", "$http", "$timeout","$location", functi
 
 	// 定时发布
 	$scope.Scheduled= function() {
-        if ($scope.post.schedule) {
-            jeDate('#timespan',{
+		if ($scope.post.schedule) {
+			jeDate('#timespan',{
 				isinitVal: true,
 				festival: true,
 				isTime: true,
@@ -444,53 +446,54 @@ myApp.controller("writeblog", ["$scope", "$http", "$timeout","$location", functi
 				donefun: function (obj) {
 					$scope.post.timespan = obj.val;
 				},
-		        clearfun: function(elem, val) {
-                    delete $scope.post.timespan;
-                }
+				clearfun: function(elem, val) {
+					delete $scope.post.timespan;
+				}
 			});
-        }
+		}
 	}
 
 	//检查草稿
-    if (localStorage.getItem("write-post-draft")) {
-        notie.confirm({
-            text: "检查到上次有未提交的草稿,是否加载?",
-            submitText: "确定",
-            cancelText: "取消",
-            position: "bottom",
-            submitCallback: function () {
-                $scope.post = JSON.parse(localStorage.getItem("write-post-draft"));
-                $scope.$apply();
-                $timeout(function () {
-                    $('.ui.dropdown.category').dropdown('set selected', [$scope.post.CategoryId]);
-                    if ($scope.post.Label) {
-                        $('.ui.dropdown.tags').dropdown('set selected', $scope.post.Label.split(','));
-                    }
-                    if ($scope.post.Keyword) {
+	if (localStorage.getItem("write-post-draft")) {
+		notie.confirm({
+			text: "检查到上次有未提交的草稿,是否加载?",
+			submitText: "确定",
+			cancelText: "取消",
+			position: "bottom",
+			submitCallback: function () {
+				$scope.post = JSON.parse(localStorage.getItem("write-post-draft"));
+				$scope.$apply();
+				$timeout(function () {
+					$('.ui.dropdown.category').dropdown('set selected', [$scope.post.CategoryId]);
+					if ($scope.post.Label) {
+						$('.ui.dropdown.tags').dropdown('set selected', $scope.post.Label.split(','));
+					}
+					if ($scope.post.Keyword) {
 						$('.ui.dropdown.keyword').dropdown('set selected', $scope.post.Keyword.split(','));
-                    }
-                    if ($scope.post.Seminars) {
-                        $('.ui.dropdown.seminar').dropdown('set selected', $scope.post.Seminars.split(','));
-                    }
-				    $scope.Scheduled();
-                }, 10);
-                window.interval = setInterval(function () {
-		            localStorage.setItem("write-post-draft",JSON.stringify($scope.post));
-	            },5000);
-            },
-            cancelCallback: function() {
-                window.interval = setInterval(function () {
-		            localStorage.setItem("write-post-draft",JSON.stringify($scope.post));
-	            },5000);
-            }
-        });
-    } else {
-        window.interval = setInterval(function () {
-		    localStorage.setItem("write-post-draft",JSON.stringify($scope.post));
-	    },5000);
-    }
+					}
+					if ($scope.post.Seminars) {
+						$('.ui.dropdown.seminar').dropdown('set selected', $scope.post.Seminars.split(','));
+					}
+					$scope.Scheduled();
+				}, 10);
+				window.interval = setInterval(function () {
+					localStorage.setItem("write-post-draft",JSON.stringify($scope.post));
+				},5000);
+			},
+			cancelCallback: function() {
+				window.interval = setInterval(function () {
+					localStorage.setItem("write-post-draft",JSON.stringify($scope.post));
+				},5000);
+			}
+		});
+	} else {
+		window.interval = setInterval(function () {
+			localStorage.setItem("write-post-draft",JSON.stringify($scope.post));
+		},5000);
+	}
 }]);
 myApp.controller("postedit", ["$scope", "$http", "$location", "$timeout", function ($scope, $http, $location, $timeout) {
+	UEDITOR_CONFIG.initialFrameHeight=window.innerHeight*0.72;
 	$scope.id = $location.search()['id'];
 	
 	$scope.reserve = true;
@@ -541,8 +544,8 @@ myApp.controller("postedit", ["$scope", "$http", "$location", "$timeout", functi
 		$('.ui.dropdown.keyword').dropdown('set selected', $scope.post.Keyword.split(','));
 	});
 	$scope.getCategory = function () {
-        $http.post("/category/getcategories", null).then(function (res) {
-            var data = res.data;
+		$http.post("/category/getcategories", null).then(function (res) {
+			var data = res.data;
 			if (data.Success) {
 				$scope.cat = data.Data;
 				$('.ui.dropdown.category').dropdown({
@@ -678,42 +681,42 @@ myApp.controller("postedit", ["$scope", "$http", "$location", "$timeout", functi
 	}
 	
 	//检查草稿
-    if (localStorage.getItem("post-draft-" + $scope.id)) {
-        notie.confirm({
-            text: "检查到上次有未提交的草稿,是否加载?",
-            submitText: "确定",
-            cancelText: "取消",
-            position: "bottom",
-            submitCallback: function () {
-                $scope.post = JSON.parse(localStorage.getItem("post-draft-" + $scope.id));
-                $scope.$apply();
-                $timeout(function () {
-                    $('.ui.dropdown.category').dropdown('set selected', [$scope.post.CategoryId]);
+	if (localStorage.getItem("post-draft-" + $scope.id)) {
+		notie.confirm({
+			text: "检查到上次有未提交的草稿,是否加载?",
+			submitText: "确定",
+			cancelText: "取消",
+			position: "bottom",
+			submitCallback: function () {
+				$scope.post = JSON.parse(localStorage.getItem("post-draft-" + $scope.id));
+				$scope.$apply();
+				$timeout(function () {
+					$('.ui.dropdown.category').dropdown('set selected', [$scope.post.CategoryId]);
 					if ($scope.post.Label) {
-                        $('.ui.dropdown.tags').dropdown('set selected', $scope.post.Label.split(','));
-                    }
-                    if ($scope.post.Keyword) {
+						$('.ui.dropdown.tags').dropdown('set selected', $scope.post.Label.split(','));
+					}
+					if ($scope.post.Keyword) {
 						$('.ui.dropdown.keyword').dropdown('set selected', $scope.post.Keyword.split(','));
-                    }
-                    if ($scope.post.Seminars) {
-                        $('.ui.dropdown.seminar').dropdown('set selected', $scope.post.Seminars.split(','));
-                    }
-                }, 10);
-                window.interval = setInterval(function () {
-			        localStorage.setItem("post-draft-"+$scope.id,JSON.stringify($scope.post));
-		        },5000);
-            },
-            cancelCallback: function() {
-                window.interval = setInterval(function () {
-			        localStorage.setItem("post-draft-"+$scope.id,JSON.stringify($scope.post));
-		        },5000);
-            }
-        });
-    } else {
-        window.interval = setInterval(function () {
+					}
+					if ($scope.post.Seminars) {
+						$('.ui.dropdown.seminar').dropdown('set selected', $scope.post.Seminars.split(','));
+					}
+				}, 10);
+				window.interval = setInterval(function () {
+					localStorage.setItem("post-draft-"+$scope.id,JSON.stringify($scope.post));
+				},5000);
+			},
+			cancelCallback: function() {
+				window.interval = setInterval(function () {
+					localStorage.setItem("post-draft-"+$scope.id,JSON.stringify($scope.post));
+				},5000);
+			}
+		});
+	} else {
+		window.interval = setInterval(function () {
 			localStorage.setItem("post-draft-"+$scope.id,JSON.stringify($scope.post));
 		},5000);
-    }
+	}
 }]);
 myApp.controller("category", ["$scope", "$http", "NgTableParams", function ($scope, $http, NgTableParams) {
 	var self = this;

+ 37 - 35
src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/system.js

@@ -5,6 +5,8 @@ myApp.controller("task", ["$scope", "$http", function ($scope, $http) {
 myApp.controller("dashboard", ["$scope", function ($scope) {
 }]);
 myApp.controller("system", ["$scope", "$http", function($scope, $http) {
+	UEDITOR_CONFIG.autoHeightEnabled=false;
+	UEDITOR_CONFIG.initialFrameHeight=320;
 	$scope.request("/system/getsettings", null, function(data) {
 		var settings = {};
 		Enumerable.From(data.Data).Select(e => {
@@ -18,19 +20,19 @@ myApp.controller("system", ["$scope", "$http", function($scope, $http) {
 		$scope.Settings = settings;
 	});
 	$scope.uploadImage = function() {
-        $("#setImageForm").ajaxSubmit({
+		$("#setImageForm").ajaxSubmit({
 			url: "/Upload",
 			type: "post",
 			success: function(data) {
 				
 				document.getElementById("setImageForm").reset();
 				$scope.$apply(function () {
-			      $scope.Settings[$scope.property] = data.Data;
-			    });
+				  $scope.Settings[$scope.property] = data.Data;
+				});
 				layer.closeAll();
 			}
 		});
-    };
+	};
 	$scope.setImage = function(property) {
 		layer.open({
 			type: 1,
@@ -281,7 +283,7 @@ myApp.controller("email", ["$scope", "$http", function ($scope) {
 	}
 }]);
 myApp.controller("firewall", ["$scope", "$http","NgTableParams","$timeout", function ($scope, $http,NgTableParams,$timeout) {
-    var self = this;
+	var self = this;
 	self.data = {};
 	$scope.request("/system/getsettings", null, function(data) {
 		var settings = {};
@@ -332,7 +334,7 @@ myApp.controller("firewall", ["$scope", "$http","NgTableParams","$timeout", func
 
 	$scope.EnableFirewall= function() {
 		if($scope.Settings.FirewallEnabled=="true") {
-            swal({
+			swal({
 				title: '确定要关闭网站防火墙么?',
 				text: "一旦关闭,网站将面临可能会被流量攻击的风险!",
 				showCancelButton: true,
@@ -342,7 +344,7 @@ myApp.controller("firewall", ["$scope", "$http","NgTableParams","$timeout", func
 				cancelButtonText: '取消',
 			}).then(function(isConfirm) {
 				if (isConfirm) {
-			        $scope.Settings.FirewallEnabled="false";
+					$scope.Settings.FirewallEnabled="false";
 					$scope.$apply();
 				}
 			});
@@ -473,43 +475,43 @@ myApp.controller("firewall", ["$scope", "$http","NgTableParams","$timeout", func
 	}
 
 	$scope.detail= function(text) {
-        layer.open({
-          type: 1,
-          area: ['600px', '80%'], //宽高
-          content: text
-        });
+		layer.open({
+		  type: 1,
+		  area: ['600px', '80%'], //宽高
+		  content: text
+		});
 		$('.layui-layer-content').jsonViewer(eval("("+text+")"), {withQuotes: true, withLinks: true});
 		$('.layui-layer-content').css("word-wrap"," break-word");
-    }
+	}
 
 	$scope.distinct=false;
 	$scope.duplicate= function() {
 		$scope.distinct=!$scope.distinct;
-        if ($scope.distinct) {
-            const res = new Map();
+		if ($scope.distinct) {
+			const res = new Map();
 			self.tableParams = new NgTableParams({}, {
 				filterDelay: 0,
 				dataset: angular.copy($scope.logs).filter(item => !res.has(item["IP"]) && res.set(item["IP"], 1))
 			});
-        } else {
+		} else {
 			self.tableParams = new NgTableParams({}, {
 				filterDelay: 0,
 				dataset: $scope.logs
 			});
-        }
-    }
+		}
+	}
 }]);
 
 myApp.controller("sendbox", ["$scope", "$http", function ($scope, $http) {
 	UEDITOR_CONFIG.autoHeightEnabled=false;
 	$scope.load= function() {
-        $http.post("/system/sendbox").then(function (res) {
-		    $scope.Mails = res.data;
-	    });
-    };
+		$http.post("/system/sendbox").then(function (res) {
+			$scope.Mails = res.data;
+		});
+	};
 
 	$scope.newmail= function() {
-        layer.open({
+		layer.open({
 			type: 1,
 			zIndex: 8,
 			title: '发送邮件',
@@ -519,24 +521,24 @@ myApp.controller("sendbox", ["$scope", "$http", function ($scope, $http) {
 				$("#modal").css("display", "none");
 			}
 		});
-    }
+	}
 
 	$scope.send= function(mail) {
-        $http.post("/system/sendmail",mail, {
+		$http.post("/system/sendmail",mail, {
 			'Content-Type':'application/x-www-form-urlencoded'
 		}).then(function (res) {
-            if (res.data) {
-                layer.alert(res.data.Message);
-            } else {
-                layer.msg('发送成功');
+			if (res.data) {
+				layer.alert(res.data.Message);
+			} else {
+				layer.msg('发送成功');
 				layer.closeAll();
 				setTimeout(function() {
-			        $("#modal").css("display", "none");
-	                $scope.load();
-		        }, 500);
-            }
-	    });
-    }
+					$("#modal").css("display", "none");
+					$scope.load();
+				}, 500);
+			}
+		});
+	}
 
 	$scope.load();
 }]);

+ 1 - 0
src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/values.js

@@ -1,5 +1,6 @@
 myApp.controller("values", ["$scope", "$http", "NgTableParams", function ($scope, $http, NgTableParams) {
 	UEDITOR_CONFIG.autoHeightEnabled=false;
+	UEDITOR_CONFIG.initialFrameHeight=320;
 	var self = this;
 	self.data = {};
 	this.load = function() {

+ 1 - 1
src/Masuit.MyBlogs.Core/wwwroot/ng-views/views/partner.html

@@ -56,7 +56,7 @@
                 {{row.ViewCount}}
             </td>
             <td title="'日均点击'">
-                {{row.AverageViewCount}}
+                {{row.AverageViewCount|number:2}}
             </td>
             <td title="'分类'" style="max-width: 220px">
                 {{row.CategoryNames}}

+ 1 - 1
src/Masuit.MyBlogs.Core/wwwroot/ng-views/views/post/edit.html

@@ -169,7 +169,7 @@
         </div>
     </div>
 </form>
-<div style="position: absolute; left: -20000px;">
+<div style="position: absolute; left: -20000px;height:0;overflow:hidden;">
     <div id="docfile">
         <form id="docform" onsubmit="return false" enctype="multipart/form-data">
             <h4 class="h4">注意:重复上传将会覆盖之前上传的内容!</h4>

+ 1 - 1
src/Masuit.MyBlogs.Core/wwwroot/ng-views/views/post/writeblog.html

@@ -191,7 +191,7 @@
         </div>
     </div>
 </form>
-<div style="position: absolute; left: -20000px; ">
+<div style="position: absolute; left: -20000px; height: 0; overflow: hidden; ">
     <div id="docfile">
         <form id="docform" onsubmit="return false" enctype="multipart/form-data">
             <h4 class="h4">注意:重复上传将会覆盖之前上传的内容!</h4>