Переглянути джерело

干掉了访问记录功能。因为有点耗性能

懒得勤快 6 роки тому
батько
коміт
b7f1f2678c
29 змінених файлів з 173 додано та 1749 видалено
  1. 22 1
      src/BLL/BLL.csproj
  2. 45 18
      src/BLL/PostBll.cs
  3. 7 1
      src/BLL/packages.config
  4. 0 1
      src/Common/Common.csproj
  5. 4 34
      src/Common/CommonHelper.cs
  6. 3 3
      src/DAL/DAL.csproj
  7. 2 2
      src/DAL/packages.config
  8. 1 0
      src/IBLL/IBLL.csproj
  9. 2 2
      src/IBLL/IMenuBll.cs
  10. 6 18
      src/IBLL/IPostBll.cs
  11. 22 57
      src/Masuit.MyBlogs.WebApp/App_Start/HangfireConfig.cs
  12. 0 6
      src/Masuit.MyBlogs.WebApp/Controllers/PostController.cs
  13. 11 16
      src/Masuit.MyBlogs.WebApp/Controllers/SearchController.cs
  14. 0 19
      src/Masuit.MyBlogs.WebApp/Controllers/SystemController.cs
  15. 2 91
      src/Masuit.MyBlogs.WebApp/Global.asax.cs
  16. 11 40
      src/Masuit.MyBlogs.WebApp/Masuit.MyBlogs.WebApp.csproj
  17. 3 366
      src/Masuit.MyBlogs.WebApp/Models/Hangfire/HangfireBackJob.cs
  18. 0 6
      src/Masuit.MyBlogs.WebApp/Models/Hangfire/IHangfireBackJob.cs
  19. 15 482
      src/Masuit.MyBlogs.WebApp/Models/LuceneHelper.cs
  20. 3 6
      src/Masuit.MyBlogs.WebApp/Models/MyActionFilterAttribute.cs
  21. 3 2
      src/Masuit.MyBlogs.WebApp/Startup.cs
  22. 1 1
      src/Masuit.MyBlogs.WebApp/Views/Shared/_Layout.cshtml
  23. 0 12
      src/Masuit.MyBlogs.WebApp/ng-views/app/route.config.js
  24. 0 0
      src/Masuit.MyBlogs.WebApp/ng-views/app/route.config.min.js
  25. 1 545
      src/Masuit.MyBlogs.WebApp/ng-views/controllers/analysis.js
  26. 2 7
      src/Masuit.MyBlogs.WebApp/ng-views/template/sidebar-left.html
  27. 5 7
      src/Masuit.MyBlogs.WebApp/packages.config
  28. 1 5
      src/Models/Models.csproj
  29. 1 1
      src/Models/packages.config

+ 22 - 1
src/BLL/BLL.csproj

@@ -34,6 +34,9 @@
     <Reference Include="AngleSharp, Version=0.9.9.0, Culture=neutral, PublicKeyToken=e83494dcdc6d31ea, processorArchitecture=MSIL">
       <HintPath>..\packages\AngleSharp.0.9.11\lib\net45\AngleSharp.dll</HintPath>
     </Reference>
+    <Reference Include="AutoMapper, Version=8.0.0.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
+      <HintPath>..\packages\AutoMapper.8.0.0\lib\net461\AutoMapper.dll</HintPath>
+    </Reference>
     <Reference Include="EFSecondLevelCache, Version=1.2.0.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\EFSecondLevelCache.1.2.0.0\lib\net45\EFSecondLevelCache.dll</HintPath>
     </Reference>
@@ -44,15 +47,25 @@
       <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
     </Reference>
     <Reference Include="HtmlSanitizer, Version=3.0.0.0, Culture=neutral, PublicKeyToken=61c49a1a9e79cc28, processorArchitecture=MSIL">
-      <HintPath>..\packages\HtmlSanitizer.4.0.199\lib\net45\HtmlSanitizer.dll</HintPath>
+      <HintPath>..\packages\HtmlSanitizer.4.0.204\lib\net45\HtmlSanitizer.dll</HintPath>
     </Reference>
     <Reference Include="ICSharpCode.SharpZipLib, Version=1.1.0.145, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
       <HintPath>..\packages\SharpZipLib.1.1.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
     </Reference>
     <Reference Include="Microsoft.CSharp" />
+    <Reference Include="Microsoft.VisualBasic" />
     <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
       <HintPath>..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
+    <Reference Include="NinjaNye.SearchExtensions, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\NinjaNye.SearchExtensions.2.2.0\lib\net45\NinjaNye.SearchExtensions.dll</HintPath>
+    </Reference>
+    <Reference Include="PanGu.Core, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\PanGu.Core.1.0.0\lib\net451\PanGu.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="PanGu.HighLight, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\PanGu.HighLight.1.0.0\lib\net451\PanGu.HighLight.dll</HintPath>
+    </Reference>
     <Reference Include="StackExchange.Redis, Version=1.2.6.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\StackExchange.Redis.1.2.6\lib\net46\StackExchange.Redis.dll</HintPath>
     </Reference>
@@ -61,6 +74,13 @@
     <Reference Include="System.Core" />
     <Reference Include="System.Data" />
     <Reference Include="System.IO.Compression" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
+      <HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Xml.Serialization" />
+    <Reference Include="System.Xml.XmlSerializer" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="BaseBLL.cs" />
@@ -73,6 +93,7 @@
     <Compile Include="CommentBll.cs" />
     <Compile Include="LeaveMessageBll.cs" />
     <Compile Include="MenuBll.cs" />
+    <Compile Include="PostBll.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="UserInfoBll.cs" />
   </ItemGroup>

+ 45 - 18
src/BLL/PostBll.cs

@@ -1,29 +1,56 @@
-using System.Collections.Generic;
-using System.Linq;
+using AutoMapper.QueryableExtensions;
+using Masuit.Tools.Html;
 using Models.DTO;
 using Models.Entity;
-using Models.Enum;
+using NinjaNye.SearchExtensions;
+using PanGu;
+using PanGu.HighLight;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
 
 namespace BLL
 {
     public partial class PostBll
     {
-        public bool MoveToCategory(int pid, int cid)
+        public List<PostOutputDto> SearchPage<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<Post, TOrder>> orderBy)
         {
-            Post post = GetById(pid);
-            post.CategoryId = cid;
-            return UpdateEntitySaved(post);
-        }
-    }
-    public partial class MenuBll
-    {
-        /// <summary>
-        /// 获取菜单
-        /// </summary>
-        /// <returns></returns>
-        public IList<MenuOutputDto> GetMenus()
-        {
-            return BaseDal.LoadEntitiesFromCacheNoTracking<MenuOutputDto>(m => m.Status == Status.Available).ToList();
+            var query = GetAllNoTracking().Search().Containing(keywords);
+            total = query.Count();
+            var posts = query.OrderByDescending(orderBy).Skip((page - 1) * size).Take(size).ProjectTo<PostOutputDto>().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 };
+
+            foreach (var p in posts)
+            {
+                p.Content = p.Content.RemoveHtml();
+                foreach (var s in keywords)
+                {
+                    string frag;
+                    if (p.Title.Contains(s) && !string.IsNullOrEmpty(frag = highlighter.GetBestFragment(s, p.Title)))
+                    {
+                        p.Title = frag;
+                        break;
+                    }
+                }
+                bool handled = false;
+                foreach (var s in keywords)
+                {
+                    string frag;
+                    if (p.Content.Contains(s) && !string.IsNullOrEmpty(frag = highlighter.GetBestFragment(s, p.Content)))
+                    {
+                        p.Content = frag;
+                        handled = true;
+                        break;
+                    }
+                }
+                if (p.Content.Length > 200 && !handled)
+                {
+                    p.Content = p.Content.Substring(0, 200);
+                }
+            }
+            return posts;
         }
     }
 }

+ 7 - 1
src/BLL/packages.config

@@ -1,11 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="AngleSharp" version="0.9.11" targetFramework="net461" />
+  <package id="AutoMapper" version="8.0.0" targetFramework="net461" />
   <package id="EFSecondLevelCache" version="1.2.0.0" targetFramework="net45" />
   <package id="EntityFramework" version="6.2.0" targetFramework="net45" />
   <package id="EntityFramework.zh-Hans" version="6.2.0" targetFramework="net45" />
-  <package id="HtmlSanitizer" version="4.0.199" targetFramework="net461" />
+  <package id="HtmlSanitizer" version="4.0.204" targetFramework="net461" />
   <package id="Newtonsoft.Json" version="12.0.1" targetFramework="net461" />
+  <package id="NinjaNye.SearchExtensions" version="2.2.0" targetFramework="net461" />
+  <package id="PanGu.Core" version="1.0.0" targetFramework="net461" />
+  <package id="PanGu.HighLight" version="1.0.0" targetFramework="net461" />
   <package id="SharpZipLib" version="1.1.0" targetFramework="net461" />
   <package id="StackExchange.Redis" version="1.2.6" targetFramework="net46" />
+  <package id="System.Linq.Queryable" version="4.3.0" targetFramework="net461" />
+  <package id="System.ValueTuple" version="4.5.0" targetFramework="net461" />
 </packages>

+ 0 - 1
src/Common/Common.csproj

@@ -82,7 +82,6 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="AggregatedCounter.cs" />
     <Compile Include="CommonHelper.cs" />
     <Compile Include="DocumentConvert.cs" />
     <Compile Include="HangfireHelper.cs" />

+ 4 - 34
src/Common/CommonHelper.cs

@@ -16,7 +16,6 @@ using Masuit.Tools.Models;
 using Masuit.Tools.NoSQL;
 using Masuit.Tools.Security;
 using Models.Application;
-using Models.DTO;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
 
@@ -99,15 +98,12 @@ namespace Common
                     return 1;
                 }
             }
-            set
-            {
-            }
         }
 
         /// <summary>
-        /// 访问量
+        /// 平均访问量
         /// </summary>
-        public static double Todaypv
+        public static double AverageCount
         {
             get
             {
@@ -115,7 +111,7 @@ namespace Common
                 {
                     using (var redisHelper = RedisHelper.GetInstance())
                     {
-                        return redisHelper.ListRange<Interview>($"Interview:{DateTime.Today:yyyy:MM:dd}").Count;
+                        return redisHelper.GetString<double>("Interview:ViewCount") / redisHelper.GetString<double>("Interview:RunningDays");
                     }
                 }
                 catch
@@ -123,42 +119,16 @@ namespace Common
                     return 1;
                 }
             }
-            set
-            {
-            }
         }
 
-        /// <summary>
-        /// 平均访问量
-        /// </summary>
-        public static double AverageCount { get; set; }
-
         /// <summary>
         /// 网站启动时间
         /// </summary>
         public static DateTime StartupTime { get; set; } = DateTime.Now;
 
         /// <summary>
-        /// 在线人数
+        /// IP黑名单地址段
         /// </summary>
-        public static int OnlineCount
-        {
-            get
-            {
-                try
-                {
-                    using (var redisHelper = RedisHelper.GetInstance(1))
-                    {
-                        return redisHelper.GetServer().Keys(1, "Session:*").Count();
-                    }
-                }
-                catch
-                {
-                    return 1;
-                }
-            }
-        }
-
         public static Dictionary<string, string> DenyIPRange { get; set; }
 
         /// <summary>

+ 3 - 3
src/DAL/DAL.csproj

@@ -59,7 +59,7 @@
       <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
     </Reference>
     <Reference Include="HtmlSanitizer, Version=3.0.0.0, Culture=neutral, PublicKeyToken=61c49a1a9e79cc28, processorArchitecture=MSIL">
-      <HintPath>..\packages\HtmlSanitizer.4.0.199\lib\net45\HtmlSanitizer.dll</HintPath>
+      <HintPath>..\packages\HtmlSanitizer.4.0.204\lib\net45\HtmlSanitizer.dll</HintPath>
     </Reference>
     <Reference Include="ICSharpCode.SharpZipLib, Version=1.1.0.145, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
       <HintPath>..\packages\SharpZipLib.1.1.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
@@ -83,8 +83,8 @@
     <Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
       <HintPath>..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
     </Reference>
-    <Reference Include="Z.EntityFramework.Extensions, Version=3.16.21.0, Culture=neutral, PublicKeyToken=59b66d028979105b, processorArchitecture=MSIL">
-      <HintPath>..\packages\Z.EntityFramework.Extensions.3.16.21\lib\net45\Z.EntityFramework.Extensions.dll</HintPath>
+    <Reference Include="Z.EntityFramework.Extensions, Version=3.16.22.0, Culture=neutral, PublicKeyToken=59b66d028979105b, processorArchitecture=MSIL">
+      <HintPath>..\packages\Z.EntityFramework.Extensions.3.16.22\lib\net45\Z.EntityFramework.Extensions.dll</HintPath>
     </Reference>
     <Reference Include="Z.EntityFramework.Plus.EF6, Version=1.8.21.0, Culture=neutral, PublicKeyToken=59b66d028979105b, processorArchitecture=MSIL">
       <HintPath>..\packages\Z.EntityFramework.Plus.EF6.1.8.21\lib\net45\Z.EntityFramework.Plus.EF6.dll</HintPath>

+ 2 - 2
src/DAL/packages.config

@@ -9,13 +9,13 @@
   <package id="EntityFramework" version="6.2.0" targetFramework="net45" />
   <package id="EntityFramework.Extended" version="6.1.0.168" targetFramework="net45" />
   <package id="EntityFramework.zh-Hans" version="6.2.0" targetFramework="net45" />
-  <package id="HtmlSanitizer" version="4.0.199" targetFramework="net461" />
+  <package id="HtmlSanitizer" version="4.0.204" targetFramework="net461" />
   <package id="Mono.Reflection" version="1.1.0.0" targetFramework="net45" />
   <package id="Mono.Reflection.Core" version="1.1.1" targetFramework="net461" />
   <package id="Newtonsoft.Json" version="12.0.1" targetFramework="net461" />
   <package id="SharpZipLib" version="1.1.0" targetFramework="net461" />
   <package id="StackExchange.Redis" version="1.2.6" targetFramework="net45" requireReinstallation="true" />
   <package id="System.ValueTuple" version="4.5.0" targetFramework="net45" requireReinstallation="true" />
-  <package id="Z.EntityFramework.Extensions" version="3.16.21" targetFramework="net461" />
+  <package id="Z.EntityFramework.Extensions" version="3.16.22" targetFramework="net461" />
   <package id="Z.EntityFramework.Plus.EF6" version="1.8.21" targetFramework="net461" />
 </packages>

+ 1 - 0
src/IBLL/IBLL.csproj

@@ -55,6 +55,7 @@
     <Compile Include="ICommentBll.cs" />
     <Compile Include="ILeaveMessageBll.cs" />
     <Compile Include="IMenuBll.cs" />
+    <Compile Include="IPostBll.cs" />
     <Compile Include="IUserInfoBll.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>

+ 2 - 2
src/IBLL/IMenuBll.cs

@@ -1,5 +1,5 @@
-using System.Data.Entity.Infrastructure;
-using Models.Entity;
+using Models.Entity;
+using System.Data.Entity.Infrastructure;
 
 namespace IBLL
 {

+ 6 - 18
src/IBLL/IPostBll.cs

@@ -1,25 +1,13 @@
-using System.Collections.Generic;
-using Models.DTO;
+using Models.DTO;
+using Models.Entity;
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
 
 namespace IBLL
 {
     public partial interface IPostBll
     {
-        /// <summary>
-        /// 移动分类
-        /// </summary>
-        /// <param name="pid">文章ID</param>
-        /// <param name="cid">分类ID</param>
-        /// <returns></returns>
-        bool MoveToCategory(int pid, int cid);
-    }
-
-    public partial interface IMenuBll
-    {
-        /// <summary>
-        /// 获取菜单
-        /// </summary>
-        /// <returns></returns>
-        IList<MenuOutputDto> GetMenus();
+        List<PostOutputDto> SearchPage<TOrder>(int page, int size, out int total, string[] keywords, Expression<Func<Post, TOrder>> orderBy);
     }
 }

+ 22 - 57
src/Masuit.MyBlogs.WebApp/App_Start/HangfireConfig.cs

@@ -1,14 +1,11 @@
 using Common;
 using Hangfire;
-using Hangfire.Console;
-using Masuit.MyBlogs.WebApp.Models.Hangfire;
 using Masuit.Tools;
 using Masuit.Tools.NoSQL;
 using Masuit.Tools.Win32;
 using Models.Application;
 using Models.Enum;
 using System;
-using System.Configuration;
 using System.Data.Entity;
 using System.Linq;
 using System.Net.Http;
@@ -24,19 +21,8 @@ namespace Masuit.MyBlogs.WebApp
     {
         public static void Register()
         {
-            #region Hangfire配置
-
-            //GlobalConfiguration.Configuration.UseMemoryStorage();
-            GlobalConfiguration.Configuration.UseSqlServerStorage(ConfigurationManager.ConnectionStrings["DataContext"].ConnectionString).UseConsole();
-
-            #region 实现类注册
-
+            GlobalConfiguration.Configuration.UseRedisStorage();
             GlobalConfiguration.Configuration.UseAutofacActivator(AutofacConfig.Container);
-
-            #endregion
-
-            #region 服务启动
-
             Server = new BackgroundJobServer(new BackgroundJobServerOptions
             {
                 ServerName = $"{Environment.MachineName}", //服务器名称
@@ -46,16 +32,11 @@ namespace Masuit.MyBlogs.WebApp
                 //Queues = new[] { "masuit" } //队列名
             });
 
-            #endregion
-
-            #endregion
-
-            HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.UpdateLucene)); //更新文章索引
-            AggregateInterviews(); //访客统计
+            //AggregateInterviews(); //访客统计
             RecurringJob.AddOrUpdate(() => Windows.ClearMemorySilent(), Cron.Hourly); //每小时清理系统内存
             RecurringJob.AddOrUpdate(() => CheckLinks(), Cron.HourInterval(5)); //每5h检查友链
             RecurringJob.AddOrUpdate(() => EverydayJob(), Cron.Daily, TimeZoneInfo.Local); //每天的任务
-            RecurringJob.AddOrUpdate(() => AggregateInterviews(), Cron.Hourly(30)); //每半小时统计访客
+            //RecurringJob.AddOrUpdate(() => AggregateInterviews(), Cron.Hourly(30)); //每半小时统计访客
             using (RedisHelper redisHelper = RedisHelper.GetInstance())
             {
                 if (!redisHelper.KeyExists("ArticleViewToken"))
@@ -76,26 +57,15 @@ namespace Masuit.MyBlogs.WebApp
             using (RedisHelper redisHelper = RedisHelper.GetInstance())
             {
                 redisHelper.SetString("ArticleViewToken", string.Empty.CreateShortToken()); //更新加密文章的密码
+                redisHelper.StringIncrement("Interview:RunningDays");
             }
             using (DataContext db = new DataContext())
             {
-                //清理hangfire数据库
-                db.Database.ExecuteSqlCommand(@"DELETE FROM [HangFire].[Job] WHERE StateName='Succeeded' or StateName='Deleted';
-                    TRUNCATE TABLE [HangFire].[Counter];
-                    DELETE FROM [HangFire].[Hash] WHERE Field='Jobid';
-                    DELETE FROM [HangFire].[AggregatedCounter] WHERE ExpireAt is not null;
-                    UPDATE [HangFire].[AggregatedCounter] SET [Value] = (select count(1) from [HangFire].[Job] WHERE StateName<>'Succeeded' and StateName<>'Deleted')-1 WHERE [Key] = 'stats:succeeded'; 
-                    UPDATE [HangFire].[AggregatedCounter] SET [Value] = 0 WHERE [Key] = 'stats:deleted'");
                 DateTime time = DateTime.Now.AddMonths(-2);
                 db.SearchDetails.Where(s => s.SearchTime < time).DeleteFromQuery();
             }
         }
 
-        public static void AggregateInterviews()
-        {
-            HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.AggregateInterviews));
-        }
-
         /// <summary>
         /// 检查友链
         /// </summary>
@@ -107,34 +77,29 @@ namespace Masuit.MyBlogs.WebApp
                 Parallel.ForEach(links, link =>
                 {
                     Uri uri = new Uri(link.Url);
-                    using (HttpClient client = new HttpClient()
-                    {
-                        BaseAddress = uri
-                    })
+                    using (HttpClient client = new HttpClient())
                     {
                         client.DefaultRequestHeaders.UserAgent.Add(ProductInfoHeaderValue.Parse("Mozilla/5.0"));
                         client.DefaultRequestHeaders.Referrer = new Uri("https://masuit.com");
                         client.Timeout = TimeSpan.FromHours(10);
-                        client.GetAsync(uri.PathAndQuery)
-                            .ContinueWith(async t =>
+                        client.GetAsync(uri).ContinueWith(async t =>
+                        {
+                            if (t.IsCanceled || t.IsFaulted)
+                            {
+                                link.Status = Status.Unavailable;
+                                return;
+                            }
+                            var res = await t;
+                            if (res.IsSuccessStatusCode)
+                            {
+                                link.Status = !(await res.Content.ReadAsStringAsync()).Contains(CommonHelper.GetSettings("Domain")) ? Status.Unavailable : Status.Available;
+                            }
+                            else
                             {
-                                if (t.IsCanceled || t.IsFaulted)
-                                {
-                                    link.Status = Status.Unavailable;
-                                    return;
-                                }
-                                var res = await t;
-                                if (res.IsSuccessStatusCode)
-                                {
-                                    link.Status = !(await res.Content.ReadAsStringAsync()).Contains(CommonHelper.GetSettings("Domain")) ? Status.Unavailable : Status.Available;
-                                }
-                                else
-                                {
-                                    link.Status = Status.Unavailable;
-                                }
-                                db.Entry(link).State = EntityState.Modified;
-                            })
-                            .Wait();
+                                link.Status = Status.Unavailable;
+                            }
+                            db.Entry(link).State = EntityState.Modified;
+                        }).Wait();
                     }
                 });
                 db.SaveChanges();

+ 0 - 6
src/Masuit.MyBlogs.WebApp/Controllers/PostController.cs

@@ -401,7 +401,6 @@ namespace Masuit.MyBlogs.WebApp.Controllers
                 });
             }
 
-            HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.UpdateLucene));
             return ResultData(null, b, b ? "审核通过!" : "审核失败!");
         }
 
@@ -411,7 +410,6 @@ namespace Masuit.MyBlogs.WebApp.Controllers
             var post = PostBll.GetById(id);
             post.Status = Status.Deleted;
             bool b = PostBll.UpdateEntitySaved(post);
-            HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.UpdateLucene));
             return ResultData(null, b, b ? "删除成功!" : "删除失败!");
         }
 
@@ -421,7 +419,6 @@ namespace Masuit.MyBlogs.WebApp.Controllers
             var post = PostBll.GetById(id);
             post.Status = Status.Pended;
             bool b = PostBll.UpdateEntitySaved(post);
-            HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.UpdateLucene));
             return ResultData(null, b, b ? "恢复成功!" : "恢复失败!");
         }
 
@@ -462,7 +459,6 @@ namespace Masuit.MyBlogs.WebApp.Controllers
             }
 
             bool b = PostBll.DeleteByIdSaved(id);
-            HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.UpdateLucene));
             return ResultData(null, b, b ? "删除成功!" : "删除失败!");
         }
 
@@ -714,7 +710,6 @@ namespace Masuit.MyBlogs.WebApp.Controllers
                     });
                 }
 #endif
-                HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.UpdateLucene));
                 return ResultData(p.Mapper<PostOutputDto>(), message: "文章修改成功!");
             }
 
@@ -809,7 +804,6 @@ namespace Masuit.MyBlogs.WebApp.Controllers
                     });
                 }
 
-                HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.UpdateLucene));
                 return ResultData(null, true, "文章发表成功!");
             }
 

+ 11 - 16
src/Masuit.MyBlogs.WebApp/Controllers/SearchController.cs

@@ -1,7 +1,6 @@
 using Common;
 using IBLL;
 using Masuit.MyBlogs.WebApp.Models;
-using Masuit.MyBlogs.WebApp.Models.Hangfire;
 using Masuit.Tools.NoSQL;
 using Models.DTO;
 using Models.Entity;
@@ -20,10 +19,12 @@ namespace Masuit.MyBlogs.WebApp.Controllers
     public class SearchController : BaseController
     {
         public ISearchDetailsBll SearchDetailsBll { get; set; }
+        private readonly IPostBll _postBll;
 
-        public SearchController(ISearchDetailsBll searchDetailsBll)
+        public SearchController(ISearchDetailsBll searchDetailsBll, IPostBll postBll)
         {
             SearchDetailsBll = searchDetailsBll;
+            _postBll = postBll;
         }
 
         [Route("s/{wd?}/{page:int?}/{size:int?}"), OutputCache(VaryByParam = "wd", Duration = 60)]
@@ -55,7 +56,6 @@ namespace Masuit.MyBlogs.WebApp.Controllers
                     return View(nul);
                 }
                 wd = wd.Trim().Replace("+", " ");
-                var sw = new Stopwatch();
                 if (!string.IsNullOrWhiteSpace(wd) && !wd.Contains("锟斤拷"))
                 {
                     if (page == 1)
@@ -67,14 +67,16 @@ namespace Masuit.MyBlogs.WebApp.Controllers
                             IP = Request.UserHostAddress
                         });
                     }
-                    sw.Start();
-                    var query = LuceneHelper.Search(wd).ToList();
-                    var posts = query.Skip((page - 1) * size).Take(size).ToList();
-                    sw.Stop();
+                    string[] keywords = LuceneHelper.CutKeywords(wd).ToArray();
+                    Stopwatch sw = Stopwatch.StartNew();
+                    var posts = _postBll.SearchPage(page, size, out count, keywords, p => p.ModifyDate);
                     ViewBag.Elapsed = sw.Elapsed.TotalMilliseconds;
-                    ViewBag.Total = query.Count;
+                    ViewBag.Total = count;
                     SearchDetailsBll.SaveChanges();
-                    redisHelper.SetString(key, wd, TimeSpan.FromSeconds(10));
+                    if (count > 1)
+                    {
+                        redisHelper.SetString(key, wd, TimeSpan.FromSeconds(10));
+                    }
                     ViewBag.hotSearches = new List<KeywordsRankOutputDto>();
                     return View(posts);
                 }
@@ -87,13 +89,6 @@ namespace Masuit.MyBlogs.WebApp.Controllers
             }
         }
 
-        [Authority]
-        public ActionResult ResetIndex()
-        {
-            string job = HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.ResetLucene));
-            return ResultData(job, true, "索引库重置成功!");
-        }
-
         [Authority, HttpPost]
         public ActionResult SearchList(int page = 1, int size = 10, string search = "")
         {

+ 0 - 19
src/Masuit.MyBlogs.WebApp/Controllers/SystemController.cs

@@ -8,7 +8,6 @@ using Masuit.Tools.Models;
 using Masuit.Tools.NoSQL;
 using Masuit.Tools.Systems;
 using Masuit.Tools.Win32;
-using Models.DTO;
 using Models.Entity;
 using Models.Enum;
 using Newtonsoft.Json;
@@ -277,24 +276,6 @@ namespace Masuit.MyBlogs.WebApp.Controllers
         public ActionResult InterceptLog()
         {
             List<IpIntercepter> list = RedisHelper.ListRange<IpIntercepter>("intercept");
-            if (list.Any())
-            {
-                string ips = string.Join(",", list.Select(i => i.IP).Distinct());
-                DateTime start = list.Min(i => i.Time).AddDays(-7);
-                var interviews = new List<Interview>();
-                for (int i = 7; i <= 0; i++)
-                {
-                    interviews.AddRange(RedisHelper.ListRange<Interview>($"Interview:{DateTime.Today.AddDays(i):yyyy:MM:dd}").Where(x => ips.Contains(x.IP) && x.ViewTime >= start));
-                }
-                Dictionary<string, string> dic = interviews.Select(i => new { i.IP, i.Address }).AsEnumerable().DistinctBy(a => a.IP).ToDictionary(a => a.IP, a => a.Address);
-                foreach (var item in list)
-                {
-                    if (dic.ContainsKey(item.IP))
-                    {
-                        item.Address = dic[item.IP];
-                    }
-                }
-            }
             return ResultData(new
             {
                 interceptCount = RedisHelper.GetString("interceptCount"),

+ 2 - 91
src/Masuit.MyBlogs.WebApp/Global.asax.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Linq;
-using System.Threading.Tasks;
 using System.Web;
 using System.Web.Mvc;
 using System.Web.Optimization;
@@ -10,11 +9,8 @@ using Hangfire;
 using Masuit.MyBlogs.WebApp.Models.Hangfire;
 using Masuit.Tools;
 using Masuit.Tools.Logging;
-using Masuit.Tools.Net;
 using Masuit.Tools.NoSQL;
-using Models.DTO;
 #if DEBUG
-using Masuit.Tools.Win32;
 #endif
 using Z.EntityFramework.Extensions;
 
@@ -38,63 +34,8 @@ namespace Masuit.MyBlogs.WebApp
         }
         protected void Session_Start(object sender, EventArgs e)
         {
-            HttpRequest request = Request;
-            string ua = request.UserAgent;
-            string ip = request.UserHostAddress;
-#if DEBUG
-            Random r = new Random();
-            ip = $"{r.StrictNext(235)}.{r.StrictNext(255)}.{r.StrictNext(255)}.{r.StrictNext(255)}";
-#endif
-            Session.Set("landDate", DateTime.Now);
-            ip.MatchInetAddress(out bool success);
-            if (success)
-            {
-                Guid uid = Guid.NewGuid();
-                Session.Set("currentOnline", uid);
-                Task.Factory.StartNew(s =>
-                {
-                    HttpRequest req = s as HttpRequest;
-                    bool isNotSpider = ua != null && !ua.Contains(new[] { "DNSPod", "Baidu", "spider", "Python", "bot" });
-                    if (isNotSpider) //屏蔽百度云观测以及搜索引擎爬虫
-                    {
-                        string refer;
-                        try
-                        {
-                            refer = req.UrlReferrer?.AbsoluteUri ?? "直接输入网址";
-                        }
-                        catch (Exception)
-                        {
-                            refer = "直接输入网址";
-                        }
-                        string browserType = req.Browser.Type;
-                        if (browserType.Contains("Chrome1") || browserType.Contains("Chrome2") || browserType.Contains("Chrome3") || browserType.Equals("Chrome4") || browserType.Equals("Chrome7") || browserType.Equals("Chrome9") || browserType.Contains("Chrome40") || browserType.Contains("Chrome41") || browserType.Contains("Chrome42") || browserType.Contains("Chrome43"))
-                        {
-                            browserType = "Chrome43-";
-                        }
-                        else if (browserType.Contains("IE"))
-                        {
-                            browserType = "InternetExplorer" + req.Browser.Version;
-                        }
-                        else if (browserType.Equals("Safari6") || browserType.Equals("Safari5") || browserType.Equals("Safari4") || browserType.Equals("Safari"))
-                        {
-                            browserType = "Safari6-";
-                        }
-                        Interview interview = new Interview()
-                        {
-                            IP = ip,
-                            UserAgent = ua,
-                            BrowserType = browserType,
-                            OperatingSystem = req.Browser.Platform,
-                            ViewTime = DateTime.Now,
-                            FromUrl = refer,
-                            HttpMethod = req.HttpMethod,
-                            LandPage = req.Url.ToString(),
-                            Uid = uid
-                        };
-                        HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.FlushInetAddress), args: interview);
-                    }
-                }, request);
-            }
+            RedisHelper.StringIncrement("Interview:ViewCount");
+            return;
         }
 
         protected void Application_BeginRequest(object sender, EventArgs e)
@@ -164,36 +105,6 @@ namespace Masuit.MyBlogs.WebApp
 
         protected void Session_End(object sender, EventArgs e)
         {
-            var uid = Session.Get<Guid>("currentOnline");
-            //IInterviewBll interviewBll = AutofacConfig.Container.Resolve<IInterviewBll>();
-            var interview = RedisHelper.ListRange<Interview>($"Interview:{DateTime.Today:yyyy:MM:dd}").Union(RedisHelper.ListRange<Interview>($"Interview:{DateTime.Today.AddDays(-1):yyyy:MM:dd}")).FirstOrDefault(i => i.Uid.Equals(uid));
-            if (interview != null)
-            {
-                RedisHelper.RemoveList($"Interview:{DateTime.Today:yyyy:MM:dd}", interview);
-                if (interview.InterviewDetails.Any())
-                {
-                    var interviewDetails = interview.InterviewDetails;
-                    var ts = DateTime.Now - interviewDetails.FirstOrDefault().Time;
-                    if (ts.TotalMinutes > 20)
-                    {
-                        ts = ts - TimeSpan.FromMinutes(20);
-                    }
-                    var len = string.Empty;
-                    if (ts.Hours > 0)
-                    {
-                        len += $"{ts.Hours}小时";
-                    }
-
-                    if (ts.Minutes > 0)
-                    {
-                        len += $"{ts.Minutes}分钟";
-                    }
-                    len += $"{ts.Seconds}.{ts.Milliseconds}秒";
-                    interview.OnlineSpan = len;
-                    interview.OnlineSpanSeconds = ts.TotalSeconds;
-                }
-                RedisHelper.ListRightPush($"Interview:{DateTime.Today:yyyy:MM:dd}", interview);
-            }
         }
 
         protected void Application_End(object sender, EventArgs e)

+ 11 - 40
src/Masuit.MyBlogs.WebApp/Masuit.MyBlogs.WebApp.csproj

@@ -108,10 +108,6 @@
     <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
       <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
     </Reference>
-    <Reference Include="EntityFramework.Extended, Version=6.0.0.0, Culture=neutral, PublicKeyToken=05b7e29bdd433584, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\packages\EntityFramework.Extended.6.1.0.168\lib\net45\EntityFramework.Extended.dll</HintPath>
-    </Reference>
     <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
       <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
     </Reference>
@@ -121,24 +117,15 @@
     <Reference Include="Hangfire.Autofac, Version=2.3.1.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\Hangfire.Autofac.2.3.1\lib\net45\Hangfire.Autofac.dll</HintPath>
     </Reference>
-    <Reference Include="Hangfire.Console, Version=1.4.2.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\Hangfire.Console.1.4.2\lib\net45\Hangfire.Console.dll</HintPath>
-    </Reference>
     <Reference Include="Hangfire.Core, Version=1.6.21.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\Hangfire.Core.1.6.21\lib\net45\Hangfire.Core.dll</HintPath>
     </Reference>
-    <Reference Include="Hangfire.SqlServer, Version=1.6.21.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\Hangfire.SqlServer.1.6.21\lib\net45\Hangfire.SqlServer.dll</HintPath>
+    <Reference Include="Hangfire.Redis.StackExchange, Version=1.7.2.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\Hangfire.Redis.StackExchange.1.7.2\lib\net46\Hangfire.Redis.StackExchange.dll</HintPath>
     </Reference>
     <Reference Include="HtmlDiff, Version=1.3.0.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\htmldiff.net.1.3\lib\net35\HtmlDiff.dll</HintPath>
     </Reference>
-    <Reference Include="ICSharpCode.SharpZipLib, Version=1.1.0.145, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
-      <HintPath>..\packages\SharpZipLib.1.1.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
-    </Reference>
-    <Reference Include="Lucene.Net, Version=3.0.3.0, Culture=neutral, PublicKeyToken=85089178b9ac3181, processorArchitecture=MSIL">
-      <HintPath>..\packages\Lucene.Net.3.0.3\lib\NET40\Lucene.Net.dll</HintPath>
-    </Reference>
     <Reference Include="Microsoft.AspNet.SignalR.Core, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\packages\Microsoft.AspNet.SignalR.Core.2.4.0\lib\net45\Microsoft.AspNet.SignalR.Core.dll</HintPath>
     </Reference>
@@ -168,17 +155,17 @@
     <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
       <HintPath>..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
+    <Reference Include="NinjaNye.SearchExtensions, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\NinjaNye.SearchExtensions.2.2.0\lib\net45\NinjaNye.SearchExtensions.dll</HintPath>
+    </Reference>
     <Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
       <HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
     </Reference>
-    <Reference Include="PanGu, Version=2.4.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\Lucene.Net.Analysis.PanGu.2.4.1\lib\PanGu.dll</HintPath>
+    <Reference Include="PanGu.Core, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\PanGu.Core.1.0.0\lib\net451\PanGu.Core.dll</HintPath>
     </Reference>
     <Reference Include="PanGu.HighLight, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\Lucene.Net.Analysis.PanGu.2.4.1\lib\PanGu.HighLight.dll</HintPath>
-    </Reference>
-    <Reference Include="PanGu.Lucene.Analyzer, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\Lucene.Net.Analysis.PanGu.2.4.1\lib\PanGu.Lucene.Analyzer.dll</HintPath>
+      <HintPath>..\packages\PanGu.HighLight.1.0.0\lib\net451\PanGu.HighLight.dll</HintPath>
     </Reference>
     <Reference Include="Quartz, Version=2.6.1.0, Culture=neutral, PublicKeyToken=f6b8c98a402cc8a4, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -193,27 +180,20 @@
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
     <Reference Include="System.Data" />
-    <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.IO.Compression" />
     <Reference Include="System.Net.Http" />
     <Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll</HintPath>
     </Reference>
-    <Reference Include="System.Runtime.Serialization" />
-    <Reference Include="System.Security" />
     <Reference Include="System.ServiceModel" />
     <Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
       <HintPath>..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
     </Reference>
     <Reference Include="System.Web" />
-    <Reference Include="System.Web.ApplicationServices" />
     <Reference Include="System.Web.Cors, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\packages\Microsoft.AspNet.Cors.5.2.7\lib\net45\System.Web.Cors.dll</HintPath>
     </Reference>
-    <Reference Include="System.Web.DynamicData" />
-    <Reference Include="System.Web.Entity" />
-    <Reference Include="System.Web.Extensions" />
     <Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.Helpers.dll</HintPath>
     </Reference>
@@ -243,7 +223,7 @@
       <HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
     </Reference>
     <Reference Include="System.Xml" />
-    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Xml.Serialization" />
     <Reference Include="WebActivatorEx, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7b26dc2a43f6a0d4, processorArchitecture=MSIL">
       <HintPath>..\packages\WebActivatorEx.2.2.0\lib\net40\WebActivatorEx.dll</HintPath>
     </Reference>
@@ -251,8 +231,8 @@
       <HintPath>..\packages\WebGrease.1.6.0\lib\WebGrease.dll</HintPath>
       <Private>True</Private>
     </Reference>
-    <Reference Include="Z.EntityFramework.Extensions, Version=3.16.21.0, Culture=neutral, PublicKeyToken=59b66d028979105b, processorArchitecture=MSIL">
-      <HintPath>..\packages\Z.EntityFramework.Extensions.3.16.21\lib\net45\Z.EntityFramework.Extensions.dll</HintPath>
+    <Reference Include="Z.EntityFramework.Extensions, Version=3.16.22.0, Culture=neutral, PublicKeyToken=59b66d028979105b, processorArchitecture=MSIL">
+      <HintPath>..\packages\Z.EntityFramework.Extensions.3.16.22\lib\net45\Z.EntityFramework.Extensions.dll</HintPath>
     </Reference>
     <Reference Include="Z.ExtensionMethods, Version=2.1.1.0, Culture=neutral, PublicKeyToken=59b66d028979105b, processorArchitecture=MSIL">
       <HintPath>..\packages\Z.ExtensionMethods.2.1.1\lib\net45\Z.ExtensionMethods.dll</HintPath>
@@ -1060,7 +1040,6 @@
       <DependentUpon>loading.html</DependentUpon>
     </Content>
     <Content Include="ng-views\views\analysis\search.html" />
-    <Content Include="ng-views\views\analysis\interview.html" />
     <Content Include="ng-views\views\comment\index.html" />
     <Content Include="ng-views\views\donate.html" />
     <Content Include="ng-views\views\contact.html" />
@@ -1142,12 +1121,6 @@
     <Content Include="ng-views\template\sidebar-left.html" />
     <Content Include="ng-views\views\dashboard.html" />
     <Content Include="ng-views\controllers\dashboard.js" />
-    <Content Include="Dict\ChsDoubleName1.txt" />
-    <Content Include="Dict\ChsDoubleName2.txt" />
-    <Content Include="Dict\ChsSingleName.txt" />
-    <Content Include="Dict\Stopword.txt" />
-    <Content Include="Dict\Synonym.txt" />
-    <Content Include="Dict\Wildcard.txt" />
     <Content Include="fonts\glyphicons-halflings-regular.svg" />
     <Content Include="fonts\glyphicons-halflings-regular.woff2" />
     <Content Include="fonts\glyphicons-halflings-regular.woff" />
@@ -1165,7 +1138,6 @@
     <Content Include="Assets\UEditor\third-party\video-js\font\vjs.ttf" />
     <Content Include="Assets\UEditor\third-party\video-js\font\vjs.woff" />
     <Content Include="App_Data\config.json" />
-    <Content Include="Dict\Dict.dct" />
     <None Include="bundleconfig.json" />
     <Content Include="fonts\icomoon.eot" />
     <Content Include="fonts\icomoon.ttf" />
@@ -1441,7 +1413,6 @@
     <Compile Include="Controllers\FileController.cs" />
     <Compile Include="Controllers\HealthController.cs" />
     <Compile Include="Controllers\HomeController.cs" />
-    <Compile Include="Controllers\InterviewController.cs" />
     <Compile Include="Controllers\LinksController.cs" />
     <Compile Include="Controllers\LoginController.cs" />
     <Compile Include="Controllers\MenuController.cs" />

+ 3 - 366
src/Masuit.MyBlogs.WebApp/Models/Hangfire/HangfireBackJob.cs

@@ -36,69 +36,11 @@ namespace Masuit.MyBlogs.WebApp.Models.Hangfire
             PostBll = postBll;
             RedisHelper = redisHelper;
         }
-
-        public void FlushInetAddress(Interview interview)
-        {
-#if DEBUG
-            interview.IP = "114.144.114.114";
-#endif
-            PhysicsAddress address = interview.IP.GetPhysicsAddressInfo().Result;
-            if (address?.Status == 0)
-            {
-                interview.Address = $"{address.AddressResult.FormattedAddress} {address.AddressResult.AddressComponent.Direction}{address.AddressResult.AddressComponent.Distance ?? "0"}米";
-                interview.Country = address.AddressResult.AddressComponent.Country;
-                interview.Province = address.AddressResult.AddressComponent.Province;
-                IList<string> strs = new List<string>();
-                address.AddressResult?.Pois?.ForEach(s => strs.Add($"{s.AddressDetail} {s.Direction}{s.Distance ?? "0"}米"));
-                if (strs.Any())
-                {
-                    interview.ReferenceAddress = string.Join("|", strs);
-                }
-                if ("true" == CommonHelper.GetSettings("EnableDenyArea"))
-                {
-                    CommonHelper.GetSettings("DenyArea")?.Split(',', ',').ForEach(area =>
-                    {
-                        if (interview.Address.Contains(area) || (interview.ReferenceAddress != null && interview.ReferenceAddress.Contains(area)))
-                        {
-                            CommonHelper.DenyAreaIP.AddOrUpdate(area, a => new HashSet<string>
-                            {
-                                interview.IP
-                            }, (s, list) =>
-                            {
-                                lock (list)
-                                {
-                                    list.Add(interview.IP);
-                                    return list;
-                                }
-                            });
-                            File.WriteAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", "denyareaip.txt"), CommonHelper.DenyAreaIP.ToJsonString());
-                        }
-                    });
-                }
-            }
-            interview.ISP = interview.IP.GetISP();
-            RedisHelper.ListRightPush($"Interview:{DateTime.Today:yyyy:MM:dd}", interview);
-            RedisHelper.Expire($"Interview:{DateTime.Today:yyyy:MM:dd}", TimeSpan.FromDays(30));
-            RedisHelper.StringIncrement("Interview:ViewCount");
-        }
-
-        public void UpdateLucene()
-        {
-            LuceneHelper.CreateIndex(PostBll.LoadEntitiesNoTracking(p => p.Status == Status.Pended));
-            LuceneHelper.IncreaseIndex();
-        }
-
-        public void ResetLucene()
-        {
-            LuceneHelper.DeleteIndex();
-            UpdateLucene();
-        }
-
         public void LoginRecord(UserInfoOutputDto userInfo, string ip, LoginType type)
         {
-            var view = RedisHelper.ListRange<Interview>($"Interview:{DateTime.Today:yyyy:MM:dd}").OrderByDescending(i => i.ViewTime).FirstOrDefault(i => i.IP.Equals(ip));
-            string addr = view?.Address;
-            string prov = view?.Province;
+            var address = ip.GetPhysicsAddressInfo().Result;
+            string addr = address.AddressResult.FormattedAddress;
+            string prov = address.AddressResult.AddressComponent.Province;
             LoginRecord record = new LoginRecord()
             {
                 IP = ip,
@@ -120,53 +62,6 @@ namespace Masuit.MyBlogs.WebApp.Models.Hangfire
             p.PostDate = DateTime.Now;
             p.ModifyDate = DateTime.Now;
             PostBll.AddOrUpdateSaved(e => e.Id, p);
-            UpdateLucene();
-        }
-
-        public void AggregateInterviews()
-        {
-            var (all, unique) = Analysis();
-            AggregatedCounter.TotalInterviews = all;
-            AggregatedCounter.UniqueInterviews = unique;
-            Windows.ClearMemorySilent();
-        }
-
-        public void InterviewTrace(Guid uid, string url)
-        {
-            for (int j = 0; j < 10; j++) //重试10次,找到这个访客
-            {
-                var view = RedisHelper.ListRange<Interview>($"Interview:{DateTime.Today:yyyy:MM:dd}").Union(RedisHelper.ListRange<Interview>($"Interview:{DateTime.Today.AddDays(-1):yyyy:MM:dd}")).FirstOrDefault(i => i.Uid.Equals(uid));
-                if (view != null)
-                {
-                    RedisHelper.RemoveList($"Interview:{DateTime.Today:yyyy:MM:dd}", view);
-                    view.InterviewDetails.Add(new InterviewDetail()
-                    {
-                        Time = DateTime.Now,
-                        Url = url
-                    });
-                    if (view.InterviewDetails.Count >= 2)
-                    {
-                        TimeSpan ts = DateTime.Now - view.InterviewDetails.FirstOrDefault().Time;
-                        string len = string.Empty;
-                        if (ts.Hours > 0)
-                        {
-                            len += $"{ts.Hours}小时";
-                        }
-
-                        if (ts.Minutes > 0)
-                        {
-                            len += $"{ts.Minutes}分钟";
-                        }
-                        len += $"{ts.Seconds}.{ts.Milliseconds}秒";
-                        view.OnlineSpan = len;
-                        view.OnlineSpanSeconds = ts.TotalSeconds;
-                    }
-                    RedisHelper.ListRightPush($"Interview:{DateTime.Today:yyyy:MM:dd}", view);
-                    //InterviewBll.UpdateEntitySaved(view);
-                    break;
-                }
-                Thread.Sleep(1000);
-            }
         }
 
         public void FlushException(Exception ex)
@@ -194,264 +89,6 @@ namespace Masuit.MyBlogs.WebApp.Models.Hangfire
             PostBll.UpdateEntitySaved(post);
         }
 
-        private (AnalysisModel, AnalysisModel) Analysis()
-        {
-            List<Interview> list;
-            using (RedisHelper redisHelper = RedisHelper.GetInstance())
-            {
-                list = redisHelper.ListRange<Interview>($"Interview:{DateTime.Today:yyyy:MM:dd}");
-                for (int i = -60; i < 0; i++)
-                {
-                    list.AddRange(redisHelper.ListRange<Interview>($"Interview:{DateTime.Today.AddDays(i):yyyy:MM:dd}"));
-                }
-                list = list.OrderBy(i => i.ViewTime).ToList();
-            }
-            if (!list.Any())
-            {
-                return (null, null);
-            }
-            CommonHelper.AverageCount = list.Count * 1.0 / list.GroupBy(i => i.ViewTime.Date).Count();
-            var dap = list.Select(i =>
-            {
-                var (a, d) = (list.GroupBy(g => g.Uid).Count(), list.Count(g => g.InterviewDetails.Count == 1));
-                return new BounceRate()
-                {
-                    All = a,
-                    Dap = d,
-                    Result = d * 1.0 / a
-                };
-            }).FirstOrDefault();
-            var dapAgg = list.GroupBy(i => i.ViewTime.Date).Select(gs =>
-            {
-                var (a, d) = (gs.GroupBy(g => g.Uid).Count(), gs.Count(g => g.InterviewDetails.Count == 1));
-                return new BounceRateAggregate()
-                {
-                    Time = gs.Key,
-                    Dap = d,
-                    All = a,
-                    Rate = d * 1.0m / a
-                };
-            });
-            int todaypv = list.Count(i => i.ViewTime >= DateTime.Today);
-            int todayuv = list.DistinctBy(i => i.IP).Count(i => i.ViewTime >= DateTime.Today);
-
-            //本月统计
-            var monthStart = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
-            int monthpv = list.Count(i => i.ViewTime >= monthStart);
-            int monthuv = list.DistinctBy(i => i.IP).Count(i => i.ViewTime >= monthStart);
-
-            var allClient = new List<object>();
-            var uniClient = new List<object>();
-            var allRegion = new List<object>();
-            var uniRegion = new List<object>();
-
-            //省份和世界地区统计
-            list.Where(i => !string.IsNullOrEmpty(i.Province)).GroupBy(i => i.Province).Select(gs => new KeyCount()
-            {
-                Key = gs.Key,
-                Count = gs.Count(),
-                UniqueCount = gs.DistinctBy(i => i.IP).Count()
-            }).OrderBy(g => Guid.NewGuid()).ForEach(g =>
-            {
-                if (string.IsNullOrEmpty(g.Key))
-                {
-                    return;
-                }
-                string name;
-                if (g.Key.Contains("新疆"))
-                {
-                    name = "新疆";
-                }
-                else if (g.Key.Contains("广西"))
-                {
-                    name = "广西";
-                }
-                else if (g.Key.Contains("西藏"))
-                {
-                    name = "西藏";
-                }
-                else if (g.Key.Contains("香港"))
-                {
-                    name = "香港";
-                }
-                else if (g.Key.Contains("澳门"))
-                {
-                    name = "澳门";
-                }
-                else if (g.Key.Contains("内蒙古"))
-                {
-                    name = "内蒙古";
-                }
-                else if (g.Key.Contains("宁夏"))
-                {
-                    name = "宁夏";
-                }
-                else if (g.Key.Contains("海南"))
-                {
-                    name = "海南";
-                }
-                else if (g.Key.Contains("台湾"))
-                {
-                    name = "台湾";
-                }
-                else if (g.Key.Contains("省"))
-                {
-                    name = g.Key.Replace("省", "");
-                }
-                else if (g.Key.Contains("市"))
-                {
-                    name = g.Key.Replace("市", "");
-                }
-                else if (g.Key.Contains("XX"))
-                {
-                    return;
-                }
-                else
-                {
-                    name = g.Key;
-                }
-                allClient.Add(new
-                {
-                    name,
-                    value = g.Count
-                });
-                uniClient.Add(new
-                {
-                    name,
-                    value = g.UniqueCount
-                });
-                allRegion.Add(new dynamic[]
-                {
-                    name,
-                    g.Count
-                });
-                uniRegion.Add(new dynamic[]
-                {
-                    name,
-                    g.UniqueCount
-                });
-            });
-            var allBrowser = list.GroupBy(i => i.BrowserType).OrderBy(g => g.Key).Select(g => new object[]
-            {
-                g.Key,
-                g.Count()
-            }).ToList();
-            var uniBrowser = list.GroupBy(i => i.BrowserType).OrderBy(g => g.Key).Select(g => new object[]
-            {
-                g.Key,
-                g.DistinctBy(i => i.IP).Count()
-            }).ToList();
-            Dictionary<DateTime, int> dic = list.DistinctBy(i => i.IP).GroupBy(g => g.ViewTime.Date).ToDictionary(g => g.Key, g => g.Count());
-            var reduce = list.GroupBy(i => i.ViewTime.Date).Select(g =>
-            {
-                var count = g.DistinctBy(i => i.IP).Count();
-                return new
-                {
-                    Date = g.Key,
-                    TimeStamp = g.Key.GetTotalMilliseconds(),
-                    pv = g.Count(),
-                    uv = count,
-                    iv = count - (dic.ContainsKey(g.Key) ? dic[g.Key] : 0)
-                };
-            }).ToList(); //汇总统计
-
-            //找出PV最高的一天
-            var p = reduce.FirstOrDefault(e => e.pv == reduce.Max(a => a.pv));
-            var highpv = new
-            {
-                date = p.Date,
-                p.pv,
-                p.uv
-            };
-
-            //找出UV最高的一天
-            var u = reduce.FirstOrDefault(e => e.uv == reduce.Max(a => a.uv));
-            var highuv = new
-            {
-                date = u.Date,
-                u.pv,
-                u.uv
-            };
-
-            //汇总统计
-            var pv = reduce.Select(g => new List<object>
-            {
-                g.TimeStamp,
-                g.pv
-            }).ToList(); //每日PV
-            var uv = reduce.Select(g => new List<object>
-            {
-                g.TimeStamp,
-                g.uv
-            }).ToList(); //每日UV
-            var iv = reduce.Select(g => new List<object>
-            {
-                g.TimeStamp,
-                g.iv
-            }).ToList();  //每日新增独立访客
-
-            double average = 0;
-            double average2 = 0;
-            if (list.Any(i => i.OnlineSpanSeconds > 0 && i.ViewTime >= DateTime.Today))
-            {
-                average = list.Where(i => i.OnlineSpanSeconds > 0).Average(i => i.OnlineSpanSeconds);
-                average2 = list.Where(i => i.OnlineSpanSeconds > 0 && i.ViewTime >= DateTime.Today).Average(i => i.OnlineSpanSeconds);
-            }
-            var averSpan = TimeSpan2String(TimeSpan.FromSeconds(average)); //平均访问时长
-            var averSpanToday = TimeSpan2String(TimeSpan.FromSeconds(average2)); //今日访问时长
-
-            BounceRateAggregate todayDap = dapAgg.LastOrDefault();
-            var all = new AnalysisModel()
-            {
-                Browser = allBrowser,
-                Client = allClient,
-                Region = allRegion,
-                Highpv = highpv,
-                Highuv = highuv,
-                Iv = iv,
-                Monthpv = monthpv,
-                Monthuv = monthuv,
-                Pv = pv,
-                Todaypv = todaypv,
-                Todayuv = todayuv,
-                Uv = uv,
-                BounceRate = $"{dap?.Dap}/{dap?.All}({dap?.Result:P})",
-                BounceRateAggregate = dapAgg.Select(a => new object[]
-                {
-                    a.Time.GetTotalMilliseconds(),
-                    a.Rate * 100
-                }).ToList(),
-                BounceRateToday = $"{todayDap?.Dap}/{todayDap?.All}({todayDap?.Rate:P})",
-                OnlineSpanAggregate = new
-                {
-                    averSpanToday,
-                    averSpan,
-                }
-            };
-            var unique = JsonConvert.DeserializeObject<AnalysisModel>(all.ToJsonString());
-            unique.Browser = uniBrowser;
-            unique.Client = uniClient;
-            unique.Region = uniRegion;
-            return (all, unique);
-        }
-
-        private static string TimeSpan2String(TimeSpan span)
-        {
-            string averSpan = string.Empty;
-            if (span.Hours > 0)
-            {
-                averSpan += span.Hours + "小时";
-            }
-
-            if (span.Minutes > 0)
-            {
-                averSpan += span.Minutes + "分钟";
-            }
-
-            averSpan += span.Seconds + "秒";
-            return averSpan;
-        }
-
         public static void InterceptLog(IpIntercepter s)
         {
             using (RedisHelper redisHelper = RedisHelper.GetInstance())

+ 0 - 6
src/Masuit.MyBlogs.WebApp/Models/Hangfire/IHangfireBackJob.cs

@@ -8,14 +8,8 @@ namespace Masuit.MyBlogs.WebApp.Models.Hangfire
     public interface IHangfireBackJob
     {
         void FlushException(Exception ex);
-        void FlushInetAddress(Interview interview);
-        //void FlushUnhandledAddress();
-        void UpdateLucene();
-        void ResetLucene();
         void LoginRecord(UserInfoOutputDto userInfo, string ip, LoginType type);
         void PublishPost(Post p);
-        void AggregateInterviews();
-        void InterviewTrace(Guid uid, string url);
         void RecordPostVisit(int pid);
     }
 }

+ 15 - 482
src/Masuit.MyBlogs.WebApp/Models/LuceneHelper.cs

@@ -1,31 +1,10 @@
-using System;
-using System.Collections.Concurrent;
+using Newtonsoft.Json;
+using System;
 using System.Collections.Generic;
-using System.IO;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
 using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using Autofac;
-using IBLL;
-using Lucene.Net.Analysis.PanGu;
-using Lucene.Net.Documents;
-using Lucene.Net.Index;
-using Lucene.Net.QueryParsers;
-using Lucene.Net.Search;
-using Lucene.Net.Store;
-using Masuit.Tools;
-using Masuit.Tools.Html;
-using Masuit.Tools.Logging;
-using Models.DTO;
-using Models.Entity;
-using Models.Enum;
-using Newtonsoft.Json;
-using PanGu;
-using PanGu.HighLight;
-using Directory = System.IO.Directory;
-using Version = Lucene.Net.Util.Version;
 
 namespace Masuit.MyBlogs.WebApp.Models
 {
@@ -34,272 +13,6 @@ namespace Masuit.MyBlogs.WebApp.Models
     /// </summary>
     public static class LuceneHelper
     {
-        #region Config
-
-        /// <summary>
-        /// 索引文件夹路径
-        /// </summary>
-        public static string IndexPath { get; set; } = AppDomain.CurrentDomain.BaseDirectory + @"App_Data\lucenedir\";//设置Lucene索引目录
-
-        public static object LockObj { get; } = new object();
-
-        ///// <summary>
-        ///// 分词API  //http://zhannei.baidu.com/api/customsearch/keywords?title=群主可撤回消息,QQ9.0去广告本地SVIP绿色精简优化版
-        ///// http://api.pullword.com
-        ///// </summary>
-        //public static HttpClient ApiClient { get; set; } = new HttpClient() { BaseAddress = new Uri("http://api.pullword.com") };
-
-        #endregion Config
-
-        #region 创建索引
-
-        /// <summary>
-        /// 创建索引,如果索引库存在则刷新索引
-        /// </summary>
-        /// <param name="dataSource"></param>
-        /// <returns></returns>
-        public static void CreateIndex(IQueryable<Post> dataSource)
-        {
-            if (string.IsNullOrEmpty(IndexPath))
-            {
-                throw new Exception("未设置索引文件夹路径,参数名:" + IndexPath);
-            }
-            string dir = IndexPath;
-
-            #region 创建索引前尝试删除索引文件夹
-
-            try
-            {
-                Directory.Delete(dir, true);
-            }
-            catch (Exception e)
-            {
-                LogManager.Debug("尝试删除索引文件夹失败!", e.Message);
-            }
-
-            #endregion 创建索引前尝试删除索引文件夹
-
-            if (!Directory.Exists(dir))
-            {
-                Directory.CreateDirectory(dir);
-            }
-            if (File.Exists(Path.Combine(dir, "segments.gen")))
-            {
-                IncreaseIndex();
-                return;
-            }
-            string indexPath = dir; //注意和磁盘上文件夹的大小写一致,否则会报错。将创建的分词内容放在该目录下。
-            using (FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory())) //指定索引文件(打开索引目录) FS指的是就是FileSystem
-            {
-                bool isUpdate = IndexReader.IndexExists(directory); //IndexReader:对索引进行读取的类。该语句的作用:判断索引库文件夹是否存在以及索引特征文件是否存在。
-                lock (LockObj)
-                {
-                    using (var writer = new IndexWriter(directory, new PanGuAnalyzer(), !isUpdate, IndexWriter.MaxFieldLength.UNLIMITED)) //!向索引库中写索引。这时在这里加锁。
-                    {
-                        foreach (Post item in dataSource.AsParallel())
-                        {
-                            item.Content = item.Content.RemoveHtml();
-                            try
-                            {
-                                writer.AddDocument(EntityToDocument(item));
-                            }
-                            catch (IOException e)
-                            {
-                                Console.WriteLine(e);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        #endregion 创建索引
-
-        #region 查询所有符合条件的内容
-
-        /// <summary>
-        /// 查询所有符合条件的内容
-        /// </summary>
-        /// <param name="kw">关键词</param>
-        /// <param name="segment">提取长度</param>
-        /// <returns></returns>
-        public static IEnumerable<PostOutputDto> Search(string kw, int segment = 200)
-        {
-            if (string.IsNullOrEmpty(IndexPath))
-            {
-                throw new Exception("未设置索引文件夹路径,参数名:" + IndexPath);
-            }
-            string indexPath = IndexPath;
-            using (var analyzer = new PanGuAnalyzer())
-            {
-                var list = CutKeywords(kw);
-                var result = new ConcurrentQueue<PostOutputDto>();
-                Parallel.ForEach(list, k =>
-                {
-                    if (k.Contains(new[] { @"\?", @"\*", @"\+", @"\-", @"\[", @"\]", @"\{", @"\}", @"\(", @"\)", "�" }))
-                    {
-                        return;
-                    }
-
-                    using (FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NoLockFactory()))
-                    {
-                        using (var reader = IndexReader.Open(directory, true))
-                        {
-                            using (var searcher = new IndexSearcher(reader))
-                            {
-                                QueryParser parser = new MultiFieldQueryParser(Version.LUCENE_30, new[] { nameof(Post.Id), nameof(Post.Title), nameof(Post.Content), nameof(Post.Author), nameof(Post.Label), nameof(Post.Email), nameof(Post.Keyword) }, analyzer); //多个字段查询
-                                Query query = parser.Parse(k);
-                                int n = 100000;
-                                TopDocs docs = searcher.Search(query, null, n);
-                                if (docs?.TotalHits != 0 && docs?.ScoreDocs != null)
-                                {
-                                    foreach (ScoreDoc sd in docs.ScoreDocs) //遍历搜索到的结果
-                                    {
-                                        Document doc = searcher.Doc(sd.Doc);
-                                        if (result.Any(p => p.Id == doc.Get(nameof(Post.Id)).ToInt32()))
-                                        {
-                                            continue;
-                                        }
-                                        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 = segment };
-                                        var content = doc.Get(nameof(Post.Content));
-                                        if (content.Length <= segment)
-                                        {
-                                            segment = content.Length;
-                                        }
-                                        result.Enqueue(new PostOutputDto()
-                                        {
-                                            Id = doc.Get(nameof(Post.Id)).ToInt32(),
-                                            Title = doc.Get(nameof(Post.Title)).ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, doc.Get(nameof(Post.Title))) : doc.Get(nameof(Post.Title)),
-                                            Content = content.ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, content) : content.Substring(0, segment),
-                                            Author = doc.Get(nameof(Post.Author)).ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, doc.Get(nameof(Post.Author))) : doc.Get(nameof(Post.Author)),
-                                            Label = doc.Get(nameof(Post.Label)).ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, doc.Get(nameof(Post.Label))) : doc.Get(nameof(Post.Label)),
-                                            Email = doc.Get(nameof(Post.Email)).ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, doc.Get(nameof(Post.Email))) : doc.Get(nameof(Post.Email)),
-                                            Keyword = doc.Get(nameof(Post.Keyword)).ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, doc.Get(nameof(Post.Keyword))) : doc.Get(nameof(Post.Keyword))
-                                        });
-                                    }
-                                }
-                            }
-                        }
-                    }
-                });
-                return result.Where(p => !string.IsNullOrEmpty(p.Title)).DistinctBy(p => p.Id);
-            }
-        }
-
-        #endregion 查询所有符合条件的内容
-
-        #region 多字段分页查询数据
-
-        /// <summary>
-        /// 多字段分页查询数据
-        /// </summary>
-        /// <param name="keyword">关键词</param>
-        /// <param name="total">总数</param>
-        /// <param name="pageIndex">第几页</param>
-        /// <param name="pageSize">页大小</param>
-        /// <param name="segment">提取长度</param>
-        /// <returns></returns>
-        public static List<PostOutputDto> SearchPages(string keyword, out int total, int pageIndex = 1, int pageSize = 10, int segment = 200)
-        {
-            if (pageIndex < 1)
-            {
-                pageIndex = 1;
-            }
-            int totalCount = 0;
-            if (string.IsNullOrEmpty(IndexPath))
-            {
-                throw new Exception("未设置索引文件夹路径,参数名:" + IndexPath);
-            }
-            string indexPath = IndexPath;
-            using (var analyzer = new PanGuAnalyzer())
-            {
-                var list = CutKeywords(keyword);
-                var result = new ConcurrentQueue<PostOutputDto>();
-                list.ForEach(k =>
-                {
-                    if (k.Contains(new[] { @"\?", @"\*", @"\+", @"\-", @"\[", @"\]", @"\{", @"\}", @"\(", @"\)", "�" }))
-                    {
-                        return;
-                    }
-
-                    using (FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NoLockFactory()))
-                    {
-                        using (var reader = IndexReader.Open(directory, true))
-                        {
-                            using (var searcher = new IndexSearcher(reader))
-                            {
-                                var bq = new BooleanQuery();
-
-                                //if (flag != "")
-                                //{
-                                //    var qpflag = new QueryParser(Version.LUCENE_30, "flag", analyzer);
-                                //    Query qflag = qpflag.Parse(flag);
-                                //    bq.Add(qflag, Occur.MUST); //与运算
-                                //}
-                                if (k != "")
-                                {
-                                    QueryParser parser = new MultiFieldQueryParser(Version.LUCENE_30, new[] { nameof(Post.Id), nameof(Post.Title), nameof(Post.Content), nameof(Post.Author), nameof(Post.Label), nameof(Post.Email), nameof(Post.Keyword) }, analyzer); //多个字段查询
-                                    try
-                                    {
-                                        Query queryKeyword = parser.Parse(k);
-                                        bq.Add(queryKeyword, Occur.MUST); //与运算
-                                    }
-                                    catch
-                                    {
-                                        return;
-                                    }
-                                }
-                                var collector = TopScoreDocCollector.Create(pageIndex * pageSize, true);
-                                searcher.Search(bq, collector);
-                                if (collector?.TotalHits == 0)
-                                {
-                                    totalCount += 0;
-                                }
-                                else
-                                {
-                                    int start = pageSize * (pageIndex - 1); //结束数
-                                    int limit = pageSize;
-                                    ScoreDoc[] hits = collector?.TopDocs(start, limit).ScoreDocs;
-                                    totalCount += collector?.TotalHits ?? 0;
-                                    foreach (ScoreDoc sd in hits) //遍历搜索到的结果
-                                    {
-                                        var doc = searcher.Doc(sd.Doc);
-                                        if (result.Any(p => p.Id == doc.Get(nameof(Post.Id)).ToInt32()))
-                                        {
-                                            continue;
-                                        }
-                                        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 = segment
-                                        };
-                                        var content = doc.Get(nameof(Post.Content));
-                                        if (content.Length <= segment)
-                                        {
-                                            segment = content.Length;
-                                        }
-                                        result.Enqueue(new PostOutputDto()
-                                        {
-                                            Id = doc.Get(nameof(Post.Id)).ToInt32(),
-                                            Title = doc.Get(nameof(Post.Title)).ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, doc.Get(nameof(Post.Title))) : doc.Get(nameof(Post.Title)),
-                                            Content = content.ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, content) : content.Substring(0, segment),
-                                            Author = doc.Get(nameof(Post.Author)).ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, doc.Get(nameof(Post.Author))) : doc.Get(nameof(Post.Author)),
-                                            Label = doc.Get(nameof(Post.Label)).ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, doc.Get(nameof(Post.Label))) : doc.Get(nameof(Post.Label)),
-                                            Email = doc.Get(nameof(Post.Email)).ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, doc.Get(nameof(Post.Email))) : doc.Get(nameof(Post.Email)),
-                                            Keyword = doc.Get(nameof(Post.Keyword)).ToLower().Contains(k.ToLower()) ? highlighter.GetBestFragment(k, doc.Get(nameof(Post.Keyword))) : doc.Get(nameof(Post.Keyword))
-                                        });
-                                    }
-                                }
-                            }
-                        }
-                    }
-                });
-                total = totalCount;
-                return result.Where(p => !string.IsNullOrEmpty(p.Title)).DistinctBy(p => p.Id).ToList();
-            }
-        }
-
         /// <summary>
         /// 分词
         /// </summary>
@@ -307,7 +20,10 @@ namespace Masuit.MyBlogs.WebApp.Models
         /// <returns></returns>
         public static List<string> CutKeywords(string keyword)
         {
-            var list = new HashSet<string> { keyword };
+            var list = new HashSet<string>
+            {
+                keyword
+            };
             var mc = Regex.Matches(keyword, @"(([A-Z]*[a-z]*)[\d]*)([\u4E00-\u9FA5]+)*((?!\p{P}).)*");
             foreach (Match m in mc)
             {
@@ -319,14 +35,20 @@ namespace Masuit.MyBlogs.WebApp.Models
             }
             if (keyword.Length >= 6)
             {
-                using (HttpClient client = new HttpClient() { BaseAddress = new Uri("http://zhannei.baidu.com") })
+                using (HttpClient client = new HttpClient()
+                {
+                    BaseAddress = new Uri("http://zhannei.baidu.com")
+                })
                 {
                     try
                     {
                         var res = client.GetAsync($"/api/customsearch/keywords?title={keyword}").Result;
                         if (res.StatusCode == HttpStatusCode.OK)
                         {
-                            BaiduAnalysisModel model = JsonConvert.DeserializeObject<BaiduAnalysisModel>(res.Content.ReadAsStringAsync().Result, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
+                            BaiduAnalysisModel model = JsonConvert.DeserializeObject<BaiduAnalysisModel>(res.Content.ReadAsStringAsync().Result, new JsonSerializerSettings()
+                            {
+                                NullValueHandling = NullValueHandling.Ignore
+                            });
                             if (model.Result.Res.KeywordList != null && model.Result.Res.KeywordList.Any())
                             {
                                 list.AddRange(model.Result.Res.KeywordList.ToArray());
@@ -342,194 +64,5 @@ namespace Masuit.MyBlogs.WebApp.Models
             list.RemoveWhere(s => s.Length < 2 || Regex.IsMatch(s, @"^\p{P}.*"));
             return list.OrderByDescending(s => s.Length).ToList();
         }
-
-        #endregion 多字段分页查询数据
-
-        #region 删除索引
-
-        /// <summary>
-        /// 删除索引
-        /// </summary>
-        public static bool DeleteIndex()
-        {
-            if (string.IsNullOrEmpty(IndexPath))
-            {
-                throw new Exception("未设置索引文件夹路径,参数名:" + IndexPath);
-            }
-            string indexPath = IndexPath;
-            using (FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NoLockFactory()))
-            {
-                using (var writer = new IndexWriter(directory, new PanGuAnalyzer(), false, IndexWriter.MaxFieldLength.LIMITED))
-                {
-                    writer.DeleteAll();
-                    writer.Commit();
-                    writer.Optimize();
-                    return writer.HasDeletions();
-                }
-            }
-        }
-
-        #endregion 删除索引
-
-        #region 文章的增量索引,全局刷新索引库
-
-        /// <summary>
-        /// 文章的增量索引,全局刷新索引库
-        /// </summary>
-        public static void IncreaseIndex()
-        {
-            if (string.IsNullOrEmpty(IndexPath))
-            {
-                throw new Exception("未设置索引文件夹路径,参数名:" + IndexPath);
-            }
-            using (FSDirectory directory = FSDirectory.Open(new DirectoryInfo(IndexPath), new NoLockFactory()))
-            {
-                using (IndexReader reader = IndexReader.Open(directory, true))
-                {
-                    //数据库中的所有数据
-                    var dataAll = AutofacConfig.Container.Resolve<IPostBll>().LoadEntities(p => p.Status == Status.Pended);
-                    var addData = new List<Post>(); //数据库中新来的数据,要进索引库的
-                    var updData = new List<Post>(); // 数据库中修改的数据,也要修改索引库的
-
-                    //判断有无字典
-                    if (Directory.Exists(IndexPath))
-                    {
-                        foreach (Post item in dataAll)
-                        {
-                            bool addf = IsInIndex(item.Id.ToString().Trim(), reader); //索引数据库是否存在这条记录
-                            if (addf)
-                            {
-                                addData.Add(item);
-                            }
-                            else
-                            {
-                                updData.Add(item);
-                            }
-                        }
-                        if (updData.Count > 0)
-                        {
-                            UpdateListToIndex(updData, reader);
-                        }
-                        using (var writer = new IndexWriter(directory, new PanGuAnalyzer(), false, IndexWriter.MaxFieldLength.UNLIMITED))
-                        {
-                            try
-                            {
-                                if (addData.Count > 0 && updData.Count > 0)
-                                {
-                                    AddListToIndex(updData, writer); //更新索引
-                                    AddListToIndex(addData, writer); //添加索引
-                                }
-
-                                if (addData.Count > 0 && updData.Count == 0)
-                                {
-                                    AddListToIndex(addData, writer);
-                                }
-                                writer.Optimize();
-                            }
-                            catch (IOException e)
-                            {
-                                Console.WriteLine(e);
-                            }
-                        }
-                    }
-                    else
-                    {
-                        CreateIndex(dataAll); //否则就直接创建索引
-                    }
-                }
-            }
-        }
-
-        #endregion 文章的增量索引,全局刷新索引库
-
-        #region 判断数据库中的某条数据是否已经索引了
-
-        /// <summary>
-        /// 功能描述:判断数据库中的某条数据是否已经索引了
-        /// </summary>
-        /// <param name="id">数据库记录的id字段值</param>
-        /// <param name="pIndexReader">IndexReader的对象</param>
-        /// <returns>true表示存在, false表示不存在</returns>
-        private static bool IsInIndex(String id, IndexReader pIndexReader)
-        {
-            bool flag = true;
-            for (int i = 0; i < pIndexReader.NumDocs(); i++)
-            {
-                Document doc = pIndexReader.Document(i);
-                if (id.Equals(doc.Get(nameof(Post.Id))))
-                {
-                    flag = false;
-                }
-            }
-            return flag;
-        }
-
-        #endregion 判断数据库中的某条数据是否已经索引了
-
-        #region 将实体对象转换成Lucene的文档对象
-
-        /// <summary>
-        /// 将实体对象转换成Lucene的文档对象
-        /// </summary>
-        /// <param name="item">文章实体</param>
-        /// <returns></returns>
-        private static Document EntityToDocument(Post item)
-        {
-            var doc = new Document();
-            doc.Add(new Field(nameof(item.Id), item.Id.ToString(), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-            doc.Add(new Field(nameof(item.Title), item.Title, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-            doc.Add(new Field(nameof(item.Content), item.Content.RemoveHtmlTag(), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-            doc.Add(new Field(nameof(item.Author), item.Author, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-            doc.Add(new Field(nameof(item.Email), item.Email ?? "", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-            doc.Add(new Field(nameof(item.Label), item.Label ?? "", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-            doc.Add(new Field(nameof(item.Keyword), item.Keyword ?? "", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-            return doc;
-        }
-
-        #endregion 将实体对象转换成Lucene的文档对象
-
-        #region 增量索引,批量添加索引库
-
-        /// <summary>
-        /// 增量索引,批量添加索引库
-        /// </summary>
-        /// <param name="posts">文章集合</param>
-        /// <param name="writer">索引读写器</param>
-        public static void AddListToIndex(List<Post> posts, IndexWriter writer)
-        {
-            if (posts.Count > 0)
-            {
-                foreach (Post item in posts)
-                {
-                    Document document = EntityToDocument(item);
-                    writer.AddDocument(document); //将文档写入索引库
-                }
-            }
-        }
-
-        #endregion 增量索引,批量添加索引库
-
-        #region 增量索引 第一步去索引库删除数据
-
-        /// <summary>
-        /// 增量索引 第一步去索引库删除数据
-        /// </summary>
-        /// <param name="resultList"></param>
-        /// <param name="reader"></param>
-        public static void UpdateListToIndex(List<Post> resultList, IndexReader reader)
-        {
-            if (resultList.Count > 0)
-            {
-                foreach (Post item in resultList)
-                {
-                    var term = new Term("id", item.Id.ToString().Trim());
-
-                    //Query query = new TermQuery(term);
-                    reader.DeleteDocuments(term);
-                }
-            }
-        }
-
-        #endregion 增量索引 第一步去索引库删除数据
     }
-}
+}

+ 3 - 6
src/Masuit.MyBlogs.WebApp/Models/MyActionFilterAttribute.cs

@@ -1,4 +1,6 @@
-using System;
+using Masuit.Tools;
+using Masuit.Tools.Net;
+using System;
 using System.Configuration;
 using System.IO;
 using System.Security.Cryptography;
@@ -7,10 +9,6 @@ using System.Text.RegularExpressions;
 using System.Web;
 using System.Web.Mvc;
 using System.Web.UI;
-using Common;
-using Masuit.MyBlogs.WebApp.Models.Hangfire;
-using Masuit.Tools;
-using Masuit.Tools.Net;
 
 namespace Masuit.MyBlogs.WebApp.Models
 {
@@ -37,7 +35,6 @@ namespace Masuit.MyBlogs.WebApp.Models
                         uid = Guid.NewGuid();
                         filterContext.HttpContext.Session.Set("currentOnline", uid);
                     }
-                    HangfireHelper.CreateJob(typeof(IHangfireBackJob), nameof(HangfireBackJob.InterviewTrace), null, uid, req.Url.ToString().Replace(":80/", "/"));
                 }
             }
             catch

+ 3 - 2
src/Masuit.MyBlogs.WebApp/Startup.cs

@@ -7,7 +7,6 @@ using Microsoft.Owin;
 using Microsoft.Owin.Cors;
 using Models.DTO;
 using Owin;
-using System.Configuration;
 using System.Web;
 
 [assembly: OwinStartup(typeof(Startup))]
@@ -20,7 +19,8 @@ namespace Masuit.MyBlogs.WebApp
         {
             //配置任务持久化到内存
             //GlobalConfiguration.Configuration.UseMemoryStorage();
-            GlobalConfiguration.Configuration.UseSqlServerStorage(ConfigurationManager.ConnectionStrings["DataContext"].ConnectionString);
+            //GlobalConfiguration.Configuration.UseSqlServerStorage(ConfigurationManager.ConnectionStrings["DataContext"].ConnectionString);
+            GlobalConfiguration.Configuration.UseRedisStorage();
 
             //启用dashboard
             app.UseHangfireServer(new BackgroundJobServerOptions { WorkerCount = 10 });
@@ -29,6 +29,7 @@ namespace Masuit.MyBlogs.WebApp
                 Authorization = new[] { new MyRestrictiveAuthorizationFilter() }
             }); //注册dashboard的路由地址
             app.UseCors(CorsOptions.AllowAll);
+            app.UseHangfireServer();
             app.MapSignalR();
         }
     }

+ 1 - 1
src/Masuit.MyBlogs.WebApp/Views/Shared/_Layout.cshtml

@@ -220,7 +220,7 @@
             <div class="cd-overlay"></div>
             <footer class="footer wow fadeIn">
                 <div class="container">
-                    当前浏览人数:@CommonHelper.OnlineCount 人,总访客量:@CommonHelper.InterviewCount,今日访问量:@CommonHelper.Todaypv 人,平均访问量:@(CommonHelper.AverageCount.ToString("N"))人/天
+                    总访客量:@CommonHelper.InterviewCount,平均访问量:@(CommonHelper.AverageCount.ToString("N"))人/天
                     <section>
                         友情链接:
                         <a href="/swagger">博客开放平台</a>

+ 0 - 12
src/Masuit.MyBlogs.WebApp/ng-views/app/route.config.js

@@ -205,18 +205,6 @@ myApp.config(["$stateProvider", "$urlRouterProvider", "$locationProvider",
 					return $ocLazyLoad.load([cpath + "/msg.js"]);
 				}]
 			}
-		}).state("interview", {
-			url: "/interview",
-			templateUrl: vpath + "/analysis/interview.html",
-			controller: "interview as list",
-			resolve: {
-				deps: ["$ocLazyLoad", function($ocLazyLoad) {
-					return $ocLazyLoad.load([{
-						files: ["/assets/jedate/jedate.min.css", "/Assets/semantic/semantic.css", "/assets/jedate/jquery.jedate.min.js", "/Scripts/boost.js", "https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.min.js", "https://img.hcharts.cn/highcharts/modules/data.js", "https://img.hcharts.cn/highcharts/modules/drilldown.js"],
-						cache: true
-					},cpath + "/analysis.js"]);
-				}]
-			}
 		}).state("search", {
 			url: "/search",
 			templateUrl: vpath + "/analysis/search.html",

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
src/Masuit.MyBlogs.WebApp/ng-views/app/route.config.min.js


+ 1 - 545
src/Masuit.MyBlogs.WebApp/ng-views/controllers/analysis.js

@@ -1,548 +1,4 @@
-myApp.controller("interview", ["$scope", "$http", "NgTableParams", "$timeout",
-	function($scope, $http, NgTableParams, $timeout) {
-		window.hub.disconnect();
-		var self = this;
-		$scope.loading();
-		$scope.distinct = true;
-		$scope.query = "";
-		$scope.currentPage = 1;
-		var _timeout;
-
-		$scope.start = $.nowDate({
-			DD:0
-		}).substring(0, 10);
-		$scope.end = $.nowDate({
-			DD:1
-		});
-		$("#start").val($scope.start);
-		$("#end").val($scope.end);
-		var start = {
-			format:'YYYY-MM-DD hh:mm:ss',
-			minDate:'2014-06-16 23:59:59', //设定最小日期为当前日期
-			isinitVal:true,
-			maxDate:$.nowDate({
-				DD:0
-			}), //最大日期
-			choosefun:function(elem, datas) {
-				end.minDate = datas; //开始日选好后,重置结束日的最小日期
-				end.trigger = false;
-				$("#end").jeDate(end);
-				$scope.start = datas;
-				$("#start").val(datas);
-			},
-			okfun:function(elem, datas) {
-				end.minDate = datas; //开始日选好后,重置结束日的最小日期
-				end.trigger = false;
-				$("#end").jeDate(end);
-				$scope.start = datas;
-				$("#start").val(datas);
-			}
-		};
-		var end = {
-			format:'YYYY-MM-DD hh:mm:ss',
-			minDate:$.nowDate({
-				DD:0
-			}), //设定最小日期为当前日期
-			isinitVal:true,
-			maxDate:$.nowDate({
-				DD:1
-			}), //最大日期
-			choosefun:function(elem, datas) {
-				start.maxDate = datas; //将结束日的初始值设定为开始日的最大日期
-				$scope.end = datas;
-				$("#end").val(datas);
-			},
-			okfun:function(elem, datas) {
-				start.maxDate = datas; //将结束日的初始值设定为开始日的最大日期
-				$scope.end = datas;
-				$("#end").val(datas);
-				self.GetPageData($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage);
-			}
-		}
-		$('#start').jeDate(start);
-		$('#end').jeDate(end);
-
-		$('.field').dropdown({
-			allowAdditions:false,
-			onChange:function(value) {
-				var state = ["OperatingSystem", "UserAgent", "BrowserType", "ISP", "HttpMethod"];
-				state.map(function(item, index, array) {
-					$scope[item] = false;
-				});
-				value.split(",").map(function(item, index, array) {
-					$scope[item] = true;
-				});
-				self.tableParams.reload();
-			}
-		});
-		$scope.paginationConf = {
-			currentPage:1,
-			itemsPerPage:10,
-			pagesLength:25,
-			perPageOptions:[1, 5, 10, 15, 20, 30, 40, 50],
-			rememberPerPage:'perPageItems',
-			onChange:function() {
-				if(_timeout) {
-					$timeout.cancel(_timeout);
-				}
-				_timeout = $timeout(function() {
-					self.GetPageData($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage);
-					_timeout = null;
-				}, 100);
-			}
-		};
-		$scope.search = function() {
-			if(_timeout) {
-				$timeout.cancel(_timeout);
-			}
-			_timeout = $timeout(function() {
-				self.GetPageData($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage);
-				_timeout = null;
-			}, 1000);
-		}
-		this.GetPageData = function(page, size) {
-			$scope.loading();
-			$http.post("/interview/getpage", {
-				start:$scope.start,
-				end:$scope.end,
-				page,
-				size,
-				distinct:$scope.distinct,
-				search:$scope.query
-			}).then(function(res) {
-				if(res.data.Data) {
-					$scope.paginationConf.currentPage = page;
-					$scope.paginationConf.totalItems = res.data.TotalCount;
-					//$("div[ng-table-pagination]").remove();
-					$("#interview").next("div[ng-table-pagination]").remove();
-					self.tableParams = new NgTableParams({
-						count:50000
-					}, {
-						filterDelay:0,
-						dataset:res.data.Data
-					});
-				} else {
-					window.notie.alert({
-						type:3,
-						text:res.data.Message,
-						time:4
-					});
-				}
-				$scope.loadingDone();
-			});
-		};
-		//self.GetPageData(1, 10);
-		$scope.loadingDone();
-		$scope.doDistinct = function() {
-			$scope.distinct = !$scope.distinct;
-			if(_timeout) {
-				$timeout.cancel(_timeout);
-			}
-			_timeout = $timeout(function() {
-				self.GetPageData($scope.paginationConf.currentPage, $scope.paginationConf.itemsPerPage);
-				$scope.analysis();
-				_timeout = null;
-			}, 500);
-		}
-		$scope.analysis = function() {
-			$http.post("/interview/analysis", {
-				uniq:$scope.distinct
-			}).then(function(res) {
-				var data = res.data.Data;
-				if(!res.data.Success) {
-					window.notie.alert({
-						type:3,
-						text:res.data.Message,
-						time:4
-					});
-					return;
-				}
-				$scope.interview = data;
-				window.echarts.init(document.getElementById('map')).setOption({
-					tooltip:{
-						trigger:'item'
-					},
-					visualMap:{
-						min:0,
-						max:Enumerable.From(data.client).Where(e => e.name != "XX").Max(e => e.value),
-						left:'left',
-						top:'bottom',
-						text:['高', '低'], // 文本,默认为数值文本
-						calculable:true
-					},
-					series:[
-						{
-							name:'访问量',
-							type:'map',
-							mapType:'china',
-							roam:false,
-							label:{
-								normal:{
-									show:true
-								},
-								emphasis:{
-									show:true
-								}
-							},
-							data:data.client
-						}
-					]
-				});
-				var china = ["北京", "天津", "上海", "重庆", "河北", "山西", "辽宁", "吉林", "黑龙江", "江苏", "浙江", "安徽", "福建", "江西", "山东",
-					"河南", "湖北", "湖南", "广东", "海南", "四川", "贵州", "云南", "陕西", "甘肃", "青海", "台湾", "内蒙古", "广西", "西藏", "宁夏",
-					"新疆", "香港", "澳门"];
-				var sum1 = 0, sum2 = 0;
-				var dril1 = {
-					"name":'中国',
-					"id":'中国',
-					"data":[]
-				};
-				var dril2 = {
-					"name":'海外',
-					"id":'海外',
-					"data":[]
-				};
-				for(var i = 0; i < data.client.length; i++) {
-					if(china.indexOf(data.client[i].name) >= 0) {
-						sum1 += data.client[i].value;
-						dril1.data.push([data.client[i].name, data.client[i].value]);
-					} else {
-						sum2 += data.client[i].value;
-						dril2.data.push([data.client[i].name, data.client[i].value]);
-					}
-				}
-				$('#client').highcharts({
-					chart:{
-						type:'pie',
-						plotBackgroundColor:null,
-						plotBorderWidth:null,
-						backgroundColor:'transparent',
-						plotShadow:false
-					},
-					title:{
-						text:'访问地区统计'
-					},
-					boost:{
-						useGPUTranslations:true
-					},
-					credits:{
-						enabled:false
-					},
-					plotOptions:{
-						series:{
-							dataLabels:{
-								enabled:true,
-								format:'<b>{point.name}</b>: {point.percentage:.2f} % - {point.y}人/次'
-							}
-						}
-					},
-					tooltip:{
-						headerFormat:'<span>{series.name}</span><br>',
-						pointFormat:
-							'<span style="color:{point.color}">{point.name}</span>: <b>{point.percentage:.2f}%</b> - {point.y}</b>人/次<br/>'
-					},
-					series:[{
-						name:'访问地区统计',
-						colorByPoint:true,
-						data:[{
-							name:'中国',
-							y:sum1,
-							drilldown:"中国"
-						}, {
-							name:'海外',
-							y:sum2,
-							drilldown:"海外"
-						}]
-					}],
-					drilldown:{
-						series:[dril1, dril2]
-					}
-				});
-				var groups = _.groupBy(data.browser, e => e[0].split(/\d+/)[0]);
-				var series = [], drilldown = [];
-				for(var key in groups) {
-					var sum = 0;
-					var dril = {
-						"name":key,
-						"id":key,
-						"data":[]
-					};
-					groups[key].map((item, index) => {
-						sum += item[1];
-						//console.log(item);
-						dril.data.push([item[0], item[1]])
-					});
-					series.push({
-						name:key,
-						y:sum,
-						drilldown:key
-					});
-					drilldown.push(dril);
-				}
-				$('#browser').highcharts({
-					chart:{
-						type:'pie',
-						plotBackgroundColor:null,
-						plotBorderWidth:null,
-						backgroundColor:'transparent',
-						plotShadow:false
-					},
-					title:{
-						text:'浏览器统计'
-					},
-					boost:{
-						useGPUTranslations:true
-					},
-					credits:{
-						enabled:false
-					},
-					plotOptions:{
-						series:{
-							dataLabels:{
-								enabled:true,
-								format:'<b>{point.name}</b>: {point.percentage:.2f} % - {point.y}人/次'
-							}
-						}
-					},
-					tooltip:{
-						headerFormat:'<span>{series.name}</span><br>',
-						pointFormat:
-							'<span style="color:{point.color}">{point.name}</span>: <b>{point.percentage:.2f}%</b> - {point.y}</b>人/次<br/>'
-					},
-					series:[{
-						name:'浏览器类型',
-						colorByPoint:true,
-						data:series
-					}],
-					drilldown:{
-						series:drilldown
-					}
-				});
-				$('#alldata').highcharts({
-					chart: {
-						zoomType: 'x'
-					},
-					subtitle: {
-						text: document.ontouchstart === undefined ?
-						'鼠标拖动可以进行缩放' : '手势操作进行缩放'
-					},
-
-					credits:{
-						enabled:false
-					},
-					boost:{
-						useGPUTranslations:true
-					},
-					tooltip:{
-						dateTimeLabelFormats:{
-							millisecond:'%H:%M:%S.%L',
-							second:'%H:%M:%S',
-							minute:'%H:%M',
-							hour:'%H:%M',
-							day:'%Y-%m-%d',
-							week:'%m-%d',
-							month:'%Y-%m',
-							year:'%Y'
-						},
-						formatter:function() {
-							try {
-								return '时间点:<b>' + Highcharts.dateFormat("%Y-%m-%d", this.points[0].x) + '</b><br/>' +
-									'<span style="color:' + Highcharts.getOptions().colors[0] + '">直接访问量:<b>' +
-									this.points[0].y +
-									'人/天</b></span><br/>' +
-									'<span style="color:' + Highcharts.getOptions().colors[39] + '">独立访客量:<b>' +
-									this.points[1].y +
-									'人/天</b></span><br/>' +
-									'<span style="color:' + Highcharts.getOptions().colors[35] + '">新增独立访客:<b>' +
-									this.points[2].y +
-									'人/天</b></span><br/>' +
-									'<span style="color:' + Highcharts.getOptions().colors[26] + '">跳出率:<b>' +
-									Highcharts.numberFormat(this.points[3].y, 2) +
-									'%</b></span><br/>';
-							} catch(e) {
-								return '时间点:<b>' + Highcharts.dateFormat("%Y-%m-%d", this.points[0].x) + '</b><br/>' +
-									'<span style="color:' + Highcharts.getOptions().colors[0] + '">直接访问量:<b>' +
-									this.points[0].y +
-									'人/天</b></span><br/>' +
-									'<span style="color:' + Highcharts.getOptions().colors[39] + '">独立访客量:<b>' +
-									this.points[1].y +
-									'人/天</b></span><br/>' +
-									'<span style="color:' + Highcharts.getOptions().colors[35] + '">新增独立访客:<b>' +
-									this.points[2].y +
-									'人/天</b></span><br/>';
-							}
-						},
-						crosshairs:true,
-						shared:true
-					},
-					scrollbar:{
-						enabled:false
-					},
-					title:{
-						text:'历史访客记录走势图'
-					},
-					xAxis:{
-						type:'datetime',
-						dateTimeLabelFormats:{
-							millisecond:'%H:%M:%S.%L',
-							second:'%H:%M:%S',
-							minute:'%H:%M',
-							hour:'%H:%M',
-							day:'%m-%d',
-							week:'%m-%d',
-							month:'%Y-%m',
-							year:'%Y'
-						}
-					},
-					yAxis:[
-						{
-							title:{
-								text:'访问量'
-							},
-							min:0,
-							opposite:false
-						}, {
-							title:{
-								text:'跳出率(%)'
-							},
-							min:0,
-							max:100,
-							opposite:true
-						}
-					],
-					plotOptions:{
-						series:{
-							showInNavigator:true,
-							marker:{
-								enabled:false
-							}
-						}
-					},
-					series:[{
-						name:'直接访问量',
-						data:data.pv,
-						type:'areaspline',
-						fillColor:{
-							linearGradient:{
-								x1:0,
-								y1:0,
-								x2:0,
-								y2:1
-							},
-							stops:[
-								[0, Highcharts.getOptions().colors[0]],
-								[1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
-							]
-						}
-					}, {
-						name:'独立访客量',
-						data:data.uv,
-						type:'areaspline',
-						fillColor:{
-							linearGradient:{
-								x1:0,
-								y1:0,
-								x2:0,
-								y2:1
-							},
-							stops:[
-								[0, Highcharts.getOptions().colors[39]],
-								[1, Highcharts.Color(Highcharts.getOptions().colors[39]).setOpacity(0).get('rgba')]
-							]
-						}
-					}, {
-						name:'独立访客',
-						data:data.iv,
-						type:'areaspline',
-						fillColor:{
-							linearGradient:{
-								x1:0,
-								y1:0,
-								x2:0,
-								y2:1
-							},
-							stops:[
-								[0, Highcharts.getOptions().colors[35]],
-								[1, Highcharts.Color(Highcharts.getOptions().colors[35]).setOpacity(0).get('rgba')]
-							]
-						}
-					}, {
-						name:'跳出率',
-						data:data.BounceRateAggregate,
-						type:'areaspline',
-						yAxis:1,
-						fillColor:{
-							linearGradient:{
-								x1:0,
-								y1:0,
-								x2:0,
-								y2:1
-							},
-							stops:[
-								[0, Highcharts.getOptions().colors[26]],
-								[1, Highcharts.Color(Highcharts.getOptions().colors[26]).setOpacity(0).get('rgba')]
-							]
-						}
-					}]
-				});
-			});
-		}
-		$scope.analysis();
-		$scope.details = function(data) {
-			layer.open({
-				type:1,
-				zIndex:20,
-				title:'访客浏览路径',
-				offset:window.screen.height * 0.02 + "px",
-				area:document.body.clientWidth * 0.8 + "px",
-				content:$("#modal"),
-				success:function(layero, index) {
-							$scope.viewer = data;
-							$scope.viewdetails = data.InterviewDetails;
-							self.ViewDetails = new NgTableParams({
-								count:10
-							}, {
-								filterDelay:0,
-								dataset:data.InterviewDetails
-							});
-				},
-				end:function() {
-					$("#modal").css("display", "none");
-				}
-			});
-		}
-		$scope.addToBlackList = function(ip) {
-			swal({
-				title: "确认添加黑名单吗?",
-				text: "将"+ip+"添加到黑名单",
-				showCancelButton: true,
-				confirmButtonColor: "#DD6B55",
-				confirmButtonText: "确定",
-				cancelButtonText: "取消",
-				animation: true,
-				allowOutsideClick: false,
-				showLoaderOnConfirm: true,
-				preConfirm: function () {
-					return new Promise(function (resolve, reject) {
-						$http.post("/system/AddToBlackList", {ip}, {
-							'Content-Type': 'application/x-www-form-urlencoded'
-						}).then(function(res) {
-							resolve(res.data);
-						}, function() {
-							reject("请求服务器失败!");
-						});
-					});
-				}
-			}).then(function (data) {
-				if (data.Success) {
-					swal("添加成功",'','success');
-				} else {
-					swal("添加失败",'','error');
-				}
-			}).catch(swal.noop);
-		}
-	}]);
-myApp.controller("searchAnalysis", ["$scope", "$http", "NgTableParams", "$timeout",
+myApp.controller("searchAnalysis", ["$scope", "$http", "NgTableParams", "$timeout",
 	function($scope, $http, NgTableParams, $timeout) {
 		window.hub.disconnect();
 		var self = this;

+ 2 - 7
src/Masuit.MyBlogs.WebApp/ng-views/template/sidebar-left.html

@@ -102,13 +102,8 @@
         <li data-ui-sref-active="active">
             <a data-ui-sref-active="active" data-ui-sref="subscribe" data-ng-click="mactrl.sidebarStat($event)"><i class="zmdi zmdi-swap-alt"></i>订阅管理</a>
         </li>
-
-        <li class="sub-menu" data-ng-class="{ 'active toggled': mactrl.$state.includes('pages') }">
-            <a href="" toggle-submenu><i class="zmdi zmdi-trending-up"></i>数据分析</a>
-            <ul>
-                <li><a data-ui-sref-active="active" data-ui-sref="interview" data-ng-click="mactrl.sidebarStat($event)">访客分析</a></li>
-                <li><a data-ui-sref-active="active" data-ui-sref="search" data-ng-click="mactrl.sidebarStat($event)">搜索记录分析</a></li>
-            </ul>
+        <li data-ui-sref-active="active">
+            <a data-ui-sref-active="active" data-ui-sref="search" data-ng-click="mactrl.sidebarStat($event)"><i class="zmdi zmdi-trending-up"></i>搜索记录分析</a>
         </li>
 
         <li data-ui-sref-active="active">

+ 5 - 7
src/Masuit.MyBlogs.WebApp/packages.config

@@ -13,13 +13,10 @@
   <package id="EntityFramework.zh-Hans" version="6.2.0" targetFramework="net45" />
   <package id="FluentScheduler" version="5.3.0" targetFramework="net45" />
   <package id="Hangfire.Autofac" version="2.3.1" targetFramework="net45" />
-  <package id="Hangfire.Console" version="1.4.2" targetFramework="net46" />
   <package id="Hangfire.Core" version="1.6.21" targetFramework="net46" />
-  <package id="Hangfire.SqlServer" version="1.6.21" targetFramework="net46" />
+  <package id="Hangfire.Redis.StackExchange" version="1.7.2" targetFramework="net461" />
   <package id="htmldiff.net" version="1.3" targetFramework="net46" />
   <package id="jQuery" version="3.3.1" targetFramework="net45" />
-  <package id="Lucene.Net" version="3.0.3" targetFramework="net45" />
-  <package id="Lucene.Net.Analysis.PanGu" version="2.4.1" targetFramework="net45" />
   <package id="Microsoft.AspNet.Cors" version="5.2.7" targetFramework="net461" />
   <package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net461" />
   <package id="Microsoft.AspNet.Mvc.zh-Hans" version="5.2.7" targetFramework="net461" />
@@ -50,16 +47,17 @@
   <package id="Microsoft.Owin.zh-Hans" version="4.0.0" targetFramework="net46" />
   <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
   <package id="Newtonsoft.Json" version="12.0.1" targetFramework="net461" />
+  <package id="NinjaNye.SearchExtensions" version="2.2.0" targetFramework="net461" />
   <package id="Owin" version="1.0" targetFramework="net45" />
-  <package id="PanGu.Lucene.Analyzer" version="0.0.2" targetFramework="net45" />
+  <package id="PanGu.Core" version="1.0.0" targetFramework="net461" />
+  <package id="PanGu.HighLight" version="1.0.0" targetFramework="net461" />
   <package id="PanGu.Segment" version="0.0.3" targetFramework="net45" />
-  <package id="SharpZipLib" version="1.1.0" targetFramework="net461" />
   <package id="StackExchange.Redis" version="1.2.6" targetFramework="net46" />
   <package id="Swashbuckle" version="5.6.0" targetFramework="net45" />
   <package id="Swashbuckle.Core" version="5.6.0" targetFramework="net45" />
   <package id="System.ValueTuple" version="4.5.0" targetFramework="net46" requireReinstallation="true" />
   <package id="WebActivatorEx" version="2.2.0" targetFramework="net45" />
   <package id="WebGrease" version="1.6.0" targetFramework="net45" />
-  <package id="Z.EntityFramework.Extensions" version="3.16.21" targetFramework="net461" />
+  <package id="Z.EntityFramework.Extensions" version="3.16.22" targetFramework="net461" />
   <package id="Z.ExtensionMethods" version="2.1.1" targetFramework="net461" />
 </packages>

+ 1 - 5
src/Models/Models.csproj

@@ -60,7 +60,7 @@
       <HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
     </Reference>
     <Reference Include="HtmlSanitizer, Version=3.0.0.0, Culture=neutral, PublicKeyToken=61c49a1a9e79cc28, processorArchitecture=MSIL">
-      <HintPath>..\packages\HtmlSanitizer.4.0.199\lib\net45\HtmlSanitizer.dll</HintPath>
+      <HintPath>..\packages\HtmlSanitizer.4.0.204\lib\net45\HtmlSanitizer.dll</HintPath>
     </Reference>
     <Reference Include="ICSharpCode.SharpZipLib, Version=1.1.0.145, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
       <HintPath>..\packages\SharpZipLib.1.1.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
@@ -95,9 +95,6 @@
     <Compile Include="DTO\CommentOutputDto.cs" />
     <Compile Include="DTO\ContactsInputDto.cs" />
     <Compile Include="DTO\ContactsOutputDto.cs" />
-    <Compile Include="DTO\InterviewAnalysisDto.cs" />
-    <Compile Include="DTO\InterviewDetail.cs" />
-    <Compile Include="DTO\Interview.cs" />
     <Compile Include="DTO\KeywordsRankOutputDto.cs" />
     <Compile Include="DTO\LeaveMessageInputDto.cs" />
     <Compile Include="DTO\LeaveMessageOutputDto.cs" />
@@ -124,7 +121,6 @@
     <Compile Include="Validation\ComplexPassword.cs" />
     <Compile Include="Validation\IsWebUrlAttribute.cs" />
     <Compile Include="Validation\SubmitCheckAttribute.cs" />
-    <Compile Include="ViewModel\AnalysisModel.cs" />
     <Compile Include="Entity\FastShare.cs" />
     <Compile Include="ViewModel\PostDataModel.cs" />
     <Compile Include="DTO\PostInputDto.cs" />

+ 1 - 1
src/Models/packages.config

@@ -8,7 +8,7 @@
   <package id="EFSecondLevelCache" version="1.2.0.0" targetFramework="net45" />
   <package id="EntityFramework" version="6.2.0" targetFramework="net45" />
   <package id="EntityFramework.zh-Hans" version="6.2.0" targetFramework="net45" />
-  <package id="HtmlSanitizer" version="4.0.199" targetFramework="net461" />
+  <package id="HtmlSanitizer" version="4.0.204" targetFramework="net461" />
   <package id="Mono.Reflection" version="1.1.0.0" targetFramework="net45" />
   <package id="Mono.Reflection.Core" version="1.1.1" targetFramework="net461" />
   <package id="Newtonsoft.Json" version="12.0.1" targetFramework="net461" />

Деякі файли не було показано, через те що забагато файлів було змінено