Jelajahi Sumber

1. 404页面修正
2. 一些数据权限漏洞修复
3. 前端优化

懒得勤快 4 tahun lalu
induk
melakukan
9a8844cfe0
27 mengubah file dengan 182 tambahan dan 145 penghapusan
  1. 1 0
      src/Masuit.MyBlogs.Core/Controllers/AdminController.cs
  2. 0 31
      src/Masuit.MyBlogs.Core/Controllers/BaseController.cs
  3. 14 12
      src/Masuit.MyBlogs.Core/Controllers/ErrorController.cs
  4. 7 13
      src/Masuit.MyBlogs.Core/Controllers/PostController.cs
  5. 55 0
      src/Masuit.MyBlogs.Core/Controllers/SubscribeController.cs
  6. 34 1
      src/Masuit.MyBlogs.Core/Extensions/MiddlewareExtension.cs
  7. 43 41
      src/Masuit.MyBlogs.Core/Extensions/UEditor/UploadHandler.cs
  8. 0 2
      src/Masuit.MyBlogs.Core/Infrastructure/Services/Interface/IPostService.cs
  9. 1 11
      src/Masuit.MyBlogs.Core/Infrastructure/Services/PostService.cs
  10. 1 1
      src/Masuit.MyBlogs.Core/Views/Dashboard/FileManager.cshtml
  11. 2 2
      src/Masuit.MyBlogs.Core/Views/Dashboard/Index.cshtml
  12. 1 1
      src/Masuit.MyBlogs.Core/Views/Error/AccessDeny.cshtml
  13. 1 1
      src/Masuit.MyBlogs.Core/Views/Error/ComingSoon.cshtml
  14. 1 1
      src/Masuit.MyBlogs.Core/Views/Error/Index.cshtml
  15. 1 1
      src/Masuit.MyBlogs.Core/Views/Error/ServiceUnavailable.cshtml
  16. 1 1
      src/Masuit.MyBlogs.Core/Views/Error/TempDeny.cshtml
  17. 3 3
      src/Masuit.MyBlogs.Core/Views/Post/Details.cshtml
  18. 3 3
      src/Masuit.MyBlogs.Core/Views/Post/Details_Admin.cshtml
  19. 2 2
      src/Masuit.MyBlogs.Core/Views/Shared/_Layout.cshtml
  20. 4 6
      src/Masuit.MyBlogs.Core/wwwroot/Assets/jquery.tocify/jquery.tocify.js
  21. 7 0
      src/Masuit.MyBlogs.Core/wwwroot/Assets/lazyload.min.js
  22. 0 1
      src/Masuit.MyBlogs.Core/wwwroot/Scripts/global/article.js
  23. 0 1
      src/Masuit.MyBlogs.Core/wwwroot/Scripts/global/leavemsg.js
  24. 0 1
      src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/msg.js
  25. 0 1
      src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/partner.js
  26. 0 7
      src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/system.js
  27. 0 1
      src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/users.js

+ 1 - 0
src/Masuit.MyBlogs.Core/Controllers/AdminController.cs

@@ -1,4 +1,5 @@
 using AutoMapper;
+using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Configs;
 using Masuit.MyBlogs.Core.Extensions;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;

+ 0 - 31
src/Masuit.MyBlogs.Core/Controllers/BaseController.cs

@@ -268,36 +268,5 @@ namespace Masuit.MyBlogs.Core.Controllers
                 }
             });
         }
-
-        protected void CheckPermission(List<Post> posts)
-        {
-            var location = Request.Location() + "|" + Request.Headers[HeaderNames.UserAgent];
-            posts.RemoveAll(p =>
-            {
-                switch (p.LimitMode)
-                {
-                    case RegionLimitMode.AllowRegion:
-                        return !location.Contains(p.Regions.Split(',', StringSplitOptions.RemoveEmptyEntries)) && !CurrentUser.IsAdmin && !VisitorTokenValid && !Request.IsRobot();
-                    case RegionLimitMode.ForbidRegion:
-                        return location.Contains(p.Regions.Split(',', StringSplitOptions.RemoveEmptyEntries)) && !CurrentUser.IsAdmin && !VisitorTokenValid && !Request.IsRobot();
-                    case RegionLimitMode.AllowRegionExceptForbidRegion:
-                        if (location.Contains(p.ExceptRegions.Split(',', StringSplitOptions.RemoveEmptyEntries)) && !CurrentUser.IsAdmin && !VisitorTokenValid)
-                        {
-                            return true;
-                        }
-
-                        goto case RegionLimitMode.AllowRegion;
-                    case RegionLimitMode.ForbidRegionExceptAllowRegion:
-                        if (location.Contains(p.ExceptRegions.Split(',', StringSplitOptions.RemoveEmptyEntries)) && !CurrentUser.IsAdmin && !VisitorTokenValid)
-                        {
-                            return false;
-                        }
-
-                        goto case RegionLimitMode.ForbidRegion;
-                    default:
-                        return false;
-                }
-            });
-        }
     }
 }

+ 14 - 12
src/Masuit.MyBlogs.Core/Controllers/ErrorController.cs

@@ -1,7 +1,6 @@
 using Hangfire;
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Configs;
-using Masuit.MyBlogs.Core.Extensions;
 using Masuit.MyBlogs.Core.Extensions.Firewall;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.Tools;
@@ -67,20 +66,14 @@ namespace Masuit.MyBlogs.Core.Controllers
                 string err;
                 var req = HttpContext.Request;
                 var ip = HttpContext.Connection.RemoteIpAddress;
-                req.EnableBuffering();
-                req.Body.Seek(0, SeekOrigin.Begin);
-                using var sr = new StreamReader(req.Body, Encoding.UTF8, false);
-                var body = await sr.ReadToEndAsync();
-                body = HttpUtility.UrlDecode(body);
-                req.Body.Position = 0;
                 switch (feature.Error)
                 {
                     case DbUpdateConcurrencyException ex:
-                        err = $"数据库并发更新异常,更新表:{ex.Entries.Select(e => e.Metadata.Name)},请求路径:{req.Scheme}://{req.Host}{HttpUtility.UrlDecode(feature.Path)}{req.QueryString},客户端用户代理:{req.Headers[HeaderNames.UserAgent]},客户端IP:{ip}\t{ex.InnerException?.Message},请求参数:\n{body}\n堆栈信息:";
+                        err = $"数据库并发更新异常,更新表:{ex.Entries.Select(e => e.Metadata.Name)},请求路径:{req.Scheme}://{req.Host}{HttpUtility.UrlDecode(feature.Path)}{req.QueryString},客户端用户代理:{req.Headers[HeaderNames.UserAgent]},客户端IP:{ip}\t{ex.InnerException?.Message},请求参数:\n{await GetRequestBody(req)}\n堆栈信息:";
                         LogManager.Error(err, ex);
                         break;
                     case DbUpdateException ex:
-                        err = $"数据库更新时异常,更新表:{ex.Entries.Select(e => e.Metadata.Name)},请求路径:{req.Scheme}://{req.Host}{HttpUtility.UrlDecode(feature.Path)}{req.QueryString} ,客户端用户代理:{req.Headers[HeaderNames.UserAgent]},客户端IP:{ip}\t{ex.InnerException?.Message},请求参数:\n{body}\n堆栈信息:";
+                        err = $"数据库更新时异常,更新表:{ex.Entries.Select(e => e.Metadata.Name)},请求路径:{req.Scheme}://{req.Host}{HttpUtility.UrlDecode(feature.Path)}{req.QueryString} ,客户端用户代理:{req.Headers[HeaderNames.UserAgent]},客户端IP:{ip}\t{ex.InnerException?.Message},请求参数:\n{await GetRequestBody(req)}\n堆栈信息:";
                         LogManager.Error(err, ex);
                         break;
                     case AggregateException ex:
@@ -90,13 +83,12 @@ namespace Masuit.MyBlogs.Core.Controllers
                             LogManager.Error($"异常源:{e.Source},异常类型:{e.GetType().Name},请求路径:{req.Scheme}://{req.Host}{HttpUtility.UrlDecode(feature.Path)}{req.QueryString} ,客户端用户代理:{req.Headers[HeaderNames.UserAgent]},客户端IP:{ip}\t", e);
                             return true;
                         });
+                        var body = await GetRequestBody(req);
                         if (!string.IsNullOrEmpty(body))
                         {
                             LogManager.Debug("↑↑↑请求参数:\n" + body);
                         }
                         break;
-                    case NotFoundException:
-                        return Index();
                     case AccessDenyException:
                         var entry = ip.GetIPLocation();
                         var tips = Template.Create(CommonHelper.SystemSettings.GetOrAdd("AccessDenyTips", @"<h4>遇到了什么问题?</h4>
@@ -112,7 +104,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                             Message = $"检测到您的IP({ip})访问过于频繁,已被本站暂时禁止访问,请稍后再试!"
                         }) : View("TempDeny");
                     default:
-                        LogManager.Error($"异常源:{feature.Error.Source},异常类型:{feature.Error.GetType().Name},请求路径:{req.Scheme}://{req.Host}{HttpUtility.UrlDecode(feature.Path)}{req.QueryString} ,客户端用户代理:{req.Headers[HeaderNames.UserAgent]},客户端IP:{ip},请求参数:\n{body}\n堆栈信息:", feature.Error);
+                        LogManager.Error($"异常源:{feature.Error.Source},异常类型:{feature.Error.GetType().Name},请求路径:{req.Scheme}://{req.Host}{HttpUtility.UrlDecode(feature.Path)}{req.QueryString} ,客户端用户代理:{req.Headers[HeaderNames.UserAgent]},客户端IP:{ip},请求参数:\n{await GetRequestBody(req)}\n堆栈信息:", feature.Error);
                         break;
                 }
             }
@@ -126,6 +118,16 @@ namespace Masuit.MyBlogs.Core.Controllers
             }) : View();
         }
 
+        private static async Task<string> GetRequestBody(HttpRequest req)
+        {
+            req.Body.Seek(0, SeekOrigin.Begin);
+            using var sr = new StreamReader(req.Body, Encoding.UTF8, false);
+            var body = await sr.ReadToEndAsync();
+            body = HttpUtility.UrlDecode(body);
+            req.Body.Position = 0;
+            return body;
+        }
+
         /// <summary>
         /// 网站升级中
         /// </summary>

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

@@ -64,7 +64,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <param name="id"></param>
         /// <param name="kw"></param>
         /// <returns></returns>
-        [Route("{id:int}"), Route("{id:int}/comments/{cid:int}"), ResponseCache(Duration = 600, VaryByQueryKeys = new[] { "id" }, VaryByHeader = "Cookie")]
+        [Route("{id:int}"), Route("{id:int}/comments/{cid:int}"), ResponseCache(Duration = 600, VaryByHeader = "Cookie")]
         public async Task<ActionResult> Details(int id, string kw)
         {
             var post = await PostService.GetAsync(p => p.Id == id && (p.Status == Status.Published || CurrentUser.IsAdmin)) ?? throw new NotFoundException("文章未找到");
@@ -80,14 +80,8 @@ namespace Masuit.MyBlogs.Core.Controllers
             }
 
             ViewBag.Ads = AdsService.GetByWeightedPrice(AdvertiseType.InPage, Request.Location(), post.CategoryId);
-            var related = PostService.ScoreSearch(1, 11, string.IsNullOrWhiteSpace(post.Keyword + post.Label) ? post.Title : post.Keyword + post.Label);
-            related.RemoveAll(p => p.Id == id);
-            if (related.Count <= 1)
-            {
-                related = (await PostService.GetPagesFromCacheAsync(1, 10, p => p.Id != id && p.CategoryId == post.CategoryId && (p.LimitMode ?? 0) == RegionLimitMode.All, p => p.TotalViewCount, false)).Data;
-            }
-
-            CheckPermission(related);
+            var regex = SearchEngine.LuceneIndexSearcher.CutKeywords(string.IsNullOrWhiteSpace(post.Keyword + post.Label) ? post.Title : post.Keyword + post.Label).Join("|");
+            var related = await PostService.GetQuery(p => p.Id != id && (p.LimitMode ?? 0) == RegionLimitMode.All && Regex.IsMatch(p.Title + (p.Keyword ?? "") + (p.Label ?? ""), regex), p => p.AverageViewCount, false).Take(10).Select(p => new { p.Id, p.Title }).Cacheable().ToDictionaryAsync(p => p.Id, p => p.Title);
             ViewBag.Related = related;
             post.ModifyDate = post.ModifyDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone));
             post.PostDate = post.PostDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone));
@@ -658,7 +652,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             if (!string.IsNullOrEmpty(kw))
             {
                 kw = Regex.Escape(kw);
-                where = where.And(p => Regex.IsMatch(p.Title + p.Author + p.Email + p.Label + p.Content, kw));
+                where = where.And(p => Regex.IsMatch(p.Title + p.Author + p.Email + p.Content, kw));
             }
 
             var list = PostService.GetQuery(where).OrderBy($"{nameof(Post.Status)} desc,{nameof(Post.IsFixedTop)} desc,{orderby.GetDisplay()} desc").ToPagedList<Post, PostDataModel>(page, size, MapperConfig);
@@ -1022,12 +1016,12 @@ namespace Masuit.MyBlogs.Core.Controllers
         {
             var keys = await RedisHelper.KeysAsync(nameof(PostOnline) + ":*");
             var sets = await keys.SelectAsync(async s => (Id: s.Split(':')[1].ToInt32(), Clients: await RedisHelper.HGetAsync<HashSet<string>>(s, "value")));
-            var ids = sets.Where(t => t.Clients.Count > 0).OrderByDescending(t => t.Clients.Count).Take(10).Select(t => t.Id).ToArray();
-            var mostHots = await PostService.GetQuery<PostModelBase>(p => ids.Contains(p.Id)).Cacheable().ToListAsync().ContinueWith(t =>
+            var ids = sets.Where(t => t.Clients?.Count > 0).OrderByDescending(t => t.Clients.Count).Take(10).Select(t => t.Id).ToArray();
+            var mostHots = await PostService.GetQuery<PostModelBase>(p => ids.Contains(p.Id)).ToListAsync().ContinueWith(t =>
             {
                 foreach (var item in t.Result)
                 {
-                    item.ViewCount = sets.FirstOrDefault(t => t.Id == item.Id).Clients.Count;
+                    item.ViewCount = sets.FirstOrDefault(x => x.Id == item.Id).Clients.Count;
                 }
 
                 return t.Result.OrderByDescending(p => p.ViewCount);

+ 55 - 0
src/Masuit.MyBlogs.Core/Controllers/SubscribeController.cs

@@ -1,5 +1,6 @@
 using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Extensions;
+using Masuit.MyBlogs.Core.Extensions.Firewall;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.Entity;
 using Masuit.MyBlogs.Core.Models.Enum;
@@ -166,6 +167,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             string scheme = Request.Scheme;
             var host = Request.Host;
             var post = await PostService.GetAsync(p => p.Rss && p.Status == Status.Published && p.Id == id) ?? throw new NotFoundException("文章未找到");
+            CheckPermission(post);
             var summary = await post.Content.GetSummary(300, 50);
             var item = new Item()
             {
@@ -236,5 +238,58 @@ namespace Masuit.MyBlogs.Core.Controllers
                 item.ModifyDate = item.ModifyDate.ToTimeZone(HttpContext.Session.Get<string>(SessionKey.TimeZone));
             }
         }
+
+        private void CheckPermission(Post post)
+        {
+            var location = Request.Location() + "|" + Request.Headers[HeaderNames.UserAgent];
+            switch (post.LimitMode)
+            {
+                case RegionLimitMode.AllowRegion:
+                    if (!location.Contains(post.Regions.Split(',', StringSplitOptions.RemoveEmptyEntries)) && !Request.IsRobot())
+                    {
+                        Disallow(post);
+                    }
+
+                    break;
+                case RegionLimitMode.ForbidRegion:
+                    if (location.Contains(post.Regions.Split(',', StringSplitOptions.RemoveEmptyEntries)) && !Request.IsRobot())
+                    {
+                        Disallow(post);
+                    }
+
+                    break;
+                case RegionLimitMode.AllowRegionExceptForbidRegion:
+                    if (location.Contains(post.ExceptRegions.Split(',', StringSplitOptions.RemoveEmptyEntries)))
+                    {
+                        Disallow(post);
+                    }
+
+                    goto case RegionLimitMode.AllowRegion;
+                case RegionLimitMode.ForbidRegionExceptAllowRegion:
+                    if (location.Contains(post.ExceptRegions.Split(',', StringSplitOptions.RemoveEmptyEntries)))
+                    {
+                        break;
+                    }
+
+                    goto case RegionLimitMode.ForbidRegion;
+            }
+        }
+
+        private void Disallow(Post post)
+        {
+            RedisHelper.IncrBy("interceptCount");
+            RedisHelper.LPush("intercept", new IpIntercepter()
+            {
+                IP = HttpContext.Connection.RemoteIpAddress.ToString(),
+                RequestUrl = $"//{Request.Host}/{post.Id}",
+                Referer = Request.Headers[HeaderNames.Referer],
+                Time = DateTime.Now,
+                UserAgent = Request.Headers[HeaderNames.UserAgent],
+                Remark = "无权限查看该文章",
+                Address = Request.Location()
+            });
+            throw new NotFoundException("文章未找到");
+        }
+
     }
 }

+ 34 - 1
src/Masuit.MyBlogs.Core/Extensions/MiddlewareExtension.cs

@@ -2,10 +2,15 @@
 using AutoMapper.Extensions.ExpressionMapping;
 using CacheManager.Core;
 using Masuit.MyBlogs.Core.Configs;
+using Masuit.Tools.AspNetCore.Mime;
 using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
 using Microsoft.AspNetCore.ResponseCompression;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.WebEncoders;
+using Microsoft.Net.Http.Headers;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Serialization;
 using System;
@@ -61,10 +66,11 @@ namespace Masuit.MyBlogs.Core.Extensions
             services.AddMvc(options =>
             {
                 options.ReturnHttpNotAcceptable = true;
+                options.Filters.Add<ExceptionFilter>();
             }).AddNewtonsoftJson(options =>
             {
                 options.SerializerSettings.ContractResolver = new DefaultContractResolver();
-                options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local; // 设置时区为 UTC
+                options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
             }).AddXmlDataContractSerializerFormatters().AddControllersAsServices().AddViewComponentsAsServices().AddTagHelpersAsServices(); // MVC
             services.Configure<WebEncoderOptions>(options =>
             {
@@ -178,4 +184,31 @@ namespace Masuit.MyBlogs.Core.Extensions
             return app;
         }
     }
+
+    public class ExceptionFilter : IExceptionFilter, IFilterMetadata
+    {
+        public void OnException(ExceptionContext context)
+        {
+            if (context.Exception is NotFoundException)
+            {
+                context.HttpContext.Response.StatusCode = 404;
+                string accept = context.HttpContext.Request.Headers[HeaderNames.Accept] + "";
+                context.Result = true switch
+                {
+                    _ when accept.StartsWith("image") => new VirtualFileResult("/Assets/images/404/4044.jpg", ContentType.Jpeg),
+                    _ when accept.StartsWith("application/json") || context.HttpContext.Request.Method == HttpMethods.Post => new JsonResult(new
+                    {
+                        StatusCode = 404,
+                        Success = false,
+                        Message = "页面未找到!"
+                    }),
+                    _ => new ViewResult()
+                    {
+                        ViewName = "/Views/Error/Index.cshtml"
+                    }
+                };
+                context.ExceptionHandled = true;
+            }
+        }
+    }
 }

+ 43 - 41
src/Masuit.MyBlogs.Core/Extensions/UEditor/UploadHandler.cs

@@ -31,53 +31,55 @@ namespace Masuit.MyBlogs.Core.Extensions.UEditor
         public override async Task<string> Process()
         {
             var form = await Request.ReadFormAsync();
-            var file = form.Files[UploadConfig.UploadFieldName];
-            var uploadFileName = file.FileName;
-
-            if (!CheckFileType(uploadFileName))
-            {
-                Result.State = UploadState.TypeNotAllow;
-                return WriteResult();
-            }
-            if (!CheckFileSize(file.Length))
-            {
-                Result.State = UploadState.SizeLimitExceed;
-                return WriteResult();
-            }
-
-            Result.OriginFileName = uploadFileName;
-            var savePath = PathFormatter.Format(uploadFileName, UploadConfig.PathFormat);
-            var localPath = AppContext.BaseDirectory + "wwwroot" + savePath;
-            var cts = new CancellationTokenSource(20000);
-            var stream = file.OpenReadStream();
-            try
+            var files = form.Files;
+            foreach (var file in files)
             {
-                stream = stream.AddWatermark();
-                var (url, success) = await Startup.ServiceProvider.GetRequiredService<ImagebedClient>().UploadImage(stream, localPath, cts.Token);
-                if (success)
+                var uploadFileName = file.FileName;
+                if (!CheckFileType(uploadFileName))
                 {
-                    Result.Url = url;
+                    Result.State = UploadState.TypeNotAllow;
+                    return WriteResult();
                 }
-                else
+                if (!CheckFileSize(file.Length))
                 {
-                    Directory.CreateDirectory(Path.GetDirectoryName(localPath));
-                    await File.WriteAllBytesAsync(localPath, await stream.ToArrayAsync());
-                    Result.Url = savePath;
+                    Result.State = UploadState.SizeLimitExceed;
+                    return WriteResult();
                 }
 
-                Result.State = UploadState.Success;
-            }
-            catch (Exception e)
-            {
-                Result.State = UploadState.FileAccessError;
-                Result.ErrorMessage = e.Message;
-                LogManager.Error(e);
-            }
-            finally
-            {
-                cts.Dispose();
-                stream.Close();
-                await stream.DisposeAsync();
+                Result.OriginFileName = uploadFileName;
+                var savePath = PathFormatter.Format(uploadFileName, UploadConfig.PathFormat);
+                var localPath = AppContext.BaseDirectory + "wwwroot" + savePath;
+                var cts = new CancellationTokenSource(20000);
+                var stream = file.OpenReadStream();
+                try
+                {
+                    stream = stream.AddWatermark();
+                    var (url, success) = await Startup.ServiceProvider.GetRequiredService<ImagebedClient>().UploadImage(stream, localPath, cts.Token);
+                    if (success)
+                    {
+                        Result.Url = url;
+                    }
+                    else
+                    {
+                        Directory.CreateDirectory(Path.GetDirectoryName(localPath));
+                        await File.WriteAllBytesAsync(localPath, await stream.ToArrayAsync());
+                        Result.Url = savePath;
+                    }
+
+                    Result.State = UploadState.Success;
+                }
+                catch (Exception e)
+                {
+                    Result.State = UploadState.FileAccessError;
+                    Result.ErrorMessage = e.Message;
+                    LogManager.Error(e);
+                }
+                finally
+                {
+                    cts.Dispose();
+                    stream.Close();
+                    await stream.DisposeAsync();
+                }
             }
 
             return WriteResult();

+ 0 - 2
src/Masuit.MyBlogs.Core/Infrastructure/Services/Interface/IPostService.cs

@@ -10,8 +10,6 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
     {
         SearchResult<PostDto> SearchPage(int page, int size, string keyword);
 
-        List<Post> ScoreSearch(int page, int size, string keyword);
-
         /// <summary>
         /// 统一保存的方法
         /// </summary>

+ 1 - 11
src/Masuit.MyBlogs.Core/Infrastructure/Services/PostService.cs

@@ -24,24 +24,14 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
     public class PostService : BaseService<Post>, IPostService
     {
         private readonly ICacheManager<SearchResult<PostDto>> _cacheManager;
-        private readonly ICacheManager<List<Post>> _searchCacheManager;
         private readonly ICacheManager<Dictionary<string, int>> _tagCacheManager;
 
-        public PostService(IPostRepository repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher, ICacheManager<SearchResult<PostDto>> cacheManager, ICacheManager<List<Post>> searchCacheManager, ICacheManager<Dictionary<string, int>> tagCacheManager) : base(repository, searchEngine, searcher)
+        public PostService(IPostRepository repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher, ICacheManager<SearchResult<PostDto>> cacheManager, ICacheManager<Dictionary<string, int>> tagCacheManager) : base(repository, searchEngine, searcher)
         {
             _cacheManager = cacheManager;
-            _searchCacheManager = searchCacheManager;
             _tagCacheManager = tagCacheManager;
         }
 
-        public List<Post> ScoreSearch(int page, int size, string keyword)
-        {
-            var cacheKey = $"scoreSearch:{keyword}:{page}:{size}";
-            var result = _searchCacheManager.GetOrAdd(cacheKey, _ => SearchEngine.ScoredSearch<Post>(BuildSearchOptions(page, size, keyword)).Results.Select(r => r.Entity).Distinct().ToList());
-            _searchCacheManager.Expire(cacheKey, TimeSpan.FromHours(1));
-            return result;
-        }
-
         public SearchResult<PostDto> SearchPage(int page, int size, string keyword)
         {
             var cacheKey = $"search:{keyword}:{page}:{size}";

+ 1 - 1
src/Masuit.MyBlogs.Core/Views/Dashboard/FileManager.cshtml

@@ -18,7 +18,7 @@
     <environment names="Stage,Production">
         @await Styles.RenderAsync("~/bundles/filemanager.css")
     </environment>
-    <script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
+    <script src="https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js"></script>
     <script src="https://cdn.staticfile.org/angular.js/1.7.7/angular.min.js"></script>
     <script src="https://cdn.staticfile.org/angular-translate/2.18.1/angular-translate.min.js"></script>
     <script src="https://cdn.staticfile.org/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>

+ 2 - 2
src/Masuit.MyBlogs.Core/Views/Dashboard/Index.cshtml

@@ -20,7 +20,7 @@
     <link href="https://cdn.staticfile.org/animate.css/3.5.2/animate.min.css" rel="stylesheet">
     <link href="https://cdn.staticfile.org/material-design-iconic-font/2.2.0/css/material-design-iconic-font.min.css" rel="stylesheet">
     <link href="https://cdn.staticfile.org/angular-loading-bar/0.9.0/loading-bar.min.css" rel="stylesheet">
-    <link href="https://cdn.staticfile.org/limonte-sweetalert2/6.6.9/sweetalert2.min.css" rel="stylesheet" async defer>
+    <link href="https://cdn.staticfile.org/limonte-sweetalert2/6.6.10/sweetalert2.min.css" rel="stylesheet" async defer>
     <link href="https://cdn.staticfile.org/notie/4.3.1/notie.min.css" rel="stylesheet">
     <link href="https://cdn.staticfile.org/node-waves/0.7.6/waves.min.css" rel="stylesheet">
     <link href="https://cdn.staticfile.org/ng-table/1.0.0/ng-table.css" rel="stylesheet" async defer>
@@ -38,7 +38,7 @@
         @await Styles.RenderAsync("/bundles/dashboard.css")
     </environment>
 
-    <script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
+    <script src="https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js"></script>
     <script src="https://cdn.staticfile.org/angular.js/1.6.9/angular.min.js"></script>
     <script src="https://cdn.staticfile.org/angular.js/1.6.9/angular-animate.min.js"></script>
     <script src="https://cdn.staticfile.org/angular.js/1.6.9/angular-resource.min.js"></script>

+ 1 - 1
src/Masuit.MyBlogs.Core/Views/Error/AccessDeny.cshtml

@@ -36,7 +36,7 @@
     <link href="https://cdn.staticfile.org/normalize/8.0.1/normalize.min.css" rel="stylesheet">
     <link href="https://cdn.staticfile.org/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet" />
     <link href="https://cdn.staticfile.org/limonte-sweetalert2/6.11.5/sweetalert2.min.css" rel="stylesheet" async defer>
-    <script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
+    <script src="https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js"></script>
     <script src="https://cdn.staticfile.org/jquery.ripples/0.5.3/jquery.ripples.min.js"></script>
     <script src="https://cdn.staticfile.org/phaser/3.24.1/phaser.min.js"></script>
     <script src="https://cdn.staticfile.org/limonte-sweetalert2/6.6.10/sweetalert2.min.js"></script>

+ 1 - 1
src/Masuit.MyBlogs.Core/Views/Error/ComingSoon.cshtml

@@ -42,7 +42,7 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
     <link href="https://cdn.staticfile.org/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet" />
-    <script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
+    <script src="https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js"></script>
     <script src="https://cdn.staticfile.org/jquery.ripples/0.5.3/jquery.ripples.min.js"></script>
     <script src="https://cdn.staticfile.org/phaser/3.24.1/phaser.min.js"></script>
     <script src="~/Assets/catchcat/catch-the-cat.js"></script>

+ 1 - 1
src/Masuit.MyBlogs.Core/Views/Error/Index.cshtml

@@ -70,7 +70,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
     <link href="https://cdn.staticfile.org/normalize/8.0.1/normalize.min.css" rel="stylesheet">
     <link href="https://cdn.staticfile.org/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet" />
-    <script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
+    <script src="https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js"></script>
     <script src="https://cdn.staticfile.org/jquery.ripples/0.5.3/jquery.ripples.min.js"></script>
     <script src="https://cdn.staticfile.org/phaser/3.24.1/phaser.min.js"></script>
     <script src="~/Assets/catchcat/catch-the-cat.js"></script>

+ 1 - 1
src/Masuit.MyBlogs.Core/Views/Error/ServiceUnavailable.cshtml

@@ -70,7 +70,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
     <link href="https://cdn.staticfile.org/normalize/8.0.1/normalize.min.css" rel="stylesheet">
     <link href="https://cdn.staticfile.org/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet" />
-    <script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
+    <script src="https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js"></script>
     <script src="https://cdn.staticfile.org/jquery.ripples/0.5.3/jquery.ripples.min.js"></script>
     <script src="https://cdn.staticfile.org/phaser/3.24.1/phaser.min.js"></script>
     <script src="~/Assets/catchcat/catch-the-cat.js"></script>

+ 1 - 1
src/Masuit.MyBlogs.Core/Views/Error/TempDeny.cshtml

@@ -30,7 +30,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
     <link href="https://cdn.staticfile.org/normalize/8.0.1/normalize.min.css" rel="stylesheet">
     <link href="https://cdn.staticfile.org/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet" />
-    <script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
+    <script src="https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js"></script>
     <script src="https://cdn.staticfile.org/jquery.ripples/0.5.3/jquery.ripples.min.js"></script>
     <script src="https://cdn.staticfile.org/phaser/3.24.1/phaser.min.js"></script>
 </head>

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

@@ -200,7 +200,7 @@
                     </section>
                 }
                 @{
-                    var posts = (List<Post>)ViewBag.Related;
+                    var posts = (Dictionary<int,string>)ViewBag.Related;
                     if (posts.Count>1)
                     {
                         <section class="wow margintop20 animated fadeIn">
@@ -209,8 +209,8 @@
                                 @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[i - 1].Id">@posts[i - 1].Title</a></td>
-                                        <td><a asp-controller="Post" asp-action="Details" asp-route-id="@posts[i].Id">@posts[i].Title</a></td>
+                                        <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>

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

@@ -209,7 +209,7 @@
                     </section>
                 }
                 @{
-                    var posts = (List<Post>)ViewBag.Related;
+                    var posts = (Dictionary<int,string>)ViewBag.Related;
                     if (posts.Count>1)
                     {
                         <section class="wow margintop20 animated fadeIn">
@@ -218,8 +218,8 @@
                                 @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[i - 1].Id">@posts[i - 1].Title</a></td>
-                                        <td><a asp-controller="Post" asp-action="Details" asp-route-id="@posts[i].Id">@posts[i].Title</a></td>
+                                        <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>

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

@@ -48,15 +48,15 @@
     </environment>
     <script src="https://cdn.staticfile.org/bluebird/3.5.3/bluebird.min.js" async defer></script>
     <script src="https://cdn.staticfile.org/modernizr/2010.07.06dev/modernizr.min.js" async defer></script>
-    <script src="https://cdn.staticfile.org/jquery/3.5.1/jquery.min.js"></script>
+    <script src="https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js"></script>
     <script src="https://cdn.staticfile.org/limonte-sweetalert2/6.6.9/sweetalert2.min.js" async defer></script>
     <script src="https://cdn.staticfile.org/notie/4.3.1/notie.min.js" async defer></script>
     <script src="https://cdn.staticfile.org/jquery.form/4.2.2/jquery.form.min.js" async defer></script>
     <script src="https://cdn.staticfile.org/jquery-mobile/1.4.5/jquery.mobile.min.js"></script>
-    <script src="https://cdn.statically.io/gh/jieyou/lazyload/master/lazyload.js"></script>
     <script src="https://cdn.staticfile.org/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
     <script src="~/Scripts/layer/layer.js"></script>
     <script src="~/Assets/layui/layui.js"></script>
+    <script src="~/Assets/lazyload.min.js"></script>
     <environment names="Development">
         <script src="~/Scripts/jquery.query.js"></script>
         <script src="~/Scripts/jquery.paging.js"></script>

+ 4 - 6
src/Masuit.MyBlogs.Core/wwwroot/Assets/jquery.tocify/jquery.tocify.js

@@ -654,9 +654,7 @@
                                 closestAnchorIdx = null,
 
                                 // Keeps a reference to all anchors
-                                anchors = $(self.options.context).find("div[data-unique]"),
-
-                                anchorText;
+                                anchors = $(self.options.context).find("div[data-unique]");
 
                             // Determines the index of the closest anchor
                             anchors.each(function(idx) {
@@ -669,10 +667,10 @@
                                 }
                             });
 
-                            anchorText = $(anchors[closestAnchorIdx]).attr("data-unique");
-
+                            var anchorText = $(anchors[closestAnchorIdx]).attr("data-unique");
+                            
                             // Stores the list item HTML element that corresponds to the currently traversed anchor tag
-                            elem = $('li[data-unique="' + anchorText + '"]');
+                            elem = $('li[data-unique=\'' + anchorText + '\']');
 
                             // If the `highlightOnScroll` option is true and a next element is found
                             if(self.options.highlightOnScroll && elem.length) {

File diff ditekan karena terlalu besar
+ 7 - 0
src/Masuit.MyBlogs.Core/wwwroot/Assets/lazyload.min.js


+ 0 - 1
src/Masuit.MyBlogs.Core/wwwroot/Scripts/global/article.js

@@ -189,7 +189,6 @@ $("#getcode-reply").on("click", function (e) {
 			swal({
 				title: '邮箱确认',
 				text: "检测到您输入的邮箱是网易邮箱,本站的邮件服务器可能会因为您的反垃圾设置而无法将邮件正常发送到您的邮箱,建议使用您的其他邮箱,或者检查反垃圾设置后,再点击确定按钮继续!",
-				type: 'warning',
 				showCancelButton: true,
 				confirmButtonColor: '#3085d6',
 				cancelButtonColor: '#d33',

+ 0 - 1
src/Masuit.MyBlogs.Core/wwwroot/Scripts/global/leavemsg.js

@@ -36,7 +36,6 @@
 			swal({
 				title: '邮箱确认',
 				text: "检测到您输入的邮箱是网易邮箱,本站的邮件服务器可能会因为您的反垃圾设置而无法将邮件正常发送到您的邮箱,建议使用您的其他邮箱,或者检查反垃圾设置后,再点击确定按钮继续!",
-				type: 'warning',
 				showCancelButton: true,
 				confirmButtonColor: '#3085d6',
 				cancelButtonColor: '#d33',

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

@@ -123,7 +123,6 @@ myApp.controller("msgs", ["$scope", "$http", function ($scope, $http) {
 		swal({
 			title: '确定清除已读消息?',
 			text: "即将彻底清除已读消息,不可恢复!",
-			type: 'warning',
 			showCancelButton: true,
 			confirmButtonColor: '#3085d6',
 			cancelButtonColor: '#d33',

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

@@ -73,7 +73,6 @@
 		swal({
 			title: '确定移除这条广告吗?',
 			text: partner.Title,
-			type: 'warning',
 			showCancelButton: true,
 			confirmButtonColor: '#3085d6',
 			cancelButtonColor: '#d33',

+ 0 - 7
src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/system.js

@@ -48,7 +48,6 @@ myApp.controller("system", ["$scope", "$http", function($scope, $http) {
 	$scope.save = function() {
 		swal({
 			title: '确认保存吗?',
-			type: 'warning',
 			showCloseButton: true,
 			confirmButtonColor: "#DD6B55",
 			confirmButtonText: "确定",
@@ -156,7 +155,6 @@ myApp.controller("system", ["$scope", "$http", function($scope, $http) {
 			swal({
 				title: '确定要关闭站点么?',
 				text: "一旦关闭,所有前台功能将不再可用!所有前台访问将会被重定向到:/ComingSoon",
-				type: 'warning',
 				showCancelButton: true,
 				confirmButtonColor: '#3085d6',
 				cancelButtonColor: '#d33',
@@ -178,7 +176,6 @@ myApp.controller("system", ["$scope", "$http", function($scope, $http) {
 			swal({
 				title: '确定要开启站点写保护么?',
 				text: "一旦开启,前台所有表单数据将无法被提交!",
-				type: 'warning',
 				showCancelButton: true,
 				confirmButtonColor: '#3085d6',
 				cancelButtonColor: '#d33',
@@ -216,7 +213,6 @@ myApp.controller("log", ["$scope", function ($scope) {
 	$scope.delete= function(file) {
 		swal({
 			title: '确定删除吗?',
-			type: 'warning',
 			showCancelButton: true,
 			showCloseButton: true,
 			confirmButtonColor: '#3085d6',
@@ -317,7 +313,6 @@ myApp.controller("firewall", ["$scope", "$http","NgTableParams","$timeout", func
 	this.clear= function() {
 		swal({
 			title: '确定清空拦截日志吗?',
-			type: 'warning',
 			showCancelButton: true,
 			showCloseButton: true,
 			confirmButtonColor: '#3085d6',
@@ -342,7 +337,6 @@ myApp.controller("firewall", ["$scope", "$http","NgTableParams","$timeout", func
             swal({
 				title: '确定要关闭网站防火墙么?',
 				text: "一旦关闭,网站将面临可能会被流量攻击的风险!",
-				type: 'warning',
 				showCancelButton: true,
 				confirmButtonColor: '#3085d6',
 				cancelButtonColor: '#d33',
@@ -443,7 +437,6 @@ myApp.controller("firewall", ["$scope", "$http","NgTableParams","$timeout", func
 	$scope.save = function() {
 		swal({
 			title: '确认保存吗?',
-			type: 'warning',
 			showCloseButton: true,
 			confirmButtonColor: "#DD6B55",
 			confirmButtonText: "确定",

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

@@ -29,7 +29,6 @@
 		swal({
 			title: '确定彻底删除这个用户吗?',
 			text: userinfo.Username,
-			type: 'warning',
 			showCancelButton: true,
 			confirmButtonColor: '#3085d6',
 			cancelButtonColor: '#d33',

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini