Jelajahi Sumber

1.草稿箱支持
2.文章页的模块顺序调整
3.文章详情页的性能优化
4.搜索性能优化
5.搜索页优化
6.https为可选配置
7.远程图片的抓取设置

懒得勤快 6 tahun lalu
induk
melakukan
ef6717e155
26 mengubah file dengan 229 tambahan dan 130 penghapusan
  1. 1 8
      src/Masuit.MyBlogs.Core/Configs/AppConfig.cs
  2. 1 0
      src/Masuit.MyBlogs.Core/Configs/RegisterAutomapper.cs
  3. 4 3
      src/Masuit.MyBlogs.Core/Controllers/PostController.cs
  4. 5 4
      src/Masuit.MyBlogs.Core/Controllers/SearchController.cs
  5. 5 1
      src/Masuit.MyBlogs.Core/Controllers/SubscribeController.cs
  6. 15 1
      src/Masuit.MyBlogs.Core/Extensions/Hangfire/HangfireBackJob.cs
  7. 1 0
      src/Masuit.MyBlogs.Core/Extensions/Hangfire/IpIntercepter.cs
  8. 1 2
      src/Masuit.MyBlogs.Core/Extensions/UEditor/CrawlerHandler.cs
  9. 18 2
      src/Masuit.MyBlogs.Core/Infrastructure/Services/PostService.cs
  10. 5 9
      src/Masuit.MyBlogs.Core/Masuit.MyBlogs.Core.csproj
  11. 15 15
      src/Masuit.MyBlogs.Core/Masuit.MyBlogs.Core.xml
  12. 0 5
      src/Masuit.MyBlogs.Core/Models/DTO/PostOutputDto.cs
  13. 1 1
      src/Masuit.MyBlogs.Core/Models/Entity/PostHistoryVersion.cs
  14. 1 10
      src/Masuit.MyBlogs.Core/Models/ViewModel/PostDataModel.cs
  15. 15 0
      src/Masuit.MyBlogs.Core/Models/ViewModel/PostModelBase.cs
  16. 0 5
      src/Masuit.MyBlogs.Core/Models/ViewModel/PostViewModel.cs
  17. 6 3
      src/Masuit.MyBlogs.Core/Program.cs
  18. 11 2
      src/Masuit.MyBlogs.Core/Startup.cs
  19. 20 20
      src/Masuit.MyBlogs.Core/Views/Post/Details.cshtml
  20. 19 19
      src/Masuit.MyBlogs.Core/Views/Post/Details_Admin.cshtml
  21. 2 2
      src/Masuit.MyBlogs.Core/Views/Search/Search.cshtml
  22. 6 14
      src/Masuit.MyBlogs.Core/appsettings.json
  23. 17 1
      src/Masuit.MyBlogs.Core/ueconfig.json
  24. 3 1
      src/Masuit.MyBlogs.Core/wwwroot/Assets/UEditor/ueditor.config.admin.js
  25. 53 1
      src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/post.js
  26. 4 1
      src/Masuit.MyBlogs.Core/wwwroot/ng-views/views/system/firewall.html

+ 1 - 8
src/Masuit.MyBlogs.Core/Configs/AppConfig.cs

@@ -1,6 +1,4 @@
-using System.Collections.Generic;
-
-namespace Masuit.MyBlogs.Core.Configs
+namespace Masuit.MyBlogs.Core.Configs
 {
     /// <summary>
     /// 应用程序配置
@@ -36,10 +34,5 @@ namespace Masuit.MyBlogs.Core.Configs
         /// 码云图床配置
         /// </summary>
         public static GitlabConfig GiteeConfig { get; set; } = new GitlabConfig();
-
-        /// <summary>
-        /// 图床域名
-        /// </summary>
-        public static List<string> ImgbedDomains { get; set; } = new List<string>();
     }
 }

+ 1 - 0
src/Masuit.MyBlogs.Core/Configs/RegisterAutomapper.cs

@@ -56,6 +56,7 @@ namespace Masuit.MyBlogs.Core.Configs
                 m.CreateMap<Notice, NoticeViewModel>().ForMember(c => c.PostDate, e => e.MapFrom(c => c.PostDate.ToString("yyyy-MM-dd HH:mm:ss"))).ForMember(c => c.ModifyDate, e => e.MapFrom(c => c.ModifyDate.ToString("yyyy-MM-dd HH:mm:ss"))).ReverseMap();
 
                 m.CreateMap<Post, PostInputDto>().ReverseMap();
+                m.CreateMap<Post, PostModelBase>();
                 m.CreateMap<Post, PostHistoryVersion>().ForMember(v => v.PostId, e => e.MapFrom(p => p.Id));
                 m.CreateMap<Post, PostOutputDto>().ForMember(p => p.CategoryName, e => e.MapFrom(p => p.Category.Name)).ForMember(p => p.CommentCount, e => e.MapFrom(p => p.Comment.Count(c => c.Status == Status.Pended))).ReverseMap();
                 m.CreateMap<PostInputDto, PostOutputDto>().ReverseMap();

+ 4 - 3
src/Masuit.MyBlogs.Core/Controllers/PostController.cs

@@ -76,7 +76,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <param name="id"></param>
         /// <param name="kw"></param>
         /// <returns></returns>
-        [Route("{id:int}/{kw}"), Route("{id:int}"), ResponseCache(Duration = 600, VaryByQueryKeys = new[] { "id", "kw" }, VaryByHeader = HeaderNames.Cookie)]
+        [Route("{id:int}/{kw}"), Route("{id:int}"), ResponseCache(Duration = 600, VaryByQueryKeys = new[] { "id" }, VaryByHeader = HeaderNames.Cookie)]
         public ActionResult Details(int id, string kw)
         {
             Post post = PostService.GetById(id);
@@ -85,12 +85,13 @@ namespace Masuit.MyBlogs.Core.Controllers
                 ViewBag.Keyword = post.Keyword + "," + post.Label;
                 UserInfoOutputDto user = HttpContext.Session.Get<UserInfoOutputDto>(SessionKey.UserInfo) ?? new UserInfoOutputDto();
                 DateTime modifyDate = post.ModifyDate;
-                ViewBag.Next = PostService.GetFirstEntityNoTracking(p => p.ModifyDate > modifyDate && (p.Status == Status.Pended || user.IsAdmin), p => p.ModifyDate);
-                ViewBag.Prev = PostService.GetFirstEntityNoTracking(p => p.ModifyDate < modifyDate && (p.Status == Status.Pended || user.IsAdmin), p => p.ModifyDate, false);
+                ViewBag.Next = PostService.GetFirstEntity<DateTime, PostModelBase>(p => p.ModifyDate > modifyDate && (p.Status == Status.Pended || user.IsAdmin), p => p.ModifyDate);
+                ViewBag.Prev = PostService.GetFirstEntity<DateTime, PostModelBase>(p => p.ModifyDate < modifyDate && (p.Status == Status.Pended || user.IsAdmin), p => p.ModifyDate, false);
                 if (!string.IsNullOrEmpty(kw))
                 {
                     ViewData["keywords"] = post.Content.Contains(kw) ? $"['{kw}']" : _searchEngine.LuceneIndexSearcher.CutKeywords(kw).ToJsonString();
                 }
+
                 if (user.IsAdmin)
                 {
                     return View("Details_Admin", post);

+ 5 - 4
src/Masuit.MyBlogs.Core/Controllers/SearchController.cs

@@ -45,12 +45,13 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <param name="page"></param>
         /// <param name="size"></param>
         /// <returns></returns>
-        [Route("s/{wd?}/{page:int?}/{size:int?}"), ResponseCache(VaryByQueryKeys = new[] { "wd", "page", "size" }, VaryByHeader = HeaderNames.Cookie, Duration = 60)]
-        public ActionResult Search(string wd = "", int page = 1, int size = 10)
+        [Route("s/{wd?}/{page:int?}/{size:int?}")]
+        public ActionResult Search(string wd = "", int page = 1, int size = 15)
         {
             var nul = new List<PostOutputDto>();
             ViewBag.Elapsed = 0;
             ViewBag.Total = 0;
+            ViewBag.PageSize = size;
             ViewBag.Keyword = wd;
             if (Regex.Match(wd ?? "", CommonHelper.BanRegex + "|" + CommonHelper.ModRegex).Length > 0)
             {
@@ -66,7 +67,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                 return View(nul);
             }
 
-            wd = wd.Trim().Replace("+", " ");
+            wd = wd?.Trim().Replace("+", " ");
             if (!string.IsNullOrWhiteSpace(wd) && !wd.Contains("锟斤拷"))
             {
                 if (!HttpContext.Session.TryGetValue("search:" + wd, out _) && !HttpContext.Request.IsRobot())
@@ -77,13 +78,13 @@ namespace Masuit.MyBlogs.Core.Controllers
                         SearchTime = DateTime.Now,
                         IP = HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString()
                     });
+                    SearchDetailsService.SaveChanges();
                     HttpContext.Session.Set("search:" + wd, wd.ToByteArray());
                 }
 
                 var posts = _postService.SearchPage(page, size, wd);
                 ViewBag.Elapsed = posts.Elapsed;
                 ViewBag.Total = posts.Total;
-                SearchDetailsService.SaveChanges();
                 if (posts.Total > 1)
                 {
                     RedisHelper.Set(key, wd);

+ 5 - 1
src/Masuit.MyBlogs.Core/Controllers/SubscribeController.cs

@@ -17,6 +17,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Net;
+using System.Text;
 using WilderMinds.RssSyndication;
 
 namespace Masuit.MyBlogs.Core.Controllers
@@ -107,7 +108,10 @@ namespace Masuit.MyBlogs.Core.Controllers
                 Copyright = "(c) 2019"
             };
             feed.Items.AddRange(posts.ToArray());
-            var rss = feed.Serialize();
+            var rss = feed.Serialize(new SerializeOption()
+            {
+                Encoding = Encoding.UTF8
+            });
             return Content(rss, "text/xml");
         }
 

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

@@ -1,10 +1,12 @@
-using Masuit.LuceneEFCore.SearchEngine.Interfaces;
+using IP2Region;
+using Masuit.LuceneEFCore.SearchEngine.Interfaces;
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Infrastructure;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.DTO;
 using Masuit.MyBlogs.Core.Models.Entity;
 using Masuit.MyBlogs.Core.Models.Enum;
+using Masuit.Tools;
 using Masuit.Tools.Core.Net;
 using Masuit.Tools.Systems;
 using Microsoft.AspNetCore.Hosting;
@@ -130,6 +132,18 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
         public static void InterceptLog(IpIntercepter s)
         {
             RedisHelper.IncrBy("interceptCount");
+            var result = s.IP.GetPhysicsAddressInfo().Result;
+            if (result.Status == 0)
+            {
+                s.Address = result.AddressResult.FormattedAddress;
+            }
+            else
+            {
+                using (DbSearcher searcher = new DbSearcher(Path.Combine(AppContext.BaseDirectory + "App_Data", "ip2region.db")))
+                {
+                    s.Address = searcher.MemorySearch(s.IP).Region;
+                }
+            }
             RedisHelper.LPush("intercept", s);
         }
 

+ 1 - 0
src/Masuit.MyBlogs.Core/Extensions/Hangfire/IpIntercepter.cs

@@ -6,6 +6,7 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
     {
         public string IP { get; set; }
         public string RequestUrl { get; set; }
+        public string Address { get; set; }
         public DateTime Time { get; set; }
     }
 }

+ 1 - 2
src/Masuit.MyBlogs.Core/Extensions/UEditor/CrawlerHandler.cs

@@ -1,5 +1,4 @@
 using Masuit.MyBlogs.Core.Common;
-using Masuit.MyBlogs.Core.Configs;
 using Masuit.Tools;
 using Microsoft.AspNetCore.Http;
 using System;
@@ -59,7 +58,7 @@ namespace Masuit.MyBlogs.Core.Extensions.UEditor
 
         public Crawler Fetch()
         {
-            if (!SourceUrl.IsExternalAddress() || SourceUrl.Contains(AppConfig.ImgbedDomains))
+            if (!SourceUrl.IsExternalAddress())
             {
                 State = "INVALID_URL";
                 return this;

+ 18 - 2
src/Masuit.MyBlogs.Core/Infrastructure/Services/PostService.cs

@@ -6,6 +6,7 @@ using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.DTO;
 using Masuit.MyBlogs.Core.Models.Entity;
 using Masuit.MyBlogs.Core.Models.Enum;
+using Microsoft.Extensions.Caching.Memory;
 using PanGu;
 using PanGu.HighLight;
 using System;
@@ -18,11 +19,21 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
 {
     public partial class PostService : BaseService<Post>, IPostService
     {
-        public PostService(IPostRepository repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
+        private readonly IMemoryCache _memoryCache;
+
+        public PostService(IPostRepository repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher, IMemoryCache memoryCache) : base(repository, searchEngine, searcher)
         {
+            _memoryCache = memoryCache;
         }
+
         public SearchResult<PostOutputDto> SearchPage(int page, int size, string keyword)
         {
+            var cacheKey = $"search:{keyword}:{page}:{size}";
+            if (_memoryCache.TryGetValue<SearchResult<PostOutputDto>>(cacheKey, out var value))
+            {
+                return value;
+            }
+
             var searchResult = _searchEngine.ScoredSearch<Post>(new SearchOptions(keyword, page, size, typeof(Post)));
             var posts = searchResult.Results.Select(p => p.Entity.Mapper<PostOutputDto>()).Where(p => p.Status == Status.Pended).ToList();
             var simpleHtmlFormatter = new SimpleHTMLFormatter("<span style='color:red;background-color:yellow;font-size: 1.1em;font-weight:700;'>", "</span>");
@@ -39,6 +50,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
                         break;
                     }
                 }
+
                 bool handled = false;
                 foreach (var s in keywords)
                 {
@@ -50,17 +62,21 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
                         break;
                     }
                 }
+
                 if (p.Content.Length > 200 && !handled)
                 {
                     p.Content = p.Content.Substring(0, 200);
                 }
             }
-            return new SearchResult<PostOutputDto>()
+
+            var result = new SearchResult<PostOutputDto>()
             {
                 Results = posts,
                 Elapsed = searchResult.Elapsed,
                 Total = searchResult.TotalHits
             };
+
+            return _memoryCache.Set(cacheKey, result, TimeSpan.FromHours(1));
         }
 
         /// <summary>

+ 5 - 9
src/Masuit.MyBlogs.Core/Masuit.MyBlogs.Core.csproj

@@ -16,10 +16,6 @@
     <DocumentationFile>.\Masuit.MyBlogs.Core.xml</DocumentationFile>
   </PropertyGroup>
 
-  <ItemGroup>
-    <Compile Remove="Controllers\TestController.cs" />
-  </ItemGroup>
-
   <ItemGroup>
     <Content Remove="bundleconfig.json" />
   </ItemGroup>
@@ -32,11 +28,11 @@
     <PackageReference Include="AutoMapper" Version="8.1.1" />
     <PackageReference Include="CacheManager.Microsoft.Extensions.Caching.Memory" Version="1.2.0" />
     <PackageReference Include="CacheManager.Serialization.Json" Version="1.2.0" />
-    <PackageReference Include="CSRedisCore" Version="3.0.60" />
-    <PackageReference Include="EFSecondLevelCache.Core" Version="2.3.1" />
+    <PackageReference Include="CSRedisCore" Version="3.0.62" />
+    <PackageReference Include="EFSecondLevelCache.Core" Version="2.4.1" />
     <PackageReference Include="Hangfire" Version="1.7.3" />
     <PackageReference Include="Hangfire.Autofac" Version="2.3.1" />
-    <PackageReference Include="Hangfire.MemoryStorage" Version="1.6.0" />
+    <PackageReference Include="Hangfire.MemoryStorage" Version="1.6.1" />
     <PackageReference Include="Hangfire.Redis.StackExchange" Version="1.8.0" />
     <PackageReference Include="htmldiff.net-core" Version="1.3.6" />
     <PackageReference Include="IP2Region" Version="1.2.0" />
@@ -47,8 +43,8 @@
     <PackageReference Include="Polly" Version="7.1.0" />
     <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" />
     <PackageReference Include="WilderMinds.RssSyndication" Version="1.5.0" />
-    <PackageReference Include="Z.EntityFramework.Extensions.EFCore" Version="2.4.0" />
-    <PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="1.10.0" />
+    <PackageReference Include="Z.EntityFramework.Extensions.EFCore" Version="2.6.1" />
+    <PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="2.0.3" />
     <PackageReference Include="Z.ExtensionMethods" Version="2.1.1" />
   </ItemGroup>
 

+ 15 - 15
src/Masuit.MyBlogs.Core/Masuit.MyBlogs.Core.xml

@@ -291,11 +291,6 @@
             码云图床配置
             </summary>
         </member>
-        <member name="P:Masuit.MyBlogs.Core.Configs.AppConfig.ImgbedDomains">
-            <summary>
-            图床域名
-            </summary>
-        </member>
         <member name="T:Masuit.MyBlogs.Core.Configs.HangfireJobInit">
             <summary>
             hangfire配置
@@ -7106,16 +7101,6 @@
             文章数据模型
             </summary>
         </member>
-        <member name="P:Masuit.MyBlogs.Core.Models.ViewModel.PostDataModel.Id">
-            <summary>
-            id
-            </summary>
-        </member>
-        <member name="P:Masuit.MyBlogs.Core.Models.ViewModel.PostDataModel.Title">
-            <summary>
-            标题
-            </summary>
-        </member>
         <member name="P:Masuit.MyBlogs.Core.Models.ViewModel.PostDataModel.Author">
             <summary>
             作者
@@ -7176,6 +7161,16 @@
             修改次数
             </summary>
         </member>
+        <member name="P:Masuit.MyBlogs.Core.Models.ViewModel.PostModelBase.Id">
+            <summary>
+            id
+            </summary>
+        </member>
+        <member name="P:Masuit.MyBlogs.Core.Models.ViewModel.PostModelBase.Title">
+            <summary>
+            标题
+            </summary>
+        </member>
         <member name="T:Masuit.MyBlogs.Core.Models.ViewModel.PostViewModel">
             <summary>
             文章视图模型
@@ -7301,6 +7296,11 @@
             依赖注入容器
             </summary>
         </member>
+        <member name="P:Masuit.MyBlogs.Core.Startup.Configuration">
+            <summary>
+            配置中心
+            </summary>
+        </member>
         <member name="M:Masuit.MyBlogs.Core.Startup.#ctor(Microsoft.Extensions.Configuration.IConfiguration)">
             <summary>
             asp.net core核心配置

+ 0 - 5
src/Masuit.MyBlogs.Core/Models/DTO/PostOutputDto.cs

@@ -7,11 +7,6 @@ namespace Masuit.MyBlogs.Core.Models.DTO
     /// </summary>
     public class PostOutputDto : BaseDto
     {
-        //public PostOutputDto()
-        //{
-        //    Comment = new HashSet<CommentOutputDto>();
-        //}
-
         /// <summary>
         /// 标题
         /// </summary>

+ 1 - 1
src/Masuit.MyBlogs.Core/Models/Entity/PostHistoryVersion.cs

@@ -25,7 +25,7 @@ namespace Masuit.MyBlogs.Core.Models.Entity
         /// <summary>
         /// ±êÌâ
         /// </summary>
-        [Required, StringLength(64)]
+        [Required, StringLength(128)]
         public string Title { get; set; }
 
         /// <summary>

+ 1 - 10
src/Masuit.MyBlogs.Core/Models/ViewModel/PostDataModel.cs

@@ -3,18 +3,9 @@
     /// <summary>
     /// 文章数据模型
     /// </summary>
-    public class PostDataModel
+    public class PostDataModel : PostModelBase
     {
-        /// <summary>
-        /// id
-        /// </summary>
-        public int Id { get; set; }
-
         public string Status { get; set; }
-        /// <summary>
-        /// 标题
-        /// </summary>
-        public string Title { get; set; }
 
         /// <summary>
         /// 作者

+ 15 - 0
src/Masuit.MyBlogs.Core/Models/ViewModel/PostModelBase.cs

@@ -0,0 +1,15 @@
+namespace Masuit.MyBlogs.Core.Models.ViewModel
+{
+    public class PostModelBase
+    {
+        /// <summary>
+        /// id
+        /// </summary>
+        public int Id { get; set; }
+
+        /// <summary>
+        /// 标题
+        /// </summary>
+        public string Title { get; set; }
+    }
+}

+ 0 - 5
src/Masuit.MyBlogs.Core/Models/ViewModel/PostViewModel.cs

@@ -8,11 +8,6 @@ namespace Masuit.MyBlogs.Core.Models.ViewModel
     /// </summary>
     public class PostViewModel : BaseEntity
     {
-        //public PostViewModel()
-        //{
-        //    Comment = new HashSet<CommentViewModel>();
-        //}
-
         /// <summary>
         /// 标题
         /// </summary>

+ 6 - 3
src/Masuit.MyBlogs.Core/Program.cs

@@ -28,10 +28,13 @@ namespace Masuit.MyBlogs.Core
             return WebHost.CreateDefaultBuilder(args).UseKestrel(opt =>
             {
                 opt.ListenAnyIP(port.ToInt32());
-                opt.ListenAnyIP(sslport.ToInt32(), s =>
+                if (bool.Parse(config["Https:Enabled"]))
                 {
-                    s.UseHttps(AppContext.BaseDirectory + config["cert:path"], config["cert:password"]);
-                });
+                    opt.ListenAnyIP(sslport.ToInt32(), s =>
+                    {
+                        s.UseHttps(AppContext.BaseDirectory + config["Https:CertPath"], config["Https:CertPassword"]);
+                    });
+                }
                 opt.Limits.MaxRequestBodySize = null;
             }).UseIISIntegration().UseStartup<Startup>();
         }

+ 11 - 2
src/Masuit.MyBlogs.Core/Startup.cs

@@ -58,19 +58,24 @@ namespace Masuit.MyBlogs.Core
         /// </summary>
         public static IServiceProvider AutofacContainer { get; set; }
 
+        /// <summary>
+        /// 配置中心
+        /// </summary>
+        public IConfiguration Configuration { get; set; }
+
         /// <summary>
         /// asp.net core核心配置
         /// </summary>
         /// <param name="configuration"></param>
         public Startup(IConfiguration configuration)
         {
+            Configuration = configuration;
             AppConfig.ConnString = configuration[nameof(AppConfig.ConnString)];
             AppConfig.BaiduAK = configuration[nameof(AppConfig.BaiduAK)];
             AppConfig.Redis = configuration[nameof(AppConfig.Redis)];
             configuration.Bind("Imgbed:AliyunOSS", AppConfig.AliOssConfig);
             configuration.Bind("Imgbed:Gitlab", AppConfig.GitlabConfig);
             configuration.Bind("Imgbed:Gitee", AppConfig.GiteeConfig);
-            configuration.Bind("Imgbed:ImgbedDomains", AppConfig.ImgbedDomains);
         }
 
         /// <summary>
@@ -190,7 +195,11 @@ namespace Masuit.MyBlogs.Core
             ConfigureLuceneSearch(env, hangfire, luceneIndexerOptions);
 
             app.UseResponseCompression();
-            app.UseHttpsRedirection().UseRewriter(new RewriteOptions().AddRedirectToNonWww()); // URL重写
+            if (bool.Parse(Configuration["Https:Enabled"]))
+            {
+                app.UseHttpsRedirection().UseRewriter(new RewriteOptions().AddRedirectToNonWww()); // URL重写
+            }
+
             app.UseStaticHttpContext(); //注入静态HttpContext对象
             app.UseSession().UseCookiePolicy(); //注入Session
 

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

@@ -3,6 +3,7 @@
 @using Masuit.MyBlogs.Core.Common
 @using Masuit.MyBlogs.Core.Models.Entity
 @using Masuit.MyBlogs.Core.Models.Enum
+@using Masuit.MyBlogs.Core.Models.ViewModel
 @using Masuit.Tools.Core.Net
 @model Masuit.MyBlogs.Core.Models.Entity.Post
 @{
@@ -146,30 +147,12 @@
                             }
                         </div>
                     </div>
-
-                </section>
-                @if (Model.PostHistoryVersion.Any())
-                {
-                    <section class="wow margintop20 animated fadeIn">
-                        <h3>文章历史版本:</h3>
-                        <p>
-                            修改次数:@Model.PostHistoryVersion.Count 次
-                            @Html.ActionLink("查看历史版本", "History", "Post", new { id = Model.Id }, null)
-                        </p>
-                    </section>
-                }
-                <section class="wow padding-bot20 animated fadeIn">
-                    <h3>版权声明:</h3>
-                    <p class="text-danger size16">
-                        本文仅用于学习、研究和交流目的,欢迎非商业性质转载。本文链接:<a href="@(Context.Request.Scheme + "://" +Context.Request.Host+Context.Request.Path)">@(HttpUtility.UrlDecode(Context.Request.Scheme + "://" + Context.Request.Host + Context.Request.Path))</a>。
-                        @Html.Raw(CommonHelper.SystemSettings["Disclaimer"])
-                    </p>
                 </section>
                 <section class="wow fadeInUp row size16">
                     <div class="col-xs-6">
                         上一篇:
                         @{
-                            Post prev = ViewBag.Prev;
+                            PostModelBase prev = ViewBag.Prev;
                             if (prev != null)
                             {
                                 @Html.ActionLink(prev.Title, "Details", "Post", new { id = prev.Id }, null)
@@ -183,7 +166,7 @@
                     <div class="col-xs-6 text-right">
                         下一篇:
                         @{
-                            Post next = ViewBag.Next;
+                            PostModelBase next = ViewBag.Next;
                             if (next != null)
                             {
                                 @Html.ActionLink(next.Title, "Details", "Post", new { id = next.Id }, null)
@@ -195,6 +178,23 @@
                         }
                     </div>
                 </section>
+                @if (Model.PostHistoryVersion.Any())
+                {
+                    <section class="wow margintop20 animated fadeIn">
+                        <h3>文章历史版本:</h3>
+                        <p>
+                            修改次数:@Model.PostHistoryVersion.Count 次
+                            @Html.ActionLink("查看历史版本", "History", "Post", new { id = Model.Id }, null)
+                        </p>
+                    </section>
+                }
+                <section class="wow padding-bot20 animated fadeIn">
+                    <h3>版权声明:</h3>
+                    <p class="text-danger size16">
+                        本文仅用于学习、研究和交流目的,欢迎非商业性质转载。本文链接:<a href="@(Context.Request.Scheme + "://" +Context.Request.Host+Context.Request.Path)">@(HttpUtility.UrlDecode(Context.Request.Scheme + "://" + Context.Request.Host + Context.Request.Path))</a>。
+                        @Html.Raw(CommonHelper.SystemSettings["Disclaimer"])
+                    </p>
+                </section>
                 @{
                     var posts = Model.Category.Post.Where(p => p.Status == Status.Pended && p.Id != Model.Id).OrderBy(p => Guid.NewGuid()).ToList();
                     int count = posts.Count >= 10 ? 10 : posts.Count;

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

@@ -130,28 +130,11 @@
                         </div>
                     </div>
                 </section>
-                @if (Model.PostHistoryVersion.Any())
-                {
-                    <section class="wow margintop20 animated fadeIn">
-                        <h3>文章历史版本:</h3>
-                        <p>
-                            修改次数:@Model.PostHistoryVersion.Count 次
-                            @Html.ActionLink("查看历史版本", "History", "Post", new { id = Model.Id }, null)
-                        </p>
-                    </section>
-                }
-                <section class="wow padding-bot20 animated fadeIn">
-                    <h3>版权声明:</h3>
-                    <p class="text-danger size16">
-                        本文仅用于学习、研究和交流目的,欢迎非商业性质转载。本文链接:<a href="@(Context.Request.Scheme + "://" +Context.Request.Host+Context.Request.Path)">@(HttpUtility.UrlDecode(Context.Request.Scheme + "://" + Context.Request.Host + Context.Request.Path))</a>。
-                        @Html.Raw(CommonHelper.SystemSettings["Disclaimer"])
-                    </p>
-                </section>
                 <section class="wow row size16 animated fadeIn">
                     <div class="col-xs-6">
                         上一篇:
                         @{
-                            Post prev = ViewBag.Prev;
+                            PostModelBase prev = ViewBag.Prev;
                             if (prev != null)
                             {
                                 @Html.ActionLink(prev.Title, "Details", "Post", new { id = prev.Id }, null)
@@ -165,7 +148,7 @@
                     <div class="col-xs-6 text-right">
                         下一篇:
                         @{
-                            Post next = ViewBag.Next;
+                            PostModelBase next = ViewBag.Next;
                             if (next != null)
                             {
                                 @Html.ActionLink(next.Title, "Details", "Post", new { id = next.Id }, null)
@@ -177,6 +160,23 @@
                         }
                     </div>
                 </section>
+                @if (Model.PostHistoryVersion.Any())
+                {
+                    <section class="wow margintop20 animated fadeIn">
+                        <h3>文章历史版本:</h3>
+                        <p>
+                            修改次数:@Model.PostHistoryVersion.Count 次
+                            @Html.ActionLink("查看历史版本", "History", "Post", new { id = Model.Id }, null)
+                        </p>
+                    </section>
+                }
+                <section class="wow padding-bot20 animated fadeIn">
+                    <h3>版权声明:</h3>
+                    <p class="text-danger size16">
+                        本文仅用于学习、研究和交流目的,欢迎非商业性质转载。本文链接:<a href="@(Context.Request.Scheme + "://" +Context.Request.Host+Context.Request.Path)">@(HttpUtility.UrlDecode(Context.Request.Scheme + "://" + Context.Request.Host + Context.Request.Path))</a>。
+                        @Html.Raw(CommonHelper.SystemSettings["Disclaimer"])
+                    </p>
+                </section>
                 @{
                     var posts = Model.Category.Post.Where(p => p.Status == Status.Pended && p.Id != Model.Id).OrderBy(p => Guid.NewGuid()).ToList();
                     int count = posts.Count >= 10 ? 10 : posts.Count;

+ 2 - 2
src/Masuit.MyBlogs.Core/Views/Search/Search.cshtml

@@ -41,7 +41,7 @@
                                 <span>搜索推荐:</span>
                                 foreach (var item in hotSearches)
                                 {
-                                    @Html.ActionLink(item.Keywords + "(" + item.Count + ")", "Search", new { wd = item.Keywords }, new { @class = "btn btn-danger" }) <span>  </span>
+                                    @Html.ActionLink(item.Keywords + "(" + item.Count + ")", "Search", new { wd = item.Keywords }, new { @class = "label label-danger" }) <span>  </span>
                                 }
                             }
                         </div>
@@ -70,7 +70,7 @@
                         @*下面是分页组件*@
                         @{
                             int count = ViewBag.Total;
-                            var size = Context.Request.Query["size"].ToString().ToInt32();
+                            int size = ViewBag.PageSize;
                             int pages = Math.Ceiling(count / (size > 0 ? size : 10.0)).ToInt32();
                             var page = Context.Request.Query["page"].ToString().ToInt32();
                             int current = page > 0 ? page : 1;

+ 6 - 14
src/Masuit.MyBlogs.Core/appsettings.json

@@ -5,13 +5,14 @@
         }
     },
     "AllowedHosts": "*",
-    "cert": {
-        "path": "App_Data/cert/server.pfx",
-        "password": "cEHlnUGu"
+    "Https": {
+        "Enabled": true, // 启用https跳转
+        "CertPath": "App_Data/cert/server.pfx", // https证书
+        "CertPassword": "cEHlnUGu" // 证书密码
     },
     "ConnString": "Server=127.0.0.1;Port=3306;Database=MyBlogs;Uid=root;Pwd=;Charset=utf8mb4",
     //"ConnString": "Data Source=.;Initial Catalog=MyBlogs;Integrated Security=True",
-    "BaiduAK": "你的BaiduAK",
+    "BaiduAK": "你的BaiduAK", // 百度开放平台AppKey
     "Redis": "127.0.0.1:6379,allowadmin=true,connectTimeout=20000,connectRetry=1,responseTimeout=20000,syncTimeout=10000",
     "Imgbed": { // 图床相关配置
         "AliyunOSS": {
@@ -35,15 +36,6 @@
             "RawUrl": "https://gitlab.com/masuit/imgbed/raw/master/",
             "AccessToken": "你的private_token",
             "Branch": "master"
-        },
-        "ImgbedDomains": [
-            "gitee.com",
-            "gitlab.com",
-            "github.com",
-            "loli.net",
-            "alicdn.com",
-            "kuaizhan.com",
-            "qpic.cn"
-        ]
+        }
     }
 }

+ 17 - 1
src/Masuit.MyBlogs.Core/ueconfig.json

@@ -38,7 +38,23 @@
     "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */
 
     /* 抓取远程图片配置 */
-    "catcherLocalDomain": [ "127.0.0.1", "localhost", "img.baidu.com", "sinaimg.cn", "aliyuncs.com","loli.net" ],
+    "catcherLocalDomain": [
+        "127.0.0.1",
+        "localhost",
+        "img.baidu.com",
+        "sinaimg.cn",
+        "aliyuncs.com",
+        "loli.net",
+        "git.imweb.io",
+        "gitee.com",
+        "gitlab.com",
+        "github.com",
+        "gitclub.cn",
+        "git.lug.ustc.edu.cn",
+        "alicdn.com",
+        "kuaizhan.com",
+        "qpic.cn"
+    ],
     "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
     "catcherFieldName": "source", /* 提交的图片列表表单名称 */
     "catcherPathFormat": "/upload/images/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */

+ 3 - 1
src/Masuit.MyBlogs.Core/wwwroot/Assets/UEditor/ueditor.config.admin.js

@@ -513,7 +513,9 @@
             tt: [],
             u: [],
             ul: ['class', 'style'],
-            video: ['autoplay', 'controls', 'loop', 'preload', 'src', 'height', 'width', 'class', 'style']
+            video: ['autoplay', 'controls', 'loop', 'preload', 'src', 'height', 'width', 'class', 'style'],
+			script:[],
+			link:[]
         }
     };
 

+ 53 - 1
src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/post.js

@@ -180,15 +180,20 @@
 }]);
 myApp.controller("writeblog", ["$scope", "$http", "$timeout", function ($scope, $http, $timeout) {
 	window.hub.stop();
+	clearInterval(window.interval);
 	$scope.post = {
 		Title: "",
 		schedule: false,
 		Content: "",
 		CategoryId: 1,
 		Label: "",
-		Seminars: ""
+		Seminars: "",
+		Keyword:""
 	};
 	$scope.loading();
+	window.interval = setInterval(function () {
+		localStorage.setItem("write-post-draft",JSON.stringify($scope.post));
+	},5000);
 	$scope.post.Author = $scope.user.NickName || $scope.user.Username;
 	$scope.post.Email = $scope.user.Email;
 	$scope.getCategory = function () {
@@ -322,6 +327,8 @@ myApp.controller("writeblog", ["$scope", "$http", "$timeout", function ($scope,
 				$scope.post.Title = "";
 				$scope.post.IsWordDocument = false;
 				$scope.post.ResourceName = "";
+				clearInterval(window.interval);
+				localStorage.removeItem("write-post-draft");
 			} else {
 				window.notie.alert({
 					type: 3,
@@ -350,6 +357,26 @@ myApp.controller("writeblog", ["$scope", "$http", "$timeout", function ($scope,
 			});
 		}, 0);
 	}
+
+	//检查草稿
+	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]);
+					$('.ui.dropdown.tags').dropdown('set selected', $scope.post.Label.split(','));
+					$('.ui.dropdown.keyword').dropdown('set selected', $scope.post.Keyword.split(','));
+					$('.ui.dropdown.seminar').dropdown('set selected', $scope.post.Seminars.split(','));
+				}, 10);
+			}
+		});	
+	}
 }]);
 myApp.controller("postedit", ["$scope", "$http", "$location", "$timeout", function ($scope, $http, $location, $timeout) {
 	window.hub.stop();
@@ -361,6 +388,9 @@ myApp.controller("postedit", ["$scope", "$http", "$location", "$timeout", functi
 		id: $scope.id
 	}, function (data) {
 		$scope.post = data.Data;
+		window.interval = setInterval(function () {
+			localStorage.setItem("post-draft-"+$scope.id,JSON.stringify($scope.post));
+		},5000);
 		$scope.request("/post/gettag", null, function (res) {
 			$scope.Tags = res.Data;
 			$('.ui.dropdown.tags').dropdown({
@@ -532,6 +562,8 @@ myApp.controller("postedit", ["$scope", "$http", "$location", "$timeout", functi
 					time: 4
 				});
 				$scope.post = data.Data;
+				clearInterval(window.interval);
+				localStorage.removeItem("post-draft-"+$scope.id);
 			} else {
 				window.notie.alert({
 					type: 3,
@@ -542,6 +574,26 @@ 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]);
+					$('.ui.dropdown.tags').dropdown('set selected', $scope.post.Label.split(','));
+					$('.ui.dropdown.keyword').dropdown('set selected', $scope.post.Keyword.split(','));
+					$('.ui.dropdown.seminar').dropdown('set selected', $scope.post.Seminars.split(','));
+				}, 10);
+			}
+		});	
+	}
 }]);
 myApp.controller("toppost", ["$scope", "$http", "$location", "$timeout", function ($scope, $http, $location, $timeout) {
 	window.hub.stop();

+ 4 - 1
src/Masuit.MyBlogs.Core/wwwroot/ng-views/views/system/firewall.html

@@ -63,7 +63,10 @@
                 <a data-microtip="查看{{row.IP}}的详细信息" data-microtip-position="bottom" ng-href="/tools/ip?ip={{row.IP}}" style="font-size: 20px;" target="_blank">{{row.IP}}</a>
                 <button class="badge btn btn-primary pull-right" ng-click="addToWhiteList(row.IP)">添加到白名单</button>
             </td>
-            <td filter="{RequestUrl: 'text'}" sortable="'RequestUrl'" title="'请求URL'">
+            <td filter="{Address: 'text'}" title="'IP地理位置'">
+                {{row.Address}}
+            </td>
+            <td filter="{RequestUrl: 'text'}" title="'请求URL'">
                 <a ng-href="{{row.RequestUrl}}" target="_blank">{{row.RequestUrl}}</a>
             </td>
             <td sortable="'Time'" title="'拦截时间'">