فهرست منبع

1.dashboard使用highstock渲染
2.一些bug修复
3.全文检索优化

懒得勤快 6 سال پیش
والد
کامیت
0e676c78c5
30فایلهای تغییر یافته به همراه321 افزوده شده و 472 حذف شده
  1. 5 0
      src/Masuit.MyBlogs.Core/Common/CommonHelper.cs
  2. 11 0
      src/Masuit.MyBlogs.Core/Common/HangfireHelper.cs
  3. 14 0
      src/Masuit.MyBlogs.Core/Configs/AppConfig.cs
  4. 9 0
      src/Masuit.MyBlogs.Core/Configs/HangfireJobInit.cs
  5. 6 1
      src/Masuit.MyBlogs.Core/Configs/RegisterAutomapper.cs
  6. 12 3
      src/Masuit.MyBlogs.Core/Controllers/BugController.cs
  7. 1 0
      src/Masuit.MyBlogs.Core/Controllers/PostController.cs
  8. 2 0
      src/Masuit.MyBlogs.Core/Controllers/SearchController.cs
  9. 3 0
      src/Masuit.MyBlogs.Core/Extensions/AuthorityAttribute.cs
  10. 15 1
      src/Masuit.MyBlogs.Core/Extensions/ExceptionMiddleware.cs
  11. 5 0
      src/Masuit.MyBlogs.Core/Extensions/FirewallMiddleware.cs
  12. 32 0
      src/Masuit.MyBlogs.Core/Extensions/Hangfire/HangfireBackJob.cs
  13. 27 0
      src/Masuit.MyBlogs.Core/Extensions/Hangfire/IHangfireBackJob.cs
  14. 2 2
      src/Masuit.MyBlogs.Core/Hubs/MyHub.cs
  15. 8 243
      src/Masuit.MyBlogs.Core/Infrastructure/Services/BaseService.cs
  16. 4 2
      src/Masuit.MyBlogs.Core/Infrastructure/Services/CategoryService.cs
  17. 4 2
      src/Masuit.MyBlogs.Core/Infrastructure/Services/CommentService.cs
  18. 0 166
      src/Masuit.MyBlogs.Core/Infrastructure/Services/Interface/IBaseService.cs
  19. 6 2
      src/Masuit.MyBlogs.Core/Infrastructure/Services/Interface/IServices.cs
  20. 4 2
      src/Masuit.MyBlogs.Core/Infrastructure/Services/LeaveMessageService.cs
  21. 4 3
      src/Masuit.MyBlogs.Core/Infrastructure/Services/MenuService.cs
  22. 3 11
      src/Masuit.MyBlogs.Core/Infrastructure/Services/PostService.cs
  23. 35 18
      src/Masuit.MyBlogs.Core/Infrastructure/Services/Services.cs
  24. 3 1
      src/Masuit.MyBlogs.Core/Infrastructure/Services/UserInfoService.cs
  25. 0 1
      src/Masuit.MyBlogs.Core/Masuit.MyBlogs.Core.csproj
  26. 1 1
      src/Masuit.MyBlogs.Core/Models/Entity/BaseEntity.cs
  27. 7 7
      src/Masuit.MyBlogs.Core/Models/Entity/Issue.cs
  28. 5 1
      src/Masuit.MyBlogs.Core/Startup.cs
  29. 3 3
      src/Masuit.MyBlogs.Core/Views/Dashboard/Index.cshtml
  30. 90 2
      src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/dashboard.js

+ 5 - 0
src/Masuit.MyBlogs.Core/Common/CommonHelper.cs

@@ -499,6 +499,11 @@ namespace Common
             return (url, success);
         }
 
+        /// <summary>
+        /// 替换img标签的src属性
+        /// </summary>
+        /// <param name="content"></param>
+        /// <returns></returns>
         public static string ReplaceImgSrc(string content)
         {
             var srcs = content.MatchImgSrcs();

+ 11 - 0
src/Masuit.MyBlogs.Core/Common/HangfireHelper.cs

@@ -5,10 +5,21 @@ using System;
 
 namespace Masuit.MyBlogs.Core.Common
 {
+    /// <summary>
+    /// HangfireHelper
+    /// </summary>
     public static class HangfireHelper
     {
         private static BackgroundJobClient Client { get; set; } = new BackgroundJobClient();
 
+        /// <summary>
+        /// 创建任务
+        /// </summary>
+        /// <param name="type">任务类</param>
+        /// <param name="method">调用方法</param>
+        /// <param name="queue">队列名</param>
+        /// <param name="args">调用参数</param>
+        /// <returns></returns>
         public static string CreateJob(Type type, string method, string queue = "", params dynamic[] args)
         {
             var job = new Job(type, type.GetMethod(method), args);

+ 14 - 0
src/Masuit.MyBlogs.Core/Configs/AppConfig.cs

@@ -1,9 +1,23 @@
 namespace Masuit.MyBlogs.Core.Configs
 {
+    /// <summary>
+    /// 应用程序配置
+    /// </summary>
     public class AppConfig
     {
+        /// <summary>
+        /// 数据库连接字符串
+        /// </summary>
         public static string ConnString { get; set; }
+
+        /// <summary>
+        /// 百度AK
+        /// </summary>
         public static string BaiduAK { get; set; }
+
+        /// <summary>
+        /// Redis连接字符串
+        /// </summary>
         public static string Redis { get; set; }
     }
 }

+ 9 - 0
src/Masuit.MyBlogs.Core/Configs/HangfireJobInit.cs

@@ -12,6 +12,9 @@ namespace Masuit.MyBlogs.Core.Configs
     /// </summary>
     public class HangfireJobInit
     {
+        /// <summary>
+        /// hangfire初始化
+        /// </summary>
         public static void Start()
         {
             RecurringJob.AddOrUpdate(() => CheckLinks(), Cron.HourInterval(5)); //每5h检查友链
@@ -25,11 +28,17 @@ namespace Masuit.MyBlogs.Core.Configs
             }
         }
 
+        /// <summary>
+        /// 检查友链
+        /// </summary>
         public static void CheckLinks()
         {
             HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.CheckLinks), "default");
         }
 
+        /// <summary>
+        /// 每日任务
+        /// </summary>
         public static void EverydayJob()
         {
             HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.EverydayJob), "default");

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

@@ -6,10 +6,15 @@ using Masuit.MyBlogs.Core.Models.ViewModel;
 using System.Linq;
 
 namespace Masuit.MyBlogs.Core.Configs
-
 {
+    /// <summary>
+    /// 注册automapper
+    /// </summary>
     public static class RegisterAutomapper
     {
+        /// <summary>
+        /// 初始化
+        /// </summary>
         public static void Excute()
         {
             Mapper.Initialize(m =>

+ 12 - 3
src/Masuit.MyBlogs.Core/Controllers/BugController.cs

@@ -67,10 +67,19 @@ namespace Masuit.MyBlogs.Core.Controllers
         public ActionResult PageData([FromBody]PageFilter filter)
         {
             UserInfoOutputDto user = HttpContext.Session.GetByRedis<UserInfoOutputDto>(SessionKey.UserInfo) ?? new UserInfoOutputDto();
-            List<Issue> list = string.IsNullOrEmpty(filter.Kw) ? IssueService.LoadPageEntitiesFromL2CacheNoTracking(filter.Page, filter.Size, out int total, i => i.Level != BugLevel.Fatal || user.IsAdmin, i => i.SubmitTime, false).ToList() : IssueService.SearchPage(filter.Page, filter.Size, out total, new[]
+            List<Issue> list;
+            int total;
+            if (string.IsNullOrEmpty(filter.Kw))
             {
-                filter.Kw
-            }, i => (i.Level != BugLevel.Fatal || user.IsAdmin), i => i.SubmitTime, false).ToList();
+                list = IssueService.LoadPageEntitiesFromL2CacheNoTracking(filter.Page, filter.Size, out total, i => i.Status != Status.Handled || i.Level != BugLevel.Fatal || user.IsAdmin, i => i.SubmitTime, false).ToList();
+            }
+            else
+            {
+                var searchResult = IssueService.SearchPage(filter.Page, filter.Size, filter.Kw);
+                total = searchResult.Total;
+                list = searchResult.Results.Where(i => i.Status != Status.Handled || i.Level != BugLevel.Fatal || user.IsAdmin).ToList();
+            }
+
             var pageCount = Math.Ceiling(total * 1.0 / filter.Size).ToInt32();
             return PageResult(list.Select(i => new
             {

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

@@ -62,6 +62,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <param name="hostingEnvironment"></param>
         /// <param name="searchEngine"></param>
         /// <param name="luceneIndexer"></param>
+        /// <param name="luceneIndexSearcher"></param>
         public PostController(IPostService postService, ICategoryService categoryService, IBroadcastService broadcastService, ISeminarService seminarService, IPostHistoryVersionService postHistoryVersionService, IHostingEnvironment hostingEnvironment, ISearchEngine<DataContext> searchEngine, ILuceneIndexer luceneIndexer, ILuceneIndexSearcher luceneIndexSearcher)
         {
             PostService = postService;

+ 2 - 0
src/Masuit.MyBlogs.Core/Controllers/SearchController.cs

@@ -28,11 +28,13 @@ namespace Masuit.MyBlogs.Core.Controllers
         public ISearchDetailsService SearchDetailsService { get; set; }
         private readonly IPostService _postService;
         private readonly ISearchEngine<DataContext> _searchEngine;
+
         /// <summary>
         /// 站内搜索
         /// </summary>
         /// <param name="searchDetailsService"></param>
         /// <param name="postService"></param>
+        /// <param name="searchEngine"></param>
         public SearchController(ISearchDetailsService searchDetailsService, IPostService postService, ISearchEngine<DataContext> searchEngine)
         {
             SearchDetailsService = searchDetailsService;

+ 3 - 0
src/Masuit.MyBlogs.Core/Extensions/AuthorityAttribute.cs

@@ -14,6 +14,9 @@ using System.Web;
 
 namespace Masuit.MyBlogs.Core.Extensions
 {
+    /// <summary>
+    /// 授权验证过滤器
+    /// </summary>
     public class AuthorityAttribute : ActionFilterAttribute
     {
         /// <summary>在执行操作方法之前由 ASP.NET MVC 框架调用。</summary>

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

@@ -7,13 +7,27 @@ using System.Threading.Tasks;
 
 namespace Masuit.MyBlogs.Core.Extensions
 {
+    /// <summary>
+    /// 异常拦截中间件
+    /// </summary>
     public class ExceptionMiddleware
     {
         private readonly RequestDelegate _next;
+
+        /// <summary>
+        /// 异常拦截中间件
+        /// </summary>
+        /// <param name="next"></param>
         public ExceptionMiddleware(RequestDelegate next)
         {
             _next = next;
         }
+
+        /// <summary>
+        /// 执行调用
+        /// </summary>
+        /// <param name="context"></param>
+        /// <returns></returns>
         public async Task Invoke(HttpContext context)
         {
             try
@@ -69,4 +83,4 @@ namespace Masuit.MyBlogs.Core.Extensions
             }
         }
     }
-}
+}

+ 5 - 0
src/Masuit.MyBlogs.Core/Extensions/FirewallMiddleware.cs

@@ -29,6 +29,11 @@ namespace Masuit.MyBlogs.Core.Extensions
             _redisHelper = redisHelper;
         }
 
+        /// <summary>
+        /// 执行调用
+        /// </summary>
+        /// <param name="context"></param>
+        /// <returns></returns>
         public async Task Invoke(HttpContext context)
         {
             string httpMethod = context.Request.Method;

+ 32 - 0
src/Masuit.MyBlogs.Core/Extensions/Hangfire/HangfireBackJob.cs

@@ -16,6 +16,9 @@ using System.Threading.Tasks;
 
 namespace Masuit.MyBlogs.Core.Extensions.Hangfire
 {
+    /// <summary>
+    /// hangfire后台任务
+    /// </summary>
     public class HangfireBackJob : IHangfireBackJob
     {
         private readonly IUserInfoService _userInfoService;
@@ -27,6 +30,17 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
         private readonly IHttpClientFactory _httpClientFactory;
         private readonly IHostingEnvironment _hostingEnvironment;
 
+        /// <summary>
+        /// hangfire后台任务
+        /// </summary>
+        /// <param name="userInfoService"></param>
+        /// <param name="postService"></param>
+        /// <param name="settingService"></param>
+        /// <param name="searchDetailsService"></param>
+        /// <param name="linksService"></param>
+        /// <param name="redisHelper"></param>
+        /// <param name="httpClientFactory"></param>
+        /// <param name="hostingEnvironment"></param>
         public HangfireBackJob(IUserInfoService userInfoService, IPostService postService, ISystemSettingService settingService, ISearchDetailsService searchDetailsService, ILinksService linksService, RedisHelper redisHelper, IHttpClientFactory httpClientFactory, IHostingEnvironment hostingEnvironment)
         {
             _userInfoService = userInfoService;
@@ -39,6 +53,12 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
             _hostingEnvironment = hostingEnvironment;
         }
 
+        /// <summary>
+        /// 登录记录
+        /// </summary>
+        /// <param name="userInfo"></param>
+        /// <param name="ip"></param>
+        /// <param name="type"></param>
         public void LoginRecord(UserInfoOutputDto userInfo, string ip, LoginType type)
         {
             var result = ip.GetPhysicsAddressInfo().Result;
@@ -62,6 +82,10 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
             }
         }
 
+        /// <summary>
+        /// 文章定时发布
+        /// </summary>
+        /// <param name="p"></param>
         public void PublishPost(Post p)
         {
             p.Status = Status.Pended;
@@ -81,6 +105,10 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
             }
         }
 
+        /// <summary>
+        /// 文章访问记录
+        /// </summary>
+        /// <param name="pid"></param>
         public void RecordPostVisit(int pid)
         {
             Post post = _postService.GetById(pid);
@@ -101,6 +129,10 @@ namespace Masuit.MyBlogs.Core.Extensions.Hangfire
             _postService.UpdateEntitySaved(post);
         }
 
+        /// <summary>
+        /// 防火墙拦截日志
+        /// </summary>
+        /// <param name="s"></param>
         public static void InterceptLog(IpIntercepter s)
         {
             using (RedisHelper redisHelper = RedisHelper.GetInstance())

+ 27 - 0
src/Masuit.MyBlogs.Core/Extensions/Hangfire/IHangfireBackJob.cs

@@ -4,12 +4,39 @@ using Masuit.MyBlogs.Core.Models.Enum;
 
 namespace Masuit.MyBlogs.Core.Extensions.Hangfire
 {
+    /// <summary>
+    /// hangfire后台任务
+    /// </summary>
     public interface IHangfireBackJob
     {
+        /// <summary>
+        /// 登陆记录
+        /// </summary>
+        /// <param name="userInfo"></param>
+        /// <param name="ip"></param>
+        /// <param name="type"></param>
         void LoginRecord(UserInfoOutputDto userInfo, string ip, LoginType type);
+
+        /// <summary>
+        /// 文章定时发表
+        /// </summary>
+        /// <param name="p"></param>
         void PublishPost(Post p);
+
+        /// <summary>
+        /// 文章访问记录
+        /// </summary>
+        /// <param name="pid"></param>
         void RecordPostVisit(int pid);
+
+        /// <summary>
+        /// 每日任务
+        /// </summary>
         void EverydayJob();
+
+        /// <summary>
+        /// 友链检查
+        /// </summary>
         void CheckLinks();
     }
 }

+ 2 - 2
src/Masuit.MyBlogs.Core/Hubs/MyHub.cs

@@ -65,7 +65,7 @@ namespace Masuit.MyBlogs.Core.Hubs
         /// <summary>
         /// 性能计数器缓存
         /// </summary>
-        public static ConcurrentLimitedQueue<PerformanceCounter> PerformanceCounter { get; set; } = new ConcurrentLimitedQueue<PerformanceCounter>(1000);
+        public static ConcurrentLimitedQueue<PerformanceCounter> PerformanceCounter { get; set; } = new ConcurrentLimitedQueue<PerformanceCounter>(5000);
 
         static MyHub()
         {
@@ -89,7 +89,7 @@ namespace Masuit.MyBlogs.Core.Hubs
                         Console.ForegroundColor = ConsoleColor.White;
                         errorCount++;
                     }
-                    Thread.Sleep(5000);
+                    Thread.Sleep(1000);
                 }
             });
         }

+ 8 - 243
src/Masuit.MyBlogs.Core/Infrastructure/Services/BaseService.cs

@@ -1,8 +1,8 @@
-using AutoMapper.QueryableExtensions;
-using EFSecondLevelCache.Core;
+using EFSecondLevelCache.Core;
+using Masuit.LuceneEFCore.SearchEngine.Interfaces;
+using Masuit.MyBlogs.Core.Infrastructure.Application;
 using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
-using NinjaNye.SearchExtensions;
 using System;
 using System.Collections.Generic;
 using System.Data.SqlClient;
@@ -19,10 +19,13 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
     public class BaseService<T> : IBaseService<T> where T : class, new()
     {
         public virtual IBaseRepository<T> BaseDal { get; set; }
-
-        public BaseService(IBaseRepository<T> repository)
+        protected readonly ISearchEngine<DataContext> _searchEngine;
+        protected readonly ILuceneIndexSearcher _searcher;
+        public BaseService(IBaseRepository<T> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher)
         {
             BaseDal = repository;
+            _searchEngine = searchEngine;
+            _searcher = searcher;
         }
 
         /// <summary>
@@ -531,244 +534,6 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
             return BaseDal.LoadPageEntitiesFromL2CacheNoTracking(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
         }
 
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <typeparam name="TDto"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<TDto> SearchPage<TOrder, TDto>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = GetAllNoTracking().Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).ProjectTo<TDto>().ToList();
-        }
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <typeparam name="TDto"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<TDto> SearchPage<TOrder, TDto>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = LoadEntities(where).Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).ProjectTo<TDto>().ToList();
-        }
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<T> SearchPage<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = GetAll().Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).ToList();
-        }
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<T> SearchPage<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = LoadEntities(where).Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).ToList();
-        }
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<T> SearchPageNotracking<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = GetAllNoTracking().Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).ToList();
-        }
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<T> SearchPageNotracking<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = LoadEntitiesNoTracking(where).Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).ToList();
-        }
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <typeparam name="TDto"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<TDto> SearchPageFromCache<TOrder, TDto>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = GetAllNoTracking().Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).ProjectTo<TDto>().Cacheable().ToList();
-        }
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <typeparam name="TDto"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<TDto> SearchPageFromCache<TOrder, TDto>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = LoadEntities(where).Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).ProjectTo<TDto>().Cacheable().ToList();
-        }
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<T> SearchPageFromCache<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = GetAll().Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).Cacheable().ToList();
-        }
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<T> SearchPageFromCache<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = LoadEntities(where).Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).Cacheable().ToList();
-        }
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<T> SearchPageFromCacheNotracking<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = GetAllNoTracking().Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).Cacheable().ToList();
-        }
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        public List<T> SearchPageFromCacheNotracking<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true)
-        {
-            var query = LoadEntitiesNoTracking(where).Search().Containing(keywords);
-            total = query.Count();
-            IOrderedQueryable<T> order = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
-            return order.Skip((page - 1) * size).Take(size).Cacheable().ToList();
-        }
-
         /// <summary>
         /// 根据ID删除实体
         /// </summary>

+ 4 - 2
src/Masuit.MyBlogs.Core/Infrastructure/Services/CategoryService.cs

@@ -1,4 +1,6 @@
-using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
+using Masuit.LuceneEFCore.SearchEngine.Interfaces;
+using Masuit.MyBlogs.Core.Infrastructure.Application;
+using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.Entity;
 
@@ -30,7 +32,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
             return b;
         }
 
-        public CategoryService(IBaseRepository<Category> repository) : base(repository)
+        public CategoryService(IBaseRepository<Category> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }

+ 4 - 2
src/Masuit.MyBlogs.Core/Infrastructure/Services/CommentService.cs

@@ -1,4 +1,6 @@
-using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
+using Masuit.LuceneEFCore.SearchEngine.Interfaces;
+using Masuit.MyBlogs.Core.Infrastructure.Application;
+using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.Entity;
 using System.Collections.Generic;
@@ -33,7 +35,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
             return 0;
         }
 
-        public CommentService(IBaseRepository<Comment> repository) : base(repository)
+        public CommentService(IBaseRepository<Comment> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }

+ 0 - 166
src/Masuit.MyBlogs.Core/Infrastructure/Services/Interface/IBaseService.cs

@@ -388,172 +388,6 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
         /// <returns>还未执行的SQL语句</returns>
         IEnumerable<T> LoadPageEntitiesFromL2CacheNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
 
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <typeparam name="TDto"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<TDto> SearchPage<TOrder, TDto>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <typeparam name="TDto"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<TDto> SearchPage<TOrder, TDto>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<T> SearchPage<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<T> SearchPage<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<T> SearchPageNotracking<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<T> SearchPageNotracking<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <typeparam name="TDto"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<TDto> SearchPageFromCache<TOrder, TDto>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <typeparam name="TDto"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<TDto> SearchPageFromCache<TOrder, TDto>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<T> SearchPageFromCache<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<T> SearchPageFromCache<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<T> SearchPageFromCacheNotracking<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
-        /// <summary>
-        /// 搜索
-        /// </summary>
-        /// <typeparam name="TOrder"></typeparam>
-        /// <param name="page">第几页</param>
-        /// <param name="size">页大小</param>
-        /// <param name="total">总条数</param>
-        /// <param name="keywords">关键词</param>
-        /// <param name="where">其他条件</param>
-        /// <param name="orderBy">排序字段</param>
-        /// <param name="isAsc">升序排列?</param>
-        /// <returns></returns>
-        List<T> SearchPageFromCacheNotracking<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> orderBy, bool isAsc = true);
-
         /// <summary>
         /// 根据ID删除实体
         /// </summary>

+ 6 - 2
src/Masuit.MyBlogs.Core/Infrastructure/Services/Interface/IServices.cs

@@ -1,4 +1,5 @@
-using Masuit.MyBlogs.Core.Models.Entity;
+using Masuit.MyBlogs.Core.Models.DTO;
+using Masuit.MyBlogs.Core.Models.Entity;
 
 namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
 {
@@ -12,7 +13,10 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
 
     public partial interface IInternalMessageService : IBaseService<InternalMessage> { }
 
-    public partial interface IIssueService : IBaseService<Issue> { }
+    public partial interface IIssueService : IBaseService<Issue>
+    {
+        SearchResult<Issue> SearchPage(int page, int size, string keyword);
+    }
 
     public partial interface ILinksService : IBaseService<Links> { }
 

+ 4 - 2
src/Masuit.MyBlogs.Core/Infrastructure/Services/LeaveMessageService.cs

@@ -1,4 +1,6 @@
-using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
+using Masuit.LuceneEFCore.SearchEngine.Interfaces;
+using Masuit.MyBlogs.Core.Infrastructure.Application;
+using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.Entity;
 using System.Collections.Generic;
@@ -30,7 +32,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
             return 0;
         }
 
-        public LeaveMessageService(IBaseRepository<LeaveMessage> repository) : base(repository)
+        public LeaveMessageService(IBaseRepository<LeaveMessage> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }

+ 4 - 3
src/Masuit.MyBlogs.Core/Infrastructure/Services/MenuService.cs

@@ -1,8 +1,9 @@
-using System.Collections.Generic;
+using Masuit.LuceneEFCore.SearchEngine.Interfaces;
+using Masuit.MyBlogs.Core.Infrastructure.Application;
 using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.Entity;
-using System.Linq;
+using System.Collections.Generic;
 
 namespace Masuit.MyBlogs.Core.Infrastructure.Services
 {
@@ -18,7 +19,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
             return SqlQuery<Menu>("exec sp_getChildrenMenusByParentId " + id);
         }
 
-        public MenuService(IBaseRepository<Menu> repository) : base(repository)
+        public MenuService(IBaseRepository<Menu> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }

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

@@ -6,6 +6,7 @@ using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 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 PanGu;
 using PanGu.HighLight;
 using System.Linq;
@@ -14,17 +15,13 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
 {
     public partial class PostService : BaseService<Post>, IPostService
     {
-        private readonly ILuceneIndexSearcher _searcher;
-        private readonly ISearchEngine<DataContext> _searchEngine;
-        public PostService(IPostRepository repository, ILuceneIndexSearcher searcher, ISearchEngine<DataContext> searchEngine) : base(repository)
+        public PostService(IPostRepository repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
-            _searcher = searcher;
-            _searchEngine = searchEngine;
         }
         public SearchResult<PostOutputDto> SearchPage(int page, int size, string keyword)
         {
             var searchResult = _searchEngine.ScoredSearch<Post>(new SearchOptions(keyword, page, size, typeof(Post)));
-            var posts = searchResult.Results.Select(p => p.Entity.Mapper<PostOutputDto>()).ToList();
+            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>");
             var highlighter = new Highlighter(simpleHtmlFormatter, new Segment()) { FragmentSize = 200 };
             var keywords = _searcher.CutKeywords(keyword);
@@ -62,10 +59,5 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
                 Total = searchResult.TotalHits
             };
         }
-
-        public PostService(IBaseRepository<Post> repository, ISearchEngine<DataContext> searchEngine) : base(repository)
-        {
-            _searchEngine = searchEngine;
-        }
     }
 }

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

@@ -1,124 +1,141 @@
-using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
+using Masuit.LuceneEFCore.SearchEngine;
+using Masuit.LuceneEFCore.SearchEngine.Interfaces;
+using Masuit.MyBlogs.Core.Infrastructure.Application;
+using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 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 System.Linq;
 
 namespace Masuit.MyBlogs.Core.Infrastructure.Services
 {
     public partial class BroadcastService : BaseService<Broadcast>, IBroadcastService
     {
-        public BroadcastService(IBaseRepository<Broadcast> repository) : base(repository)
+        public BroadcastService(IBaseRepository<Broadcast> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class ContactsService : BaseService<Contacts>, IContactsService
     {
-        public ContactsService(IBaseRepository<Contacts> repository) : base(repository)
+        public ContactsService(IBaseRepository<Contacts> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class DonateService : BaseService<Donate>, IDonateService
     {
-        public DonateService(IBaseRepository<Donate> repository) : base(repository)
+        public DonateService(IBaseRepository<Donate> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class FastShareService : BaseService<FastShare>, IFastShareService
     {
-        public FastShareService(IBaseRepository<FastShare> repository) : base(repository)
+        public FastShareService(IBaseRepository<FastShare> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class InternalMessageService : BaseService<InternalMessage>, IInternalMessageService
     {
-        public InternalMessageService(IBaseRepository<InternalMessage> repository) : base(repository)
+        public InternalMessageService(IBaseRepository<InternalMessage> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class IssueService : BaseService<Issue>, IIssueService
     {
-        public IssueService(IBaseRepository<Issue> repository) : base(repository)
+        public IssueService(IBaseRepository<Issue> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
+        public SearchResult<Issue> SearchPage(int page, int size, string keyword)
+        {
+            var searchResult = _searchEngine.ScoredSearch<Issue>(new SearchOptions(keyword, page, size, typeof(Issue)));
+            var posts = searchResult.Results.Select(p => p.Entity).Where(i => i.Status == Status.Handled).ToList();
+            return new SearchResult<Issue>()
+            {
+                Results = posts,
+                Elapsed = searchResult.Elapsed,
+                Total = searchResult.TotalHits
+            };
+        }
     }
 
     public partial class LinksService : BaseService<Links>, ILinksService
     {
-        public LinksService(IBaseRepository<Links> repository) : base(repository)
+        public LinksService(IBaseRepository<Links> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class LoginRecordService : BaseService<LoginRecord>, ILoginRecordService
     {
-        public LoginRecordService(IBaseRepository<LoginRecord> repository) : base(repository)
+        public LoginRecordService(IBaseRepository<LoginRecord> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class MiscService : BaseService<Misc>, IMiscService
     {
-        public MiscService(IBaseRepository<Misc> repository) : base(repository)
+        public MiscService(IBaseRepository<Misc> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class NoticeService : BaseService<Notice>, INoticeService
     {
-        public NoticeService(IBaseRepository<Notice> repository) : base(repository)
+        public NoticeService(IBaseRepository<Notice> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class PostAccessRecordService : BaseService<PostAccessRecord>, IPostAccessRecordService
     {
-        public PostAccessRecordService(IBaseRepository<PostAccessRecord> repository) : base(repository)
+        public PostAccessRecordService(IBaseRepository<PostAccessRecord> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class PostHistoryVersionService : BaseService<PostHistoryVersion>, IPostHistoryVersionService
     {
-        public PostHistoryVersionService(IBaseRepository<PostHistoryVersion> repository) : base(repository)
+        public PostHistoryVersionService(IBaseRepository<PostHistoryVersion> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class SearchDetailsService : BaseService<SearchDetails>, ISearchDetailsService
     {
-        public SearchDetailsService(IBaseRepository<SearchDetails> repository) : base(repository)
+        public SearchDetailsService(IBaseRepository<SearchDetails> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class SeminarService : BaseService<Seminar>, ISeminarService
     {
-        public SeminarService(IBaseRepository<Seminar> repository) : base(repository)
+        public SeminarService(IBaseRepository<Seminar> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class SystemSettingService : BaseService<SystemSetting>, ISystemSettingService
     {
-        public SystemSettingService(IBaseRepository<SystemSetting> repository) : base(repository)
+        public SystemSettingService(IBaseRepository<SystemSetting> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class SeminarPostService : BaseService<SeminarPost>, ISeminarPostService
     {
-        public SeminarPostService(IBaseRepository<SeminarPost> repository) : base(repository)
+        public SeminarPostService(IBaseRepository<SeminarPost> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }
 
     public partial class SeminarPostHistoryVersionService : BaseService<SeminarPostHistoryVersion>, ISeminarPostHistoryVersionService
     {
-        public SeminarPostHistoryVersionService(IBaseRepository<SeminarPostHistoryVersion> repository) : base(repository)
+        public SeminarPostHistoryVersionService(IBaseRepository<SeminarPostHistoryVersion> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }

+ 3 - 1
src/Masuit.MyBlogs.Core/Infrastructure/Services/UserInfoService.cs

@@ -1,4 +1,6 @@
 using Common;
+using Masuit.LuceneEFCore.SearchEngine.Interfaces;
+using Masuit.MyBlogs.Core.Infrastructure.Application;
 using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 using Masuit.MyBlogs.Core.Infrastructure.Services;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
@@ -146,7 +148,7 @@ namespace Service
             return false;
         }
 
-        public UserInfoService(IBaseRepository<UserInfo> repository) : base(repository)
+        public UserInfoService(IBaseRepository<UserInfo> repository, ISearchEngine<DataContext> searchEngine, ILuceneIndexSearcher searcher) : base(repository, searchEngine, searcher)
         {
         }
     }

+ 0 - 1
src/Masuit.MyBlogs.Core/Masuit.MyBlogs.Core.csproj

@@ -70,7 +70,6 @@
     <PackageReference Include="Microsoft.AspNetCore.App" />
     <PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="2.2.1" />
     <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.1" />
-    <PackageReference Include="NinjaNye.SearchExtensions" Version="3.0.0" />
     <PackageReference Include="PanGu.HighLight" Version="1.0.0" />
     <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" />
     <PackageReference Include="Quartz" Version="3.0.7" />

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

@@ -9,7 +9,7 @@ namespace Masuit.MyBlogs.Core.Models.Entity
     /// </summary>
     public class BaseEntity : LuceneIndexableBaseEntity
     {
-        [DefaultValue(Status.Default)]
+        [DefaultValue(Status.Default), LuceneIndex]
         public Status Status { get; set; }
     }
 }

+ 7 - 7
src/Masuit.MyBlogs.Core/Models/Entity/Issue.cs

@@ -1,9 +1,9 @@
-using System;
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-using Masuit.MyBlogs.Core.Models.Entity;
+using Masuit.LuceneEFCore.SearchEngine;
 using Masuit.MyBlogs.Core.Models.Enum;
 using Masuit.MyBlogs.Core.Models.Validation;
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
 
 namespace Masuit.MyBlogs.Core.Models.Entity
 {
@@ -35,19 +35,19 @@ namespace Masuit.MyBlogs.Core.Models.Entity
         /// <summary>
         /// 问题标题
         /// </summary>
-        [Required(ErrorMessage = "标题不能为空!")]
+        [Required(ErrorMessage = "标题不能为空!"), LuceneIndex]
         public string Title { get; set; }
 
         /// <summary>
         /// 存在问题的页面链接
         /// </summary>
-        [Required(ErrorMessage = "链接不能为空!")]
+        [Required(ErrorMessage = "链接不能为空!"), LuceneIndex]
         public string Link { get; set; }
 
         /// <summary>
         /// 问题的详细描述
         /// </summary>
-        [Required(ErrorMessage = "问题描述不能为空!"), SubmitCheck(20, 5000)]
+        [Required(ErrorMessage = "问题描述不能为空!"), SubmitCheck(20, 5000), LuceneIndex(IsHtml = true)]
         public string Description { get; set; }
 
         /// <summary>

+ 5 - 1
src/Masuit.MyBlogs.Core/Startup.cs

@@ -38,6 +38,7 @@ using Newtonsoft.Json;
 using Newtonsoft.Json.Serialization;
 using Swashbuckle.AspNetCore.Swagger;
 using System;
+using System.Collections.Generic;
 using System.Data;
 using System.Data.SqlClient;
 using System.IO;
@@ -201,7 +202,10 @@ namespace Masuit.MyBlogs.Core
             if (!Directory.Exists(lucenePath) || Directory.GetFiles(lucenePath).Length < 1)
             {
                 Console.WriteLine("开始自动创建Lucene索引库...");
-                searchEngine.CreateIndex();
+                searchEngine.CreateIndex(new List<string>()
+                {
+                    nameof(DataContext.Post),nameof(DataContext.Issues)
+                });
                 Console.WriteLine("索引库创建完成!");
             }
 

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

@@ -34,11 +34,11 @@
     <link href="~/ng-views/css/app.css" rel="stylesheet" />
 
     <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.2.0/highcharts.js"></script>
+    <script src="https://img.highcharts.com.cn/highstock/highstock.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.1.0/echarts.min.js"></script>
     <script src="~/Assets/echarts/china.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.0.3/highcharts-more.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/highcharts/6.0.3/js/modules/solid-gauge.js"></script>
+    <script src="https://img.highcharts.com.cn/highcharts/highcharts-more.js"></script>
+    <script src="https://img.highcharts.com.cn/highcharts/modules/solid-gauge.js"></script>
     <script src="https://img.hcharts.cn/highcharts-plugins/highcharts-zh_CN.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.9/angular.min.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.9/angular-animate.min.js"></script>

+ 90 - 2
src/Masuit.MyBlogs.Core/wwwroot/ng-views/controllers/dashboard.js

@@ -87,7 +87,7 @@
 	}
 	$scope.connectWebsocket();
 	$.post("/system/GetHistoryList", null, function(data) {
-		$('#cpu').highcharts({
+		Highcharts.stockChart("cpu",{
 			subtitle: {
 				text: document.ontouchstart === undefined ?
 				'鼠标拖动可以进行缩放' : '手势操作进行缩放'
@@ -162,6 +162,50 @@
 			scrollbar: {
 				enabled: false
 			},
+			rangeSelector : {
+				buttons: [{
+					type: 'minute',
+					count: 5,
+					text: '5分钟'
+				}, {
+					type: 'minute',
+					count: 15,
+					text: '15分钟'
+				}, {
+					type: 'minute',
+					count: 30,
+					text: '30分钟'
+				}, {
+					type: 'hour',
+					count: 1,
+					text: '1小时'
+				}, {
+					type: 'hour',
+					count: 2,
+					text: '2小时'
+				}, {
+					type: 'hour',
+					count: 5,
+					text: '5小时'
+				}, {
+					type: 'hour',
+					count: 12,
+					text: '12小时'
+				}, {
+					type: 'day',
+					count: 1,
+					text: '1天'
+				}, {
+					type: 'day',
+					count: 3,
+					text: '3天'
+				}, {
+					type: 'all',
+					text: 'All'
+				}],
+				inputEnabled: false,
+				selected : 1
+			},
 			tooltip: {
 				formatter: function() {
 					return '时间点:<b>' + Highcharts.dateFormat("%H:%M:%S", this.points[0].x) + '</b><br/>' +
@@ -235,7 +279,7 @@
 				},
 			}]
 		});
-		$('#io').highcharts({
+		Highcharts.stockChart("io",{
 			subtitle: {
 				text: document.ontouchstart === undefined ?
 				'鼠标拖动可以进行缩放' : '手势操作进行缩放'
@@ -287,6 +331,50 @@
 			title: {
 				text: '网络状态 和 磁盘I/O'
 			},
+			rangeSelector : {
+				buttons: [{
+					type: 'minute',
+					count: 5,
+					text: '5分钟'
+				}, {
+					type: 'minute',
+					count: 15,
+					text: '15分钟'
+				}, {
+					type: 'minute',
+					count: 30,
+					text: '30分钟'
+				}, {
+					type: 'hour',
+					count: 1,
+					text: '1小时'
+				}, {
+					type: 'hour',
+					count: 2,
+					text: '2小时'
+				}, {
+					type: 'hour',
+					count: 5,
+					text: '5小时'
+				}, {
+					type: 'hour',
+					count: 12,
+					text: '12小时'
+				}, {
+					type: 'day',
+					count: 1,
+					text: '1天'
+				}, {
+					type: 'day',
+					count: 3,
+					text: '3天'
+				}, {
+					type: 'all',
+					text: 'All'
+				}],
+				inputEnabled: false,
+				selected : 1
+			},
 			xAxis: {
 				type: 'datetime',
 				tickPixelInterval: 150